web-dev-qa-db-ja.com

numpyまたはcythonを使用した効率的なペアワイズDTW計算

Numpy配列に含まれる複数の時系列間のペアワイズ距離を計算しようとしています。以下のコードをご覧ください

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

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

したがって、salesには長さ157の687時系列が含まれます。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
_

そのため、そこにはfastdtwのcythonバージョンがあります。インストール中にエラーは発生しませんでした。今でも、プログラムの実行中に_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)
_

コードは以前と同じように遅いままです。

12
user1274878

TL; DR

あなたのfastdtwは、高速のcpp-versionをインストールするために失敗し、遅い純粋なpythonバージョンにサイレントにフォールバックします。

fastdtw-パッケージのインストールを修正する必要があります。


計算全体はfastdtwで行われるため、外部から実際に高速化することはできません。そして、並列化とpythonはそれほど簡単なことではありません(まだ?)。

fastdtwのドキュメントには、比較のためにO(n)操作が必要であると記載されているため、テストセット全体で、10^9操作の桁違いが必要になります。たとえば、Cでプログラムされている場合、約数秒で実行されます。表示されるパフォーマンスは、それに近いものではありません。

code of fastdtw を見ると、2つのバージョンがあることがわかります。高速でcython経由でインポートされるcython/cpp-versionと、低速のフォールバックpure-pythonです。 -バージョン。高速バージョンが事前設定されていない場合、低速pythonバージョンがサイレントに使用されます。

したがって、計算を実行し、Ctr+Cで中断すると、Pythonコードのどこかにいることがわかります。 lib-folderに移動して、内部に純粋なPythonバージョンしかないことを確認することもできます。

そのため、高速fastdtwバージョンのインストールは失敗しました。実際、wheel-packageは失敗していると思います。少なくとも私のバージョンでは、純粋なpythonコードしか存在しません。

何をすべきか?

  1. ソースコードを取得します。例: git clone https://github.com/slaypni/fastdtw経由
  2. fstdtwフォルダーに移動し、python setup.py buildを実行します
  3. エラーに注意してください。私のは

致命的なエラー:numpy/npy_math.h:そのようなファイルまたはディレクトリはありません

  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倍高速になるはずです。 `

6
ead

正直なところ、fastdtwはまったく速くありません

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倍遅い

変更を検討してください。 dtaidistancegitは次のとおりです。

https://github.com/wannesm/dtaidistance

インストールするには、次のようにします。

pip install dtaidistance
4
Felipe Mello