Dynamic Time Warping Example in R

   Dynamic Time Warping (DTW) is an algorithm to measure an optimal alignment between two sequences. Linear sequence data like time series, audio, video can be analyzed with this method. DTW finds out optimal match of two numeric sequence data by stretching and compressing them locally, and the distance can also be calculated between those series. 

    The R package 'dtw' provides various functions for DTW operations. In this post, we will learn how to find the alignment of two numeric sequence data.

Installing 'dtw' package

To install the package run the 'install.packages()' command and load it with 'library()' command.

install.packages("dtw")
library(dtw)

Creating Sequence Data

First, we generate sequence data, and visualize it in a plot.

n <- 200
a <- sin(seq(0,4*pi, len = n)) + runif(n)/5
b <- cos(seq(-pi,3*pi, len = n)) + runif(n)/5
 
plot(a, type = "l")
lines(b, col = "blue")


Computing alignment


dtw() function calculates an optimal alignment.

align <- dtw(a, b, keep = T)

dtw() returns the following items. You may refer to a help page to learn more about them.

str(align)
List of 20
 $ costMatrix        : num [1:200, 1:200] 1.15 2.19 3.45 4.71 5.99 ...
 $ directionMatrix   : int [1:200, 1:200] NA 3 3 3 3 3 3 3 3 3 ...
 $ stepPattern       : stepPattern [1:6, 1:4] 1 1 2 2 3 3 1 0 0 0 ...
  ..- attr(*, "npat")= num 3
  ..- attr(*, "norm")= chr "N+M"
 $ N                 : int 200
 $ M                 : int 200
 $ call              : language dtw(x = a, y = b, keep.internals = T)
 $ openEnd           : logi FALSE
 $ openBegin         : logi FALSE
 $ windowFunction    :function (iw, jw, ...)  
 $ jmin              : int 200
 $ distance          : num 38.6
 $ normalizedDistance: num 0.0965
 $ index1            : num [1:308] 1 2 2 2 2 2 2 2 2 2 ...
 $ index2            : num [1:308] 1 2 3 4 5 6 7 8 9 10 ...
 $ index1s           : num [1:308] 1 2 2 2 2 2 2 2 2 2 ...
 $ index2s           : num [1:308] 1 2 3 4 5 6 7 8 9 10 ...
 $ stepsTaken        : int [1:307] 1 2 2 2 2 2 2 2 2 2 ...
 $ localCostMatrix   : crossdist [1:200, 1:200] 1.15 1.04 1.26 1.26 1.28 ...
  ..- attr(*, "method")= chr "Euclidean"
  ..- attr(*, "call")= language proxy::dist(x = x, y = y, method = dist.method)
 $ query             : num [1:200, 1] 0.1972 0.0905 0.307 0.3036 0.329 ...
 $ reference         : num [1:200, 1] -0.953 -0.861 -0.947 -0.918 -0.933 ...
 - attr(*, "class")= chr "dtw"


Now, we can plot the alignment.


Plotting with a two-way method

dtwPlotTwoWay(align)
 

Plotting with a density


dtwPlotDensity(align)



1 comment: