首先我们获取到足够的公式,对公式进行规范化处理,方便划分出字典。然后通过规范化的公式使用脚本生成图片,具体用到了latex和ghostscript和magick,同时保存哪个公式生成哪个图片,保存为公式-图片映射文件。这样我们得到了3个数据集:规范化的公式集,图片集,公式-图片映射集,还有个附赠品:latex字典。这个字典决定了模型的上限,也就是说,模型预测出的公式只能由字典里的字符组成,不会出现字典以外的字符。
然后构建模型。
模型分为3部分,数据生成器,神经网络模型,使用脚本。
数据生成器读取公式-图片映射文件,为模型提供(公式, 图片)的矩阵元组。
神经网络模型是 Seq2Seq + Attention + Beam Search。Seq2Seq的Encoder是CNN,Decoder是LSTM。Encoder和Decoder之间插入Attention层,具体操作是这样:Encoder到Decoder有个扁平化的过程,Attention就是在这里插入的。随Attention插入的还有我们自定义的一个op,用来导出Attention的数据,做Attention的可视化。
使用脚本包括构建脚本、训练脚本、测试脚本、预测脚本、评估脚本、可视化脚本。使用说明看上面的命令行就行。
训练过程根据epoch动态调整LearningRate。decoder可以选择用lstm
或gru
,在configs/model.json
里改就行。最后输出结果可以选择用 beam_search
或 greedy
,也是在configs/model.json
里改。
我们只要获取到正确的latex公式就行。因为我们可以使用脚本将latex渲染出图片,所以就不用图片数据了。
原来我们想使用爬虫爬取arXiv的论文,然后通过正则表达式提取论文里的latex公式。
但是最后我们发现已经有人做了这个工作,所以就用了他们的公式数据。im2latex-100k , arXiv:1609.04938
现在我们获取到latex公式数据,下面进行规范化。
为什么要规范化:如果不规范化,我们构建字典时就只能是char wise,而latex中有很多是有特定排列的指令,比如
\lim
,这样模型需要花费额外的神经元来记住这些pattern,会使模型效果变差,也导致训练费时间。(有时根本不收敛...别问我怎么知道的...)
我们先手动在代码编辑器里对数据进行规范化,很玄学地用了一些正则表达式,一步一步进行规范化。
最后总结了一下,明确要构建的字典大概是什么样的,然后写了脚本来处理。
然后是通过公式生成图片,保存公式-图片映射文件,构建字典。
构建字典很简单,遍历公式文件的每一行,然后以空格符
为分隔符分割成若干latex块,去掉每一块首尾空格,若非空则加入字典集,保证不重复。
保存公式-图片映射文件也很简单,就是在渲染出图片后,保存当前的公式在公式文件里的行号
和图片路径
,写入映射文件里,也就是.matching.txt
文件。图片文件名是直接用公式行号来命名的,比如1234.png 1234
表示第1234行公式的公式图片是1234.png。所以知道了行号,就知道了公式图片路径。
通过公式生成图片稍微复杂一点,需要用到几个库:latex、ghostscript和magick。事实上用Katex也是可以的,katex是一个渲染latex公式的js库,体积小速度快。原来我们也是打算用这个库处理,后来因为环境问题放弃了。
latex原先我的环境里有了,这是用来生成pdf文件的。执行脚本后会得到A4纸大小的一页pdf。
ghostscript和magick绑定在一起,用来把pdf转化为png格式的图片。
转化为图片后,选定公式 padding 8个像素的方框,crop框外的空白,然后灰度化。
让我鸽一段时间。。。有空再写!
训练时注意控制超参数。推荐参数:
learning rate < 0.1
batchSize == 1