Tesseractの辞書ファイルの有無の影響について（Failed to load any specific lstm-dictionaries for lang XXX!）

#背景
私は学校の学生研究で手書き文字認識をTesseractで行っているのですが、Tesseractはデフォルトで手書き文字には対応してません。
また、LSTMによる学習が可能との事でいろんなデータセットを使って学習データを作ろうとしているのですが、

> Failed to load any specific lstm-dictionaries for lang XXX!

という警告に戸惑ってしまっています。経緯はこちらを見てもらうと分かると思います。
[ocrd-train(Tesseract)の学習で辞書が見つからない（Failed to load any lstm-specific dictionaries for lang XXX!!）](https://qiita.com/mimuro_syunya/items/c99a7ad37b3c1b98cfd0)

要約すると、
１、kmnistのデータセットを作る（成功）
２、ocrd-trainによって学習データを作成する（成功）
３、学習データは出来たんだけど、変な警告が出る。（失敗？）
４、警告は消せたけど、正しいか分からない。。。（成功？）
てな感じです。

いろいろ調べました。そして自分なりに分かったのですが、なにせ技術系の記事に慣れていないのとwikiが英語なので正しく理解できているかすごく怪しいです。
よって、これは自分用のメモなので、この記事を参考にして学習を行い精度に影響が出てしまっても責任は取れません。
ふんわり「こんな感じなのね」と読んでいただけるとありがたいです。
また、Tesseractに詳しくて、間違い等に気づいた方がいらっしゃったらご教授くださると本当にありがたいです。

#環境
この記事を書いている時点（12月22日）ではtesseract 4.1.1-rc2を使用しています。
また、Ubuntu18.04を前提としています。

#はじめに
Tesseractでは現在、2つの方法により単語（各文字？）判定を行っています。
・パターン認識の手法（Tesseract4.0.0以前）
・LSTMの学習による手法（Tesseract4.0.0以降）
このどちらにおいても辞書を使っているのですが、双方辞書を使うタイミングが異なっています。
なので、ここでは2つとも説明したいと思います。

#結論
結構記事が長くなりそうなので、先に現時点での私の中の結論（正しい保証は無い）

・パターン認識の手法
辞書無しでの単語の認識はとても難しい、というか、辞書がパターン認識の要になっている。

・LSTMの学習による手法
おそらく無くても大丈夫、あまり影響しない。

それでは、上記の2つについて説明していきたいと思います。

#パターン認識の手法
まず、パターン認識と言っても具体的でないので、Tesseractの開発者の一人であるRay Smith氏の論文を参考にして説明していきます。（私は英語が得意ではないので間違った解釈をしているかもしれません）
参考：[Adapting the Tesseract Open Source OCR Engine for Multilingual OCR](https://storage.googleapis.com/pub-tools-public-publication-data/pdf/35248.pdf)
##パターン認識の原理
<div align="center">
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/554112/82a30a38-aeb4-8dbb-5eca-488c31f8a78e.png" alt="属性" title="タイトル">
</div>
まず、辞書の使用を調べるために必要と思える所のみを読みました。第2章の大まかな流れが分かれば辞書の意味がつかめると思います。
そして、この↑の画像ですが、これがパターン認識の流れを示しています。1個ずつ説明していきます。（Fuzzy Space & x-height Fix-upは今回説明しません）
###Page Layout Analysis
読んだ所
>After noting that the commercial engines at the time were strictly for black-on-white text, one of the original design goals of Tesseract was that it should recognize white-on-black (inverse video) text as easily as black-on-white. This led the design (fortuitously as it turned out) in the direction of connected component (CC) analysis and operating on outlines of the components

正直何言ってるかよく分からないですが、2章でPage Layout Analysisに該当する文が恐らくここだと思います。
黒背景に白のテキストにする？って事だから画像をある閾値で２値化しているって事で良さそうです。
そして矢印のComponent Outlines In Text Regionsは、connected component（CCと呼ぶ、繋がっている領域を一つとするという事？）とoperating on outlines of the components（白黒画像の輪郭をいい感じに操作するという事？）を示しています。

###Blob Finding
読んだ所
>A blob is a putative classifiable unit, which may be one or more horizontally overlapping CCs, and their inner nested outlines or holes. A problem is detecting inverse text inside a box vs. the holes inside a character. For English, there are very few characters (maybe © and ®) that have more than 2 levels of outline, and it is very rare to have more than 2 holes, so any blob that breaks these rules is "clearly" a box containing inverse characters, or even the inside or outside of a frame around black-on-white characters.

CC（connected component）により繋がっている領域を一つとして、それに対しブロブを検出するって事ですね。
黒背景に白い文字なので、点とか丸で囲まれた所が検出されます。英語に限って言えば、ブロブが2つ以上ある文字はめったに無いので、ブロブが2個以上検出された文字領域では文字ががぶってしまっている可能性が高いって事らしいです。
そうして、1文字ずつのBOXを決定します。（矢印のCharacter Outlines in Text regionsとはこの事ですね）

###Find Text Lines And Words
まず、Find　Text Linesから、
読んだ所
>After deciding which outlines make up blobs, the text line finder [11] detects (horizontal only) text lines by virtue of the vertical overlap of adjacent characters on a text line. For English the overlap and baseline are so well behaved that they can be used to detect skew very precisely to a very large angle.

ここでは水平方向のみを前提としています（英語が最初なので当たり前ですね）。Blob Findingで検出された文字領域（1文字ずつ）の被りとか隣接具合で1行を判定しているって事ですかね。

次に、Find Words、
読んだ所
> After finding the text lines, a fixed-pitch detector checks for fixed pitch character layout, and runs one of two different word segmentation algorithms according to the fixed pitch decision. 

なんか2つの方法で1つの文字に固定ピッチを割り当てて、そのピッチの間隔とかで文字のまとまりごとに"１つの単語”としているのですね。（多分）
矢印のCharacter Outlines Orgnized Into Wordsは各文字の輪郭から単語ごとにまとめた領域にしたよって事を表しているっぽいですね。
###Recgnize Word (Pass 1 & Pass 2)
これについてはもう一枚図の説明付きで記載がありました。それがこれです。
<div align="center">
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/554112/409eda27-8bee-56ce-3f6e-f0999e7b5111.png" alt="属性" title="タイトル">
</div>
左の矢印は、各”単語”の領域のが入ってくると思って下さい。Static Character Classifierはで単語領域を１文字ずつ区切ります。（いくつかの候補を出す）そして、その候補を<font color="red">辞書</font color>を使って可能性のあるものを選択して良かったものをAdaptive Character Classifierに追加するみたいです。（次回以降の認識に役立てるらしい、全部読んでないのでどう役立てるかは分からない）
<font color="red">辞書はここで使っています！！！！！</font color>
しかし、なかなか何を言っているか分からないと思います。そこで、Ray Smith氏の2016年の何かのプレゼン？資料みたいなのに分かりやすい画像がありました。
参考：[4CharSegmentation.pdf](https://github.com/tesseract-ocr/docs/blob/master/das_tutorial2016/4CharSegmentation.pdf)
<div align="center">
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/554112/0bd80be2-a65f-c833-ff23-64c5cd55d522.png" alt="属性" title="タイトル">
</div>
左の黒背景の画像が単語領域を1文字ずつ区切った候補たちです。そんでWordがどう文字を判定したかです。
（数字の計算方法は知りませんが）辞書を頼りにつけた評価値が右に並んでいる数字です。
そして、一番良い区切り方（画像だと一番下の区切り方）をその領域の単語として処理する。

##パターン認識の辞書の影響
原理で述べた通り、パターン認識は辞書に頼って単語の各文字の決定を行っています。すごく大きな決定要因じゃないですかね。もし辞書がなかったらいくつもある単語領域の各文字の候補から選ぶのがとても困難になると思います。
なので、パターン認識において辞書はとても重要！と言えます。

※2019年12月25日時点での追記
どうやらTesseract3.x時点での辞書は必須だったみたいです。

#LSTMの学習による認識
LSTMで認識すると言っても、どの段階で使うかを説明しておかないといけませんね。（まさか入力画像をそのまま、、、とかじゃないです）
※2020年2月27日追記
LSTMモデルの詳細について調査しました。以下の記事を読んでいただけるとより深く理解できると思います。
[Tesseractの原理のあれこれその２　〜VGSL編〜](https://qiita.com/mimuro_syunya/items/eb26d901f5c30bce51e5)
##LSTMによる認識の処理の流れ
これは文献での説明が見つけられなかったのですが、先程ちょっと出したRay Smith氏のプレゼン資料をお借りします。
参考：[2ArchitectureAndDataStructures.pdf](https://github.com/tesseract-ocr/docs/blob/master/das_tutorial2016/2ArchitectureAndDataStructures.pdf)

<div align="center">
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/554112/b652a274-4f3f-933a-40fd-99faf5c2b660.png" alt="属性" title="タイトル">
</div>

これを見ると、どうやらRecognize Wordの前までは同じステップを踏むみたいですね。
って事は、LSTMに与えるのは”単語ごと”の領域ですね。そしてLSTMの出力は単語らしいです。

<font color="Red">ちょっとまって！！辞書はどこで使うの？？</font color>

安心して下さい、ちゃんと使ってます。別の資料を見てみると、
参考：[6ModernizationEfforts.pdf](https://github.com/tesseract-ocr/docs/blob/master/das_tutorial2016/6ModernizationEfforts.pdf)

<div align="center">
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/554112/fe0d848b-018f-b4f2-f395-1e499867f4ed.png" alt="属性" title="タイトル">
</div>

この画像は下から上へと処理を表しています。まず、単語ごとの画像をLSTMにより1文字単位で文字を検出します。
そして、検出した文字を<font color="Red">Tesseract language model（多分辞書の事）</font color>を参考にして正しい単語に修正する。
という流れかと思います（画像しかヒントを見つけられなかったので完全に私の予想です）
因みに、この単語の修正ですが、検出が

>--EE----n-----c----yy----l----o---p---e----d---i---a-　　----G----a----l--a-----c----t---i----c----a--

なんですが、恐らく'-'は文字の間隔を表していて、その間隔具合と<font color="Red">辞書</font color>を考慮して修正しているんだと思います。

##LSTMの学習による辞書の影響
これははっきり言及している文献が見つからないのですが、調べていく中でのQ＆Aでなんとなく分かってきました。
参考：[Failed to load any lstm-specific dictionaries for lang xxx](https://github.com/tesseract-ocr/tesstrain/issues/28)でのwrnz氏の発言（on 9 Dec 2018）

>Of course, the recognition is heavily influenced by the existence (or non-existence) of dictionaries. Is this influence necessarily positive? I do not think so. Using dictionaries as hypotheses in text recognition bears the risk of introducing false positives (e.g. the German city Rust might be returned as the noun Rost if it is not in the dictionary). However, they were very important for the old, character-focused recognizer (tesseract version < 4) since they provided the necessary context for the single characters. With the line-focussed (lstm) approach, <font color="Red">context information is implicitly provided by the model.</font color> Btw., I am not aware of any systematic evaluation of dictionary usage in OCR.

バージョン４以前では辞書の存在が欠かせなかったのに対して、lstmによるアプローチでは<font color="Red">文脈の情報は暗黙的にモデルに与えられている。</font color>との内容がコメントされています。つまり、lstmで学習すれば、モデルに単語領域内での文脈的な特徴を判定する機能が含まれているので、辞書の重要性はそんなに高くないのかなって思います。

#前回の解決策（仮）は大丈夫なのか？（[これ](https://qiita.com/mimuro_syunya/items/c99a7ad37b3c1b98cfd0#%E8%A7%A3%E6%B1%BA%E7%AD%96%E4%BB%AE)）
LSTMによる学習がどう行われているかまだ完全に分かっていないのですが、私が考えるには、LSTMの学習時に辞書を使うことは無いと思います。（何度も言いますが、現時点で調べた段階での話です。調査中です）すると、処理の流れは以下の2段階に分けられると思います。

①１文字ごとの検出（LSTMによる判別）
②文字（単語内）の組み合わせ等の修正（辞書による修正）

もし仮にに学習が完璧にできていれば、上の処理でいう①だけでも良いと言えます。

話を戻します。

解決策（仮）は前回の記事を見てもらうとして、その記事を書く原因となった[kmnistを使ってTesseractにLSTMの再学習する](https://qiita.com/mimuro_syunya/items/7eaea638530f7034a29f)ではどのようにLSTMを学習させていたかですが、学習対象のデータセットはランダムな文字の羅列です。つまり、１文字ごとにそれがなんの文字であるかを学習させたわけですね。

そして、使っている辞書はjpn_best.lstm-***-dawgです。Tesseractが用意している標準の日本語の辞書です。

別に問題ないんじゃないかなと思いますね。LSTMでの辞書の役割って文字が決定されたあとの単語の修正なので、決定するためのモデルの内容がちょっと変わっただけなんで、辞書は言語ごと（日本語とか英語ごと）に同じ物を使用すべきだと思います。


#まとめ
一応前回の記事にはっきり答えると、「解決策（仮）」は正しい！

以上が現時点（2019年12月22日）で急いで調べた事柄です。
何度も言いますが、これが本当に正しいかどうかは断定できません。私の稚拙な英語力と、技術に関する知識で記事を書いています。
もじ確実な情報が必要な場合はこの記事を信用せず、参考文献等をご自身で読んで確かめて下さい。

なにせ調べた事柄が多いのと、いろんな参考文献を見ているので”あくまで自分のために”体系的にまとまった記事を書きたかっただけです。
今後はこの記事に修正が入るかもしれないです（なんなら消すかもしれないです）。
しかし、Tesseractに詳しい方でもし間違いに気づいた方がいらっしゃったらご教授くださると本当にありがたいです。

それでは、お疲れ様でした。読んでくれてありがとうございます。