当前位置: 首页 > article >正文

从动态规划到DTW:一个Python可视化教程,带你亲手画出时间规整路径图

从动态规划到DTW一个Python可视化教程带你亲手画出时间规整路径图在信号处理和机器学习领域时间序列的相似性比较是一个基础但极具挑战性的问题。想象一下当你需要比较两段语音、心电图或股票走势时简单的逐点对比往往会得到反直觉的结果——这正是动态时间规整(DTW)算法大显身手的地方。传统欧氏距离在处理时间序列时有个致命弱点它要求两个序列必须严格对齐。但现实中相似的波形往往存在时间轴上的非线性变形。比如两个人以不同语速说同一个单词或者同一首歌曲的快慢版本。DTW通过动态规划的思想巧妙地解决了这个问题。本文将带你用Python的Matplotlib库从零开始可视化DTW的核心计算过程。不同于直接调用现成库的黑箱操作我们会一步步构建累积距离矩阵动态展示最优路径的搜索过程最终绘制出直观的时间规整对齐图。这种可视化推导的方式能让你真正理解DTW如何实现时间轴的弹性匹配。1. 准备工作与环境配置首先确保你的Python环境已安装必要的科学计算库。推荐使用Anaconda发行版它已经集成了我们所需的大部分工具conda install numpy matplotlib为了更直观地展示动态过程我们还会用到Matplotlib的动画功能。以下是基础导入语句import numpy as np import matplotlib.pyplot as plt from matplotlib.animation import FuncAnimation from IPython.display import HTML让我们创建两个具有时间变形关系的示例序列。这里构造一个正弦波和一个经过非线性拉伸的相同波形t np.linspace(0, 10, 100) seq1 np.sin(t) # 原始正弦波 # 创建非线性变形的时间轴 warped_time np.sqrt(t) * 3 seq2 np.sin(warped_time) # 变形后的正弦波 plt.figure(figsize(12,4)) plt.plot(t, seq1, label原始序列) plt.plot(t, seq2, label变形序列) plt.legend() plt.show()这个简单的例子展示了时间规整问题的本质——两个序列形态相似但在时间轴上存在非线性对应关系。直接计算欧氏距离会得到很大的数值尽管人眼能明显看出它们的相似性。2. DTW核心算法解析DTW的核心思想是通过构建累积距离矩阵寻找两个序列间的最优匹配路径。让我们分解这个过程的每一步。2.1 构建局部距离矩阵首先计算两个序列所有点对之间的局部距离。通常使用欧氏距离def compute_local_dist(seq1, seq2): return np.array([[abs(x - y) for y in seq2] for x in seq1]) local_dist compute_local_dist(seq1, seq2)这个n×m矩阵n和m是两个序列的长度中的每个元素代表对应点对的局部不相似度。我们可以用热图直观展示plt.figure(figsize(8,6)) plt.imshow(local_dist, originlower, cmapviridis) plt.colorbar(label局部距离) plt.xlabel(序列2索引) plt.ylabel(序列1索引) plt.title(局部距离矩阵) plt.show()2.2 累积距离矩阵的动态构建DTW的精华在于通过动态规划逐步构建累积距离矩阵。递推公式为γ(i,j) local_dist(i,j) min(γ(i-1,j), γ(i,j-1), γ(i-1,j-1))让我们用动画展示这个构建过程def init(): im.set_data(np.zeros_like(local_dist)) return [im] def update(frame): i, j frame if i 0 and j 0: gamma[i,j] local_dist[i,j] elif i 0: gamma[i,j] local_dist[i,j] gamma[i,j-1] elif j 0: gamma[i,j] local_dist[i,j] gamma[i-1,j] else: gamma[i,j] local_dist[i,j] min(gamma[i-1,j], gamma[i,j-1], gamma[i-1,j-1]) im.set_array(gamma) return [im] gamma np.zeros_like(local_dist) fig, ax plt.subplots(figsize(8,6)) im ax.imshow(gamma, originlower, cmapviridis, vmaxlocal_dist.max()*10) plt.colorbar(im, label累积距离) plt.xlabel(序列2索引) plt.ylabel(序列1索引) plt.title(累积距离矩阵构建过程) frames [(i,j) for i in range(len(seq1)) for j in range(len(seq2))] ani FuncAnimation(fig, update, framesframes, init_funcinit, blitTrue, interval50) HTML(ani.to_jshtml())这段动画会逐步填充累积距离矩阵你可以清晰地看到最小值路径是如何形成的。矩阵右下角的值就是两个序列的DTW距离。3. 回溯最优路径有了完整的累积距离矩阵后我们需要从终点(n,m)回溯到起点(0,0)找出最优路径def trace_path(gamma): path [] i, j gamma.shape[0]-1, gamma.shape[1]-1 path.append((i, j)) while i 0 or j 0: if i 0: j - 1 elif j 0: i - 1 else: min_val min(gamma[i-1,j], gamma[i,j-1], gamma[i-1,j-1]) if gamma[i-1,j-1] min_val: i - 1 j - 1 elif gamma[i-1,j] min_val: i - 1 else: j - 1 path.append((i, j)) return path[::-1] # 反转使路径从起点开始 path trace_path(gamma)现在让我们可视化这条路径plt.figure(figsize(8,6)) plt.imshow(gamma, originlower, cmapviridis) plt.colorbar(label累积距离) plt.plot([p[1] for p in path], [p[0] for p in path], r, linewidth2) plt.xlabel(序列2索引) plt.ylabel(序列1索引) plt.title(最优规整路径) plt.show()红色路径展示了两个序列间的最佳对齐方式。路径的走向反映了时间轴的压缩和拉伸——水平移动表示序列1的一个点对应序列2的多个点时间拉伸垂直移动则相反。4. 时间规整对齐可视化最直观的理解方式是将两个序列按照最优路径进行对齐展示def plot_alignment(seq1, seq2, path): fig, (ax1, ax2) plt.subplots(2, 1, figsize(12,8), sharexTrue) # 绘制原始序列 ax1.plot(seq1, b-, label序列1) ax1.plot(seq2, g-, label序列2) ax1.legend() ax1.set_title(原始序列对比) # 绘制对齐后的序列 aligned_seq1 [seq1[i] for i,j in path] aligned_seq2 [seq2[j] for i,j in path] ax2.plot(aligned_seq1, b-, label序列1(对齐后)) ax2.plot(aligned_seq2, g-, label序列2(对齐后)) # 添加对应关系连线 for step in range(0, len(path), 10): # 每隔10个点画一条线 i, j path[step] ax1.plot([i, j], [seq1[i], seq2[j]], r--, alpha0.3) ax2.legend() ax2.set_title(规整对齐后的序列) plt.tight_layout() plt.show() plot_alignment(seq1, seq2, path)上图中第一个子图展示了原始序列红色虚线显示了关键点之间的对应关系。第二个子图则展示了按照DTW路径对齐后的序列——你可以看到波形特征点现在完美对齐了。5. 高级应用与优化技巧理解了基本原理后让我们探讨一些实际应用中的高级技巧。5.1 约束窗口加速计算完整DTW的复杂度是O(nm)对于长序列可能很耗时。通过添加约束窗口可以显著加速def constrained_dtw(seq1, seq2, window_size10): n, m len(seq1), len(seq2) gamma np.full((n,m), np.inf) gamma[0,0] abs(seq1[0] - seq2[0]) for i in range(1, n): for j in range(max(1, i-window_size), min(m, iwindow_size)): cost abs(seq1[i] - seq2[j]) gamma[i,j] cost min(gamma[i-1,j], gamma[i,j-1], gamma[i-1,j-1]) return gamma[n-1,m-1], gamma这个版本只计算对角线附近一定范围内的单元格复杂度降为O(nw)其中w是窗口大小。5.2 导数动态时间规整对于某些应用序列的形状比绝对值更重要。导数DTW(DDTW)先计算序列的导数def derivative(seq): return np.diff(seq, prependseq[0]) def ddtw_distance(seq1, seq2): dseq1 derivative(seq1) dseq2 derivative(seq2) return dtw_distance(dseq1, dseq2)这种方法对振幅偏移和线性趋势不敏感更适合比较形状相似性。5.3 多维度DTW对于多维时间序列如3D运动捕捉数据只需修改距离计算def multivariate_dtw(seq1, seq2): # seq1和seq2形状为(T, D)D是维度数 local_dist np.array([[np.linalg.norm(x - y) for y in seq2] for x in seq1]) # 其余部分与标准DTW相同6. 实战案例语音信号对齐让我们用一个真实案例展示DTW的威力。假设我们有两段说Hello的录音语速不同# 生成模拟语音信号 def create_voice(word, speed1.0): t np.linspace(0, 1, 1000) if word hello: sig np.sin(2*np.pi*50*t) * (t0.2) * (t0.8) # 基频 sig 0.5*np.sin(2*np.pi*120*t) * (t0.1) * (t0.9) # 第一共振峰 sig 0.3*np.sin(2*np.pi*240*t) * (t0.3) * (t0.7) # 第二共振峰 return sig[::int(1/speed)] # 通过采样模拟语速变化 normal create_voice(hello, 1.0) fast create_voice(hello, 1.5) plt.figure(figsize(12,4)) plt.plot(normal, label正常语速) plt.plot(fast, label快速语音) plt.legend() plt.title(不同语速的语音信号) plt.show()计算DTW对齐distance, gamma constrained_dtw(normal, fast, window_size50) path trace_path(gamma) plt.figure(figsize(10,8)) plt.imshow(gamma, originlower, cmapviridis, aspectauto) plt.plot([p[1] for p in path], [p[0] for p in path], r, linewidth2) plt.colorbar(label累积距离) plt.title(语音信号对齐路径) plt.xlabel(快速语音帧) plt.ylabel(正常语速帧) plt.show()从路径可以看出DTW成功找到了非线性对应关系将快速语音的压缩部分与正常语速的展开部分正确匹配。

相关文章:

从动态规划到DTW:一个Python可视化教程,带你亲手画出时间规整路径图

从动态规划到DTW:一个Python可视化教程,带你亲手画出时间规整路径图 在信号处理和机器学习领域,时间序列的相似性比较是一个基础但极具挑战性的问题。想象一下,当你需要比较两段语音、心电图或股票走势时,简单的逐点对…...

从‘调参噩梦’到‘一键收敛’:全局快速Terminal滑模控制参数整定心得分享

从‘调参噩梦’到‘一键收敛’:全局快速Terminal滑模控制参数整定实战指南 滑模控制工程师的日常,往往始于理论推导的兴奋,终于参数调试的崩溃。当你在Simulink里反复拖动α、β、p、q的滑块,看着仿真曲线在发散与抖振之间反复横跳…...

Face3D.ai Pro使用技巧:掌握这几点,让你的3D重建效果提升一个档次

Face3D.ai Pro使用技巧:掌握这几点,让你的3D重建效果提升一个档次 1. 为什么你的3D重建效果不够理想? 1.1 输入照片的质量决定重建上限 Face3D.ai Pro虽然强大,但"垃圾进、垃圾出"的原则依然适用。经过上百次测试&am…...

ChemCrow实战指南:用AI大模型解决复杂化学问题的终极方案

ChemCrow实战指南:用AI大模型解决复杂化学问题的终极方案 【免费下载链接】chemcrow-public Chemcrow 项目地址: https://gitcode.com/gh_mirrors/ch/chemcrow-public 你是否曾为复杂的化学计算感到头疼?需要计算分子量、预测反应产物&#xff0c…...

2026年云端新手步骤:如何安装OpenClaw?Coding Plan配置及大模型API Key接入

2026年云端新手步骤:如何安装OpenClaw?Coding Plan配置及大模型API Key接入。OpenClaw(前身为Clawdbot/Moltbot)作为开源、本地优先的AI助理框架,凭借724小时在线响应、多任务自动化执行、跨平台协同等核心能力&#x…...

告别万年历芯片!用GD32F407内部RTC打造低功耗数据记录仪

用GD32F407内部RTC实现低功耗数据记录仪的5个实战技巧 在便携式设备设计中,数据记录仪往往需要持续运行数月甚至数年。传统方案依赖外部RTC芯片维持时间基准,但GD32F407内置的RTC模块配合低功耗模式,能实现更精简的设计。去年我们为某环境监测…...

避开EtherCAT FOE开发的那些坑:从Busy状态处理到数据包边界问题详解

EtherCAT FOE开发实战:从协议细节到异常处理全解析 当你在凌晨三点的实验室里盯着示波器上那些不按预期跳变的信号线时,可能会突然意识到——工业通信协议的魔鬼都藏在细节里。EtherCAT的FOE(File Access over EtherCAT)协议看似简…...

别再手动调参了!用Simulink S函数实现递推最小二乘(RLS)实时系统辨识(附模型下载)

工程实战:用Simulink S函数实现递推最小二乘系统辨识 在工业控制领域,系统辨识就像给未知对象"把脉"——我们需要通过输入输出数据反推数学模型。传统手动调参不仅效率低下,面对时变系统更是力不从心。本文将带你用Simulink S函数打…...

基于宾汉姆流体粘度空间衰减的COMSOL三维离散裂隙恒压注浆模型研究

COMSOL 三维离散裂隙注浆模型。 基于粘度空间衰减的宾汉姆流体注浆。 裂隙采用随机分布的圆盘模型,恒压注浆。 裂隙注浆数值仿真这活儿,说难不难,说简单也够折腾。最近在COMSOL里搭了个三维注浆模型,用宾汉姆流体模拟水泥浆液&am…...

别再只会调占空比了!STM32 HAL库的Timer PWM,从呼吸灯到舵机控制的完整配置流程

STM32 HAL库Timer PWM实战:从呼吸灯到舵机控制的高级应用技巧 在嵌入式开发领域,PWM(脉冲宽度调制)技术就像一把瑞士军刀,看似简单却功能强大。许多开发者虽然掌握了PWM的基础配置,却止步于简单的LED亮度调…...

MATLAB环境下的结构模态参数识别方法:基于数据驱动的SSI-DATA和协方差驱动的SSI-...

MATLAB环境下基于数据驱动的随机子空间(SSI-DATA)和协方差驱动的随机子空间(SSI-COV)的结构模态参数识别方法,可用于土木,航空航天,机械等领域。 本品为程序,已调通,可直接运行。 一、系统概述 本系统是一套基于MATL…...

PopLDdecay深度解析:高性能连锁不平衡衰减分析工具的技术实现与实战应用

PopLDdecay深度解析:高性能连锁不平衡衰减分析工具的技术实现与实战应用 【免费下载链接】PopLDdecay PopLDdecay: a fast and effective tool for linkage disequilibrium decay analysis based on variant call format(VCF) files 项目地址: https://gitcode.co…...

AutoCAD字体管理终极指南:如何用FontCenter彻底解决字体缺失问题

AutoCAD字体管理终极指南:如何用FontCenter彻底解决字体缺失问题 【免费下载链接】FontCenter AutoCAD自动管理字体插件 项目地址: https://gitcode.com/gh_mirrors/fo/FontCenter 你是否曾在打开AutoCAD图纸时,看到文字变成问号或乱码而束手无策…...

从手机到基站:聊聊GNSS授时在5G网络里到底有多重要(附北斗/GPS对比)

从手机到基站:GNSS授时如何成为5G网络的隐形支柱 当你在城市中心用5G手机流畅观看4K直播时,可能不会想到,百米之外的基站正通过数万公里高空的卫星维持着纳秒级的时间同步。这种看似科幻的场景,正是全球导航卫星系统(G…...

基于深度学习的yolo11的SAR图像车辆检测 sar图像识别

文章目录一个用于车辆检测的SAR图像数据集引言数据下载基本信息统计信息推理代码注释格式文件结构一个用于车辆检测的SAR图像数据集 引言 是一个专为车辆检测设计的合成孔径雷达(SAR)图像数据集。它使用了Ka、Ku和X波段的数据,旨在提供多样化…...

架构实战:基于 GB28181/RTSP 多协议兼容的 AI 视频中台——支持源码交付与边缘异构部署

1. 引言:安防集成开发中的“协议围城” 作为一名深耕安防领域十余年的架构师,我见过太多集成商陷于协议对接的泥潭。在面对海康、大华、宇视等跨品牌设备接入时,开发者往往需要处理复杂的 GB/T28181 级联、不稳定的 RTSP 轮询以及异构硬件下…...

斯坦福邱肖杰:预测性虚拟胚胎

摘要 整合单细胞数据、空间数据与人工智能技术的预测性虚拟胚胎系统,为跨尺度模拟哺乳动物胚胎发育提供了可行路径,有望深化人类对胚胎发育与先天性疾病的基础认知。 尽管发育生物学已取得数10年进展,构建胚胎发育的整合式、可预测模型仍是…...

生成引擎优化(GEO)为内容创作引入新视角与用户体验提升策略

生成引擎优化(GEO)为内容创作提供了新的思路,着眼于以用户需求为中心的创作方式。通过深入理解目标受众的行为和偏好,创作者能够定制更具个性化的内容,提高互动性和用户参与度。GEO并非单纯依赖关键词排名,…...

解锁高效办公新体验:探索QuickLook OfficeViewer-Native的智能文档预览方案

解锁高效办公新体验:探索QuickLook OfficeViewer-Native的智能文档预览方案 【免费下载链接】QuickLook.Plugin.OfficeViewer-Native View Word, Excel, and PowerPoint files with MS Office and WPS Office components. 项目地址: https://gitcode.com/gh_mirro…...

企业统一任务调度平台MoiaControl介绍

1、批量作业调度的现状当前批量作业调度软件普遍面临着一些问题:调度方式原始落后时至今日仍然有一些系统使用人工调度或操作系统的crontab方式调度。在如今追求自动化甚至智能化的时代已显得非常原始和低效,容易出错且难以监控,已成为这类系…...

Windows系统级输入模拟终极指南:Interceptor深度解析与应用实践

Windows系统级输入模拟终极指南:Interceptor深度解析与应用实践 【免费下载链接】Interceptor C# wrapper for a Windows keyboard driver. Can simulate keystrokes and mouse clicks in protected areas like the Windows logon screen (and yes, even in games).…...

手把手教你将FAST-LIO2部署到Jetson Orin/NX:从源码编译到实车测试避坑全记录

FAST-LIO2在Jetson Orin/NX上的实战部署指南:从编译优化到实车调参全解析 引言 当Livox Mid-70激光雷达以10Hz频率吐出数万点云数据,而Jetson Orin NX的ARM架构处理器必须在20毫秒内完成运动补偿、状态估计和地图更新时,传统SLAM方案往往面临…...

掌握N_m3u8DL-RE:跨平台流媒体下载的5大实战技巧

掌握N_m3u8DL-RE:跨平台流媒体下载的5大实战技巧 【免费下载链接】N_m3u8DL-RE Cross-Platform, modern and powerful stream downloader for MPD/M3U8/ISM. English/简体中文/繁體中文. 项目地址: https://gitcode.com/GitHub_Trending/nm3/N_m3u8DL-RE 在…...

3步实现本地分屏游戏:NucleusCoop让单机游戏变多人同屏神器

3步实现本地分屏游戏:NucleusCoop让单机游戏变多人同屏神器 【免费下载链接】nucleuscoop Starts multiple instances of a game for split-screen multiplayer gaming! 项目地址: https://gitcode.com/gh_mirrors/nu/nucleuscoop 你是否曾经想过和朋友们在同…...

如何快速解密JSXBIN:面向开发者的完整反编译指南

如何快速解密JSXBIN:面向开发者的完整反编译指南 【免费下载链接】jsxer A fast and accurate JSXBIN decompiler. 项目地址: https://gitcode.com/gh_mirrors/js/jsxer Jsxer是一个高效准确的JSXBIN反编译器,专门用于将Adobe ExtendScript二进制…...

Windows Defender Remover 终极指南:如何彻底禁用系统安全防护的完整解决方案

Windows Defender Remover 终极指南:如何彻底禁用系统安全防护的完整解决方案 【免费下载链接】windows-defender-remover A tool which is uses to remove Windows Defender in Windows 8.x, Windows 10 (every version) and Windows 11. 项目地址: https://gitc…...

YOLOv1的‘快’从何而来?对比Faster R-CNN与SSD,聊聊单阶段检测的演进与局限

YOLOv1的速度革命:单阶段检测器的设计哲学与时代局限 当Joseph Redmon在2015年首次提出YOLO(You Only Look Once)架构时,计算机视觉领域正被两阶段检测器的计算复杂度所困扰。Faster R-CNN虽然精度优异,但其区域提议网…...

从.wrl文件到三维点云:手把手教你用MATLAB提取并处理VRML模型数据

从.wrl文件到三维点云:MATLAB自动化处理VRML模型全流程解析 当你拿到一个复杂的VRML场景文件(.wrl格式),是否曾为如何提取其中的三维几何数据而头疼?这类文件虽然可以用文本编辑器查看,但手动复制粘贴顶点坐…...

告别画框框!用OpenCV的rotatedRectangleIntersection函数,5分钟搞定旋转目标检测的IoU计算

旋转目标检测实战:5分钟掌握OpenCV旋转框IoU计算技巧 在计算机视觉领域,旋转目标检测正逐渐成为处理倾斜物体的标配方案。与传统的水平框相比,旋转框能更精确地框定物体,减少背景干扰。但随之而来的一个棘手问题是如何高效计算两个…...

别再只盯着CNN了!用ViT的cls token搞定图像分类,保姆级原理拆解

从会议主持人到图像分类:ViT中cls token的全局智慧 想象你正在组织一场跨部门会议,每个参会者都带着自己的专业见解。作为主持人,你需要倾听所有人的发言,提炼关键信息,最终形成一份综合报告——这正是Vision Transfor…...