Search code examples
pythonarraysscipydtw

Error in calculating Dynamic Time Warping


I am using this github codes (https://github.com/nageshsinghc4/-Dynamic-Time-Warping-DTW-/blob/main/Dynamic_Time_Warping(DTW).ipynb) to calculate Dynamic Time Warping. However, when run dtw_distance, warp_path = fastdtw(x, y, dist=euclidean), I get an error that "ValueError: Input vector should be 1-D.". I have same problem with this github codes (https://github.com/ElsevierSoftwareX/SOFTX-D-22-00246) too.

Here is the codes,

import pandas as pd
import numpy as np

# Plotting Packages
import matplotlib.pyplot as plt
import seaborn as sbn

import matplotlib as mpl
mpl.rcParams['figure.dpi'] = 150
savefig_options = dict(format="png", dpi=150, bbox_inches="tight")

# Computation packages
from scipy.spatial.distance import euclidean
from fastdtw import fastdtw

def compute_euclidean_distance_matrix(x, y) -> np.array:
    """Calculate distance matrix
    This method calcualtes the pairwise Euclidean distance between two sequences.
    The sequences can have different lengths.
    """
    dist = np.zeros((len(y), len(x)))
    for i in range(len(y)):
        for j in range(len(x)):
            dist[i,j] = (x[j]-y[i])**2
    return dist


def compute_accumulated_cost_matrix(x, y) -> np.array:
    """Compute accumulated cost matrix for warp path using Euclidean distance
    """
    distances = compute_euclidean_distance_matrix(x, y)

    # Initialization
    cost = np.zeros((len(y), len(x)))
    cost[0,0] = distances[0,0]
    
    for i in range(1, len(y)):
        cost[i, 0] = distances[i, 0] + cost[i-1, 0]  
        
    for j in range(1, len(x)):
        cost[0, j] = distances[0, j] + cost[0, j-1]  

    # Accumulated warp path cost
    for i in range(1, len(y)):
        for j in range(1, len(x)):
            cost[i, j] = min(
                cost[i-1, j],    # insertion
                cost[i, j-1],    # deletion
                cost[i-1, j-1]   # match
            ) + distances[i, j] 
            
    return cost



# Create two sequences
x = [7, 1, 2, 5, 9]
y = [1, 8, 0, 4, 4, 2, 0]
dtw_distance, warp_path = fastdtw(x, y, dist=euclidean)
cost_matrix = compute_accumulated_cost_matrix(x, y)

When I run the code, I get the following error that, ValueError: Input vector should be 1-D.


Solution

  • There's a conflict here between what SciPy is expecting and what FastDTW is expecting.

    FastDTW is expecting to compare one element at a time. SciPy is expecting to get an entire vector at once.

    Here's what FastDTW says about the dist argument. (Source.)

            dist : function or int
                The method for calculating the distance between x[i] and y[j]. If
                dist is an int of value p > 0, then the p-norm will be used. If
                dist is a function then dist(x[i], y[j]) will be used. If dist is
                None then abs(x[i] - y[j]) will be used.
    

    Here's what SciPy says about the euclidean function:

    Computes the Euclidean distance between two 1-D arrays.

    The FastDTW documentation I just quoted gives you a way to solve this. A p-norm with p=2 is equivalent to the Euclidean norm. (Source.)

    Therefore, the simplest way to solve this problem is to provide dist=2.

    dtw_distance, warp_path = fastdtw.fastdtw(x, y, dist=2)