不同的库具有不同的结果和性能

时间:2018-09-24 12:05:20

标签: python dtw

我正在比较DTW计算的库dtaidistancefastdtwcdtw。这是我的代码:

from fastdtw import fastdtw
from cdtw import pydtw
import fastdtw
import array
from timeit import default_timer as timer
from dtaidistance import dtw, dtw_visualisation as dtwvis

s1 = mySampleSequences[0] # first sample sequence consisting of 3000 samples
s2 = mySampleSequences[1] # second sample sequence consisting of 3000 samples

start = timer()
distance1 = dtw.distance(s1, s2)
end = timer()
start2 = timer()
distance2 = dtw.distance_fast(array.array('d',s1),array.array('d',s2))
end2 = timer()
start3 = timer()
distance3, path3 = fastdtw(s1,s2)
end3 = timer()
start4 = timer()
distance4 = pydtw.dtw(s1,s2).get_dist()
end4 = timer()

print("dtw.distance(x,y) time: "+ str(end - start))
print("dtw.distance(x,y) distance: "+str(distance1))
print("dtw.distance_fast(x,y) time: "+ str(end2 - start2))
print("dtw.distance_fast(x,y) distance: " + str(distance2))
print("fastdtw(x,y) time: "+ str(end3 - start3))
print("fastdtw(x,y) distance: " + str(distance3))
print("pydtw.dtw(x,y) time: "+ str(end4 - start4))
print("pydtw.dtw(x,y) distance: " + str(distance4))

这是我得到的输出:

  • dtw.distance(x,y)时间:22.16925272245262
  • dtw.distance(x,y)距离:1888.8583853746156
  • dtw.distance_fast(x,y)时间:0.3889036471839056
  • dtw.distance_fast(x,y)距离:1888.8583853746156
  • fastdtw(x,y)时间:0.23296659641047412
  • fastdtw(x,y)距离:27238.0
  • pydtw.dtw(x,y)时间:0.13706478039556558
  • pydtw.dtw(x,y)距离:17330.0

我的问题是:为什么我会有不同的表现和不同的距离?非常感谢您的评论。

//编辑:时间测量单位为秒。

2 个答案:

答案 0 :(得分:3)

在Felipe Mello的翔实答案之上(免责声明:此处DTAIDistance的作者),还有一些其他信息。

对于距离结果:

  • DTAIDistance仅使用欧几里得距离(或L2范数),这是硬编码的。选择该选项是为了加快C代码的执行速度(不调用函数)。 “快速”是指使用基于C的实现而不是纯Python版本,因此这两种方法给出的结果完全相同。
  • FastDTW是与DTW不同的算法。这是线性近似。 “快速”是指较低的复杂性。
  • cDTW。我对这个工具箱不是很熟悉,但是它似乎实现了L1规范。

对于速度结果:

通常,基于C的纯算法比纯Python的算法快100倍左右(在DTAIDistance中,这是distance()和distance_fast()之间的差异)。对于基于C的方法,差异主要是由于方法的灵活性。例如,传递自定义规范会减慢该方法的速度(更多函数调用)。同样,不同的方法具有不同的选项,这会导致算法中或多或少的switch语句。例如,DTAIDistance提供了许多方法来调整该方法,因为它更喜欢提早停止计算而不是进一步优化(也由Felipe Mello观察到)。此外,不同的方法存储不同数量的数据。 DTAIDistance距离方法不存储整个矩阵,也不提供线性空间复杂度(使用具有二次空间复杂度的warping_paths方法获得完整的矩阵)。通常,对于DTW,建议使用窗口来同时降低时间复杂度。

对于DTAIDistance,所有设计选择都考虑了时间序列聚类应用程序(distance_matrix_fast方法)。这是不允许自定义规范的另一个原因。 DTW代码必须是纯C语言,才能在C代码级别上支持并行化,并且具有最小的开销(它使用OpenMP)来计算序列之间的所有成对距离。

答案 1 :(得分:2)

编辑时间测量的单位是什么?我相信您将它们进行了比较,因为它们都位于同一单元中。 dtw.distance可能以毫秒为单位,而其他答案以毫秒为单位,并且您认为dtw.distance的执行速度较慢,而实际上却相反。

有两种方法可以测量两点之间的距离。它可以基于标准偏差或仅基于欧几里德距离。这是其中许多距离的list

其中一些可能比其他一些计算量更大,并且具有不同的含义。例如,快速dtw将所需的距离类型用作第三个输入,如其github

中所述
distance3, path3 = fastdtw(s1, s2, dist = euclidean)

速度差异的另一个原因是基础代码。其中一些使用纯python,而另一些使用C,可以轻松快100倍。加快距离的一种方法是设置最大距离阈值。如果算法意识到总距离将超过某个值,则会停止计算:

distance2 = dtw.distance_fast(array.array('d',s1),array.array('d',s2), max_dist = your_threshold)

同样重要的是要注意,有些阵列可能针对更长或更短的阵列进行了优化。查看下面的示例并在计算机上运行它,我发现不同的结果:

from cdtw import pydtw
from dtaidistance import dtw
from fastdtw import fastdtw
from scipy.spatial.distance import euclidean
s1=np.array([1,2,3,4],dtype=np.double)
s2=np.array([4,3,2,1],dtype=np.double)

%timeit dtw.distance_fast(s1, s2)
4.1 µs ± 28.6 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
%timeit d2 = pydtw.dtw(s1,s2,pydtw.Settings(step = 'p0sym', window = 'palival', param = 2.0, norm = False, compute_path = True)).get_dist()
45.6 µs ± 3.39 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
%timeit d3,_=fastdtw(s1, s2, dist=euclidean)
901 µs ± 9.95 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

fastdtwdtaidistance lib要慢219倍,比cdtw要慢20倍