作者复现了《基于轨迹聚类的船舶异常行为识别研究_胡智辉》的文章内容,对模型感兴趣的朋友可以下载文章深入研究。本文主要是分享复现过程中的算法实现。
本模型通过处理AIS数据得到船舶轨迹,通过计算改进的 Hausdorff 距离,对轨迹进行DNSCAN聚类,得到不同类型的航迹簇。主要包含以下内容
具体的代码原理比较繁琐,笔者时间精力有限,难以详尽描述,有需要的可以私信咨询。这里就直接分享部分源码
% clc
% close all
% clear all
% % %%
% % global noisenum
% % % %% 数据路径
% % % path='AIS1246-1.CSV';
% % % %% 计算H距离
% % % [data1,px,tempMapDis,tempMapV,tempMapHeading]=myHuasdoff(path);
% % % Hdist = (tempMapDis + tempMapV + tempMapHeading) / 3;
% % % %% 取距离中的较小值
% % % for i = 1 : size(Hdist,1)
% % % for j = i + 1 : size(Hdist,2)
% % % max1 = Hdist(i,j);
% % % if max1 < Hdist(j,i)
% % % max1 = Hdist(j,i);
% % % end
% % % Hdist(i,j) = max1;
% % % Hdist(j,i) = max1;
% % % end
% % % end
% load data.mat
% %% 设置聚类参数
% eps=0.056;
% MinNum=18;
% %% DBscan 聚类
% cluster_label=DBSCAN(Hdist,eps,MinNum);
% %% 计算聚类数
% cluster_num=max(cluster_label);
% %% 计算轨迹平均位置
% meanpos=zeros(length(cluster_label),2);
% for i=1:length(cluster_label)
% meanpos(i,1)=mean(data1(data1(:,1)==i,2));
% meanpos(i,2)=mean(data1(data1(:,1)==i,3));
% end
% %% 画图
% % %% plot trace
% figure
% Plottrace(data1,cluster_label)
% title(sprintf(['DBSCAN聚类结果(航迹示意图) \n邻域距离 = ' num2str(eps) ', 最小样本数 = ' num2str(MinNum) '\n航迹类别:' num2str(cluster_num) '类,噪声航迹:' num2str(noisenum) '条']));
% xlabel('经度')
% ylabel('纬度')
% %% plot meanpos
% % figure
% % Plotmeanpos(meanpos, cluster_label);
% % title(sprintf(['DBSCAN聚类结果(航迹平均坐标示意图) \n邻域距离 = ' num2str(eps) ', 最小样本数 = ' num2str(MinNum) '\n航迹类别:' num2str(cluster_num) '类,噪声航迹:' num2str(noisenum) '条']));
% % xlabel('经度')
% % ylabel('维度')
% % 逐类计数典型轨迹
% filename='典型轨迹数据.xlsx';
% DXcolor={'black','magenta'};
% DXindexlist=[15,36];
% Legendslist={'主航道出口船舶典型轨迹','主航道进口船舶典型轨迹'};
%
% for k=1:cluster_num
% data_ind=[];
% temp_trace_ind=find(cluster_label==k);
% for t=1:length(temp_trace_ind)
% data_ind1=find(data1(:,1)==temp_trace_ind(t));
% data_ind=[data_ind;data_ind1];
% end
% % Legendsname = ['第' num2str(k) '类航迹的典型航迹'];
% Legendsname=Legendslist{k};
% [DXfinalData{k},DXdatanew{k},DXpx{k},DXfData{k},DXMapDis{k},DXMapV{k},DXMapHeading{k}]=DXGJ(data1(data_ind,:),DXcolor{k},Legendsname,DXindexlist(k));
% datawriter(filename,DXfData{k},Legendsname)% end
% end
%
% % %%
% % addpath '识别数据集'
% % filename_train_in1='进口正常行为数据.xlsx';
% % filename_train_in0='进口异常行为数据.xlsx';
% addpath '正常与异常数据'
% filename_train_in1='进口正常轨迹数据.xlsx';
% filename_train_in0='进口异常轨迹数据.xlsx';
% [data_in1,finalData_in1]=makeData(filename_train_in1);
% [data_in0,finalData_in0]=makeData(filename_train_in0);
% stepNum=20;
% DistThre=linspace(1,250,stepNum);
% SogThre=linspace(1,8,stepNum);
% CogThre=linspace(1,8,stepNum);
% %
% % DistThre=1:0.01:250;
% DXTrace=DXfData{2};
% % ACC_P=[];
% % ACC_S=[];
% % ACC_C=[];
% for i=1:stepNum
% tDistThre=DistThre(i);
% tSogThre=SogThre(i);
% tCogThre=CogThre(i);
% [ACC_P(i),ACC_S(i),ACC_C(i)]=drawErrerRate(finalData_in1,finalData_in0,DXTrace,tDistThre,tSogThre,tCogThre);
% end
% %%
filename='阈值.xlsx';
data=xlsread(filename);
figure
plot(DistThre,[ACC_P.r],'-gp','DisPlayName','准确率')
hold on
plot(DistThre,1-[ACC_P.r],'-rd','DisPlayName','误警率')
xlabel('位置偏差')
legend
figure
plot(SogThre,[ACC_S.r],'-gp','DisPlayName','准确率')
hold on
plot(SogThre,1-[ACC_S.r],'-rd','DisPlayName','误警率')
xlabel('航速偏差')
legend
figure
plot(CogThre,[ACC_C.r],'-gp','DisPlayName','准确率')
hold on
plot(CogThre,1-[ACC_C.r],'-rd','DisPlayName','误警率')
xlabel('航向偏差')
legend
%% 2类:进口 1类出口
global DistThre SogThre CogThre
DistThre=60;
SogThre=2.8;
CogThre=3.8;
addpath '正常与异常数据'
filename_in='验证进口道船舶异常行为.xlsx';
tracetype=input('请选择要验证的船舶类型:1(出口)/ 2(进口)');
try
DXTrace=DXfData{tracetype};
catch
disp('输入错误')
return
end
checkTrace(filename_in,DXTrace);```
function [data1,px,tempMapDis,tempMapV,tempMapHeading]=myHuasdoff(datapath)
data1 = xlsread(datapath);
[sy,sx] = size(data1);
tempx = 1;tempy = 1;
global finalData;
finalData{1,1} = data1(1,:);
px(1,1) = 1;
px(1,2) = data1(1,1);
for i = 2 : sy
if data1(i,1) ~= data1(i - 1,1)
tempx = tempx + 1;
px(tempx,1) = tempx;px(tempx,2) = data1(i,1);
finalData{tempx,1} = data1(i,:);
tempy = 1;
else
tempy = tempy + 1;
finalData{tempx,tempy} = data1(i,:);
end
end
global n;
global yy;
xx = size(finalData,1);
yy = size(finalData,2);
n = xx;
tempMapDis = zeros(n,n);
tempMapV = zeros(n,n);
tempMapHeading = zeros(n,n);
%%计算最小值
for i = 1 : xx
for j = 1 : xx
......
end
end
%%归一化
for i = 1 : n
for j = 1 : n
... ...
end
end
end
disGy = disGy - disMin;
vGy = vGy - vMin;
headingGy = headingGy - headingMin;
for i = 1 : n
for j = 1 : n
......
end
end
end
function [labels, isnoise]=DBSCAN(D,epsilon,MinPts)
C=0;
n=size(D,1);
labels=zeros(n,1);
% D=pdist2(X,X);
% D=X;
visited=false(n,1);
isnoise=false(n,1);
for i=1:n
if ~visited(i)
visited(i)=true;
Neighbors=RegionQuery(i);
if numel(Neighbors)=MinPts
Neighbors=[Neighbors Neighbors2]; %#ok
end
end
if labels(j)==0
labels(j)=C;
end
k = k + 1;
if k > numel(Neighbors)
break;
end
end
end
function Neighbors=RegionQuery(i)
end
%求同一簇典型轨迹
function [finalData1,data1,px,fData,tempMapDis,tempMapV,tempMapHeading]=DXGJ(data1,DXcolor,DXlegend,DXindex)
% function main()
%%数据预处理
% data1 = xlsread(path); %xls xlsx
% data1 = csvread('1.csv'); %csv
[sy,sx] = size(data1);
tempx = 1;tempy = 1;
global finalData;
finalData=[];
finalData{1,1} = data1(1,:);
px(1,1) = 1;
px(1,2) = data1(1,1);
for i = 2 : sy
if data1(i,1) ~= data1(i - 1,1)
tempx = tempx + 1;
px(tempx,1) = tempx;px(tempx,2) = data1(i, 1);
finalData{tempx,1} = data1(i,:);
tempy = 1;
else
tempy = tempy + 1;
finalData{tempx,tempy} = data1(i,:);
end
end
finalData1 = finalData;
%画出船舶轨迹线
% for i = 1 : length(data1(:,1)) - 1
% if data1(i,1) == data1(i + 1,1)
% line([data1(i,2) data1(i + 1,2)],[data1(i,3) data1(i + 1,3)]);
% hold on
% end
% end
% hold on
global a;
a=DXindex;
global xx;
global yy;
xx = size(finalData,1);
yy = size(finalData,2);
tempX = [];
tempY = [];
tempH = [];
tempV = [];
%%计算交点
for k = 1 : yy
if isempty(finalData{a,k})
break;
end
[t1,t2,t3,t4] = toIntersection(k);
if t1 == -1
continue;
end
tempX = [tempX,t1];
tempY = [tempY,t2];
tempH = [tempH,t3];
tempV = [tempV,t4];
end
hold on;
plot(tempX,tempY,'Color',DXcolor,'LineWidth',1,'DisPlayName',DXlegend) %典型轨迹的划线
hold on;
fData ={};
for i = 1 : size(tempX,2)
temp = [tempX(i),tempY(i),tempH(i),tempV(i)];
fData{1,i} = temp;
temp = [1,temp];
finalData{xx + 1,i} = temp;
end
xx = size(finalData,1);
yy = size(finalData,2);
n = xx;
tempMapDis = zeros(1,n - 1);
tempMapV = zeros(1,n - 1);
tempMapHeading = zeros(1,n - 1);
%%计算最小值
for j = 1 : xx - 1
totalDis = 0;
totalV = 0;
totalHeading = 0;
len = 0;
for k = 1 : yy
if isempty(finalData{xx,k})
break;
end
min1 = 999999999;
minl = -1;
for l = 1 : yy
if isempty(finalData{j,l})
break;
end
if min1 > osDis(xx,k,j,l)
min1 = osDis(xx,k,j,l);
minl = l;
end
end
[t1,t2,t3] = toMinDis(xx,k,j,minl);
t2 = abs(t2 - finalData{xx,k}(4));
t3 = abs(t3 - finalData{xx,k}(5));
totalDis = totalDis + t1;
totalHeading = totalHeading + t2;
totalV = totalV + t3;
len = len + 1;
end
tempMapDis(1,j) = totalDis / len;
tempMapV(1,j) = totalV / len;
tempMapHeading(1,j) = totalHeading / len;
end
end
function [ACC_P,ACC_S,ACC_C]=drawErrerRate(finalData_in1,finalData_in0,DXTrace,DistThre,SogThre,CogThre)
% DistThre=60;
% SogThre=2.8;
% CogThre=3.8;
% filename_train_in1='进口正常轨迹数据.xlsx';
% filename_train_in0='进口异常轨迹数据.xlsx';
% [data_in1,finalData_in1]=makeData(filename_train_in1);
% [data_in0,finalData_in0]=makeData(filename_train_in0);
% pred_label_in1_P=zeros(length(finalData_in1),1);
% pred_label_in0_P=zeros(length(finalData_in0),1);
% pred_label_in1_S=zeros(length(finalData_in1),1);
% pred_label_in0_S=zeros(length(finalData_in0),1);
% pred_label_in1_C=zeros(length(finalData_in1),1);
% pred_label_in0_C=zeros(length(finalData_in0),1);
TP_P=0;
FP_P=0;
TN_P=0;
FN_P=0;
TP_S=0;
FP_S=0;
TN_S=0;
FN_S=0;
TP_C=0;
FP_C=0;
TN_C=0;
FN_C=0;
for ind=1:size(finalData_in1,1)
currentTrace=finalData_in1(ind,:);
% DXTrace=DXfData{t};
[DevPosition,DevSog,DevCog]=getDev(currentTrace,DXTrace);
pred_label_in_P=zeros(length(DevPosition),1);
pred_label_in_S=zeros(length(DevSog),1);
pred_label_in_C=zeros(length(DevCog),1);
for node=1:length(DevPosition)
if DevPosition(node)
本文的过程相对来说比较复杂,结果也比较多,主要将后期可视化的结果进行展示,完整的数据处理过程和相关结果见第四部分代码分享。
源码链接:C币下载
需要免费分享的关注+点赞+收藏的 私聊领取
完整的项目内容
包含:
**模型文件和航迹数据
DBSCAN代码
H距离计算代码
航迹提取代码
基于H距离的阈值分类代码
阈值寻优代码
均可直接运行
可以结合这个案例,学习DBSCAN距离算法和H距离的计算方法,掌握了航迹分类的大致流程,取得了较好的聚类效果,并基于航迹聚类进行航迹偏离预测,经检测准确率较高。
需要学习DBSCAN的朋友可以当作一个应用案例来学习,船舶航迹研究方向的朋友可以通过替换数据和相关模块实现拓展成自己的模型实现
参考文献
[1]:基于轨迹聚类的船舶异常行为识别研究
胡智辉
[2]:Typical trajectory extraction method for ships based on AIS data
and trajectory clustering
Huaipeng Li∗
Beijing Industry University, Beijing, China