Giới thiệu

Nhận dạng văn bản viết tay là một trong những bài toán khôn cùng thú vị, với nguồn vào là một ảnh chứa chữ và cổng output là chữ cất trong ảnh đó. Việc này tương đối khó đối với chữ viết tay, cộng với viết bộ dữ liệu việt nam tương đối hiếm có. Lần này, mình sẽ phân tách sẽ hướng tiếp cận mà team mình đã sử dụng trong cuộc thi do Cinnamon tổ chức, nhờ các phương pháp sử lý hợp lý mà team mình đã đoạt đượt top 1 trong phase 1 của cuộc thi này. Dẫu vậy mà cuộc thì này tổ chức triển khai cũng nhiều năm hơi, làm phần lớn thí sinh tương đối nản. (tầm 2 mon với phần tranh tài + bootcamp). Sơ qua về một ít ứng dụng của OCR. Mình thấy có 2 ứng dụng khá lừng danh là Google Translate, với GotIt của Hùng Trần.

Bạn đang xem: Nhận dạng tiếng việt

Dữ liệu

Dữ liệu của vấn đề này là chỉ có text-line không tồn tại scene text nên vấn đề dễ dàng và đơn giản hơn nhiều so với vấn đề phải detect được chữ trên ảnh có background như ko kể thực tế.

*

Chuẩn bị dữ liệu

Đối cùng với văn bản scan thì việc tiền xử trí như remove noise,background là cực kỳ quan trọng và ảnh hưởng khá nhiểu mang lại độ đúng đắn của bài bác toán. Để remove noise với background thì các bạn có thể sử dụng kmean nhằm cluster bức ảnh ra 2 màu chủ yếu trắng và black rồi tiếp đến binary hình ảnh dựa vào kết quả cluster. Trong quy trình xử lý các chúng ta cũng có thể sử dụng tool này nhé


*

Mô hình

Dữ liệu đã chuẩn chỉnh bị chấm dứt thì mang đến phần model. Môt trong số những mô hình được hay được dùng là CRNN, tuy vậy mô hình mình sử dụng thêm vào nguyên lý attention cho phép model sàng lọc vùng hình ảnh mong ước ao để phát ra đời text. Nguyên lý attention được sử dụng rất nhiều trong machine translation. Mình sẽ sở hữu một bài bác về lý lẽ này,tuy nhiên các chúng ta có thể tham khảo tại đây.


*

Đối tài liệu là ảnh thì họ sẽ dùng mô hình CNN để extract feature. Ở đây, mình dùng VGG16 nhé. Trong model hình này, chúng ta nên để ý số tầng pooling, mình chỉ sử dụng 4 tầng pooling của VGG16, mỗi tầng pooling sẽ có size 2x2,đồng thời bỏ hết toàn bộ các tầng fully connected cuối cùng, cho nên output của VGG16 là 1 tập các feature maps, mỗi px trên feature khớp ứng vùng 16x16 trên bức ảnh đầu vào.


*

Việc chọn form size và số tầng pooling này cực kì quan trọng vì chưng nó ảnh hưởng đến số pixel mà mỗi timestep thấy được được.Nếu các bạn chọn kính thước tầng pooling size quá lớn sẽ dần dần đến việc một step sẽ bao gồm nhiểũ chữ trong hình ảnh do đó quy mô sẽ không nhận dạng được.


base_model = applications.VGG16(weights="imagenet", include_top=False)
Với hình ảnh đầu vào có kích thước 1280x60 thì output của vgg16 là (nmaps, w, h) = …, mỗi dòng tương xứng với chiều w thì khớp ứng với một timstep cho tầng LSTM.

Visual attention

Với mô hình CRNN, kết quả của vgg được truyền trực tiếp vào quy mô LSTM, tuy nhiên, cùng với thực nghiệp của mình khi stack thêm một tờ attention trung tâm tầng vgg cùng LSTM đang cho tác dụng nhận dạng giỏi hơn. Attention cho phép model của chúng ta được thoải mái lựa chọn phối hợp thông tin giữa những timestep khác biệt để tổng vừa lòng lại và sử dụng đặc thù tổng thích hợp này làm đầu vào để thừa nhận dạng chữ cái. Rõ ràng vector context được tổng phù hợp tại từng timestep như sau:


Đầu tiên ta phải tính e cùng với e đó là output của Aligment Model, một dạng feedforward nets với input là tâm lý của networks hiện nay tại


Sau kia ta tính attention score tại từng timestep bằng hàm softmax vì bọn họ mong hy vọng tổng attention score bởi 1


Cuối cùng, context vector là weighted average của trạng thái ẩn cùng với attention score.


def attention_rnn(inputs): # inputs.shape = (batch_size, time_steps, input_dim) input_dim = int(inputs.shape<2>) timestep = int(inputs.shape<1>) a = Permute((2, 1))(inputs) a = Dense(timestep, activation="softmax")(a) // Alignment model + Softmax a = Lambda(lambda x: K.mean(x, axis=1), name="dim_reduction")(a) a = RepeatVector(input_dim)(a) a_probs = Permute((2, 1), name="attention_vec")(a) output_attention_mul = multiply(, name="attention_mul") // Weighted Average return output_attention_mul

LSTM

Với những vector context được tính ở tầng Attention được thực hiện là nguồn vào cho mô hình LSTM. Tại từng timestep, bọn họ dự đoán từ bỏ tại thời khắc đó. Những timestep liên tục có thể dữ đoán và một từ.


*

Connectionist Temporal Classification loss

Với dữ liệu huấn luyện, chúng ta có nhãn là 1 trong đoạn text tương ứng với chữ trong bức hình ảnh đó. Bọn họ không bao gồm nhãn ví dụ tại mỗi thời khắc từ lộ diện là gì khớp ứng với timestep trong quy mô LSTM, vày đó bọn họ không thể sử dụng cross entropy loss để tính độ lỗi mà bắt buộc dùng CTC loss trong vấn đề bài.

Encoding ground truth

CTC loss xử lý vấn đề này theo cách rất là thông minh, nạm thể họ sẽ thử toàn bộ các alignment của ground truth với tính score của tổng toàn bộ alignment. Alignment của ground truth được phân phát sinh bằng phương pháp thêm blank token (-) cùng lặp lại bất cứ kí tự như thế nào trong ground truth.

Ví dụ ta bao gồm ground truth là: sun và có quy mô LSTM của chúng ta dự toán 4 timesteps. Thì những alignment đúng của ground truth là:

sun -> -sun, s-un, su-n, sun- sun -> suun, ssun, sunn

Đới với đều từ gồm 2 kí tự tiếp tục giống nhau, họ sẽ thêm blank token đặt tại giữa để tạo nên một alignment đúng. Lấy ví dụ với kí từ bỏ too. Các alignment đúng có thể là:

too -> -to-o, tto-o

Nhưng ko thể là tooo.

Decoding text

Mô hình của bọn họ sẽ học để predict số đông alignment trên, sau đó chúng ta phải decode để lấy ra chuỗi dự kiến cuối cùng bằng cách gộp số đông kí từ lặp lại liên tục nhau thành một kí từ và kế tiếp xóa hết tất cả blank token.Ví dụ với alignment tto-o thì sau khoản thời gian decode họ sẽ có too bằng cách gộp 2 kí trường đoản cú ‘t’ lại với nhau cùng xóa ‘-‘.

Tính CTC loss

Với mỗi grouth truth chúng ta có các alignment, bất kể alignment làm sao được dự đoán đều là một dự đoán đúng. Do đó, hàm loss ta đề xuất tối ưu đó là tổng của toàn bộ các alignment.


*

Với tự sun, ta tất cả tổng 7 alignments đúng sống trên. Cho nên vì vậy theo model, phần trăm từ sun lộ diện là


p("sun") = p("-sun") + p("s-un") + p("su-n") + p("sun-") + p("ssun") + p("suun") + p("sunn") = 0.2186

Hàm loss của họ sẽ là 1 trong những - p(‘sun’)

Word Beam Search

Chúng ta hoàn toàn có thể lựa chọn câu được phân phát sinh bởi best path, hoặc rất có thể bằng word beam search. Đối cùng với best path, tại từng thời điểm chúng ta lựa lựa chọn từ có tỷ lệ lớn nhất. Mặc dù nhiên đối với cách này,câu được phát sinh rất có thể không bắt buộc là câu có tỷ lệ cao nhất. Cố gắng vào đó,chúng ta hoàn toàn có thể sử dụng beam tìm kiếm để giữ tại N câu có phần trăm lớn theo theo best path rồi ở đầu cuối câu được lựa chọn sẽ là câu tất cả sác xuất cao nhất trong N câu đó.

Đối với vấn đề OCR, từng timestep vẫn phát sinh một kí tự vì vậy từ được phát sinh hoàn toàn có thể không phía bên trong từ điển. Đối ngôi trường trường hợp này, chúng ta có thể sử dụng một trong những phương phát post process để cách xử lý câu được vạc sinh. Đơn giản, họ sử dụng edit distance nhằm so sánh khoảng cách 2 từ, và thay thế từ không phía trong từ điển bởi từ có edit distance phải chăng nhất. Hay tinh vi hơn, chúng ta có thể dùng language model để sửa lỗi câu được phạt sinh.Đối với python/tensorflow, các bạn cũng có thể dùng tủ sách sau để phát sinh câu tự model

OCR Data Augmentation

Trong cuộc thi này, tập tài liệu mà BTC hỗ trợ chỉ bao gồm 2000 mẫu, vì thế để đào tạo model chúng ta cần sử dụng một số phương pháp để tăng dữ liệu.

luân phiên hay dịch chuyển một ít bức ảnh. Sử dụng elastic transform Random erasor 1 phần của bức ảnh.

Xem thêm: "To Hold On Là Gì ? Hold Onto/On To Sth Hold Onto/On To Sth


Kết quả

Mình train 5 folds ,mỗi fold mất khoảng chừng 8 tiếng để chạy. Sau khi chay khoảng tầm 70-80 epochs thì WER khoảng tầm 0.1x. Theo mình thấy thì hiệu quả tương đối bao gồm xác. Có vẻ như bộ dataset hơi dễ :))


Download dataset

Bộ dataset này là của Cinnamon. Mình không phụ trách khi chúng ta sử dụng sai mục đích.