Tesseract4の再学習・追加学習手順まとめ

2019年9月25日

tesseractの学習方法であるScratch TrainingとFine Trainingの手順をまとめた。

結構な文量になってしまったけど、頑張って読んでほしい。

基本的に以下の公式ページを参考にして書いてます。
https://github.com/tesseract-ocr/tesseract/wiki/TrainingTesseract-4.00
英語が得意な方はこちらにもお目通しを。

そもそも学習させる必要あるの?

Tesseract 4.00は新たなニューラルネットワークを用いた文字認識技術を使うようになった。
それによって文字認識精度は格段に高まっている。

4.00のデフォルトで準備されているモデルはかなりの量の
データを学習して作られているのだが、
それでもまだ満足できない認識結果になることがある。

満足できる文字認識結果を出すためには、
公式が提供しているモデルを再学習させ精度をあげる必要がある。

学習方法3種

以下に3つの学習方法を紹介するが、学習の手順はどれもほとんど同じ。
だから、平行して学習を実行するだけのリソースがあれば全てを同時に実行すること出来る。

それぞれに得意、不得意な点があるので、
どの学習方法が自分の目的にあっているのか考えて選ぼう。

Fine Tune

すでに存在するgithubに上がっているモデルに対し、
新たに準備したデータを利用して学習させる方法。
(モデルがあるリポジトリは以下。
 https://github.com/tesseract-ocr/tessdata_best )

この方法なら少数の学習データでの再学習でも機能する。

すでに存在している学習データに近い文字を認識できない場合には、
この方法が最適な可能性が高い。

しかし学習データに”存在しない”、”普通ではない”フォントに関する問題にに対しては、
うまくいかない可能性が高い。

Cut off and Retrain top layer of network

ニューラルネットワークの上層(出力に近い層)を削除し、新たな学習データを用いて、
新たな上層を再学習させる方法。

Fine Tuneのやり方でうまく行かなかったら、このやり方を試すべき。

新たな言語を学習させる際にはうまく機能する可能性が高い。

Retrain from scratch

一から自分の持つデータで学習させる方法。

この方法は問題を解消するためのかなり上質で大量の学習データがないと、
良い結果をもたらす可能性は低い。

過学習に陥ったり、実際のデータではうまく行かない可能性が高い。

学習を始める前に

tesseractを学習させるのにニューラルネットワークの学習工程に関する知識は特に必要はない。
学習工程についても深く掘り下げたい人はこちらの公式wikiもどうぞ。
https://github.com/tesseract-ocr/tesseract/wiki/NeuralNetsInTesseract4.00

あと、学習させることにたくさんの時間と努力を費やす前に
以下のページを読んでおくことを強くおすすめ。
https://github.com/tesseract-ocr/tesseract/wiki/ImproveQuality
文字認識させる対象画像に対してやっておくべき前処理が書かれているよ。

この”前処理”をやってみるとモデルを再学習させなくても、
うまく文字認識出来るようになったりする。

学習の手順

それでは本題のtesseractの学習方法の手順について。

この記事の一番上で紹介した公式ページ
tesseractの学習チュートリアル(TessTutorial)というものがあったので、
それに沿って説明する。

日本語ではなくて英語の再学習の流れであることに注意。
日本語の学習方法に関してはこの応用なので、
復習のつもりで実施してみてね。

要望があれば日本語を対象とした再学習の方法も記載しようと思う。

TessTutorialのための準備

使いたいフォントがすでにインストールされていることが前提条件。
フォントについて詳しく知りたい方は以下のページで。
https://github.com/tesseract-ocr/tesseract/wiki/Fonts

(参考ページの紹介ばかりでごめんね。
 近いうちにリンクに飛ばないでも理解できるようなページに内容を拡張しておきます。)

使いたいフォントがインストールされていることを確認したら以下を順次実行していく。

# 必要なパッケージのインストール
sudo apt update
sudo apt install ttf-mscorefonts-installer
sudo apt install fonts-dejavu
# 追加したフォントの有効化(フォントのキャッシュファイルの更新)
fc-cache -vf
# TessTutorial用のフォルダ作成&移動
mkdir ~/tesstutorial
cd ~/tesstutorial
# 言語データを取得
mkdir langdata
cd langdata
wget https://raw.githubusercontent.com/tesseract-ocr/langdata_lstm/master/radical-stroke.txt
wget https://raw.githubusercontent.com/tesseract-ocr/langdata_lstm/master/common.punc
wget https://raw.githubusercontent.com/tesseract-ocr/langdata_lstm/master/font_properties
wget https://raw.githubusercontent.com/tesseract-ocr/langdata_lstm/master/Latin.unicharset
wget https://raw.githubusercontent.com/tesseract-ocr/langdata_lstm/master/Latin.xheights
# 英語の学習に必要なファイルをダウンロード
mkdir eng
cd eng
wget https://raw.githubusercontent.com/tesseract-ocr/langdata/master/eng/eng.training_text
wget https://raw.githubusercontent.com/tesseract-ocr/langdata/master/eng/eng.punc
wget https://raw.githubusercontent.com/tesseract-ocr/langdata/master/eng/eng.numbers
wget https://raw.githubusercontent.com/tesseract-ocr/langdata/master/eng/eng.wordlist
# tesseract本体のダウンロード
cd ~/tesstutorial
git clone --depth 1 https://github.com/tesseract-ocr/tesseract.git
cd tesseract/tessdata
wget https://github.com/tesseract-ocr/tessdata/raw/master/eng.traineddata
wget https://github.com/tesseract-ocr/tessdata/raw/master/osd.traineddata
mkdir best
cd best
wget https://github.com/tesseract-ocr/tessdata_best/raw/master/eng.traineddata
wget https://github.com/tesseract-ocr/tessdata_best/raw/master/heb.traineddata
wget https://github.com/tesseract-ocr/tessdata_best/raw/master/chi_sim.trained

学習用データ作成

ここで言う学習用のファイルとはlstmfファイルのこと。
このファイルを使ってLSTMトレーニングというtesseractの再学習を行うことになる。

tesstrain.shというシェルスクリプトを使ってlstmfファイルを作成する。

tesstrain.sh実行の準備

tesstrain.shを使うためにはクローンしてきたtesseractコンパイルしてインストールする必要がある。
その手順に関しては以下のページにまとめた。

また特にtesseractのコンパイル、インストール手順で
何をしているのかは特に知らなくても良いという方のために、
実行するコマンドだけを抜粋して以下に載せる。

sudo apt-get install g++ # or clang++ (presumably)
sudo apt-get install autoconf automake libtool
sudo apt-get install pkg-config
sudo apt-get install libpng-dev
sudo apt-get install libjpeg8-dev
sudo apt-get install libtiff5-dev
sudo apt-get install zlib1g-dev
sudo apt-get install libicu-dev
sudo apt-get install libpango1.0-dev
sudo apt-get install libcairo2-dev
git clone https://github.com/DanBloomberg/leptonica.git
cd leptonica
./autogen.sh
./configure
make
sudo make install
cd ~/tesstutorial/tesseract
./autogen.sh
./configure
make
sudo make install
sudo ldconfig
make training
sudo make training-install

tesstrain.shの実行

LSTM training用のファイルを作成するのは以下のコマンド。

~/tesstutorial/tesseract$ src/training/tesstrain.sh --fonts_dir /usr/share/fonts --lang eng --linedata_only \
  --noextract_font_properties --langdata_dir ../langdata \
  --tessdata_dir ./tessdata --output_dir ~/tesstutorial/engtrain

オプションの説明は以下

  • –font_dir: フォントのデータが格納されているディレクトリを指定
  • –linedata_only: lstmtraining用の学習データしか作らないようにする
  • –lang: 対象の言語を指定
  • –noextract_font_properties: フォントのプロパティを抽出しないようにする
  • –langdata_dir: 言語情報が格納されているディレクトリを指定
  • –tessdata_dir: 学習用データを作る際に利用する学習済みのデータのありかを指定
  • –output_dir: 学習用データの出力先を指定

再学習にどれだけの効果があったのか確認するための
評価用のデータもここで作成しておく。

先ほどのコマンドとの違いは–fontlistオプションがついて、
“Impact Condensed”というフォントのみを対象として
LSTM training用のファイルを作成していること。

~/tesstutorial/tesseract$ src/training/tesstrain.sh --fonts_dir /usr/share/fonts --lang eng --linedata_only \
  --noextract_font_properties --langdata_dir ../langdata \
  --tessdata_dir ./tessdata \
  --fontlist "Impact Condensed" --output_dir ~/tesstutorial/engeval

lstmtraining

まずはスクラッチ学習(Training from Scratch)のやり方について紹介する。

Fine Tuningについてはその後で行う。
Fine Tuningのチュートリアルに関してはスクラッチ学習の結果も利用するので、
スクラッチ学習の実施も行って欲しい。

Training From Scratch

上記のtesstrain.shの出力結果を使ってスクラッチ学習を実行する。
lstmtrainingにはかなり時間がかかるので注意。

mkdir -p ~/tesstutorial/engoutput
training/lstmtraining --debug_interval 100 \
  --traineddata ~/tesstutorial/engtrain/eng/eng.traineddata \
  --net_spec '[1,36,0,1 Ct3,3,16 Mp3,3 Lfys48 Lfx96 Lrx96 Lfx256 O1c111]' \
  --model_output ~/tesstutorial/engoutput/base --learning_rate 20e-4 \
  --train_listfile ~/tesstutorial/engtrain/eng.training_files.txt \
  --eval_listfile ~/tesstutorial/engeval/eng.training_files.txt \
  --max_iterations 5000 &>~/tesstutorial/engoutput/basetrain.log

別のターミナルを開いて以下のコマンドを実行すれば、
ログを確認できる。

tail -f ~/tesstutorial/engoutput/basetrain.log

lstmtrainingが完了したら出来上がったモデルを精度を調査する。

試しに”Impact”というフォントで今作ったモデルの精度を検証してみる。

training/lstmeval --model ~/tesstutorial/engoutput/base_checkpoint \
  --traineddata ~/tesstutorial/engtrain/eng/eng.traineddata \
  --eval_listfile ~/tesstutorial/engeval/eng.training_files.txt

一文字の誤認識率(Char error rate)は70~85%あたり、
単語あたりの誤認識率(Word error rate)は90%以上になったりする。

つまりかなり精度が悪い。
上記のlstmtrainingでは4系よりも前のtesseractと
同じだけの量の学習データを使って学習させているにもかかわらずだ。

そこで今度はデフォルトで準備されているtessdata_bestのeng.traineddataを使って精度を測ってみる。

training/lstmeval --model ~/tesstutorial/tesseract/tessdata/best/eng.traineddata \
  --traineddata ~/tesstutorial/engtrain/eng/eng.traineddata \
  --eval_listfile ~/tesstutorial/engeval/eng.training_files.txt

一文字の誤認識率(Char error rate)は2.5%あたり、
単語あたりの誤認識率(Word error rate)は8%あたり。

デフォルトのモデルを使用した方が圧倒的に良い精度が得られている。

ちなみにscratch学習のmax_iterationsの値をさらに増やして行うと、全体的な誤認識率は下がるが、
学習セットで利用されていないフォントに対しては誤認識率が上がってしまったりする。
これは過学習が行われている結果である。

以上の事実からscratch学習を行う際には非常に大量で良質な学習データを準備しないと、
精度の出るモデルは作成されないことが分かった。

Fine Tuning

それでは今度は先ほどscratch学習で作成したモデルに対して、
Fine Tuningを行って認識精度を上げていく。

以下のコマンドを実行する。

mkdir -p ~/tesstutorial/impact_from_small
training/lstmtraining --model_output ~/tesstutorial/impact_from_small/impact \
  --continue_from ~/tesstutorial/engoutput/base_checkpoint \
  --traineddata ~/tesstutorial/engtrain/eng/eng.traineddata \
  --train_listfile ~/tesstutorial/engeval/eng.training_files.txt \
  --max_iterations 1200

上記のコマンドの中でも特に重要なコマンドが”–continue_from”。
これはどのモデルから追加で学習するかを指定するオプションで、
これが記述されることによってFine Tuningが行われることになる。

–continue_fromで指定するのは
学習のチェックポイントファイルか認識用のモデルファイル。
認識用のモデルは”combine_tessdata”コマンドを使えば
traineddataから作成することが出来る。

training/combine_tessdata -e tessdata/best/eng.traineddata \
  ~/tesstutorial/impact_from_full/eng.lstm

また–train_listfileで指定されているファイルがスクラッチ学習の時とは異なり、
engevalディレクトリ内のファイルに指定されていることにも注目。
engevalは”Impact”フォントを基に作られた学習用のファイルが格納されている。

このlstmtrainingの結果作成されたモデルで精度検証してみる。

training/lstmeval --model ~/tesstutorial/impact_from_small/impact_checkpoint \
  --traineddata ~/tesstutorial/engtrain/eng/eng.traineddata \
  --eval_listfile ~/tesstutorial/engeval/eng.training_files.txt

限りなくゼロに近いエラー率になったはず。
私は実施した結果、Char error rateもWord error rateも0になった。

これはFine tuningでモデルが改善された結果だ。

ちなみに注意点があり、tessdata_bestから持ってきたあらかじめ学習が
されているモデルの場合にはイタレーション数を増やしすぎると
誤認識率が上がってしまう恐れがあること。

誤認識率に注目しながら、過学習を起こさないよう注意する。

新たな文字を追加するFine Tuning

Fine Tuningならモデルに無い新たな文字を追加学習することも出来る。

ここでは例として”±”(プラスマイナス)という文字を追加する手順を説明する。

“±”を学習させるために、学習用のテキストである”langdata/eng/eng.training_text”を編集して、
複数箇所(10箇所以上あると良い)に”±”を追記する。
数字の前に付けると意味が通るようになるのでおすすめ。

編集し終わったら、tesstrain.shでlstmtraining用のデータと評価用のデータを作成する。

~/tesstutorial/tesseract$ src/training/tesstrain.sh --fonts_dir /usr/share/fonts --lang eng --linedata_only \
  --noextract_font_properties --langdata_dir ../langdata \
  --tessdata_dir ./tessdata --output_dir ~/tesstutorial/trainplusminus
~/tesstutorial/tesseract$ src/training/tesstrain.sh --fonts_dir /usr/share/fonts --lang eng --linedata_only \
  --noextract_font_properties --langdata_dir ../langdata \
  --tessdata_dir ./tessdata \
  --fontlist "Impact Condensed" --output_dir ~/tesstutorial/evalplusminus

作成したlstmtraining用のデータでlstmtrainingを実行する。

~/tesstutorial/tesseract/src$ training/combine_tessdata -e ../tessdata/best/eng.traineddata \
  ~/tesstutorial/trainplusminus/eng.lstm
~/tesstutorial/tesseract/src$ training/lstmtraining --model_output ~/tesstutorial/trainplusminus/plusminus \
  --continue_from ~/tesstutorial/trainplusminus/eng.lstm \
  --traineddata ~/tesstutorial/trainplusminus/eng/eng.traineddata \
  --old_traineddata ../tessdata/best/eng.traineddata \
  --train_listfile ~/tesstutorial/trainplusminus/eng.training_files.txt \
  --max_iterations 3600

実行が完了したら以下のコマンドを入力して、
“±”の学習が正常に行われているか確認してみる。

~/tesstutorial/tesseract/src$ training/lstmeval --model ~/tesstutorial/trainplusminus/plusminus_checkpoint \
  --traineddata ~/tesstutorial/trainplusminus/eng/eng.traineddata \
  --eval_listfile ~/tesstutorial/evalplusminus/eng.training_files.txt 2>&1 |
  grep ±

Truthの行が実際文字列で、OCRの行がtesseractによる認識結果。
“±”がきちんと認識できていることを確認できるはず。

今度は比較のために”±”を学習させていないモデルで、
結果を確認してみる。

~/tesstutorial/tesseract/src$ training/lstmeval --model ~/tesstutorial/tesseract/tessdata/best/eng.traineddata \
  --eval_listfile ~/tesstutorial/evalplusminus/eng.training_files.txt 2>&1 | \
  grep ±

“Can’t encode transcription: ~”という出力があり、
“±”が認識できていないようだ。

再学習結果をモデルとして使える形にする

ここまで様々な再学習方法を学んできたが、
実は今までのlstmtrainingではcheckpointファイルを作っているだけで、
tesseractで利用できる形のモデル(~.traineddata)にはなっていない。

tesseractで利用できる形のモデルにするためには以下のようなコマンドの実行が必要。

~/tesstutorial/tesseract/src$ mkdir -p ~/tesstutorial/new_trainedata
~/tesstutorial/tesseract/src$ training/lstmtraining --stop_training \
  --continue_from ~/tesstutorial/engoutput/base_checkpoint \
  --traineddata ~/tesstutorial/engtrain/eng/eng.traineddata \
  --model_output ~/tesstutorial/new_trainedata/eng.traineddata

ここでのポイントが–stop_training。

このオプションを付けることで–continue_fromで指定したcheckpointファイルから
新たなtraineddataが作成される。

作成されたら以下のように作成されたtraineddataを使って、
tesseractでの文字認識が行えるようになる。

TESSDATA_PREFIX環境変数を設定
$ export TESSDATA_PREFIX=~/tesstutorial/new_trainedata/
tesseractでの文字認識
$ tesseract -l eng 認識対象の画像ファイル名 stdout

-lで指定するtraineddataは”TESSDATA_PREFIX/~~~.traineddata”の~~~の部分だけで良い。

以上でtesseractの再学習方法の解説は終わり。

再学習のためには必要な手順が多い。
混乱するところもたくさんあるだろうけど、
何回も読み直して再学習を成功させてほしい。

以下に勉強用にメモしていたことを載せておく。
いつかきちんと記事としてまとめる予定なのでお楽しみに。

おまけ

ハードウェア要件

  • マルチコアだと良いが必須では無い。
  • GPUはサポートしていないので使う必要はない。
  • メモリ使用量は–max_image_MBというオプションで指定できる。
    少なくともOSが使用する分を除いて1GBは欲しい。

学習における注意点

  • ラテン語が基となっている言語は約400,000行を4500個のフォントで学習させている。
  • 他の言語は上記ほどたくさんのフォントは学習させていないが、同じくらいの行数学習させている。
  • 試験対象となるもので学習が行われる必要がある
    もしターゲットとなる言語が限られているのなら大量の学習用データは必要とはならないかもしれない。
    ただし、その場合networkの仕様が変わる必要がある。

学習の流れ概要

基本的にはTesseract 3.04の学習の流れと同一

  1. 学習用のテキストデータを準備する
  2. テキストを画像ファイルとboxファイル(画像ファイルと対応する座標ファイルらしい。)に変える
  3. 画像ファイルとboxファイルからunicharsetファイルを作成する
  4. unicharsetと自由選択の辞書データから始まりとなるtraineddataを作成する
  5. 画像ファイルとboxファイルでtraining data set を作成する
  6. training data setで学習を行う
  7. 作成されたdata ファイルを結合させる
  8. 完了

参考情報として3系との重要な違いは以下

  • boxファイルが行単位での情報しか必要としていない。
    そのため処理の高速化が実現されている
  • .trファイルはlstmfファイルというファイルに置き換わった
  • フォントは分離するのではなく、自由に混合させることができる
  • 複数あったクラスタリングのステップは
    lstmtrainingという一つの処理に時間のかかるものに置き換わった

4系の学習ステップは3.04と比較して自動化がそこまで出来ていない。
その理由は以下

  • 中間ファイルから実行すると、処理が止まった場合に再スタートとなってしまう
  • 中間ファイルから実行すると、処理が完了した時自動的に処理が終了したことを報告することが難しくなる
  • networkをtrainするためのオプションが複数ある
  • tesseractで使われている言語モデルやunicharsetと異なるものの使用が許されている。

trainingで使われているファイルを理解する

LSTMモデルに必要なものは全てtaineddataファイルに集約されている。
ただし、starter traineddataファイルはtesstrain中に作成され、あらかじめ準備されている必要がある。

starter traineddataファイルは以下の内容を含むことができる。

  • 制御(controll)値を持つ設定ファイル
  • character setを定義するUni charset
  • Unicharcompress:unicharsetをニューラルネットワークの認識器に実際に使われる文字コードにマッピングするもの
  • Punctuation pattern dawg 句読点のパターン
  • Word dawg 単語リスト
  • Number dawg 数字

その他知っておくと良い点

  • 太字と句読点の情報は必要。他は使うか選べる。
  • combine_lang_modelというツールはunicharsetと任意の単語リストから
    starter traineddataを作成するためにある。
  • 学習中にはcheckpointファイルが作成される。
    このファイルのおかげで学習を途中で終えたり、続けて学習を行うことが出来るようになったりする。
  • 全てのcheckpointファイルは–stop_trainingというlstmtrainingのオプションで
    完全なtraineddataに変換することが出来る。
  • checkpointファイルは学習中、精度が上がってきたら定期的に作成される。
  • –continue_fromフラグで指定されたモデルで使われるunicharsetと
    –traineddataフラグで与えられたデータ内で使われるunicharsetが異なる際には、
    不足分のunicharsetを持つtraineddataを–old_traineddataとともに記載する必要がある。
  • .lstmfファイルはtifファイルとboxファイルから作られる。
  • .lstmファイルは複数の情報が格納されたデータであり、
    画像とそれに対応するUTF8テキストの情報を保持している。
    このlstmfファイルからtraining dataが作成される。