教程:Connectionist Temporal Classification詳解補充
感想
CTC的想法很難懂,尤其是對前向後向演算法不熟的人,然後再網上發現了一篇很好的教程,我把它翻譯了下來,裡面有大量的例子,專注於原理的講解,非常透徹,不像CTC的原論文,那樣全面冗長,希望也能幫助大家理解。我在五六月份找過其它中文資料,發現原理詳解的很少,我特地彌補一下中文這一塊的空缺。
介紹
Connectionist Temporal Classification (CTC)是一項技術,它是為RNN專門設計的頂層(top layer)。使得針對輸入序列的每一幀,網路能夠輸出一個標籤或者空白(blank)。CTC使得用一個RNN構建語音識別系統成為可能,這個和混合方法HMM+DNN不一樣。
語音識別問題
輸入是一個聲音片段x,然後分割成很多個幀:
X={x1,…,xT}
每一幀在時刻t,用xt表示,xt由G個聲譜的權重組成:
Xt=[xt1,…,xt,G]T
我們可以設計一個RNN對每一幀xt的輸出yt::
Y={y1,…,yT}
Yt是一個字母表的概率分佈:
Yt=[yt,1…yt,K]T
其中yt,k和lt代表在時刻t發音字母。
那麼,問題來了,我們怎樣把y解釋成一串字母。
首先,很直接,我們要找一個路徑
Π={π1…πT}
其中πt屬於[1,K]
設想一個人說了一個“a”,在說之前,之後有一個安靜的部分(silence),路徑π可以是:
aaaaaaaa
aaaaa___
____aaaa
__aaaaa_
但這個沒考慮到安靜期和發音的變化,下面這個例子所有對應 “a”的路徑:
aa______
aaa_____
_aaa____
___aaaa_
_aaaaaaa
上面的例子告訴我們,網路的輸出既不是y也不是π。而是一些叫做標籤的序列,用l表示:
L={l1,…,lS}
其中S<=T
對於上面的例子,所有那些路徑都是對應樣本標籤:l={a}.
所有下面的樣例對應l={h,e}:
hhheeee
__heeee
_hee___
hh__eee
_hh_eee
h__ee__
__h_ee_
注意空白(blanks)可以出現在he之前,之間,之後。
更復雜一點的例子是l={b,e,e}:
bbbeee_ee
_bb_ee__e
__bbbe_e_
但下面的例子對應l={b,e}
_b_eeeeee
bbb__eeee
_bb_eee__
這兩個例子顯示了空白在分開連續重複字母的重要性。
綜上,語音識別的輸出並不是字母表的分佈y或者路徑π,而是標籤l.CTC 是從y結合π來推出l的方法。
動態時間規整(Dynamic Time Warping)
Y的長度可能和l的長度不一樣,因此從y推理(inference)l實際上是動態時間規整問題。動態時間規整演算法使得我們可以用(x,l)對進行訓練,而不是(x,y)對,這是非常有價值的,因為我們在訓練前不需要預先分割y,並且把x和y對齊。
時間規整的意思是我們想要把yt對映到某個ls.由上述的例子我們其實是想要把yt 對映到要麼是ls,要麼是一個空白。因為要是我們這樣做了,我們就有機會識別後繼字母,比如coffee中“ff”,bee中的”ee“。
假設我們有一個“bee”的語音片段,最可能的路徑π是:
___bbeeee____
我們想要把它規整到l={b,e,e},好像我們可以建立下面的對映:
但是事實是我們沒有太多資訊去組織演算法把所有的e對映到l中的第一個e:
另一個問題是我們應該把這些空白(blanks)對映到π中的哪一個。
一個解決辦法就是我們把π對映到l’,我們在l之前,中間,後面都插入blank就構成了l’,對於上面的例子,我們就可以得到:
L’={,b,,e,,e,}
就有了下面的規整:
但有時π中的第一個字元不是空白,所以我們可以把第一幀對應到‘b’,而不是對應l’中的空白:
一個相似的情況是π中沒有對齊的空白,因此沒有幀可以對齊l’中的空白。所以這兩種情況都需要我們設計一個演算法計算π和l’的對映。
前向後向演算法
這裡我們推導用於計算,很顯然他和等價,因為在給定l的情況下構造是唯一的
1.前向演算法
上面的規整的例子說明可以對映到要麼,即的空白,要麼,根據的構造法則,即l的最後一個元素。
可以寫成下面的形式:
在上面例子中,π1可以對映到要麼是,即的第一個空白;要麼是,l 的第一個元素。因此:
假設我們有l’={_,h,_,e,_}和一串序列y,因此有以下兩種情況:
緊接著我們用一個更通用的方法去對映.大體上,我們可以這樣對映一個到:
1. ,用表示
2. 緊挨著的元素,用表示,或者
3. ,如果="_"
第三個情況是我們想跳過空白,即="_".
一個例子:我們想要把π={h,h,h,h,e,e,e}對映到l’={_,h,_,e,_}
但是,當的時候,上述第3種情況是不合理的。在這種情況下,我們不應該跳過空白。例如,當識別單詞bee的時候,l’={_,b ,_,e ,_,e ,_},在這種情況下,當我們跳過兩個e之間的空格,我們就會把兩個e錯誤地當成了一個e.在下面這個樣例中,即使我們把這幀(y5)聽起來更像一個e而不是空白,我們還是想要把它對映成空白,即="_",因此我們識別出了bee這個單詞。
綜上,我們可得:
2.後向演算法
和前向變數α(t ,s)相似,我們定義後向變數β(t ,s)
由於時間規整把πT對映到要麼是,,即用1的概率對齊空白,要麼,即l集合中最後一個元素,概率為1,即:
和前向演算法的泛華規則相似,我們有:
搜尋空間
計算α(t ,s)的時候,我們需要α(t-1 ,s),α(t-1 ,s-1),α(t-1 ,s-2)。為了計算β(t,s),我們需要β(t+1,s),β(t+1,s+1),β(t+1,s+2)。其中的一些值為0,如圖:
每個圈代表搜尋空間的一個可能狀態,這些狀態以t和s的各自對齊,箭頭連線一個狀態和另一個狀態,當我們計算α(t ,s)的時候,我們不需要進入不可能的區域,即右上角的的連線狀態。
當我們計算β(t ,s)的時候,我們不可能進入左下角的狀態:
為了約束動態規劃演算法(dynamic programming algorithm),我們需要下列條件:
參考文獻
[1]. Connectionist Temporal Classification:A Tutorial with Gritty Details.
https://cxwangyi.wordpress.com/2015/10/07/connectionist-temporal-classification-the-gritty-details/