【时间序列】动态时间规整(DTW)算法简介(python)
簡介
動態時間規整:(Dynamic Time Warping,DTW)
定義:用于比較不同長度的兩個數組或時間序列之間的相似性或計算兩者間的距離。
例1:a =[1,2,3],b=[3,2,2]
例2:a=[1,2,3],b=[2,2,2,3,4]
例1好計算,但對于例2,如何計算呢?即所謂的規整或扭曲。
比較不同長度的數組的思想是構建一對多和多對一匹配,以便使兩者之間的總距離最小化。
DTW是計算給定兩個序列最優匹配的一種方法,滿足以下規則:
第一個序列的每個索引必須與另一序列的一個或多個索引匹配,反之亦然
第一個序列的第一個索引必須匹配另一個序列的第一個索引(也可匹配多個索引)
第一個序列索引對另一個序列索引的映射必須是單調遞增的,反之亦然。如果第一個序列中索引,另一個序列中索引,則匹配,匹配(和兩者連續且相差不大于1)。如下圖所示:
最優匹配是指滿足上述條件且代價最小的匹配表示,代價計算方法是計算每個匹配索引對的值之間的絕對差的和。
總結一下,頭和尾必須在位置上匹配,不能交叉匹配,也不能遺漏。
DTW中warping對應于在時間維度上的非線性序列,即所謂的“warping path”。通過時間對齊解決。常用于基因序列和音頻同步。
用一個矩陣表示序列()和序列()各個點之間的距離,等于的第個點和的第個點之間的距離,即:
傳統歐幾里得距離里對應的點:
A(1)-B(1)
A(2)-B(2)
A(3)-B(3)
A(4)-B(4)
A(5)-B(5)
A(6)-B(6)
它們正好構成了對角線,對角線上元素和為6。
時間規整的方法里,對應的點為:
A(1)-B(1)
A(2)-B(1)
A(3)B(2)
A(4)-B(2)
A(5)-B(4)
A(5)-B(4)
A(6)-B(5)
A(6)-B(6)
這些點構成了從左上角到右下角的另一條路徑,路徑上的元素和為0。
因此,DTW算法的步驟為:
計算兩個序列各個點之間的距離矩陣。
尋找一條從矩陣左上角到右下角的路徑,使得路徑上的元素和最小。
我們稱路徑上的元素和為路徑長度。那么如何尋找長度最小的路徑呢?
矩陣從左上角到右下角的路徑長度有以下性質:
當前路徑長度 = 前一步的路徑長度 + 當前元素的大小
路徑上的某個元素,它的前一個元素只可能為以下三者之一:
a) 左邊的相鄰元素 (i, j-1)?
b) 上面的相鄰元素 (i-1, j)?
c) 左上方的相鄰元素 (i-1, j-1)
假設矩陣為M,從矩陣左上角到任一點的最短路徑長度為。那么可以用遞歸算法求最短路徑長度:
起始條件:
遞推規則:
遞推規則這樣寫的原因是因為當前元素的最短路徑必然是從前一個元素的最短路徑的長度加上當前元素的值。前一個元素有三個可能,我們取三個可能之中路徑最短的那個即可。
python實現
import?numpy?as?npdef?dtw(s,?t):""":param?s:?第一個序列:param?t:?第二個序列:return:"""n,?m?=?len(s),?len(t)#?構建n行m列矩陣dtw_matrix?=?np.zeros((n?+?1,?m?+?1))dtw_matrix.fill(np.inf)dtw_matrix[0,?0]?=?0??#?路徑左上-->右下#?dtw_matirx[i,?j]?is?the?distance?between?s[1:i]?and?t[1:j]?with?the?best?alignment.for?i?in?range(1,?n?+?1):for?j?in?range(1,?m?+?1):cost?=?np.abs(s[i?-?1]?-?t[j?-?1])??#?計算絕對距離#?找到當前索引方塊的top,left,top_left方向的累積損失的最小值last_min?=?np.min([dtw_matrix[i,?j?-?1],?dtw_matrix[i?-?1,?j],?dtw_matrix[i?-?1,?j?-?1]])dtw_matrix[i,?j]?=?cost?+?last_minreturn?dtw_matrixa?=?[1,?2,?3] b?=?[2,?2,?2,?3,?4]dtw(a,?b)結果如下:
array([[?0.,?inf,?inf,?inf,?inf,?inf],[inf,??1.,??2.,??3.,??5.,??8.],[inf,??1.,??1.,??1.,??2.,??4.],[inf,??2.,??2.,??2.,??1.,??2.]])a和b之間的距離是矩陣的最后一個元素,也就是2。
添加窗口約束
上述算法的一個問題是:我們允許一個數組中的一個元素與另一個數組中的無限個元素匹配(只要尾部最終能夠匹配),這將導致映射大量彎曲,例如,下面的數組
a?=?[1,?2,?3] b?=?[1,?2,?2,?2,?2,?2,?2,?2,?...,?5]為了最小化距離,數組a中的元素2將匹配數組b中的所有2,這導致數組b嚴重彎曲。
為了避免這種情況,我們可以添加一個窗口約束來限制可以匹配的元素的數量。
關鍵的區別是,現在每個元素都被限制在匹配范圍和中的元素。保證所有索引都可以匹配:
def?dtw(s,?t,?window):n,?m?=?len(s),?len(t)w?=?np.min([window,?abs(n?-?m)])dtw_matrix?=?np.full((n?+?1,?m?+?1),?np.inf)dtw_matrix[0,?0]?=?0for?i?in?range(1,?n?+?1):for?j?in?range(np.max([1,?i?-?w]),?np.min([i?+?w,?m])?+?1):#?當前損失cost?=?np.abs(s[i?-?1]?-?t[j?-?1])#?上一個最小值last_min?=?np.min([dtw_matrix[i,?j?-?1],?dtw_matrix[i?-?1,?j],?dtw_matrix[i?-?1,?j?-?1]])#?當前累積損失dtw_matrix[i,?j]?=?last_min?+?costreturn?dtw_matrixa?=?[1,?2,?3,?3,?5] b?=?[1,?2,?2,?2,?2,?2,?2,?4]dtw(a,?b,?window=3)結果如下:
array([[?0.,?inf,?inf,?inf,?inf,?inf,?inf,?inf,?inf],[inf,??0.,??1.,??2.,??3.,?inf,?inf,?inf,?inf],[inf,??1.,??0.,??0.,??0.,??0.,?inf,?inf,?inf],[inf,??3.,??1.,??1.,??1.,??1.,??1.,?inf,?inf],[inf,??5.,??2.,??2.,??2.,??2.,??2.,??2.,?inf],[inf,?inf,??5.,??5.,??5.,??5.,??5.,??5.,??3.]])fastdtw 包
from?fastdtw?import?fastdtw from?scipy.spatial.distance?import?euclideanx?=?np.array([1,?2,?3,?3,?7]) y?=?np.array([1,?2,?2,?2,?2,?2,?2,?4])distance,?path?=?fastdtw(x,?y,?dist=euclidean)print(distance) print(path)結果如下:
5.0 [(0,?0),?(1,?1),?(1,?2),?(1,?3),?(1,?4),?(2,?5),?(3,?6),?(4,?7)]應用于多元變量
并不要求兩個時間序列具有相同的長度,但它們必須具有相同大小的維度。
def?get_squared_dist(x,?y):"""計算歐式距離"""dist?=?0.for?di?in?range(x.shape[0]):diff?=?(x[di]?-?y[di])dist?+=?diff?*?diffreturn?distdef?accumulated_matrix(s1,?s2):l1?=?s1.shape[0]l2?=?s2.shape[0]cum_sum?=?np.full((l1?+?1,?l2?+?1),?np.inf)cum_sum[0,?0]?=?0.for?i?in?range(l1):for?j?in?range(l2):cum_sum[i?+?1,?j?+?1]?=?get_squared_dist(s1[i],?s2[j])cum_sum[i?+?1,?j?+?1]?+=?min(cum_sum[i,?j?+?1],cum_sum[i?+?1,?j],cum_sum[i,?j])return?cum_sum[1:,?1:]s1?=?np.array([[1,?2],?[3,?4]]) s2?=?np.array([[1,?5],?[6,?7]])accumulated_matrix(s1,?s2)結果如下:
array([[?9.,?59.],[14.,?27.]])計算方法如下:
參考:
[1] https://en.wikipedia.org/wiki/Dynamic_time_warping
[2] https://towardsdatascience.com/dynamic-time-warping-3933f25fcdd
[3] https://zhuanlan.zhihu.com/p/43247215
建議閱讀:
高考失利之后,屬于我的大學本科四年
【資源分享】對于時間序列,你所能做的一切.
【時空序列預測第一篇】什么是時空序列問題?這類問題主要應用了哪些模型?主要應用在哪些領域?
【AI蝸牛車出品】手把手AI項目、時空序列、時間序列、白話機器學習、pytorch修煉
公眾號:AI蝸牛車
保持謙遜、保持自律、保持進步
個人微信
備注:昵稱+學校/公司+方向
如果沒有備注不拉群!
拉你進AI蝸牛車交流群
總結
以上是生活随笔為你收集整理的【时间序列】动态时间规整(DTW)算法简介(python)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 工作408- Module build
- 下一篇: 记一次 Vue2 迁移 Vue3 的实践