DTW是一種衡量兩個時間序列之間的相似度的方法,主要應用在語音識別領域來識別兩段語音是否表示同一個單詞。
1. DTW方法原理
在時間序列中,需要比較相似性的兩段時間序列的長度可能并不相等,在語音識別領域表現為不同人的語速不同。而且同一個單詞內的不同音素的發音速度也不同,比如有的人會把‘A’這個音拖得很長,或者把‘i’發的很短。另外,不同時間序列可能僅僅存在時間軸上的位移,亦即在還原位移的情況下,兩個時間序列是一致的。在這些復雜情況下,使用傳統的歐幾里得距離無法有效地求的兩個時間序列之間的距離(或者相似性)。
DTW通過把時間序列進行延伸和縮短,來計算兩個時間序列性之間的相似性:
image
如上圖所示,上下兩條實線代表兩個時間序列,時間序列之間的虛線代表兩個時間序列之間的相似的點。DTW使用所有這些相似點之間的距離的和,稱之為**歸整路徑距離**(Warp Path Distance)來衡量兩個時間序列之間的相似性。
2. DTW計算方法:
令要計算相似度的兩個時間序列為X和Y,長度分別為|X|和|Y|。
2.1歸整路徑(Warp Path)
歸整路徑的形式為W=w<sub>1</sub>,w<sub>2</sub>,...,w<sub>K,</sub>其中Max(|X|,|Y|)<=K<=|X|+|Y|。
w<sub>k</sub>的形式為(i,j),其中i表示的是X中的i坐標,j表示的是Y中的j坐標。
歸整路徑W必須從w1=(1,1)開始,到wK=(|X|,|Y|)結尾,以保證X和Y中的每個坐標都在W中出現。
另外,W中w(i,j)的i和j必須是單調增加的,以保證圖1中的虛線不會相交,所謂單調增加是指:
image
我們最后要得到的歸整路徑是距離最短的一個歸整路徑:
image
其中Dist(w<sub>ki</sub>,w<sub>kj</sub>)為任意經典的距離計算方法,比如歐幾里得距離。w<sub>ki</sub>是指X的第i個數據點,w<sub>kj</sub>是指Y的第j個數據點。
3. DTW實現
在實現DTW時,我們采用動態規劃的思想,其中D(i,j)表示長度為i和j的兩個時間序列之間的歸整路徑距離:image
我們最后求得的歸整路徑距離為D(|X|,|Y|),使用動態規劃來進行求解:
image
上圖為代價矩陣(Cost Matrix) D,D(i,j)表示長度為i和j的兩個時間序列之間的歸整路徑距離。
3.1 DTW實現的偽代碼為:
int DTWDistance(s: array [1..n], t: array [1..m]) {
DTW := array [0..n, 0..m]
for i := 1 to n
DTW[i, 0] := infinity
for i := 1 to m
DTW[0, i] := infinity
DTW[0, 0] := 0
for i := 1 to n
for j := 1 to m
cost:= d(s[i], t[j])
DTW[i, j] := cost + minimum(DTW[i-1, j ], // insertion
DTW[i , j-1], // deletion
DTW[i-1, j-1]) // match
return DTW[n, m]
}
3.2 DTW實現的Python代碼:
def dtw(X,Y):
X=[1,2,3,4]
Y=[1,2,7,4,5]
M=[[distance(X[i],Y[i]) for i in range(len(X))] for j in range(len(Y))]
l1=len(X)
l2=len(Y)
D=[[0 for i in range(l1+1)] for i in range(l2+1)]
D[0][0]=0
for i in range(1,l1+1):
D[0][i]=sys.maxint
for j in range(1,l2+1):
D[j][0]=sys.maxint
for j in range(1,l2+1):
for i in range(1,l1+1):
D[j][i]=M[j-1][i-1]+Min(D[j-1][i],D[j][i-1],D[j-1][i-1]+M[j-1][i-1])
- DTW加速
DTW雖然使用線性規劃可以快速的求解,但是在面對比較長的時間序列是,O(N2)的時間復雜度還是很大。已經有很多改進的快速DTW算法,比如FastDTW,SparseDTW,LB_Keogh,LB_Improved等等。