文字识别:一文读懂 Transformer OCR

共 4595字,需浏览 10分钟

 ·

2022-02-09 17:36

深度学习时代的文字识别:行识别,主流有两种算法,一种是CRNN 算法,一种是attention 算法。

CRNN:CNN+RNN+CTC

白裳:一文读懂CRNN+CTC文字识别

attention :CNN+Seq2Seq+Attention

白裳:完全解析RNN, Seq2Seq, Attention注意力机制

两种算法都比较成熟,互联网上也有很多讲解的文章。

Attention Is All You Need (Transformer)这篇文章,设计了一种新型self-attention结构,取代了 RNN(LSTM\GRU) 的结构,在众多nlp相关任务上取得了效果上的突破,而后来的BERT、GPT等模型亦是来源于这篇文章。有关Transformer 的讲解也有很多。

大师兄:详解Transformer (Attention Is All You Need)

OCR行识别本身也是seq2seq的序列识别问题,这里讲下如何利用transformer结构进行OCR识别,本文介绍的Transformer OCR 基于以下代码

github.com/saberSabersa

目前仅支持宽、高固定的定长识别(高度固定,宽度需要padding到最大长度),以下假设输入图像高度固定为32, 最大宽度为100。

Transformer OCR 模型结构,核心分为两个部分:backbone + transfromer

  1. Backbone:

backbone一般是由卷积层+pooling层堆叠而成, 这里以crnn 中 VGG_FeatureExtractor 为例,一共是经过4次pooling层,其中 2 个2*2 pooling ,2个 2 * 1 的pooling,经过backbone之后输出为512*2*25(其中512是channel数),为了将高度pooling 到1 ,最后又额外利用卷积操作将图像变为512*1*24。(并不必要,因为后面会接一个AdaptiveAvgPool2d 层,以保证不同backbone提取到的特征高度均为1)。

2. Transformer:

Transformer 结构图

transformer 主要有两个结构,encoder 和 decoder.

2.1 Encoder:

encoder 结构由多个MultiHeadAttentionLayer 和 PositionwiseFeedforwardLayer 堆叠而成的block组成。其输入为经过backbone之后提取的特征,这里记为 ,为了保证transformer 输入的时序性,transformer 额外计算了位置编码(pos_embedding),这里记为 ,那么 encoder内部输入给MultiHeadAttentionLayer 的输入可以表示为: 。encoder 第一个block(MultiHeadAttentionLayer + PositionwiseFeedforwardLayer)输入是有图像特征和位置编码得到的 ,后面block 的输入为上一个block 的输出。

Self-attention

Self-attention 是 transformer 的核心结构,在这里数据首先会经过一个叫做self-attention的模块得到一个加权之后的特征向量 ,这个 便是论文公式1中的 :

在encoder 中, 全部来自于输入 :

其中 是模型参数。Self-attention 可以看到是将输入经过三个不同的线性映射得到三个中间变量 ,然后利用矩阵乘法来模拟RNN 的时序计算。RNN,包括LSTM、GRU的一个问题是随着时间步的变长,时序依赖性会减弱,即 和 ,在 比较小的时候互相之间依赖较强,当 越来越大时,两个时刻之间的联系也会越来越弱。但是在矩阵乘法中,每一列也可以认为是一个时间步,而任意两列在矩阵乘法中距离是一样的,都会得到计算,故而对于序列识别来说,transformer打破了时序长时依赖的障碍。但是,由于矩阵乘法是无序的,而OCR识别输入的图像是有序的,所以需要通过位置编码来弥补。

MultiHeadAttentionLayer

Multi-Head Attention,其实是多个self-attention的集成,这里采用多个self-attention能够丰富特征,代买设置的参数为 。Multi-Head Attention的输出分成3步:

  1. 将输入 分别输入到8个self-attention中,得到8个加权后的特征矩阵 ,将这8个输出矩阵直接拼成一个大的特征矩阵,最后再利用一层全连接后得到输出 。

PositionwiseFeedforward

这个全连接有两层,第一层的激活函数是ReLU,第二层是一个线性激活函数,可以表示为:

图像特征 经过encoder之后得到的特征记为 。

2.2 Decoder

Decoder 结构和encoder 稍有不同,是由 MASK MultiHeadAttentionLayer 、encoder-decoder MultiHeadAttentionLayer 和 PositionwiseFeedforwardLayer 三部分组成的多个block 堆叠而成。

Decoder 的输入由两部分组成,其中之一是encoder 输出 ,另外一个输入是target, 由label 得到,而MASK MultiHeadAttentionLayer 结构输入就是target。

MASK MultiHeadAttentionLayer

这里首先要讲一下target 的生成方式,以下图为例,其真实label为London,在计算loss 时,会在字符串最后补一个终止符[end], 由于是batch 训练,多个样本的label长度不同,这里也采用pading 的方式对齐到max_len,即label为London[end][pad][pad]....,而target 为[begin]London[end][pad]...., 即在label 前插入一个起始符,[begin] 和 [end] 用途稍后会说。

London

MASK MultiHeadAttentionLayer 与 MASK MultiHeadAttentionLayer 区别在于mask,而利用mask 的原因是在序列运算的时候,后面的字符可以看到前面的字符,但是前面的字符看不到后面的字符,比如,当预测o的时候,L是已经预测出来的,可以用于输入,但是o、n都不能用于输入,所以要生成三角矩阵来进行mask。操作起来也比较简单,就是在公示(1)中 得到的矩阵对应位置上填充-inf即可。其余地方和 MultiHeadAttentionLayer 一致。将target 经过MASK MultiHeadAttentionLayer 之后得到的特征记为 。

encoder-decoder MultiHeadAttentionLayer

encoder-decoder MultiHeadAttentionLayer 运算过程和MultiHeadAttentionLayer 也是一样的,只不过这里的 来自于 , 而 来自于 , 其余部分与MultiHeadAttentionLayer 完全相同。其意思为每个时刻输入一个query,通过query,key,和 value的矩阵乘法得到当前时刻的输出。target在最开始的时候插入[begin]就是为了输入的query 领先于需要预测的label,即query为[begin],预测得到L,query为L, 预测得到o。最后的PositionwiseFeedforwardLayer 与encoder中相同。

Tips:

最后针对一些常见的问题,给出一些解释:

1)label 为何要在最后添加[end] 符号?

这是因为在测试的时候我们不知道最终结果的长度,比如London这个单词,当预测到字符n的时候,程序并不会终止,会继续预测,添加终止符号的情况下,模型会学到预测到[end],这时候可以终止预测,或者通过简单的后处理提取[end]之前有效字符。

2)target 为何在最开始添加[begin] 符号?

这个和attention OCR 中类似,只不过在运算中由于都是矩阵运算体现的不明显(在代码中测试的时候采用的是循环的方式,这种方式更容易理解)

从decoder 输入可以看到,decoder 同时输入了图像和label(target 是在lable 最开始插入了[begin]符号),但是实际情况我们是没有label的,只有图像,仍然以London 为例,当预测第一个字符的L的时候,如果不补[begin]会发生什么?模型能看到整张图像的特征以及label第一个字符L 提取的特征,当预测o的时候,模型能看到整张图像的特征以及label 前两个符号Lo的特征,这样显然是有问题的。接下来在label 最开始的位置插入一个[begin] 符号,那么当预测第一个字符的L的时候, 模型能看到整张图像的特征以及[begin]的特征,当预测o的时候,模型能看到整张图像的特征以及label 前两个符号[begin][L] 的特征,在训练的时候 L 来自label,当预测的时候,L 是前一次预测的结果。

3)encoder-decoder MultiHeadAttentionLayer 需不需要用mask?

在encoder-decoder MultiHeadAttentionLayer 中计算是不需要计算mask的,这是因为这个模块的输入是MASK MultiHeadAttentionLayer的输出,这里的输出已经保证了 时刻的特征看不到 时刻的特征。

4)transformer VS RNN(LSTM、GRU)有哪些优势?为什么要用位置编码?

这里把两个问题放在一起,之前也简单提过,不过这里只是个人理解,不保证个人理解一定正确。

RNN 是利用隐含层h记录之前时刻的状态,LSTM、GRU 通过记录更多的额外状态以期保留时间跨度更长的信息,但都不可避免的是, 和 ,在 比较小的时候互相之间依赖较强,当 越来越大时,两个时刻之间的联系也会越来越弱。Transformer 里面是 的矩阵乘法,而矩阵乘法任意两列(两个时刻)都会计算。以Beijing is the captial of china 为例,在RNN 这种结构中,Beijing 和 china 距离较远,所以在预测china 的时候RNN中几乎没有任何关于Beijing特征的信息,但是在transformer 中,Beijing is the captial of china 这句话和 is the captial of Beijing china 是一样的,所以在长时间依赖上,transformer 能够优于RNN,也正是因为这个原因,需要利用位置编码将位置信息加给模型。

浏览 15
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐