Tesseract5の再学習・追加学習手順まとめ – LinuxOS
tesseractの学習方法であるScratch TrainingとFine Trainingの手順をまとめました。
以下の公式ページを参考にして書いてます。英語が得意な方はこちらにもお目通しを。(Tesseractバージョン4についての記事ですが、バージョン5でもほぼ同じ手順で学習が可能なことを確認できています。またバージョン5用にコマンドを少し変更しないといけない箇所も存在しますが、本記事内に記載しているのでご安心ください。)
https://tesseract-ocr.github.io/tessdoc/tess4/TrainingTesseract-4.00.html
tesseract5では画像と正解となるテキストデータでの学習手順が追加されています。本記事で紹介しているのはテキストとフォントデータからの学習方法ですが、画像とテキストでの学習方法も知りたいという方は以下リポジトリのREADMEをご確認ください。
https://github.com/tesseract-ocr/tesstrain
学習用のサンプルデータと手順を詳細に記載してくれています。
そもそも学習させる必要あるの?
Tesseractはバージョン4から新たなニューラルネットワークを用いた文字認識技術を使うようになり、精度は格段に高まっています。
Tesseractにデフォルトで準備されているモデル「tessdata_best」は大量のデータを学習して作られていますが、それでもまだうまく文字認識できないことがあります。またデフォルトで提供されているモデルでは学習されていない文字も存在します。例えば"±"(プラスマイナス)。学習されていない文字は認識することができません。("±"を追加学習により認識できるようにする手順もこの記事に載せています)
満足できる文字認識結果を出すためには、公式が提供しているモデルを再学習させ認識精度をあげたり、認識できる文字を増やす必要があります。
学習方法3種
3つの学習方法を紹介しますが、学習させるための手順はどれもほとんど同じです。
それぞれの学習方法に良い点、悪い点があるので、どの学習方法が自分の目的にあっているのか把握してから選びましょう。
大体の場合は最初に紹介する「Fine Tune」で問題ないです。
Fine Tune
「Fine Tune」はすでに存在するモデルに対して自前で準備したデータを利用して再学習させる方法です。
この方法なら少数の学習データでも機能します。
一般的なフォントの文字でうまく認識できないことがある場合には、この方法が最適な可能性が高いです。
しかし一般的なフォントからはかけ離れた文字を対象とした認識をさせたい時には、うまくいかないこともあります。
これは元のモデルの影響が大きく残ってしまうためです。
Cut off and Retrain top layer of network
この学習はニューラルネットワークの上層(出力に近い層)を削除し、新たな学習データを用いて新たな上層を作る方です。
「Fine Tune」をした結果うまく認識できなかったら、このやり方を試してみましょう。
完全に新しい言語を学習させる時にうまく機能する可能性が高いです。
Retrain from scratch
1から自分の持つデータで学習させる方法です。
この方法はかなり大量かつ上質な学習データがないと、良い結果が出ません。
大抵の場合過学習に陥ってしまい、学習に使ったデータ以外ではうまく行かない可能性が高いでしょう。
学習を始める前に
これから学習の手順について説明しますが、学習を始める前に見ておくべきページを紹介しておきます。
Improving the quality of the output
このページには文字認識させる対象画像に対してやっておくべき前処理が書かれており、モデルを再学習させなくてもここに記載されている前処理をするだけでうまく認識出来るようになったりします。モデルの学習をさせる前に一度このページに従って前処理をして結果を確認することをお勧めします。
前処理の例をいくつか抜粋しておきます。
- 画質の変更(300dpi以上だとうまく認識されやすい)
- ノイズの除去(認識させたい文字以外の模様や色の削除)
- 文字が横にまっすぐになるように画像を回転させる
記事には上記記事には載っていなかったのですが、一行だけの文字画像であれば、–psm 7をオプションに設定すると精度が上がる可能性が高いです。
tesseract input.png output -l jpn -psm 7
–psm 7は画像を一行の文字画像として扱うことをtesseractに伝えるオプションです。
学習の手順
それでは本題のtesseractの学習方法の手順について。
この記事の一番上で紹介した公式ページにtesseractの学習チュートリアル(TessTutorial)があるので、それに沿って説明します。
日本文字ではなくて英文字の追加学習の流れであることに注意してください。日本文字の学習も手順は変わりません。基本的にダウンロードするファイルなどengという文言が登場する箇所をjpnに変える形です。
またUbuntuなどのdebian系統のOSでの学習手順になる点にもご注意ください。windowsOSでの学習手順は以下の記事が参考になります。
https://www.kkaneko.jp/ai/licenseplate/tesseract.html
TessTutorialのための準備
使いたいフォントがすでに学習実行する予定のマシンにインストールされていることが前提条件です。今回のチュートリアルではフォントデータの登録方法も記載しているので、この記事に書かれている内容以上のことはする必要はありません。
※ 様々なフォントのインストール方法が知りたい方は以下のページを参考にしてください。(英語)
Fonts for Tesseract training
それでは学習環境の構築作業に入ります。以下のコマンドを上から実施してください。rootユーザーで実施する場合はsudoは不要です。
# 必要なパッケージのインストール
sudo echo "deb http://deb.debian.org/debian bookworm contrib non-free" > /etc/apt/sources.list.d/contrib.list
sudo apt update
sudo apt install -y ttf-mscorefonts-installer fonts-dejavu fontconfig git
# 追加したフォントの有効化(フォントのキャッシュファイルの更新)
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/main/eng.traineddata
wget https://github.com/tesseract-ocr/tessdata/raw/main/osd.traineddata
mkdir best
cd best
wget https://github.com/tesseract-ocr/tessdata_best/raw/main/eng.traineddata
wget https://github.com/tesseract-ocr/tessdata_best/raw/main/heb.traineddata
wget https://github.com/tesseract-ocr/tessdata_best/raw/main/chi_sim.traineddata
学習用データ作成
tesseractの学習用ファイルはlstmfファイルと呼ばれ、このファイルを使って学習を行います。tesstrainというpythonスクリプトを使うことでlstmfファイルを作成することができます。
tesstrain実行の準備
tesstrainを使うためにはクローンしてきたtesseractをインストールする必要があります。
インストール手順は以下の記事にまとめているのでご確認ください。
また特にtesseractのインストール手順で何をしているのかは特に知らなくても良いという方のために、実行するコマンドだけを抜粋して以下に載せておきます。
sudo apt-get install -y automake ca-certificates g++ git libtool libleptonica-dev make pkg-config
sudo apt-get install -y --no-install-recommends asciidoc docbook-xsl xsltproc
sudo apt-get install -y libpango1.0-dev libicu-dev libcairo2-dev
cd ~/tesstutorial/tesseract
./autogen.sh
./configure
make
sudo make install
sudo ldconfig
make training
sudo make training-install
pythonのインストール
Tesseract5からtesstrainがpythonスクリプトになったため、tesstrainを実行するためにはpythonをインストールする必要がうまれました。Linux系OSであればpythonがデフォルトでインストールされていると思います。インストールされているか確認し、なければインストールしてください。
# インストールされているか確認(バージョンが出力されればされている)
python3 --version
# 入っていない場合は以下のコマンドでインストール(debian系の場合の例です。OSによってコマンドは異なります。)
sudo apt install python3
この後行う学習の手順ではtesstrainというpythonモジュールを利用しますのでインストール手順を載せます。
sudo apt install -y python3-pip python3.11-venv
cd ~/tesstutorial/tesseract/
python3 -m venv venv
source venv/bin/activate
pip install tesstrain
tesstrainの実行
LSTMトレーニング用のファイルを作成するために以下のコマンドを実行します。
cd ~/tesstutorial/tesseract/
python3 -m tesstrain --fonts_dir /usr/share/fonts --lang eng --linedata_only \
--noextract_font_properties --langdata_dir ../langdata \
--tessdata_dir ./tessdata --fontlist "Arial" "Arial Bold" \
--output_dir ~/tesstutorial/engtrain
オプションの説明は以下です。
- –font_dir: フォントのデータが格納されているディレクトリを指定
- –fontlist: 作成される学習用画像のフォントを指定。複数指定可能
- –linedata_only: lstmtraining用の学習データしか作らないようにする
- –lang: 対象の言語を指定
- –noextract_font_properties: フォントのプロパティを抽出しないようにする
- –langdata_dir: 言語情報が格納されているディレクトリを指定
- –tessdata_dir: 学習用データを作る際に利用する学習済みのデータのありかを指定
- –output_dir: 学習用データの出力先を指定
このコマンドで何をやっているのかを補足説明します。このコマンドでは指定されたテキストデータと指定されたフォントデータを利用して学習に利用する画像データを生成しています。
テキストの指定は–langdata_dirで行っています。langdata_dirで指定されたフォルダ内の指定された言語名(今回だとeng)のフォルダにある.training_textが学習用のテキストとして利用されます。今回は学習用環境の準備のところですでにlangdata/engにtesseractが配布しているトレーニングテキストをダウンロードしていたため、特に意識せずに上記のコマンドを実行できました。
そしてtesstrainによって出来上がった学習用の画像と正解となるテキストデータを用いて、この後のlstmtrainingコマンドでモデルを学習させます。
以上補足でした。
次に追加学習にどれだけの効果があったのかを確認可能にするための評価用のデータを作成します。
先ほどのコマンドとの違いは–fontlistでの指定先が"Impact Condensed"というフォントのみになっていることと、ファイルの出力先です。
python3 -m tesstrain --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 Tune」の説明はその後で行います。「Fine Tune」のチュートリアルの際にはスクラッチ学習の結果も利用するので、スクラッチ学習も行ってください。
Training From Scratch
上記のtesstrainで作成された学習用のデータを使って0からモデルを作成するスクラッチ学習を実行します。
lstmtrainingにはかなり時間がかかります。これは5000回繰り返し学習しているためです。
mkdir -p ~/tesstutorial/engoutput
lstmtraining --debug_interval 100 \
--debug_interval -1 \
--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が完了したら出来上がったモデルを精度を確認します。今作ったモデルの精度を検証してみましょう。
lstmeval --model ~/tesstutorial/engoutput/base_checkpoint \
--traineddata ~/tesstutorial/engtrain/eng/eng.traineddata \
--eval_listfile ~/tesstutorial/engeval/eng.training_files.txt
–modelで指定している~/tesstutorial/engoutput/base_checkpointが先ほどのスクラッチ学習で得られたモデルファイルです。
私の環境での実施結果は"BCER eval=98.035, BWER eval=98.287″でした。
一文字の誤認識率(BCER)も単語あたりの誤認識率(BWER)も90%以上になってます。
つまりかなり精度が悪いです。今度はデフォルトで準備されているtessdata_bestのeng.traineddataを使って精度を測ってみます。
lstmeval --model ~/tesstutorial/tesseract/tessdata/best/eng.traineddata \
--traineddata ~/tesstutorial/engtrain/eng/eng.traineddata \
--eval_listfile ~/tesstutorial/engeval/eng.training_files.txt
私の環境での実施結果は"BCER eval=3.327, BWER eval=9.577″
一文字の誤認識率(BCER)も単語あたりの誤認識率(BWER)も10%以下です。先ほどのスクラッチ学習をして出来上がったモデルとは雲泥の差です。
スクラッチ学習を行う際には非常に大量で良質な学習データを準備しないと、精度の出るモデルは作成できません。
ちなみにlstmtraining時にのmax_iterationsの値をさらに増やして行うと、全体的な誤認識率は下がりますが、tesstrainで指定しなかったフォントに対しては誤認識率が上がってしまいます。これは過学習の結果です。
Fine Tuning
それでは今度は先ほどスクラッチ学習で作成したモデルに対して、Fine Tuningを行って認識精度を上げていきます。
以下のコマンドを実行します。
mkdir -p ~/tesstutorial/impact_from_small
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から作成することが出来ます。
combine_tessdata -e tessdata/best/eng.traineddata \
~/tesstutorial/impact_from_full/eng.lstm
また–train_listfileで指定されているファイルがスクラッチ学習の時とは異なり、engevalディレクトリ内のファイルに指定されていることにも注目しましょう。engevalには検証用のデータとして作成した"Impact"フォントの学習用のファイルが格納されています。
–trainneddataではモデルのプロパティを取得するために利用しています。プロパティとは1文字1文字の文字情報や辞書、学習前のモデルの状態などです。–continue_fromと近いようですが、–trainneddataはあくまで学習に必要な補助的なデータを渡しているに過ぎません。
それではFineTuningの結果作成されたモデルで精度検証してみましょう。
lstmeval --model ~/tesstutorial/impact_from_small/impact_checkpoint \
--traineddata ~/tesstutorial/engtrain/eng/eng.traineddata \
--eval_listfile ~/tesstutorial/engeval/eng.training_files.txt
ゼロに近いエラー率になったはずです。
私が実施した結果は"BCER eval=0.259, BWER eval=1.101″でした。
これはFine tuningでモデルが改善された結果です。
ここで一つ注意点を紹介します。イテレーション数を増やしすぎると検証時の誤認識率が上がってしまうことがあります。これは過学習が行われた結果であると考えられます。誤認識率に注目しながら、過学習を起こさないよう注意しましょう。
新たな文字を追加するFine Tuning
Fine Tuningならモデルに無い新たな文字を追加学習することも出来ます。
ここでは例として"±"(プラスマイナス)という文字を追加する手順を説明します。
“±"を学習させるために、学習用のテキストである"langdata/eng/eng.training_text"を編集して、複数箇所(10箇所以上あると良い)に"±"を追記します。数字の前に付けると文章としての意味が通るようになるので、文字の前後関係が学習対象となるLSTM学習をする上でおすすめです。
編集し終わったら、tesstrain.shでlstmtraining用のデータと評価用のデータを作成しましょう。
cd ~/tesstutorial/tesseract
python3 -m tesstrain --fonts_dir /usr/share/fonts --lang eng --linedata_only \
--noextract_font_properties --langdata_dir ../langdata --fontlist "Arial" "Arial Bold" \
--tessdata_dir ./tessdata --output_dir ~/tesstutorial/trainplusminus
python3 -m tesstrain --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を実行します。
cd ~/tesstutorial/tesseract
combine_tessdata -e tessdata/best/eng.traineddata ~/tesstutorial/trainplusminus/eng.lstm
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
実行が完了したら以下のコマンドを入力して、"±"の学習が正常に行われているか確認してみましょう。
lstmeval --model ~/tesstutorial/trainplusminus/plusminus_checkpoint \
--traineddata ~/tesstutorial/trainplusminus/eng/eng.traineddata \
--eval_listfile ~/tesstutorial/evalplusminus/eng.training_files.txt | \
grep ±
Truthの行が実際文字列で、OCRの行がtesseractによる認識結果です。
“±"がきちんと認識できていることを確認できるはず。
今度は比較のために"±"を学習させていないモデルで、結果を確認してみましょう。
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で利用できる形のモデルにするためには以下のようなコマンドの実行が必要です。
mkdir -p ~/tesstutorial/new_trainedata
cd ~/tesstutorial/tesseract
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(モデル)が作成されます。新しく作成されたモデルは~/tesstutorial/new_trainedata/にeng.traineddataとして作成されています。
作成されたら以下のように作成されたtraineddataを使って文字認識が行えるようになります。
# TESSDATA_PREFIX環境変数を設定
export TESSDATA_PREFIX=~/tesstutorial/new_trainedata/
# tesseractでの文字認識
tesseract -l eng 認識対象の画像ファイル名 stdout
# 例
tesseract -l eng test.png stdout
-lで指定するtraineddataは"TESSDATA_PREFIX/~~~.traineddata"の~~~の部分だけで良いです。
以上でtesseractの再学習方法の解説は終わりです。
追加学習・再学習をするためには必要な手順が多いです。混乱するところもたくさんあると思いますが、何回も読み直して学習を成功させてほしいです。
おまけ
最後に私がtesseractのトレーニング方法を学んでいる中でメモしていた内容を載せておきます。
ハードウェア要件
- マルチコアだと良いが必須では無い。
- GPUはサポートしていないので使う意味はない。
- メモリ使用量は–max_image_MBというオプションで指定できる。少なくともOSが使用する分を除いて1GBは欲しい。
学習の流れ概要
基本的にはTesseract 3.04の学習の流れと同じ
- 学習用のテキストデータを準備する
- テキストを画像ファイルとboxファイル(画像ファイルと対応する座標ファイルらしい。)に変える
- 画像ファイルとboxファイルからunicharsetファイルを作成する
- unicharsetと自由選択の辞書データから始まりとなるtraineddataを作成する
- 画像ファイルとboxファイルでtraining data set を作成する
- training data setで学習を行う
- 作成されたdata ファイルを結合させる
- 完了
参考情報として3系との重要な違いは以下
- boxファイルが行単位での情報しか必要としていない。
そのため処理の高速化が実現されている - .trファイルはlstmfファイルというファイルに置き換わった
- フォントは分離するのではなく、自由に混合させることができる
- 複数あったクラスタリングのステップは
lstmtrainingという一つの処理に時間のかかるものに置き換わった
その他知っておくと良い点
- 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が作成される。