How the makefile in tesstrain-win work

Train Tesseract LSTM methods Comparison

Train Tesseract LSTM with tesstrain.sh on Windows

Train Tesseract LSTM with make on Windows

Win10 Tesseract4.1 LSTM training

tesstrain-win可以在Windows下,根据图像及其对应的文本进行Tesseract LSTM with make的训练。它来源于Tesseract-ocr/tesstrain,makefile以及文件结构有一些改动。本文以tesstrain-win中的makefile为例,记录Train Tesseract LSTM with make训练流程与工作原理。

注:最近为了在windows下进行Tesseract LSTM with make的训练,首次接触makefile,属于初学者,本文属于个人学习笔记与心得记录,请谨慎参考,若有大神愿意对文中的错误或误解之处指点一二,将不甚感激。

References

GNU make

Make 命令教程

makefile基本原理

代码变成可执行文件,叫做编译(compile);先编译这个,还是先编译那个(即编译的安排),叫做构建(build)。Make是最常用的构建工具,诞生于1977年,主要用于C语言的项目。但是实际上 ,任何只要某个文件有变化,就要重新构建的项目,都可以用Make构建。

无规矩不成方圆,make的构建规则都写在Makefile文件里面。

Makefile文件由一系列规则(rules)构成。每条规则的形式如下。

上面第一行冒号前面的部分,叫做”目标”(target),冒号后面的部分叫做”前置条件”(prerequisites);第二行必须由一个tab键起首,后面跟着”命令”(commands)。

“目标”是必需的,不可省略;”前置条件”和”命令”都是可选的,但是两者之中必须至少存在一个。

井号(#)在Makefile中表示注释。

每条规则就明确两件事:构建目标的前置条件是什么,以及如何构建。

前置条件通常是一组文件名,之间用空格分隔。它指定了”目标”是否重新构建的判断标准:只要有一个前置文件不存在,或者有过更新(前置文件的last-modification时间戳比目标的时间戳新),”目标”就需要重新构建。

target这一个或多个的目标文件依赖于prerequisites中的文件,其生成规则定义在command中。prerequisites中如果有一个以上的文件比target文件要新的话,command所定义的命令就会被执行。这就是Makefile的规则。也就是Makefile中最核心的内容。

How the makefile in tesstrain-win work

GNU make中可知,“–trace”可以在执行过程中同时在命令行打印出正在执行的命令与结果。由此,我们可以大致了解一下Train Tesseract LSTM with make的命令执行顺序。

1. make training –trace

在Train Tesseract LSTM with make时,做好准备工作之后,我们会在命令行运行如下命令:

根据makefile的基本规则,首先要构建的目标是”training”,

它并没有命令行,其前置条件是data/foo.traineddata,该前置条件不存在。因此顺序往下执行。

2. $(ALL_GT): $(wildcard $(GROUND_TRUTH_DIR)/*.gt.txt)

$(ALL_GT) = data/foo/all-gt 该文件当前不存在,但其前置条件已存在。在data/foo-ground-truth中有已准备好的训练数据集,其中包含.gt.txt文件。

按照makefile基本规则,前置条件的时间戳比目标时间戳新,因此其命令行会执行,重新构建目标。

命令行完成的任务:在GROUND_TRUTH_DIR路径下找到所有后缀名为*.gt.txt的文件,并取出相应文件的内容按顺序存储到data/foo/all-gt文件中,且去掉重复的内容。

3. ifdef START_MODEL

因$(ALL_GT) 作为此条件下两个目标的前置,因此接下来会执行到这里。

若START_MODEL已赋值,则分别执行combine_tessdata/unicharset_extractor/merge_unicharsets命令;若START_MODEL未赋值,则仅执行unicharset_extractor。

combine_tessdata:用来合并/提取/覆盖/list/压缩 [lang].traineddata files 中的tessdata组件。通过 -u 指令,可以将所有组件解压到指定路径,这些组件包含.lstm/.lstm-number-dawg/.lstm-punc-dawg/.lstm-recorder/.lstm-unicharset/.lstm-word-dawg/.version。

unicharset_extractor:根据设定参数,从.box或纯文本文件以提取字符集unicharset

merge_unicharsets:将参数中设定的两个字符集合并为一个,并存储在data/foo/unicharset中。

4. .PRECIOUS: %.box

第3步执行完成后,无前置关系跳转,故从第2步开始跳转的代码处顺序执行此语句。

.PRECIOUS所依赖的目标具有以下特殊处理:如果make在执行其配方期间被杀死或中断,则不会删除目标。如果目标是中间文件,则不再需要它后,将不会删除它。

这一段代码针对不同的图像格式进行不同的处理,我们的测试数据是.tif和.gt.txt,因此最终执行的代码为:

其用途是调用generate_line_box.py,根据.tif和.gt.txt文件生成相应的.box文件,相对于 jTessBoxEditor + lstmtraining的方案,该代码替代了人工通过jTessBoxEditor来调整和生成box的步骤。但是这里生成的.box文件并不是单个字符所在的位置信息,而是单行文本整体的位置信息。

5. %.lstmf: %.box

%.box作为目标%.lstmf的前置条件已更新,因此接下来会该行代码开始执行。

此处先根据测试数据集中不同的图像格式为变量image赋值。

set -x; 从这里开始打印执行的命令及其参数。

根据设定参数执行tesseract-ocr的训练命令tesseract,利用.tif和.box文件生成.lstmf文件用于lstm训练。

此句执行完成后,重新回到第4步,处理下一张图片,以此类推,循环执行,直到data/foo-ground-truth中的所有图片均已生成相应的.box和lstm文件。

6.$(ALL_LSTMF)

%.lstmf作为该行命令的前置条件之一,第4,5循环执行完成之后,会执行到此处。
在解释该行代码之前,我们先学习一下:

patsubst 意义:查找text中的单词(单词以“空格”、“Tab”或“回车”“换行”分隔)是否符合模式pattern,如果匹配的话,则以replacement替换。这里,pattern可以包括通配符“%”,表示任意长度的字串。如果replacement中也包含“%”,那么,replacement中的这个“%”将是pattern中的那个“%”所代表的字串。

函数返回被替换过后的字符串。

示例:

把字串“a.c b.c”符合模式[%.c]的单词替换成[%.o],返回结果是“a.o b.o”

根据以上解释,makefile中的patsubst所在代码的意义为:将符合模式【%.gt.txt】的文件替换为【%.lstmf】,text内容为相应.gt.txt的文件名。

上面的代码实际执行代码为:

找到路径data/foo-ground-truth下的所有后缀为”.lstmf”的文件,并将这些文件的文件名写入data/foo/all-lstmf中,该行代码执行完成后,all-lstmf中的部分内容为:

7. $(OUTPUT_DIR)/list.train: $(ALL_LSTMF)

根据目标与前置条件的关系,接下来执行此行代码,这一块代码中,两个目标有一个共同的前置条件:

在上面的代码段中,wc –l 用途是计算一个文件的行数。

因此,该段代码的大意是:计算ALL_LSTMF中的行数,并根据变量RATIO_TRAIN的设定值分配训练数据量train与评估数据量eval,train和eval任意一个为0,makefile的执行均会终止并报错。

若train和eval符合条件,则将ALL_LSTMF的前train行写入文件data/foo/list.train中,ALL_LSTMF的后eval行写入文件data/foo/list.eval中。

8. $(PROTO_MODEL)

第7步生成的list.train和list.eval未作为其他目标的前置条件,因此从第5步结束的地方开始顺序执行。

不过我不确定第206~225行是否有执行,何时执行的,作何用,但是make trainging –trace均未打印出此部分的代码,有知道的同学还请不吝赐教。

因此我们这里直接开始看第228行。

该段代码用于生成一个初始的训练数据文件(.traineddata文件),该文件可用于训练基于LSTM的神经网络模型,它以一个unicharset和一组可选的单词列表作为输入。

$(PROTO_MODEL): $(OUTPUT_DIR)/unicharset data/radical-stroke.txt :makefile会在路径data下寻找radical-stroke.txt文件,如果没有会自动通过wget下载,但为了顺利的进行训练,建议提前下载相应的文件放在执行路径下。

script_dir data :应该指向包含* .unicharset文件的目录。 对于基于英语和其他基于拉丁语的脚本,文件为Latin.unicharset。建议提前下载并放在指定路径下。

有的同学用此方式训练完成后,可能会出现如下警告:

Failed to load any lstm-specific dictionaries for lang led!!

该警告与本代码段中numbers/puncs/words这几行代码相关,相关讨论可以参考这里Failed to load any lstm-specific dictionaries for lang xxx

我个人认为Tesseract-ocr/tesstrain的makefile中,此处是有BUG的。虽然numbers/puncs/words这几个参数对应的文件是可选项,但若这几个文件缺失,训练得到的字库虽可以正常识别,但是会报出“Failed to load any lstm-specific dictionaries for lang led!!”警告。在makefile中,若START_MODEL未赋值,makefile并不会自动产生任何相关文件;若已赋值,makefile生成的是.lstm-number-dawg/.lstm-punc-dawg/.lstm-word-dawg等为后缀名的文件,这些文件并不是训练时所需要的文件,它们需要更多的命令来将其转换为正确的文件。

在tesstrain-win中,我也没有修改此处,不过大家在训练时自行准备相应基础字库的numbers/puncs/words相关文件,并放入tesstrain-win的makefile指定路径中,即可避开此处的BUG。

9 lstmtraining

第8步生成的文件为以下代码段的前置,如下:

该段代码正式开始训练LSTM,实际执行语句根据START_MODEL是否有赋值会略有差异,以上代码是START_MODEL已赋值会执行的代码。其中需要注意的参数:

–traineddata:该参数对应combine_lang_model生成的初始训练文件的路径;

–old_traineddata:该参数对应的是基础字库文件的路径,本文中对应的是tessdata/eng.traineddata.

若START_MODEL已赋值,当前训练有基础字库,属于Fine-tune;若START_MODEL未赋值,则属于TRAIN FROM SCRATCH.

两种方式相比,会有以下差异:

Fine-tune特有的两个参数,分别是基础字库的路径和训练的起始点,训练会从基础字库的.lstm文件开始。

TRAIN FROM SCRATCH特有的两个参数,分别用于设置神经网络的相关参数和训练过程中可占用的内存比例。

10 stop_training

训练完成后,将checkpoint文件和.traineddata文件合并成新的.traineddata文件,训练大功告成。

本文到此结束,感谢阅读,谢谢支持。

发表评论

电子邮件地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据

Fork me on GitHub