基于隐马尔科夫链模型的地图匹配问题 map matching based on HMM

完整项目文件见我的仓库

一、数据存储方式

  1. 数据点、带时间的数据点:使用struct Posi 、 Posi_t。前者用于road里的数据点,后者用于track里的数据点。
  2. 图:使用邻接表,用vector数组实现。定义struct road存储路段id,数据点个数,路段长度,开始的点,结束的点以及道路等级。里面还有一个Posi型vector存储点信息。
  3. 轨迹Posi_t的vec组成的vec。
  4. 格子:长度、数量均可变,用二维vector实现
  5. 当前的概率与最对应的前置状态:用map实现
  6. 最短距离:用map<int,double>型的vector,每个map代表始发点,其中第一个int是到达点的id,第二个double是最短路的长度。

二、函数介绍

    1. cqlt_pp_eu:输入两个点,返回二者的欧拉距离。定义为内联函数。
    2. read():先读取道路信息,忽略道路等级的string,顺便得到道路的长度、道路最西、最南的值。由于输入数据把两条相反的路放在相邻位置,如果是二者终点、起点相同,则二者为友路。然后读取轨迹信息。
    3. initial():根据read得到的经纬度最小值,结合定义的格子大小,计算每条路上每个点应该属于哪个格子,然后把路的id插入格子里,同时插入周围的8个格子中。插入完成后对格子中去除重复边。
    4. no_dunjiao:输入三个点,第一个点是轨迹点,另外两个个是路段起始点。返回一个布尔值,判断路段起始点是否是钝角。都不是则返回false。
    5. cqlt_s:输入三个点,返回这三个点对应三角形的面积。
    6. cqlt_posi_to_edge,输入一个点和一个边,利用刚刚的面积和路段距离计算该点到此边的距离,并判断垂线是否在路段上。返回路段和点的距离。
    7. cqlt_start_to_posi:输入一个点和一条边,返回这个点到路段开始点的距离
    8. Dijkstra():用优先队列优化的版本。对shortestlens经行修改。首先循环始发点,对于每个始发点,创建一个<double,int>型小端优先队列double是首发点到顶点为int值最短路径长度。每次pop一个pair出来,判断是否经过pair对应的顶点会不会更优。当q为空时、最短路径长度已经超过约定值、已经有50条最短路时就结束,将结果加入shortestlens中。最开始是存路径,用一个单独的函数计算距离。但是这样会带来额外的时间开销。所以直接往map里存距离就行,避免重复计算,直接预处理。但是这样就会带来一个问题,就是有可能会访问到不存在的元素,所以需要判断key是否在map里。
    9. cqlt_p2p_onroad:输入2点和2点对应的匹配上的边,利用刚刚的Dijkstra算法得到的路径距离,返回二者在地图上的路径长度。
    10. guancegailv:输入一点和一边,根据点和边的距离,以及道路等级,由正态分布概率公式得到观测概率:

    1. zhuanyigailv:输入两点两边,计算出两点在地图上的距离dis,然后计算出转移概率。其中β是和t有关的超参,随着两点时间差越来越大,β就越来越大:

    1. match:输入一条轨迹,一个空的vector存储前向边,和一个空的vector存储最后的概率。根据轨迹得到所在格子,如果是第一个点就只计算观测概率,之后所有的点还要计算状态转移概率。将遍历每个点的所有边,将状态转移概率与所有前向边概率相乘。然后找到乘积最大的一项,得到对应的前向边与概率,乘观测概率,更新,然后开始下一次遍历。这样结束就得到每一点中所有匹配边的前向边以及最终的概率,这两个就是要修改的“返回值”。
    2. print:传入前向边矩阵和最终概率矩阵,找到最大概率的一项,在前向边矩阵中向前遍历,直到最开始。然后输出遍历结果。

三、优化

1.准确度优化:

    1.距离计算:由于1度大概对应111km实际长度,所以会有个系数,让每个点都乘以这个系数,可以得到相应的优化。(有小作用)

    2.反向路:在匹配的时候,由于两条相邻的反向路,有可能会带来观测概率的不准确。于是判断道路方向与前进方向是否相同。如果相反,如果这条路有友路,就采用其友路,如果没有友路,就采用长度第二的路。(作用不大)

    3.匹配的边的范围:将原来较大的格子缩小为1/3,每次匹配不仅将原来的格子放进去,而且把周围8个格子的边也加进来(作用较大)

    4.输出时检查重复边:由于不会绕圈,所以一条边除了相邻时会重复,距离2-5条边如果出现了重复边,那么就应该把这之间的其它边置为当前边。(作用很大)

    5.归一化:在匹配过程中,把概率置为0-1之间,避免越乘越小,以至于精度不够。(作用不大)

    6.道路等级:由于等级越高的道路数量会越少,所以从概率上将,匹配到高等级的道路概率会略小于普通道路。

    7.道路限速:根据轨迹的速度大小与道路限速比较,越接近的就转移概率越大。(作用不大,并且会带了较大的内存开销,会爆内存,因此没有启用)

2.时间优化

    1.采用emplace_back代替push_back,提高性能。(作用不大)

    2.在遍历的时候提前得到size,而不是每次都调用size函数(作用不大)

    3.在向格子里插入边的时候直接插在周围8个格子里,而不是在匹配过程中加边的时候一个格子一个格子的加边,直接对所在格加边就行(作用很大,不但时间减小,而且内存也显著减小)

    4.在向格子里加边完成后对格子里的边去重。(作用非常大,尽管看似比较蠢,但是由于匹配的边数量急剧减少,避免大量重复计算)

    5.格子的大小:如果减小每个格子的大小,就会减少边的数量,就减少时间(作用很大,但是会降低准确率)

    6.直接在Dijkstra里得到距离,直接预处理出,而不是通过另一个函数计算距离(作用很大)

    7.在Dijkstra里,结束的判断标志可以适当减小,与格子长度相匹配(作用很大,还会同时降低空间消耗)

    8.在对准确率要求不高的时候关闭准确率优化,可以提高速度。

四、调节参数

需要调节的参数一共2个,分别是Dijkstra中的停止距离l,格子的大小h,l和h越大,带来的时间开销就越大,但是准确度就越高。

算法可以达到70、90、93的准确度。

  1. 70准确度下,l=0.0005,h=0.001
  2. 90准确度下,l=0.0006,h=0.0016
  3. 93准确度下,l=0.0008,h=0.0024

五、效率分析

假设:

输入的边数为e,顶点数为n,平均每个边有a个顶点;

输入的轨迹数为m,平均每个轨迹有b个顶点;

格子数为x,平均每个格子去重前有y个边,去重后又z个边。

则:

时间复杂度:

  1. 读入函数复杂度为O(ea+mb)
  2. 初始化函数复杂度为O(ea+x2ylogy)
  3. 迪杰斯特拉算法复杂度为O(nzlogz)(由于边数和顶点数大致相等,只会在一个格子大小的范围内dijkstra)
  4. 每次得到观测概率和状态转换概率的复杂度为O(a),因为要对边逐段分析。
  5. 每个轨迹的每个点需要匹配O(z2)次,每次都要求状态转移概率(除了第一次)以及观测距离,所以每次匹配的复杂度为O(z2ab)
  6. 每次输出的的复杂度为O(b+z)
  7. 一共要匹配m次

因此,程序的时间复杂度为:

O(ea+mb+ea+ x2ylogy+ nzlogz+mz2ab+ b+z)

= O (ea+m z2ab + x2ylogy+ nzlogz)

空间复杂度:

  1. 存边的空间复杂度为O(ea)
  2. 存轨迹的空间复杂度为O(mb)
  3. 存最短距离的空间复杂度为O(nz)
  4. 存前向边的空间复杂度为O(mbz2),概率矩阵空间复杂度为O(mz)

因此,程序的空间复杂度为:

O(ea+ mb+ nz+ mbz2+ mz)

= O(ea+mbz2+nz)

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
马尔科夫模型HMM)是一种统计模型,用于描述一个由藏状态和可观察状态组成的序列,并通过计算概率来对藏状态进行推断。HMM算法可以应用于许多领域,包括地图匹配地图匹配是将移动对象的轨迹数据与预先定义的地图进行对应的过程。HMM算法可以用于实现地图匹配,以下是实现地图匹配的基本步骤: 1. 数据预处理:将原始轨迹数据进行清洗和处理,包括去除噪声、填充缺失值等。 2. 地图建模:将地图划分为一系列的离散区域,例如网格或路段,并给每个区域分配一个藏状态。 3. 初始化HMM模型:定义HMM模型的初始状态概率矩阵、转移概率矩阵和观测概率矩阵。 4. 观测生成:将轨迹数据中的观测状态映射到地图的区域。 5. 动态规划:利用前向算法或维特比算法计算给定观测序列条件下的最优藏状态序列。 6. 地图匹配结果:通过最优藏状态序列映射到地图的区域,得到地图匹配结果。 7. 评估与优化:对地图匹配结果进行评估和优化,比较匹配结果与真实轨迹数据的差异,并可能采取进一步的优化措施。 HMM算法地图匹配中的优势是可以处理观测数据中的噪声和不确定性,并且具有较好的鲁棒性。然而,HMM算法也有一些限制,例如对初始参数的依赖和计算复杂度较高等。 综上所述,HMM算法可以实现地图匹配,通过对观测数据进行概率计算来推断藏状态序列,从而映射轨迹数据到地图上的区域。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值