弗雷歇distanceDTW(动态时间规整)算法(附部分代码)

news2024/12/25 10:35:26

1、理论知识

1.1 什么是弗雷歇距离,它是用来干什么的?

费雷歇distance是求两个序列匹配之后的最大距离,这里需要明确a)两个序列;b)匹配过程;c)最大距离的含义。
a)两个序列的长度可以不同
b)匹配的过程可以是一一对应或者是一对多,这里可以这样理解:(小明拉着他家的狗旺财,在一条笔直的道路上玩耍,假设小明每走一步,旺财也会走一步,这个时候匹配的点就是一一对应的;当小明停下来捡狗屎的时候,如果旺财没有静止的话,旺财走过的所有点与小明当前所在的点就是多对一的关系)
c)最大距离可以理解为上述小明手里狗绳的长度,为什么狗可以走的很远也可以走得很近,因为绳子可能是弹簧绳(笑)。
思考如何实现两个不同长度的序列如何匹配:这里匹配的难点是一对多如何匹配。

1.2 DTW的概念以及算法

引入概念DTW(动态时间规整)这个算法是评估两个序列元素之间的对应关系,根据两个序列元素距离评估两个序列的相似度。这里DTW的作用和弗雷歇距离的是非常相似的,都是评价两个序列之间法的相似程度。
那么DTW是如何进行两个序列的匹配的:这里解释两个匹配中的概念(锁步度量:一对一的匹配;弹性度量:一对多的匹配)。

  1. DTW算法要求: 第一个点和第一个点匹配,最后一个点和最后一个点匹配
  2. 单向对应,不能回头(就是只能和自己相邻的两个点对应,不能越过已经链接的匹配进行对应)
  3. 一一对应,不能为空(这里的一一对应是,每个点都要有对应的点,不是严格意义上的一一对应)
  4. 对应之后,距离最近

bilibili关于DWT讲解

在这里插入图片描述
DTW算法中匹配算法,不需要实现绝对的两个序列的点之间一一对应,这里使用两个序列,一维数点进行举例,如上图所示,1)需要一个计算distance的function这里使用两个点的差的绝对值。2)然后两个序列的点一一对应,计算出每个点的dist然后生成一个m*n的矩阵。3)遍历这个矩阵,获得最小距离的路径path以及最小mean,code如下:

import numpy as np


def euc_dis(a, b):
    return abs(a-b)


def fill_matrix(a: np.array, b: np.array):
    l1 = len(a)
    l2 = len(b)
    dis_all = np.ones((l1, l2)) * -1
    dis_all[0, 0] = euc_dis(a[0], b[0])
    for i in range(1, l1):
        dis_all[i, 0] = euc_dis(a[i], b[0]) + dis_all[i-1, 0]
    for j in range(1, l2):
        dis_all[0, j] = euc_dis(a[0], b[j]) + dis_all[0, j-1]

    for i in range(1, l1):
        for j in range(1, l2):
            if dis_all[i, j] < 0:
                dis_all[i, j] = euc_dis(
                    a[i], b[j]) + min(dis_all[i-1, j], dis_all[i, j-1], dis_all[i-1, j-1])

    return dis_all, l1, l2


def DTW(dis_all: np.ndarray, l1: int, l2: int):
    # 返回匹配的最小距离的集合
    i, j = l1-1, l2-1
    path = []
    res = []
    cnt = 0
    path.append((i, j))
    res.append(dis_all[i, j])
    while True:
        if i > 0 and j > 0:
            m_pre = dis_all[i, j]
            m = min(dis_all[i-1, j], dis_all[i, j-1], dis_all[i-1, j-1])
            if m == dis_all[i-1, j]:
                i = i-1
            elif m == dis_all[i, j-1]:
                j = j-1
            elif m == dis_all[i-1, j-1]:
                j = j-1
                i = i-1
            res.append(m_pre - m)
            path.append((i, j))
            cnt += 1
        elif i == 0 and j == 0:
            path.append((i, j))
            res.append(dis_all[i, j])
            cnt += 1
            break
        elif i == 0:
            path.append((i, j))
            res.append(dis_all[i, j] - dis_all[i, j-1])
            j = j-1
            cnt += 1
        elif j == 0:
            path.append((i, j))
            res.append(dis_all[i, j] - dis_all[i-1, j])
            i = i-1
            cnt += 1

    mean = np.sum(res)/cnt
    print("cnt: ", cnt)
    return mean, res[:-1], path[::-1]


if __name__ == '__main__':
    a = np.array([2, 4, 6, 8])
    b = np.array([2, 3, 4, 6, 5, 7, 8])
    result, l1, l2 = fill_matrix(a, b)
    mean, res, path = DTW(result, l1, l2)
    print("result is:", result)
    print("mean is:", mean)
    print("res is:", res)
    print("path is:", path)
1.3弗雷歇距离的计算

弗雷歇距离也需要计算下方三个连线之间的最小距离
在这里插入图片描述

using namespace std;


class Frechet_dist{
public:
    Frechet_dist(){};
    ~Frechet_dist(){};

    double Frechet_distance(vector<vector<double>> curve_1, vector<vector<double>> curve_2);
    double Euc_dist(vector<double> p1, vector<double> p2);
    double Alignt(int l1, int l2, vector<vector<double>> curve_1, vector<vector<double>> curve_2, Eigen::MatrixXd Dis_all);
    double call_back();


};



#include "frechet_dist.h"
#include <iostream>
#include <math.h>

using namespace std;

double Frechet_dist::Euc_dist(vector<double> p1, vector<double> p2){
    double dis = sqrt(pow((p1[0] - p2[0]), 2) + pow((p1[1] - p2[1]), 2));
    return dis;
}
double min_of_three(double a,double b,double c)
{
    double temp = a;
    if(b < a) temp = b;
    if(temp > c) temp = c;
    return temp;
}
double Frechet_dist::Alignt(int l1, int l2, vector<vector<double>> curve_1, vector<vector<double>> curve_2, Eigen::MatrixXd Dis_all){
    double dis = 0;
    //多次迭代影响计算效率,这部分改成动态规划会不会稍微好一些
    cout <<  "len1" <<l1  << "len2" << l2 <<endl;
    for(int i = 0; i < l1; i++){
        for(int j = 0; j < l2; j++){
            if( i == 0 && j == 0){
                dis = Euc_dist(curve_1[0], curve_2[0]);
                Dis_all(i, j) = dis;
            }else if(i == 0 && j > 0){
                dis = Euc_dist(curve_1[0], curve_2[j]);
                Dis_all(i, j) = max(dis, Alignt(0, j-1, curve_1, curve_2, Dis_all));
            }else if(j == 0 && i > 0){
                dis = Euc_dist(curve_1[i], curve_2[0]);
                Dis_all(i, j) = max(dis ,  Alignt(i-1, 0, curve_1, curve_2, Dis_all));
            }else{
                dis = Euc_dist(curve_1[i], curve_2[j]);
                Dis_all(i, j) = max(dis , min_of_three(Alignt(i-1, j, curve_1, curve_2, Dis_all), Alignt(i-1, j-1, curve_1, curve_2, Dis_all),
                                    Alignt(i, j-1, curve_1, curve_2, Dis_all)));
            }
        }
    }
    cout << Dis_all << endl;
    return Dis_all(l1,l2);
}

double Frechet_dist::Frechet_distance(vector<vector<double>> curve_1, vector<vector<double>> curve_2){
    int l1 = curve_1.size();
    int l2 = curve_2.size();
    Eigen::MatrixXd Dis_all = Eigen::MatrixXd::Zero(l1,l2);

    Alignt(l1, l2, curve_1, curve_2, Dis_all);
    // Dis_all[0, 0] = dis;
    // // 动态规划方程的设计
    // // 第一行的计算方式:
    // for(int i = 1; i < l1; i++){
    //     dis = Euc_dist(curve_1[i], curve_2[0]);
    //     Dis_all[0, i] = dis + Dis_all[0, i-1];
    // }

    // // 第一列的计算
    // for(int j = 1; i < l2; i++){
    //     dis = Euc_dist(curve_1[0], curve_2[i]);
    //     Dis_all[0, i] = dis + Dis_all[i-1, 0];
    // }

    // 其他情况
    return 0.0;

}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【java】 【Springboot】 开发通用审核流程服务模块

完全自研一个极其轻量级 通用审核流程服务 可以进行流程&#xff0c;节点配置&#xff0c;流程&#xff0c;节点审核人权限配置 批量审核&#xff0c;批量驳回&#xff0c;审核&#xff0c;驳回&#xff0c;批量退回第一步&#xff0c;退回第一步等操作 涉及数据库表单字段

OSPF最优路径选择

路由比较 1、内部区域>区域间路由>NSSA1>Nssa2 2、如果只有Ex1、Ex2或者Nssa1、nNssa2开销类型。则Ex1>Ex2或者Nssa1>Nssa2 3、如果Ex1、Nssa1,Ex2和Nssa2,Ex1和Nssa1优于Ex2和Nssa2 4、如果外部开销加上内部开销,Ex1和Nssa1一样,则Ex1和Nssa1相同负载分担 5、如果外…

CVE-2016-1000027安全漏洞分析和解决方案

文章目录 前言复现问题漏洞分析解决办法相关阅读 前言 CVE-2016-1000027 安全漏洞&#xff0c;该漏洞在5.x的最新版本(5.3.27)依然存在,官方未给出任何解决办法。在spring-web6.0之后&#xff0c;则不存在该漏洞。 受影响范围:spring-web<6.0 解决办法&#xff1a;升级到sp…

【机器学习】分类问题和Logistic回归算法详解

在阅读本文前&#xff0c;请确保你已经掌握代价函数、假设函数等常用机器学习术语&#xff0c;最好已经学习线性回归算法&#xff0c;前情提要可参考https://blog.csdn.net/weixin_45434953/article/details/130593910 分类问题是十分广泛的一个问题&#xff0c;其代表问题是&…

图表控件LightningChart JS v.4.1已经发布!引入虚线模式

LightningChart JS是性能最高的JavaScript图表库&#xff0c;专注于实时数据可视化。是Web上性能最高的图表库具有出色的执行性能 - 使用高数据速率同时监控数十个数据源。 GPU加速和WebGL渲染确保您的设备的图形处理器得到有效利用&#xff0c;从而实现高刷新率和流畅的动画。…

固态硬盘基础知识:M.2 NVMe PCIe SATA的含义及区别

SATA接口 固态硬盘开始流行于笔记本电脑上&#xff0c;使用SATA接口&#xff0c;尺寸与笔记本硬盘相同&#xff0c;为2.5英寸。 那个时候&#xff0c;如果台式机需要加装固态硬盘&#xff0c;需要使用硬盘架&#xff0c;将固态硬盘安装在硬盘架上&#xff0c;然后再安装与机箱…

5.2.3 IP数据报(一)IP数据报的格式

5.2.3 IP数据报&#xff08;一&#xff09;IP数据报的格式 我们知道要想实现全球范围的通信除了地址要统一之外&#xff0c;数据格式也要统一&#xff0c;所以就有了IP分组&#xff0c;或者被称之为IP数据报&#xff0c;下面我们来学习IP分组的格式。如图 总体来说一个IP分组…

JetBrains的Java集成开发环境IntelliJ 2023版本在Linux系统的下载与安装配置教程

目录 前言一、IntelliJ安装二、使用配置总结 前言 IntelliJ IDEA Ultimate是一款功能强大的Java集成开发环境&#xff08;IDE&#xff09;。它提供了丰富的功能和工具&#xff0c;可以帮助开发人员更高效地编写、调试和部署Java应用程序。注&#xff1a;已在CentOS7.9和Ubuntu…

带大家来认识下SUMIF函数

如果您需要在Excel表格中对特定条件下的数据进行求和&#xff0c;那么SUMIF函数是一个非常有用的工具。SUMIF函数允许您在满足指定条件的情况下&#xff0c;将符合条件的单元格的值相加起来。在本文中&#xff0c;我们将向您介绍如何使用SUMIF函数来处理您的表格数据。 如下图…

想定制鞋子?先给脚部建模吧!

最近灌篮高手的电影正在火热上映中&#xff0c;湘北大战山王的比赛从漫画搬上了大荧幕&#xff0c;看得人热血沸腾&#xff0c;直呼“爷青回”&#xff0c;恨不得马上换上球衣球鞋&#xff0c;再去球场上挥汗如雨一番。 灌篮高手 同时NBA的季后赛也在如火如荼的进行中&#xf…

Cmake学习记录(九)--使用Cmake交叉编译Android .so库

文章目录 一、前言二、使用NDK进行编译的相关代码四、使用交叉工具链进行编译四、参考链接 一、前言 目前Android编译.so的话使用Android Studio比较简单&#xff0c;但是有时候时候Android Studio的话还需要创建一个Android的项目&#xff0c;这里记录下脱离Android Studio单…

华为OD机试真题B卷 Java 实现【百钱买百鸡问题】,附详细解题思路

一、题目描述 公元五世纪&#xff0c;我国古代数学家张丘建在《算经》一书中提出了“百鸡问题”&#xff1a;鸡翁一值钱五&#xff0c;鸡母一值钱三&#xff0c;鸡雏三值钱一。百钱买百鸡&#xff0c;问鸡翁、鸡母、鸡雏各几何&#xff1f; 现要求你打印出所有花一百元买一百…

2023-05-31-[音视频处理] FFmpeg使用指北1-视频解码

本文将详细介绍如何使用ffmpeg 4.4在C中解码多种格式的媒体文件&#xff0c;这些媒体文件可以是视频、视频流、图片&#xff0c;或是桌面截屏或USB摄像头的实时图片。解码文件后&#xff0c;还将每帧图片转换为OpenCV的Mat格式以供后续使用。 文章目录 1 基于ffmpeg的媒体文件解…

Java之旅(五)

运算符 算术运算符 加法&#xff08;&#xff09;减法&#xff08;-&#xff09;乘法&#xff08;*&#xff09;除法&#xff08;/&#xff09;取余&#xff08;%&#xff09;一元运算符 自增运算符&#xff08;&#xff09;自减运算符&#xff08;--&#xff09;变量前就先运…

基于Yarn搭建Flink

基于Yarn搭建Flink 1. 概述 1.1 Yarn 简介 Apache Hadoop YARN是一个资源提供程序&#xff0c;受到许多数据处理框架的欢迎。Flink服务被提交给 YARN 的 ResourceManager&#xff0c;后者再由 YARN NodeManager 管理的机器上生成容器。Flink 将其 JobManager 和 TaskManager…

Apache DolphinScheduler——开源大数据调度器神器(国人之光)

本文已参与「新人创作礼」活动&#xff0c;一起开启掘金创作之路。 1. 简 介 Apache DolphinScheduler(海豚调度),国人之光&#xff0c;是许多国人雷锋开源在Apache的顶级项目&#xff0c;主要功能就是负责任务的调度处理。 1.1 概 念 Apache DolphinScheduler是一个分布式去…

CentOS6 通过shell脚本的离线安装MySQL5.7.40(rpm)

说明: 在项目的实施过程中,多次遇到安装MySQL的工作,尤其在内网环境下,无法使用在线yum源,只能使用源码或采用rpm离线安装的方式进行安装,在安装过程中会遇到各种各样的问题,小编特地就rpm离线安装方式进行了整理及验证,并通过shell脚本的方式实现一键安装。使用此脚本…

软件性能测试有哪些方法?性能测试报告怎么编写?

性能测试是通过自动化的测试工具模拟多种正常、峰值以及异常负载条件来对系统的各项性能指标进行测试。在软件的质量保证中起着重要的作用&#xff0c;它包括的测试方法丰富多样。 一、常用的软件性能测试方法包括以下几种&#xff1a; 1、负载测试&#xff1a;模拟真实用户场…

连续十年亏损,哔哩哔哩估值遭质疑

来源&#xff1a;猛兽财经 作者&#xff1a;猛兽财经 财务业绩 2023年3月2日&#xff0c;哔哩哔哩&#xff08;BILI&#xff09;公布了其2022年第四季度和2022财年全年的财务业绩&#xff0c;财报显示哔哩哔哩的用户数量和收入均实现了稳步增长。2022年第四季度的总收入达到了…

【MySQL】单表获取库存数

系列文章 C#底层库–MySQLBuilder脚本构建类&#xff08;select、insert、update、in、带条件的SQL自动生成&#xff09; 本文链接&#xff1a;https://blog.csdn.net/youcheng_ge/article/details/129179216 C#底层库–MySQL数据库操作辅助类&#xff08;推荐阅读&#xff0…