软件工程应用与实践(八):Paddle OCR文字识别器策略六

2021SC@SDUSC

 

目录

一、前情回顾

1.1 PP-OCR文字识别策略

1.2 本文介绍策略

二、CTC介绍

2.1 CTC是什么

2.2 为什么选用CTC

2.3  CTC算法原理实现

流程

具体细节及过程

CTC怎么做

2.4  CRNN和CTC总结

三、CTC代码实现

3.1  代码位置

3.2  关键代码

总结



一、前情回顾

1.1 PP-OCR文字识别策略

        策略的选用主要是用来增强模型能力和减少模型大小。下面是PP-OCR文字识别器所采用的九种策略:

  • 轻主干,选用采用 MobileNetV3 large x0.5 来权衡精度和效率;
  • 数据增强,BDA (Base Dataaugmented)和TIA (Luo et al. 2020);
  • 余弦学习率衰减,有效提高模型的文本识别能力;
  • 特征图辨析,适应多语言识别,进行向下采样 feature map的步幅修改;
  • 正则化参数,权值衰减避免过拟合;
  • 学习率预热,同样有效;
  • 轻头部,采用全连接层将序列特征编码为预测字符,减小模型大小;
  • 预训练模型,是在 ImageNet 这样的大数据集上训练的,可以达到更快的收敛和更好的精度;
  • PACT量化,略过 LSTM 层;

1.2 本文介绍策略

        在之前系列文章中,已经陆续介绍了PP-OCR文字识别模型中的轻主干策略、轻头部策略、数据增强策略、余弦学习率衰减策略以及特征图辨析策略。同时在各个策略的介绍过程中,穿插了包括PP-OCR文字识别模型的组织网络构建、常用以及最新数据增强算法实现、学习率介绍与学习率衰减常用策略、CRNN文字识别策略介绍等知识的介绍。

        由于之前的介绍可能过于笼统,仍有部分细节没有展开讲述,本篇及之后陆续发布的文章,会对之前的策略介绍进行补充(与之前介绍策略的文章的发布顺序没有太大关系,在哪个部分有新的认识就会补充哪里,欢迎大家指正)。

        在上次的文章中,我们介绍了特征图辨析,结合CRNN网络结构,进行了 feature map的步幅修改,在CRNN最终标签生成时,利用了CTC loss作为对齐方式。本篇文章将会详细介绍CTC算法,并结合代码介绍CTC算法在PP-OCR中的应用。


二、CTC介绍


2.1 CTC是什么

       CTC,Connectionist Temporal Classification,用来解决输入序列和输出序列难以一一对应的问题。

        CTC是一种Loss计算方法,用CTC代替Softmax Loss,训练样本无需对齐。CTC特点:

  • 引入blank字符,解决有些位置没有字符的问题
  • 通过递推,快速计算梯度

2.2 为什么选用CTC

        基于文本识别算法的两种框架(之前也介绍过)如下图:

软件工程应用与实践(八):Paddle OCR文字识别器策略六_第1张图片

   

         选用第一种框架,是由于相比于attention,CTC结合CRNN具有以下优点:

  • 从效果上来看,通用OCR场景CTC的识别效果优于Attention,因为带识别的字典中的字符比较多,常用中文汉字三千字以上,如果训练样本不足的情况下,对于这些字符的序列关系挖掘比较困难。中文场景下Attention模型的优势无法体现。而且Attention适合短语句识别,对长句子识别比较差。
  • 从训练和预测速度上,Attention的串行解码结构限制了预测速度,而CTC网络结构更高效,预测速度上更有优势。

        根据上一篇文章介绍的CRNN OCR,第一种框架为CTC结合CRNN。整个网络,包含CNN和RNN层,然后根据RNN网络结果进一步CTC loss处理获取最终标签(结果)。

       框架选择的CTC loss与其他算法的优劣比较:

  • 对于RNN层,如果使用常见的Softmax cross-entropy loss,则每一列输出都需要对应一个字符元素。那么训练时候每张样本图片都需要标记出每个字符在图片中的位置,再通过CNN感受野对齐到Feature map的每一列,获取该列输出对应的Label才能进行训练。
  • 在实际情况中,标记这种对齐样本非常困难(除了标记字符,还要标记每个字符的位置),工作量非常大。另外,由于每张样本的字符数量不同,字体样式不同,字体大小不同,导致每列输出并不一定能与每个字符一一对应。
  • CTC提出一种对不需要对齐的Loss计算方法,用于训练网络,被广泛应用于文本行识别和语音识别中。

2.3  CTC算法原理实现

流程

        首先,再讲一下CRNN流程(如下图):先通过CNN提取文本图片的Feature map,然后输入到LSTM中。LSTM的每一个时间片后接softmax,输出一个后验概率矩阵。

软件工程应用与实践(八):Paddle OCR文字识别器策略六_第2张图片

具体细节及过程

        先通过CNN提取文本图片的Feature map,然后将每一个channel作为 D = 512 的时间序列输入到LSTM中.

补充定义:

  • CNN Feature map:Feature map的每一列作为一个时间片输入到LSTM中。设Feature map大小为m·T。
  • LSTM:LSTM的每一个时间片后接softmax,输出 y 是一个后验概率矩阵,LSTM可以表示为:y = NETw(X):
  • 空白blank符号:blank表示当前列对应的图像位置没有字符。
  • β变换:中间有空白格的就不消除重复。LSTM的结果y经过β变换之后可以获得结果,β变换显然不是单对单映射

CTC怎么做

对于LSTM给定输入 X 的情况下,输出为 L 的概率为:

对于任意一条路径 Π 有 :

举例,T =  12时

在实际情况中,T会设置的非常大(>=20),且路径非常多,无法通过逐条求和直接计算

P( l | x)。因此需要快速计算方法。

在CTC的训练过程,本质上是通过梯度 调整LSTM的参数 W ,使得对于输入样本为  时使得  取得最大。 

CTC借用了HMM的“向前—向后”(forward-backward)算法来计算,这样对LSTM的输出y求导之后,再根据y对LSTM里面的权重参数w进行链式求导,就可以使用梯度下降的方法来更新参数。

2.4  CRNN和CTC总结

        核心就是将CNN/LSTM/CTC三种方法结合:

  • 首先CNN提取图像卷积特征
  • 然后LSTM进一步提取图像卷积特征中的序列特征
  • 最后引入CTC解决训练时字符无法对齐的问题

三、CTC代码实现

3.1  代码位置

3.2  关键代码

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import paddle
from paddle import nn


class CTCLoss(nn.Layer):
    def __init__(self, **kwargs):
        super(CTCLoss, self).__init__()
        self.loss_func = nn.CTCLoss(blank=0, reduction='none')

    def forward(self, predicts, batch):
        predicts = predicts.transpose((1, 0, 2))
        N, B, _ = predicts.shape
        preds_lengths = paddle.to_tensor([N] * B, dtype='int64')
        labels = batch[1].astype("int32")
        label_lengths = batch[2].astype('int64')
        loss = self.loss_func(predicts, labels, preds_lengths, label_lengths)
        loss = loss.mean()  # sum
        return {'loss': loss}


总结

        由于之前系列文章的介绍可能过于笼统,仍有部分细节没有展开讲述,本篇及之后陆续发布的文章,将会对之前的策略介绍进行补充(与之前介绍策略的文章的发布顺序没有太大关系,在哪个部分有新的认识就会补充哪里)欢迎大家指正。

你可能感兴趣的:(paddle,python,人工智能)