DeepSpeech2中主要講的幾點
- 網絡結構
convolution layers --> rnn layers --> one fully connected layer
網絡結構的輸入是音頻信號的頻譜特征, 輸出的是字母表中的一個個字母.(不同語言的字母表不一樣). 訓練是采用CTC損失函數.
在推理過程中,輸入音頻信號x,輸出y是通過最大化下面的公式得到的:
\(Q(y) = log(P_{rnn}(y|x)) + \alpha log(P_{LM}(y)) + \beta wc(y)\)
其中wc表示輸出序列的長度, 該公式就是鼓勵翻譯識別得到的句子包含更多的單詞.為什么鼓勵更多的單詞呢?
我在語音識別訓練中,遇到剛開始訓練中,模型識別出來的字母都連在了一起,成了一大長串, 根本無法辨別.這種情況的識別得到的句子中單詞是很少的.是這樣解釋嗎?
- BatchNorm
實踐發現, 在rnn layers中加入歸一化, 能夠加速模型的收斂和提高模型的泛化能力.歸一化的方式主要有兩種方式:(公式中W和U,與一些關於rnn表述的恰好相反)
方式1是在非線性函數前對其進行歸一化\(h_t^{l} = f({B}(W^lh_t^{l-1}+U^lh_{t-1}^{l}))\)
方式2是僅僅對垂直連接方向進行歸一化\(h_t^{l} = f({B}(W^lh_t^{l-1})+U^lh_{t-1}^{l})\)
實踐表明,方式1效果不佳, 而方式2卻能帶來很大的性能提升
tensorflow中rnn是如何實現的??
參考https://blog.csdn.net/cjopengler/article/details/78227004
之前並沒有了解rnn的結構及計算過程,或者是早就淡忘了,這里再來回憶加深一下認識
rnn結構的示意圖如下圖所示:

左側是rnn的結構,右側是並不是真實存在的結構,而是按照時間維度將左側結構展開的示意圖.一個rnn layer只有一個輸入位,一個中間狀態位,和一個輸出位. 只不過針對一個序列, 不斷的按序在輸入位輸入序列元素, 才會不斷地得到中間狀態值和輸出值. 一般rnn中, 輸入x,中間狀態s和輸出o都是向量. 中間狀態s的維度就是通常所說的中間隱含節點的數目.
這樣,按方式2對rnn layers進行歸一化, 將會對各個隱含單元(rnn layer的狀態向量的各個分量),計算其均值與方差. 計算是要遍歷minibatch所有序列樣本,從序列開始到序列結束.用文章中的原話就是, for each hidden unit we compute the mean and variance statistics over all items in the minibatch over the length of the sequences. 這樣做也是十分合理的, 計算下一層的狀態值, \(h_t^{l} = f(W^lh_t^{l-1}+U^lh_{t-1}^{l})\), 同一層同一時刻,不同樣本,其值的差異也許是很大的; 即使同一序列樣本,樣本不同時刻的某層狀態值也可能有很大差異性, 未來保證數值的穩定性, 因此要在對所有樣本,樣本的所有時刻進行歸一化.
方式1計算均值方差,是遍歷了minibatch中樣本,但是沒有遍歷各個時刻. 方式1的計算方式是,對每個時刻單獨求其均值與方差,忽略了不同時刻數值的差異性, 從而可能導致數值的不穩定性.
- SortaGrad
在運行Mozila開源的DeepSpeech過程中, 設置一個batchsize,運行開始時還很正常,運行一段時間后就出現了OOM問題. 最后查看issue得知,代碼中對音頻數據按大小升序排列, 所以運行到某個時刻, 加載的minibatch都是長度很長的音頻數據,從而導致OOM問題. DeepSpeech2遇到的雖不是這個問題,但是也是由於序列過長導致的. 采用CTC損失函數,在訓練初始階段,遇到過長的序列,導致預測的概率接近於0,從而導致梯度不穩定訓練不穩定. SortaGrad方法就是,對序列長度進行排序,選擇長度適中的序列用於初始階段的模型訓練, 然后再使用全部的序列參與訓練.
- Lookahead Convolution
作者設計Lookahead Convolution的目的,是為了解決語音翻譯實時性的問題.比如同聲翻譯,不能是別人說完了一整句話,你才能翻譯.必須是邊說邊翻譯,說幾個詞馬上就能准確翻譯.這就對現在的語音識別提出了更高的要求. 比如bidirectional rnn這個結構,就必須要求輸入完整的一句話,才能進行計算.因為該結構t時刻的輸出依賴t時刻之前的信息還依賴t時刻之后的信息. 如果改為常規的單向rnn結構,可以解決這個問題,但是單向rnn的性能比雙向rnn的性能要差很多.主要還是未來的信息對當前識別還是很重要的.為此作者設計了一個新的結構Lookahead Convolution來解決這個問題.這個層t時刻輸出不再依賴t時刻之后全部, 而是依賴t時刻之后若干個時間步. 這樣翻譯延遲就可以控制了.結構圖如下所示:

按照圖中的結構,翻譯延遲也就是2個時間步,相比bidirecitonal rnn還是可以接受的.公式化表示如下:
設\(h_t\)都是d維, Lookahead Convolution依賴未來\(\tau\)個時間步,參數矩陣\(W\in R^{(d,\tau)}\),從而得到\(r_t = \sum_{j=0}^{\tau-1}(\alpha_j, h_{t+j})\),其中\((\alpha_j, h_{t+j})\)表示點乘操作,故而\(\alpha\)也是d維的, 因此參數矩陣可以看作是由\(\alpha\)按列組合而成的即\(W = [\alpha_0, \alpha_2, ..., \alpha_{\tau - 1}]\)
