То В этом примере показано, как классифицировать радар, возвращается с обоими подходами машинного и глубокого обучения. Подход машинного обучения использует извлечение признаков рассеивания вейвлета вместе с машиной опорных векторов. Кроме того, два подхода глубокого обучения проиллюстрированы: использование передачи обучения SqueezeNet и рекуррентная нейронная сеть Долгой краткосрочной памяти (LSTM). Обратите внимание на то, что набор данных, используемый в этом примере, не требует усовершенствованных методов, но рабочий процесс описан, потому что методы могут быть расширены к более сложным задачам.
Целевая классификация является важной функцией в современных радиолокационных системах. Этот пример использует машинное и глубокое обучение, чтобы классифицировать радарное эхо от цилиндра и конуса. Несмотря на то, что этот пример использует синтезируемые выборки I/Q, рабочий процесс применим к действительному радару, возвращается.
Следующий раздел показывает, как создать синтезируемые данные, чтобы обучить алгоритмы обучения.
Следующий код симулирует шаблон RCS цилиндра с радиусом 1 метра и высотой 10 метров. Рабочая частота радара составляет 850 МГц.
c = 3e8; fc = 850e6; [cylrcs,az,el] = rcscylinder(1,1,10,c,fc); helperTargetRCSPatternPlot(az,el,cylrcs);
Шаблон может затем быть применен к радарной цели обратного рассеяния, чтобы симулировать, возвращается из углов различных аспектов.
cyltgt = phased.BackscatterRadarTarget('PropagationSpeed',c,... 'OperatingFrequency',fc,'AzimuthAngles',az,'ElevationAngles',el,'RCSPattern',cylrcs);
Следующий график показывает, как симулировать 100, возвращается из цилиндра в зависимости от времени. Это принято, что цилиндр под движениями движение, которое вызывает маленькие колебания вокруг вида скуки, в результате угол обзора, изменяется от одной выборки до следующего.
rng default; N = 100; az = 2*randn(1,N); el = 2*randn(1,N); cylrtn = cyltgt(ones(1,N),[az;el]); plot(mag2db(abs(cylrtn))); xlabel('Time Index') ylabel('Target Return (dB)'); title('Target Return for Cylinder');
Возврат конуса может быть сгенерирован так же. Чтобы создать набор обучающих данных, вышеупомянутый процесс повторяется для 5 произвольно выбранных цилиндрических радиусов. Кроме того, для каждого радиуса, 10 профилей движения симулированы путем варьирования инцидентного угла после 10 случайным образом сгенерированных кривых синусоиды вокруг опорного направления. В каждом профиле движения существует 701 выборка, таким образом, существуют 701 50 выборки. Процесс повторяется для цилиндрической цели, которая приводит к 701 100 матрица обучающих данных с 50 цилиндрами и 50 коническими профилями. В наборе тестов мы используем 25 цилиндров и 25 конических профилей, чтобы создать 701 50 набор обучающих данных. Из-за долгого времени вычисления обучающие данные предварительно вычислены и загружены ниже.
load('RCSClassificationReturnsTraining'); load('RCSClassificationReturnsTest');
Как пример, следующий график показывает возврат для одного из профилей движения от каждой формы. Графики показывают, как изменение значений в зависимости от времени и для инцидентных углов азимута и для цели возвращается.
subplot(2,2,1) plot(cylinderAspectAngle(1,:)) ylim([-90 90]) grid on title('Cylinder Aspect Angle vs. Time'); xlabel('Time Index'); ylabel('Aspect Angle (degrees)'); subplot(2,2,3) plot(RCSReturns.Cylinder_1); ylim([-50 50]); grid on title('Cylinder Return'); xlabel('Time Index'); ylabel('Target Return (dB)'); subplot(2,2,2) plot(coneAspectAngle(1,:)); ylim([-90 90]); grid on; title('Cone Aspect Angle vs. Time'); xlabel('Time Index'); ylabel('Aspect Angle (degrees)'); subplot(2,2,4); plot(RCSReturns.Cone_1); ylim([-50 50]); grid on; title('Cone Return'); xlabel('Time Index'); ylabel('Target Return (dB)');
В вейвлете, рассеивающем экстрактор функции, данные распространены через серию вейвлета, преобразовывает, нелинейность и усреднение, чтобы произвести представления низкого отклонения временных рядов. Время вейвлета, рассеивая урожаи сигнализирует, что представления, нечувствительные к, переключают входной сигнал на нижний регистр, не жертвуя классом discriminability.
Основные параметры, чтобы задать в разложении рассеивания времени вейвлета являются шкалой независимого от времени, количество вейвлета преобразовывает, и количество вейвлетов на октаву в каждом из наборов фильтров вейвлета. Во многих приложениях каскад двух наборов фильтров достаточен, чтобы достигнуть хорошей производительности. В этом примере мы создаем разложение рассеивания времени вейвлета с наборами фильтров по умолчанию: 8 вейвлетов на октаву в первом наборе фильтров и 1 вейвлет на октаву во втором наборе фильтров. Шкала инвариантности установлена в 701 выборку, длину данных.
sf = waveletScattering('SignalLength',701,'InvarianceScale',701);
Затем мы получаем рассеивающиеся преобразования и наборов обучающих данных и наборов тестов.
sTrain = sf.featureMatrix(RCSReturns{:,:},'transform','log'); sTest = sf.featureMatrix(RCSReturnsTest{:,:},'transform','log');
В данном примере используйте среднее значение рассеивающихся коэффициентов, взятых с собой каждый путь.
TrainFeatures = squeeze(mean(sTrain,2))'; TestFeatures = squeeze(mean(sTest,2))';
Создайте метки для обучения и изучения
TrainLabels = repelem(categorical({'Cylinder','Cone'}),[50 50])'; TestLabels = repelem(categorical({'Cylinder','Cone'}),[25 25])';
Подбирайте модель машины опорных векторов с квадратичным ядром к рассеивающимся функциям и получите точность перекрестной проверки.
template = templateSVM('KernelFunction', 'polynomial', ... 'PolynomialOrder', 2, ... 'KernelScale', 'auto', ... 'BoxConstraint', 1, ... 'Standardize', true); classificationSVM = fitcecoc(... TrainFeatures, ... TrainLabels, ... 'Learners', template, ... 'Coding', 'onevsone', ... 'ClassNames', categorical({'Cylinder','Cone'})); partitionedModel = crossval(classificationSVM, 'KFold', 5); [validationPredictions, validationScores] = kfoldPredict(partitionedModel); validationAccuracy = (1 - kfoldLoss(partitionedModel, 'LossFun', 'ClassifError'))*100
validationAccuracy = 100
Используя обученный SVM, классифицируйте рассеивающиеся функции, полученные из набора тестов.
predLabels = predict(classificationSVM,TestFeatures); accuracy = sum(predLabels == TestLabels )/numel(TestLabels)*100
accuracy = 100
Постройте матрицу беспорядка.
figure('Units','normalized','Position',[0.2 0.2 0.5 0.5]); ccDCNN = confusionchart(TestLabels,predLabels); ccDCNN.Title = 'Confusion Chart'; ccDCNN.ColumnSummary = 'column-normalized'; ccDCNN.RowSummary = 'row-normalized';
Для наборов более комплексных данных рабочий процесс глубокого обучения может улучшать производительность.
SqueezeNet является глубокой сверточной нейронной сетью (CNN), обученной изображениям в 1 000 классов, как используется в Крупном масштабе ImageNet визуальной проблеме распознавания (ILSVRC). В этом примере мы снова используем предварительно обученный SqueezeNet, чтобы классифицировать радар, возвращает принадлежность одному из двух классов.
Загрузите SqueezeNet.
snet = squeezenet; snet.Layers
ans = 68x1 Layer array with layers: 1 'data' Image Input 227x227x3 images with 'zerocenter' normalization 2 'conv1' Convolution 64 3x3x3 convolutions with stride [2 2] and padding [0 0 0 0] 3 'relu_conv1' ReLU ReLU 4 'pool1' Max Pooling 3x3 max pooling with stride [2 2] and padding [0 0 0 0] 5 'fire2-squeeze1x1' Convolution 16 1x1x64 convolutions with stride [1 1] and padding [0 0 0 0] 6 'fire2-relu_squeeze1x1' ReLU ReLU 7 'fire2-expand1x1' Convolution 64 1x1x16 convolutions with stride [1 1] and padding [0 0 0 0] 8 'fire2-relu_expand1x1' ReLU ReLU 9 'fire2-expand3x3' Convolution 64 3x3x16 convolutions with stride [1 1] and padding [1 1 1 1] 10 'fire2-relu_expand3x3' ReLU ReLU 11 'fire2-concat' Depth concatenation Depth concatenation of 2 inputs 12 'fire3-squeeze1x1' Convolution 16 1x1x128 convolutions with stride [1 1] and padding [0 0 0 0] 13 'fire3-relu_squeeze1x1' ReLU ReLU 14 'fire3-expand1x1' Convolution 64 1x1x16 convolutions with stride [1 1] and padding [0 0 0 0] 15 'fire3-relu_expand1x1' ReLU ReLU 16 'fire3-expand3x3' Convolution 64 3x3x16 convolutions with stride [1 1] and padding [1 1 1 1] 17 'fire3-relu_expand3x3' ReLU ReLU 18 'fire3-concat' Depth concatenation Depth concatenation of 2 inputs 19 'pool3' Max Pooling 3x3 max pooling with stride [2 2] and padding [0 1 0 1] 20 'fire4-squeeze1x1' Convolution 32 1x1x128 convolutions with stride [1 1] and padding [0 0 0 0] 21 'fire4-relu_squeeze1x1' ReLU ReLU 22 'fire4-expand1x1' Convolution 128 1x1x32 convolutions with stride [1 1] and padding [0 0 0 0] 23 'fire4-relu_expand1x1' ReLU ReLU 24 'fire4-expand3x3' Convolution 128 3x3x32 convolutions with stride [1 1] and padding [1 1 1 1] 25 'fire4-relu_expand3x3' ReLU ReLU 26 'fire4-concat' Depth concatenation Depth concatenation of 2 inputs 27 'fire5-squeeze1x1' Convolution 32 1x1x256 convolutions with stride [1 1] and padding [0 0 0 0] 28 'fire5-relu_squeeze1x1' ReLU ReLU 29 'fire5-expand1x1' Convolution 128 1x1x32 convolutions with stride [1 1] and padding [0 0 0 0] 30 'fire5-relu_expand1x1' ReLU ReLU 31 'fire5-expand3x3' Convolution 128 3x3x32 convolutions with stride [1 1] and padding [1 1 1 1] 32 'fire5-relu_expand3x3' ReLU ReLU 33 'fire5-concat' Depth concatenation Depth concatenation of 2 inputs 34 'pool5' Max Pooling 3x3 max pooling with stride [2 2] and padding [0 1 0 1] 35 'fire6-squeeze1x1' Convolution 48 1x1x256 convolutions with stride [1 1] and padding [0 0 0 0] 36 'fire6-relu_squeeze1x1' ReLU ReLU 37 'fire6-expand1x1' Convolution 192 1x1x48 convolutions with stride [1 1] and padding [0 0 0 0] 38 'fire6-relu_expand1x1' ReLU ReLU 39 'fire6-expand3x3' Convolution 192 3x3x48 convolutions with stride [1 1] and padding [1 1 1 1] 40 'fire6-relu_expand3x3' ReLU ReLU 41 'fire6-concat' Depth concatenation Depth concatenation of 2 inputs 42 'fire7-squeeze1x1' Convolution 48 1x1x384 convolutions with stride [1 1] and padding [0 0 0 0] 43 'fire7-relu_squeeze1x1' ReLU ReLU 44 'fire7-expand1x1' Convolution 192 1x1x48 convolutions with stride [1 1] and padding [0 0 0 0] 45 'fire7-relu_expand1x1' ReLU ReLU 46 'fire7-expand3x3' Convolution 192 3x3x48 convolutions with stride [1 1] and padding [1 1 1 1] 47 'fire7-relu_expand3x3' ReLU ReLU 48 'fire7-concat' Depth concatenation Depth concatenation of 2 inputs 49 'fire8-squeeze1x1' Convolution 64 1x1x384 convolutions with stride [1 1] and padding [0 0 0 0] 50 'fire8-relu_squeeze1x1' ReLU ReLU 51 'fire8-expand1x1' Convolution 256 1x1x64 convolutions with stride [1 1] and padding [0 0 0 0] 52 'fire8-relu_expand1x1' ReLU ReLU 53 'fire8-expand3x3' Convolution 256 3x3x64 convolutions with stride [1 1] and padding [1 1 1 1] 54 'fire8-relu_expand3x3' ReLU ReLU 55 'fire8-concat' Depth concatenation Depth concatenation of 2 inputs 56 'fire9-squeeze1x1' Convolution 64 1x1x512 convolutions with stride [1 1] and padding [0 0 0 0] 57 'fire9-relu_squeeze1x1' ReLU ReLU 58 'fire9-expand1x1' Convolution 256 1x1x64 convolutions with stride [1 1] and padding [0 0 0 0] 59 'fire9-relu_expand1x1' ReLU ReLU 60 'fire9-expand3x3' Convolution 256 3x3x64 convolutions with stride [1 1] and padding [1 1 1 1] 61 'fire9-relu_expand3x3' ReLU ReLU 62 'fire9-concat' Depth concatenation Depth concatenation of 2 inputs 63 'drop9' Dropout 50% dropout 64 'conv10' Convolution 1000 1x1x512 convolutions with stride [1 1] and padding [0 0 0 0] 65 'relu_conv10' ReLU ReLU 66 'pool10' Global Average Pooling Global average pooling 67 'prob' Softmax softmax 68 'ClassificationLayer_predictions' Classification Output crossentropyex with 'tench' and 999 other classes
Вы видите, что SqueezeNet состоит из 68 слоев. Как весь DCNNs, SqueezeNet располагает каскадом сверточные операторы, сопровождаемые нелинейностью и объединением или усреднением. SqueezeNet ожидает вход изображений размера 227 227 3, который вы видите со следующим кодом.
snet.Layers(1)
ans = ImageInputLayer with properties: Name: 'data' InputSize: [227 227 3] Hyperparameters DataAugmentation: 'none' Normalization: 'zerocenter' NormalizationDimension: 'auto' Mean: [1×1×3 single]
Кроме того, SqueezeNet сконфигурирован к распознанным 1 000 различных классов, которые вы видите со следующим кодом.
snet.Layers(68)
ans = ClassificationOutputLayer with properties: Name: 'ClassificationLayer_predictions' Classes: [1000×1 categorical] OutputSize: 1000 Hyperparameters LossFunction: 'crossentropyex'
В последующем разделе мы изменим избранные слои SqueezeNet для того, чтобы применить его к нашей проблеме классификации.
SqueezeNet спроектирован, чтобы отличить различия в изображениях и классифицировать результаты. Поэтому для того, чтобы использовать SqueezeNet, чтобы классифицировать радар, возвращается, мы должны преобразовать 1D радар, возвращают временные ряды в изображение. Распространенный способ сделать это должно использовать представление частоты времени (TFR). Существует много вариантов для представления частоты времени сигнала и какой является самым соответствующим, зависит от характеристик сигнала. Чтобы определить, какой TFR может подходить для этой проблемы, случайным образом выберите и постройте некоторых, радар возвращается из каждого класса.
rng default;
idxCylinder = randperm(50,2);
idxCone = randperm(50,2)+50;
Очевидно, что радар возвращается ранее показанный, характеризуются путем замедления различных изменений, акцентированных большими переходными уменьшениями, аналогичными описанному ранее. Вейвлет преобразовывает, идеально подходит для разреженного представления таких сигналов. Вейвлеты уменьшаются, чтобы локализовать переходные процессы с высоким временным разрешением и фрагментом, чтобы получить медленно различную структуру сигнала. Получите и постройте непрерывное преобразование вейвлета одного из цилиндра, возвращается.
cwt(RCSReturns{:,idxCylinder(1)},'VoicesPerOctave',8)
CWT одновременно получает и медленно различный (низкая частота) колебания и переходные процессы. Контрастируйте CWT цилиндра возвращаются с одним из конической цели.
cwt(RCSReturns{:,idxCone(2)},'VoicesPerOctave',8);
Из-за очевидной важности переходных процессов в определении, происходит ли целевой возврат из цилиндра или конической цели, мы выбираем CWT как идеальный TFR, чтобы использовать. После получения CWT для каждого целевого возврата мы заставляем изображения из CWT каждого радара возвратиться. Эти изображения изменены, чтобы быть совместимыми с входным слоем SqueezeNet, и мы усиливаем SqueezeNet, чтобы классифицировать получившиеся изображения.
Функция помощника, helpergenWaveletTFImg
, получает CWT для каждого радара, возвращаются, изменяет CWT, чтобы быть совместимым с SqueezeNet и пишет CWT как jpeg файл. Запускать helpergenWaveletTFImg
, выберите parentDir
где у вас есть разрешение записи. Этот пример использует tempdir
, но можно использовать любую папку на машине, где у вас есть разрешение записи. Функция помощника создает Training
и Test
установите папки под parentDir
а также создание Cylinder
и Cone
подпапки под обоими Training
и Test
. Эти папки заполняются с изображениями jpeg, которые будут использоваться в качестве входных параметров к SqueezeNet.
parentDir = tempdir; helpergenWaveletTFImg(parentDir,RCSReturns,RCSReturnsTest)
Generating Time-Frequency Representations...Please Wait Creating Cylinder Time-Frequency Representations ... Done Creating Cone Time-Frequency Representations ... Done Creating Cylinder Time-Frequency Representations ... Done Creating Cone Time-Frequency Representations ... Done
Теперь используйте imageDataStore
управлять доступом к файлу от папок для того, чтобы обучить SqueezeNet. Создайте хранилища данных и для обучения и для тестовых данных.
trainingData= imageDatastore(fullfile(parentDir,'Training'), 'IncludeSubfolders', true,... 'LabelSource', 'foldernames'); testData = imageDatastore(fullfile(parentDir,'Test'),'IncludeSubfolders',true,... 'LabelSource','foldernames');
Для того, чтобы использовать SqueezeNet с этой бинарной проблемой классификации, мы должны изменить пару слоев. Во-первых, мы изменяем последний learnable слой в SqueezeNet (слой 64), чтобы иметь то же количество сверток 1 на 1 как наше новое количество классов, 2.
lgraphSqueeze = layerGraph(snet); convLayer = lgraphSqueeze.Layers(64); numClasses = numel(categories(trainingData.Labels)); newLearnableLayer = convolution2dLayer(1,numClasses, ... 'Name','binaryconv', ... 'WeightLearnRateFactor',10, ... 'BiasLearnRateFactor',10); lgraphSqueeze = replaceLayer(lgraphSqueeze,convLayer.Name,newLearnableLayer); classLayer = lgraphSqueeze.Layers(end); newClassLayer = classificationLayer('Name','binary'); lgraphSqueeze = replaceLayer(lgraphSqueeze,classLayer.Name,newClassLayer);
Наконец, установите опции для переквалификации SqueezeNet. Установите начальную букву, изучают уровень 1e-4, определяют максимальный номер эпох к 15 и мини-пакетного размера к 10. Используйте стохастический градиентный спуск с импульсом.
ilr = 1e-4; mxEpochs = 15; mbSize =10; opts = trainingOptions('sgdm', 'InitialLearnRate', ilr, ... 'MaxEpochs',mxEpochs , 'MiniBatchSize',mbSize, ... 'Plots', 'training-progress','ExecutionEnvironment','cpu');
Обучите сеть. Если у вас есть совместимый графический процессор, trainNetwork
автоматически использует графический процессор, и обучение должно завершиться меньше чем через одну минуту. Если у вас нет совместимого графического процессора, trainNetwork
использует центральный процессор, и обучение должно занять приблизительно пять минут. Учебные времена действительно варьируются на основе многих факторов. В этом случае обучение происходит на CPU путем установки ExecutionEnvironment
параметр к cpu
.
CWTnet = trainNetwork(trainingData,lgraphSqueeze,opts);
Initializing input data normalization.
|========================================================================================| | Epoch | Iteration | Time Elapsed | Mini-batch | Mini-batch | Base Learning | | | | (hh:mm:ss) | Accuracy | Loss | Rate | |========================================================================================|
| 1 | 1 | 00:00:01 | 60.00% | 2.6639 | 1.0000e-04 |
| 5 | 50 | 00:00:42 | 100.00% | 0.0001 | 1.0000e-04 |
| 10 | 100 | 00:01:20 | 100.00% | 0.0002 | 1.0000e-04 |
| 15 | 150 | 00:01:58 | 100.00% | 2.2276e-05 | 1.0000e-04 |
|========================================================================================|
Используйте обучивший сеть, чтобы предсказать, что цель возвращается в протянутом наборе тестов.
predictedLabels = classify(CWTnet,testData,'ExecutionEnvironment','cpu'); accuracy = sum(predictedLabels == testData.Labels)/50*100
accuracy = 100
Постройте график беспорядка наряду с точностью и отзывом. В этом случае 100% тестовых выборок классифицируются правильно.
figure('Units','normalized','Position',[0.2 0.2 0.5 0.5]); ccDCNN = confusionchart(testData.Labels,predictedLabels); ccDCNN.Title = 'Confusion Chart'; ccDCNN.ColumnSummary = 'column-normalized'; ccDCNN.RowSummary = 'row-normalized';
В итоговом разделе этого примера описан рабочий процесс LSTM. Сначала слои LSTM заданы:
LSTMlayers = [ ... sequenceInputLayer(1) bilstmLayer(100,'OutputMode','last') fullyConnectedLayer(2) softmaxLayer classificationLayer ]; options = trainingOptions('adam', ... 'MaxEpochs',30, ... 'MiniBatchSize', 150, ... 'InitialLearnRate', 0.01, ... 'GradientThreshold', 1, ... 'plots','training-progress', ... 'Verbose',false,'ExecutionEnvironment','cpu'); trainLabels = repelem(categorical({'cylinder','cone'}),[50 50]); trainLabels = trainLabels(:); trainData = num2cell(table2array(RCSReturns)',2); testData = num2cell(table2array(RCSReturnsTest)',2); testLabels = repelem(categorical({'cylinder','cone'}),[25 25]); testLabels = testLabels(:); RNNnet = trainNetwork(trainData,trainLabels,LSTMlayers,options);
Точность для этой системы также построена.
predictedLabels = classify(RNNnet,testData,'ExecutionEnvironment','cpu'); accuracy = sum(predictedLabels == testLabels)/50*100
accuracy = 100
Этот пример представляет рабочий процесс для выполнения радарной классификации целей с помощью методов машинного и глубокого обучения. Несмотря на то, что этот пример использовал синтезируемые данные, чтобы сделать обучение и тестирование, это может быть легко расширено, чтобы разместить действительный радар, возвращается. Из-за характеристик сигнала методы вейвлета использовались и в машинном обучении и в подходах CNN.
С этим набором данных мы были также получены, чтобы достигнуть подобной точности, только подав необработанные данные в LSTM. В более сложных наборах данных необработанные данные могут быть слишком по сути переменными для модели, чтобы узнать об устойчивых функциях из необработанных данных, и вам, вероятно, придется обратиться к извлечению признаков до использования LSTM.