slaypni / fastdtw

A Python implementation of FastDTW
MIT License
774 stars 122 forks source link

Incorrect DTW path for Euclidean distance? #54

Closed weidenka closed 2 years ago

weidenka commented 2 years ago

I'm struggling understanding a very simple example. I boiled it down to the following test:

from fastdtw import fastdtw
from scipy.spatial.distance import euclidean, sqeuclidean
def test_euclidean_distance():
    q=[0,1,2,3,4,5,6,7,8]
    r=[1,2,3,4,5,6,7,8,0]
    distA, pathA = fastdtw(q, r, radius=2, dist=euclidean)
    distB, pathB = fastdtw(q, r, radius=2, dist=sqeuclidean)
    assert all([a==b for a,b in zip(pathA, pathB)])
    assert distA*distA == distB   # 9*9 == 65 fails

Since the paths are the same I would expect to that also the distances are the same. The correct Euclidean distance should be sqrt(65) (only first and last elements of the input vectors contribute). Since it is 9 it looks like the Manhattan distance is used instead of the Euclidean distance.

I have the feeling that I miss something simple. But could someone give me a hint?

torkos commented 2 years ago

The path is the same for both dtws. When you look at the errors, you can see they come from the first element q[0]=0, p[0]=1, and the last element q[8]=8, p[8]=0.

The euclidean distance is abs(p[0]-q[0]) + abs(p[8]-q[8]) = 1 + 8 = 9 The square euclidean is (p[0]-q[0])(p[0]-q[0]) + (p[8]-q[8])(p[8]-q[8]) = 1 + 64 = 65

So the outputs are correct. The second assert is wrong. The second distance value is the sum of the squares of each individual euclidean element, not the square of the sum of euclideans.

weidenka commented 2 years ago

I agree