作者:桂。
時間:2017-05-31 16:17:29
鏈接:http://www.cnblogs.com/xingshansi/p/6924911.html
前言
動態時間規整(Dynamic Time Warping,DTW)是孤立詞識別的早期技術,梳理一下,主要包括:
1)孤立詞識別操作步驟;
2)DTW原理;
內容基本就是兩個博文的整合,最后一並給出鏈接。
一、孤立詞識別操作步驟
基本原理:

基本操作是預加重、分幀,端點檢測技術又叫有話幀檢測(Voice activity detection, VAD)技術。特征提取參考之前的博文。例如:

檢測語音→特征提取。
多說一句,倒譜就是將乘性關系變為加性關系:xy→logx+logy,一般的譜分析我們都是采用頻譜,或者小波這樣與頻譜的區別只是不同量度,這些都是解決加性噪聲的濾波問題,倒譜是一種為了濾除乘性噪聲的譜方法,簡單的說就是對功率譜求log,再反傅里葉變換,公式如
。
特征提取之后就是特征的模板匹配,也就是DTW算法。
二、DTW算法思路
A-DTW必要性
語音識別的匹配需要解決的一個關鍵問題是說話人對同一個詞的兩次發音不可能完全相同,這些差異不僅包括音強的大小、頻譜的偏移,更重要的是發音時音節的長短不可能完全相同,而且兩次發音的音節往往不存在線性對應關系。

設參考模板有M幀矢量{R(1),R(2),…R(m),…,R(M)},R(m)為第m幀的語音特征矢量,測試模板有N幀矢量{T(1),T(2),…T(n),…,T(N)},T(n)是第n幀的語音特征矢量。d(T(in),R(im))表示T中第in幀特征與R中im幀特征之間的歐幾里得距離。直接匹配是假設測試模板和參考模板長度相等,即in=im;線性時間規整技術假設說話速度是按不同說話單元的發音長度等比例分布的,即
。這兩種假設其實都不符合實際語音的發音情況,我們需要一種更加符合實際情況的非線性時間規整技術,也就是DTW算法。三種匹配模式的對比:

B-DTW思路
首先還是介紹下DTW的思想:假設現在有一個標准的參考模板R,是一個M維的向量,即R={R(1),R(2),……,R(m),……,R(M)},每個分量可以是一個數或者是一個更小的向量。現在有一個才測試的模板T,是一個N維向量,即T={T(1),T(2),……,T(n),……,T(N)}同樣每個分量可以是一個數或者是一個更小的向量,注意M不一定等於N,但是每個分量的維數應該相同。
由於M不一定等於N,現在要計算R和T的相似度,就不能用以前的歐式距離等類似的度量方法了。那用什么方法呢?DTW就是為了解決這個問題而產生的。
首先我們應該知道R中的一個分量R(m)和T中的一個分量T(n)的維數是相同的,它們之間可以計算相似度(即距離)。在運用DTW前,我們要首先計算R的每一個分量和T中的每一個分量之間的距離,形成一個M*N的矩陣。(為了方便,行數用將標准模板的維數M,列數為待測模板的維數N)。
然后下面的步驟該怎么計算呢?用個例子來看看。
這個例子中假設標准模板R為字母ABCDEF(6個),測試模板T為1234(4個)。R和T中各元素之間的距離已經給出。如下:

既然是模板匹配,所以各分量的先后匹配順序已經確定了,雖然不是一一對應的。現在題目的目的是要計算出測試模板T和標准模板R之間的距離。因為2個模板的長度不同,所以其對應匹配的關系有很多種,我們需要找出其中距離最短的那條匹配路徑。現假設題目滿足如下的約束:當從一個方格((i-1,j-1)或者(i-1,j)或者(i,j-1))中到下一個方格(i,j),如果是橫着或者豎着的話其距離為d(i,j),如果是斜着對角線過來的則是2d(i,j).其約束條件如下圖像所示:

其中g(i,j)表示2個模板都從起始分量逐次匹配,已經到了M中的i分量和T中的j分量,並且匹配到此步是2個模板之間的距離。並且都是在前一次匹配的結果上加d(i,j)或者2d(i,j),然后取最小值。
所以我們將所有的匹配步驟標注后如下:

怎么得來的呢?比如說g(1,1)=4, 當然前提都假設是g(0,0)=0,就是說g(1,1)=g(0,0)+2d(1,1)=0+2*2=4.
g(2,2)=9是一樣的道理。首先如果從g(1,2)來算的話是g(2,2)=g(1,2)+d(2,2)=5+4=9,因為是豎着上去的。
如果從g(2,1)來算的話是g(2,2)=g(2,1)+d(2,2)=7+4=11,因為是橫着往右走的。
如果從g(1,1)來算的話,g(2,2)=g(1,1)+2*d(2,2)=4+2*4=12.因為是斜着過去的。
綜上所述,取最小值為9. 所有g(2,2)=9.
當然在這之前要計算出g(1,1),g(2,1),g(1,2).因此計算g(I,j)也是有一定順序的。
其基本順序可以體現在如下:

計算了第一排,其中每一個紅色的箭頭表示最小值來源的那個方向。當計算了第二排后的結果如下:

最后都算完了的結果如下:

到此為止,我們已經得到了答案,即2個模板直接的距離為26. 我們還可以通過回溯找到最短距離的路徑,通過箭頭方向反推回去。如下所示:

到這里,估計大家動手算一下就會明白了,其實這個就是動態規划的思路:

主要code:
from numpy import array, zeros, argmin, inf, equal, ndim
from scipy.spatial.distance import cdist
def dtw(x, y, dist):
"""
Computes Dynamic Time Warping (DTW) of two sequences.
:param array x: N1*M array
:param array y: N2*M array
:param func dist: distance used as cost measure
Returns the minimum distance, the cost matrix, the accumulated cost matrix, and the wrap path.
"""
assert len(x)
assert len(y)
r, c = len(x), len(y)
D0 = zeros((r + 1, c + 1))
D0[0, 1:] = inf
D0[1:, 0] = inf
D1 = D0[1:, 1:] # view
for i in range(r):
for j in range(c):
D1[i, j] = dist(x[i], y[j])
C = D1.copy()
for i in range(r):
for j in range(c):
D1[i, j] += min(D0[i, j], D0[i, j+1], D0[i+1, j])
if len(x)==1:
path = zeros(len(y)), range(len(y))
elif len(y) == 1:
path = range(len(x)), zeros(len(x))
else:
path = _traceback(D0)
return D1[-1, -1] / sum(D1.shape), C, D1, path
def _traceback(D):
i, j = array(D.shape) - 2
p, q = [i], [j]
while ((i > 0) or (j > 0)):
tb = argmin((D[i, j], D[i, j+1], D[i+1, j]))
if (tb == 0):
i -= 1
j -= 1
elif (tb == 1):
i -= 1
else: # (tb == 2):
j -= 1
p.insert(0, i)
q.insert(0, j)
return array(p), array(q)
放在音頻里就是:模板/測試樣本的STFT取幅度后,每一幀存在一個sum(dist)的距離dij,i為模板的第i幀,j表示測試樣本的第j幀,這樣就得出了路徑,從而計算最短路徑,完成識別:

三、其他
其實DTW是模板匹配的一般思路,這是理論層面。孤立詞識別是它的一個應用,對於尺寸不同的匹配問題,DTW都應該有一定效果,比如數字識別.首先建立模板:

然后是測試樣本:

測試樣本有大有小,直接模板匹配是不合適的。實際應用中數字可能形狀存在差異、且有傾斜,需要把字符切割出來,而不考慮白框。這里只是梳理思路,僅考慮最理想的情況。
例如利用DTW:將圖片二值化im2bw→拉成向量img(:)→將測試數據利用DTW,分別與模板匹配,找出最短距離的最小值,即是對應的數字。
參考
- http://www.cnblogs.com/ChengQH/p/2dc8272d6b045b9cee3a02d221662251.html
- http://www.cnblogs.com/tornadomeet/archive/2012/03/23/2413363.html
