DTW(Dynamic Time Warping)算法学习应用实践与效率对比分析

DTW(Dynamic Time Warping)算法是一种用于度量两个时间序列之间的相似性的方法。它的构建原理如下:

  1. 基本思想:DTW算法通过计算两个时间序列之间的最小距离,来度量它们的相似性。与欧氏距离等传统距离度量方法不同,DTW算法考虑了时间序列中元素之间的时序关系。

  2. 算法步骤:

    • 创建一个距离矩阵,用于存储计算过程中的距离。
    • 初始化第一行和第一列的值为无穷大。
    • 从矩阵的(1,1)位置开始,计算每个位置的距离。具体计算方法是将当前位置的距离设为当前位置的元素之间的距离加上三个相邻位置中最小的距离。
    • 最后返回距离矩阵的最后一个元素,即两个时间序列的DTW距离。

DTW算法的优点:

  1. 考虑了时间序列中元素之间的时序关系,适用于比较不同长度和变化速度的时间序列。
  2. 具有较好的鲁棒性,对于时间序列中的噪声、缺失数据等问题有一定的容忍度。

DTW算法的缺点:

  1. 计算复杂度较高,时间和空间复杂度都为O(n*m),其中n和m分别是两个时间序列的长度。
  2. 对于高维数据的处理能力有限,当时间序列的维度较高时,DTW算法的效果可能下降。

实例原理图如下所示:

DTW 算法重要的特征就是通过“扭曲”X 轴来解释 Y 轴变量,以达到使时间序列对齐的目的。但是简单的通过 Y 轴的变量值来扭曲 X 轴会导致“不直观”( unintuitive )的对齐,其中一个时间序列上的单个点会映射到另一个时间序列的一部分上。我们称这种我们不期望看到的行为为“奇点”( singularities )。

DTW算法的核心思想就是通过扭曲来实现序列的近似对齐处理,基于动态规划的思想找到最优匹配路径。

相关的原理这里就不再赘述了,感兴趣的话可以自行查阅即可,这里接下来主要是想要基于python开发实现DTW算法,如下所示:

def dtw_distance(s1, s2):
    """
    两序列DTW距离计算
    """
    n = len(s1)
    m = len(s2)
    # 创建一个n*m的矩阵,用于存储计算过程中的距离
    dtw_matrix = np.zeros((n + 1, m + 1))
    # 初始化第一行和第一列的值为无穷大
    dtw_matrix[0, 1:] = np.inf
    dtw_matrix[1:, 0] = np.inf
    # 计算每个位置的距离
    for i in range(1, n + 1):
        for j in range(1, m + 1):
            cost = abs(s1[i - 1] - s2[j - 1])  # 计算s1[i]和s2[j]之间的距离
            dtw_matrix[i, j] = cost + min(
                dtw_matrix[i - 1, j], dtw_matrix[i, j - 1], dtw_matrix[i - 1, j - 1]
            )
    # 返回最终的DTW距离
    dtw = dtw_matrix[n, m]
    print("[-]" * 30)
    print("dtw_matrix: ")
    print(dtw_matrix)
    print("[-]" * 30)
    print("dtw_distance: ", dtw)
    return dtw

结果输出如下所示:

[-][-][-][-][-][-][-][-][-][-][-][-][-][-][-][-][-][-][-][-][-][-][-][-][-][-][-][-][-][-]
dtw_matrix: 
[[ 0. inf inf inf inf inf]
 [inf  1.  4.  9. 16. 25.]
 [inf  1.  3.  7. 13. 21.]
 [inf  2.  2.  5. 10. 17.]
 [inf  4.  2.  4.  8. 14.]
 [inf  7.  3.  3.  6. 11.]]
[-][-][-][-][-][-][-][-][-][-][-][-][-][-][-][-][-][-][-][-][-][-][-][-][-][-][-][-][-][-]
dtw_distance:  11.0

上面打印输出的是dtw动态规划过程中产生的转移矩阵,下面打印的是dtw算法计算得到的序列之间的距离。

上面的代码是不依赖于任何第三方库实现的dtw算法,在现在已经有现成的第三方库可以直接进行使用,代码实现也很简单,如下所示:

s1 = [1, 2, 3, 4, 5]
s2 = [2, 4, 6, 8, 10]
x = np.array(s1)
y = np.array(s2)
dtw_distance, dtw_matrix = fastdtw(x, y, dist=euclidean)
print("[-]" * 30)
print("dtw_matrix: ")
print(dtw_matrix)
print("[-]" * 30)
print("dtw_distance: ", dtw_distance)

结果输出如下所示:

[-][-][-][-][-][-][-][-][-][-][-][-][-][-][-][-][-][-][-][-][-][-][-][-][-][-][-][-][-][-]
dtw_matrix: 
[(0, 0), (1, 0), (2, 1), (3, 1), (4, 2), (4, 3), (4, 4)]
[-][-][-][-][-][-][-][-][-][-][-][-][-][-][-][-][-][-][-][-][-][-][-][-][-][-][-][-][-][-]
dtw_distance:  11.0

接下来我想要对比下不同算法实现的效率情况,核心实现如下所示:

nums_list = [10,100,1000,10000]
time_list1=[]
for one_num in nums_list:
    start = time.time()
    for i in range(one_num):
        one = [random.randint(1, 1000) for _ in range(random.randint(1, 100))]
        two = [random.randint(1, 1000) for _ in range(random.randint(1, 100))]
        dtw_distance(one, two)
    end = time.time()
    delta = end - start
    time_list1.append(delta)
print(time_list1)

另一个算法也是类似,这里就不再赘述了,分别进行了四组计算,对比可视化如下:

plt.clf()
plt.plot(time_list1,label="selfDTW")
plt.plot(time_list2,label="fastDTW")
plt.legend()
plt.title("Different DTW Method TimeConsume Compare")
plt.savefig("DTW_compare.png")

结果如下所示:

很奇怪的就是我原以为第三方模块的效率应该会更高,但是在这里对比实验结果下反而是相反的情况,不知道是我哪里设置出了问题还是什么原因,如果有发现的还望不吝指教,感兴趣的话都是可以自行尝试实践下的。

基于动态时间规整(DTW)算法的变种算法有多种,以下是其中一些常见的变种算法:

  1. FastDTW(快速动态时间规整):FastDTW是对DTW算法的一种加速版本。它通过将时间序列进行下采样,然后在较小的序列上应用DTW算法来减少计算量。FastDTW在保持较小时间和空间复杂度的同时,仍能提供较好的近似DTW距离。

  2. Multivariate DTW(多变量动态时间规整):DTW算法最初应用于单变量时间序列,但在实际问题中,往往存在多个变量之间的关联。Multivariate DTW扩展了DTW算法,使其能够处理多维时间序列。它考虑了每个维度上的距离度量和对齐路径的形状。

  3. Weighted DTW(加权动态时间规整):在标准的DTW算法中,每个时间步的匹配都被视为等权重。然而,在某些应用中,不同时间步的重要性可能不同。Weighted DTW引入了一个权重系数,用于调整每个时间步的贡献,从而更好地适应不同的应用场景。

  4. Constrained DTW(约束动态时间规整):在某些情况下,我们可能希望对DTW算法的搜索空间进行限制,以便更好地满足特定的约束条件。Constrained DTW通过引入限制条件,如全局约束或局部约束,来约束匹配路径的搜索范围,从而减少计算复杂度并提高算法的效率。

这些是基于DTW算法的一些常见变种算法,每种算法都有其适用的场景和优势。具体选择哪种算法取决于你的应用需求、时间序列的特征以及对计算效率和准确性的要求。感兴趣的话都可以对照了解学习一下。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/154764.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【文末送书——数学经典著作】工科必备的数学思维培养

欢迎关注博主 Mindtechnist 或加入【智能科技社区】一起学习和分享Linux、C、C、Python、Matlab,机器人运动控制、多机器人协作,智能优化算法,滤波估计、多传感器信息融合,机器学习,人工智能等相关领域的知识和技术。关…

elementplus DateTimePicker 日期范围选择器 设置默认时间范围为当前月的起始时间到结束时间

代码如下&#xff1a; <el-date-pickerv-model"value"type"datetimerange"start-placeholder"Start Date"end-placeholder"End Date":default-time"defaultTime" />const defaultTime: [Date, Date] [new Date(2000…

Ubuntu18.04安装ROS系统+turtle测试

安装 1.设置安装源 sudo sh -c echo "deb http://packages.ros.org/ros/ubuntu $(lsb_release -sc) main" > /etc/apt/sources.list.d/ros-latest.list sudo sh -c . /etc/lsb-release && echo "deb http://mirrors.tuna.tsinghua.edu.cn/ros/ubun…

科技云报道:Citrix正式退出中国市场!国产们谁能真正顶上?

科技云报道原创。 2023年12月3日&#xff0c; Citrix&#xff08;思杰&#xff09;发布的公告将全面生效&#xff0c;中国市场&#xff08;包括香港地区和澳门地区&#xff09;也会停止所有新的交易。 这个消息&#xff0c;无疑是引起了业界的热议&#xff0c;毕竟Citrix可以…

【教3妹学编程-算法题】购买物品的最大开销

3妹&#xff1a;2哥&#xff0c;听说你今天发工资啦&#xff1f; 请我吃饭怎么样&#xff0c;嘿嘿 2哥 : 切&#xff0c;你上周还发工资了呢&#xff0c;也没见你请我吃饭。 3妹&#xff1a;哎呀&#xff0c; 我的工资都用来双11 shopping了&#xff0c; 双11过后我都吃了1周土…

Android Jetpack的组件介绍,常见组件解析

jetpack组件有哪些 Android Jetpack是一个集成Android应用程序组件的一站式解决方案。它使开发人员能够专注于他们的应用程序的真正创新部分&#xff0c;而不会受到Android平台特定的限制。Jetpack组件可分为四个类别&#xff1a; 架构组件&#xff08;Architecture Componen…

C++初阶-模板初阶

模板初阶 一、泛型编程二、函数模板2.1函数模板概念2.2函数模板格式2.3函数模板的原理2.4函数模板的原理2.5模板参数的匹配原则 三、类模板3.1类模板的定义格式3.2类模板的实例化 一、泛型编程 如何实现一个通用的交换函数呢&#xff1f; void Swap(int& left, int& …

IntelliJIDEA快捷键中文版

IntelliJIDEA快捷键中文版&#xff0c;对于Android Studio也适用。官方快捷键链接在此&#xff0c;官方上是英文的&#xff0c;我于2023-11-16下载并翻译成中文&#xff0c;可能翻译不太准&#xff0c;所以英文我都保留下来了&#xff0c;大家可以对比着看&#xff0c;有些英文…

Python语言:面向对象——类与对象初体验

什么是面向对象的编程思想&#xff1f; 我就知道他是一种编程思想&#xff0c;因资历尚浅&#xff0c;没有悟到面向对象的精髓和奥秘所在&#xff0c;只好援引一下chatgpt给我的答案了。 接下来到了分析类与对象的实质是什么了&#xff0c;这个我倒是知道&#xff0c;以下是我的…

用strtok和指针数组构造一个能对字符转进行解析的函数

代码如下 #include<stdio.h> #include<string.h> #include<stdlib.h> int msg_deal(char *msg_src, char *msg_done[],char *str)//返回切割了多少次 {msg_done[0] msg_src;int i 0;while((msg_done[i] strtok(msg_done[i], ",")) && …

OpenVPN服务器搭建与OpenVPN客户端访问

1.服务器搭建: 操作系统 ubuntu 22.04: 安装OpenVPN服务器前先更新系统 2.下载OpenVPN安装脚本: wget https://raw.githubusercontent.com/angristan/openvpn-install/master/openvpn-install.sh 3.给脚本运行权限: chmod +x openvpn-install.sh 4.运行脚本进行OpenVPN服务器…

收集整理微信小程序源码精选8500套(不同行业的源码集合)/带后台+含搭建开发教程

这下面分享的是精心收集整理的微信小程序源码精选8500套&#xff0c;它含有不同行业的源码集合&#xff0c;带后台&#xff0c;而且含搭建开发教程。可以转存起来&#xff0c;需要的时候直接搜索关键词查找就行了&#xff0c;方便得很。 很多伙伴学习小程序不知怎么开始&#…

轻松预览:Axure RP在线原型展示指南,快速掌握!

当UI设计师想要提供功能和细节丰富的原型时&#xff0c;可以使用原型设计工具预览Axure原型。原型设计工具Axurerp作为线框图和原型制作工具的创始人&#xff0c;功能非常强大。取代Axure的国产原型设计工具即时设计&#xff0c;界面布局清新&#xff0c;非常适合复杂的原型设计…

DNS正向解析和主从复制

目录 概念 DNS解析 例&#xff1a;www.baidu.com. 解析过程 DNS查询方式 DNS的查询过程 DNS软件bind 正向解析&#xff08;根据域名查找ip地址&#xff09; 1.先安装bind软件 2.打开网卡配置文件 将DNS1改为自己本机 &#xff08;更改完配置重启服务&#xff09; 3.打…

Java_实现图书管理系统

目录 前言 框架核心思想 框架的实现 书类和书架类的实现 功能接口实现 功能的声明 父类用户和子类管理员&#xff0c;子类普通用户 Main方法 前言 java图书管理系统的详细解析;从思考到实现,一步步带你学会图书管理系统. 框架核心思想 下图只是一个图书管理系统的初步…

【源码系列】情侣游戏小程序系统开发飞行棋扫雷大冒险

系统介绍 情侣游戏小程序系统&#xff0c;为情侣们提供了一种全新的互动方式。通过专属的游戏体验、创新的游戏玩法、丰富的道具与场景、个性化定制以及实时互动与社交等功能&#xff0c;该系统让爱情在棋盘上飞舞&#xff0c;为情侣们带来了更多的乐趣和益处。随着技术的不断…

Python实现求解上个工作日逻辑

目录 一、需求描述二、代码实现三、测试结果 一、需求描述 因工作需要&#xff0c;现需获取任意一个日期的上个工作日&#xff0c;要求考虑法定假日及周末。 例如&#xff1a;2024年2月10日&#xff08;春节&#xff09;的上一个工作日为2024年2月9日&#xff0c;2024年2月17…

【C++】数组中出现次数超过一半的数字

代码&#xff1a; class Solution { public:/*** 代码中的类名、方法名、参数名已经指定&#xff0c;请勿修改&#xff0c;直接返回方法规定的值即可** * param numbers int整型vector * return int整型*/int MoreThanHalfNum_Solution(vector<int>& numbers) {int …

spring学习笔记-IOC,AOP,事务管理

目录 概述 什么是spring 侵入式的概念 spring的核心 spring的优势 注意 IOC控制反转 概述 核心 容器 DI&#xff0c;dependency injection依赖注入 概念 注入方式 循环依赖 spring如何解决循环依赖 spring生成Bean的方式 Bean属性注入&#xff08;Bean属性赋值…

如何用Postman做接口自动化测试?一文带你学会

什么是自动化测试 把人对软件的测试行为转化为由机器执行测试行为的一种实践。 例如GUI自动化测试&#xff0c;模拟人去操作软件界面&#xff0c;把人从简单重复的劳动中解放出来 本质是用代码去测试另一段代码&#xff0c;属于一种软件开发工作&#xff0c;已经开发完成的用…