在文本识别模型CRNN中,涉及到了CTC算法的使用,由于算法的原理涉及内容较多,所以特另开一篇文章对其原理进行叙述。
自己在学习CTC过程中也是看了诸多资料才大概理解其中的思想,其中最著名的是一篇英文博客,其对CTC算法进行了通俗又详尽地讲解,链接在文末给出。本文的内容也是以其为大纲,同时参考其他优秀的资料,并加上了自己一些的理解,希望能让读者对CTC的原理有一个大致的了解。
文章涉及内容较多,难免有疏漏之处,如有错误,还望指出。
1. 前言
CTC全称Connectionist temporal classification,是一种常用在语音识别、文本识别等领域的算法,用来解决输入和输出序列长度不一、无法对齐的问题。在CRNN中,它实际上就是模型对应的损失函数。
再进行进一步叙述前,这里需要做几点说明。不管是在语音识别还是文本识别领域,CTC通常接在RNN的后面,与RNN结合使用,就像CRNN中一样。所以后面除非特别说明,否则提到的CTC均是将RNN和CTC当整体看待。
RNN在CRNN模型中代表的就是BiLSTM,它接受经过CNN提取的特征向量,大小为
![equation?tex=%5B%5Cmathrm%7Bseq%5C_len%7D%2C%5Cmathrm%7Bchannels%7D%5D](https://i-blog.csdnimg.cn/blog_migrate/ea46ebca0b7ef6574fb8813142052f86.png)
。
![equation?tex=%5Cmathrm%7Bseq%5C_len%7D](https://i-blog.csdnimg.cn/blog_migrate/d4bddc7a3029e95816aab2ab5bd04a7a.png)
即上文提到的特征图的宽度,由于高度为1,所以被去掉了,
![equation?tex=%5Cmathrm%7Bchannels%7D](https://i-blog.csdnimg.cn/blog_migrate/d25391ad535cbefe49a0486a1b2dc34b.png)
即为特征图的通道数。为了便于理解,后面将
![equation?tex=%5Cmathrm%7Bseq%5C_len%7D](https://i-blog.csdnimg.cn/blog_migrate/d4bddc7a3029e95816aab2ab5bd04a7a.png)
也记作
![equation?tex=%5Cmathrm%7Btime%5C_step%7D](https://i-blog.csdnimg.cn/blog_migrate/d87757a93525e27a4ac95c5402b3d4b6.png)
,也可以简写为
![equation?tex=T](https://i-blog.csdnimg.cn/blog_migrate/51d9020f7a89028fa8905549e9b9dc6f.png)
,即CTC中常涉及的概念——时间步。输出序列的大小为
![equation?tex=%5B%5Cmathrm%7Btime%5C_step%7D%2C%5Cmathrm%7Bout%5C_size%7D%5D](https://i-blog.csdnimg.cn/blog_migrate/a3e23d0cb1c5003ef6eb97e5222d5e77.png)
,序列长度与输入一致。而每个分量(向量)的维度均为
![equation?tex=%5Cmathrm%7Bout%5C_size%7D](https://i-blog.csdnimg.cn/blog_migrate/bf04a5cc34abb6648b6acbb7cd65e1ff.png)
,在这里等于字符字典的个数,表示字典个数的概率分布。概率分布经过变换便可以得到最终的预测结果。
为方便叙述,假设输入的序列为
![equation?tex=x%3D%5Cleft%5Bx_%7B1%7D%2C+x_%7B2%7D%2C+%5Cldots%2C+x_%7BT%7D%5Cright%5D+](https://i-blog.csdnimg.cn/blog_migrate/333ef0b5e09fe93fb90e4b73a1b7d84b.png)
,对应的输出序列为
![equation?tex=y%3D%5Cleft%5By_%7B1%7D%2C+y_%7B2%7D%2C+%5Cldots%2C+y_%7BU%7D%5Cright%5D+](https://i-blog.csdnimg.cn/blog_migrate/547f3df3d0608da14d255e8ef3c6d28e.png)
,在这里希望找到
![equation?tex=x](https://i-blog.csdnimg.cn/blog_migrate/79271a73b75b1b2971964504afad8a27.png)
到
![equation?tex=y](https://i-blog.csdnimg.cn/blog_migrate/56151f71c4866c0e204ce3d096379823.png)
的映射关系。
如果使用一般的监督学习算法,会面临诸多的问题,主要可以概括为以下几点:
-
![equation?tex=x](https://i-blog.csdnimg.cn/blog_migrate/79271a73b75b1b2971964504afad8a27.png)
和
![equation?tex=y](https://i-blog.csdnimg.cn/blog_migrate/56151f71c4866c0e204ce3d096379823.png)
的长度是可变的。
-
![equation?tex=x](https://i-blog.csdnimg.cn/blog_migrate/79271a73b75b1b2971964504afad8a27.png)
和
![equation?tex=y](https://i-blog.csdnimg.cn/blog_migrate/56151f71c4866c0e204ce3d096379823.png)
的长度比例也是可变的。
-
![equation?tex=x](https://i-blog.csdnimg.cn/blog_migrate/79271a73b75b1b2971964504afad8a27.png)
和
![equation?tex=y](https://i-blog.csdnimg.cn/blog_migrate/56151f71c4866c0e204ce3d096379823.png)
对应元素之间不能找到严格的对齐关系。
而CTC正是一种可以解决这些问题的算法。对于一个给定的输入
![equation?tex=x](https://i-blog.csdnimg.cn/blog_migrate/79271a73b75b1b2971964504afad8a27.png)
,它可以计算对应所有可能的
![equation?tex=y](https://i-blog.csdnimg.cn/blog_migrate/56151f71c4866c0e204ce3d096379823.png)
的概率分布。通过该概率分布,可以预测最大概率对应的输出或者某个特定输出的概率
由此可以引出损失函数的定义。对于一个给定的输入
![equation?tex=x](https://i-blog.csdnimg.cn/blog_migrate/79271a73b75b1b2971964504afad8a27.png)
,转录层需要最大化对应
![equation?tex=y](https://i-blog.csdnimg.cn/blog_migrate/56151f71c4866c0e204ce3d096379823.png)
的后验概率
![equation?tex=p%28y%5Cmid+x%29](https://i-blog.csdnimg.cn/blog_migrate/6c971d65bce01ad37b76e043ff5f47a1.png)
。当然为了能够正常地训练模型,
![equation?tex=p%28y%5Cmid+x%29](https://i-blog.csdnimg.cn/blog_migrate/6c971d65bce01ad37b76e043ff5f47a1.png)
应该是可导的。由于训练模型通常以最小化损失函数为目标,所以将优化目标转为最小化
![equation?tex=p%28y%5Cmid+x%29](https://i-blog.csdnimg.cn/blog_migrate/6c971d65bce01ad37b76e043ff5f47a1.png)
的负对数似然值,即:
其中
![equation?tex=D](https://i-blog.csdnimg.cn/blog_migrate/1e9eba693a949ee1aa8125a9b7dfe4ba.png)
表示训练集。
而在预测阶段,每给定一个输入
![equation?tex=x](https://i-blog.csdnimg.cn/blog_migrate/79271a73b75b1b2971964504afad8a27.png)
,CRNN要找到最大概率对应的输出,即
不难想到,如果序列长度稍长,所有概率分布的计算量是及其巨大的,因此这里需要一个速度更快的算法。
前面说过,对于给定的输入
![equation?tex=x](https://i-blog.csdnimg.cn/blog_migrate/79271a73b75b1b2971964504afad8a27.png)
,转录层需要计算所有可能的
![equation?tex=y](https://i-blog.csdnimg.cn/blog_migrate/56151f71c4866c0e204ce3d096379823.png)
的概率分布,而关键的问题在于如何处理
![equation?tex=x](https://i-blog.csdnimg.cn/blog_migrate/79271a73b75b1b2971964504afad8a27.png)
与
![equation?tex=y](https://i-blog.csdnimg.cn/blog_migrate/56151f71c4866c0e204ce3d096379823.png)
间的对齐问题。所以下面先分析CTC的对齐方式。
2. 对齐
要说明的是,CTC是不需要输入输出进行对齐的。但是对于给定的输入,为了计算对应
![equation?tex=y](https://i-blog.csdnimg.cn/blog_migrate/56151f71c4866c0e204ce3d096379823.png)
的概率,仍需要对所有可能对齐的概率进行求和,因为可能同一个输出有多个输出路径对应。下面举例进行说明。
例如CRNN的输入
![equation?tex=x](https://i-blog.csdnimg.cn/blog_migrate/79271a73b75b1b2971964504afad8a27.png)
是一张包含单词“cat”的图片,所以对应的输出序列应该为
![equation?tex=y+%3D+%5Bc%2Ca%2Ct%5D](https://i-blog.csdnimg.cn/blog_migrate/56151f71c4866c0e204ce3d096379823.png+%3D+%5Bc%2Ca%2Ct%5D)
。那么一种对齐
![equation?tex=x](https://i-blog.csdnimg.cn/blog_migrate/79271a73b75b1b2971964504afad8a27.png)
和
![equation?tex=y](https://i-blog.csdnimg.cn/blog_migrate/56151f71c4866c0e204ce3d096379823.png)
的方式是先对输入的每个分量
![equation?tex=x_i](https://i-blog.csdnimg.cn/blog_migrate/79271a73b75b1b2971964504afad8a27.png_i)
对应一个输出字符,然后将相邻的重复字符进行合并,具体如下图所示。
图1 单词cat对齐过程 [1]
当然这里很容易发现这种对应方式是不合理的。第一个问题是输入的图片可能根本不包含任何字符,即输出的结果应该为空,而强制每个输入分量
![equation?tex=x_i](https://i-blog.csdnimg.cn/blog_migrate/79271a73b75b1b2971964504afad8a27.png_i)
对应一个字符显然得不到这样的结果。第二个问题是如果将所有相邻重复字符都进行合并处理的话,将不能产生连续相同字符,导致结果可能是错误的。比如如果将单词tooth进行合并处理,那么最终的输出将是toth而不是tooth。
所以考虑上述问题,CTC算法又引入了一个特殊的字符——占位符,记作
![equation?tex=%5Cepsilon](https://i-blog.csdnimg.cn/blog_migrate/9d83d5a736cfe878f7d1f9052bd2ee7b.png)
或
![equation?tex=-](https://i-blog.csdnimg.cn/blog_migrate/1f8cb12c523cba34df1c738af322b7b3.png)
。它表示一个占位,不对应任何字符,因此在最终的输出时要将其删除。这样以后这里仍可以采用上述的对齐规则,并同时避免以上的问题,当然最后不要忘了在输出中去掉 。单词hello的对齐过程如下图所示。
图2 单词hello对齐过程 [1]
可以看出,如果单词存在两个相同的字符,为了能够处理这种情况,需要在这两个字符间插入
![equation?tex=%5Cepsilon](https://i-blog.csdnimg.cn/blog_migrate/9d83d5a736cfe878f7d1f9052bd2ee7b.png)
。这样就能区分诸如“toth”和“tooth”的对齐方式了。
这样的规则具有以下几种特征。第一,输入
![equation?tex=x](https://i-blog.csdnimg.cn/blog_migrate/79271a73b75b1b2971964504afad8a27.png)
与输出
![equation?tex=y](https://i-blog.csdnimg.cn/blog_migrate/56151f71c4866c0e204ce3d096379823.png)
的对齐是单调的,即当
![equation?tex=x](https://i-blog.csdnimg.cn/blog_migrate/79271a73b75b1b2971964504afad8a27.png)
前进至下一个时间片对应的输入分量
![equation?tex=x_%7Bi%2B1%7D](https://i-blog.csdnimg.cn/blog_migrate/79271a73b75b1b2971964504afad8a27.png_%7Bi%2B1%7D)
时,
![equation?tex=y](https://i-blog.csdnimg.cn/blog_migrate/56151f71c4866c0e204ce3d096379823.png)
既可以保持不动,也可以移动至下一个时间片对应的输出分量
![equation?tex=y_%7Bu%2B1%7D](https://i-blog.csdnimg.cn/blog_migrate/56151f71c4866c0e204ce3d096379823.png_%7Bu%2B1%7D)
。第二,输入与最终的输出是一对多的关系,即多个输入分量可能只对应一个输出分量。
所以,输出
![equation?tex=y](https://i-blog.csdnimg.cn/blog_migrate/56151f71c4866c0e204ce3d096379823.png)
的长度一定不大于
![equation?tex=x](https://i-blog.csdnimg.cn/blog_migrate/79271a73b75b1b2971964504afad8a27.png)
。
3. 后验概率
回顾CTC的优化目标,对于一个给定的输入
![equation?tex=x](https://i-blog.csdnimg.cn/blog_migrate/79271a73b75b1b2971964504afad8a27.png)
,需要最大化
![equation?tex=y](https://i-blog.csdnimg.cn/blog_migrate/56151f71c4866c0e204ce3d096379823.png)
对应
![equation?tex=x](https://i-blog.csdnimg.cn/blog_migrate/79271a73b75b1b2971964504afad8a27.png)
的后验概率
![equation?tex=p%28y%5Cmid+x%29](https://i-blog.csdnimg.cn/blog_migrate/6c971d65bce01ad37b76e043ff5f47a1.png)
,所以显然需要先得到后验概率的值。通过上面定义的对齐规则,已经解决了最后序列合并的对齐问题。接下来说明具体如何根据每个时间片的概率,推算出最终输出序列的后验概率
![equation?tex=p%28y%5Cmid+x%29](https://i-blog.csdnimg.cn/blog_migrate/6c971d65bce01ad37b76e043ff5f47a1.png)
。
具体地,对于一个输入
![equation?tex=x%3D%5Cleft%5Bx_%7B1%7D%2C+x_%7B2%7D%2C+%5Cldots%2C+x_%7BT%7D%5Cright%5D+](https://i-blog.csdnimg.cn/blog_migrate/333ef0b5e09fe93fb90e4b73a1b7d84b.png)
,每一时间步对应分量
![equation?tex=x_i](https://i-blog.csdnimg.cn/blog_migrate/79271a73b75b1b2971964504afad8a27.png_i)
的特征维度,记为
![equation?tex=m](https://i-blog.csdnimg.cn/blog_migrate/f79ab5c40ded11a5ecf9c3162bbd89d5.png)
。
![equation?tex=x](https://i-blog.csdnimg.cn/blog_migrate/79271a73b75b1b2971964504afad8a27.png)
经过BiLSTM输出
![equation?tex=z%3D%5Cleft%5Bz_%7B1%7D%2C+z_%7B2%7D%2C+%5Cldots%2C+z_%7BT%7D%5Cright%5D+](https://i-blog.csdnimg.cn/blog_migrate/a6026e0047b3d4ded489618fee3b7b40.png)
,每个分量
![equation?tex=z_i](https://i-blog.csdnimg.cn/blog_migrate/f218af2a19a9356c856f3e5f7a2f13da.png)
的维度记为
![equation?tex=n](https://i-blog.csdnimg.cn/blog_migrate/ce59f55893efd960f1dbdfcd5c192a96.png)
,表示
![equation?tex=n](https://i-blog.csdnimg.cn/blog_migrate/ce59f55893efd960f1dbdfcd5c192a96.png)
个概率。
![equation?tex=n](https://i-blog.csdnimg.cn/blog_migrate/ce59f55893efd960f1dbdfcd5c192a96.png)
实际上等于字符集合
![equation?tex=L](https://i-blog.csdnimg.cn/blog_migrate/600ccfe8e45e11592cb9c011c4107772.png)
的个数,假如需要预测的字符对应的字段包含52个英文字母(包括大小写),考虑之前加入的占位符,则
![equation?tex=n](https://i-blog.csdnimg.cn/blog_migrate/ce59f55893efd960f1dbdfcd5c192a96.png)
的值就是53。
对于每个分量
![equation?tex=z_i](https://i-blog.csdnimg.cn/blog_migrate/f218af2a19a9356c856f3e5f7a2f13da.png)
,都选取一个元素,便可以组成一条输出路径,记为
![equation?tex=l](https://i-blog.csdnimg.cn/blog_migrate/f32f9aac32d40c08bf41372d319a306a.png)
,输出路径的空间可表示为
![equation?tex=L%5ET](https://i-blog.csdnimg.cn/blog_migrate/600ccfe8e45e11592cb9c011c4107772.png%5ET)
。
定义一个映射
![equation?tex=F](https://i-blog.csdnimg.cn/blog_migrate/2d0017cb7d6481fec7e76e6f804647a9.png)
,表示对中间输出路径进行变换,得到最后的输出
![equation?tex=y](https://i-blog.csdnimg.cn/blog_migrate/56151f71c4866c0e204ce3d096379823.png)
。注意这里的路径不是最终的输出
![equation?tex=y](https://i-blog.csdnimg.cn/blog_migrate/56151f71c4866c0e204ce3d096379823.png)
,需要经过合并相邻字符以及删除占位符的处理,才会得到
![equation?tex=y](https://i-blog.csdnimg.cn/blog_migrate/56151f71c4866c0e204ce3d096379823.png)
,所以相当于中间结果。下面举例说明。
假设识别的序列为"taste",
![equation?tex=T%3D12](https://i-blog.csdnimg.cn/blog_migrate/51d9020f7a89028fa8905549e9b9dc6f.png%3D12)
时,那么以下几种路径均满足条件:
因此求taste最终输出对输入的后验概率时 ,就是求这四条路径对应概率之和。进一步推广,给定输入
![equation?tex=x](https://i-blog.csdnimg.cn/blog_migrate/79271a73b75b1b2971964504afad8a27.png)
,中间结果对应的路径
![equation?tex=l](https://i-blog.csdnimg.cn/blog_migrate/f32f9aac32d40c08bf41372d319a306a.png)
,最终输出
![equation?tex=y](https://i-blog.csdnimg.cn/blog_migrate/56151f71c4866c0e204ce3d096379823.png)
,则
![equation?tex=y](https://i-blog.csdnimg.cn/blog_migrate/56151f71c4866c0e204ce3d096379823.png)
对
![equation?tex=x](https://i-blog.csdnimg.cn/blog_migrate/79271a73b75b1b2971964504afad8a27.png)
的后验概率可以表示为:
假设不同时间步的输出变量相互独立,那么对于输出路径
![equation?tex=l](https://i-blog.csdnimg.cn/blog_migrate/f32f9aac32d40c08bf41372d319a306a.png)
对
![equation?tex=x](https://i-blog.csdnimg.cn/blog_migrate/79271a73b75b1b2971964504afad8a27.png)
的后验概率可表示为:
![equation?tex=l_t](https://i-blog.csdnimg.cn/blog_migrate/f32f9aac32d40c08bf41372d319a306a.png_t)
表示路径
![equation?tex=l](https://i-blog.csdnimg.cn/blog_migrate/f32f9aac32d40c08bf41372d319a306a.png)
在
![equation?tex=t](https://i-blog.csdnimg.cn/blog_migrate/3b1922fd3ef8dd7c883fb35b699da495.png)
时间步时对应的输出字符,而
![equation?tex=z_%7B%7Bl_t%7D%7D%5Et](https://i-blog.csdnimg.cn/blog_migrate/fc4aed6ab145807f37fbee5772f6fe78.png)
表示在
![equation?tex=t](https://i-blog.csdnimg.cn/blog_migrate/3b1922fd3ef8dd7c883fb35b699da495.png)
时间步时选取的字符为
![equation?tex=l_t](https://i-blog.csdnimg.cn/blog_migrate/f32f9aac32d40c08bf41372d319a306a.png_t)
的概率。因此,综合上述两式可得:
简单来说,公式表示的含义为
![equation?tex=y](https://i-blog.csdnimg.cn/blog_migrate/56151f71c4866c0e204ce3d096379823.png)
对
![equation?tex=x](https://i-blog.csdnimg.cn/blog_migrate/79271a73b75b1b2971964504afad8a27.png)
的后验概率等于所有对应路径的概率之和,而每条路径对
![equation?tex=x](https://i-blog.csdnimg.cn/blog_migrate/79271a73b75b1b2971964504afad8a27.png)
的后验概率又等于组成该路径的字符出现概率的乘积。
由于连续重复字符以及占位符的存在,每一个特定的输出
![equation?tex=y](https://i-blog.csdnimg.cn/blog_migrate/56151f71c4866c0e204ce3d096379823.png)
都会对应相当多的路径。如果这里逐一遍历进行求解,那么时间的复杂度可达到
![equation?tex=O%28%7Bn%5ET%7D%29](https://i-blog.csdnimg.cn/blog_migrate/9f0e2b4ad7cdfb6b3149d0bf0f2ae677.png)
,
![equation?tex=n](https://i-blog.csdnimg.cn/blog_migrate/ce59f55893efd960f1dbdfcd5c192a96.png)
为前面定义的字符集的个数,
![equation?tex=T](https://i-blog.csdnimg.cn/blog_migrate/51d9020f7a89028fa8905549e9b9dc6f.png)
为时间步总长。这是因为有
![equation?tex=T](https://i-blog.csdnimg.cn/blog_migrate/51d9020f7a89028fa8905549e9b9dc6f.png)
个步长,而每个步长输出的字符又有
![equation?tex=n](https://i-blog.csdnimg.cn/blog_migrate/ce59f55893efd960f1dbdfcd5c192a96.png)
种可能性。所以需要对算法进行改进,这里便借鉴了动态规划的思想。
4. 前向后向算法
对于一个最终输出序列
![equation?tex=y](https://i-blog.csdnimg.cn/blog_migrate/56151f71c4866c0e204ce3d096379823.png)
,实际上也表示中间路径合并后的结果。定义
![equation?tex=y%27](https://i-blog.csdnimg.cn/blog_migrate/56151f71c4866c0e204ce3d096379823.png%27)
表示在序列
![equation?tex=y](https://i-blog.csdnimg.cn/blog_migrate/56151f71c4866c0e204ce3d096379823.png)
所有相邻元素之间插入占位符后的序列。比如:
依然拿上述例子进行说明,如下图所示。
图3 单词state的可取路径 [3]
从上图可以看出,四条中间路径
![equation?tex=l_1](https://i-blog.csdnimg.cn/blog_migrate/f32f9aac32d40c08bf41372d319a306a.png_1)
,
![equation?tex=l_2](https://i-blog.csdnimg.cn/blog_migrate/f32f9aac32d40c08bf41372d319a306a.png_2)
,
![equation?tex=l_3](https://i-blog.csdnimg.cn/blog_migrate/f32f9aac32d40c08bf41372d319a306a.png_3)
,
![equation?tex=l_4](https://i-blog.csdnimg.cn/blog_migrate/f32f9aac32d40c08bf41372d319a306a.png_4)
合并处理后都可以得到state,并且他们都经过字符
![equation?tex=a](https://i-blog.csdnimg.cn/blog_migrate/3a1b450ba33b8215b0d69885896f7309.png)
。如果将路径蓝色部分记为
![equation?tex=b](https://i-blog.csdnimg.cn/blog_migrate/111cf5c2cf1cc54e0b93080ff933d2e8.png)
,红色部分记为
![equation?tex=r](https://i-blog.csdnimg.cn/blog_migrate/96cd0c66831377044bebc676cc938856.png)
,则不难推出:
由于4条路径都经过
![equation?tex=a](https://i-blog.csdnimg.cn/blog_migrate/3a1b450ba33b8215b0d69885896f7309.png)
,所以都包含
![equation?tex=z_a%5E6](https://i-blog.csdnimg.cn/blog_migrate/d23f91a1f1845bdebf57f4783f8a3aa6.png)
项,提取公因式进行合并,令
则公式
![equation?tex=p%28%7Bl%5E1%7D%2C%7Bl%5E2%7D%2C%7Bl%5E3%7D%2C%7Bl%5E4%7D%5Cmid+x%29](https://i-blog.csdnimg.cn/blog_migrate/465cea5c06ca6f5ba8649e18857fbbbe.png)
可以写成:
当然,这只是包含4条路径的结果,实际上序列state应该对应更多的路径,如下图所示。
图4 单词state所有可能路径 [3]
所以上述公式可推广为:
进一步地,这里可以定义
![equation?tex=%7B%5Calpha+_t%7D%28%7By%27_k%7D%29](https://i-blog.csdnimg.cn/blog_migrate/9facf21c917f78ed323231b02fdccfbe.png)
, 表示时间步为
![equation?tex=t](https://i-blog.csdnimg.cn/blog_migrate/3b1922fd3ef8dd7c883fb35b699da495.png)
时经过字符
![equation?tex=y_k%27](https://i-blog.csdnimg.cn/blog_migrate/56151f71c4866c0e204ce3d096379823.png_k%27)
的所有路径在
![equation?tex=1-t](https://i-blog.csdnimg.cn/blog_migrate/0a881789098e7117b34c2d98ae440beb.png)
时刻的概率和,即:
不难分析,
![equation?tex=t%3D1](https://i-blog.csdnimg.cn/blog_migrate/3b1922fd3ef8dd7c883fb35b699da495.png%3D1)
时字符只能占位符或
![equation?tex=y_1](https://i-blog.csdnimg.cn/blog_migrate/56151f71c4866c0e204ce3d096379823.png_1)
,所以可得:
进一步观察可以发现,由于
![equation?tex=%7Bl_6%7D+%3D+a](https://i-blog.csdnimg.cn/blog_migrate/572da8962257d65febbf2c4513549d5c.png)
的限制,
![equation?tex=t%3D5](https://i-blog.csdnimg.cn/blog_migrate/3b1922fd3ef8dd7c883fb35b699da495.png%3D5)
时对应的字符只能为
![equation?tex=a](https://i-blog.csdnimg.cn/blog_migrate/3a1b450ba33b8215b0d69885896f7309.png)
,
![equation?tex=t](https://i-blog.csdnimg.cn/blog_migrate/3b1922fd3ef8dd7c883fb35b699da495.png)
或
![equation?tex=%5Cepsilon](https://i-blog.csdnimg.cn/blog_migrate/9d83d5a736cfe878f7d1f9052bd2ee7b.png)
。所以可得递推公式:
进一步推广可得一般式如下:
类似地,这里可以定义
![equation?tex=%7B%5Cbeta+_t%7D%28%7By%27_k%7D%29](https://i-blog.csdnimg.cn/blog_migrate/57a56126fd75ab8c46a8c345df71e27c.png)
,表示时间步为
![equation?tex=t](https://i-blog.csdnimg.cn/blog_migrate/3b1922fd3ef8dd7c883fb35b699da495.png)
时经过字符
![equation?tex=y_k%27](https://i-blog.csdnimg.cn/blog_migrate/56151f71c4866c0e204ce3d096379823.png_k%27)
的所有路径在
![equation?tex=t-T](https://i-blog.csdnimg.cn/blog_migrate/3b1922fd3ef8dd7c883fb35b699da495.png-T)
时刻的概率和,即:
不难分析,
![equation?tex=t%3DT](https://i-blog.csdnimg.cn/blog_migrate/3b1922fd3ef8dd7c883fb35b699da495.png%3DT)
时字符只能占位符或
![equation?tex=%7By_%7B%7Cy%27%7C+-+1%7D%7D](https://i-blog.csdnimg.cn/blog_migrate/8fd87727d4a2a1b154a1cad3afc0a9a7.png)
,所以可得初始条件:
类似地,可得
![equation?tex=%7B%5Cbeta+_t%7D%28%7By%27_k%7D%29](https://i-blog.csdnimg.cn/blog_migrate/57a56126fd75ab8c46a8c345df71e27c.png)
的递推公式为:
由于
![equation?tex=p%28y%5Cmid+x%29](https://i-blog.csdnimg.cn/blog_migrate/6c971d65bce01ad37b76e043ff5f47a1.png)
对
![equation?tex=y_k%27](https://i-blog.csdnimg.cn/blog_migrate/56151f71c4866c0e204ce3d096379823.png_k%27)
求导时,只与经过
![equation?tex=z_%7By_k%27%7D%5Et](https://i-blog.csdnimg.cn/blog_migrate/8918efc4c8442e3d09503d9bf3890eab.png)
的路径有关,所以在反向传播对
![equation?tex=p%28y%5Cmid+x%29](https://i-blog.csdnimg.cn/blog_migrate/6c971d65bce01ad37b76e043ff5f47a1.png)
进行梯度计算时,便可以将公式进行简化:
而由于
所以将其带入可得:
由上面的推导可知,
![equation?tex=%7B%5Calpha+_t%7D%28%7By%27_k%7D%29](https://i-blog.csdnimg.cn/blog_migrate/9facf21c917f78ed323231b02fdccfbe.png)
和
![equation?tex=%7B%5Cbeta+_t%7D%28%7By%27_k%7D%29](https://i-blog.csdnimg.cn/blog_migrate/57a56126fd75ab8c46a8c345df71e27c.png)
都可以利用动态规划的思想通过递推公式求出,而不用从头开始计算,复杂度从
![equation?tex=O%28%7Bn%5ET%7D%29](https://i-blog.csdnimg.cn/blog_migrate/9f0e2b4ad7cdfb6b3149d0bf0f2ae677.png)
变为了
![equation?tex=O%28nT%29](https://i-blog.csdnimg.cn/blog_migrate/5fe8ba2b62a3c4bfed55be813e505e20.png)
,大大简化了计算。而
![equation?tex=p%28y%5Cmid+x%29](https://i-blog.csdnimg.cn/blog_migrate/6c971d65bce01ad37b76e043ff5f47a1.png)
只涉及乘法和加法运算,显然是可导的,所以就可以通过上式进行反向传播计算了。
5. 预测
前面提到,在预测阶段,给定一个输入
![equation?tex=x](https://i-blog.csdnimg.cn/blog_migrate/79271a73b75b1b2971964504afad8a27.png)
,计算最大概率对应的输出序列。如果假设时间片之间相互独立,那么只需将每一时间片对应概率最大的字符作为预测值,然后组成序列,最后做去重等处理得到最终结果。不过这样并没有考虑多个序列经过对齐对应同一个输出结果。例如,假如
![equation?tex=%5Bc%2Cc%2C%5Cepsilon%5D](https://i-blog.csdnimg.cn/blog_migrate/229d5e34f1feb6d00b9e9b13e286c464.png)
和
![equation?tex=%5Bc%2Cc%2Cc%5D](https://i-blog.csdnimg.cn/blog_migrate/ec6d3c3330911ae27b5e6c3a9bc55c44.png)
各自的概率都低于
![equation?tex=%5Bc%2Co%2Cc%5D](https://i-blog.csdnimg.cn/blog_migrate/994d5adb45d5674b66c3d7509aff0d3c.png)
,而二者的概率之和高于后者。前者对齐后的结果均为
![equation?tex=%5Bc%5D](https://i-blog.csdnimg.cn/blog_migrate/26d76c9fd99b0c6c36ea2b9c410c370a.png)
,而后者对齐的结果仍为
![equation?tex=%5Bc%2Co%2Cc%5D](https://i-blog.csdnimg.cn/blog_migrate/994d5adb45d5674b66c3d7509aff0d3c.png)
,显然输出
![equation?tex=%5Bc%5D](https://i-blog.csdnimg.cn/blog_migrate/26d76c9fd99b0c6c36ea2b9c410c370a.png)
比
![equation?tex=%5Bc%2Co%2Cc%5D](https://i-blog.csdnimg.cn/blog_migrate/994d5adb45d5674b66c3d7509aff0d3c.png)
更合理些。
所以为了避免这一问题的发生,又引入了另一种算法,称为Beam Search。
里面有个参数
![equation?tex=B](https://i-blog.csdnimg.cn/blog_migrate/24500c30f1c598e72490259b989fae10.png)
,用来指定每次保留的前缀序列的个数。假如设置
![equation?tex=B%3D3](https://i-blog.csdnimg.cn/blog_migrate/24500c30f1c598e72490259b989fae10.png%3D3)
,则每次选取概率最大的3个前缀序列,比如
![equation?tex=t%3D1](https://i-blog.csdnimg.cn/blog_migrate/3b1922fd3ef8dd7c883fb35b699da495.png%3D1)
时选取概率最大的3个字符,
![equation?tex=t%3D2](https://i-blog.csdnimg.cn/blog_migrate/3b1922fd3ef8dd7c883fb35b699da495.png%3D2)
时也选取概率最大的3个字符,这样便有9种组合方式。当然对齐之后可能会对应相同的输出,所以要将结果相同的前缀序列进行合并(概率也要相加),然后挑出概率最大的3个作为下一次的输出,以此类推。以序列
![equation?tex=%5B%5Cepsilon%2Ca%2Cb%5D](https://i-blog.csdnimg.cn/blog_migrate/b2523f187bb5fad0db581baace5d0539.png)
为例,具体过程如下图所示。
图5 Beam Search示意图 [1]
这里要注意的是,当前缀序列的末尾字符与下一个字符相同时,合并可以产生两种有效输出。
比如上图中
![equation?tex=t%3D3](https://i-blog.csdnimg.cn/blog_migrate/3b1922fd3ef8dd7c883fb35b699da495.png%3D3)
时前缀序列为
![equation?tex=a](https://i-blog.csdnimg.cn/blog_migrate/3a1b450ba33b8215b0d69885896f7309.png)
, 而合并的字符同样为
![equation?tex=a](https://i-blog.csdnimg.cn/blog_migrate/3a1b450ba33b8215b0d69885896f7309.png)
,这样既可以输出
![equation?tex=a](https://i-blog.csdnimg.cn/blog_migrate/3a1b450ba33b8215b0d69885896f7309.png)
,也可以输出
![equation?tex=aa](https://i-blog.csdnimg.cn/blog_migrate/3a1b450ba33b8215b0d69885896f7309.pnga)
,二者都是可能的。因为在
![equation?tex=a%3D2](https://i-blog.csdnimg.cn/blog_migrate/3a1b450ba33b8215b0d69885896f7309.png%3D2)
时,其中一个结果占位符
![equation?tex=%5Cepsilon](https://i-blog.csdnimg.cn/blog_migrate/9d83d5a736cfe878f7d1f9052bd2ee7b.png)
在对齐时被移除了,但是在这里后面又遇到了相同的字符,按照前面定义的规则,此时合并的结果应该为
![equation?tex=aa](https://i-blog.csdnimg.cn/blog_migrate/3a1b450ba33b8215b0d69885896f7309.pnga)
。
![equation?tex=%5B%5Cepsilon%2Ca%2Cb%5D](https://i-blog.csdnimg.cn/blog_migrate/b2523f187bb5fad0db581baace5d0539.png)
的两种计算情况如下图所示。
图6 [epsilon,a,b] 的预测过程 [1]
所以,这两种结果应作为两种序列分别进行概率计算。当然,为了能够计算这两种情况对应的概率,需要分别记录以
![equation?tex=%5Cepsilon](https://i-blog.csdnimg.cn/blog_migrate/9d83d5a736cfe878f7d1f9052bd2ee7b.png)
结尾的前缀序列的概率,以及不以
![equation?tex=%5Cepsilon](https://i-blog.csdnimg.cn/blog_migrate/9d83d5a736cfe878f7d1f9052bd2ee7b.png)
结尾的前缀序列的概率。
6. 总结
以上便是CTC计算的所有过程。最后,总结CTC的几个特点。
- 条件独立。回顾上面的计算过程,可以发现在进行路径概率计算时,CTC直接将每个时间片对应的概率值进行相乘,也就是说CTC默认每个时间片都是相互独立的。但是,在文本识别中,文本显然是包含上下文信息的,所以模型中才引入了RNN层。当然,结果表明这并没有妨碍到CTC在文本识别领域的优异表现。不过,假如能够在CTC中将输入数据的上下文信息考虑进去,效果应该能得到进一步的提升。
- 单调对齐。CTC的规则决定了输入 与输出 的对齐是单调的。这也导致了CTC无法应用在机器翻译等不符合该约束的领域。
- 多对一映射。输入与最终的输出是一对多的关系,即多个输入分量可能只对应一个输出分量。所以输出 的长度一定不大于 。所以如果遇到 的长度大于 长度的情况,CTC便无法处理了。
最后,不要光收藏不点赞嘛,点个赞再走吧,写文章不易,多多鼓励~
参考资料
[1] Sequence Modeling With CTC
[2] CTC(Connectionist Temporal Classification)介绍
[3] 一文读懂CRNN+CTC文字识别