本章节主要介绍如何制作适合神经网络输入/输出的数据集,以及对输出数据的维度还原。下一章更新神经网络的搭建。
引言
输入/输出数据集制作
理论支持
1、单一时间点的输入/输出特征说明
2、连续时间戳分割
3、样本数据归一化
4、样本随机化
代码实现
输出维度还原
本章总结
重新回顾一下出发点,由于具体报文信息易被篡改,本文希望找到一种不受ADS-B具体报文信息影响的飞机坐标定位方案。如飞机失事,需要紧急救援,若报文被篡改,那么根据报文信息得到的坐标就是虚假的,无法实施及时救援,后果不堪设想。
那么在此整理一下,哪些信息是无法被篡改的呢?根据航空大数据——由ADS-B报文系统预测飞机坐标(飞行轨迹)(一),在本文所用数据集中,ADS-B信号强度、接收机本身序列号(Serial)、接收机本身坐标是不易被篡改的。
ADS-B信号强度:指接收机接收到的ADS-B信号强度,这是客观的,是由接收机在本地接收时测得的一个信息,不易被篡改。
接收机本身序列号(Serial)、接收机本身坐标:这两个信息均能在前文所提的传感器数据集中找到,这些信息都是公开的,也不易被篡改。
根据前文分析,飞机与接收机距离越近,接收机接收到的ADS-B信号强度越大,而飞机与接收机距离涉及接收机本身坐标,又接收机序列号与坐标对等(已知序列号能知道坐标,已知坐标能找到序列号),因此从ADS-B信号强度、接收机本身序列号与坐标理论上能够挖掘出飞机发送ADS-B报文时的坐标。
图1 单一时间点的输入/输出数据
根据引言分析,得到如图1所示的单一时间点的输入/输出数据(后文所用模型的输入/输出为多个连续单一时间点的数据拼接),输入特征为3个地面传感器的序列号、接收信号强度和自身坐标,即每个传感器对应5个特征,因此输入的特征共计15个。输出特征为飞机的纬度和经度共计3个特征。
若当前时间点接收到信号的地面传感器个数不足3个,则用0补充特征;若超过3个,则以前一章所述的各类传感器精度为优先级,挑选出3个优先级高的传感器作为特征使用。
图2 时间戳分割(以采样时间步长等于64为例)
飞机坐标在时间上是连续的,为充分利用数据的时间特性,本文将数据集进行了连续时间戳分割,以采样时间步长等于64为例的数据采样过程如图2所示。先将数据集按航班号进行排列,再将每个航班的数据按服务器接收时间戳依次排列,图2左侧Input部分即两次排列后的效果图。
采样过程中用64×15的滑块在同一航班号内依次采样(其中64表示连续时间点的个数,15表示单一时间点的特征个数),滑块每次滑动步长为1,采样过程仅在单个航班内部采样,如:sample2若再向下滑动一步,就同时包含了航班X和航班Y的信息了,此时需要直接跳到sample3的位置继续采样。
采样后得到输入样本集的维度为(None,64,15),其中None表示样本个数。同理,可以得到输出样本集的维度为(None,64)。
需要注意的是,输出样本集的维度为(None,64),不是(None,64,1),也不是(None,64,2)。
为什么不是(None,64,1)?:(None,64,1)与(None,64)从矩阵内部数据上讲是等价的,只不过前者是三维矩阵,后者是二维矩阵。在神经网络运算中,对于三维矩阵需要用到二维卷积,而对于二维矩阵只需用到一维卷积,因此在不影响数据内容的前提下,将数据降维能够减少后续运算量。
为什么不是(None,64,2)?:在后文神经网络中是对飞机坐标的经度和纬度进行了单独训练,即每次训练只有1个特征输出,而非2个特征。经实验论证,单独训练的性能优于经纬度同时训练的性能,实验数据不在此公开,直接公布结论。
在将样本数据输入到网络模型之前,需要对样本数据进行归一化,本文采用了最大最小归一化方法,具体的公式定义如下:
(1)
其中,X 为原始样本数据,max 为样本的最大值,min为样本的最小值,N 为归一化后的样本。
这是一个很经典归一化方法,公式本身没有问题,但在对坐标归一化时需要注意,本文所用数据集多数为欧洲航班的信息,但不排除个别航班在欧洲之外,比如:大多数航班或传感器坐标纬度范围为36°~71°,有个别坐标的纬度在80°附近,又有个别坐标的纬度在10°附近,那么此时最大最小值不能选80°和10°,而应该选71°和36°。即不能对数据集直接套函数归一化,需要对每一列数据进行升序或者降序排列,观察数据特征后手动设定最大和最小值。
图3 样本随机化
如图3所示,在样本数据归一化后还需要对样本数据进行打乱(Shuffle)操作,该操作能够增加样本随机性,防止模型在训练过程中的抖动,防止过拟合。实验结果表明,样本随机化后的性能会有提升。
根据上一章所述,主数据集和传感器数据集被整合到了变量allinfo中,根据单一时间点的输入/输出特征说明,从allinfo中取出对应的15列输入特征并按列归一化,命名为x_train_norm,同理,取出对应的2列输出特征并按列归一化,命名为y_train_norm。
输入和输出数据集制作matlab代码如下:
[n,m]=size(x_train_norm); height=64;%连续时间点采样步长,根据需求可变 width=15;%单一时间点输入特征个数 index_3d=1; i=1; while i <= n%第一次遍历,确定根据当前矩阵x_train_norm能制作出多少个二维样本 if i+height-1 > n break; end %保证采样窗里只有单个航班的信息 if x_train_norm(i,1) == x_train_norm(i+height-1,1) index_3d=index_3d+1; i = i+1; continue; end %若采样窗里不是单个航班,则将窗口跳跃至下一个航班起始位置 for t = 1:height-1 if x_train_norm(i,1) ~= x_train_norm(i+t,1) i=i+t; break; end end end fprintf('total %d \n',index_3d-1); %提前开辟空间,加快后续运算速度 x_train=zeros(index_3d-1,height,width); yla_train=zeros(index_3d-1,height); ylong_train=zeros(index_3d-1,height); %(index_3d-1)是能够制作的样本数,生成一个1~(index_3d-1)的整数随机序列,用于实现shuffle操作。 % ps:这段代码是灵魂~~~~ randIndex = randperm(index_3d-1); randIndex=randIndex.'; index_3d=1; i=1; %%%%%%%%%%%%%%%%%%%%% % 在制作测试集时打开注释 % count=0; % count_all_test=0; % count_single_test=[]; %%%%%%%%%%%%%%%%%%%%% while i <= n%第二次遍历,制作训练集 if(~mod(i,1000)) fprintf('已完成 %d 行转换!\n',i); end if i+height-1 > n %%%%%% 在制作测试集时打开注释 %%%%% % count=i-n-1; % count_single_test=[count_single_test count]; % count_all_test=count_all_test+1; % count=0; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% break; end if x_train_norm(i,1) == x_train_norm(i+height-1,1) index=randIndex(index_3d);%获取一个随机索引(灵魂~~~~) % 若是在制作测试集,测试集不需要shuffle,测试集打乱后会增加后续维度复原难度 % 在制作测试集时直接按顺序将index作为索引即可,无需使用随机索引 % 最终得到训练集输入x_train,和训练集输出yla_train、ylong_train x_train(index,:,:)=x_train_norm(i:i+height-1,2:2+width-1); yla_train(index,:)=y_train_norm(i:i+height-1,1); ylong_train(index,:)=y_train_norm(i:i+height-1,2); index_3d=index_3d+1; i = i+1; %%%%%% 在制作测试集时打开注释 %%%%% % count=count+1; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% continue; end for t = 1:height-1 if x_train_norm(i,1) ~= x_train_norm(i+t,1) i=i+t; %%%%%% 在制作测试集时打开注释 %%%%% % if count==0 % count=-t; % end % count_single_test=[count_single_test count]; % count_all_test=count_all_test+1; % count=0; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% break; end end end
最终得到训练集输入x_train,和训练集输出yla_train、ylong_train 。这样得到的数据集可以直接供后面神经网络使用,验证集和测试集也可以用以上同样的方式制作而成。
在制作测试集时,需要额外记录两个变量:
count_all_test:记录了数据集中所有不同航班的航班数。
count_single_test:记录了数据集中每一个航班在当前采样窗下所制成的样本数。
这两个变量主要是用于对测试集输出的维度还原。
对测试集或实际预测时(训练集和验证集无需考虑维度还原),根据上述在制作输入数据集时对采样的描述,对于输出数据集理应能够被拆分成如图4所示的形式,即每一个航班的坐标(经度或纬度),连续时间采样的中间部分是被多次预测的,最后进行维度还原时需要根据重复预测次数取平均。
图4 输出拆解
matlab实现代码如下:
load('count_all_test.mat'); load('count_single_test.mat');%加载制作测试集输入时生成的变量count_all_test和count_single_test yla=zeros(6000000,1);%预分配空间,用于存放降维后的数据 ylong=zeros(6000000,1); len_y=1;%表示yla\ylong的index y1=yla_pre.';%yla_pre和ylong_pre即为原始输出的预测坐标 y2=ylong_pre.';%ylong_pre按行排放,转成按列排 y_count=0;%表示y1\y2的index size=64;%采样窗长度 count=0;%count为当前航班的样本数 for t = 1:count_all_test fprintf("t=%d\n",t); count=count_single_test(1,t);%count为当前航班的样本数 temp1=zeros(10000,10000); temp2=zeros(10000,10000); y_1=zeros(10000,1); y_2=zeros(10000,1);%预分配空间,加速 if count<0%小于零表示采样时由于长度小于采样窗长度,没有被采到,所以在恢复时补nan count=abs(count); y_=nan(count,1); yla(len_y:len_y+count-1,1)=y_; ylong(len_y:len_y+count-1,1)=y_; len_y=len_y+count; continue; end %将同航班数据分解并排入同一个矩阵,方便求平均 for i = 1:count temp1(i:i+size-1,i)=y1(:,i+y_count); temp2(i:i+size-1,i)=y2(:,i+y_count); end y_count=y_count+count; %按行求和 y_1=sum(temp1,2); y_2=sum(temp2,2); len=count+size-1; %按行求平均 for i = 1:len if i<size y_1(i,1)=y_1(i,1)/i; y_2(i,1)=y_2(i,1)/i; %如果觉得前段和后段预测重复次数太少,可以选择抛弃数据 % y_1(i,1)=nan; % y_2(i,1)=nan; elseif i>len-size+1 y_1(i,1)=y_1(i,1)/(len-i+1); y_2(i,1)=y_2(i,1)/(len-i+1); % y_1(i,1)=nan; % y_2(i,1)=nan; else %对重复预测次数最多的中间段取平均 y_1(i,1)=y_1(i,1)/size; y_2(i,1)=y_2(i,1)/size; end end yla(len_y:len_y+len-1,1)=y_1(1:len,1); ylong(len_y:len_y+len-1,1)=y_2(1:len,1); len_y=len_y+len; end
最终得到变量yla和ylong,对其用训练集的归一化因子进行返归一化,即可得到神经网络对应每个输入时间点的预测坐标(经度和纬度)。
本章主要介绍了如何制作适用于神经网络的数据集,为了利用数据中的时间特性,本文对原始数据集进行了按时间采样,后续实验表明利用时间特性相比直接使用原始数据,性能有着显著提升。对输入数据的时间采样,为输出数据复原制造了困难。