(原創文章,轉載請注明出處哦~)
簡單介紹CTC算法
CTC是序列標注問題中的一種損失函數。
傳統序列標注算法需要每一時刻輸入與輸出符號完全對齊。而CTC擴展了標簽集合,添加空元素。
在使用擴展標簽集合對序列進行標注后,所有可以通過映射函數轉換為真實序列的 預測序列,都是正確的預測結果。也就是在無需數據對齊處理,即可得到預測序列。
其目標函數就是 最大化 所有正確的預測序列的概率和。
在查找所有正確預測序列時,采用了前向后向算法。
前向過程計算從1-t時刻,預測出正確的前綴的概率;后向過程計算從t - T時刻,預測出正確的后綴的概率。
那么: 前綴概率 * 后綴概率 / t 時刻預測s的概率 = t 時刻時所有正確的預測序列的概率。
動態規划降低時間復雜度:只有在前一時刻到達預測出某些特定符號,在當前時刻,才可以做出正確預測。
那么,到 t 時刻為止,預測出正確的 標簽序列的前綴 的概率 = (到t - 1為止預測正確的所有子序列概率和) * 預測出當前標簽的概率。
定義與背景
CTC全稱:Connectionist temporal classification, 主要用於處理序列標注問題中的輸入與輸出標簽的對齊問題。
--------------------------------
什么是數據的對齊問題? (參考鏈接:https://www.cnblogs.com/qcloud1001/p/9041218.html)
傳統的語音識別的聲學模型訓練,對於每一幀的數據,需要知道對應的label才能進行有效的訓練,在訓練數據之前需要做語音對齊的預處理。
上圖是“你好”這句話的聲音的波形示意圖, 每個紅色的框代表一幀數據,傳統的方法需要知道每一幀的數據是對應哪個發音音素。比如第1,2,3,4幀對應n的發音,第5,6,7幀對應i的音素,第8,9幀對應h的音素,第10,11幀對應a的音素,第12幀對應o的音素。(這里暫且將每個字母作為一個發音音素)
------------------------------------
傳統模型的不足:
1. 訓練數據之前需要做語音對齊的預處理,工作比較耗時,並且在缺失對齊標簽時,無法做出准確預測;
2. 輸出的預測是局部分類,只利用了當前幀的信息,並未利用序列的全局信息(比如相鄰兩個標簽的連續性等,則需要通過其他外加處理。)
------------------------------------------
CTC與傳統模型的對比:
1. 與傳統的聲學模型訓練相比,采用CTC作為損失函數的聲學模型訓練,是一種完全端到端的聲學模型訓練,不需要預先對數據做對齊,只需要一個輸入序列和一個輸出序列即可以訓練。這樣就不需要對數據對齊和一一標注,輸入輸出之間的alignment不再那么重要。
2. CTC直接輸出序列預測的概率,不需要外部的后處理。
--------------------------------------------
CTC的算法原理
<1> 符號定義與目標函數
1. $A$: 序列標注任務中的標簽所在字母表集合為 $A$
2. $A'$: 擴展的字母表集合。CTC的softmax 輸出層中,比 $A$ 多包含一個標簽。我們記為$'blank'$. 即 $A' = A \bigcup \{blank\}$. 那么在輸出預測時,前$|A|$個單元輸出的是對應字母表$A$中各元素的預測概率,最后一個單元輸出的是預測為$'blank'$的概率。
3. $y_k^t$: 網絡在 $t$ 時刻輸出元素 $k$ 的概率,即在給定長度為 $T$ 的輸入序列 $x$ 后,在 $t$ 時刻,預測為 $A'$ 中的元素 $k$ 的概率。
4. $A^{'T}$: 在 $A'$ 集合上的所有長度為 $T$ 的序列集合。
5. 假設在每一個時刻的輸出與其他時刻的輸出是條件獨立的(或者說,條件獨立於給定的 $x$ ),那么可以得到在給定輸入 $x$ 后,得到 $A^{'T}$ 集合中任何一條路徑 $\pi$ 的概率分布: $ \pi \in A^{'T}$ 的分布:
$$p(\pi | x) = \prod_{t = 1} ^ T y_{\pi_t}^t \tag1$$ 。
我們記在$A^{'T}$集合中的序列 $\pi$ 為 $paths$.
6. $l$: 我們記在 $A$ 集合中產生的標簽序列為 $l$。
7. 由於在$A^{'T}$ 集合中可能有多條 $paths$,最終所映射的都是同一個序列, 我們需要定義一個多對一的函數,來實現從 $paths$集合到預測序列的映射。$F: A^{'T} \rightarrow A^{\le T}$
其中,我們設定映射后的序列長度不大於映射前的序列長度。
這是要做什么呢?舉個例子:
$F(a-ab-) = F(-aa--abb) = aab$
函數映射關系是,將'-'與'-'之間的重復的元素,只保留一個,並且去掉'-'分隔。這樣,無論我們的神經網絡預測出的序列為‘a-ab-’ 或是 ‘-aa--abb’,它所對應的最終的預測結果都是 'aab',而我們的目標函數也是將 'aab' 與真實標簽序列作比較。
這樣就不難看出,CTC算法並不要求預測標簽與輸入的一一對齊關系,而是關注於整個序列的最終預測結果,也就是經過這個函數映射后的結果。
那么我們預測出真實標簽序列的概率可以表示為:
$$ p(l|x) = \sum_{\pi \in F^{-1}(l)} p(\pi|x) \tag2$$
即所有的可以映射為真實標簽序列的 預測序列的概率和。
<2> blank標簽的角色
1. 可以出現重復字符。
設想一下,如果沒有'-',對於單詞中有重復字符的,比如'apple',其函數映射的結果為'aple',這是不能滿足實際情況需要的
2. 如果沒有'-',那么神經網絡需要一直不停的預測出來一個label,直到下一個不同的label出現。而真實情況中,經常出現一段間隔內(比如語音的停頓處),並沒有標簽。所以有blank可以滿足這樣的情況需要。
<3> 前向后向算法的前向過程
由公式(2),我們的目標函數是對所有可以映射為真實標簽序列的paths的預測出的概率求和。那么首先,我們要先知道都有哪些paths可以映射為真實標簽序列。
對於長度為 $T$ 的輸入序列和長度為 $U$ 的標簽序列,有2^[(T - U^2 + U(T-3))] * 3^ [(U - 1)(T- U) - 2]種不同路徑
有指數級別的路徑可能性,不能滿足實際需要。為了降低時間復雜度,CTC算法處理時采用了動態規划方法。算法的主要思想是,在篩選可能的paths時,只選取前綴與$l$對應前綴是相同的那些paths. 這樣說很難理解,舉個例子。
1. 首先,我們構造一個table,希望通過這個table,直觀的看出所有可以映射到真實標簽序列'apple'的可能路徑。
table的橫坐標為輸入的時間序列,縱坐標為將真實標簽序列兩兩字母以'-'分隔,並且在首尾各加一個'-'。用$U'$標記標簽序列經過'-'擴展后的序列。
那么從首'-'或'a'開始,到尾'e'或'-'結束;箭頭只能向右,或向下,所有依次經過a, p, p, l, e的那些路徑,即為我們要找的,可以映射為真實標簽序列的路徑。
比如下圖1,黑線部分表示的預測的序列為 '- - a p - p l e' (t1時刻預測'-', t2時刻預測為'-', t3時刻預測為'a' ...)。 注意,紅色箭頭是錯誤的,因為我們不可能先預測出第3個標簽,再預測出第2個標簽,標簽需要按順序依次預測出。所以,箭頭只能向右或向下!$F( '- - a p - p l e') = 'apple'$
圖1.路徑舉例
那么初始t1時刻,我們只能處於'-'或‘a’的位置,
圖2. 初始時刻狀態
而最終,我們需要依次經過apple所有字母。
圖3.搜索的最終結果狀態。
那么,求總路徑的問題,也就是找從初始位置,到結束位置的所有的可能路徑的問題。
動態規划體現在哪里呢?敲黑板,下面內容是重點~
(1) 對於一條可能路徑,其字路徑的概率可以表示為,對應時刻神經網絡預測標簽的概率乘積。比如,如下圖所示 $p('- a p - ') = y_-^1 * y_a ^ 2 * y_p^3 * y_-^4$
圖4. subpath的概率計算
(2) $\alpha_t(s)$: 稱為前向變量(forward variable)。表示 前綴末端 在 $t$ 時刻到達序列的第 $s$ 個位置的所有可能子路徑的概率和。前綴的意義是,在前$(1-t)$時間內,經過映射后,可以得到真實標簽序列的前s / 2個符號。我們把符合這個要求的所有可能路徑前綴的概率加和,即為 $\alpha_t(s)$。
那么以此類推,在T時刻,可以到達終止節點'-',或真實標簽最后一個符號的,概率和,即為所有可以映射得到真實標簽序列的預測序列的概率和,也就是我們需要最大化的目標。
如下圖5所示:在 $t3$ 時刻,共有四條路徑前綴終止於擴展的標簽序列的的第4個節點p.那么$\alpha_3(4) = p('-ap') + p('aap') + p('a-p') + p('app')$ 這四條子路徑的前綴經過映射后,都可以得到真實標簽序列的前綴:'ap'.
圖5.前綴相同的子路徑的概率和
(3) 之后,我們需要做的就是,對於每一個cell,都計算其對應的 $\alpha_t(s)$。我們可以遞歸地進行計算。
即計算可以到達(t, s) 這個cell 的所有子路徑概率和 與 在t時刻預測出符號s的概率做乘積,即為在t時刻,到達符號s的所有子路徑的概率。
在計算中,有三種情況:
Case1. 第 $s$ 個符號為blank時。
比如 $s = 3, t = 3$,序列的第三個符號為 '-'。見圖中紅色的cell. $\alpha_3(3)$ 只取決於 $\alpha_2(3)$ (藍色cell)和 $\alpha_2(2)$ (綠色cell). 那么易得,$\alpha_3(3) = (\alpha_2(3) + \alpha_2(2)) * y_-^3$.
一般的,有$$\alpha_t(s) = (\alpha_{t-1}(s) + \alpha_{t-1}(s-1)) * y_{seq(s)}^t \tag3$$
圖6. Case1.前向算法中s=‘-’時的$\alpha_s^t$ 計算
Case2. 第s個符號與第(s - 2)個符號相同時,即$seq(s) == seq(s - 2) $。
此時(t,s)cell,只取決於 (t-1, s) (藍色cell) 和 (t - 1, s - 1)(綠色cell)。一般的:
$$\alpha_t(s) = (\alpha_{t-1}(s) + \alpha_{t-1}(s-1)) * y_{seq(s)}^t \tag4$$
圖7. Case2.前向算法中seq(s) == seq(s - 2)時的$\alpha_s^t$ 計算
Case3. 其他情況。有:
$$\alpha_t(s) = (\alpha_{t-1}(s) + \alpha_{t-1}(s-1) + \alpha_{t-1}(s-2) ) * y_{seq(s)}^t \tag5$$
圖8. Case3.前向算法中其他情況下 $\alpha_s^t$ 的計算
(4) 通過以上步驟,我們最終可以得到$\alpha_T(U - 1)$ 和 $\alpha_T(U)$。那么預測出真實標簽序列的概率為 $$p(l|x) =\alpha_T(U' - 1) + \alpha_T(U') \tag6 $$. 前向過程完成!
圖9. 前向過程完成得到預測出真實序列的概率
<4> 前向后向算法的后向過程
后向算法與前向類似,只是方向不同,后向是找 從序列末端到首端的各個子路徑的概率。
定義$\beta_t(s)$為 后綴起始於序列末端, $t$ 時刻到達第 $s$ 個符號的所有可能子路徑的概率和。
比如,$t = 6, s = 8, \beta_6(8)$表示所有以下圖中紅色節點開始的,最終可以到達序列末端的子路徑的概率。$\beta_6^(8) = p('lle') + p('l-e') + p('lee') + p('le')$
圖10. 反向過程舉例
那么,將前向過程中所有箭頭反向,使用同樣的計算方式,即可計算出反向變量。
圖10. 反向過程
<5> 前向后向算法
<3>部分$\alpha_s(t)$前向變量記錄1-t時間內預測出正確前綴的概率(或者可以說,子路徑的概率和);<4>部分$\beta_s(t)$后向變量記錄t - T時間內預測出正確后綴的概率;
那么
$$\alpha_t(s) * \beta_t(s) / y_t^s\tag7$$
即為 在t時刻,所有正確預測的,並且經過第s符號的,路徑的概率和。(除以 y_t^s 因為在 $\alpha$ 和 $\beta$ 中乘了兩次)。
舉個例子:
$\alpha_{t3}(2) = y_-^{t1} * y_-^{t2} * y_a^{t3} + y_-^{t1} * y_-^{t2} * y_-^{t3}$
$\beta_{t3}(2) = y_a^{t3} * y_p^{t4} * y_-^{t5} * y_p^{t6} * y_l^{t7} * y_e^{t8}$
$\alpha_{t3}(2) * \beta_{t3}(2) = ( y_-^{t1} * y_-^{t2} * y_a^{t3} ) * ( y_a^{t3} * y_p^{t4} * y_-^{t5} * y_p^{t6} * y_l^{t7} * y_e^.{t8}) + (y_-^{t1} * y_-^{t2} * y_-^{t3}) * (y_a^{t3} * y_p^{t4} * y_-^{t5} * y_p^{t6} * y_l^{t7} * y_e^{t8}) = (p('--ap-ple') + p('-aap-ple) + p('aaap-ple')) * y_a^3$
那么 $\alpha_{t3}(2) * \beta_{t3}(2) / y_a^3$ = 在t3時刻,經過符號a的所有正確預測序列的概率和。
圖11. 前向后向算法,在t時刻經過第s符號的所有正確預測的路徑的概率和
那么將t3時刻,正確預測序列可能會預測出,a, -, p, -,用上面方法,將經過這四個符號的路徑概率加和,即可得到在t3時刻,可以做出正確預測的概率。
圖11. 前向后向算法,在t時刻可以做出正確預測的概率
最后,應用於1 - T的所有時刻,可以得到在任意時刻內預測出正確標簽序列的概率。
$$p('apple') = \sum_{s = 1}^{|seq|} \frac{\alpha_s(t) * \beta_s(t)}{y_{seq(s)} ^ t}\tag8$$
<6> 反向傳播
我們的目標是最大化$p('apple')$,也就是$ min {-ln(p('apple'))}$,這是我們的目標函數
在反向傳播時,我們需要對神經網絡的每一個預測輸出求偏導。
$$\frac{\partial{(-ln(p('apple')))}}{\partial{y_k^t}} = -\frac{1}{p('apple')} * \frac{\partial{p('apple')}}{\partial{y_k^t}}\tag9$$
我們重點看$$\frac{\partial{p('apple')}}{\partial{y_k^t}} \tag{10}$$的求解。
$p('apple')= \frac{\alpha_{s1}(t) * \beta_{s1}(t)}{y_{s1}^t} + ... + \frac{\alpha_{k}(t) * \beta_{s1}(t)}{y_{k}^t} +... + \frac{\alpha_{sT}(t) * \beta_{sT}(t)}{y_{sT}^t}$
若t時刻過k,則t時刻時不可能經過其他字符的。也就是,在求偏導時,只有紅色部分是包含$y_k^t$的,其他項可以看做常數項。
最終,
$$\frac{\partial{p('apple')}}{\partial{y_k^t}} = -\frac{1}{{y_k^t}^2} * \sum_{s:seq(s) = k}\alpha_t(s) * \beta_t(s)\tag{11}$$
舉個例子:
這樣就完成了!
------------------------------------------
思考:
$\alpha_S(T)$即可可表示所有正確預測序列的概率和,也就是可以表示目標函數,為什么要引入$\beta$呢?
原因:為了反向傳播時候求偏導方便呀!否則$\alpha_S(T)$是關於$y_k^t$的一個復雜的函數,很難直接求導的,引入$\beta$后,我們可以關注於t時刻內的偏導計算,會簡便許多。
------------------------------------------
<7> 要點總結
1. 動態規划
2. 矩陣 $\alpha$ (前向變量)用於計算loss.
3. 矩陣$\beta$ (后向變量)用來方便計算gradients.
參考鏈接:
1. Supervised Sequence Labelling with Recurrent Neural Networks:https://www.cs.toronto.edu/~graves/preprint.pdf
2. 語音識別中的CTC算法的基本原理解釋:https://www.cnblogs.com/qcloud1001/p/9041218.html
=======================================
[支付寶]
您願意請我吃一根雪糕嗎? O(∩_∩)O