python - 使用 numpy 或 cython 进行高效的成对 DTW 计算

标签 python numpy cython joblib

我正在尝试计算 numpy 数组中包含的多个时间序列之间的成对距离。请看下面的代码

print(type(sales))
print(sales.shape)

<class 'numpy.ndarray'>
(687, 157)

因此,sales 包含 687 个长度为 157 的时间序列。使用 pdist 计算时间序列之间的 DTW 距离。

import fastdtw
import scipy.spatial.distance as sd

def my_fastdtw(sales1, sales2):
    return fastdtw.fastdtw(sales1,sales2)[0]

distance_matrix = sd.pdist(sales, my_fastdtw)

---编辑:尝试不使用 pdist()-----

distance_matrix = []
m = len(sales)    
for i in range(0, m - 1):
    for j in range(i + 1, m):
        distance_matrix.append(fastdtw.fastdtw(sales[i], sales[j]))

---编辑:并行化内部 for 循环-----

from joblib import Parallel, delayed
import multiprocessing
import fastdtw

num_cores = multiprocessing.cpu_count() - 1
N = 687

def my_fastdtw(sales1, sales2):
    return fastdtw.fastdtw(sales1,sales2)[0]

results = [[] for i in range(N)]
for i in range(0, N- 1):
    results[i] = Parallel(n_jobs=num_cores)(delayed(my_fastdtw) (sales[i],sales[j])  for j in range(i + 1, N) )

所有的方法都很慢。并行方法大约需要 12 分钟。有人可以建议一种有效的方法吗?

---编辑:按照下面答案中提到的步骤---

这是 lib 文件夹的样子:

VirtualBox:~/anaconda3/lib/python3.6/site-packages/fastdtw-0.3.2-py3.6- linux-x86_64.egg/fastdtw$ ls
_fastdtw.cpython-36m-x86_64-linux-gnu.so  fastdtw.py   __pycache__
_fastdtw.py                               __init__.py

所以,那里有一个 cython 版本的 fastdtw。安装时,我没有收到任何错误。即使现在,当我在程序执行期间按下 CTRL-C 时,我也可以看到正在使用纯 python 版本(fastdtw.py):

/home/vishal/anaconda3/lib/python3.6/site-packages/fastdtw/fastdtw.py in fastdtw(x, y, radius, dist)

/home/vishal/anaconda3/lib/python3.6/site-packages/fastdtw/fastdtw.py in __fastdtw(x, y, radius, dist)

代码和以前一样慢。

最佳答案

长话短说

您的 fastdtw 无法安装快速的 cpp 版本并静静地退回到纯 python 版本,这很慢。

您需要修复 fastdtw 软件包的安装。


整个计算是在 fastdtw 中完成的,所以你无法从外部真正加速它。并行化和 Python 并不是一件容易的事(现在?)。

fastdtw 文档说它需要大约 O(n) 操作来进行比较,因此对于您的整个测试集,它需要大约 的数量级>10^9 操作,如果用 C 语言编程,应该在几秒钟内完成。您看到的性能远不及它。

如果我们看一下 code of fastdtw我们看到,有两个版本:通过 cython 快速导入的 cython/cpp 版本和缓慢的后退纯 python 版本。如果未预设快速版本,则静默使用慢速 python 版本。

所以运行你的计算,用 Ctr+C 中断它,你会看到,你在 python 代码的某个地方。你也可以去你的lib文件夹看看,里面只有纯python版本。

因此您安装快速 fastdtw 版本失败。实际上,我认为 wheel-package 是拙劣的,至少对于我的版本来说,只有纯 python 代码存在。

要做什么?

  1. 获取源代码,例如通过 git clone https://github.com/slaypni/fastdtw
  2. 进入 fstdtw 文件夹并运行 python setup.py build
  3. 注意错误。我的是

fatal error: numpy/npy_math.h: No such file or directory

  1. 修复它。

对我来说,解决方法是更改​​ setup.py 中的以下行:

import numpy # THIS ADDED
extensions = [Extension(
        'fastdtw._fastdtw',
        [os.path.join('fastdtw', '_fastdtw' + ext)],
        language="c++",
        include_dirs=[numpy.get_include()], # AND ADDED numpy.get_include()
        libraries=["stdc++"]
    )]
  1. 重复 3.+4。直到成功
  2. 运行python setup.py install

现在您的程序应该快大约 100 倍。 `

关于python - 使用 numpy 或 cython 进行高效的成对 DTW 计算,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44994866/

相关文章:

python - 在 python 中连续检查具有许多正则表达式的字符串时缩进太多

python - 如何在字符串中添加 X 个空格

python - 在 buildozer 中编译 Cython 文件时出错

python - 导入 Cython 模块时出现 undefined symbol 错误

python - 使用 getopt() 获取从命令行传递的值

python - 如何用 Pandas 划分两个不同形状的数据框?

python - Theano共享变量更新导致 `ValueError: length not known`

python - 使用 LAPACK 例程的 python 库的理论时间复杂度

python - 返回 Cython 数组

python - 具有相同类型属性的类的类型注释?