DTW算法——Matlab实现
概述
DTW (Dynamic time warping)算法是可以度量兩個獨立時間序列的相似度的一種方法。曾被廣泛應(yīng)用在單詞音頻的匹配上。該方法主要用來解決在兩段序列的時長不同的情況下,進行相似度的判斷。
上圖中,左側(cè)時長相等,可以逐一進行歐式距離的計算,右側(cè)則是時長不等,經(jīng)過DTW之后得到的結(jié)果,可以看出來兩個序列并不是一一對應(yīng)的。
再比如上面左圖,要得到藍(lán)色序列與紅色序列的相似度,因為可以看出來兩個序列有經(jīng)過平移的跡象,直接用一一匹配的方法顯然是不合理的。要得到左圖的對應(yīng)效果,就需要用DTW方法。
算法原理與步驟
① 計算兩個特征點之間的歐氏距離。構(gòu)成一個 n*m 矩陣,距離矩陣。
②計算累計距離 得到DP矩陣。
計算后的的值,放到DP矩陣中,為了更加直觀的理解,把這兩個序列繪圖如下:
其實在計算過程中,計算的順序其實是有方向的。網(wǎng)上有很多的博客說的也非常清楚,博主在這里不再贅述。為了更好的理解計算過程,列舉一個非常非常非常非常簡單的例子來幫助理解,如下圖: A B為帶有兩個特征值的序列,右邊是其對應(yīng)的DP矩陣的求解步驟。
③ 當(dāng)計算完整個DP矩陣 后,右上角的值(不一定是右上角,就是最終的得到的那個矩陣角上的值)即為兩個序列的累計距離。
④從右上角往左下角回溯,找到累計距離最短的路徑,根據(jù)路徑可以得到各個點之間的對應(yīng)關(guān)系。
算法的實現(xiàn)
博主是利用matlab實現(xiàn)的這個算法,只是因為利用matlab可以很方便的查看矩陣和畫圖,檢查算法的正確性,但是沒有調(diào)用matlab中成形的函數(shù),所以利用這個思路,用C/C++也是可以實現(xiàn)的,便于移植。
首先要寫好兩個函數(shù)。
一個是Get Min();用來得到三個值中的最小值,在計算 DP矩陣 時用得到。
另一個是GetMinIndex();這是用來在得到 DTW 結(jié)果之后,方便顯示特征點匹配的結(jié)果,返回兩個序列對應(yīng)特征點的索引。
function [index_i,index_j] = GetMinIndex(a,b,c,i,j) %a 是相鄰左上角,b 是相鄰正上方,c說相鄰正左方 %i 是當(dāng)前的x坐標(biāo) j 是當(dāng)前 y坐標(biāo) if(a <= b && a <= c)index_i = i-1;index_j = j-1; elseif(b <= a && b <= c)index_i = i-1;index_j = j; elseif(c <= b && c <= a)index_i = i;index_j = j-1; end end接下來就是主函數(shù)了
%生成兩個有明顯平移性質(zhì)的時間序列 x = zeros(1,50); for i = 1:50x(i) = sin(i*2*pi/50)+2; end y = zeros(1,50); for i = 1:50y(i) = sin(i*2*pi/50 + pi/6)+2; end x_len = length(x); y_len = length(y); plot(1:x_len,x);hold on plot(1:y_len,y);hold on %計算兩序列每個特征點的距離矩陣 distance = zeros(x_len,y_len); for i = 1:x_lenfor j=1:y_lendistance(i,j) = (x(i)-y(j)).^2;end end %計算兩個序列 DP = zeros(x_len,y_len); DP(1,1) = distance(1,1); for i=2:x_lenDP(i,1) = distance(i,1)+DP(i-1,1); end for j=2:y_lenDP(1,j) = distance(1,j)+DP(1,j-1); end for i=2:x_lenfor j=2:y_lenDP(i,j) = distance(i,j) + GetMin(DP(i-1,j),DP(i,j-1),DP(i-1,j-1));end end %回溯,找到各個特征點之間的匹配關(guān)系 i = x_len; j = y_len; while(~((i == 1)&&(j==1)))plot([i,j],[x(i),y(j)],'b');hold on %畫出匹配之后的特征點之間的匹配關(guān)系if(i==1)index_i = 1index_j = j-1elseif(j==1)index_i = i-1index_j = 1else[index_i,index_j] = GetMinIndex(DP(i-1,j-1),DP(i-1,j),DP(i,j-1),i,j)endi = index_i;j = index_j; end最終效果如下圖,可以看出來是考慮了平移之后的匹配。
總結(jié)
以上是生活随笔為你收集整理的DTW算法——Matlab实现的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 前端学习(2941):vue的生命周期
- 下一篇: 递归与分治策略之利用中位数线性时间选择