В этом примере показано, как обучить сеть PointNet для классификации облаков точек.
Данные об облаке точек получены множеством датчиков, таких как лидар, радар и камеры глубины. Эти датчики получают 3-D информацию о положении об объектах в сцене, которая полезна для многих приложений в автономном управлении автомобилем и дополненной реальности. Например, отличительные транспортные средства от пешеходов очень важно для планирования пути автономного транспортного средства. Однако учебные устойчивые классификаторы с данными об облаке точек сложны из-за разреженности данных на объект, объектные поглощения газов и шум датчика. Методы глубокого обучения, как показывали, обратились ко многим из этих проблем путем изучения устойчивых представлений функции непосредственно от данных об облаке точек. Один из оригинальных методов глубокого обучения для классификации облаков точек является PointNet [1].
Этот пример обучает классификатор PointNet на наборе данных Сидни Урбана Обджектса, созданном Сиднейским университетом [2]. Этот набор данных обеспечивает набор данных об облаке точек, полученных городской средой с помощью датчика лидара. Набор данных имеет 100 помеченных объектов от 14 различных категорий, таких как автомобиль, пешеход и шина.
Загрузите и извлеките набор данных Сидни Урбана Обджектса к временной директории.
downloadDirectory = tempdir; datapath = downloadSydneyUrbanObjects(downloadDirectory);
Загрузите загруженный набор данных обучения и валидации с помощью loadSydneyUrbanObjectsData
функция помощника перечислена в конце этого примера. Используйте первые три сгиба данных для обучения и четвертое для валидации.
foldsTrain = 1:3; foldsVal = 4; dsTrain = loadSydneyUrbanObjectsData(datapath,foldsTrain); dsVal = loadSydneyUrbanObjectsData(datapath,foldsVal);
Считайте одну из обучающих выборок и визуализируйте ее с помощью pcshow
.
data = read(dsTrain); ptCloud = data{1,1}; label = data{1,2}; figure pcshow(ptCloud.Location,[0 1 0],"MarkerSize",40,"VerticalAxisDir","down") xlabel("X") ylabel("Y") zlabel("Z") title(label)
Считайте метки и считайте число точек присвоенным каждой метке лучше изучить распределение меток в наборе данных.
dsLabelCounts = transform(dsTrain,@(data){data{2} data{1}.Count}); labelCounts = readall(dsLabelCounts); labels = vertcat(labelCounts{:,1}); counts = vertcat(labelCounts{:,2});
Затем используйте гистограмму, чтобы визуализировать распределение класса.
figure histogram(labels)
Гистограмма метки показывает, что набор данных является неустойчивым и склоняется к автомобилям и пешеходам, которые могут предотвратить обучение устойчивого классификатора. Можно обратиться к неустойчивости класса путем сверхдискретизации нечастых классов. Для набора данных Сидни Урбана Обджектса, копируя файлы, соответствующие нечастым классам, простой метод обратиться к неустойчивости класса.
Сгруппируйте файлы меткой, считайте количество наблюдений в классе и используйте randReplicateFiles
функция помощника, перечисленная в конце этого примера, чтобы случайным образом сверхдискретизировать файлы к желаемому количеству наблюдений в классе.
rng(0) [G,classes] = findgroups(labels); numObservations = splitapply(@numel,labels,G); desiredNumObservationsPerClass = max(numObservations); files = splitapply(@(x){randReplicateFiles(x,desiredNumObservationsPerClass)},dsTrain.Files,G); files = vertcat(files{:}); dsTrain.Files = files;
Дублирование файлов, чтобы обратиться к неустойчивости класса увеличивает вероятность сверхподбора кривой сети, потому что большая часть обучающих данных идентична. Чтобы возместить этот эффект, примените увеличение данных к обучающим данным с помощью transform
и augmentPointCloud
функция помощника, которая случайным образом вращает облако точек, случайным образом удаляет точки, и случайным образом дрожит точки с Гауссовым шумом.
dsTrain = transform(dsTrain,@augmentPointCloud);
Предварительно просмотрите одну из увеличенных обучающих выборок.
data = preview(dsTrain); ptCloud = data{1,1}; label = data{1,2}; figure pcshow(ptCloud.Location,[0 1 0],"MarkerSize",40,"VerticalAxisDir","down") xlabel("X") ylabel("Y") zlabel("Z") title(label)
Обратите внимание на то, что, потому что данные для того, чтобы измерить уровень обучившего сеть должны быть представительными для исходного набора данных, увеличение данных не применяется к валидации или тестовым данным.
Два шага предварительной обработки требуются, чтобы готовить данные об облаке точек к обучению и предсказанию.
Во-первых, чтобы включить пакетную обработку данных во время обучения, выберите постоянное число точек от каждого облака точек. Оптимальное число точек зависит от набора данных и числа точек, требуемого точно получать форму объекта. Чтобы помочь выбрать соответствующее число точек, вычислите минимум, максимум, и означайте число точек в классе.
minPointCount = splitapply(@min,counts,G); maxPointCount = splitapply(@max,counts,G); meanPointCount = splitapply(@(x)round(mean(x)),counts,G); stats = table(classes,numObservations,minPointCount,maxPointCount,meanPointCount)
stats=14×5 table
classes numObservations minPointCount maxPointCount meanPointCount
______________ _______________ _____________ _____________ ______________
4wd 15 140 1955 751
building 15 193 8455 2708
bus 11 126 11767 2190
car 64 52 2377 528
pedestrian 107 20 297 110
pillar 15 80 751 357
pole 15 13 253 90
traffic lights 36 38 352 161
traffic sign 40 18 736 126
tree 24 53 2953 470
truck 9 445 3013 1376
trunk 42 32 766 241
ute 12 90 1380 580
van 28 91 5809 1125
Из-за большой суммы внутрикласса и изменчивости межкласса в числе точек в классе, выбирая значение, которое соответствует всем классам, затрудняет. Одна эвристика должна выбрать достаточно точек, чтобы соответственно получить форму объектов, не увеличивая вычислительную стоимость путем обработки слишком многих точек. Значение 1 024 обеспечивает хороший компромисс между этими двумя фасетами. Можно также выбрать оптимальное число точек на основе эмпирического анализа. Однако это выходит за рамки этого примера. Используйте transform
функционируйте, чтобы выбрать 1 024 точки в наборах обучения и валидации.
numPoints = 1024; dsTrain = transform(dsTrain,@(data)selectPoints(data,numPoints)); dsVal = transform(dsVal,@(data)selectPoints(data,numPoints));
Последний шаг предварительной обработки должен нормировать данные об облаке точек между 0 и 1 с учетом значительных различий в области значений значений данных. Например, объекты ближе к датчику лидара имеют меньшие значения по сравнению с объектами, которые являются еще дальше. Эти различия могут препятствовать сходимости сети во время обучения. Используйте transform
нормировать данные об облаке точек в наборах обучения и валидации.
dsTrain = transform(dsTrain,@preprocessPointCloud); dsVal = transform(dsVal,@preprocessPointCloud);
Предварительно просмотрите увеличенные и предварительно обработанные обучающие данные.
data = preview(dsTrain); figure pcshow(data{1,1},[0 1 0],"MarkerSize",40,"VerticalAxisDir","down"); xlabel("X") ylabel("Y") zlabel("Z") title(data{1,2})
Модель классификации PointNet состоит из двух компонентов. Первый компонент является энкодером облака точек, который учится кодировать разреженные данные об облаке точек в плотный характеристический вектор. Второй компонент является классификатором, который предсказывает категориальный класс каждого закодированного облака точек.
Модель энкодера PointNet далее состоит из четырех моделей, сопровождаемых макс. операцией.
Введите преобразовывают модель
Разделяемая модель MLP
Покажите преобразовывают модель
Разделяемая модель MLP
Разделяемая модель MLP реализована с помощью серии свертки, нормализации партии. и операций ReLU. Операция свертки сконфигурирована таким образом, что веса совместно используются через облако точки ввода. Модель преобразования состоит из разделяемого MLP, и learnable преобразовывают матрицу, которая применяется к каждому облаку точек. Разделяемый MLP и макс. операция делают инвариант энкодера PointNet к порядку, в котором обрабатываются точки, в то время как модель преобразования предоставляет инвариантность изменениям ориентации.
Разделяемые MLP и преобразовывают модели, параметрируются количеством входных каналов и скрытых размеров канала. Значения, выбранные в этом примере, выбраны путем настройки этих гиперпараметров на наборе данных Сидни Урбана Обджектса. Обратите внимание на то, что, если вы хотите применить PointNet к различному набору данных, необходимо выполнить дополнительную настройку гиперпараметра.
Установите вход, преобразовывают входной размер канала модели к три и скрытые размеры канала к 64, 128, и 256 и используют initializeTransform
функция помощника, перечисленная в конце этого примера, чтобы инициализировать параметры модели.
inputChannelSize = 3; hiddenChannelSize1 = [64,128]; hiddenChannelSize2 = 256; [parameters.InputTransform, state.InputTransform] = initializeTransform(inputChannelSize,hiddenChannelSize1,hiddenChannelSize2);
Установите первый разделяемый входной размер канала модели MLP на три и скрытый размер канала к 64 и используйте initializeSharedMLP
функция помощника, перечисленная в конце этого примера, чтобы инициализировать параметры модели.
inputChannelSize = 3; hiddenChannelSize = [64 64]; [parameters.SharedMLP1,state.SharedMLP1] = initializeSharedMLP(inputChannelSize,hiddenChannelSize);
Установите входной размер канала модели преобразования функции на 64 и скрытые размеры канала к 64, 128, и 256 и используйте initializeTransform
функция помощника, перечисленная в конце этого примера, чтобы инициализировать параметры модели.
inputChannelSize = 64; hiddenChannelSize1 = [64,128]; hiddenChannelSize2 = 256; [parameters.FeatureTransform, state.FeatureTransform] = initializeTransform(inputChannelSize,hiddenChannelSize,hiddenChannelSize2);
Установите второй разделяемый входной размер канала модели MLP на 64 и скрытый размер канала к 64 и используйте initializeSharedMLP
функция, перечисленная в конце этого примера, чтобы инициализировать параметры модели.
inputChannelSize = 64; hiddenChannelSize = 64; [parameters.SharedMLP2,state.SharedMLP2] = initializeSharedMLP(inputChannelSize,hiddenChannelSize);
Модель классификатора PointNet состоит из разделяемого MLP, полностью связанной операции и softmax активации. Установите входной размер модели классификатора на 64 и скрытый размер канала к 512 и 256 и используйте initalizeClassifier
функция помощника, перечисленная в конце этого примера, чтобы инициализировать параметры модели.
inputChannelSize = 64; hiddenChannelSize = [512,256]; numClasses = numel(classes); [parameters.ClassificationMLP, state.ClassificationMLP] = initializeClassificationMLP(inputChannelSize,hiddenChannelSize,numClasses);
Создайте функциональный pointnetClassifier
, перечисленный в разделе Model Function в конце примера, чтобы вычислить выходные параметры модели PointNet. Модель функции берет в качестве входа данные об облаке точек, learnable параметры модели, состояние модели и флаг, который задает, возвращает ли модель выходные параметры для обучения или предсказания. Сеть возвращает предсказания для классификации облака точки ввода.
Создайте функциональный modelGradients
, перечисленный в разделе Model Gradients Function примера, который берет в качестве входа параметры модели, состояние модели и мини-пакет входных данных, и возвращает градиенты потери относительно настраиваемых параметров в моделях и соответствующей потери.
Обучайтесь в течение 10 эпох и загрузите данные в пакетах 128. Установите начальную скорость обучения на 0,002 и фактор регуляризации L2 к 0,01.
numEpochs = 10; learnRate = 0.002; miniBatchSize = 128; l2Regularization = 0.01; learnRateDropPeriod = 15; learnRateDropFactor = 0.5;
Инициализируйте опции для оптимизации Адама.
gradientDecayFactor = 0.9; squaredGradientDecayFactor = 0.999;
Обучите модель с помощью пользовательского учебного цикла.
Переставьте данные в начале обучения.
Для каждой итерации:
Считайте пакет данных.
Оцените градиенты модели.
Примените регуляризацию веса L2.
Используйте adamupdate
обновить параметры модели.
Обновите график процесса обучения.
В конце каждой эпохи оцените модель против набора данных валидации и соберите метрики беспорядка, чтобы измерить точность классификации, в то время как обучение прогрессирует.
После завершения learnRateDropPeriod
эпохи, уменьшайте скорость обучения на коэффициент learnRateDropFactor
.
Инициализируйте скользящее среднее значение градиентов параметра и поэлементные квадраты градиентов, используемых оптимизатором Адама.
avgGradients = []; avgSquaredGradients = [];
Обучите модель если doTraining
верно. В противном случае загружает предварительно обученную сеть.
Обратите внимание на то, что обучение было проверено на Титане NVIDIA X с 12 Гбайт памяти графического процессора. Если ваш графический процессор имеет меньше памяти, у можно закончиться память во время обучения. Если это происходит, понизьте miniBatchSize
. Обучение эта сеть занимает приблизительно 5 минут. В зависимости от вашего оборудования графического процессора это может занять больше времени.
doTraining = false; if doTraining % Create a minibatchqueue to batch data from training and validation % datastores. Use the batchData function, listed at the end of the % example, to batch the point cloud data and one-hot encode the label % data. numOutputsFromDSRead = 2; mbqTrain = minibatchqueue(dsTrain,numOutputsFromDSRead,... "MiniBatchSize", miniBatchSize,... "MiniBatchFcn",@batchData,... "MiniBatchFormat",["SCSB" "BC"]); mbqVal = minibatchqueue(dsVal,numOutputsFromDSRead,... "MiniBatchSize", miniBatchSize,... "MiniBatchFcn",@batchData,... "MiniBatchFormat",["SCSB" "BC"]); % Use the configureTrainingProgressPlot function, listed at the end of the % example, to initialize the training progress plot to display the training % loss, training accuracy, and validation accuracy. [lossPlotter, trainAccPlotter,valAccPlotter] = initializeTrainingProgressPlot; numClasses = numel(classes); iteration = 0; start = tic; for epoch = 1:numEpochs % Shuffle data every epoch. shuffle(mbqTrain); % Iterate through data set. while hasdata(mbqTrain) iteration = iteration + 1; % Read next batch of training data. [XTrain, YTrain] = next(mbqTrain); % Evaluate the model gradients and loss using dlfeval and the % modelGradients function. [gradients, loss, state, acc] = dlfeval(@modelGradients,XTrain,YTrain,parameters,state); % L2 regularization. gradients = dlupdate(@(g,p) g + l2Regularization*p,gradients,parameters); % Update the network parameters using the Adam optimizer. [parameters, avgGradients, avgSquaredGradients] = adamupdate(parameters, gradients, ... avgGradients, avgSquaredGradients, iteration,... learnRate,gradientDecayFactor, squaredGradientDecayFactor); % Update the training progress. D = duration(0,0,toc(start),"Format","hh:mm:ss"); title(lossPlotter.Parent,"Epoch: " + epoch + ", Elapsed: " + string(D)) addpoints(lossPlotter,iteration,double(gather(extractdata(loss)))) addpoints(trainAccPlotter,iteration,acc); drawnow end % Evaluate the model on validation data. cmat = sparse(numClasses,numClasses); while hasdata(mbqVal) % Read next batch of validation data. [XVal, YVal] = next(mbqVal); % Compute label predictions. isTraining = false; YPred = pointnetClassifier(XVal,parameters,state,isTraining); % Choose prediction with highest score as the class label for % XTest. [~,YValLabel] = max(YVal,[],1); [~,YPredLabel] = max(YPred,[],1); % Collect confusion metrics. cmat = aggreateConfusionMetric(cmat,YValLabel,YPredLabel); end % Update training progress plot with average classification accuracy. acc = sum(diag(cmat))./sum(cmat,"all"); addpoints(valAccPlotter,iteration,acc); % Upate the learning rate. if mod(epoch,learnRateDropPeriod) == 0 learnRate = learnRate * learnRateDropFactor; end % Reset training and validation data queues. reset(mbqTrain); reset(mbqVal); end else % Download pretrained model parameters, model state, and validation % results. pretrainedURL = 'https://ssd.mathworks.com/supportfiles/vision/data/pointnetSydneyUrbanObjects.zip'; pretrainedResults = downloadPretrainedPointNet(pretrainedURL); parameters = pretrainedResults.parameters; state = pretrainedResults.state; cmat = pretrainedResults.cmat; % Move model parameters to the GPU if possible and convert to a dlarray. parameters = prepareForPrediction(parameters,@(x)dlarray(toDevice(x,canUseGPU))); % Move model state to the GPU if possible. state = prepareForPrediction(state,@(x)toDevice(x,canUseGPU)); end
Отобразите матрицу беспорядка валидации.
figure chart = confusionchart(cmat,classes);
Вычислите среднюю точность обучения и валидации.
acc = sum(diag(cmat))./sum(cmat,"all")
acc = 0.5742
Из-за ограниченного количества обучающих выборок в наборе данных Сидни Урбана Обджектса, увеличивая точность валидации вне 60% сложно. Модель легко сверхсоответствует обучающим данным в отсутствие увеличения, заданного в augmentPointCloudData
функция помощника. Чтобы улучшить робастность классификатора PointNet, дополнительное обучение требуется.
Загрузите данные об облаке точек с pcread
, предварительно обработайте облако точек с помощью той же функции, используемой во время обучения, и преобразуйте результат в dlarray
.
ptCloud = pcread("car.pcd"); X = preprocessPointCloud(ptCloud); dlX = dlarray(X{1},"SCSB");
Предскажите метки облака точек с pointnetClassifier
функция модели.
YPred = pointnetClassifier(dlX,parameters,state,false); [~,classIdx] = max(YPred,[],1);
Отобразите облако точек и предсказанную метку с самым высоким счетом.
figure pcshow(ptCloud.Location,[0 1 0],"MarkerSize",40,"VerticalAxisDir","down") title(classes(classIdx))
Функция modelGradients берет в качестве входа мини-пакет данных dlX
, соответствующий целевой dlY
, и настраиваемые параметры, и возвращают градиенты потери относительно настраиваемых параметров и соответствующей потери. Потеря включает термин регуляризации, спроектированный, чтобы гарантировать, что матрица преобразования функции, предсказанная энкодером PointNet, является приблизительно ортогональной. Чтобы вычислить градиенты, оцените modelGradients
функция с помощью dlfeval
функция в учебном цикле.
function [gradients, loss, state, acc] = modelGradients(X,Y,parameters,state) % Execute the model function. isTraining = true; [YPred,state,dlT] = pointnetClassifier(X,parameters,state,isTraining); % Add regularization term to ensure feature transform matrix is % approximately orthogonal. K = size(dlT,1); B = size(dlT, 4); I = repelem(eye(K),1,1,1,B); dlI = dlarray(I,"SSCB"); treg = mse(dlI,pagemtimes(dlT,permute(dlT,[2 1 3 4]))); factor = 0.001; % Compute the loss. loss = crossentropy(YPred,Y) + factor*treg; % Compute the parameter gradients with respect to the loss. gradients = dlgradient(loss, parameters); % Compute training accuracy metric. [~,YTest] = max(Y,[],1); [~,YPred] = max(YPred,[],1); acc = gather(extractdata(sum(YTest == YPred)./numel(YTest))); end
pointnetClassifier
функционируйте берет в качестве входа данные об облаке точек dlX, learnable параметры модели, состояние модели и флаг isTraining, который задает, возвращает ли модель выходные параметры для обучения или предсказания. Затем функция вызывает энкодер PointNet и многоуровневый perceptron, чтобы извлечь функции классификации. Во время обучения уволенный применяется после каждой perceptron операции. После последнего perceptron, fullyconnect
операция сопоставляет функции классификации с количеством классов, и softmax активация используется, чтобы нормировать выход в вероятностное распределение меток. Вероятностное распределение, обновленное состояние модели и матрица преобразования функции, предсказанная энкодером PointNet, возвращены как выходные параметры.
function [dlY,state,dlT] = pointnetClassifier(dlX,parameters,state,isTraining) % Invoke the PointNet encoder. [dlY,state,dlT] = pointnetEncoder(dlX,parameters,state,isTraining); % Invoke the classifier. p = parameters.ClassificationMLP.Perceptron; s = state.ClassificationMLP.Perceptron; for k = 1:numel(p) [dlY, s(k)] = perceptron(dlY,p(k),s(k),isTraining); % If training, apply inverted dropout with a probability of 0.3. if isTraining probability = 0.3; dropoutScaleFactor = 1 - probability; dropoutMask = ( rand(size(dlY), "like", dlY) > probability ) / dropoutScaleFactor; dlY = dlY.*dropoutMask; end end state.ClassificationMLP.Perceptron = s; % Apply final fully connected and softmax operations. weights = parameters.ClassificationMLP.FC.Weights; bias = parameters.ClassificationMLP.FC.Bias; dlY = fullyconnect(dlY,weights,bias); dlY = softmax(dlY); end
pointnetEncoder
функциональные процессы, которые вход dlX использование входа преобразовывает, разделяемый MLP, функция, преобразовывают, секунда совместно использовала MLP и макс. операцию, и возвращает результат макс. операции.
function [dlY,state,T] = pointnetEncoder(dlX,parameters,state,isTraining) % Input transform. [dlY,state.InputTransform] = dataTransform(dlX,parameters.InputTransform,state.InputTransform,isTraining); % Shared MLP. [dlY,state.SharedMLP1.Perceptron] = sharedMLP(dlY,parameters.SharedMLP1.Perceptron,state.SharedMLP1.Perceptron,isTraining); % Feature transform. [dlY,state.FeatureTransform,T] = dataTransform(dlY,parameters.FeatureTransform,state.FeatureTransform,isTraining); % Shared MLP. [dlY,state.SharedMLP2.Perceptron] = sharedMLP(dlY,parameters.SharedMLP2.Perceptron,state.SharedMLP2.Perceptron,isTraining); % Max operation. dlY = max(dlY,[],1); end
Разделяемый многоуровневый perceptron
функциональные процессы вход dlX использование ряда perceptron операций и возвращают результат последнего perceptron.
function [dlY,state] = sharedMLP(dlX,parameters,state,isTraining) dlY = dlX; for k = 1:numel(parameters) [dlY, state(k)] = perceptron(dlY,parameters(k),state(k),isTraining); end end
Функция perceptron обрабатывает вход dlX использование свертки, нормализации партии. и relu операции и возвращает выходной параметр операции ReLU.
function [dlY,state] = perceptron(dlX,parameters,state,isTraining) % Convolution. W = parameters.Conv.Weights; B = parameters.Conv.Bias; dlY = dlconv(dlX,W,B); % Batch normalization. Update batch normalization state when training. offset = parameters.BatchNorm.Offset; scale = parameters.BatchNorm.Scale; trainedMean = state.BatchNorm.TrainedMean; trainedVariance = state.BatchNorm.TrainedVariance; if isTraining [dlY,trainedMean,trainedVariance] = batchnorm(dlY,offset,scale,trainedMean,trainedVariance); % Update state. state.BatchNorm.TrainedMean = trainedMean; state.BatchNorm.TrainedVariance = trainedVariance; else dlY = batchnorm(dlY,offset,scale,trainedMean,trainedVariance); end % ReLU. dlY = relu(dlY); end
dataTransform
функциональные процессы вход dlX
с помощью разделяемого MLP, макс. операции, и другой совместно использовал MLP, чтобы предсказать матрицу преобразования T. Матрица преобразования применяется к входу dlX, использование пакетного умножение матриц операция. Функция возвращает результат пакетного, умножение матриц и матрица преобразования.
function [dlY,state,T] = dataTransform(dlX,parameters,state,isTraining) % Shared MLP. [dlY,state.Block1.Perceptron] = sharedMLP(dlX,parameters.Block1.Perceptron,state.Block1.Perceptron,isTraining); % Max operation. dlY = max(dlY,[],1); % Shared MLP. [dlY,state.Block2.Perceptron] = sharedMLP(dlY,parameters.Block2.Perceptron,state.Block2.Perceptron,isTraining); % Transform net (T-Net). Apply last fully connected operation as W*X to % predict tranformation matrix T. dlY = squeeze(dlY); % N-by-B T = parameters.Transform * stripdims(dlY); % K^2-by-B % Reshape T into a square matrix. K = sqrt(size(T,1)); T = reshape(T,K,K,1,[]); % [K K 1 B] T = T + eye(K); % Apply to input dlX using batch matrix multiply. [C,B] = size(dlX,[3 4]); % [M 1 K B] dlX = reshape(dlX,[],C,1,B); % [M K 1 B] Y = pagemtimes(dlX,T); dlY = dlarray(Y,"SCSB"); end
initializeTransform
ФункцияinitializeTransform
функционируйте берет в качестве входа, размер канала и количество скрытых каналов для двух совместно использовали MLPs и возвращают инициализированные параметры в struct. Параметры инициализируются с помощью Него инициализация веса [3].
function [params,state] = initializeTransform(inputChannelSize,block1,block2) [params.Block1,state.Block1] = initializeSharedMLP(inputChannelSize,block1); [params.Block2,state.Block2] = initializeSharedMLP(block1(end),block2); % Parameters for the transform matrix. params.Transform = dlarray(zeros(inputChannelSize^2,block2(end))); end
initializeSharedMLP
ФункцияФункция initializeSharedMLP берет в качестве входа размер канала и скрытый размер канала, и возвращает инициализированные параметры в struct. Параметры инициализируются с помощью Него инициализация веса.
function [params,state] = initializeSharedMLP(inputChannelSize,hiddenChannelSize) weights = initializeWeightsHe([1 1 inputChannelSize hiddenChannelSize(1)]); bias = zeros(hiddenChannelSize(1),1,"single"); p.Conv.Weights = dlarray(weights); p.Conv.Bias = dlarray(bias); p.BatchNorm.Offset = dlarray(zeros(hiddenChannelSize(1),1,"single")); p.BatchNorm.Scale = dlarray(ones(hiddenChannelSize(1),1,"single")); s.BatchNorm.TrainedMean = zeros(hiddenChannelSize(1),1,"single"); s.BatchNorm.TrainedVariance = ones(hiddenChannelSize(1),1,"single"); params.Perceptron(1) = p; state.Perceptron(1) = s; for k = 2:numel(hiddenChannelSize) weights = initializeWeightsHe([1 1 hiddenChannelSize(k-1) hiddenChannelSize(k)]); bias = zeros(hiddenChannelSize(k),1,"single"); p.Conv.Weights = dlarray(weights); p.Conv.Bias = dlarray(bias); p.BatchNorm.Offset = dlarray(zeros(hiddenChannelSize(k),1,"single")); p.BatchNorm.Scale = dlarray(ones(hiddenChannelSize(k),1,"single")); s.BatchNorm.TrainedMean = zeros(hiddenChannelSize(k),1,"single"); s.BatchNorm.TrainedVariance = ones(hiddenChannelSize(k),1,"single"); params.Perceptron(k) = p; state.Perceptron(k) = s; end end
initializeClassificationMLP
ФункцияinitializeClassificationMLP
функционируйте берет в качестве входа размер канала, скрытый размер канала и количество классов и возвращает инициализированные параметры в struct. Разделяемый MLP инициализируется с помощью Него, инициализация веса и финал полностью соединились, операция инициализируется с помощью случайных Гауссовых значений.
function [params,state] = initializeClassificationMLP(inputChannelSize,hiddenChannelSize,numClasses) [params,state] = initializeSharedMLP(inputChannelSize,hiddenChannelSize); weights = initializeWeightsGaussian([numClasses hiddenChannelSize(end)]); bias = zeros(numClasses,1,"single"); params.FC.Weights = dlarray(weights); params.FC.Bias = dlarray(bias); end
initializeWeightsHe
ФункцияinitializeWeightsHe
функция инициализирует использование параметров Он инициализация.
function x = initializeWeightsHe(sz) fanIn = prod(sz(1:3)); stddev = sqrt(2/fanIn); x = stddev .* randn(sz); end
initializeWeightsGaussian
ФункцияinitializeWeightsGaussian
функция инициализирует параметры с помощью Гауссовой инициализации со стандартным отклонением 0,01.
function x = initializeWeightsGaussian(sz) x = randn(sz,"single") .* 0.01; end
preprocessPointCloudData
ФункцияpreprocessPointCloudData
функционируйте извлекает эти X, Y, Z данные о точке из входных данных и нормирует данные между 0 и 1. Функция возвращает нормированный X, Y, Z данные.
function data = preprocessPointCloud(data) if ~iscell(data) data = {data}; end numObservations = size(data,1); for i = 1:numObservations % Scale points between 0 and 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}.Location - xyzMin) ./ xyzDiff; end end
selectPoints
ФункцияselectPoints
функциональные выборки желаемое число точек. Когда облако точек содержит больше, чем желаемое число точек, функция использует pcdownsample
случайным образом выбрать точки. В противном случае функция реплицирует данные, чтобы произвести желаемое число точек.
function data = selectPoints(data,numPoints) % Select the desired number of points by downsampling or replicating % point cloud data. numObservations = size(data,1); for i = 1:numObservations ptCloud = data{i,1}; if ptCloud.Count > numPoints percentage = numPoints/ptCloud.Count; data{i,1} = pcdownsample(ptCloud,"random",percentage); else replicationFactor = ceil(numPoints/ptCloud.Count); ind = repmat(1:ptCloud.Count,1,replicationFactor); data{i,1} = select(ptCloud,ind(1:numPoints)); end end end
augmentPointCloudData
функция случайным образом вращает облако точек об оси z, случайным образом понижается на 30% точек, и случайным образом дрожит местоположение точки с Гауссовым шумом.
function data = augmentPointCloud(data) numObservations = size(data,1); for i = 1:numObservations ptCloud = data{i,1}; % Rotate the point cloud about "up axis", which is Z for this data set. tform = randomAffine3d(... "XReflection", true,... "YReflection", true,... "Rotation",@randomRotationAboutZ); ptCloud = pctransform(ptCloud,tform); % Randomly drop out 30% of the points. if rand > 0.5 ptCloud = pcdownsample(ptCloud,'random',0.3); end if rand > 0.5 % Jitter the point locations with Gaussian noise with a mean of 0 and % a standard deviation of 0.02 by creating a random displacement field. D = 0.02 * randn(size(ptCloud.Location)); ptCloud = pctransform(ptCloud,D); end data{i,1} = ptCloud; end end function [rotationAxis,theta] = randomRotationAboutZ() rotationAxis = [0 0 1]; theta = 2*pi*rand; end
aggregateConfusionMetric
ФункцияaggregateConfusionMetric
функционируйте инкрементно заполняет матрицу беспорядка на основе предсказанных результатов YPred
и ожидаемые результаты YTest
.
function cmat = aggreateConfusionMetric(cmat,YTest,YPred) YTest = gather(extractdata(YTest)); YPred = gather(extractdata(YPred)); [m,n] = size(cmat); cmat = cmat + full(sparse(YTest,YPred,1,m,n)); end
initializeTrainingProgressPlot
ФункцияinitializeTrainingProgressPlot
функция конфигурирует два графика для отображения учебной потери, учебной точности и точности валидации.
function [plotter,trainAccPlotter,valAccPlotter] = initializeTrainingProgressPlot() % Plot the loss, training accuracy, and validation accuracy. figure % Loss plot subplot(2,1,1) plotter = animatedline; xlabel("Iteration") ylabel("Loss") % Accuracy plot subplot(2,1,2) trainAccPlotter = animatedline('Color','b'); valAccPlotter = animatedline('Color','g'); legend('Training Accuracy','Validation Accuracy','Location','northwest'); xlabel("Iteration") ylabel("Accuracy") end
replicateFiles
ФункцияreplicateFiles
функция случайным образом сверхдискретизировала набор файлов и возвращает набор файлов с numDesired
элементы.
function files = randReplicateFiles(files,numDesired) n = numel(files); ind = randi(n,numDesired,1); files = files(ind); end
downloadSydneyUrbanObjects
ФункцияdownloadSydneyUrbanObjects
функционируйте загружает набор данных и сохраняет его во временную директорию.
function datapath = downloadSydneyUrbanObjects(dataLoc) if nargin == 0 dataLoc = pwd; end 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'); if ~exist(datapath,'dir') disp('Downloading Sydney Urban Objects data set...'); untar(url+name,dataLoc); end end
loadSydneyUrbanObjectsData
ФункцияThe loadSydneyUrbanObjectsData
функция создает datastore для облака пункта погрузки и данных о метке из набора данных Сидни Урбана Обджектса.
function ds = loadSydneyUrbanObjectsData(datapath,folds) if nargin == 0 return; end if nargin < 2 folds = 1:4; end datapath = string(datapath); path = fullfile(datapath,'objects',filesep); % Add folds to datastore. foldNames{1} = importdata(fullfile(datapath,'folds','fold0.txt')); foldNames{2} = importdata(fullfile(datapath,'folds','fold1.txt')); foldNames{3} = importdata(fullfile(datapath,'folds','fold2.txt')); foldNames{4} = importdata(fullfile(datapath,'folds','fold3.txt')); names = foldNames(folds); names = vertcat(names{:}); fullFilenames = append(path,names); ds = fileDatastore(fullFilenames,'ReadFcn',@extractTrainingData,'FileExtensions','.bin'); end
batchData
ФункцияbatchData
функция сопоставляет данные в пакеты и данные о перемещениях к графическому процессору для обработки.
function [X,Y] = batchData(ptCloud,labels) X = cat(4,ptCloud{:}); labels = cat(1,labels{:}); Y = onehotencode(labels,2); end
extractTrainingData
ФункцияextractTrainingData функционируют облако точек извлечений и данные о метке из набора данных Сидни Урбана Обджектса.
function dataOut = extractTrainingData(fname) [pointData,intensity] = readbin(fname); [~,name] = fileparts(fname); name = string(name); name = extractBefore(name,'.'); name = replace(name,'_',' '); labelNames = ["4wd","building","bus","car","pedestrian","pillar",... "pole","traffic lights","traffic sign","tree","truck","trunk","ute","van"]; label = categorical(name,labelNames); dataOut = {pointCloud(pointData,'Intensity',intensity),label}; end
readbin
Функцияreadbin
функция считывает данные об облаке точек из двоичных файлов Сидни Урбана Обджекта.
function [pointData,intensity] = readbin(fname) % readbin Read point and intensity data from Sydney Urban Object binary % files. % names = ['t','intensity','id',... % 'x','y','z',... % 'azimuth','range','pid'] % % formats = ['int64', 'uint8', 'uint8',... % 'float32', 'float32', 'float32',... % 'float32', 'float32', 'int32'] fid = fopen(fname, 'r'); c = onCleanup(@() fclose(fid)); fseek(fid,10,-1); % Move to the first X point location 10 bytes from beginning X = fread(fid,inf,'single',30); fseek(fid,14,-1); Y = fread(fid,inf,'single',30); fseek(fid,18,-1); Z = fread(fid,inf,'single',30); fseek(fid,8,-1); intensity = fread(fid,inf,'uint8',33); pointData = [X,Y,Z]; end
downloadPretrainedPointNet
ФункцияdownloadPretrainedPointNet
функционируйте загружает предварительно обученную pointnet модель.
function data = downloadPretrainedPointNet(pretrainedURL) % Download and load a pretrained pointnet model. if ~exist('pointnetSydneyUrbanObjects.mat', 'file') if ~exist('pointnetSydneyUrbanObjects.zip', 'file') disp('Downloading pretrained detector (5 MB)...'); websave('pointnetSydneyUrbanObjects.zip', pretrainedURL); end unzip('pointnetSydneyUrbanObjects.zip'); end data = load("pointnetSydneyUrbanObjects.mat"); end
prepareForPrediction
ФункцияprepareForPrediction
функция используется, чтобы применить пользовательскую функцию к вложенным данным о структуре. Это - используемый, чтобы переместить параметр модели и данные состояния к графическому процессору.
function p = prepareForPrediction(p,fcn) for i = 1:numel(p) p(i) = structfun(@(x)invoke(fcn,x),p(i),'UniformOutput',0); end function data = invoke(fcn,data) if isstruct(data) data = prepareForPrediction(data,fcn); else data = fcn(data); end end end % Move data to the GPU. function x = toDevice(x,useGPU) if useGPU x = gpuArray(x); end end
[1] Чарльз, Р. Ци, Хао Су, Мо Кэйчун и Леонидас Дж. Гуибас. “PointNet: Глубокое обучение на Наборах Точки для 3D Классификации и Сегментации”. На 2 017 Конференциях по IEEE по Компьютерному зрению и Распознаванию образов (CVPR), 77–85. Гонолулу, HI: IEEE, 2017. https://doi.org/10.1109/CVPR.2017.16.
[2] де Деж, Марк, Аластер Куэдрас, Келвин Хун и Бертран Дуиллар. "Безнадзорная Функция, Учащаяся для Классификации Наружных 3D Сканов". На австралазийской Конференции по Робототехнике и Автоматизации 2013 (ACRA 13). Сидней, Австралия: ACRA, 2013.
[3] Он, Kaiming, Сянюй Чжан, Шаоцин Жэнь и Цзянь Сунь. “Копаясь Глубоко в Выпрямителях: Превышение Эффективности Человеческого Уровня на Классификации ImageNet”. На 2 015 Международных конференциях IEEE по вопросам Компьютерного зрения (ICCV), 1026–34. Сантьяго, Чили: IEEE, 2015. https://doi.org/10.1109/ICCV.2015.123.