不同库的不同结果和性能
Different results and performances with different libraries
我正在比较用于 DTW 计算的库 dtaidistance, fastdtw and cdtw。这是我的代码:
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
我的问题是:为什么我会得到不同的性能和不同的距离?非常感谢您的意见。
//编辑:时间测量的单位是秒。
编辑: 时间测量的单位是什么?我相信您将它们进行了比较,因为它们都在同一个单元中。例如,可能 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)
fastdtw
比 dtaidistance
lib 慢 219 倍,比 cdtw
慢 20 倍
在 Felipe Mello 的信息性回答之上的一些附加信息(免责声明:此处为 DTAIDistance 的作者)。
对于距离结果:
- DTAIDistance 仅使用欧氏距离(或 L2 范数),这是硬编码的。做出此选择是为了加快 C 代码的执行速度(无函数调用)。 'fast' 指的是使用基于 C 的实现而不是纯 Python 版本,因此这两种方法给出完全相同的结果。
- FastDTW 是一种不同于 DTW 的算法。它是一个线性近似值。 'fast' 指的是较低的复杂度。
- cDTW。我对这个工具箱不是很熟悉,但它似乎实现了 L1 规范。
对于速度结果:
一般来说,纯基于 C 的算法比纯 Python 算法快约 100 倍(在 DTAIDistance 中,这是 distance() 和 distance_fast() 之间的区别)。对于基于 C 的方法,差异主要是由于方法的灵活性。例如,传递自定义规范会减慢方法(更多函数调用)。此外,不同的方法有不同的选项,这会导致算法中或多或少的 switch 语句。例如,DTAIDistance 提供了相当多的选项来调整方法,因为它更喜欢提前停止计算而不是进一步优化(Felipe Mello 也观察到)。此外,不同的方法存储不同数量的数据。 DTAIDistance 距离方法不存储整个矩阵也提供线性 space 复杂度(完整矩阵是使用具有二次 space 复杂度的 warping_paths 方法获得的)。一般来说,对于 DTW,建议使用 window 来减少时间复杂度。
对于 DTAIDistance,所有设计选择都是在考虑时间序列聚类应用程序的情况下做出的(distance_matrix_fast 方法)。这是不允许自定义规范的另一个原因。
DTW 代码需要是纯 C 代码以支持 C 代码级别的并行化,并且具有最小的开销(它使用 OpenMP)来计算系列之间的所有成对距离。
我正在比较用于 DTW 计算的库 dtaidistance, fastdtw and cdtw。这是我的代码:
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
我的问题是:为什么我会得到不同的性能和不同的距离?非常感谢您的意见。
//编辑:时间测量的单位是秒。
编辑: 时间测量的单位是什么?我相信您将它们进行了比较,因为它们都在同一个单元中。例如,可能 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)
fastdtw
比 dtaidistance
lib 慢 219 倍,比 cdtw
在 Felipe Mello 的信息性回答之上的一些附加信息(免责声明:此处为 DTAIDistance 的作者)。
对于距离结果:
- DTAIDistance 仅使用欧氏距离(或 L2 范数),这是硬编码的。做出此选择是为了加快 C 代码的执行速度(无函数调用)。 'fast' 指的是使用基于 C 的实现而不是纯 Python 版本,因此这两种方法给出完全相同的结果。
- FastDTW 是一种不同于 DTW 的算法。它是一个线性近似值。 'fast' 指的是较低的复杂度。
- cDTW。我对这个工具箱不是很熟悉,但它似乎实现了 L1 规范。
对于速度结果:
一般来说,纯基于 C 的算法比纯 Python 算法快约 100 倍(在 DTAIDistance 中,这是 distance() 和 distance_fast() 之间的区别)。对于基于 C 的方法,差异主要是由于方法的灵活性。例如,传递自定义规范会减慢方法(更多函数调用)。此外,不同的方法有不同的选项,这会导致算法中或多或少的 switch 语句。例如,DTAIDistance 提供了相当多的选项来调整方法,因为它更喜欢提前停止计算而不是进一步优化(Felipe Mello 也观察到)。此外,不同的方法存储不同数量的数据。 DTAIDistance 距离方法不存储整个矩阵也提供线性 space 复杂度(完整矩阵是使用具有二次 space 复杂度的 warping_paths 方法获得的)。一般来说,对于 DTW,建议使用 window 来减少时间复杂度。
对于 DTAIDistance,所有设计选择都是在考虑时间序列聚类应用程序的情况下做出的(distance_matrix_fast 方法)。这是不允许自定义规范的另一个原因。 DTW 代码需要是纯 C 代码以支持 C 代码级别的并行化,并且具有最小的开销(它使用 OpenMP)来计算系列之间的所有成对距离。