如何获取最小化两序列欧氏距离的X轴偏移?DTW结果解析
问题:寻找序列间最小欧氏距离的X轴偏移量及DTW结果解读
需求背景
有两个非完全相同的序列,其中一个滞后于另一个,需要找到能最小化二者欧氏距离的X轴偏移量,并解读DTW计算结果中的数值含义。
数据示例
df = pd.DataFrame({'a':[1,4,5,10,9,3,2,6,8,4], 'b': [1,7,3,4,1,10,5,4,7,4]})
序列可视化说明:两个序列的折线图,显示出明显的时间错位特征。
当前实现及疑问
已使用Python的DTW模块计算得到最小距离,但不确定如何获取偏移量,同时疑惑成本矩阵顶部的“15”是偏移后序列的最小距离,还是能得到最小距离的偏移值。
相关代码:
from dtw import dtw,accelerated_dtw import numpy as np import matplotlib.pyplot as plt d1 = df['a'].values d2 = df['b'].values d, cost_matrix, acc_cost_matrix, path = accelerated_dtw(d1,d2, dist='euclidean') plt.imshow(acc_cost_matrix.T, origin='lower', cmap='gray', interpolation='nearest') plt.plot(path[0], path[1], 'w') plt.xlabel('a') plt.ylabel('b') plt.title(f'DTW Minimum Path with minimum distance: {np.round(d,2)}') plt.show()
DTW成本矩阵可视化说明:灰度矩阵显示累积成本分布,白色路径为DTW的最优匹配路径,顶部标注的“15”为最小距离值。
解答
1. 成本矩阵顶部“15”的含义
这个数值是DTW计算出的最小累计距离,是两个序列经过弹性时间规整(允许局部多对多索引匹配)后的总欧氏距离之和,不是偏移量。
2. 获取最小欧氏距离的X轴偏移量
根据你的需求(寻找单一固定的X轴偏移量,即序列整体滞后/超前),分两种场景处理:
场景1:序列为刚性错位(无局部时间扭曲)
优先使用滑动窗口计算固定偏移的欧氏距离,这种方法直接针对“单一偏移量”需求,结果更准确:
import pandas as pd import numpy as np import matplotlib.pyplot as plt df = pd.DataFrame({'a':[1,4,5,10,9,3,2,6,8,4], 'b': [1,7,3,4,1,10,5,4,7,4]}) d1 = df['a'].values d2 = df['b'].values max_offset = len(d1) - 1 distances = [] offsets = [] # 遍历所有可能的偏移量(正数:a向右偏移;负数:b向右偏移) for k in range(-max_offset, max_offset + 1): if k >= 0: # a偏移k位,取d1[k:]与d2[:len(d1)-k]匹配 seq1, seq2 = d1[k:], d2[:len(d1)-k] else: # b偏移(-k)位,取d1[:len(d1)+k]与d2[-k:]匹配 seq1, seq2 = d1[:len(d1)+k], d2[-k:] if not len(seq1): continue # 计算欧氏距离 dist = np.linalg.norm(seq1 - seq2) distances.append(dist) offsets.append(k) # 找到最小距离对应的偏移量 min_idx = np.argmin(distances) best_offset = offsets[min_idx] min_dist = distances[min_idx] print(f"最小欧氏距离对应的X轴偏移量:{best_offset}") print(f"最小欧氏距离值:{np.round(min_dist, 2)}") # 可视化偏移匹配结果 plt.figure(figsize=(10,5)) if best_offset >= 0: plt.plot(np.arange(best_offset, len(d1)), d1[best_offset:], label='a (偏移后)') plt.plot(np.arange(len(seq2)), seq2, label='b') else: plt.plot(np.arange(len(seq1)), seq1, label='a') plt.plot(np.arange(-best_offset, len(d2)), d2[-best_offset:], label='b (偏移后)') plt.legend() plt.title(f"序列刚性偏移匹配(偏移量:{best_offset},欧氏距离:{np.round(min_dist,2)})") plt.show()
场景2:序列存在局部时间扭曲(需弹性匹配)
如果序列有局部时间变形,可从DTW的匹配路径中提取最频繁出现的偏移量(因为DTW路径是多对多索引匹配,取众数代表整体偏移趋势):
from scipy.stats import mode # 从DTW路径计算每个匹配点的偏移量(d2索引 - d1索引) offsets_dtw = [p[1] - p[0] for p in zip(path[0], path[1])] # 取众数作为整体偏移量 best_offset_dtw = mode(offsets_dtw)[0][0] print(f"DTW路径中最常见的偏移量:{best_offset_dtw}")
内容的提问来源于stack exchange,提问作者finstats
相关产品推荐
相关产品推荐

