2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Pythonにおける動的時間伸縮法(DTW: Dynamic Time Warping)のサンプルコード

Last updated at Posted at 2024-12-01

はじめに

動的時間伸縮法(DTW: Dynamic Time Warping)とは2つの波形データの類似度を測定する手法です。

本記事では、Pythonで fastdtw というライブラリを用いて、DTW を簡易的に計算します。

DTW のアルゴリズムについては次の記事で解説しています。

また、ライブラリを用いずに DTW の実装する方法については次の記事にコードを載せています。

サンプルコード

環境構築

以降にあるコードを実行するためには、 fastdtw ライブラリをインストールする必要があります。

仮想環境の構築

Python 環境を特に気にしない場合は 次に 進んでください。

お手持ちの環境を変更したくない場合は、ターミナルで次のコマンドを実行して仮想環境を用意しましょう。

python コマンドが通らない場合は、 python3py をお試しください。

  • Windows の場合

    仮想環境の作成と有効化
    python -m venv .venv
    .venv/Script/actvate
    
  • Mac / Linux の場合

    仮想環境の作成と有効化
    python -m venv .venv
    . .venv/bin/activate
    

    もしくは

    仮想環境の作成と有効化
    python -m venv .venv
    source .venv/bin/activate
    

次のように、ターミナルに仮想環境名(上記のコマンドの場合 .venv )が表示されるようになります。

仮想環境が有効になっているかの確認
(.venv) $

ライブラリのインストール

ターミナルで次のコマンドを実行してライブラリをインストールします。

ライブラリのインストール
pip install fastdtw scipy numpy matplotlib japanize-matplotlib
ライブラリ 目的
fastdtwscipynumpy DTWを簡易的に実装するため
matplotlib 図を作成するため
japanize-matplotlib 図で日本語を表示させるため

なお、VSCode でノートブック形式( .ipynb )を実行する場合は ipykernel ライブラリも必要です。

ライブラリのインストール
pip install ipykernel

波形データの用意

本記事では疑似的なデータとして、前回の記事 と同様の波形を用意します。

波形データの用意
Q = [3, 4, 3, 3, 2, 3]
S = [1, 6, 4, 4, 1, 5]

次のコードで各波形データの形状を確認できます。

波形データの確認
from matplotlib import pyplot as plt
import japanize_matplotlib

# 2つの時系列データをプロットする
plt.plot(Q, label='Q')
plt.plot(S, label='S')

# 凡例の表示
plt.legend()

# グラフタイトル
plt.title('波形データ')

# グラフを表示する
plt.show()

image.png

DTW距離の計算

次のコードで DTW 距離を計算します。

DTW距離の計算
import numpy as np
from scipy.spatial.distance import euclidean
from fastdtw import fastdtw

# データの整形
Q = np.array(Q).reshape(-1, 1)
S = np.array(S).reshape(-1, 1)

dist, path = fastdtw(Q, S, dist=euclidean)

print(f"DTW距離: {dist}")
print(f"各点のパス:{path}")

次が出力されると成功です。

TW距離: 9.0
各点のパス:[(0, 0), (1, 1), (1, 2), (1, 3), (2, 3), (3, 3), (4, 4), (5, 5)]

次のコードでデータポイント間の対応関係を確認できます。

DTW の結果をプロットする
# 2つの時系列データをプロットする
plt.plot(Q, label='Q')
plt.plot(S, label='S')

# データポイントの対応関係をプロットする
for index_Q, index_S in path:
  plt.plot([index_Q, index_S], [Q[index_Q], S[index_S]], color='gray', linestyle='dotted', linewidth=1)

# プロット
plt.legend()
plt.title(f'波形データ(DTW距離={dist}')
plt.show()

上記のコードを実行すると、次のグラフがプロットされます。

image.png

$(横軸, 縦軸) = (1, 4), (2, 4), (2, 3), (3, 4)$ の点にご注目ください。

$(1, 4), (2, 4)$ 間と $(2, 3), (3, 4)$ 間のパスについて、不自然な対応となっています。

この原因として fastdtw は計算量を抑えるために近似的な処理をしていることが考えられます。

参考

2
3
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?