TraClus轨迹聚类算法原理及java版实现

8 篇文章 0 订阅

  前一阵子我们部门接到了业务那边的一个需求。想通过用户的wifi数据计算出商场内用户最喜爱走的线路。其实说白了就是用户轨迹聚类。根据业务的需求,我们最终采用了traClus聚类算法。traClus算法相比于其它的轨迹聚类算法的一大不同点是,该算法先把一个用户的轨迹分成了若干线段,然后把基于所有用户的轨迹生成的线段放到一个集合中进行聚类。

算法本身可以划分为三个部分,分别为:

用户轨迹分段。 
分段轨迹聚类。
计算每个类簇的代表轨迹。

  虽然算法大体可以分为以上三步,但为了实现1、2两步的算法,traclus的作者提出了一种新的计算线段距离的方式。算法的第一部分是根据这种新的距离定义来对轨迹进行划分。第二部分采用了DBSCAN聚类的思想把相近的线段聚类。第3部分则找出簇中的代表轨迹(此轨迹不一般情况不会是簇中的线段直接组合而成)。下面我们详细的讲解一下距离的定义及算法的三部分。

一、线段距离的定义

  图片名称

  如上图,作者提出了三种距度量来表示两条线段间的距离。分别是垂直距离、平等距离和角度距离。需要注意的是角度距离 l θ l_\theta lθ 9 0 ∘ ≤ θ ≤ 18 0 ∘ 90^\circ \le \theta \le 180^\circ 90θ180。有的同学可能会说上面的公式不是对等的,线段j和线段i要怎么区分,这个我们下面会讲到。

二、traclus算法

1、用户轨迹分段

这部分的主要任务是:把用户的轨迹按照相关算法分成若干段。举个例子,有一条5个点的轨迹 p 1 p 2 p 3 p 4 p 5 p_1p_2p_3p_4p_5 p1p2p3p4p5,通过我们的分段算法确定p3是一个切分点,把这条轨迹分成 p 1 p 3 p_1p_3 p1p3 , p 3 p 5 p_3p_5 p3p5两条线段。但这个切分点是怎么确定的呢,这里作者采用MDL原则(最小描述原则),通过垂直距离 d ⊥ d_⊥ d与角度距离 d θ d_{\theta} dθ定义了两个度量 M D L p a r MDL_{par} MDLpar M D L n o _ p a r MDL_{no\_par} MDLno_par如果 M D L p a r MDL_par MDLpar 大于 M D L n o _ n o p a r MDL_{no\_nopar} MDLno_nopar则在当前点的前一个点进行切分。下面是具体的细节描述。

  a) 分段度量:定义了两个度量公式:
     i) L ( H ) = ∑ j = 1 p a r i − 1 l o g 2 ( l e n ( p c j , p c j + 1 ) ) L(H)=\sum^{par_i - 1} _ {j=1} log_2(len(p_{c_j} , p_{c_j + 1})) L(H)=j=1pari1log2(len(pcj,pcj+1))
    ii) L ( D ∣ H ) = ∑ j = 1 p a r i − 1 ∑ k = c j c j + 1 − 1 { l o g 2 ( d ⊥ ( p c j p c j + 1 , p k p k + 1 ) ) + l o g 2 ( d θ ( p c j p c j + 1 , p k p k + 1 ) ) } L(D|H)=\sum^{par_i - 1} _ {j=1} \sum^{c_{j+1} - 1}_{k=c_j}\{log_2(d_{\perp}(p_{c_j}p_{c_{j+1}} , p_k p_{k+1})) + log_2(d_{\theta}(p_{c_j}p_{c_{j+1}} , p_k p_{k+1}))\} L(DH)=j=1pari1k=cjcj+11{log2(d(pcjpcj+1,pkpk+1))+log2(dθ(pcjpcj+1,pkpk+1))}
  只看上面两个公式比较晦涩,下面我们看下在实际中是怎么应用上面两个公式的。从下图中可以看 L ( H ) L(H) L(H)是直接计算两个点之间的距离然后取以2为底的对数,与上面 L ( H ) L(H) L(H)的连加公式好像对不上,其实这个与我们的计算类别有关,如果我们计算的是 M D L p a r MDL_{par} MDLpar那么我们所观察的线段其实是 p c 1 p c 2 p_{c1}p_{c2} pc1pc2,就是下面图中的式子,直接计算 p c 1 p c 2 ( p_{c1}p_{c2}( pc1pc2( p 1 p 4 p_1p_4 p1p4)的长度,然后取对数。如果我们计算的是 M D L n o _ p a r MDL_{no\_par} MDLno_par,那么就是 l o g 2 ( l e n ( p 1 p 2 ) + l e n ( p 2 p 3 ) + l e n ( p 3 p 4 ) ) log_2(len(p_1p_2) + len(p_2p_3) + len(p_3p_4)) log2(len(p1p2)+len(p2p3)+len(p3p4)) 。然后我们再说下 L ( D ∣ H ) L(D|H) L(DH)这个式子,这个式子中只有垂直距离( l ⊥ l_\perp l)和角度距离( l θ l_\theta lθ),我们没有看到平行距离( l ∣ ∣ l_{||} l∣∣),有同学分析说,是因为首尾相加的线段平行距离( l ∣ ∣ l_{||} l∣∣)距离为0,这个说法我不完全认同,因为从图中我们可以看出 p 1 p 4 p_1p_4 p1p4 p 2 p 3 p_2p_3 p2p3的水平距离不是为0的。也有可能是因为加入了平行距离会使不同长度(线段数)的轨迹计算 L ( D ∣ H ) L(D|H) L(DH)时不公平。但这只是猜测,也许作者就是不想用,或者用了发现效果不好。然后我们说另一个问题,就是在线段距离的定义的那个图中,哪条线段是 L i L_i Li哪条是 L j L_j Lj的问题,原文中"We assign a longer line segment to L i L_i Li and a shorter one to L j L_j Lj without losing generality." 直接简单粗暴的把较长的线段设为了 L i L_i Li,较短的设为了 L j L_j Lj。这样做有两个好处,首先长线段为 L i L_i Li使平行距离更容易落在 L i L_i Li内,更好理解。而别一个好处是符合实际的物理意义,如下图,我们在算 p 4 p_4 p4这个切分点时,较长的线段一直是 p 1 p 4 p_1p_4 p1p4,只有在 p 1 p 2 p 3 p 4 p_1p_2p_3p_4 p1p2p3p4形成一个弧度很大的轨迹时,才会出现 p 1 p 2 p_1p_2 p1p2 p 2 p 3 p_2p_3 p2p3 p 3 p 4 p_3p_4 p3p4中某一段的距离比 p 1 p 4 p_1p_4 p1p4长,但一般不会出现这种情况,因为轨迹角度过大的话,路径中的某个点就成为了切分点,不会让这种大角度轨迹出现。
    
  b)切分依据:
   M D L ( c o s t ) = L ( H ) + L ( D ∣ H ) MDL(cost)=L(H) + L(D|H) MDL(cost)=L(H)+L(DH)
  切分的依据是上面那个公式,对于一段轨迹,我们如果要判断在某个节点是否要切分,首先要计算这个节点的 M D L p a r MDL_{par} MDLpar M D L n o _ p a r MDL_{no\_par} MDLno_par , 计算 M D L p a r MDL_{par} MDLpar时,我们直接按照上面的公式计算,计算 M D L n o _ p a r MDL_{no\_par} MDLno_par时,只需令上面公式中的 L ( D ∣ H ) L(D|H) L(DH)等于0,其实此时就是计算的这一段轨迹的长度。论文中给出切分依据是比较 M D L p a r MDL_{par} MDLpar M D L n o _ p a r MDL_{no\_par} MDLno_par的大小,如果 M D L p a r MDL_{par} MDLpar 大于 M D L n o _ p a r MDL_{no\_par} MDLno_par 则在前一个节进行切分。 但在我们比较的是 M D L p a r MDL_{par} MDLpar M D L n o _ p a r + ξ MDL_{no\_par}+\xi MDLno_par+ξ,其中 ξ \xi ξ是一个超参。通过这个超参数,可以调节线段切分的效果。
  c)切分算法:下面是具体切分流程的伪代码。
    

2、用户轨迹聚类

这部分的主要任务是:使用DBScan的思想把第一部分划分好的线段聚成类 ,DBScan的算法不是本篇的重点,这里不做细解,过程见下图。
    

3、代表轨迹计算

  这部分的主要任务是:对上一步聚类的结果进行计算,在每一个簇中,找出一条代表轨迹。
   算法流程:
  a) 对一个簇中的所有向量(线段)求平均向量。
    
  b)把整个簇内的向量按平均向量旋转。(旋转到 x x x轴平行于a)步骤求得的平均向量。
    
    
  c)使用垂直于 x x x轴的sweep line延 x x x轴平扫,如果与这条直线相交的向量大于等于设置的最小值(MinLns),则计算这些相交点的 y y y坐标的平均值,形成点 ( x i , y ‾ i ) (x_i , \overline{y}_i) (xi,yi) , 重复此过程,直到sweep line的右边再无向量的起始或结束点。
    
    
  d)把c)步骤生成的点旋转回原来的角度,连接成一条轨迹,这条轨迹就是这个簇的代表轨迹。
  e)对所有的簇重复a)、b)、c)、d)步骤

三、算法效果图

  我实现了一版java版的traclus算法,下图使用论文中的数据(deer95)跑的一个结果,有兴趣的同学可以去下载我的源码. 跑一跑。有问题可以留言交流。
在这里插入图片描述

  • 16
    点赞
  • 66
    收藏
    觉得还不错? 一键收藏
  • 42
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 42
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值