如何有效地计算多个时间序列的欧氏距离矩阵
How to efficiently calculate euclidean distance matrix for several timeseries
我有 6 个时间序列数据如下,即 t1、t2、t3、t4、t5 和 t6。
import numpy as np
series = np.array([
[0., 0, 1, 2, 1, 0, 1, 0, 0],
[0., 1, 2, 0, 0, 0, 0, 0, 0],
[1., 2, 0, 0, 0, 0, 0, 1, 1],
[0., 0, 1, 2, 1, 0, 1, 0, 0],
[0., 1, 2, 0, 0, 0, 0, 0, 0],
[1., 2, 0, 0, 0, 0, 0, 1, 1]])
我想从这 6 个时间序列创建一个欧氏距离矩阵,格式为(即 6*6,其中 x
表示相应的欧氏距离):
t1 t2 t3 t4 t5 t6
t1 0 x x x x x
t2 x 0 x x x x
t3 x x 0 x x x
t4 x x x 0 x x
t5 x x x x 0 x
t6 x x x x x 0
我目前正在手动构造这个矩阵,如下所示(在这个SO问题中:这种方法获得了最高的性能)。
例如,计算 t3 和 t6 之间的欧氏距离。
def eudis(v1, v2):
dist = [(a - b)**2 for a, b in zip(v1, v2)]
dist = math.sqrt(sum(dist))
return dist
eudis(t3, t6)
不过,我确信在 python 中可以有更简单且计算效率更高的方法来执行此操作。如果您有任何建议,请告诉我。
如果需要,我很乐意提供更多详细信息。
您根本不需要循环,因为两个数组之间的欧几里德距离只需计算差值的元素平方:
def euclidean_distance(v1, v2):
return np.sqrt(np.sum((v1 - v2)**2))
对于距离矩阵,你有 sklearn.metrics.pairwise.euclidean_distances
:
from sklearn.metrics.pairwise import euclidean_distances
euclidean_distances(a).round(2)
array([[0. , 2.83, 3.74, 0. , 2.83, 3.74],
[2.83, 0. , 2.83, 2.83, 0. , 2.83],
[3.74, 2.83, 0. , 3.74, 2.83, 0. ],
[0. , 2.83, 3.74, 0. , 2.83, 3.74],
[2.83, 0. , 2.83, 2.83, 0. , 2.83],
[3.74, 2.83, 0. , 3.74, 2.83, 0. ]])
np.allclose(
eudis(series[2], series[3]),
euclidean_distance(series[2], series[3])
)
# True
也可以用pdist
得到距离矩阵:
from scipy.spatial.distance import pdist, squareform
squareform(pdist(series))
与 and 解决方案的性能比较:
因此对于相对较小的数据集(最多约 20 个系列,每个系列 200 个元素)pdist
最快,对于较大的数据集 euclidean_disances
表现更好。 pure numpy
大部分速度较慢,并且可能无法为大型数据集分配中间数组。
使用 np.random.randint(0, 100, (n, 10*n)).astype('int16')
、numpy 1.17.4、scipy 1.4.1、sklearn 0.23.1、python 3.8.2、Win10 64 位进行测试。
您可以在一行中用简单的 numpy 创建一个距离矩阵,您不需要任何其他东西。
np.sqrt(((series[:,None,:] - series)**2).sum(axis=2))
我有 6 个时间序列数据如下,即 t1、t2、t3、t4、t5 和 t6。
import numpy as np
series = np.array([
[0., 0, 1, 2, 1, 0, 1, 0, 0],
[0., 1, 2, 0, 0, 0, 0, 0, 0],
[1., 2, 0, 0, 0, 0, 0, 1, 1],
[0., 0, 1, 2, 1, 0, 1, 0, 0],
[0., 1, 2, 0, 0, 0, 0, 0, 0],
[1., 2, 0, 0, 0, 0, 0, 1, 1]])
我想从这 6 个时间序列创建一个欧氏距离矩阵,格式为(即 6*6,其中 x
表示相应的欧氏距离):
t1 t2 t3 t4 t5 t6
t1 0 x x x x x
t2 x 0 x x x x
t3 x x 0 x x x
t4 x x x 0 x x
t5 x x x x 0 x
t6 x x x x x 0
我目前正在手动构造这个矩阵,如下所示(在这个SO问题中:
例如,计算 t3 和 t6 之间的欧氏距离。
def eudis(v1, v2):
dist = [(a - b)**2 for a, b in zip(v1, v2)]
dist = math.sqrt(sum(dist))
return dist
eudis(t3, t6)
不过,我确信在 python 中可以有更简单且计算效率更高的方法来执行此操作。如果您有任何建议,请告诉我。
如果需要,我很乐意提供更多详细信息。
您根本不需要循环,因为两个数组之间的欧几里德距离只需计算差值的元素平方:
def euclidean_distance(v1, v2):
return np.sqrt(np.sum((v1 - v2)**2))
对于距离矩阵,你有 sklearn.metrics.pairwise.euclidean_distances
:
from sklearn.metrics.pairwise import euclidean_distances
euclidean_distances(a).round(2)
array([[0. , 2.83, 3.74, 0. , 2.83, 3.74],
[2.83, 0. , 2.83, 2.83, 0. , 2.83],
[3.74, 2.83, 0. , 3.74, 2.83, 0. ],
[0. , 2.83, 3.74, 0. , 2.83, 3.74],
[2.83, 0. , 2.83, 2.83, 0. , 2.83],
[3.74, 2.83, 0. , 3.74, 2.83, 0. ]])
np.allclose(
eudis(series[2], series[3]),
euclidean_distance(series[2], series[3])
)
# True
也可以用pdist
得到距离矩阵:
from scipy.spatial.distance import pdist, squareform
squareform(pdist(series))
与
因此对于相对较小的数据集(最多约 20 个系列,每个系列 200 个元素)pdist
最快,对于较大的数据集 euclidean_disances
表现更好。 pure numpy
大部分速度较慢,并且可能无法为大型数据集分配中间数组。
使用 np.random.randint(0, 100, (n, 10*n)).astype('int16')
、numpy 1.17.4、scipy 1.4.1、sklearn 0.23.1、python 3.8.2、Win10 64 位进行测试。
您可以在一行中用简单的 numpy 创建一个距离矩阵,您不需要任何其他东西。
np.sqrt(((series[:,None,:] - series)**2).sum(axis=2))