- vừa được xem lúc

Cơ chế mã hóa vị trị 2 chiều giải quyết bài toán nhận dạng nhiều dòng

0 0 34

Người đăng: Nguyen Viet Hoai

Theo Viblo Asia

Giới thiệu

Hầu hết các mô hình nhận dạng văn bản hiện nay đều xử lí trên dữ liệu 1 dòng . Về cơ bản mô hình nhận dạng sẽ có 3 thành phần là trích xuất , giải mã. Ở phần trích xuất sẽ là các mạng trích xuất đặc trưng như CNN,.. thu được một véc-tơ 1 chiều biểu diễn đặc trưng của các kí tự từ ảnh đầu vào. Vì vậy khi cho qua phần 2 đó là phần giải mã, phần này có nhiệm vụ dự đoán các giá trị phần tử trong véc-tơ trên tương ứng với kí tự nào trong bộ từ điển. Như vậy, việc biểu diễn ảnh đầu vào thành 1 véc-tơ đặc trưng 1 chiều không làm cho mô hình có thể học được dữ liệu dạng nhiều dòng, vì nó đều quy về tính toán trên 1 dòng hết.

Trên ứng dụng thực tế, việc xử lí trên dữ liệu nhiều dòng không có tính ứng dụng cao và bởi vì có thể chia dữ liệu nhiều dòng thành nhiều dữ liệu 1 dòng và đưa qua mô hình nhận dạng như bình thường. Do vậy, việc xây dựng một mô hình nhận dạng trên nhiều dòng không được sự chú ý và quan tâm nhiều từ các nhà nghiên cứu và cộng đồng phân tích văn bản. Tuy vậy, vẫn có nhiều bài toán đặc thù, mà việc áp dụng một mô hình có thể học và hiểu được cả dữ liệu 1 chiều và nhiều chiều là rất hữu ích, ví dụ như bài toán nhận dạng biển số xe, đặc thù của biển số xe là nó gồm cả biển số xe 1 dòng và biển số xe 2 dòng. Với bài toán nhận dạng biển số xe, hoàn toàn các bạn có thể xử lí theo hướng phát hiện biển số xe, sau đó điều chỉnh nó và chia đôi thành 2 phần trên dưới và đưa qua mô hình nhận dạng 1 dòng hay có thể phát hiện 4 góc của biển số xe rồi sau đó chia đôi 2 phần bằng trên dưới rồi cũng đưa qua mô hình nhận dạng 1 dòng hay phân đoạn ảnh cũng là 1 ý tưởng cho bài toán này. Tuy nhiên, sẽ có rất nhiều trường hợp mà biển số đó bị mất góc hay nghiêng, xiên, thì việc phát hiện sau đó chia đôi ảnh biển số xe ra sẽ gặp vấn đề về phát hiện không được hay chia đôi bị mất thông tin kí tự, ...

Cho nên ở một số bài toán thì việc làm cho mô hình có thể nhận dạng trên nhiều chiều là một hướng xử lí rất hay và có tính nghiên cứu cao, không những vậy nó còn đạt hiệu suất cao trong quá trình dự đoán. Để mô hình có thể làm được điều này, ở bài viết này mình sẽ giới thiệu đến các bạn một phương thức mã hóa vị trí 2 chiều, áp dụng cho mô hình TransformerOCR.

Mã hóa vị trí 2 chiều

Trong kiến trúc Transformer , mã hóa vị trí (Positional Encoding - PE) được định nghĩa là một phương thức làm cho mô hình có thể tính toán theo thứ tự . PE có thể giữ đươc thông tin về mối quan hệ về vị trí giữa các mã hóa trong dãy, từ đó khi đưa vào mô hình Transformer nó có thêm thông tin về vị trí, sư tương quan lẫn nhau giữa các mã hóa trong dãy, giúp cho việc dự đoán trở nên tốt hơn. Trong bài toán OCR, Transformer thường sẽ được kết hợp cùng với mạng trích xuất đặc trưng CNN. PE đóng vai trò quan trọng là cầu nối giữa CNN và Transformer. Ban đầu, PE được thiết kế để nhúng các giá trị vị trí thành 1 ma trận đặc trưng 1 chiều, tuy nhiên, điều này làm cho mô hình chỉ chú ý vào dãy tuần tự từ trái sang phải và nó không phù hợp với dữ liệu nhiều dòng.

Trong khi PE làm mất đi thông tin vị trí theo chiều dọc của ảnh thì 2DPE có thể giải quyết được vấn đề này bằng cách cho mô hình chú ý là cả chiều dọc và chiều ngang của ảnh. Điều này làm cho mô hình có thể chú ý trên từng dòng của và từ trái qua phải. Do vậy, nhánh nhận dạng có thể học dữ liệu cong, xiêng, nhiều dòng mà không cần xoay ảnh.

Giả sử rằng chúng ta có một ma trận đặc trưng hai chiều được sinh ra bởi Mạng chia sẻ. Đặt nó là ma trận SS và có chiều (N,C,H,W)(N,C,H,W), trong đó NN là kích thước của 1 lô dữ liệu, HHWW lần lượt là chiều cao và chiều rộng của feature map khi đi qua backbone. Cho rằng chúng ta có ma trận SS được xem là shws_{hw}. Khi đó cơ chế tự chú ý được tính toán như sau:
Attentionhw=softmax(QKTdk)V\text{Attention}_{hw} = \text{softmax}(\frac{QK^T}{\sqrt{d_k}})V
Trong đó Q=WqShwQ=W_qS_{hw}, K=WkShwK=W_kS_{h'w'}V=WvShwV=W_vS_{hw} , Wq,WkW_q,W_kWvW_v là trọng số tuyến tính của mô hình. QKTQK^T là trọng số thể hiện hệ số chú ý của ma trận đặc trưng khi (h,w)(h,w), trong khi ma trận truy vấn đặc trưng có kích thước (h,w)(h',w'), trong cơ chế tự chú ý thì h=h,w=wh=h',w=w'.

Mã hóa vị trí hai chiều 2DPE được biểu diễn như sau:
attn_weight=QKT=phwWqWkTphw\text{attn\_weight} = QK^T = p_{hw}W^qW^{k^T}p_{h'w'}
phw=α(S)phsinu+β(S)pwsinup_{hw} = \alpha(S)p_h^{sinu}+\beta(S)p_w^{sinu}
phw=α(S)phsinu+β(S)pwsinup_{h'w'} = \alpha(S)p_h'^{sinu}+\beta(S)p_w'^{sinu}
Trong đó, phsinup_h^{sinu}, pwsinup_w^{sinu} là các mã hóa vị trí theo chiều cao và chiều rộng có dạng hình sin :
pp,2isinu=sin(p/100002i/D)p_{p,2i}^{sinu} = \text{sin}(p/10000^{2i/D})
pp,2i+1sinu=cos(p/100002i/D)p_{p,2i+1}^{sinu} = \text{cos}(p/10000^{2i/D})
Ở đây, ppii chỉ số vị trí trong dãy và số chiều. Các hệ số tỷ lệ, α(S)\alpha(S)β(S)\beta(S), được tính toán từ ma trận đặc trưng đầu vào \textbf{S} với hai lớp tích chập được áp dụng vào tính năng trung bình toàn cục như sau:
α(S)=sigmoid(max(0,g(S)W1h)W2h)\alpha(S) = \text{sigmoid}(\text{max}(0,g(S)W_1^h)W_2^h)
β(S)=sigmoid(max(0,g(S)W1w)W2w)\beta(S) = \text{sigmoid}(\text{max}(0,g(S)W_1^w)W_2^w)
Trong đó, W1h,W2h,W1w,W2wW_1^h,W_2^h,W_1^w,W_2^w là trọng số tuyến tính của mô hình. Hàm g(S)g(S) chỉ ra một hình thức gộp trung bình trên tất cả các tính năng của SS. Đầu ra được cho qua hàm kích hoạt sigmoid. α(S)\alpha(S)β(S)\beta(S) đã xác định ảnh hưởng trực tiếp đến mã hóa vị trí chiều rộng và chiều cao để kiểm soát tỷ lệ tương ứng giữa trục dọc và trục ngang để duy trì sự đa dạng về không gian. Theo đó, 2DPE cho phép mô hình phản ánh một cách thích ứng sự liền kề của chiều rộng và chiều cao khi tính toán trọng lượng của sự chú ý bằng cách sử dụng α\alphaβ\beta

Triển khai code trên Torch

Đầu tiền chúng ta khởi tạo 1 class có tên là _2DPositionalEncoding như sau :

class _2DPositionalEncoding(nn.Module): def __init__(self, d_model, dropout=0.1, max_len=100): super(_2DPositionalEncoding, self).__init__() #code def forward(self,x): #code

Trong đó d_model là số chiều chiều của mô hình, max_len là số lượng kí tự tối đa, x là feature map đầu ra khi cho qua một mạng backbone. Tiếp theo, chúng ta cần khởi tạo tensor pe có kích thước (max_len,d_model) và tính toán pe theo công thức của . Và sau đó khởi tạo các lớp để tính hàm α(S)\alpha(S)β(S)\beta(S) như theo công thức trên :

class _2DPositionalEncoding(nn.Module): def __init__(self, d_model, dropout=0.1, max_len=100): super(_2DPositionalEncoding, self).__init__() #init positional encoding pe = torch.zeros(max_len, d_model) position = torch.arange(0, max_len, dtype=torch.float).unsqueeze(1) div_term = torch.exp(torch.arange(0, d_model, 2).float() * (-math.log(10000.0) / d_model)) pe[:, 0::2] = torch.sin(position * div_term) pe[:, 1::2] = torch.cos(position * div_term) self.register_buffer('pe', pe) #init other self.avg = nn.AdaptiveAvgPool2d(1) self.dense = nn.Sequential( nn.Linear(d_model,d_model//2), nn.ReLU(), nn.Dropout(dropout), nn.Linear(d_model//2,d_model*2), nn.Sigmoid()) self.d_model = d_model def forward(self,x):

Tiếp theo đến hàm forward, áp dụng công thức tính PE lên chiều cao và chiều rộng của đầu vào x. Thu được 2 h_encodingw_encoding. Tính α\alphaβ\beta thông qua avgdense. Tính toán 2DPE theo công thức ở trên, ta có code hoàn thiện sau đây :

class _2DPositionalEncoding(nn.Module): def __init__(self, d_model, dropout=0.1, max_len=100): super(_2DPositionalEncoding, self).__init__() #init positional encoding pe = torch.zeros(max_len, d_model) position = torch.arange(0, max_len, dtype=torch.float).unsqueeze(1) div_term = torch.exp(torch.arange(0, d_model, 2).float() * (-math.log(10000.0) / d_model)) pe[:, 0::2] = torch.sin(position * div_term) pe[:, 1::2] = torch.cos(position * div_term) self.register_buffer('pe', pe) #init other self.avg = nn.AdaptiveAvgPool2d(1) self.dense = nn.Sequential( nn.Linear(d_model,d_model//2), nn.ReLU(), nn.Dropout(dropout), nn.Linear(d_model//2,d_model*2), nn.Sigmoid()) self.d_model = d_model def forward(self,x): B,C,H,W = x.shape #position encoding h_encoding = self.pe[:H,:] #H,D w_encoding = self.pe[:W,:] #W,D h_encoding = h_encoding.unsqueeze(1) #H,1,D w_encoding = w_encoding.unsqueeze(0) #1,H,D h_encoding = h_encoding.unsqueeze(0).repeat(B,1,1,1) #B,H,1,D w_encoding = w_encoding.unsqueeze(1).repeat(B,1,1,1) #B,1,W,D #adaptive position encoding inter = self.avg(x).view(B,-1) #B,Hidden alpha = self.dense(inter) #B,d_model*2 alpha = alpha.reshape(-1,2,1,self.d_model)#B,2,1,d_model x = x.permute(0,2,3,1) x = x + alpha[:,0:1,:,:]*h_encoding+ alpha[:,1:2,:,:]*w_encoding return x.reshape(-1,H*W,self.d_model).permute(1,0,2) 

Tổng kết

Để xây dựng mô hình hoàn chỉnh Tranformer OCR các bạn phải thiết kế thêm phần trích xuất thông tin sử dụng mạng CNN nào đó và sau khi đưa qua 2DPE thì cho qua mô hình transformer. Cảm ơn các bạn đã quan tâm, nếu thấy hay thì cho mình 1 vote nhé ❤️

Tham khảo

On Recognizing Texts of Arbitrary Shapes with 2D Self-Attention

Bình luận

Bài viết tương tự

- vừa được xem lúc

Tấn công và phòng thủ bậc nhất cực mạnh cho các mô hình học máy

tấn công bậc nhất cực mạnh = universal first-order adversary. Update: Bleeding edge của CleverHans đã lên từ 3.1.0 đến 4.

0 0 42

- vừa được xem lúc

[Deep Learning] Key Information Extraction from document using Graph Convolution Network - Bài toán trích rút thông tin từ hóa đơn với Graph Convolution Network

Các nội dung sẽ được đề cập trong bài blog lần này. . Tổng quan về GNN, GCN. Bài toán Key Information Extraction, trích rút thông tin trong văn bản từ ảnh.

0 0 219

- vừa được xem lúc

Trích xuất thông tin bảng biểu cực đơn giản với OpenCV

Trong thời điểm nhà nước đang thúc đẩy mạnh mẽ quá trình chuyển đổi số như hiện nay, Document Understanding nói chung cũng như Table Extraction nói riêng đang trở thành một trong những lĩnh vực được quan tâm phát triển và chú trọng hàng đầu. Vậy Table Extraction là gì? Document Understanding là cái

0 0 230

- vừa được xem lúc

Con đường AI của tôi

Gần đây, khá nhiều bạn nhắn tin hỏi mình những câu hỏi đại loại như: có nên học AI, bắt đầu học AI như nào, làm sao tự học cho đúng, cho nhanh, học không bị nản, lộ trình học AI như nào... Sau nhiều lần trả lời, mình nghĩ rằng nên viết hẳn một bài để trả lời chi tiết hơn, cũng như để các bạn sau này

0 0 157

- vừa được xem lúc

[B5'] Smooth Adversarial Training

Đây là một bài trong series Báo khoa học trong vòng 5 phút. Được viết bởi Xie et. al, John Hopkins University, trong khi đang intern tại Google. Hiện vẫn là preprint do bị reject tại ICLR 2021.

0 0 45

- vừa được xem lúc

Deep Learning với Java - Tại sao không?

Muốn tìm hiểu về Machine Learning / Deep Learning nhưng với background là Java thì sẽ như thế nào và bắt đầu từ đâu? Để tìm được câu trả lời, hãy đọc bài viết này - có thể kỹ năng Java vốn có sẽ giúp bạn có những chuyến phiêu lưu thú vị. DJL là tên viết tắt của Deep Java Library - một thư viện mã ng

0 0 139