前言
最近在看这个论文,本来想要写一个翻译,但是鉴于本人英语的渣水平,再加上论文本身一些说明,虽然能够看懂,但是很难翻译过来,所以还是写个阅读笔记好了。在这篇文章,我会跟着论文的思路大致说明论文的内容和自己的理解。
CTC解决什么问题
在许多的训练任务中,我们需要输入一个序列,这个序列有可能有噪声,并不是我们需要的信息都连续存在。比如声音的识别之类的,对于一个语音,假设我们要翻译成文字,但是声音中的信息并不是连续的,说了一个字可能要停顿个1秒才会说下个字:
- 我~~~~要吃饭
- 我要~~~~吃饭
- 我要吃~~~~饭
像上面这三种情况,显然结果都是我要吃饭。想要让RNN做到这一点,我们要解决两个问题,一个是,如何将RNN的输出翻译成同一句话,另一个问题,如何训练这样一个网络。CTC就这两个问题提供了一个可行的方案,使得训练这样的网络成为可能。
2.时序分类器(Temporal Classification)
论文的第二节,实际上是定义了一些基础的概念和问题,这个小标题大概是这么翻译吧……
这里提到了一大堆符号,不过有一些都是为了后面少说几个字~
S :表示训练集
χ=(Rm)∗ :输入空间,表示m维的所有序列(这里的m就是输入序列长度)
L :字符集
Z=L∗ :输出空间,是字符集中的字符的组合序列。
(x,z) :表示训练集中的一个训练样例。
x=(x1,x2,...,xT) :一个训练样例中的输入的序列。
z=(z1,z2,...,zU) :一个训练样例中的label的序列(就是应该输出的结果)。
U≤T :这里要说明的是,输出序列长度要小于等于输入序列的长度(RNN对于序列的每个元素都有个输出,但是我们要做一些操作吧这些输出转化成真正的结果)。
说了这么多,终于可以说训练的目标了,我们的目标是训练一个时序分类器
2.1 label的错误率计算
在论文里,评价标签的错误率使用了最小编辑距离的方法,也就是说,想要把一个串变成目标串最少需要几步(可用的操作包括添加、修改、删除一个字符)。最小编辑距离用
论文里还是用符号和公式来表达了最终测试的评价结果:
S′ :表示测试集
LER :标签的错误率(label error rate)
扫描二维码关注公众号,回复: 3371160 查看本文章LER(h,S′)=1|S′|∑(x,z)∈S′ED(h(x),z)|z|a(1)
使用分类器h 在测试集S′ 上测试的标签错误率,计算方法是,对于每个样例,计算分类器的输出与label的最小编辑距离,然后除label的长度,把这些求和除测试集的长度~
3. Connectionist Temporal Classification
也不知道具体如何翻译,就这样吧。这一节是说,要把RNN的输出使用CTC来描述,最重要的一步是把网络的输出转化成标签上每个字符的独立的条件概率,然后网络就可以根据对应的最有可能的label来训练分类器。
3.1 从网络输出到标签
这里大概说了一下CTC网络的结构,首先是有一个softmax的输出层,输出层除了字符集
接下来,又是惯例的公式时间:
Nw:(Rm)T↦(Rn)T :这里对于一个长度为T 的输入序列x ,定义了一个m 个输入,n 个输出,权重向量为w 的RNN网络作为映射函数。这里m,n 指的是网络的输入输出,而T 指的一个输入序列的长度,有些绕,就是一个输入到输出的定义,大概理解就好了。
y=Nw(x) :这里y 就是网络的输出序列。
ytk :这个就是在t 时刻,网络输出的k 元素的值(概率)。
L′=L∪{blank} :也就是说L′ 是网络的所有输出元素的集合。
L′T :一个长度为T 的输出序列。
论文中说,把p(π|x)=∏t=1Tytπt,∀π∈L′Ta(2) L′T 中的元素称之为paths,并用π 表示。这个公式就是定义了在输入为x 的时候,输出为某个路径π 的概率,这个概率的算法,就是把对应的每个时刻的网络输出的对应元素的概率乘起来。
论文里说,(2)式假设了不同时刻网络的输出概率是条件独立的,并且这一点通过给定的网络的输出层与网络不存在反馈连接来保证:
This is ensured by requiring that no feedback connections exist from the output layer to itself or the network.
我看的时候还是有些疑惑的,因为RNN的输出在时间上是存在依赖性的,这里说不同时刻是独立的,总觉得哪里不太对。我的理解是,当RNN的输出确定之后,这时候对于CTC网络来说,每个时刻的输出是独立的,这样似乎可以解释得通。
然后又讲了一下从网络的输出映射为一个唯一的label的方法,其实就是把输出串的blank删掉,并且相邻的相同字符合并起来就好了。下面说一下相关的公式表示:
B:L′T↦L≤T :这个就是上面说的映射函数,方法就向上面说的那样。(如:B(a−ab−)=B(−aa−−abb)=aab )
这个公式定义了在输入为p(l|x)=∑π∈B−1(l)p(π|x)(3) x 的时候,输出一个给定label的值l 的概率,计算方法就是把所有可以用B 函数映射为l 的路径的概率相加。
3.2 构造分类器
根据上面说的,就可以很容易得出结论,最终我们的结果就是概率最大的那个labelling:
不过,这个东西是没有一个好的解法的,因为要枚举所有的可能的
第一种:
叫作best path decoding。其实就是把每个时刻的输出的argmax作为最终的输出,用这个输出序列来求出最后的label:
第二种:
叫作prefix search decoding。这里论文讲的节奏有点不太好,论文提到了用后面的前向后向算法,用同样的方法来做一个前缀计算。这里先简单说一下前向后向算法在这里的作用,具体后面再说,这个算法利用动态规划,可以算出输出为某个前缀的概率的值,prefix search decoding的想法就是,我每次给当前的串添加一个字符(最开始是空),算出用哪个字符得到的概率最大,一个一个添上去,就得到了最终的答案:
这里我还是有个疑问,就是输出串的长度是如何确定的,我猜应该是不断续上字符,然后所有的结果中取一个最大值吧。
但是呢,这么算还是有个bug,就是说,当最优解向下图中的实线部分那样分布,用这个方法是算不出来的。
然后呢,论文的作者就加了一个黑科技,先把输出序列分段,在每一段的内部使用这个方法得到答案,然后把这些结果拼起来作为最终答案。而分段的依据就是通过判断每个时刻输出的blank的概率值大于某个阈值。这个方法表现的还是挺好的,但是在一个被分好的一段序列的内部再出现上面的情况,那就没办法了。
4. 训练网络
这里说了现在描述了一个用CTC来表示RNN的输出的方法,然后根据目标函数就可以开始愉快的训练了balabala~
4.1 CTC的前向后向算法
这一节讲了计算
简单来说呢,这个方法是基于这样一个结论:t时刻的一个前缀s,可以通过t-1时刻算出的前缀的结果推导出来。
下面会列一下论文中的公式和推导:
这个公式看起来很复杂,其实也不难懂啦,其实就是定义了对于特定的
就像前面所说的:
大概的意思就是上面所说的,但是实际实现的时候,还是有一些不同的。论文里,把给定的
接下来,首先定义一下初始值:
然后是状态转移方程:
这个公式把
根据上面的公式,我们就能得到
然后,我们可以用相似的方法定义后缀的概率
接下来还有一个问题,就是这个计算有可能溢出,因为每一步都要进行乘法。所以,论文里在计算的时候加了一个缩放的操作:
在(6)(7)式中用
后向的结果也一样:
这节的最后,提了一个最大似然误差的计算,但是我没看懂公式是怎么算出来的,后面貌似也没有用到。这里就贴个图吧,后面看懂再说。
4.2 最大似然训练
这一节基本就是训练的各种公式,求导之类的。
首先,定义目标函数,涉及的符号前面都有提及:
然后是对于每个网络(字符)的输出,可以单独地进行求导:
接下来用上一节提到的前向后向算法来计算(13),对于一个特定的时刻
联合公式(2),得到:
可以看出来,上面这个式子由特定的时刻和位置决定的,我们想要计算
在前面也说过,ctc网络输出是独立概率的,所以对于在
显然:
然后,论文里说令
结语
这文章还是有一些细节没太看懂,希望了解的大佬可以讲解一下。不过整体的思路应该说的还是比较清晰的~