简介

在上一篇文章里我们介绍了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整型会导致计算错误,就像下图:

dtw代码python python dtw库_动态规划


会发现左上角出现了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.index1ds.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表示了图的模式,一般有twowaythreeway两种模式,下面详解,offset=-2可以理解为两根线之间的分离程度,为了方便看清可以设的大一些。

上面代码生成的图片如下:

dtw代码python python dtw库_动态规划_02


在这幅图中可以看到头和尾进行了严格的匹配,图中黑线表示query序列,蓝线代表template序列,虚线代表点的匹配,我们可以发现在’asymmetric’(step_pattern)模式下,虽然头和尾匹配好了,但是中间的一些点被忽略了。它是什么样的匹配形式呢,我们可以打印出来看一看:

print(asymmetric)
asymmetric.plot()

dtw代码python python dtw库_dtw代码python_03


dtw代码python python dtw库_python_04


老实说,我也看不太懂,不过看不懂没关系啊,我们可以对比一下,是吧。

ds = dtw(y, x,keep_internals=True, step_pattern=symmetric1)
ds.plot(type="twoway",offset=-2)

把step_pattern换成symmetric1,作图如下:

dtw代码python python dtw库_动态规划_05


我们可以发现图中的点这次得到了一一对应,看看symmetric1的模式图:

print(symmetric1)
symmetric1.plot()

dtw代码python python dtw库_数据建模_06


显然这个模式和之前的asy不对称模式相比显得更加灵活(有上,左下,下三个方向),这应该就是点能一一对应的原因吧。

同时我们来看看另一种图:

ds.plot(type="threeway",offset=-2)

dtw代码python python dtw库_dtw代码python_07


在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 python dtw库_python_08


可以发现它完成了局部匹配。

总结

本文主要介绍了dtw-python库的作图功能,其中窗口定义,距离函数定义这些还没有涉及,希望读者能够自行探索补充,这个库除了int型计算错误的重大bug之外,其他还是比较完善的。至此,对dtw的探索暂时告一段落,欢迎读者留言讨论。