在上一篇文章里我们介绍了dtw库的使用,但其限制太多,不够灵活,且作图不够方便,因此我们来介绍一个更加复杂的库----dtw-python。它是R语言中dtw实现的python版本,基本的API是对应的,它的优势在于能够自定义点的匹配模式,约束条件,和滑动窗口。同时提供方便的作图和快速的计算(C语言的内核),官方文档点击这里。
本次两条时间序列依然选择上一篇文章中的序列:
import numpy as np
from dtw import *
x=[2., 0., 1., 1., 2., 4., 2., 1., 2., 0.]
y=[1., 1., 2., 4., 2., 1., 2., 0.]
需要注意的是这个库里作图默认用的是浮点数,所以这里我们用float类型初始化,如果用int整型会导致计算错误,就像下图:
会发现左上角出现了1e18的y轴百分比,其中的黑线变成了长长的平直线。
我调试了好久才发现是int和float的问题。
接下来具体讲解计算和作图:
ds = dtw(y, x,keep_internals=True, step_pattern=asymmetric)
ds.plot(type="twoway",offset=-2)
第一行代码进行了计算生成了一个dtw对象,可以通过对象的各个属性获得内容,比如ds.distance显示计算出的最短距离,ds.reference显示的是模板序列的值,ds.query显示的是查询序列的值,ds.index1和ds.index2分别显示各自序列的对应顺序,这里不赘述了。我们在这里只需要知道我们的y是query(查询)序列,x是template(模板)序列,我们把y去匹配x。
再来讲解括号里的参数,x,y不用说了,为了全面,我们补上其他的参数:
dtw.dtw(x, y=None, dist_method='euclidean', step_pattern='symmetric2', window_type=None, window_args={}, keep_internals=False, distance_only=False, open_end=False, open_begin=False)
dist_method 定义你用的距离方法,默认为’euclidean’,即欧几里得距离。
keep_internals=True保存内部的信息包含距离矩阵之类的,一般我们把它设为True。
step_pattern定义了点之间的匹配模式,有好几种,具体查看官网。
window_type表示全局条件约束,也有几种模式,同查看官网。
distance_only如果设置为True,会加速计算,只计算距离,忽略匹配函数。
open_end和open_begin设为True表示无拘束的匹配,即完全的部分匹配,默认是全局匹配,就是严格对应头和尾。
第二行代码是作图代码,其中的type表示了图的模式,一般有twoway和threeway两种模式,下面详解,offset=-2可以理解为两根线之间的分离程度,为了方便看清可以设的大一些。
上面代码生成的图片如下:
在这幅图中可以看到头和尾进行了严格的匹配,图中黑线表示query序列,蓝线代表template序列,虚线代表点的匹配,我们可以发现在’asymmetric’(step_pattern)模式下,虽然头和尾匹配好了,但是中间的一些点被忽略了。它是什么样的匹配形式呢,我们可以打印出来看一看:
print(asymmetric)
asymmetric.plot()
老实说,我也看不太懂,不过看不懂没关系啊,我们可以对比一下,是吧。
ds = dtw(y, x,keep_internals=True, step_pattern=symmetric1)
ds.plot(type="twoway",offset=-2)
把step_pattern换成symmetric1,作图如下:
我们可以发现图中的点这次得到了一一对应,看看symmetric1的模式图:
print(symmetric1)
symmetric1.plot()
显然这个模式和之前的asy不对称模式相比显得更加灵活(有上,左下,下三个方向),这应该就是点能一一对应的原因吧。
同时我们来看看另一种图:
ds.plot(type="threeway",offset=-2)
在threeway模式下画出的图和我们上一篇文章的图就很相似了,可以看到从纵轴从第二个点开始就一一匹配了。
既然asymmetric不能全局匹配,那么它能不能部分匹配呢?其实是可以的,用我们之前说明的open_end和open_begin参数:
ds = dtw(y, x,keep_internals=True, step_pattern=asymmetric,open_begin=True,open_end=False)
ds.plot(type="twoway",offset=-2)
因为x序列实际上是y序列的除去开头的序列,所以我们把open_begin设为True,这也就意味着我们放开了头的限制,可以使开头任意匹配,在这种情况下作图:
可以发现它完成了局部匹配。
本文主要介绍了dtw-python库的作图功能,其中窗口定义,距离函数定义这些还没有涉及,希望读者能够自行探索补充,这个库除了int型计算错误的重大bug之外,其他还是比较完善的。至此,对dtw的探索暂时告一段落,欢迎读者留言讨论。
1.https://dynamictimewarping.github.io/py-api/html/api/dtw.dtw.html#dtw.dtw
2.https://dynamictimewarping.github.io/py-api/html/api/dtw.StepPattern.html#dtw.StepPattern
3.https://dynamictimewarping.github.io/
4.https://www.jstatsoft.org/article/view/v031i07