使用点网深度学习的点云分类

这个例子展示了如何训练用于点云分类的PointNet网络。

点云数据由各种传感器获取,如激光雷达、雷达和深度摄像机。这些传感器捕获场景中物体的3d位置信息,这对于自动驾驶和增强现实中的许多应用非常有用。例如,区分车辆和行人对于规划自动驾驶车辆的路径至关重要。然而,由于每个对象的数据稀疏性、对象遮挡和传感器噪声,使用点云数据训练健壮的分类器具有挑战性。深度学习技术已被证明可以通过直接从点云数据中学习健壮的特征表示来解决许多这些挑战。用于点云分类的开创性深度学习技术之一是PointNet [1].

这个例子在悉尼大学创建的悉尼城市对象数据集上训练一个PointNet分类器[2].该数据集提供了使用激光雷达传感器从城市环境中获取的点云数据的集合。数据集有来自14个不同类别(如汽车、行人和公共汽车)的100个标记对象。

负载数据集

下载Sydney Urban Objects数据集并将其解压缩到一个临时目录。

downloadDirectory = tempdir;datapath = downloadSydneyUrbanObjects(downloadDirectory);

方法加载下载的训练和验证数据集sydneyUrbanObjectsClassificationDatastore本例末尾列出的Helper函数。使用前三个数据折叠进行训练,使用第四个数据折叠进行验证。

foldsTrain = 1:3;foldsVal = 4;dsTrain = sydneyUrbanObjectsClassificationDatastore(数据路径,foldsTrain);dsVal = sydneyUrbanObjectsClassificationDatastore(数据路径,foldsVal);

阅读其中一个训练样本,并想象它是如何使用的pcshow

data = read(dsTrain);ptCloud = data{1,1};Label = data{1,2};图pcshow (ptCloud。位置,[0 0 1],“MarkerSize”现年40岁的“VerticalAxisDir”“向下”)包含(“X”) ylabel (“Y”) zlabel (“Z”标题(标签)

阅读标签并计算分配给每个标签的点数,以便更好地理解标签在数据集中的分布。

dsLabelCounts = transform(dsTrain,@(data){data{2} data{1}.Count});labelCounts = readall(dsLabelCounts);标签= vertcat(labelCounts{:,1});counts = vertcat(labelCounts{:,2});

接下来,使用直方图来可视化类分布。

图直方图(标签)

标签直方图显示数据集是不平衡的,偏向于汽车和行人,这可能会阻止训练一个健壮的分类器。您可以通过对不频繁的类进行过度采样来解决类不平衡的问题。对于Sydney Urban Objects数据集,复制与不常见的类对应的文件是解决类不平衡的一种简单方法。

按标签对文件进行分组,计算每个类的观察数,并使用randReplicateFilesHelper函数,在本例的末尾列出,用于对每个类随机地对文件进行过采样,以达到所需的观察数。

rng(0) [G,classes] = findgroups(标签);numObservations = splitapply(@numel,labels,G);desiredNumObservationsPerClass = max(numObservations);files = splitapply(@(x){randReplicateFiles(x,desiredNumObservationsPerClass)},dsTrain.Files,G);Files = vertcat(Files {:});dsTrain。文件=文件;

打乱复制的文件列表,这样就不会在每个训练批中都有相同的观察类别。

dsTrain。Files = dsTrain.Files(randperm(length(dsTrain.Files)));

将训练和验证数据存储的迷你批处理大小设置为128。

dsTrain。MiniBatchSize = 128;dsVal。MiniBatchSize = 128;

数据增加

复制文件以解决类不平衡会增加网络过拟合的可能性,因为大部分训练数据是相同的。方法对训练数据应用数据增强以抵消这种影响变换而且augmentPointCloud辅助函数,随机旋转点云,随机移除点,随机抖动高斯噪声点。

dsTrain = transform(dsTrain,@augmentPointCloud);

预览一个增强训练样本。

data = preview(dsTrain);ptCloud = data{1,1};Label = data{1,2};图pcshow (ptCloud。位置,[0 0 1],“MarkerSize”现年40岁的“VerticalAxisDir”“向下”)包含(“X”) ylabel (“Y”) zlabel (“Z”标题(标签)

请注意,由于用于测量训练网络性能的数据必须代表原始数据集,因此数据增强不适用于验证或测试数据。

数据预处理

为训练和预测准备点云数据需要两个预处理步骤。

首先,为了在训练期间启用批处理,从每个点云中选择固定数量的点。最佳点数取决于数据集和精确捕捉物体形状所需的点数。为了帮助选择适当的点数,请计算每个类的最小点数、最大值和平均值。

minPointCount = splitapply(@min,counts,G);maxPointCount = splitapply(@max,counts,G);= splitapply(@(x)round(mean(x)),counts,G);stats = table(类,numObservations,minPointCount,maxPointCount,meanPointCount)
统计=14×5表类numObservations minPointCount maxPointCount meanPointCount  ______________ _______________ _____________ _____________ ______________ 4 wd 15 140 1955 751 126 11767 193 8455 2708总线11 2190车64 52 2377 528步行15 80 751 357 107 297 110柱杆13 253 90红绿灯36 38 352 161交通标志40 18 736 126树24 53 2953 470卡车9 445 3013 1376箱42 32 766 241 ute 12 90 1380 580范28 91 5809 1125

由于每个类别的分数在类别内和类别间都有很大的可变性,选择一个适合所有类别的值是很困难的。一种启发方法是选择足够多的点来充分捕捉物体的形状,同时不因处理太多点而增加计算成本。1024的值可以很好地平衡这两个方面。你也可以根据实证分析来选择最优的点数。但是,这超出了本例的范围。使用变换函数在训练集和验证集中选择1024个点。

numPoints = 1024;dsTrain = transform(dsTrain,@(data)selectPoints(data,numPoints));dsVal = transform(dsVal,@(数据)selectPoints(数据,numPoints));

最后一个预处理步骤是将0到1之间的点云数据归一化,以解释数据值范围内的较大差异。例如,与距离较远的物体相比,距离激光雷达传感器较近的物体具有较小的值。这些差异会阻碍训练过程中网络的收敛。使用变换对训练集和验证集中的点云数据进行归一化。

dsTrain = transform(dsTrain,@preprocessPointCloud);dsVal = transform(dsVal,@preprocessPointCloud);

预览增强和预处理的训练数据。

data = preview(dsTrain);图pcshow(data{1,1},[0 0 1],“MarkerSize”现年40岁的“VerticalAxisDir”“向下”);包含(“X”) ylabel (“Y”) zlabel (“Z”{1,2})标题(数据)

定义点网模型

PointNet分类模型由两个组件组成。第一个组件是一个点云编码器,它学习将稀疏的点云数据编码为密集的特征向量。第二个组件是一个分类器,它预测每个编码点云的分类类别。

PointNet编码器模型进一步由四个模型和一个max操作组成。

  1. 输入变换模型

  2. 共享MLP模型

  3. 特征转换模型

  4. 共享MLP模型

共享MLP模型使用一系列卷积、批归一化和ReLU操作实现。卷积操作被配置为在输入点云上共享权重。转换模型由一个共享的MLP和一个应用于每个点云的可学习转换矩阵组成。共享MLP和max操作使PointNet编码器对点的处理顺序不变性,而转换模型对方向变化提供不变性。

定义PointNet编码器模型参数

共享MLP和转换模型由输入通道数量和隐藏通道大小参数化。本例中选择的值是通过调优Sydney Urban Objects数据集上的这些超参数来选择的。注意,如果希望将PointNet应用到不同的数据集,则必须执行额外的超参数调优。

将输入转换模型输入通道大小设置为3,隐藏通道大小设置为64、128和256,并使用initializeTransformHelper函数,在本例的末尾列出,用于初始化模型参数。

inputChannelSize = 3;hiddenChannelSize1 = [64128];hiddenChannelSize2 = 256;(参数。在putTransform, state.InputTransform] = initializeTransform(inputChannelSize,hiddenChannelSize1,hiddenChannelSize2);

将第一个共享MLP模型输入通道大小设置为3,将隐藏通道大小设置为64,并使用initializeSharedMLPHelper函数,在本例的末尾列出,用于初始化模型参数。

inputChannelSize = 3;hiddenChannelSize = [64 64];[parameters.SharedMLP1状态。SharedMLP1] = initializeSharedMLP(inputChannelSize,hiddenChannelSize);

将特征转换模型输入通道大小设置为64,隐藏通道大小设置为64、128和256,并使用initializeTransformHelper函数,在本例的末尾列出,用于初始化模型参数。

inputChannelSize = 64;hiddenChannelSize1 = [64128];hiddenChannelSize2 = 256;(参数。FeatureTransform,状态。FeatureTransform] = initializeTransform(inputChannelSize,hiddenChannelSize,hiddenChannelSize2);

将第二个共享MLP模型输入通道大小设置为64,将隐藏通道大小设置为64,并使用initializeSharedMLP函数初始化模型参数,该函数列在本示例的末尾。

inputChannelSize = 64;hiddenChannelSize = 64;[parameters.SharedMLP2状态。SharedMLP2] = initializeSharedMLP(inputChannelSize,hiddenChannelSize);

定义PointNet分类器模型参数

PointNet分类器模型由一个共享MLP、一个完全连接的操作和一个softmax激活组成。设置分类器模型输入大小为64,隐藏通道大小为512和256,并使用initalizeClassifierHelper函数,在本例的末尾列出,用于初始化模型参数。

inputChannelSize = 64;hiddenChannelSize = [512,256];numClasses = nummel(类);(参数。ClassificationMLP,状态。ClassificationMLP] = initializeClassificationMLP(inputChannelSize,hiddenChannelSize,numClasses);

定义PointNet函数

创建函数pointnetClassifier,在示例末尾的模型函数部分中列出,以计算PointNet模型的输出。函数模型将点云数据、可学习的模型参数、模型状态和指定模型是否返回用于训练或预测的输出的标志作为输入。网络返回对输入点云进行分类的预测。

定义模型梯度函数

创建函数modelGradients,在示例的Model Gradients Function部分中列出,它将模型参数、模型状态和一小批输入数据作为输入,并返回相对于模型中可学习参数的损失梯度和相应的损失。

指定培训项目

训练40个纪元。将初始学习率设置为0.001,L2正则化因子设置为0.01。

numEpochs = 40;learnRate = 0.001;l2Regularization = 0.01;learnratdropperiod = 15;learnratdropfactor = 0.5;

初始化Adam优化的选项。

gradientDecayFactor = 0.9;squaredGradientDecayFactor = 0.999;

火车PointNet

使用自定义训练循环训练模型。

在训练开始时对数据进行洗牌。

对于每个迭代:

  • 读取一批数据。

  • 评估模型梯度。

  • 应用L2权值正则化。

  • 使用adamupdate更新模型参数。

  • 更新培训进度图。

在每个epoch结束时,根据验证数据集评估模型,并收集混淆指标来测量训练过程中的分类准确性。

在完成learnRateDropPeriodepoch,将学习率降低一个因子learnRateDropFactor

初始化参数梯度的移动平均值和Adam优化器使用的梯度的元素平方。

avgGradients = [];avgSquaredGradients = [];

训练模型,如果doTraining是真的。否则,加载一个预先训练好的网络。

请注意,训练是在具有12 GB GPU内存的NVIDIA Titan X上验证的。如果你的GPU内存较少,你可能会在训练过程中耗尽内存。如果发生这种情况,降低miniBatchSize。训练这个网络大约需要5分钟。根据GPU硬件的不同,可能需要更长的时间。

doTraining = false;如果doTraining的末尾列出的configureTrainingProgressPlot函数%示例,初始化训练进度图以显示训练%损失、训练准确率和验证准确率。[lossPlotter, trainAccPlotter,valAccPlotter] = initializtrainingprogressplot;numClasses = nummel(类);迭代= 0;开始= tic;epoch = 1:numEpochs重置训练和验证数据存储。重置(dsTrain);重置(dsVal);遍历数据集。hasdata(dsTrain)迭代=迭代+ 1;读取数据。data = read(dsTrain);创建批处理。[XTrain,YTrain] = batchData(data);使用dlfeval和% modelGradients函数。[gradients, loss, state, acc] = dlfeval(@modelGradients,XTrain,YTrain,parameters,state);L2正则化。梯度= dlupdate(@(g,p) g + l2Regularization*p,梯度,参数);使用Adam优化器更新网络参数。。[parameters, avgGradients, avgSquaredGradients] = adamupdate(parameters, gradients, avgSquaredGradients)...avgGradients avgSquaredGradients迭代...learnRate、gradientDecayFactor squaredGradientDecayFactor);更新培训进度。D = duration(0,0,toc(start),“格式”“hh: mm: ss”);标题(lossPlotter。父母,”时代:“+ epoch +,消失:"+字符串(D)) addpoints(lossPlotter,迭代,double(gather(extractdata(loss)))) addpoints(trainAccPlotter,迭代,acc);drawnow结束根据验证数据评估模型。cmat = sparse(numClasses,numClasses);hasdata (dsVal)获取下一批数据。data = read(dsVal);创建批处理。[XVal,YVal] = batchData(data);计算标签预测。istring = false;YPred = pointnetClassifier(XVal,parameters,state, istrin);选择得分最高的预测作为类别标签% XTest。[~,YValLabel] = max(YVal,[],1);[~,YPredLabel] = max(YPred,[],1);收集混淆指标。cmat = aggreateConfusionMetric(cmat,YValLabel,YPredLabel);结束以平均分类准确率更新训练进度图。Acc = sum(diag(cmat))./sum(cmat,“所有”);addpoints (valAccPlotter迭代,acc);更新学习率。如果mod(epoch, learnratdrop period) == 0 learnRate = learnRate * learnratdrop factor;结束重置训练和验证数据存储。重置(dsTrain);重置(dsVal);结束其他的下载预训练的模型参数、模型状态和验证。%的结果。pretrainedURL =“//www.tianjin-qmedu.com/万博1manbetxsupportfiles/vision/data/pretrainedPointNet.mat”;pretrainedNetwork = fullfile(pwd,“pretrainedPointNet.mat”);如果~存在(pretrainedNetwork“文件”) disp (“下载预训练的网络(5 MB)…”);websave (pretrainedNetwork pretrainedURL);结束加载预训练模型。预训练结果=负载(“pretrainedPointNet.mat”);参数= pretrainedResults.parameters;state = pretrainedResults.state;cmat =预训练结果。cmat;如果可能的话,将模型参数移动到GPU并转换为dlarray。parameters = prepareForPrediction(parameters,@(x)dlarray(toDevice(x,canUseGPU)));如果可能,将模型状态移动到GPU。state = prepareForPrediction(state,@(x)toDevice(x,canUseGPU));结束
下载预训练的网络(5 MB)…

显示验证混淆矩阵。

Figure chart = confusionchart(cmat,classes);

计算平均训练和验证精度。

Acc = sum(diag(cmat))./sum(cmat,“所有”
Acc = 0.6000

由于悉尼城市对象数据集中训练样本数量有限,将验证精度提高到60%以上具有挑战性。模型中定义的增广在缺乏的情况下很容易对训练数据进行过拟合augmentPointCloudDatahelper函数。为了提高PointNet分类器的健壮性,需要进行额外的训练。

使用点网对点云数据进行分类

加载点云数据用pcread,使用训练时使用的相同函数对点云进行预处理,并将结果转换为dlarray

ptCloud = pcread(“car.pcd”);X = preprocessPointCloud(ptCloud);dlX = dlarray(X{1},“SCSB”);

预测点云标签pointnetClassifier模型的功能。

YPred = pointnetClassifier(dlX,参数,状态,false);[~, classsidx] = max(YPred,[],1);

显示得分最高的点云和预测标签。

图pcshow (ptCloud。位置,[0 0 1],“MarkerSize”现年40岁的“VerticalAxisDir”“向下”标题(类(classIdx))

模型梯度函数

modelGradients函数将一小批数据作为输入dlX,对应的目标海底,和可学习参数,并返回损失相对于可学习参数和相应损失的梯度。损失包括一个正则化项,旨在确保PointNet编码器预测的特征转换矩阵近似正交。要计算梯度,请计算modelGradients函数使用dlfeval在训练循环中发挥作用。

函数[gradients, loss, state, acc] = modelGradients(X,Y,parameters,state)执行模型函数。istring = true;[YPred,state,dlT] = pointnetClassifier(X,parameters,state, istrin);添加正则化项,确保特征变换矩阵为%近似正交。K = size(dlT,1);B = size(dlT, 4);I = repelem(眼(K),1,1,1,B);dlI = dlarray(I,“SSCB”);treg = mse(dlI,pagemtimes(dlT,permute(dlT,[2 1 3 4])));因子= 0.001;计算损失。损失=交叉熵(YPred,Y) +因子*treg;计算关于损失的参数梯度。Gradients = dlgradient(损失,参数);计算训练精度度量。[~,YTest] = max(Y,[],1);[~,YPred] = max(YPred,[],1);acc = gather(extractdata(sum(YTest == YPred)./ nummel (YTest)));结束

PointNet分类器函数

pointnetClassifier函数将点云数据dlX、可学习的模型参数、模型状态和标志istrin作为输入,istrin指定模型是返回训练输出还是预测输出。然后,该函数调用PointNet编码器和多层感知器来提取分类特征。在训练过程中,dropout应用于每个感知器操作之后。在最后一个感知器之后,afullyconnect操作将分类特征映射到类的数量,并使用softmax激活将输出归一化为标签的概率分布。PointNet编码器预测的概率分布、更新的模型状态和特征转换矩阵作为输出返回。

函数[dlY,state,dlT] = pointnetClassifier(dlX,parameters,state, istrin)调用PointNet编码器。[dlY,state,dlT] = pointnetEncoder(dlX,parameters,state, istrin);调用分类器。p = parameters.ClassificationMLP.Perceptron;s = state.ClassificationMLP.Perceptron;k = 1:元素个数(p)[海底,s (k)] =感知器(海底,p (k), s (k), isTraining);%如果是训练,则应用概率为0.3的反向dropout。如果istrain概率= 0.3;dropoutScaleFactor = 1 -概率;dropoutMask = (rand(size(dlY),“喜欢”, dlY) >概率)/ dropoutScaleFactor;ly = ly .*dropoutMask;结束结束state.ClassificationMLP.Perceptron = s;应用最终的全连接和softmax操作。weights = parameters.ClassificationMLP.FC.Weights;偏差=参数。分类mlp . fc .偏差;ly =完全连接(ly,权重,偏差);dlY = softmax(dlY);结束

PointNet Encoder函数

pointnetEncoder函数使用输入转换、共享MLP、特征转换、第二个共享MLP和max操作处理输入dlX,并返回max操作的结果。

函数[dlY,state,T] = pointnetEncoder(dlX,parameters,state, istrin)输入变换。(海底,状态。在putTransform] = dataTransform(dlX,parameters.InputTransform,state.InputTransform,isTraining);共享MLP。(海底,state.SharedMLP1。Perceptron] = sharedMLP(dlY,parameters.SharedMLP1.Perceptron,state.SharedMLP1.Perceptron, istrain);%特征变换。(海底,状态。FeatureTransform,T] = dataTransform(dlY,parameters.FeatureTransform,state.FeatureTransform, istrain);共享MLP。(海底,state.SharedMLP2。Perceptron] = sharedMLP(dlY,parameters.SharedMLP2.Perceptron,state.SharedMLP2.Perceptron, istrain);%最大操作。ly = max(ly,[],1);结束

共享多层感知器函数

共享多层感知器函数使用一系列感知器操作处理输入dlX,并返回最后一个感知器的结果。

函数[dlY,state] = sharedMLP(dlX,parameters,state, istring) dlY = dlX;k = 1: nummel (parameters) [dlY, state(k)] =感知器(dlY,parameters(k),state(k), istrain);结束结束

感知器函数

感知器函数使用卷积、批归一化和relu操作处理输入dlX,并返回relu操作的输出。

函数[dlY,state] =感知器(dlX,parameters,state, istrin)%卷积。W = parameters. convc . weights;B = parameters. convc . bias;dlconv(dlX,W,B);批处理归一化。训练时更新批归一化状态。offset = parameters.BatchNorm.Offset;scale = parameters.BatchNorm.Scale;trainedMean = state.BatchNorm.TrainedMean;trainedVariance = state.BatchNorm.TrainedVariance;如果istrain [dlY,trainedMean,trainedVariance] = batchnorm(dlY,offset,scale,trainedMean,trainedVariance);%更新状态。state.BatchNorm.TrainedMean = trainedMean;state.BatchNorm.TrainedVariance = trainedVariance;其他的dlY = batchnorm(dlY,offset,scale,trainedMean,trainedVariance);结束% ReLU。dlY = relu(dlY);结束

数据转换函数

dataTransform函数处理输入dlX使用一个共享MLP,一个max操作,和另一个共享MLP来预测一个变换矩阵t。变换矩阵使用批处理矩阵乘法操作应用到输入dlX。该函数返回批处理矩阵相乘和变换矩阵的结果。

函数[dlY,state,T] = dataTransform(dlX,parameters,state, istrin)共享MLP。(海底,state.Block1。Perceptron] = sharedMLP(dlX,parameters.Block1.Perceptron,state.Block1.Perceptron, istrion);%最大操作。ly = max(ly,[],1);共享MLP。(海底,state.Block2。Perceptron] = sharedMLP(dlY,parameters.Block2.Perceptron,state.Block2.Perceptron, istrain);转换网络(T-Net)。将最后一个全连接操作作为W*X应用于%预测变换矩阵T。dlY = extractdata(dlY);dlY =挤压(dlY);% N-by-BT =参数。改造;% K ^ 2-by-B将T重塑成一个方阵。K =√(size(T,1));T =重塑(T,K,K,1,[]);% [k k 1 b]T = T +眼(K);使用批处理矩阵乘法应用于输入dlX。X = extractdata(dlX);% [m 1 k b][C,B] = size(X,[3 4]);X =重塑(X,[],C,1,B);% [m k 1 b]Y = pagemtimes(X,T);ly = darray (Y,“SCSB”);结束

模型参数初始化函数

initializeTransform函数

initializeTransform函数将两个共享mlp的通道大小和隐藏通道数量作为输入,并返回结构体中的初始化参数。参数初始化使用He权重初始化[3.].

函数[params,state] = initializeTransform(inputChannelSize,block1,block2) [params. block1, state.]Block1] = initializeSharedMLP(inputChannelSize, Block1);[params.Block2状态。Block2] = initializeSharedMLP(block1(end), Block2);%变换矩阵的参数。参数个数。变换= dlarray(0 (inputChannelSize^2,block2(end)));结束

initializeSharedMLP函数

initializeSharedMLP函数将通道大小和隐藏通道大小作为输入,并在结构体中返回初始化的参数。参数初始化使用He权值初始化。

函数[params,state] = initializeSharedMLP(inputChannelSize,hiddenChannelSize) weights = initializeWeightsHe([1 1 inputChannelSize hiddenChannelSize(1)]);偏差= 0 (hiddenChannelSize(1),1,“单身”);p.c. . weights = dlarray(weights);p.c. . bias = dlarray(偏差);p. batchnormal . offset = dlarray(0 (hiddenChannelSize(1),1,“单身”));p. batchnormal . scale = dlarray(ones(hiddenChannelSize(1),1,“单身”));s.BatchNorm.TrainedMean = 0 (hiddenChannelSize(1),1,“单身”);s.BatchNorm.TrainedVariance = ones(hiddenChannelSize(1),1,“单身”);params.Perceptron(1) = p;state.Perceptron(1) = s;k = 2:numel(hiddenChannelSize) weights = initializeWeightsHe([1 1 hiddenChannelSize(k-1) hiddenChannelSize(k)]);偏差= 0 (hiddenChannelSize(k),1,“单身”);p.c. . weights = dlarray(weights);p.c. . bias = dlarray(偏差);p. batchnormal . offset = dlarray(0 (hiddenChannelSize(k),1,“单身”));p. batchnormal . scale = dlarray(ones(hiddenChannelSize(k),1,“单身”));s.BatchNorm.TrainedMean = 0 (hiddenChannelSize(k),1,“单身”);s.BatchNorm.TrainedVariance = ones(hiddenChannelSize(k),1,“单身”);params.Perceptron(k) = p;state.Perceptron(k) = s;结束结束

initializeClassificationMLP函数

initializeClassificationMLP函数将通道大小、隐藏通道大小和类数量作为输入,并返回结构体中的初始化参数。共享MLP初始化使用He权值初始化,最后的全连接操作初始化使用随机高斯值。

函数[params,state] = initializeClassificationMLP(inputChannelSize,hiddenChannelSize,numClasses) [params,state] = initializeSharedMLP(inputChannelSize,hiddenChannelSize);weights = initializeWeightsGaussian([numClasses hiddenChannelSize(end)]);偏差= 0 (numClasses,1,“单身”);params.FC.Weights = dlarray(weights);params.FC.Bias = dlarray(bias);结束

initializeWeightsHe函数

initializeWeightsHe函数使用He初始化初始化参数。

函数x = initializeWeightsHe(sz) fanIn = prod(sz(1:3));stddev = sqrt(2/fanIn);X = stddev .* randn(sz);结束

initializeWeightsGaussian函数

initializeWeightsGaussian函数初始化参数使用高斯初始化,标准偏差为0.01。

函数x =初始化加权高斯(sz) x = randn(sz,“单身”) .* 0.01;结束

数据预处理功能

preprocessPointCloudData函数

preprocessPointCloudData函数从输入数据中提取X, Y, Z点数据,并将0到1之间的数据归一化。该函数返回规范化的X、Y、Z数据。

函数data = preprocessPointCloud(data)如果~iscell(data) data = {data};结束numObservations = size(data,1);i = 1:numObservations刻度点在0到1之间。xlim = data{i,1}.XLimits;ylim = data{i,1}.YLimits;zlim = data{i,1}.ZLimits;xyzMin = [xlim(1) ylim(1) zlim(1)];xyzDiff = [diff(xlim) diff(ylim) diff(zlim)];Data {i,1} = (Data {i,1}.)- xyzMin) ./ xyzDiff;结束结束

selectPoints函数

selectPoints函数对所需的点数进行抽样。当点云包含超过所需数量的点时,函数使用pcdownsample随机选择点。否则,该函数复制数据以生成所需的点数。

函数data = selectPoints(data,numPoints)通过向下抽样或复制选择所需的点数%点云数据。numObservations = size(data,1);i = 1:numObservations ptCloud = data{i,1};如果ptCloud。计数> numPoints百分比= numPoints/ptCloud.Count;data{i,1} = pcdownsample(ptCloud,“随机”、比例);其他的replicationFactor = ceil(numPoints/ptCloud.Count);ind = repmat(1:ptCloud.Count,1,replicationFactor);data{i,1} = select(ptCloud,ind(1:numPoints));结束结束结束

数据增强功能

augmentPointCloudData函数围绕z轴随机旋转点云,随机下降30%的点,并使用高斯噪声随机抖动点的位置。

函数data = augmentPointCloud(data) numObservations = size(data,1);i = 1:numObservations ptCloud = data{i,1};%围绕“上轴”旋转点云,即该数据集的Z轴。tform = randomAffine3d(...“XReflection”,真的,...“YReflection”,真的,...“旋转”, @randomRotationAboutZ);ptCloud = pctransform(ptCloud,tform);%随机掉分30%。如果0.5 ptCloud = pcdownsample(ptCloud,“随机”, 0.3);结束如果兰特> 0.5%用高斯噪声抖动点位置,均值为0和通过创建一个随机位移场,使标准偏差为0.02。D = 0.02 * randn(size(ptCloud.Location));ptCloud = pctransform(ptCloud,D);结束data{i,1} = ptCloud;结束结束函数[rotationAxis,theta] = randomRotationAboutZ() rotationAxis = [0 0 1];= 2* π *rand;结束

万博1manbetx支持功能

aggregateConfusionMetric函数

aggregateConfusionMetric函数根据预测结果增量填充混淆矩阵YPred以及预期的结果欧美

函数cmat = aggreateConfusionMetric(cmat,YTest,YPred) YTest = gather(extractdata(YTest));YPred = gather(extractdata(YPred));[m,n] = size(cmat);cmat = cmat + full(稀疏(YTest,YPred,1,m,n));结束

initializeTrainingProgressPlot函数

initializeTrainingProgressPlot函数配置两个图来显示训练损失、训练精度和验证精度。

函数[plotter,trainAccPlotter,valAccPlotter] = initializeTrainingProgressPlot()绘制损失、训练准确率和验证准确率。数字%损失图Subplot (2,1,1) plot = animatedline;包含(“迭代”) ylabel (“损失”%准确度图subplot(2,1,2) trainAccPlotter = animatedline(“颜色”“b”);valAccPlotter = animatedline(“颜色”‘g’);传奇(“训练的准确性”“验证准确性”“位置”“西北”);包含(“迭代”) ylabel (“准确性”结束

replicateFiles函数

replicateFiles函数随机地对一组文件进行过采样,并返回一组文件numDesired元素。

函数randReplicateFiles(files,numDesired) n = numel(files);ind = randi(n,numDesired,1);文件=文件(ind);结束

downloadSydneyUrbanObjects函数

downloadSydneyUrbanObjects函数下载数据集并将其保存到临时目录。

函数datapath = downloadSydneyUrbanObjects(dataLoc)如果nargin == 0 dataLoc = pwd;结束dataLoc = string(dataLoc);url =“http://www.acfr.usyd.edu.au/papers/data/”;name =“sydney-urban-objects-dataset.tar.gz”;datapath = fullfile(dataLoc,“sydney-urban-objects-dataset”);如果~存在(datapath公司,“dir”) disp (“正在下载悉尼城市对象数据集……”);解压(url +名字,dataLoc);结束结束

batchData函数

batchData方法中读取的输入数据进行排序sydneyUrbanObjectsClassificationDatastore并将数据移动到GPU进行处理。

函数[dlX,海底]= batchData(数据)X =猫(4,数据{:1});标签= cat(1,data{:,2});Y = oneHotEncode(标签);将数据转换为单个数据进行处理。X =单(X);Y =单(Y);尽可能将数据移动到GPU。如果canUseGPU X = gpuArray(X);Y = gpuArray(Y);结束返回X和Y作为dlarray对象。dlX = dlarray(X,“SCSB”);ly = darray (Y,“CB”);结束

oneHotEncode函数

oneHotEncode函数将分类标签编码为单一热数值向量。

函数Y = oneHotEncode(labels) numObservations = numel(labels);numCategories = nummel(类别(标签));sz = [numCategories, numObservations];Y = 0 (sz,“单一”);标签=标签';idx = sub2ind(sz, int32(labels), 1:numObservations);Y(idx) = 1;结束

prepareForPrediction函数

prepareForPrediction函数用于将用户定义的函数应用于嵌套结构数据。它用于将模型参数和状态数据移动到GPU。

函数p = prepareForPrediction(p,fcn)i = 1:元素个数(p) p (i) = structfun (@ (x)调用(fcn x)、p (i),“UniformOutput”, 0);结束函数数据=调用(fcn, Data)如果isstruct(data) data = prepareForPrediction(data,fcn);其他的数据= fcn(数据);结束结束结束将数据移动到GPU。函数x = toDevice(x,useGPU)如果useGPU x = gpuArray(x);结束结束

参考文献

[1]查理斯,R. Qi,苏浩,莫凯春和列奥尼达J. gu。“点网:用于3D分类和分割的点集深度学习。”在2017 IEEE计算机视觉与模式识别大会, 77 - 85。檀香山,HI: IEEE, 2017。https://doi.org/10.1109/CVPR.2017.16。

[2] de Deuge, Mark, Alastair Quadras, Calvin Hung和Bertrand Douillard。室外3D扫描分类的无监督特征学习。在2013澳大拉西亚机器人与自动化会议.悉尼,澳大利亚:ACRA, 2013。

[3]何开明,张翔宇,任少卿,孙健。“深入研究整流器:在ImageNet分类上超越人类水平的性能。”在2015 IEEE计算机视觉国际会议(ICCV)1026 - 34。圣地亚哥,智利:IEEE, 2015。https://doi.org/10.1109/ICCV.2015.123。

相关的话题