本文介绍基于PaddlePaddle2.0构建动态时间规整(DTW)模型的方法。DTW用于计算两时间序列相似度,适用于语音识别等场景,能解决序列长度不一致问题,但不适用于交叉对应关系的序列。文中举例说明DTW建模流程,包括初始化距离矩阵、用动态规划找最短路径,并给出了基于PaddlePaddle2.0的实现代码及示例计算结果。
☞☞☞AI 智能聊天, 问答助手, AI 智能搜索, 免费无限量使用 DeepSeek R1 模型☜☜☜

作者:陆平
动态时间归整模型(Dynamic Time Warping, DTW)可以用于计算两个时间序列的相似程度。它适用于语音识别中的孤立词识别、姿势识别等场景。
例如,我们通常需要用唤醒词来启动智能音响,小米的小爱音响的唤醒词为“小爱同学”。但是不同的人对“小爱同学”这四个字的发音、语速等都是不同的,即便是相同的人也不可能每次说“小爱同学”这四个字的发音、语速完全相同,也就是说,实际发音与标准序列在长度上是不一致的。为解决这个问题,可以对序列进行缩放,使得两个时间序列长度一致,但这里没有考虑到序列中的某个元素一对多问题、一对零的问题。还有一种解决方式是利用动态规划方法,找到两个时间序列的最短匹配路径,即DTW模型。
然而,DTW模型不适用于具有交叉对应关系的时间序列。例如,中英文语言翻译场景中,词语序列之间普遍存在交叉对应关系,这种情形DTW模型不太适用。“今天我吃了水果”这句话翻译成英文是“I had fruit today”,“今天”这个词在中文语境中通常在第一个词的位置,而在英文语境下“today”处于最后一个词位置,这表明这两个时间序列存在交叉对应关系。
以下用个例子来看DTW建模流程。
步骤1:设有两个时间序列s1=[1,2,3,4,5,5,5,4]和s2=[3,4,5,6,5,4],这两个时间序列的长度分别为8和6.
步骤2:初始化一个距离矩阵dtw,该矩阵用于衡量两时间序列的距离。
初始化第一列,采用以下公式: dtw[i,0]=dtw[i−1,0]+distance(s1[i],s2[0]),i=1,...,7.
具体来看,dtw[0,0]这个位置取值为2,是因为∣1−3∣=2.
dtw[1,0]这个位置取值为3,是因为dtw[0,0]+distance(s1[1],s2[0])=2+∣2−3∣=2+1=3.
dtw[2,0]这个位置取值为3,是因为dtw[1,0]+distance(s1[2],s2[0])=3+∣3−3∣=3+0=3.
dtw[3,0]这个位置取值为4,是因为dtw[2,0]+distance(s1[3],s2[0])=3+∣4−3∣=3+1=4.
以此类推。
初始化第一行,采用以下公式: dtw[0,i]=dtw[0,i−1]+distance(s1[0],s2[i]),i=1,...,5.
dtw[0,1]这个位置取值为5,是因为dtw[0,0]+distance(s1[0],s2[1])=2+∣1−4∣=2+3=5.
dtw[0,2]这个位置取值为9,是因为dtw[0,1]+distance(s1[0],s2[2])=5+∣1−5∣=5+4=9.
dtw[0,3]这个位置取值为14,是因为dtw[0,2]+distance(s1[0],s2[3])=9+∣1−6∣=9+5=14.
以此类推。
Tensor(shape=[8, 6], dtype=float32, place=CPUPlace, stop_gradient=True,
[[ 2., 5., 9., 14., 18., 21.],
[ 3., inf., inf., inf., inf., inf.],
[ 3., inf., inf., inf., inf., inf.],
[ 4., inf., inf., inf., inf., inf.],
[ 6., inf., inf., inf., inf., inf.],
[ 8., inf., inf., inf., inf., inf.],
[ 10., inf., inf., inf., inf., inf.],
[ 11., inf., inf., inf., inf., inf.]])步骤3: 利用动态规划算法找出最短的对应路径。 这里假设了一个单调性条件,即通往dtw[i,j]的路径,上一步只能是dtw[i−1,j]、dtw[i,j−1]、dtw[i−1,j−1]三者之一。相应的代码为:
for i in range(1,len(src)): for j in range(1,len(tar)): cost=dist_func(src[i],tar[j]) temp=[] temp.append(cost+dtw[i-1,j]) temp.append(cost+dtw[i,j-1]) temp.append(cost+dtw[i-1,j-1])
dtw[i,j]=min(temp)这里的假设是可以放松的,如果想要涵盖跳跃一步的对应关系。即通往dtw[i,j]的路径,上一步可以是dtw[i−1,j]、dtw[i,j−1]、dtw[i−1,j−1]、dtw[i−2,j−1]、dtw[i−1,j−2]之一。可以在循环中增加如下代码:
temp.append(cost+dtw[i-2,j-1]) temp.append(cost+dtw[i-1,j-2])
进一步,如果我们想避免某种跳跃关系,可以在cost前乘以某个正数,从而放大该步的即时成本。
正因为DTW模型含有单调性假设,它不适合于计算具有交叉对应关系的序列相似性。
import paddleimport numpy as np#距离函数def dist_func(v1,v2):
return paddle.abs(v1-v2)#DTW模型def dtw_func(src,tar):
dtw=paddle.zeros([len(src),len(tar)])
dtw[:] = np.inf #初始化
dtw[0,0]=dist_func(src[0],tar[0]) for i in range(1,len(src)):
dtw[i,0] = dtw[i-1,0]+dist_func(src[i],tar[0])
for i in range(1,len(tar)):
dtw[0,i] = dtw[0,i-1]+dist_func(src[0],tar[i])
#动态规划
for i in range(1,len(src)): for j in range(1,len(tar)):
cost=dist_func(src[i],tar[j])
temp=[]
temp.append(cost+dtw[i-1,j])
temp.append(cost+dtw[i,j-1])
temp.append(cost+dtw[i-1,j-1])
dtw[i,j]=min(temp) return dtw[-1,-1].numpy().item()
s1=paddle.to_tensor([1, 2, 3, 4, 5, 5, 5, 4])
s2=paddle.to_tensor([3, 4, 5, 6, 5, 4])
ds=dtw_func(s1,s2)print("s1, s2两序列之间的距离为:{}".format(ds))s1, s2两序列之间的距离为:4.0
以上就是基于PaddlePaddle2.0-构建动态时间归整模型(DTW)的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号