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

2019年9月25日

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

結構な文量になってしまいましたので、頑張って読んでください。

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

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

Tesseractはバージョン4から新たなニューラルネットワークを用いた文字認識技術を使うようになりました。
それによって文字認識精度は格段に高まりました。

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

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

学習方法3種

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

それぞれに良い点、悪い点があるので、どの学習方法が自分の目的にあっているのか考えて選びましょう。
基本的には一番はじめに紹介するFine Tune学習で問題ないです。

Fine Tune

Fine Tuneはすでに存在するモデルに対し、自前で準備したデータを利用して学習させる方法。

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

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

しかし”かなり普通ではない”フォントに関する問題に対しては、うまくいかないこともあります。

Cut off and Retrain top layer of network

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

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

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

Retrain from scratch

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

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

過学習に陥ってしまい、学習に使ったデータ以外ではうまく行かない可能性が高いでしょう。

学習を始める前に

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

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

ここに記載されている前処理をするとモデルを再学習させなくても、うまく文字認識出来るようになったりします。

学習の手順

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

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

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

TessTutorialのための準備

使いたいフォントがすでに学習を実行するマシンにインストールされていることが前提条件です。
フォントのインストール方法を詳しく知りたい方は以下のページを参考にしてください。
https://tesseract-ocr.github.io/tessdoc/Fonts.html

(参考ページの紹介ばかりですみません。
 リンクに飛ばないでも理解できるようなページに内容を拡張したいです。)

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

# 必要なパッケージのインストール
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 Tuneのチュートリアルに関してはスクラッチ学習の結果も利用するので、スクラッチ学習の実施も行ってください。

Training From Scratch

上記のtesstrain.shの出力結果を使ってスクラッチ学習を実行します。
lstmtrainingにはかなり時間がかかります。これは5000回繰り返し学習しているためです。

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

~/tesstutorial/engoutput/base_checkpointがスクラッチ学習で得られたモデルです。

一文字の誤認識率(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の値をさらに増やして行うと、全体的な誤認識率は下がりますが、学習セットで利用されていないフォントに対しては誤認識率が上がってしまうことがあります。これは過学習が行われている結果です。

以上、スクラッチ学習の手順とともに、スクラッチ学習を行う際には非常に大量で良質な学習データを準備しないと、精度の出るモデルは作成されないことが分かりました。

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箇所以上あると良い)に”±”を追記します。
数字の前に付けると文章としての意味が通るようになり、LSTM学習をする上でおすすめです。

編集し終わったら、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を使って文字認識が行えるようになります。

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が作成される。

文字認識

Posted by iruka