1 什么是轨迹数据挖掘
得益于空间定位技术、传感器网络的飞速发展,空间定位传感器在飞机、舰船、汽车以及手持设备上得到普遍使用,产生并积累了海量的移动目标时空轨迹数据。这些时空轨迹数据内嵌于连续的空间,数据本身在时间与空间上存在很强的自相关性,其中隐含的模式往往具有局部性的特点,从而使得面向时空轨迹数据的挖掘具有较高的复杂性。过去十几年来业界提出了一些列的技术与方法来分析挖掘海量、高维的时空轨迹数据,萃取轨迹数据中隐含的价值知识,从而催生出众基于轨迹数据、多面向不同业务场景的上层应用,如智能交通系统、智慧城市/城市计算、飓风预测等。
现有的位置服务,通常直接使用用户提供的位置数据,缺乏对这些数据的分析和挖掘,忽略了这些位置数据中蕴含的信息和知识。如何利用数据挖掘和机器学习等技术从个人/车辆轨迹数据中获取知识,并利用这些知识来定制更加智能的基于轨迹的位置服务。
1.1 轨迹数据的基本特征
轨迹数据,通俗地讲就是连续的定位位置点数据,其区别于其他一般点线面等地理实体在于其带有连续的时间维度信息。轨迹数据的主要特征包括其核心要素和采集环境特征2个方面:
(1)核心要素特征:时间、位置坐标(二维/三维/多维)
(2)其他环境特征:设备型号/系统、轨迹定位模式、轨迹点位精度、加速度、采样率等。
1.2 轨迹数据的采集
轨迹点来源于设备的定位数据,不同场景的定位方式可参考前文《之二:移动定位、导航与互联网地图》,一般来说,用户轨迹数据来源于手机的GPS(或北斗)定位模块,应用软件通过调用系统API来触发采集指令,因手机定位模块属于高耗能功能,故一般不能像车载GPS模块那样24小时连续不间断采集,且如采集轨迹点数据量较大,对后端存储也是挑战。故通常需设置以下采集策略:
(1)灵活设置采集时机/时段,只采集业务关键节点位置;
(2)在采集端进行轨迹预处理后再上传,包括轨迹压缩,失败检测及时重采等;
(3)保留定位精度信息,以此调整采样频率,或作为后续挖掘时的权重参考。
1.3 轨迹数据的挖掘内涵
从轨迹中可挖掘的知识包括:个人数据中挖掘出的用户行为,意图,经验和生活方式;集合多人数据来发现热点地区和经典线路理解人与人的相关性,以及人与地域之间的活动模式等。

从轨迹数据挖掘全生命周期又可以分为如下几个方面:
(1)时空轨迹数据预处理:时空轨迹数据预处理是时空轨迹数据挖掘的基础,包含噪声过滤、轨迹分段、停留点检测、轨迹压缩、地图匹配等内容。其中噪声过滤目的是剔除轨迹中因传感定位设备误差造成的显著偏离正常范围的数据点或者航迹段;轨迹分段是通过时间分段、空间形状、语义含义将轨迹分段,便于后续的聚类分类,例如人的一天出行的轨迹可分段为家到工作地、工作地到商场、商场到地铁站、地铁站到家等几段;停留点/驻留区域检测指找出轨迹段中含有特定语义的轨迹段,如逛商场或吃饭;轨迹压缩主要采用一定的算法在不丢失轨迹原有的特征情况下,压缩数据规模,降低存储处理的难度;地图匹配主要实现轨迹与路网的匹配。
(2)时空轨迹数据管理:旨在对海量时空轨迹数据构建时空索引,满足大量应用从轨迹库中对原始轨迹数据的即席查询分析需求。典型的即席查询需要包括最近邻查询(the nearest neighbors)与范围查询(Range queries)。轨迹间距离度量是最近邻查询的基础,常见的距离度量算法将在后续进行详细讨论。此外历史轨迹数据管理和实时轨迹数据管理采用不同的方法进行处理。
(3)时空轨迹数据分析挖掘:包括时空轨迹数据的不确定性处理、轨迹模式挖掘。其中轨迹数据不确定性是指目标在采用时间区间之间的位置不确定性,处理包含两个方面的研究内容,其一,试图通过建模与引入背景知识来减少轨迹的不确定性;其二对时空轨迹数据的隐私保护研究。轨迹模式挖掘主要研究目标对象的移动模式,伴随模式、周期模式、频繁序列模式、关联模式、轨迹聚类。
(4)时空轨迹数据分类与预测:轨迹分类采用有监督学习方法将轨迹划分为某些类别,同时构建分类模型,用于实时轨迹的分类识别。轨迹预测包含两个层次的预测,其一基于当前状态的位置与轨迹预测;其二基于当前密度、事件、历史知识相结合的时间序列预测。预测是轨迹数据挖掘分析的最终应用需求,同时也是当前研究实现难度较大的部分。
(5)时空轨迹数据异常检测:包含两个层次的异常检测。第一层次基于当前运动状态与背景知识的异常检测,如飞机掉高等;其二、通过与样本库中的轨迹模式进行对比分析,当前轨迹的异常值在某些度量方面与其他数据有着显著的不同或者是不符合预期模式的事件或者观察值,如车祸。
(6)时空轨迹数据转移处理:通过一定的数据,可将轨迹数据转换为其他格式数据,如图、矩阵、张量,一方面可以降低数据规模,另一方面,可以借助现有的数据挖掘技术(图挖掘、协同过滤CF、矩阵因式分解MF、张量分析TD)拓展时空轨迹挖掘的方法。
2 轨迹数据预处理
轨迹数据挖掘的一般处理流程包括:用户/实体轨迹点抽取、分段、去噪(或平滑)、质量评估等,是后续进行轨迹知识挖掘的基础。
2.1 轨迹数据清洗压缩
一些应用场景中,轨迹数据采样量通常非常大,占用较多的网络流量消耗,但被采样的实体(手机/车辆等)并不是一直处于运动中,所以可以对一些相对静止的时刻减少采样/上传;另外,大规模的用户/车辆轨迹也给分析处理带来压力,如轨迹聚类计算等,在后端处理中,也可以先对轨迹点进行同分布的压缩采样,后再处理。
(1)采集端压缩
采集端压缩有2个手段,一是直接根据场景重要性,适当降低轨迹采样率,即增大采样时间间隔,或是改时间间隔采样为事件触发采样等;另一方面,则是对采样的数据,在上传后端前,对相对静止状态的轨迹点进行压缩(一般业务场景中,目标对象相对静止状态是占比更大的),具体的做法是,在速度较慢的轨迹点数据中,增加一维“持续时间”,连续静止状态的轨迹点只需保留第一个即可,如此,就可以压缩掉大部分持续静态的轨迹点。
(2)后端压缩
对于后端压缩,如采集端没有进行静态轨迹点的压缩,那么在后端也可以同样处理。另外,在分析复杂空间分布规律且对轨迹时序不敏感时,则可以针对目标对象的整个轨迹空间划分N个格网小空间(N较大),每个小空间设置等比例随机采样率,或设置需保留的最终数量(自动确定采样率),这样确保最终采样的数据与原轨迹分布的一致性,参考算法实现如下(Compression类):
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.aliyun.odps.udf.UDF;
public class Compression extends UDF {
public String evaluate(String initstr,String retainNum){
String result="";
String mapkey="1";
try {
Map<String, List<Point>> map=new HashMap<String, List<Point>>();
if(initstr==null||"".equals(initstr)){
return "";
}
String[] ks=initstr.split(";");
List<Point> list=new ArrayList<Point>();
if(ks!=null&&ks.length>0){
for(int i=0;i<ks.length;i++){
String lonlat[]=ks[i].split(",");
Point point=new Point(Double.parseDouble(lonlat[0]),Double.parseDouble(lonlat[1]));
list.add(point);
}
map.put(mapkey, list);
Map<String, List<Point>> resultMap=PointReduce.Reduce(map,Integer.parseInt(retainNum));
list=resultMap.get(mapkey);
for(int i=0;i<list.size();i++){
result+=list.get(i).getX()+","+list.get(i).getY();
if(i<list.size()-1){
result+=";";
}
}
}
return result;
} catch (Exception e) {
e.printStackTrace();
return "Parms Error";
}
}
}
2.2 轨迹分段与匹配
2.2.1 轨迹分段
轨迹分段是对长时段轨迹(例如以天或月为单位)的合理切分与标注,切分后的子轨迹段代表一次出行的记 录。轨迹分段不仅降低了计算复杂度,同时提供了更加丰富的知识。例如,子轨迹模式挖掘,轨迹分段的核心是理解时空移动特征,轨迹分段的主要方式有基于时间阈值、几何拓扑和轨迹语义这 3 种基本策略,业务场景中,最常用的是基于时间阈值分段,也即轨迹中断的时间大于某个阈值即断开。另外,也有利用旅游者的经验和地点兴趣度推荐热门旅游景点,利用历史数据挖掘获得停留点,将原始轨迹数据分段。轨迹的分段极大地提高了挖掘效率。文献[2]融入频率权重来优化兴趣点挖掘模型,结合轨迹分段思想挖掘兴趣点区域。
2.2.2 轨迹路网匹配
路网匹配是结合轨迹与数字地图,将 GPS 坐标下的采样序列转换成路网坐标序列.经过路网匹配后,每个 轨迹采样点都映射到一个路网位置.路网匹配对于评估交通流量、引导车辆导航、预测车辆行驶路线、从出发 地到目的地之间寻找频繁旅游路线等具有重要的作用,但是路网匹配是较为复杂的问题。路网匹配主要有在线和离线两种方式:
(1)在线匹配更强调实时性,当每一个 GPS 位置信息被接收时,算法需要在路网中进行识别匹配,该方法主 要应用于车辆导航、追踪等;
(2)而离线匹配主要针对静态历史数据匹配,其精度要求更高,只有整个行程数据匹配均已完成才提供匹 配结果,并且尽可能准确地匹配车辆行驶路线.
对于离线路网匹配问题,文献[3]利用 Dijkstra 最短路径算法来确定轨迹与地图序列的距离,从而实现轨迹匹配;对于在线路网匹配问题,文献[4]提出了使用坐标系观测用户位置的拓扑分析方法,该方法假定没有预期行驶路线和任何速度信息。文献[5]提出了基于模糊逻辑理论的路网匹配算法,针对不同密度和不同复杂程度的路网进行匹配,其结果表明,该算法精度较高。
2.3 轨迹数据质量评估
所谓轨迹质量评估,其实是通过检测目标对象实体的轨迹基础指标,如采样率、噪点率,缺失率,精度等来衡量是否符合具体业务场景的需要;通常我们需要实现一个Track类来计算track的基础指标,同时也需要一个实例来实现业务相关质量指标的实际计算,这里直接给出个人实现的轨迹质量类参考代码(Java):
(1)轨迹质量指标计算(PostmanTrackQualityAnalysis)实现:
import java.util.List;
import com.aliyun.odps.udf.UDFException;
import com.aliyun.odps.udf.UDTF;
import com.aliyun.odps.udf.annotation.Resolve;
import com.alipay.cnlbs.udf.algo.semanticmining.StayPointDetectionAlgo;
import com.alipay.cnlbs.udf.model.TrackPoint;
import com.alipay.cnlbs.udf.model.Tracks;
import com.alipay.cnlbs.udf.algo.preprocessing.PostmanTrackPreprocessingAlgo;
import com.vividsolutions.jts.geom.Geometry;
import com.alibaba.fastjson.JSON;
@Resolve({"string,string->" +
"string,bigint,double,double,bigint,string,double,double,double,bigint,bigint,bigint,bigint,bigint,bigint,string,"
+ "string,double,string"})
public class PostmanTrackQualityAnalysisUdtf extends UDTF {
@Override
public void process(Object[] args) throws UDFException {
try {
String deviceid = (String)args[0];
String gpsPointStr = (String)args[1];
String result = "";
if (gpsPointStr == null || gpsPointStr.length() < 3) {
forward(deviceid, -1L, -1.0, -1.0, -1L, "null", -1.0, -1.0, -1.0, -1L, -1L, -1L, -1L, -1L, -1L,
"null", "null", -1.0, "null");
}
PostmanTrackPreprocessingAlgo postmanTrackAlgo = new PostmanTrackPreprocessingAlgo();
StayPointDetectionAlgo stayPointDetectionAlgo = new StayPointDetectionAlgo();
//解析udf传入的string
List<TrackPoint> tpList = postmanTrackAlgo.ReadTrackStr(gpsPointStr);
//对原始轨迹做时间排序、去除重复点、轨迹分段、轨迹去噪
Tracks trajectoryList = postmanTrackAlgo.preProcess(tpList);
//停留点挖掘
Geometry stayPointList = stayPointDetectionAlgo.StayPointExtract(trajectoryList);
//统计预处理后的轨迹特征
trajectoryList.CalculateTracksInfo();
forward(deviceid
, trajectoryList.getTotalptnum()
, trajectoryList.getTotaltrkduration()
, trajectoryList.getTotaltrklength()
, trajectoryList.getTracksegnum()
, JSON.toJSONString(trajectoryList.getHistoptnum())
, trajectoryList.getAvgsampleinterval()
, trajectoryList.getAvgsamplespeed()
, trajectoryList.getAvgsampledistance()
, trajectoryList.getTrkareacoverage()
, trajectoryList.getTrkdurationcoverage()
, trajectoryList.getDuplicateptnum()
, trajectoryList.getNoiseptnum()
, trajectoryList.getStayptnum()
, trajectoryList.getStayareanum()
, trajectoryList.getSystem()
, JSON.toJSONString(trajectoryList.getHistoptprecise())
, trajectoryList.getPreciseptcoverage()
, JSON.toJSONString(trajectoryList.getHistolocationmode())
);
} catch (Exception e) {
forward(args[0] + ":" + e, -1L, -1.0, -1.0, -1L, "null", -1.0, -1.0, -1.0, -1L, -1L, -1L, -1L, -1L, -1L,
"null", "null", -1.0, "null");
e.printStackTrace();
}
}
}
(2)轨迹基础指标算子类(PostmanTrackPreprocessingAlgo)实现:
import java.util.ArrayList;
import java.util.List;
import com.cainiao.cnlbs.udf.para.ConstTrack;
import com.vividsolutions.jts.geom.*;
import com.cainiao.cnlbs.udf.model.Tracks;
import com.cainiao.cnlbs.udf.util.TrackPointUtil;
import com.cainiao.cnlbs.udf.model.Track;
import com.cainiao.cnlbs.udf.model.TrackPoint;
/**
*/
public class PostmanTrackPreprocessingAlgo {
private static final double EPSILON = 1.0E8;
TrackPointUtil trackPointUtil = new TrackPointUtil();
private GeometryFactory geometryFactory = new GeometryFactory(new PrecisionModel(), 4326);
public List<TrackPoint> ReadTrackStr(String gpsPointStr) {
if (gpsPointStr == null || gpsPointStr.length() < 3) {
return null;
}
List<TrackPoint> pointList = new ArrayList<>();
String[] dotArray = gpsPointStr.split(";");
for (String dot : dotArray) {
String[] ele = dot.split(",");
if (ele.length == 8) {
&


412

被折叠的 条评论
为什么被折叠?



