背景

Connectionist temporal classification简称CTC,翻译不太清楚,可以理解为基于神经网络的时序类分类。其中classification比较好理解,表示分类问题;temporal可以理解为时序类问题,比如语音识别的一帧数据,很难给出一个label,但是几十帧数据就容易判断出对应的发音label,这个词也给出CTC最核心的意义;connectionist可以理解为神经网络中的连接。 
语音识别声学模型的训练属于监督学习,需要知道每一帧对应的label才能进行有效的训练,在训练的数据准备阶段必须要对语音进行强制对齐。 
CTC的引入可以放宽了这种一一对应的限制要求,只需要一个输入序列和一个输出序列即可以训练。有两点好处:不需要对数据对齐和一一标注;CTC直接输出序列预测的概率,不需要外部的后处理。 
这里写图片描述
如上图,传统的Framewise训练需要进行语音和音素发音的对齐,比如“s”对应的一整段语音的标注都是s;而CTC引入了blank(该帧没有预测值),“s”对应的一整段语音中只有一个spike(尖峰)被认为是s,其他的认为是blank。对于一段语音,CTC最后的输出是spike的序列,不关心每一个音素对应的时间长度。

输出

语音识别中的DNN训练,每一帧都有相应的状态标记,比如有5帧输入x1,x2,x3,x4,x5,对应的标注分别是状态a1,a1,a1,a2,a2。 
CTC的不同之处在于输出状态引入了一个blank,输出和label满足如下的等价关系: 

F(aab)=F(aaabb)=aabF(a−ab−)=F(−aa−−abb)=aab

多个输出序列可以映射到一个输出。

整体思路

训练流程和传统的神经网络类似,构建loss function,然后根据BP算法进行训练,不同之处在于传统的神经网络的训练准则是针对每帧数据,即每帧数据的训练误差最小,而CTC的训练准则是基于序列(比如语音识别的一整句话)的,比如最大化p(z|x)p(z|x),序列化的概率求解比较复杂,因为一个输出序列可以对应很多的路径,所有引入前后向算法来简化计算。

前期准备

  1. 输入 
    xx,长度为T
  2. 输出集合 
    AA表示正常的输出 
    A=A{blank}A′=A⋃{blank}表示输出全集 
    ATA′T表示输入x对应的输出元素集合
  3. 输出序列 
    ππ表示输出路径 
    ll表示输出label序列 
    FF表示路径到label序列的映射关系
  4. 概率 
    ytkykt表示时间t输出k的概率 
    p(π|x)=t=1Tytπtp(π|x)=∏t=1Tyπtt表示基于输入x的输出ππ路径的概率 
    p(l|x)=πF1(l)p(π|x)p(l|x)=∑π∈F−1(l)p(π|x)表示输出label序列的概率是多条路径的概率和。

前后向算法

这里写图片描述
考虑到计算p(l|x)p(l|x)需要计算很多条路径的概率,随着输入长度呈指数化增加,可以引入类似于HMM的前后向算法来计算该概率值。 
为了引入blank节点,在label首尾以及中间插入blank节点,如果label序列原来的长度为U,那么现在变为U’=2U+1。

前向

前向变量为α(t,u)α(t,u),表示t时刻在节点u的前向概率值,其中u[1,2U+1]u∈[1,2U+1]
初始化值如下: 

α(1,1)=y1bα(1,1)=yb1

α(1,2)=y1l1α(1,2)=yl11

α(1,u)=0,u>2α(1,u)=0,∀u>2

递推关系: 
α(t,u)=ytlui=f(u)uα(t1,i)α(t,u)=ylu′t∑i=f(u)uα(t−1,i)

其中 
f(u)={u1u2if lu=blank or lu2=luotherwisef(u)={u−1if lu′=blank or lu−2′=lu′u−2otherwise

注:如果l表示{c,a,t},那么l’表示为{b,c,b,a,b,t,b},所以原来在l中的下标u为2,在l’中的下标u变为4。 
α(t,u)=0u<U2(Tt)1α(t,u)=0∀u<U′−2(T−t)−1
对应于上图中的右上角部分,因为时间的限制,有些节点不可能到达最后的终止节点。 
根据上图,很容易理解前向的递推关系。

后向

初始化值: 

β(T,U)=1β(T,U′)=1

β(T,U1)=1β(T,U′−1)=1

β(T,u)=0,u<U2β(T,u)=0,∀u<U′−2

α(1,u)=0,u>2α(1,u)=0,∀u>2

递推关系: 
β(t,u)=i=ug(u)β(t+1,i)yt+1liβ(t,u)=∑i=ug(u)β(t+1,i)yli′t+1

其中 
g(u)={u+1u+2if lu=blank or lu+2=luotherwiseg(u)={u+1if lu′=blank or lu+2′=lu′u+2otherwise

取log

概率计算在log计算,避免underflow,其中log加可以通过以下形式转化: 

ln(a+b)=lna+ln(1+elnblna)ln(a+b)=lna+ln(1+elnb−lna)

训练

loss function

CTC的loss function使用最大似然: 

L(S)=(x,z)SL(x,z)L(S)=∑(x,z)∈SL(x,z)

L(x,z)=lnp(z|x)L(x,z)=−lnp(z|x)

根据前后向变量,可以求得: 
p(z|x)=u=1|z|α(t,u)β(t,u)p(z|x)=∑u=1|z′|α(t,u)β(t,u)

|z||z′| 表示z对应的label长度的U’, α(t,u)β(t,u)α(t,u)β(t,u) 表示t时刻经过节点u的所有路径的概率和。 
L(x,z)=lnu=1|z|α(t,u)β(t,u)L(x,z)=−ln∑u=1|z′|α(t,u)β(t,u)

bp训练

ytkykt表示t时刻输出k的概率 
atkakt表示t时刻对应输出节点k在做softmax转换之前的值 

L(x,z)ytk=1p(z|x)p(z|x)ytk∂L(x,z)∂ykt=−1p(z|x)∂p(z|x)∂ykt

只需要考虑t时刻经过k节点的路径即可 
p(z|x)ytk=uB(z,k)α(t,u)β(t,u)ytk∂p(z|x)∂ykt=∑u∈B(z,k)∂α(t,u)β(t,u)∂ykt

其中 B(z,k)B(z,k) 表示节点为k的集合 
考虑到 
α(t,u)β(t,u)=πX(t,u)t=1Tytπtα(t,u)β(t,u)=∑π∈X(t,u)∏t=1Tyπtt

其中 X(t,u)X(t,u) 表示所有在t时刻经过节点u的路径。 
所以 
p(z|x)ytk=uB(z,k)α(t,u)β(t,u)ytk∂p(z|x)∂ykt=∑u∈B(z,k)α(t,u)β(t,u)ykt

可以到损失函数对 ytkykt 偏导数 
L(x,z)ytk=1p(z|x)ytkuB(z,k)α(t,u)β(t,u)∂L(x,z)∂ykt=−1p(z|x)ykt∑u∈B(z,k)α(t,u)β(t,u)

同时可以得到损失函数对于 atkakt 偏导数 
L(x,z)atk=ytk1p(z|x)uB(z,k)α(t,u)β(t,u)∂L(x,z)∂akt=ykt−1p(z|x)∑u∈B(z,k)α(t,u)β(t,u)

推导参考: 
这里写图片描述
这里写图片描述

后续可以使用BPTT算法得到损失函数对神经网络参数的偏导。

参考文献:https://blog.csdn.net/xmdxcsj/article/details/51763886

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐