基于深度学习的行人与自行车分类

该文介绍了一个使用CNN进行行人和骑自行车者识别的示例,基于雷达的微多普勒信号。通过模拟数据训练网络,然后检查在有无汽车噪声情况下分类的表现。网络结构包含卷积层、批量归一化层和全连接层,训练过程中使用了分段学习率策略。文章强调了汽车噪声对分类准确性的影响,并展示了重新训练网络以适应噪声后性能的提升。
摘要由CSDN通过智能技术生成

放置在雷达前的物体的不同部分的运动产生微多普勒信号,可用于识别该物体。这个例子使用了一个卷积神经网络(CNN)来根据行人和骑自行车的人的签名来识别他们。

这个例子使用模拟数据训练深度学习网络,然后检查网络在分类两个重叠签名案例时的表现。

基于仿真的综合数据生成用于训练网络的数据是使用来自 Radar ToolboxTM 的反向散射行人和反向散射自行车手生成的。这些函数分别模拟行人和骑自行车者反射的信号的雷达后向散射。Helper 函数 helperBackScatterSignals 生成指定数量的行人、骑自行车者和汽车雷达返回值。由于该示例的目的是对行人和骑自行车的人进行分类,因此该示例仅将汽车特征视为噪声源。为了了解所要解决的分类问题,研究了一种来自行人、自行车和汽车的微多普勒信号的实现方法。(对于每个实现,返回信号的维数为 Nfast-by-Nsllow,Nfast是快速时间样本的数量和Nsllow是慢时间样本的数量)

%% 
numPed = 1; % 行人实现次数
numBic = 1; % 自行车实现次数
numCar = 1; % 汽车实现次数
[xPedRec,xBicRec,xCarRec,Tsamp] = helperBackScatterSignals(numPed,numBic,numCar);

辅助函数 helperDopplerSignatures 通过计算雷达回波的短时距傅里叶变换(STFT)来产生微多普勒信号。为了获得微多普勒信号,利用辅助函数对每个信号进行短时傅里叶变换和预处理。

[SPed,T,F] = helperDopplerSignatures(xPedRec,Tsamp);
[SBic,~,~] = helperDopplerSignatures(xBicRec,Tsamp);
[SCar,~,~] = helperDopplerSignatures(xCarRec,Tsamp);

绘制步行者、骑自行车者和汽车实现的时频地图。

%% 绘制步行者、骑自行车者和汽车实现的时频地图。
figure
subplot(1,3,1)
imagesc(T,F,SPed(:,:,1))
ylabel('Frequency (Hz)')
title('Pedestrian')
axis square xy

subplot(1,3,2)
imagesc(T,F,SBic(:,:,1))
xlabel('Time (s)')
title('Bicyclist') 
axis square xy

subplot(1,3,3)
imagesc(T,F,SCar(:,:,1))
title('Car')
axis square xy

归一化谱图(STFT 绝对值)表明,这三个物体具有相当不同的特征。具体来说,行人和骑自行车者的声谱图分别具有丰富的微多普勒特征,这些特征是由手臂和腿的摆动以及车轮的转动引起的。相比之下,在这个例子中,汽车被建模为一个点目标与刚体,所以汽车的频谱显示,短期多普勒频移变化很小,表明微多普勒效应很小。

对象的组合:

由于行人和骑自行车者的微多普勒特征不同,将单个实现分类为行人或骑自行车者相对简单。然而,分类多个重叠的行人或自行车,加上高斯噪声或汽车噪声,是困难得多。如果雷达探测区域内同时存在多个目标,那么接收到的雷达信号就是来自所有目标的探测信号的总和。作为一个例子,产生接收雷达信号的行人和自行车与高斯背景噪声。

%% 在接收端配置高斯噪声电平
rx = phased.ReceiverPreamp('Gain',25,'NoiseFigure',10);

xRadarRec = complex(zeros(size(xPedRec)));
for ii = 1:size(xPedRec,3)
    xRadarRec(:,:,ii) = rx(xPedRec(:,:,ii) + xBicRec(:,:,ii));
end

然后利用短时傅里叶变换获得接收信号的微多普勒特征。

[S,~,~] = helperDopplerSignatures(xRadarRec,Tsamp);

figure
imagesc(T,F,S(:,:,1)) % Plot the first realization
axis xy
xlabel('Time (s)')
ylabel('Frequency (Hz)')
title('Spectrogram of a Pedestrian and a Bicyclist')

由于行人和骑自行车者的特征在时间和频率上重叠,因此很难区分两个物体。 

生成训练数据:

通过使用由具有不同属性的对象的模拟实现组成的数据来训练 CNN,例如,骑自行车的人以不同的速度骑车,行人以不同的速度行走。假设雷达固定在原点,在一个实现中,一个物体或多个物体沿 X 轴和 Y 轴分别均匀分布在[5,45]和[ -10,10]米的矩形区域内。

随机调优的三个对象的其他属性如下:

1)行人

  • 高度ーー均匀分布在[1.5,2]米的间距内;
  • 方向ーー在[ -180,180]度间隔内均匀分布;
  • 速度ーー均匀分布在[0,1.4 h]米/秒的间隔内,其中 h 为高度值;

2)骑单车者

  • 方向ーー在[ -180,180]度间隔内均匀分布;
  • 速度ーー均匀分布在[1,10]米/秒的间隔内;
  • 齿轮传动比ーー均匀分布在[0.5,6]区间内;
  • 踩踏板或滑行ーー50% 的可能性踩踏板(滑行意味着骑自行车的人没有踩踏板);

3)汽车

  • 速度ーー沿 X、 Y 方向均匀分布在[0,10]米/秒的区间内

卷积网络的输入是微多普勒特征,由以分贝表示并归一化为[0,1]的光谱图组成,如下图所示:

 雷达回波来自不同的物体和物体的不同部分。根据配置的不同,一些回波要比其他回波强得多。较强的回波往往掩盖较弱的回波。对数缩放通过使返回强度具有可比性来增强这些特性。幅度归一化有助于 CNN 更快地收敛。

数据集包含以下场景的实现:

  • 现场有一个行人
  • 现场有一名骑自行车的人
  • 现场有一名行人和一名骑自行车的人
  • 现场有两个行人
  • 两名骑自行车的人出现在现场

数据集下载:

数据包括20,000个行人、20,000个骑自行车的人和12,500个汽车信号,这些信号是使用 helper 函数 helperBackScatterSignals 和 helperdopplerSignature 生成的。信号分为两个数据集: 一个没有汽车噪声样本,一个有汽车噪声样本。

对于第一个数据集(没有汽车噪声) ,将行人和自行车信号合并,添加高斯噪声,并计算微多普勒特征,以生成五个场景中每个场景的5000个特征。

在每个类别中,80% 的签名(即4000个签名)保留给训练数据集,而20% 的签名(即1000个签名)保留给测试数据集。

为了生成第二个数据集(汽车噪声) ,遵循第一个数据集的过程,除了汽车噪声被添加到50% 的签名。在训练和测试数据集中,有和没有汽车噪声的签名的比例是相同的。

下载并解压缩临时目录中的数据,其位置由 MATLAB 的 temdir 命令指定。数据大小为21GB,下载过程可能需要一些时间。如果数据位于与 temdir 不同的文件夹中,请在后面的说明中更改目录名。

%% 数据集下载
dataURL = 'https://ssd.mathworks.com/supportfiles/SPT/data/PedBicCarData.zip';
saveFolder = fullfile(tempdir,'PedBicCarData'); 
zipFile = fullfile(tempdir,'PedBicCarData.zip');
if ~exist(zipFile,'file')
    websave(zipFile,dataURL);
elseif ~exist(saveFolder,'dir')
    % Unzip the data
    unzip(zipFile,tempdir)
end

注意事项:此处直接使用tempdir路径极大可能报错,我的做法是将tempdir替换为当前脚本路径下文件夹,创建zipFlie ,大概是下面这样:(下载进程可以单击属性栏查看)

%% 数据集下载
dataURL = 'https://ssd.mathworks.com/supportfiles/SPT/data/PedBicCarData.zip';
saveFolder = fullfile("F:\机器学习\deep\zipFile",'PedBicCarData'); 
zipFile = fullfile("F:\机器学习\deep\zipFile",'PedBicCarData.zip');
if ~exist(zipFile,'file')
    websave(zipFile,dataURL);
elseif ~exist(saveFolder,'dir')
    % Unzip the data
    unzip(zipFile,tempdir)
end

数据档案如下:

  • 训练数据集 train DataNoCar 及其标签集 train LabelNoCar。
  • 测试数据集 testDataNoCar 及其标签集 testLabelNoCar。
  • 训练数据集 train DataCarNoise.mat 及其标签集 train LabelCarNoise.mat。
  • 测试数据集 testDataCarNoise.mat 及其标签集 testLabelCarNoise.mat。
  • TF.mat 包含微多普勒信号的时间和频率信息。

网络架构 :

创建五个卷积层和一个完全连接层。前四个卷积层之后是批归一化层、整流线性单元(ReLU)激活层和最大池层。在最后一个卷积层中,最大池层被一个平均池层所代替。输出层是 Softmax 激活后的分类层。

批归一化层:https://blog.csdn.net/u014453898/article/details/108172108

整流线性单元激活层:https://zhuanlan.zhihu.com/p/98863801

https://zhuanlan.zhihu.com/p/363345545

layers = [
    imageInputLayer([size(S,1),size(S,2),1],'Normalization','none')
    %图形输入层,[size(S,1),size(S,2),1]输入数据大小;
    %图形输入层,'Normalization',归一化,‘none’:不采取任何归一化措施;
    convolution2dLayer(10,16,'Padding','same')
    batchNormalizationLayer
    reluLayer
    maxPooling2dLayer(10,'Stride',2)
    
    convolution2dLayer(5,32,'Padding','same')
    batchNormalizationLayer
    reluLayer
    maxPooling2dLayer(10,'Stride',2)
    
    convolution2dLayer(5,32,'Padding','same')
    batchNormalizationLayer
    reluLayer
    maxPooling2dLayer(10,'Stride',2)
    
    convolution2dLayer(5,32,'Padding','same')
    batchNormalizationLayer
    reluLayer
    maxPooling2dLayer(5,'Stride',2)
    
    convolution2dLayer(5,32,'Padding','same')
    batchNormalizationLayer
    reluLayer
    averagePooling2dLayer(2,'Stride',2)
    
    fullyConnectedLayer(5)
    softmaxLayer
    
    classificationLayer]

图像输入层 imageInputLayer 用于指定图像大小,在本例中为 [size(S,1),size(S,2),1]。这些数字对应于高度、宽度和通道大小。数字数据由灰度图像组成,因此通道大小(颜色通道)为 1。对于彩色图像,通道大小为 3,对应于 RGB 值。您不需要打乱数据,因为 trainNetwork 默认会在训练开始时打乱数据。trainNetwork 还可以在训练过程中的每轮训练开始时自动打乱数据。

卷积层 在卷积层中,第一个参数是 filterSize,它是训练函数在沿图像扫描时使用的过滤器的高度和宽度。在此示例中,数字 10表示过滤器大小为 10×10。您可以为过滤器的高度和宽度指定不同大小。第二个参数是过滤器数量 numFilters,它是连接到同一输入区域的神经元数量。此参数决定了特征图的数量。使用 ‘Padding’ 名称-值对组对输入特征图进行填充。对于默认步幅为 1 的卷积层,‘same’ 填充可确保空间输出大小与输入大小相同。您也可以使用 convolution2dLayer 名称-值对组参数定义该层的步幅和学习率。

批量归一化层 批量归一化层对网络中的激活值和梯度传播进行归一化,使网络训练成为更简单的优化问题。在卷积层和非线性部分(例如 ReLU 层)之间使用批量归一化层,来加速网络训练并降低对网络初始化的敏感度。使用 batchNormalizationLayer 创建批量归一化层。

ReLU 层 批量归一化层后接一个非线性激活函数。最常见的激活函数是修正线性单元 (ReLU)。使用 reluLayer 创建 ReLU 层。

最大池化层 卷积层(带激活函数)有时会后跟下采样操作,以减小特征图的空间大小并删除冗余空间信息。通过下采样可以增加更深卷积层中的过滤器数量,而不会增加每层所需的计算量。下采样的一种方法是使用最大池化,可使用 maxPooling2dLayer 创建。最大池化层返回由第一个参数 poolSize 指定的矩形输入区域的最大值。在此示例中,该矩形区域的大小是 [10,10]。‘Stride’ 名称-值对组参数指定训练函数在沿输入扫描时所采用的步长。

全连接层 卷积层和下采样层后跟一个或多个全连接层。顾名思义,全连接层中的神经元将连接到前一层中的所有神经元。该层将先前层在图像中学习的所有特征组合在一起,以识别较大的模式。最后一个全连接层将特征组合在一起来对图像进行分类。因此,最后一个全连接层中的 OutputSize 参数等于目标数据中的类数。在此示例中,输出大小为5,对应于 5个类。使用 fullyConnectedLayer 创建全连接层。

softmax 层 softmax 激活函数对全连接层的输出进行归一化。softmax 层的输出由总和为 1 的多个正数组成,这些数字随后可被分类层用作分类概率。使用 softmaxLayer 函数在最后一个全连接层后创建一个 softmax 层。

分类层 最终层是分类层。该层使用 softmax 激活函数针对每个输入返回的概率,将输入分配到其中一个互斥类并计算损失。要创建分类层,请使用 classificationLayer。

指定优化求解器和超参数

%% 指定优化求解器和超参数,以使用 training ingOptions 训练 CNN。
options = trainingOptions('adam', ...
    'ExecutionEnvironment','gpu',...
    'MiniBatchSize',128, ...
    'MaxEpochs',30, ...
    'InitialLearnRate',1e-2, ...
    'LearnRateSchedule','piecewise', ...
    'LearnRateDropFactor',0.1, ...
    'LearnRateDropPeriod',10, ...
    'Shuffle','every-epoch', ...
    'Verbose',false, ...
    'Plots','training-progress');

  • solverName:优化函数,可选’sgdm’,‘rmsprop’,‘adam’
  • ExecutionEnvironment:名称-值对组参数指定所需的执行环境(可以指定单个 CPU ('cpu')、单个 GPU ('gpu')、多个 GPU ('multi-gpu'),或本地并行池或计算集群 ('parallel'))
  • MiniBatchSize:指定用于每次训练迭代的小批量的大小作为由MiniBatchSize和a组成的逗号分隔对正整数。迷你批次是训练集的子集,它是用于评估损失函数的梯度并更新权重。
  • InitialLearnRate:初始学习率
  • MaxEpochs:最大训练轮数
  • LearnRateSchedule:学习率策略,‘none’或者’piecewise’,'none’表示学习率不变,'piecewise’为分段学习率
  • LearnRateDropFactor:学习率下降因子,[0,1]之间,降低之后学习率为:当前学习率*下降因子
  • LearnRateDropPeriod:学习率下降周期,即几个epoch下降一次学习率
  • shuffle:数据洗牌选项,指定为由“洗牌”和下列选项之一组成的逗号分隔对:'once’在训练之前,对训练和验证数据进行一次洗牌。'never’不打乱数据。'every-epoch’在每个训练轮次之前洗牌训练数据,在每个网络验证之前洗牌验证数据。如果小批量大小不能均匀划分训练样本的数量,则训练网络丢弃不适合每个轮次的最终完整小批量的训练数据。为了避免在每个轮次中丢弃相同的数据,将“Shuffle”值设置为“every-epoch”。
  • Verbose:是否在命令行窗口显示实时训练进程,0或1,若为1,则在命令行显示当前在干啥了,默认为true
  • Plots:是否画出实时训练进程,可选’none’或者’training-progress’,默认为’none’

加载数据集(根据各自环境改变路径即可)

%% 加载数据集
load(fullfile("F:\机器学习\deep\zipFile",'PedBicCarData','trainDataNoCar.mat')) % load training data set
load(fullfile("F:\机器学习\deep\zipFile",'PedBicCarData','testDataNoCar.mat')) % load test data set
load(fullfile("F:\机器学习\deep\zipFile",'PedBicCarData','TF.mat')) % load time and frequency information
helperPlotTrainData(trainDataNoCar,trainLabelNoCar,T,F)

训练你创建的 CNN

trainedNetNoCar = trainNetwork(trainDataNoCar,trainLabelNoCar,layers,options);

使用训练好的网络和分类函数来获得测试数据集 testDataNoCar 的预测标签

predTestLabel = classify(trainedNetNoCar,testDataNoCar);
testAccuracy = mean(predTestLabel == testLabelNoCar);
figure
confusionchart(testLabelNoCar,predTestLabel);

为了分析汽车噪声的影响,利用经过训练的 NetNoCar 网络对含有汽车噪声的数据进行分类,该网络在没有汽车噪声的情况下进行训练。

%加载汽车噪声损坏的测试数据集 testDataCarNoise.mat。
load(fullfile("F:\机器学习\deep\zipFile",'PedBicCarData','testDataCarNoise.mat'));

向网络输入汽车噪声损坏的测试数据集。

predTestLabel = classify(trainedNetNoCar,testDataCarNoise);
testAccuracy = mean(predTestLabel == testLabelCarNoise);
confusionchart(testLabelCarNoise,predTestLabel);

在训练数据集中添加汽车噪声对 CNN 进行再训练,加载汽车噪声损坏的训练数据集 train DataCarNoise.mat。

load(fullfile("F:\机器学习\deep\zipFile",'PedBicCarData','trainDataCarNoise.mat'))

利用汽车噪声污染的训练数据集对网络进行再训练,在30个训练周期内,训练过程达到近90% 的准确率。

trainedNetCarNoise = trainNetwork(trainDataCarNoise,trainLabelCarNoise,layers,options);
predTestLabel = classify(trainedNetCarNoise,testDataCarNoise);
testAccuracy = mean(predTestLabel == testLabelCarNoise);
%% 混淆矩阵显示,经过训练的网络在预测一个行人和两个行人的场景方面表现得更好。
confusionchart(testLabelCarNoise,predTestLabel);

训练效果此处不附图,可自行使用工具箱实现。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

如果我什么都不会,那么阁下如何应对呢?

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值