初识DTW(动态时间规整)算法及Python实现例
目錄?
1. 概要
2. 時(shí)序列相似度度量
3. DTW基本算法
4. Python實(shí)現(xiàn)
5. Next Action
1. 概要
???????DTW( Dynamic Time Warping,動(dòng)態(tài)時(shí)間規(guī)整)是基于動(dòng)態(tài)規(guī)劃(Dynamic Programming)策略對(duì)兩個(gè)時(shí)序列通過非線性地進(jìn)行時(shí)域?qū)?zhǔn)(Timing alignment)調(diào)整以便于正確地計(jì)算兩者之間相似度(similarity)的一種算法。
????????本文簡(jiǎn)單介紹DTW算法所針對(duì)的問題背景、DTW基本算法流程,并給出簡(jiǎn)單的Python實(shí)現(xiàn)例。
????????本文如標(biāo)題“初識(shí)。。?!彼?#xff0c;面向像作者這樣初次接觸DTW的渣渣^-^。不過本文并不準(zhǔn)備動(dòng)態(tài)規(guī)劃策略進(jìn)行描述,所以本文要求讀者對(duì)動(dòng)態(tài)規(guī)劃有基本的了解。
2. 時(shí)序列相似度度量
????????考慮如下所示的幾個(gè)時(shí)序列波形之間的“相似度”的比較。時(shí)序列波形之間的相似度的衡量的一種方法就是把時(shí)序列波形看作是一個(gè)向量,然后計(jì)算兩個(gè)向量之間的歐幾里得距離。除了歐幾里得距離以外,其它的相似度度量還有比如說余弦相似度(cosine similarity)。
# -*- coding: utf-8 -*- """ Created on Sat Oct 30 10:50:53 2021@author: chenxy """import numpy as np import matplotlib.pyplot as pltdef euclid_dist(t1,t2):return np.sqrt(np.sum((t1-t2)**2))t = np.arange(100) ts1 = 5*np.sin(2*np.pi*t*0.05) # 0.05Hz sin wave, 1Hz sampling rate, amplitude=5 ts2 = 3*np.sin(2*np.pi*t*0.02) # 0.02Hz sin wave, 1Hz sampling rate, amplitude=3 ts3 = 0.08*t-4fig,axs = plt.subplots(figsize=(12,8)) axs.plot(ts1) axs.plot(ts2) axs.plot(ts3) axs.legend(['ts1: sin,0.05Hz, amplitude=5',\'ts2: sin,0.02Hz, amplitude=3',\'ts3: line with slope = 0.08'])euclidean_dist_12 = euclid_dist(ts1,ts2) euclidean_dist_13 = euclid_dist(ts1,ts3) euclidean_dist_23 = euclid_dist(ts2,ts3) print('euclidean_dist_12 = {0:6.2f}'.format(euclidean_dist_12)) print('euclidean_dist_13 = {0:6.2f}'.format(euclidean_dist_13)) print('euclidean_dist_23 = {0:6.2f}'.format(euclidean_dist_23))運(yùn)行后得到:
?
?圖1
????????如果直接采用歐幾里得距離作為相似性度量的話,如以上結(jié)果可得,ts2和ts3之間的距離最小,或者說相似度最高。但是,從人類的直覺來看的話,由于ts1和ts2都是正弦波,只不過頻率和幅度不同而已,而ts3是一根直線,顯然應(yīng)該是ts1和ts2更相似才合理。
????????進(jìn)一步,考慮一個(gè)與ts1頻率、幅度都相等,但是相位差180度的正弦波。
ts4 = 5*np.sin(2*np.pi*t*0.05+np.pi) # 0.05Hz sin wave, 1Hz sampling rate, amplitude=5 fig,axs = plt.subplots(figsize=(12,8)) axs.plot(ts1) axs.plot(ts4) axs.plot(ts3) axs.legend(['ts1: sin,0.05Hz, amplitude=5',\'ts4: sin,0.05Hz, amplitude=5, phase offset=pi',\'ts3: line with slope = 0.08'])euclidean_dist_14 = euclid_dist(ts1,ts4) euclidean_dist_34 = euclid_dist(ts3,ts4) print('euclidean_dist_14 = {0:6.2f}'.format(euclidean_dist_14)) print('euclidean_dist_34 = {0:6.2f}'.format(euclidean_dist_34))????????運(yùn)行后得到:?
圖2?
????????這一次結(jié)果更加明顯地反直覺。Ts1與ts4僅僅只是反相而已,而它們之間的”距離”居然會(huì)遠(yuǎn)遠(yuǎn)大于ts3與ts4之間的距離!?
????????造成以上反直覺的結(jié)果的原因在于:Ts1,ts2,ts4之間雖然基本波形其實(shí)是相似的,但是在時(shí)域存在沒有對(duì)準(zhǔn)(或者說不同步)的問題。Ts1和ts4之間相位相反也可以看作是時(shí)域未對(duì)準(zhǔn),因?yàn)榭梢园裻s4看作是ts1延遲半個(gè)周期的波形。而ts2與ts1之間則不僅僅是相位偏差導(dǎo)致的時(shí)域未對(duì)準(zhǔn),還有因?yàn)樗麄兊闹芷诓煌鴮?dǎo)致相位的偏差是隨時(shí)間變化的。
????????以上的情況還只是最簡(jiǎn)單的情況。因?yàn)閠s1和ts2和ts4同是正弦波,差異在于相位和頻率,但是相位和頻率差異是固定的。因此,通過對(duì)其中一個(gè)信號(hào)進(jìn)行相位調(diào)整的掃描以及對(duì)時(shí)域波形擴(kuò)張(對(duì)應(yīng)于改變頻率)的掃描,然后再進(jìn)行信號(hào)處理中的相關(guān)運(yùn)算是可以正確地識(shí)別出它們之間的相似度來的。
????????在真實(shí)世界中,兩個(gè)原本相似度很高的時(shí)序列之間可能時(shí)域上相對(duì)變形(distortion)程度不但是時(shí)變的,而且還是非線性變化的。將一段語(yǔ)音變速播放就會(huì)產(chǎn)生這種類似的效果。這種情況下要想正確識(shí)別出它們之間的相似度,就需要先對(duì)兩者之間局部時(shí)域波形的相對(duì)變形進(jìn)行糾正以后再計(jì)算歐幾里得距離?!皩?duì)兩者之間局部時(shí)域波形的相對(duì)變形糾正”稱為Time-Warping(時(shí)域規(guī)整)處理。經(jīng)過Time-Warping(時(shí)域規(guī)整)處理后,兩個(gè)序列中樣點(diǎn)間不再保持一一對(duì)應(yīng)關(guān)系,而是可能出現(xiàn)一些一對(duì)多或者多對(duì)一的關(guān)系,相當(dāng)于局部范圍內(nèi)時(shí)域波形出現(xiàn)了相對(duì)壓縮或者拉伸后再進(jìn)行對(duì)應(yīng),如下圖所示:
圖3?
3. DTW基本算法
????????DTW算法就是基于動(dòng)態(tài)規(guī)劃策略對(duì)兩個(gè)時(shí)序列進(jìn)行動(dòng)態(tài)的時(shí)域規(guī)整處理后以搜索估計(jì)它們之間最小可能的距離(最大可能的相似度)。廣泛地用于時(shí)序列分類和聚類等應(yīng)用中。
????????DTW算法基本工作原理如下所述:
????????考慮兩個(gè)時(shí)序列和,長(zhǎng)度分別為n和m(直接計(jì)算兩個(gè)序列之間的歐氏距離要求兩者長(zhǎng)度相等。但是,基于DTW算法來估計(jì)相似度并不要求長(zhǎng)度相等)。
????????首先,構(gòu)建一個(gè)n*m的矩陣D,其中D[i,j]表示Qi與Pj之間的歐氏距離(注意,為了描述方便,下標(biāo)是從1開始計(jì)數(shù)(記為1-indexed)。但是在python或C代碼實(shí)現(xiàn)中則是從0開始計(jì)數(shù),稱為0-indexed)。DTW的目標(biāo)就是要找到一條從[1,1]到[n,m]的路徑使得該條路徑的累積歐氏距離最小。
如前所述,在Time Warping處理中,一個(gè)時(shí)序列上的一個(gè)點(diǎn)可以對(duì)應(yīng)另一個(gè)時(shí)序列的一個(gè)或者多個(gè)點(diǎn)。對(duì)應(yīng)地,在以上矩陣D中的路徑(從左上角的[1,1]出發(fā)的)構(gòu)造過程中,可以從一個(gè)格點(diǎn)到達(dá)其右邊、下邊以及右下的格點(diǎn)。理論上,也可以走向其它5個(gè)方向的格點(diǎn),但是這樣肯定會(huì)導(dǎo)致非最小化的距離,因此可以不用考慮。
考慮表示一條從[1,1]到[n,m]的路徑,其中Wk表示路徑經(jīng)過的某格點(diǎn)所保存的Q和C之間某兩點(diǎn)之間的歐氏距離的平方 (注意,這里用平方而不是絕對(duì)值,是因?yàn)閮蓚€(gè)時(shí)序列之間的距離是要先進(jìn)行平方和運(yùn)算再開方的)。如下圖所示就是一條可能的路徑。
圖4?
????????這樣,以上最小累計(jì)距離搜索的優(yōu)化問題可以表述為求解
?????????如上圖所示,將從[1,1]到達(dá)[i,j]的累計(jì)距離記為 。
????????很顯然,經(jīng)歷最短累計(jì)距離到達(dá)[i,j]的前一個(gè)點(diǎn)必然是[i-1,j-1], [i,j-1], [i-1,j]三者之一。在已經(jīng)計(jì)算出[i-1,j-1], [i,j-1], [i-1,j]各自所對(duì)應(yīng)的最短累計(jì)距離的前提下,可以得到關(guān)于 的遞推關(guān)系式如下:?
?
????????基于這個(gè)遞推關(guān)系式,可以從[1,1]開始逐行(或逐列也可以)計(jì)算并填充關(guān)于的表格,填充完整個(gè)表格后即可以得到兩個(gè)序列之間的最短距離 ,這個(gè)距離通常也稱為DTW距離。
?????????
????????進(jìn)一步,記錄以上關(guān)于的創(chuàng)建過程中的路徑選擇歷史的話,可以從[n,m]回溯得到最優(yōu)路徑所經(jīng)歷的所有格點(diǎn)。也就可以據(jù)此得到如以上圖3那樣的Time Warping映射圖。
4. Python實(shí)現(xiàn)
?????????DTW算法實(shí)現(xiàn)如以下函數(shù)DTWDistance()所示?;谶@一函數(shù)我們來重新評(píng)估以上4個(gè)序列之間的DTW距離。
""" DTWDistance(s1, s2) is copied from: http://alexminnaar.com/2014/04/16/Time-Series-Classification-and-Clustering-with-Python.html """def DTWDistance(s1, s2):DTW={}for i in range(len(s1)):DTW[(i, -1)] = float('inf')for i in range(len(s2)):DTW[(-1, i)] = float('inf')DTW[(-1, -1)] = 0for i in range(len(s1)):for j in range(len(s2)):dist= (s1[i]-s2[j])**2DTW[(i, j)] = dist + min(DTW[(i-1, j)],DTW[(i, j-1)], DTW[(i-1, j-1)])return np.sqrt(DTW[len(s1)-1, len(s2)-1])dtw_dist_12 = DTWDistance(ts1,ts2) dtw_dist_13 = DTWDistance(ts1,ts3) dtw_dist_14 = DTWDistance(ts1,ts4) dtw_dist_23 = DTWDistance(ts2,ts3) dtw_dist_24 = DTWDistance(ts2,ts4) dtw_dist_34 = DTWDistance(ts3,ts4) print('dtw_dist_12 = {0:6.2f}'.format(dtw_dist_12)) print('dtw_dist_14 = {0:6.2f}'.format(dtw_dist_14)) print('dtw_dist_24 = {0:6.2f}'.format(dtw_dist_24)) print('dtw_dist_23 = {0:6.2f}'.format(dtw_dist_23)) print('dtw_dist_13 = {0:6.2f}'.format(dtw_dist_13)) print('dtw_dist_34 = {0:6.2f}'.format(dtw_dist_34))?運(yùn)行結(jié)果如下:?
由此可以看出ts3(直線)與其它三者之間的DTW距離都比其它三者之間的相互的DTW距離要大,也就是說ts1,2,4相互之間的相似度是要大于ts3與ts1,2,4之間的相似度的。
5. Next Action
Reference:
[1]http://alexminnaar.com/2014/04/16/Time-Series-Classification-and-Clustering-with-Python.html
總結(jié)
以上是生活随笔為你收集整理的初识DTW(动态时间规整)算法及Python实现例的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Boll布林带波动率策略
- 下一篇: 紫色特别舒服的UI趣味测试微信小程序源码