제퍼넷 로고

송장 인식을위한 미세 조정 변환기 모델

시간

송장 인식을위한 미세 조정 변환기 모델

작성자는 주석에서 교육에 이르기까지 단계별 가이드를 제공합니다.


By 왈 리드 아마 무, UBIAI 설립자

그림
송장 인식

개요

 
에 대한 최근 튜토리얼을 기반으로 NLP 애플리케이션 용 PDF 및 스캔 이미지에 주석을 추가하는 방법, 우리는 최근에 출시 된 Microsoft의 레이아웃 LM 모델 프랑스어 및 영어 송장이 포함 된 주석이 달린 사용자 지정 데이터 세트. 이전 자습서에서는 공개적으로 사용 가능한 FUNSD 데이터 세트 모델을 미세 조정하기 위해 여기에서는 주석 및 사전 처리부터 학습 및 추론에 이르는 전체 프로세스를 보여줍니다.

LayoutLM 모델

 
LayoutLM 모델은 BERT 아키텍처를 기반으로하지만 두 가지 추가 유형의 입력 임베딩이 있습니다. 첫 번째는 문서 내 토큰의 상대적 위치를 나타내는 2D 위치 임베딩이고, 두 번째는 문서 내 스캔 된 토큰 이미지에 대한 이미지 임베딩입니다. 이 모델은 양식 이해 (70.72에서 79.27), 영수증 이해 (94.02에서 95.24), 문서 이미지 분류 (93.07에서 94.42)를 포함한 여러 다운 스트림 작업에서 새로운 최신 결과를 달성했습니다. 자세한 내용은 원래 기사.

고맙게도이 모델은 오픈 소스 였고 허깅 페이스 라이브러리에서 사용할 수있게되었습니다. 감사합니다, Microsoft!

이 튜토리얼에서는 Huggingface 라이브러리에서 직접 모델을 복제하고 자체 데이터 세트에서 미세 조정합니다. 하지만 먼저 훈련 데이터를 만들어야합니다.

송장 주석

 
사용법 - UBIAI 텍스트 주석 도구, 약 50 개의 개인 송장에 주석을 달았습니다. 엔티티의 키와 값을 모두 추출하고 싶습니다. 예를 들어 다음 텍스트 "Date : 06/12/2021"에서 "Date"를 DATE_ID로, "06/12/2021"을 DATE로 주석 처리합니다. 키와 값을 모두 추출하면 숫자 값을 해당 속성과 연관시키는 데 도움이됩니다. 주석이 달린 모든 항목은 다음과 같습니다.

DATE_ID, DATE, INVOICE_ID, INVOICE_NUMBER,SELLER_ID, SELLER, MONTANT_HT_ID, MONTANT_HT, TVA_ID, TVA, TTC_ID, TTC

다음은 몇 가지 엔티티 정의입니다.

MONTANT_HT: 세전 총액
TTC: 세금 포함 총액
TVA: 세금

다음은 다음을 사용하여 주석이 달린 송장의 예입니다. 유비아이:

그림
UBIAI의 송장 주석

 

주석 처리 후 UBIAI에서 기차 및 테스트 파일을 올바른 형식으로 직접 내 보냅니다. 전처리 단계. 내보내기에는 각 학습 및 테스트 데이터 세트에 대한 XNUMX 개의 파일과 labels.txt라는 모든 라벨이 포함 된 텍스트 파일 XNUMX 개가 포함됩니다.

Train / Test.txt 2018 O Sous-total O en O EUR O 3,20 O € O TVA S-TVA_ID (0 %) O 0,00 € S-TVA 합계 B-TTC_ID en I-TTC_ID EUR E-TTC_ID 3,20 , XNUMX S-TTC € O 서비스 O soumis O au O mécanisme O d 'autoliquidation O-O


Train / Test_box.txt (각 토큰에 대한 경계 상자 포함) :

€ 912 457 서비스 920 soumis 466 80 486 133 au 495 136 mécanisme 487 182 d 'autoliquidation 495 185 488 200-495 204 486 276


Train / Test_image.txt (경계 상자, 문서 크기 및 이름 포함) :

€ 912 425 920 image434.jpg TVA 1653 2339 1 image500.jpg (441 %) 526 449 1653 2339 1 image0.jpg 529 € 441 557 451 image1653.jpg 합계 2339 1 0,00 882 image441.jpg ko 920 451 1653 image2339.jpg EUR 1 500 457 image531.jpg 466 1653 2339 1 534 459 549 image466.jpg € 1653 2339 1 image553.jpg 서비스 457 578 466 1653 2339 1 image3,20.jpg soumis 882 457 911 467 1653 2339 image1.jpg au 912 457 920 466 image1653.jpg mécanisme 2339 1 80 486 image133.jpg d' autoliquidation 495 1653 2339 1 136 487 image182.jpg -495 1653 2339 1 185 488 image200.jpg


labels.txt :

B-DATE_ID B-INVOICE_ID B-INVOICE_NUMBER B-MONTANT_HT B-MONTANT_HT_ID B-SELLER B-TTC B-DATE B-TTC_ID B-TVA B-TVA_ID E-DATE_ID E-DATE E-INVOICE_ID E-INVOICE_NUMBER E-MONTANT_HT E- MONTANT_HT_ID E-SELLER E-TTC E-TTC_ID E-TVA E-TVA_ID I-DATE_ID I-DATE I-SELLER I-INVOICE_ID I-MONTANT_HT_ID I-TTC I-TTC_ID I-TVA_ID O S-DATE_ID S-DATE S-INVOICE_ID S-INVOICE_NUMBER S-MONTANT_HT_ID S-MONTANT_HT S-SELLER S-TTC S-TTC_ID S-TVA S-TVA_ID


LayoutLM 모델 미세 조정 :

 
여기서는 GPU와 함께 google colab을 사용하여 모델을 미세 조정합니다. 아래 코드는 원본 레이아웃 LM 용지이 튜토리얼 

먼저 layoutLM 패키지를 설치하세요…

! rm -r unilm! git clone -b remove_torch_save https://github.com/NielsRogge/unilm.git! cd unilm / layoutlm! pip install unilm / layoutlm


… 또한 모델을 다운로드 할 변압기 패키지 :

! rm -r 변환기! git clone https://github.com/huggingface/transformers.git! cd 트랜스포머! pip 설치 ./transformers


다음으로 labels.txt에서 고유 한 라벨을 포함하는 목록을 만듭니다.

from torch.nn import CrossEntropyLoss def get_labels (path) : with open (path, "r") as f : labels = f.read (). splitlines () if "O"not in labels : labels = [ "O"] + 레이블은 레이블을 반환합니다. 레이블 = get_labels ( "./ labels.txt") num_labels = len (labels) label_map = {i : i의 레이블, enumerate (labels)의 레이블} pad_token_label_id = CrossEntropyLoss (). ignore_index


그런 다음 pytorch 데이터 세트와 데이터 로더를 만듭니다.

변환기에서 import LayoutLMTokenizer from layoutlm.data.funsd import FunsdDataset, InputFeatures from torch.utils.data import DataLoader, RandomSampler, SequentialSampler args = { 'local_rank': -1, 'overwrite_cache': True, 'data_dir': '/ content / data ','model_name_or_path ':'microsoft / layoutlm-base-uncased ','max_seq_length ': 512,'model_type ':'layoutlm ',} # dict의 키를 속성으로 바꾸는 클래스 class AttrDict (dict) : def __init __ (self, * args, ** kwargs) : super (AttrDict, self) .__ init __ (* args, ** kwargs) self .__ dict__ = self args = AttrDict (args) tokenizer = LayoutLMTokenizer.from_pretrained ( "microsoft / layoutlm- base-uncased ") # LayoutLM 작성자가 이미 특정 FunsdDataset을 정의 했으므로 여기서 사용하겠습니다 train_dataset = FunsdDataset (args, tokenizer, labels, pad_token_label_id, mode ="train ") train_sampler = RandomSampler (train_dataset) train_dataloader = DataLoader (train_dataset, sampler = train_sampler, batch_size = 2) eval_dataset = FunsdDataset (args, tokenizer , labels, pad_token_label_id, mode = "test") eval_sampler = SequentialSampler (eval_dataset) eval_dataloader = DataLoader (eval_dataset, sampler = eval_sampler, batch_size = 2) batch = next (iter (train_dataloader)) input_ids = batch [0] [0] tokenizer .decode (input_ids)


Huggingface에서 모델을로드합니다. 이것은 데이터 세트에서 미세 조정됩니다.

변환기에서 import LayoutLMForTokenClassification import torch device = torch.device ( "cuda"if torch.cuda.is_available () else "cpu") model = LayoutLMForTokenClassification.from_pretrained ( "microsoft / layoutlm-base-uncased", num_labels = num_labels) model. to (장치)


마지막으로 교육을 시작합니다.

rom 변환기는 tqdm에서 AdamW를 가져옵니다 import tqdm optimizer = AdamW (model.parameters (), lr = 5e-5) global_step = 0 num_train_epochs = 50 t_total = len (train_dataloader) * num_train_epochs # 총 훈련 단계 수 # 훈련에 모델을 넣습니다. mode model.train () for epoch in range (num_train_epochs) : for batch in tqdm (train_dataloader, desc = "Training") : input_ids = batch [0] .to (device) bbox = batch [4] .to (device) Attention_mask = batch [1] .to (device) token_type_ids = batch [2] .to (device) labels = batch [3] .to (device) # forward pass outputs = model (input_ids = input_ids, bbox = bbox, tention_mask = Attention_mask, token_type_ids = token_type_ids, labels = labels) loss = outputs.loss # global_step % 100 == 100 인 경우 0 단계마다 인쇄 손실 : print (f "{global_step} 단계 후 손실 : {loss.item ()}") # 기울기를 얻기위한 역방향 패스 loss.backward () #print ( "Gradients on classification head :") #print (model.classifier.weight.grad [6, :]. sum ()) # update optimizer.step () optimizer .zero_grad () global_step + = 1


훈련 진행 상황과 손실이 업데이트되는 것을 볼 수 있어야합니다.

그림
레이아웃 LM 교육 진행 중

 

훈련 후 다음 함수를 사용하여 모델 성능을 평가합니다.

mport numpy as np from seqeval.metrics import (classification_report, f1_score, precision_score, reval_score,) eval_loss = 0.0 nb_eval_steps = 0 preds = None out_label_ids = None # model.eval () for batch in tqdm (eval_dataloader, desc) = "평가 중") : torch.no_grad () 사용 : input_ids = 배치 [0] .to (장치) bbox = 배치 [4] .to (장치) Attention_mask = 배치 [1] .to (장치) token_type_ids = 배치 [ 2] .to (device) labels = batch [3] .to (device) # forward pass outputs = model (input_ids = input_ids, bbox = bbox, tention_mask = attention_mask, token_type_ids = token_type_ids, labels = labels) # 손실을 얻고 logits tmp_eval_loss = outputs.loss logits = outputs.logits eval_loss + = tmp_eval_loss.item () nb_eval_steps + = 1 # preds가 None이면 예측을 계산합니다 : preds = logits.detach (). cpu (). numpy () out_label_ids = labels .detach (). cpu (). numpy () else : preds = np.append (preds, logits.detach (). cpu (). numpy (), axis = 0) out_label_ids = np.append (out_label_ids, labels. detach (). cpu (). n umpy (), axis = 0) # 평균 평가 손실 계산 eval_loss = eval_loss / nb_eval_steps preds = np.argmax (preds, axis = 2) out_label_list = [[] for _ in range (out_label_ids.shape [0])] preds_list = [[] for _ in range (out_label_ids.shape [0])] for i in range (out_label_ids.shape [0]) : for j in range (out_label_ids.shape [1]) : if out_label_ids [i, j]! = pad_token_label_id : out_label_list [i] .append (label_map [out_label_ids [i] [j]]) preds_list [i] .append (label_map [preds [i] [j]]) 결과 = { "손실": eval_loss, "정밀도 ": precision_score (out_label_list, preds_list),"recall ": recall_score (out_label_list, preds_list),"f1 ": f1_score (out_label_list, preds_list),}


50 개의 문서만으로 다음과 같은 점수를 얻습니다.

그림
교육 후 평가 점수

 

더 많은 주석으로 더 높은 점수를 받아야합니다.

마지막으로 향후 예측을 위해 모델을 저장합니다.

PATH = '. / drive / MyDrive / trained_layoutlm / layoutlm_UBIAI.pt'torch.save (model.state_dict (), PATH)


추론:

 
이제 재미있는 부분이 있습니다. 인보이스를 업로드하고 OCR을 수행하고 관련 항목을 추출해 보겠습니다. 이 테스트에서는 교육 또는 테스트 데이터 세트에없는 송장을 사용합니다. 송장에서 텍스트를 구문 분석하기 위해 오픈 소스 Tesseract 패키지를 사용합니다. 패키지를 설치하겠습니다.

! sudo apt install tesseract-ocr! pip install pytesseract


예측을 실행하기 전에 이미지에서 텍스트를 구문 분석하고 토큰과 경계 상자를 기능으로 사전 처리해야합니다. 이를 위해 전처리 파이썬 파일을 만들었습니다. 레이아웃LM_preprocess.py 그러면 이미지를 더 쉽게 전처리 할 수 ​​있습니다.

mport sys sys.path.insert (1, './drive/MyDrive/UBIAI_layoutlm') from layoutlm_preprocess import * image_path = '. / content / invoice_test.jpg'image, words, boxes, actual_boxes = preprocess (image_path)


다음으로 모델을로드하고 경계 상자를 사용하여 단어 예측을 가져옵니다.

model_path = '. / drive / MyDrive / trained_layoutlm / layoutlm_UBIAI.pt'model = model_load (model_path, num_labels) word_level_predictions, final_boxes = convert_to_features (image, words, boxes, actual_boxes, model)


마지막으로 예측 엔터티 및 경계 상자가있는 이미지를 표시합니다.

draw = ImageDraw.Draw (image) font = ImageFont.load_default () def iob_to_label (label) : if label! = 'O': return label [2 :] else : return ""label2color = { 'data_id': 'green' , 'date': 'green', 'invoice_id': 'blue', 'invoice_number': 'blue', 'montant_ht_id': 'black', 'montant_ht': 'black', 'seller_id': 'red', ' seller ':'red ','ttc_id ':'grey ','ttc ':'grey ',' ':'violet ','tva_id ':'orange ','tva ':'orange '} 예측, 상자 in zip (word_level_predictions, final_boxes) : predicted_label = iob_to_label (label_map [prediction]). lower () draw.rectangle (box, outline = label2color [predicted_label]) draw.text ((box [0] + 10, box [1] -10), text = predicted_label, fill = label2color [predicted_label], font = font) 이미지


Et voila :

그림
LayoutLM을 사용한 송장 엔터티 추출

 

모델은 판매자, 송장 번호, 날짜, TTC를 정확하게 추출 할 수 있었지만 구매 항목에 TTC 라벨을 할당하여 실수를했습니다. 주석이 달린 문서의 수가 적기 때문에 결과는 인상적이고 매우 유망합니다 (단지 50 개)! 더 많은 주석이 달린 송장으로 더 높은 F 점수와 더 정확한 예측에 도달 할 수 있습니다. 

결론 :

 
전반적으로 LayoutLM 모델의 결과는 매우 유망하며 반 구조화 된 텍스트 분석에서 변환기의 유용성을 보여줍니다. 이 모델은 운전 면허증, 계약서, 정부 문서, 재무 문서 등과 같은 다른 반 구조화 된 문서에서 미세 조정할 수 있습니다.

질문이 있으시면 아래에 질문하거나 admin@ubiai.tools로 이메일을 보내 주시기 바랍니다.

이 글이 마음에 드 셨다면 박수 치고 좋아요를 눌러주세요! 

 
바이오 : 왈 리드 아마 무 NLP 애플리케이션을위한 주석 도구 인 UBIAI의 창립자이며 물리학 박사 학위를 보유하고 있습니다.

관련 :

코인 스마트. 유로파 최고의 비트 코인-보르 스
출처 : https://www.kdnuggets.com/2021/06/fine-tuning-transformer-model-invoice-recognition.html

spot_img

최신 인텔리전스

spot_img

우리와 함께 채팅

안녕하세요! 어떻게 도와 드릴까요?