You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何获取最小化两序列欧氏距离的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 05:40:32