整体思路
训练流程和传统的神经网络类似,构建loss function,然后根据BP算法进行训练,不同之处在于传统的神经网络的训练准则是针对每帧数据,即每帧数据的训练误差最小,而CTC的训练准则是基于序列(比如语音识别的一整句话)的,比如最大化p ( z ∣ x ) p(z|x)p(z∣x),序列化的概率求解比较复杂,因为一个输出序列可以对应很多的路径,所有引入前后向算法来简化计算。
前期准备
- 输入
x xx,长度为T - 输出集合
A AA表示正常的输出
A ′ = A ⋃ { b l a n k } A'=A \bigcup \{blank\}A′=A⋃{blank}表示输出全集
A ′ T A'^TA′T表示输入x对应的输出元素集合 - 输出序列
π \piπ表示输出路径
l ll表示输出label序列
F \mathcal{F}F表示路径到label序列的映射关系 - 概率
y k t y_k^tykt表示时间t输出k的概率
p ( π ∣ x ) = ∏ t = 1 T y π t t p(\pi|x)=\displaystyle\prod_{t=1}^{T}y_{\pi_t}^{t}p(π∣x)=t=1∏Tyπtt表示基于输入x的输出π \piπ路径的概率
p ( l ∣ x ) = ∑ π ∈ F − 1 ( l ) p ( π ∣ x ) p(l|x)=\displaystyle\sum_{\pi \in \mathcal{F}^{-1}(l)}p(\pi|x)p(l∣x)=π∈F−1(l)∑p(π∣x)表示输出label序列的概率是多条路径的概率和。
前后向算法

考虑到计算p ( l ∣ x ) p(l|x)p(l∣x)需要计算很多条路径的概率,随着输入长度呈指数化增加,可以引入类似于HMM的前后向算法来计算该概率值。
为了引入blank节点,在label首尾以及中间插入blank节点,如果label序列原来的长度为U,那么现在变为U’=2U+1。
前向
前向变量为α ( t , u ) \alpha(t,u)α(t,u),表示t时刻在节点u的前向概率值,其中u ∈ [ 1 , 2 U + 1 ] u\in [1,2U+1]u∈[1,2U+1].
初始化值如下:
α ( 1 , 1 ) = y b 1 \alpha(1,1)=y_b^1α(1,1)=yb1
α ( 1 , 2 ) = y l 1 1 \alpha(1,2)=y_{l_1}^1α(1,2)=yl11
α ( 1 , u ) = 0 , ∀ u > 2 \alpha(1,u)=0, \forall u>2α(1,u)=0,∀u>2
递推关系:
α ( t , u ) = y l u ′ t ∑ i = f ( u ) u α ( t − 1 , i ) \alpha(t,u)=y_{l'_{u}}^t\displaystyle\sum_{i=f(u)}^{u}\alpha(t-1,i)α(t,u)=ylu′ti=f(u)∑uα(t−1,i)
其中
f ( u ) = { u − 1 if l u ′ = b l a n k or l u − 2 ′ = l u ′ u − 2 otherwise f(u) = \begin{cases} u-1 & \quad \text{if } l'_u=blank \text{ or }l'_{u-2}=l'_u\\ u-2 & \quad \text{otherwise}\\ \end{cases}f(u)={u−1u−2if lu′=blank or lu−2′=lu′otherwise
注:如果l表示{c,a,t},那么l’表示为{b,c,b,a,b,t,b},所以原来在l中的下标u为2,在l’中的下标u变为4。
α ( t , u ) = 0 ∀ u < U ′ − 2 ( T − t ) − 1 \alpha(t,u)=0 \forall u< U'-2(T-t)-1α(t,u)=0∀u<U′−2(T−t)−1对应于上图中的右上角部分,因为时间的限制,有些节点不可能到达最后的终止节点。
根据上图,很容易理解前向的递推关系。
后向
初始化值:
β ( T , U ′ ) = 1 \beta(T,U')=1β(T,U′)=1
β ( T , U ′ − 1 ) = 1 \beta(T,U'-1)=1β(T,U′−1)=1
β ( T , u ) = 0 , ∀ u < U ′ − 2 \beta(T,u)=0, \forall u<U'-2β(T,u)=0,∀u<U′−2
α ( 1 , u ) = 0 , ∀ u > 2 \alpha(1,u)=0, \forall u>2α(1,u)=0,∀u>2
递推关系:
β ( t , u ) = ∑ i = u g ( u ) β ( t + 1 , i ) y l i ′ t + 1 \beta(t,u)=\displaystyle\sum_{i=u}^{g(u)}\beta(t+1,i)y_{l'_{i}}^{t+1}β(t,u)=i=u∑g(u)β(t+1,i)yli′t+1
其中
g ( u ) = { u + 1 if l u ′ = b l a n k or l u + 2 ′ = l u ′ u + 2 otherwise g(u) = \begin{cases} u+1 & \quad \text{if } l'_u=blank \text{ or }l'_{u+2}=l'_u\\ u+2 & \quad \text{otherwise}\\ \end{cases}g(u)={u+1u+2if lu′=blank or lu+2′=lu′otherwise
取log
概率计算在log计算,避免underflow,其中log加可以通过以下形式转化:
l n ( a + b ) = l n a + l n ( 1 + e l n b − l n a ) ln(a+b)=lna+ln(1+e^{lnb-lna})ln(a+b)=lna+ln(1+elnb−lna)
##训练
loss function
CTC的loss function使用最大似然:
L ( S ) = ∑ ( x , z ) ∈ S L ( x , z ) L(S)=\displaystyle\sum_{(x,z)\in S}L(x,z)L(S)=(x,z)∈S∑L(x,z)
L ( x , z ) = − l n p ( z ∣ x ) 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)=\displaystyle\sum_{u=1}^{|z'|}\alpha(t,u)\beta(t,u)p(z∣x)=u=1∑∣z′∣α(t,u)β(t,u)
∣ z ′ ∣ |z'|∣z′∣表示z对应的label长度的U’,α ( t , u ) β ( t , u ) \alpha(t,u)\beta(t,u)α(t,u)β(t,u)表示t时刻经过节点u的所有路径的概率和。
L ( x , z ) = − l n ∑ u = 1 ∣ z ′ ∣ α ( t , u ) β ( t , u ) L(x,z)=-ln\displaystyle\sum_{u=1}^{|z'|}\alpha(t,u)\beta(t,u)L(x,z)=−lnu=1∑∣z′∣α(t,u)β(t,u)
bp训练
y k t y_k^tykt表示t时刻输出k的概率
a k t a_k^takt表示t时刻对应输出节点k在做softmax转换之前的值
∂ L ( x , z ) ∂ y k t = − 1 p ( z ∣ x ) ∂ p ( z ∣ x ) ∂ y k t \frac{\partial L(x,z)}{\partial y_k^t}=-\frac{1}{p(z|x)}\frac{\partial p(z|x)}{\partial y_k^t}∂ykt∂L(x,z)=−p(z∣x)1∂ykt∂p(z∣x)
只需要考虑t时刻经过k节点的路径即可
∂ p ( z ∣ x ) ∂ y k t = ∑ u ∈ B ( z , k ) ∂ α ( t , u ) β ( t , u ) ∂ y k t \frac{\partial p(z|x)}{\partial y_k^t}=\displaystyle\sum_{u\in B(z,k)}\frac{\partial \alpha(t,u)\beta(t,u)}{\partial y_k^t}∂ykt∂p(z∣x)=u∈B(z,k)∑∂ykt∂α(t,u)β(t,u)
其中B ( z , k ) B(z,k)B(z,k)表示节点为k的集合
考虑到
α ( t , u ) β ( t , u ) = ∑ π ∈ X ( t , u ) ∏ t = 1 T y π t t \alpha(t,u)\beta(t,u)=\displaystyle\sum_{\pi \in X(t,u)}\displaystyle\prod_{t=1}^{T}y_{\pi_t}^{t}α(t,u)β(t,u)=π∈X(t,u)∑t=1∏Tyπtt
其中X ( t , u ) X(t,u)X(t,u)表示所有在t时刻经过节点u的路径。
所以
∂ p ( z ∣ x ) ∂ y k t = ∑ u ∈ B ( z , k ) α ( t , u ) β ( t , u ) y k t \frac{\partial p(z|x)}{\partial y_k^t}=\displaystyle\sum_{u\in B(z,k)}\frac{\alpha(t,u)\beta(t,u)}{y_k^t}∂ykt∂p(z∣x)=u∈B(z,k)∑yktα(t,u)β(t,u)
可以到损失函数对y k t y_k^tykt偏导数
∂ L ( x , z ) ∂ y k t = − 1 p ( z ∣ x ) y k t ∑ u ∈ B ( z , k ) α ( t , u ) β ( t , u ) \frac{\partial L(x,z)}{\partial y_k^t}=-\frac{1}{p(z|x)y_k^t}\displaystyle\sum_{u\in B(z,k)}{\alpha(t,u)\beta(t,u)}∂ykt∂L(x,z)=−p(z∣x)ykt1u∈B(z,k)∑α(t,u)β(t,u)
同时可以得到损失函数对于a k t a_k^takt偏导数
∂ L ( x , z ) ∂ a k t = y k t − 1 p ( z ∣ x ) ∑ u ∈ B ( z , k ) α ( t , u ) β ( t , u ) \frac{\partial L(x,z)}{\partial a_k^t}=y_k^t-\frac{1}{p(z|x)}\displaystyle\sum_{u\in B(z,k)}{\alpha(t,u)\beta(t,u)}∂akt∂L(x,z)=ykt−p(z∣x)1u∈B(z,k)∑α(t,u)β(t,u)
推导参考:

后续可以使用BPTT算法得到损失函数对神经网络参数的偏导。
参考
《Supervised Sequence Labelling with Recurrent Neural Networks》 chapter7
后面的技术分享转移到微信公众号上面更新了,【欢迎扫码关注交流】
