Eukleidiline kauguse ja dünaamilise ajadeformatsiooni erinevust illustreeriv pilt.
**Dünaamiline ajadeformatsioon** (inglise keeles **dynamic time warping**) on aegridade analüüsi algoritm, mida kasutatakse kahe aegrea sarnasuste leidmiseks. See algoritm on loodud analüüsimaks aegridu, mis on omavahel faasist väljas. Näiteks kasutatakse dünaamilist ajadeformatsiooni kõneanalüüsis. Kui soovime tuvastada sõna "kana", kuid kõneleja ütleb seda sõna kui "kaanaaaa", on aegread erineva pikkusega. See tähendab, et kahte aegrida ei saa otse võrrelda. Just selliste juhtude jaoks kasutataksegi dünaamilist ajadeformatsiooni. See analüüsimisalgoritm suudab tuvastada sarnasusi isegi kui aegread on erineva pikkusega, leides millised elemendid esimesest aegreast on kõige sarnasemad elementidega teisest aegreast. Teisteks kasutusaladeks on veel näiteks kõnelejatuvastus, allkirjatuvastus ja aktsiaturu analüüs.

Loogika
-------

Kahest aegreast luuakse maatriks, kus ühe väärtused pannakse y-teljele ja teise väärtused pannakse x-teljele. Järgmisena arvutatakse maatriksisse väärtused kasutades valemit {\displaystyle D{ij}=|y{i}-x{j}|+\min(D[{i-1},{j-1}],D[{i-1},{j}],D[{i},{j-1}])}. Y ja x telgede äärmiste elementide jaoks kasutatakse vastavalt {\displaystyle D{ij}=|y{i}-x{j}|+D[{i-1},0]} ja {\displaystyle D{ij}=|y{i}-x{j}|+D[0,{j-1}]}. Kui maatriksis on igale kohale väärtus leitud, tuleb leida lühim tee läbi maatriksi. Selle jaoks on 3 reeglit, mida tuleb jälgida: 

1. tee algab alati maatriksi ülevalt paremast nurgast ja lõppeb all vasakul nurgas
2. lubatud on liikuda ainult alla, vasakule või alla-vasakule
3. liikuma peab alati kõige väiksema elemendi poole. Näiteks kui saab liikuda 3, 5 või 2 poole, tuleb liikuda 2 poole.

Õigesti ja valesti lahendamise näited on näha alloleval pildil.

Näide õigest teekonna leidmisest(a) ja näited valesti teekonna leidmisest(n, c, d).
Leitud tee läbi maatriksi näitab meile, millised elemendid signaalist x on kõige sarnasemad elementidega signaalist y. Samuti saame lühima tee elementidega hinnata signaalide erinevust. Seda saab teha liites kokku kõik leitud teekonna väärtused. See näitab meile kui erinevad on signaalid peale nihutamist. Mida väiksem on summa, seda sarnasemad on signaalid.

Realiseerimine
--------------

Dünaamilise ajadeformatsiooni algoritmi Python3 näitekood. See kood võtab sisendiks kaks jada ja tagastab arvutatud dünaamilise ajadeformatsiooni maatriksi. 

```
def dtw(s, t):
    n, m = len(s), len(t)
    dtw\_matrix = np.zeros((n+1, m+1))
    for i in range(n+1):
        for j in range(m+1):
            dtw\_matrix[i, j] = np.inf
    dtw\_matrix[0, 0] = 0
    
    for i in range(1, n+1):
        for j in range(1, m+1):
            cost = abs(s[i-1] - t[j-1])
            # take last min from a square box
            last\_min = np.min([dtw\_matrix[i-1, j], dtw\_matrix[i, j-1], dtw\_matrix[i-1, j-1]])
            dtw\_matrix[i, j] = cost + last\_min
    return dtw\_matrix

```
Esmalt valmistatakse ette massiiv, kuhu hakatakse väärtuseid sisse arvutama. Järgmise for tsükliga hakatakse maatriksisse väärtuseid arvutama. 

Esmalt leitakse valemi {\displaystyle D{ij}=|y{i}-x{j}|+\min(D[{i-1},{j-1}],D[{i-1},{j}],D[{i},{j-1}])} esimene pool, ehk {\displaystyle |y{i}-x{j}|}. 

```
cost = abs(s[i-1] - t[j-1])

```
Järgmisena leitakse ümber olevatest väärtustest väikseim valemi teise poole järgi.

```
last\_min = np.min([dtw\_matrix[i-1, j], dtw\_matrix[i, j-1], dtw\_matrix[i-1, j-1]])

```
Lõpuks liidetakse maatriksis kohale {\displaystyle [i,j]} viimase kahe arvutuse summa.

```
dtw\_matrix[i, j] = cost + last\_min

```
Seda protsessi korratakse iga elemendi peal maatriksis.

Kiiremad algoritmid
-------------------

Kuna suurte andmemassiivide vaheliste sarnasuste otsimine dünaamilise ajadeformatsiooniga on aeganõudev, on välja töötatud erinevaid meetodeid algoritmi kiirendamiseks. 

### FastDTW

FastDTW põhimõte seisneb dünaamilise ajadeformatsiooni võimalikult väikesteks alamdeformatsioonideks tegemises. Alustatakse väikseima võimaliku resolutsiooniga, ehitades üles originaalse resolutsioonini.

FastDTW algoritm töötab kolmes etapis:

1. aegrida muudetakse võimalikult väikeseks, proovides samas hoida graafiku kõveraid võimalikult sarnasena originaaliga
2. leitakse väiksema resolutsiooniga maatriksist lühim teekond ja kasutatakse seda veidi suurema resolutsiooniga maatriksis teekonna leidmiseks, ehitades üles originaalse resolutsioonini (maatriksi resolutsioonid kasvavad kahe korrutisena)
3. leitud teekonnas tehakse väikeseid parandusi nii, et see sobiks optimaalselt originaalsesse maatriksisse.

### PrunedDTW

PrunedDTW põhimõte seisneb maatriksi elementide, mis kindlalt ei saa lühima teekonna osaks, mitte arvutamisel. Nii jäetakse ära paljud muidu kasutud arvutused.

### Piiride seadmine

Üheks populaarseks dünaamilise ajadeformatsiooni kiirendamise viisiks on seada mööda maatriksi diagonaali kindlad piirid. Need piirid määravad ära, mis piirkonnas lühimat teed otsitakse. See töötab kuna tihti läheb lühim tee mööda diagonaali või selle lähedalt. Selle meetodi jaoks peavad olema mõlemad andmemassiivid ühe pikkusega. Populaarsemateks piirikujudeks on Sakoe-Chiba ja Itakura.

Viited
------

1. ↑  "Finding the best path through the matrix". Vaadatud 29.05.2020.
2. ↑  Jeremy Zhang. "Dünaamilise ajadeformatsiooni python3 kood". Vaadatud 23.05.2020.
3. ↑  Stan Salvador ja Philip Chan. "FastDTW: Toward Accurate Dynamic Time Warping in Linear Time and Space" (PDF). Vaadatud 29.05.2020.
4. ↑  Diego F. Silva ja Gustavo E. A. P. A. Batista. "Speeding Up All-Pairwise Dynamic Time Warping Matrix Calculation" (PDF). Vaadatud 29.05.2020.
5. ↑  Chotirat Ann Ratanamahatana ja Eamonn Keogh. "Everything you know about dynamic time warping is wrong". Vaadatud 29.05.2020.