一、序言
对于 OCR 任务来说,目的是为了将图像中的文字识别出来,近几年的研究主要包含以下几个步骤:
- 文字检测:首先对图像进行文字检测,将图中识别为文字的部分标记出来。
- 方向分类器:文字角度分类主要用于图片非0度的场景下,在这种场景下需要对图片里检测到的文本行进行一个转正的操作。
- 文字识别:通过文字检测的文本框识别为具体的文字。
目前研究主要集中在文字检测和文字识别两个任务,本文只介绍文字识别任务中的一种模型,即 CRNN+CTC Loss 方案;另外一种方案是基于 Attention 机制。主要区别在于(后续重点介绍 CTC):
[2]:两大方法主要区别在于最后的输出层(翻译层),即怎么将网络学习到的序列特征信息转化为最终的识别结果。这两大主流技术在其特征学习阶段都采用了 CNN+RNN 的网络结构,CRNN OCR 在对齐时采取的方式是 CTC 算法,而 attention OCR 采取的方式则是 attention 机制。
二、CRNN 介绍
[3]:CRNN 全称为 Convolutional Recurrent Neural Network,主要用于端到端地对不定长的文本序列进行识别,不用先对单个文字进行切割,而是将文本识别转化为时序依赖的序列学习问题,就是基于图像的序列识别。
2.1 CRNN 网络结构
CRNN 网络结构如图 2-1 所示,输入为经过文字检测的文本框(小图),输出为具体的文字内容 “state”,从下往上的结构依次为:卷积层、循环层和翻译层。
2.1.1 CNN 层
卷积层:使用深度 CNN 进行图像的局部特征提取。如图 2-2 所示,整个 CRNN 网络的层级以及参数设置。
注意:卷积核的大小是 3x3,步长 s 和 padding 都为 1,则证明卷积层在不改变图像的尺寸大小情况下进行特征提取;池化层有四个,大小分别为 2x2、2x2、1x2、1x2,则对于图像的高度减半 16 倍,宽度减半 4 倍。然后再经过最后的 Conv 层,例如:图像的输入尺寸为 (channel, height, width) = (1, 32, 160),CNN 的输出尺寸为 (512,1,40)。
并且在 CRNN 模型的训练阶段:所有图像均缩放为 100×32 尺寸,以加速训练过程;测试阶段:针对字符拉伸导致识别率降低的问题,CRNN 保持输入图像尺寸比例,但是图像高度还是必须统一为 32 个像素,卷积特征图的尺寸动态决定 LSTM 时序长度。
2.1.2 Map-to-Sequence
经过 CNN 层的特征图(512,1,40)是不能直接送给 LSTM 进行训练的,通过对特征图中的 40 作为特征向量的序列数,每列包含 512 维特征,构成了 40x512 大小的维度矩阵,输入到 LSTM 网络中。论文 [5] 中提到:
由于卷积层,最大池化层和激活函数在局部区域上执行,因此它们是平移不变的。因此,特征图的每列(即一个特征向量)对应于原始图像的一个矩形区域(称为感受野),并且这些矩形区域与特征图上从左到右的相应列具有相同的顺序。特征序列中的每个向量关联一个感受野。如图 2-3 所示:
2.1.3 RNN
使用双向的 LSTM 进行时序特征的提取,通过上一步,输入到 LSTM 的特征大小为(40x512),每个 LSTM 的时间步为 40,每个时间点的特征维度为 512。LSTM 网络的目标:预测每个时间步的字符内容,即输出为所有字符的 softmax 概率分布,然后将这个后验概率矩阵传入 CTC 层。
总结为:
- 首先会将图像缩放到 32×W×1 大小
- 然后经过 CNN 后变为 1×(W/4)× 512
- 接着针对 LSTM,设置 T=(W/4) , D=512 ,即可将特征输入 LSTM。LSTM 有 256 个隐藏节点,经过 LSTM 后变为长度为 T × nclass 的向量,再经过 softmax 处理,列向量每个元素代表对应的字符预测概率,最后再将这个 T 的预测结果去冗余合并成一个完整识别结果即可。
2.2 CRNN 训练问题
对于 LSTM,正常使用多分类的交叉熵进行训练,完成参数更新,则每一时间步的输出对应一个字符,也就意味着训练时候每张样本图片都需要标记出每个字符在图片中的位置。但是实际上是不可能实现的,所以 CTC 提出一种对不需要对齐的 Loss 计算方法,用于训练网络,被广泛应用于文本行识别和语音识别中。
三、CTC 原理介绍
对于输入 X 和 输出标签 Y 长度都不一致且变换的情况,CTC 提供解决方案为:对于一个给定的输入序列 X ,CTC 给出所有可能的输出分布 Y。根据这个分布,我们可以输出最可能的结果或者给出某个输出的概率。
- 损失函数:给定输入序列 X ,目的是最大化 Y 的后验概率 ,然后通过梯度回传更新参数。
- 预测函数:给定训练好的模型和测试序列 X ,输出概率最大的 Y:
3.1 序列合并机制
RNN 进行时序分类时,不可避免出现冗余信息,如图 3-1 所示,5 个时间步分别被识别为 [a,a,a,b,b],然后将重复的字符合并为 “ab”,但是对于如 book 等字符,合并字符后变成了 bok ,显然不行,所以 CTC 使用 blank 机制解决这个问题。
blank 机制原理:以“-”符号代表 blank,RNN 输出序列时,在文本标签中的重复的字符之间插入一个 “-”,比如输出序列为 “bbooo-ookk”,则最后将被映射为 “book”,即有 blank 字符隔开的话,连续相同字符就不进行合并。即对字符序列先删除连续重复字符,然后从路径中删除所有“-”字符,这个称为解码过程。引入 blank 机制,我们就可以很好地解决重复字符的问题。
3.2 训练阶段
定义一条路径 的输出概率为:
其中, 代表 时间步为 t 时刻的输出概率,使用连乘的方式得出整条路径的概率值。但是存在多条路径经过上一步的合并冗余机制得到相同的路径结果,如(“a-a-a-b-b”和“aa-aa-a-b-b-”通过合并序列之后都为“aaabb”),所以定义:
其中, 代表合并之后的路径,由所有合并之后的相同路径求和所得。常规解法是将所有的合法路径输出概率,然后进行求和,但是实际上路径组合数量非常大,无法逐条求和直接计算 。
借用概率图 HMM 的 “向前-向后” 算法计算:
训练的目的在于最大化概率 ,使用对数似然法定义损失函数为:
- 定义前向递推概率和
[1] 中截图:
性质的初始化说明:在 t = 1 时只可能出现 “_” 和 的情况,y 代表概率。
递推公式为:
对于递推公式的解释说明,可以看到 X 轴代表时间步,z 轴代表输出的字符串,输出标签为“ZOO”:
上图主要分为以下两种情况:
- 当 时:当前字符为 blank,概率只能由前一个时间步的 “-” 或者 前一个时间步的 的值推出;当 为连续两个字符的后一个时,如 “ZOO” 的第 2 个 O,概率只能由前一个时间步的 “-” 或者 前一个时间步的 “O” 的值推出。
- 当 也不是连续字符时:概率除了之前的两种情况,还可以由前一个时间步的 的值推出。
- 同理:定义后向递推概率和
[1] 中截图:
递推公式为,解释见前向:
- 计算梯度
得到了前向和后向概率,将其概率相乘再经过转化,就可以计算 的概率,公式如下:
对于 来说,可以表示为每个时间步输出 label 的概率之和,因为上面的公式都是在 这一点进行前向和后向概率的计算。
为计算每个时刻每个因素的梯度: 观察公式 7 中右端求各项,仅有 的项包含 ,其他项的偏导都为 0,不用考虑,于是有:
公式 8 中,分子第一项是因为 中包含为两个 乘积项(即 ),其他均为与 无关的常数。 中可能包含多个 字符,它们计算的梯度要进行累加,因此,最后的梯度计算结果为:
通过对对数似然进行求导,梯度计算如下:
其中, 通过前向计算可得,就是最后输出为 "-" 或者最后一个 的前向概率值:。其中,由于某时刻某因素的前向和后向概率都已经求出,都为常数,故此梯度计算完成,通过优化算法进行参数调整即可。
3.3 测试阶段
预测就是找到概率值最大的路径,目前存在两种方案:一是 Greedy Search,二是 Beam Search。
Greedy Search:每个时间片均取该时间片概率最高的节点作为输出,这个方法最大的缺点是忽略了一个输出可能对应多个对齐方式。
Beam Search:寻找全局最优值和Greedy Search在查找时间和模型精度的一个折中。在每个时间片计算所有可能假设的概率,并从中选出最高的几个作为一组,进行概率最大值计算。