Классификация модуляций с использованием вейвлет на NVIDIA Jetson

Этот пример показывает, как сгенерировать и развернуть исполняемый файл CUDA ®, который выполняет классификацию модуляции с использованием функций, извлеченных непрерывным вейвлет (CWT) и предварительно обученной сверточной нейронной сетью (CNN).

Классификация модуляции является важной функцией для интеллектуального приемника. Классификация модуляций имеет многочисленные приложения, такие как когнитивный радар и программно-определяемое радио. Обычно, чтобы идентифицировать эти формы волны и классифицировать их по типу модуляции, необходимо задать значимые функции и ввести их в классификатор. Будучи эффективной, эта процедура может потребовать больших усилий и знаний в области, чтобы получить точную классификацию. В этом примере исследуется среда, чтобы автоматически извлечь функции из сигналов и выполнить классификацию сигналов с помощью нейронной сети для глубокого обучения.

Вы используете CWT, чтобы создать частотно-временные представления комплексно-значимых сигналов. Вам не нужно разделять сигнал на I и Q каналы. Вы используете представления, называемые скалограммами, и используете существующий CNN, переобучая сеть, чтобы классифицировать сигналы. Такое использование существующих нейронных сетей называется передачей обучения.

В этом примере мы адаптируем SqueezeNet, CNN, предварительно обученный для распознавания изображений, чтобы классифицировать тип модуляции каждой системы координат на основе скалограммы. Затем мы создадим исполняемый файл CUDA, который генерирует скалограмму входного сигнала. Мы развертываем исполняемый и переобученный CNN на целевом устройстве, позволяя классифицировать сигналы в режиме реального времени.

По умолчанию этот пример загружает обучающие данные и обученную сеть в один ZIP- файла wavelet_modulation_classification.zip. Размер ZIP- файла составляет примерно 1,2 гигабайта. У вас есть опция сгенерировать обучающие данные и обучить сеть. Однако оба являются длительными операциями. В зависимости от оборудования, генерация обучающих данных может занять один час или больше времени. Обучение сети может занять 90 минут или больше.

Типы модуляции

Задайте пять типов цифровой и три типа аналоговой модуляции:

  • Двоичная клавиша фазы сдвига (BPSK)

  • 16-арная квадратурная амплитудная модуляция (16-QAM)

  • 4-арная импульсная амплитудная модуляция (PAM4)

  • Гауссовая манипуляция со сдвигом частоты (GFSK)

  • Непрерывная манипуляция фазы сдвига частотой (CPFSK)

  • Широковещательная FM (B-FM)

  • Двойная амплитудная модуляция боковой полосы (DSB-AM)

  • Однополосная амплитудная модуляция (SSB-AM)

modTypesList = ["BPSK", ...
  "16QAM", "PAM4", "GFSK", "CPFSK", ...
  "B-FM", "DSB-AM", "SSB-AM"];
modulationTypes = categorical(modTypesList);

Укажите родительскую директорию parentDir и имя директории dataDir который будет внутри parentDir. Вы должны иметь разрешение на запись в parentDir. ZIP- файла загружается в parentDir. Поскольку пример загружает данные по умолчанию, dataDir должен быть 'wavelet_modulation_classification'. Область директории dataDirectory будет содержать обучающие данные, используемые в этом примере. ResultDir задает имя директории, который будет содержать обученную сеть. ResultDir находится в той же директории, что и этот пример, и будет создан для вас при необходимости.

parentDir = tempdir;
dataDir = 'wavelet_modulation_classification';
dataDirectory = fullfile(parentDir,dataDir);
ResultDir = 'trainedNetworks';

Задайте параметры обучающих данных. Обучающие данные состоят из 5000 систем координат для каждого типа модуляции. Каждая система координат имеет длину 1024 выборки и частоту дискретизации 200 кГц. Для типов цифровой модуляции восемь выборок представляют символ. Предположим, что центральная частота 902 МГц и 100 МГц для цифрового и аналогового типов модуляции, соответственно.

numFramesPerModType = 5000;
frameLength = 1024;
fs = 200e3;

Загрузка данных

Загрузите и разархивируйте обучающие данные и обученную сеть. The dataDirectory папка содержит папки, названные в честь каждого типа модуляции. Обучающие данные находятся в этих папках. Обученная сеть, waveletModClassNet.mat, находится в ResultDir.

Если вы не хотите загружать данные, задайте downloadData на ложь. Функция помощника helperGenerateModWaveforms генерирует системы координат и сохраняет их в dataDirectory. В целях воспроизводимости установите случайный seed.

downloadData = true;
if downloadData
    dataURL = 'https://ssd.mathworks.com/supportfiles/wavelet/waveletModulation/wavelet_modulation_classification.zip';
    zipFile = fullfile (parentDir,'wavelet_modulation_classification.zip');
    tic
    веб-сайт (zipFile, dataURL);
    disp (['Download time: ', num2str (toc),' seconds'])
    tic
    unzip (zipFile, parentDir);
    disp (['Unzipping time: ', num2str (toc),' seconds'])
    trainedNetworkDir = fullfile (parentDir, dataDir,'results');
    status = copyfile (trainedNetworkDir, ResultDir);
else
    rng (1235)
    helperGenerateModWaveforms (dataDirectory, modulationTypes, numFramesPerModType, frameLength, fs);
end
Download time: 38.2209 seconds
Unzipping time: 7.9005 seconds

Другой пример, Modulation Classification with Глубокое Обучение (Communications Toolbox), выполняет классификацию модуляции нескольких различных типов модуляции, используя Communications Toolbox™. Функция помощника helperGenerateModWaveforms генерирует и увеличивает подмножество типов модуляции, используемых в этом примере. Смотрите ссылку в качестве примера для подробного описания рабочего процесса, необходимого для классификации цифровых и аналоговых модуляций, и методов, используемых для создания этих осциллограмм.

Постройте график амплитуды действительной и мнимой частей представителя каждого типа модуляции. Функция помощника helperModClassPlotTimeDomain2 делает это.

helperModClassPlotTimeDomain2(dataDirectory,modulationTypes,fs)

Сгенерируйте скалограммы

Создайте частотно-временные представления форм волны. Эти представления называются скалограммами. Скалограмма является абсолютным значением коэффициентов CWT сигнала. Чтобы создать скалограммы, предварительно вычислите банк фильтров CWT. Предварительное вычисление группы фильтров CWT является предпочтительным способом при получении CWT многих сигналов с использованием тех же параметров.

Прежде чем сгенерировать все скалограммы, постройте график скалограмм от представителя каждого типа модуляции. Создайте банк фильтров CWT с помощью cwtfilterbank для сигнала с 1024 выборками и используйте банк фильтров, чтобы принять CWT сигнала. Поскольку сигнал является комплексным, CWT является трехмерным массивом. Первая страница является CWT для положительных шкал (аналитическая часть или компонент против часовой стрелки), а вторая страница является CWT для отрицательных шкал (антианалитическая часть или компонент против часовой стрелки). Чтобы сгенерировать скалограммы, примите абсолютное значение конкатенации каждой страницы. Функция помощника helperPlotScalogramsMod2 делает это.

helperPlotScalogramsMod2(dataDirectory,modulationTypes,frameLength,fs)

Если вы загрузили обучающие данные и обученную сеть, перейдите к разделению на данные обучения, проверки и валидации. В противном случае сгенерируйте все скалограммы в виде изображений RGB и запишите их в соответствующий подкаталог в dataDirectory. Функция помощника helperGenerateCWTfiles2 делает это. Для совместимости с архитектурой SqueezeNet каждый образ RGB представляет собой массив размера 227 227 3.

if ~downloadData
    helperGenerateCWTfiles2(dataDirectory,modulationTypes,frameLength,fs)
end

Разделите на данные обученияпроверки и валидации

Загрузите скалограммные изображения как image datastore. The imageDatastore функция автоматически помечает изображения на основе имен папок и сохраняет данные как объект ImageDatastore. image datastore позволяет вам хранить большие данные об изображениях, включая данные, которые не помещаются в памяти, и эффективно считывать пакеты изображений во время обучения CNN.

folders = fullfile(dataDirectory,string(modulationTypes));
imds = imageDatastore(folders,...
    'FileExtensions','.jpg','LabelSource','foldernames');

Случайным образом разделите изображения на три группы, где 80% используются для обучения, 10% используются для валидации и 10% используются для проверки. Мы используем системы координат обучения и валидации на фазе сетевого обучения. В целях воспроизводимости мы устанавливаем случайный seed.

rng(1235)
[imdsTrain,imdsTest,imdsValidation] = splitEachLabel(imds,0.8,0.1);

При необходимости создайте директорию, который будет содержать обученную сеть. Если вы загрузили данные, директорию, заданный как ResultDir уже exsts, и файл waveletModClassNet.mat в эта директория содержится обученная сеть.

if ~exist(ResultDir,'dir')
    mkdir(ResultDir)
end
MatFile = fullfile(ResultDir,'waveletModClassNet.mat');

Если вы загрузили ZIP- файла, загрузите обученную сеть и перейдите к разделу Оценка сети. В противном случае необходимо переобучить SqueezeNet.

if downloadData
    disp('Load ML model from the file')
    load(MatFile,'trainedNet','imdsValidation')
end
Load ML model from the file

SqueezeNet

SqueezeNet является предварительно обученным CNN, который может классифицировать изображения в 1000 категорий объектов. Необходимо переобучить SqueezeNet, чтобы классифицировать формы волны по их типу модуляции. Перед переобучением вы изменяете несколько слои сети и настраиваете различные опции обучения. После завершения переобучения вы сохраняете CNN в .mat файл. Исполняемый файл CUDA использует файл .mat.

Загрузите SqueezeNet и извлеките график слоев из сети. Смотрите последние пять слоев графика.

net = squeezenet;
lgraph = layerGraph(net);
lgraph.Layers(end-4:end)
ans = 
  5×1 Layer array with layers:

     1   'conv10'                            Convolution              1000 1×1×512 convolutions with stride [1  1] and padding [0  0  0  0]
     2   'relu_conv10'                       ReLU                     ReLU
     3   'pool10'                            Global Average Pooling   Global average pooling
     4   'prob'                              Softmax                  softmax
     5   'ClassificationLayer_predictions'   Classification Output    crossentropyex with 'tench' and 999 other classes

Последний обучаемый слой в SqueezeNet является сверточным слоем 1 на 1, 'conv10'. Замените слой на новый сверточный слой с количеством фильтров, равным количеству типов модуляции.

numClasses = numel(modulationTypes);
newLearnableLayer = convolution2dLayer(1,numClasses,'Name','new_conv10');
lgraph = replaceLayer(lgraph,lgraph.Layers(end-4).Name,newLearnableLayer);

Замените слой классификации новым слоем без меток классов. Классы выхода слоя устанавливаются автоматически во время обучения. Отображение последних пяти слоев для подтверждения изменений.

newClassLayer = classificationLayer('Name','new_classoutput');
lgraph = replaceLayer(lgraph,lgraph.Layers(end).Name,newClassLayer);
lgraph.Layers(end-4:end)
ans = 
  5×1 Layer array with layers:

     1   'new_conv10'        Convolution              8 1×1 convolutions with stride [1  1] and padding [0  0  0  0]
     2   'relu_conv10'       ReLU                     ReLU
     3   'pool10'            Global Average Pooling   Global average pooling
     4   'prob'              Softmax                  softmax
     5   'new_classoutput'   Classification Output    crossentropyex

Обучите CNN

Настройка нейронной сети является итеративным процессом, который включает минимизацию функции потерь. Используйте trainingOptions (Deep Learning Toolbox), чтобы задать опции для процесса обучения, который обеспечивает хорошую эффективность сети. Обратитесь к trainingOptions документация для описания каждой опции.

OptimSolver = 'adam';
MiniBatchSize = 50;
MaxEpochs = 20;
InitialLearnRate = 1e-4;
Shuffle = 'every-epoch';

options = trainingOptions(OptimSolver, ...
    'MiniBatchSize',MiniBatchSize, ...
    'MaxEpochs',MaxEpochs, ...
    'InitialLearnRate',InitialLearnRate, ...
    'Shuffle',Shuffle, ...
    'Verbose',false, ...
    'Plots','training-progress',...
    'ValidationData',imdsValidation);

Сохраните все параметры в структуре. Обученная сеть и структура будут позже сохранены в .mat файл.

TrialParameter.OptimSolver = OptimSolver;
TrialParameter.MiniBatchSize = MiniBatchSize;
TrialParameter.MaxEpochs = MaxEpochs;
TrialParameter.InitialLearnRate = InitialLearnRate;

Установите случайное начальное значение по умолчанию и используйте trainNetwork (Deep Learning Toolbox) функция для обучения CNN. Сохраните обученную сеть, пробные параметры, время запуска обучения и datastore, содержащее изображения для валидации. Из-за большого размера набора данных процесс займет много минут. По умолчанию обучение выполняется на графическом процессоре, если он доступен. Для использования графический процессор требуется Parallel Computing Toolbox™. Информацию о том, какие графические процессоры поддерживаются, см. в разделе Поддержка GPU Release (Parallel Computing Toolbox). В противном случае обучение выполняется на центральном процессоре. Графики точности обучения на рисунке показывают прогресс обучения сети во всех итерациях.

if ~downloadData
    rng default
    tic;
    trainedNet = trainNetwork(imdsTrain,lgraph,options);
    trainingTime = toc;
    fprintf('Total training time: %.2e sec\n',trainingTime);
    save(MatFile,'TrialParameter','trainedNet','trainingTime','imdsValidation');
end

Оценка сети

Загрузите .mat файл, содержащий обученную сеть и параметры обучения. Сохраните только обученную сеть в отдельном .mat файл. Этот файл будет использоваться исполняемым файлом CUDA.

OutMatFile = 'mdwv_model.mat';
data = load(MatFile,'trainedNet');
trainedNet = data.trainedNet;
save(OutMatFile,'trainedNet');

Оцените обученную сеть путем получения точности классификации для тестовых систем координат.

[YPred,probs] = classify(trainedNet,imdsTest);
imdsTestLabels = imdsTest.Labels;
modAccuracy = sum(YPred==imdsTestLabels)/numel(imdsTestLabels)*100
modAccuracy = 96.2250

Результирующая эффективность обученной сети на тестовых системах координат с графика путаницы. Отображение точности и отзыва для каждого класса с помощью сводных данных по столбцам и строкам. Сохраните рисунок. Таблица в нижней части графика неточностей показывает значения точности. Таблица справа от графика неточностей показывает значения отзыва.

figure('Units','normalized','Position',[0.2 0.2 0.5 0.5]);
ccDCNN = confusionchart(imdsTestLabels,YPred);
ccDCNN.Title = ['Test Accuracy: ',num2str(modAccuracy)];
ccDCNN.ColumnSummary = 'column-normalized';
ccDCNN.RowSummary = 'row-normalized';
AccFigFile = fullfile(ResultDir,'Network_ValidationAccuracy.fig');
saveas(gcf,AccFigFile);

Отображение размера обученной сети.

info = whos('trainedNet');
ModelMemSize = info.bytes/1024;
fprintf('Trained network size: %g kB\n',ModelMemSize)
Trained network size: 2992.95 kB

Определите среднее время, необходимое сети для классификации изображения.

NumTestForPredTime = 20;
TrialParameter.NumTestForPredTime = NumTestForPredTime;

fprintf('Test prediction time (number of tests: %d)... ',NumTestForPredTime)
Test prediction time (number of tests: 20)... 
imageSize = trainedNet.Layers(1).InputSize;
PredTime = zeros(NumTestForPredTime,1);
for i = 1:NumTestForPredTime
    x = randn(imageSize);
    tic;
    [YPred, probs] = classify(trainedNet,x);
    PredTime(i) = toc;
end
AvgPredTimePerImage = mean(PredTime);
fprintf('Average prediction time: %.2e sec \n',AvgPredTimePerImage);
Average prediction time: 8.41e-02 sec 

Сохраните результаты.

if ~downloadData
    save(MatFile,'modAccuracy','ccDCNN','PredTime','ModelMemSize', ...
        'AvgPredTimePerImage','-append')
end

Генерация кода GPU - Определение функций

Скалограмма сигнала - это вход «изображения» глубокому CNN. Создайте функцию, cwtModType, который вычисляет скалограмму комплексной формы волны и возвращает изображение в заданных пользователем размерностях. Изображение использует jet(128) палитра. Для целей генерации кода обрабатывайте входной сигнал как матрицу 1024 на 2, где первый столбец содержит действительные части выборок формы волны, а второй столбец содержит мнимые части. The %#codegen директива в функции указывает, что функция предназначена для генерации кода. При использовании coder.gpu.kernelfun pragma, генерация кода пытается сопоставить расчеты в cwtModType функцию для графический процессор.

type cwtModType
function im = cwtModType(inputSig, imgSize)  %#codegen
% This function is only intended to support wavelet deep learning examples.
% It may change or be removed in a future release.
coder.gpu.kernel;

% Input is a 1024x2 matrix, convert it into complex form (a + 1*ib)
cinputSig = convertToComplex(inputSig);

% Wavelet time-frequency representations
[wt, ~, ~] = cwt(cinputSig, 'morse', 1, 'VoicesPerOctave', 48);

% Generate Wavelet Time-Frequency Coefficients from Signal
cfs = abs([wt(:,:,1); wt(:,:,2)]); % Concatenate the clockwise and counterclockwise representation

% Image generation
im = generateImagefromCWTCoeff(cfs, imgSize);
end

Создайте функцию точки входа, modelPredictModType, для генерации кода. Функция принимает комплексный сигнал, заданный как матрица 1024 на 2, как вход и вызывает cwtModType функция для создания изображения скалограммы. The modelPredictModType функция использует сеть, содержащуюся в mdwv_model файл для классификации формы волны.

type modelPredictModType
function predClassProb = modelPredictModType(inputSig) %#codegen
% This function is only intended to support wavelet deep learning examples.
% It may change or be removed in a future release.
coder.gpu.kernelfun();
% input signal size is 1024-by-2

% parameters
ModelFile = 'mdwv_model.mat'; % file that saves the neural network model
imSize = [227 227]; % Size of the input image for the deep learning network

%Function to converts signal to wavelet time-frequency image
im = cwtModType(inputSig, imSize);

%Load the trained deep learning network
persistent model;
if isempty(model)
    model = coder.loadDeepLearningNetwork(ModelFile, 'mynet');
end

% Predict the Signal Modulation
predClassProb = model.predict(im);
end

Чтобы сгенерировать исполняемый файл CUDA, который можно развернуть на целевом устройстве NVIDIA, создайте пользовательский основной файл (main_mod_jetson.cu) и заголовочный файл (main_mod_jetson.h). Можно сгенерировать пример основного файла и использовать его как шаблон для переписывания новых основных и заголовочных файлов. Для получения дополнительной информации смотрите GenerateExampleMain свойство coder.CodeConfig (MATLAB Coder). Основной файл вызывает код, сгенерированный для функции точки входа MATLAB. Основной файл сначала читает сигнал формы волны из текстового файла, передает данные в функцию точки входа и записывает результаты предсказания в текстовый файл (predClassProb.txt). Чтобы максимизировать эффективность расчетов на графическом процессоре, исполняемый файл обрабатывает данные с одной точностью.

Если вы хотите просмотреть содержимое основного и заголовочного файлов, задайте viewFiles к true.

viewFiles = false;
if viewFiles
    напечатать main_mod_jetson.cu
end
if viewFiles
    напечатать main_mod_jetson.h
end

Генерация кода GPU - подключение к оборудованию

Для связи с оборудованием NVIDIA создайте объект подключения к активному оборудованию с помощью jetson функция. Для создания объекта подключения к активному оборудованию необходимо знать имя хоста или IP-адрес, имя пользователя и пароль целевой платы.

Создайте объект подключения к оборудованию Jetson. Во время оборудования объекта создания оборудования выполняется установка сервера ввода-вывода и сбор периферийной информации о цели. Эта информация отображается в Командном окне.

hwobj = jetson('gpucoder-nano-2','ubuntu','ubuntu');
Checking for CUDA availability on the Target...
Checking for 'nvcc' in the target system path...
Checking for cuDNN library availability on the Target...
Checking for TensorRT library availability on the Target...
Checking for prerequisite libraries is complete.
Gathering hardware details...
Checking for third-party library availability on the Target...
Gathering hardware details is complete.
 Board name         : NVIDIA Jetson TX1, NVIDIA Jetson Nano
 CUDA Version       : 10.0
 cuDNN Version      : 7.3
 TensorRT Version   : 5.0
 GStreamer Version  : 1.14.5
 V4L2 Version       : 1.14.2-1
 SDL Version        : 1.2
 Available Webcams  :  
 Available GPUs     : NVIDIA Tegra X1

Используйте coder.checkGpuInstall (GPU Coder) и проверьте, что компиляторы и библиотеки, необходимые для выполнения этого примера, правильно настроены на оборудовании.

envCfg = coder.gpuEnvConfig('jetson');
envCfg.DeepLibTarget = 'cudnn';
envCfg.DeepCodegen = 1;
envCfg.HardwareObject = hwobj;
envCfg.Quiet = 1;
coder.checkGpuInstall(envCfg)
ans = struct with fields:
                 gpu: 1
                cuda: 1
               cudnn: 1
            tensorrt: 0
        basiccodegen: 0
       basiccodeexec: 0
         deepcodegen: 1
        deepcodeexec: 0
    tensorrtdatatype: 0
           profiling: 0

Генерация кода GPU - установка целевого процессора

Чтобы создать исполняемый файл, который можно развернуть на целевом устройстве, установите CodeGenMode равным 1. Если вы хотите создать исполняемый файл, который запускается локально и удаленно соединяется с целевым устройством, установите CodeGenMode равным 2. Jetson_BuildDir задает директорию для выполнения процесса удаленной сборки на целевом компьютере. Если указанная директория сборки не существует в целевом устройстве, то программное обеспечение создает директорию с заданным именем.

CodeGenMode = 1;
Function_to_Gen = 'modelPredictModType';
ModFile = 'mdwv_model.mat'; % file that saves neural network model; consistent with "main_mod_jetson.cu"
ImgSize = [227 227]; % input image size for the ML model
Jetson_BuildDir = '~/projectMDWV';

Создайте объект строения кода GPU, необходимый для компиляции. Используйте coder.hardware функция для создания объекта строения для платформы Jetson и назначения его Hardware свойство объекта строения кода cfg. Использование 'NVIDIA Jetson' для TX1 Jetson или TX2 плат. Пользовательский основной файл является оболочкой, которая вызывает функцию точки входа в сгенерированном коде. Пользовательский файл необходим для развернутого исполняемого файла.

Используйте coder.DeepLearningConfig (GPU Coder) функция для создания CuDNN объект строения глубокого обучения и присвоение его DeepLearningConfig свойство объекта строения кода GPU. Генератор кода использует преимущества библиотеки глубоких нейронных сетей (cuDNN) NVIDIA ® CUDA ® для графических процессоров NVIDIA. cuDNN является библиотекой примитивов для глубоких нейронных сетей с ускорением графического процессора.

if CodeGenMode == 1
    cfg = coder.gpuConfig('exe');
    cfg.Hardware = coder.hardware('NVIDIA Jetson');
    cfg.Hardware.BuildDir = Jetson_BuildDir;
    cfg.DeepLearningConfig = coder.DeepLearningConfig('cudnn');
    cfg.CustomSource = 'main_mod_jetson.cu';
elseif CodeGenMode == 2
    cfg = coder.gpuConfig('lib');
    cfg.VerificationMode = 'PIL';
    cfg.Hardware = coder.hardware('NVIDIA Jetson');
    cfg.Hardware.BuildDir = Jetson_BuildDir;
    cfg.DeepLearningConfig = coder.DeepLearningConfig('cudnn');
end

Генерация кода GPU - компиляция

Чтобы сгенерировать код CUDA, используйте codegen и передайте строение кода графического процессора вместе с размером и типом входа для modelPredictModType функция точки входа. После завершения генерации кода на хосте сгенерированные файлы копируются и строятся на целевом компьютере.

codegen('-config ',cfg,Function_to_Gen,'-args',{single(ones(1024,2))},'-report');
Code generation successful: View report

Генерация кода GPU - Выбор сигнала

Исполняемый файл CUDA выполняет классификацию модуляции, генерируя скалограмму комплексной формы волны и применяя переобученный CNN к скалограмме. Выберите форму волны, которая была сгенерирована в начале этого примера. Из 5000 систем координат каждого типа модуляции выберите один из первых 50 систем координат, сгенерированных установкой waveNumber. Постройте график действительной и мнимой частей системы координат, и сгенерированной из него скалограммы. Используйте функцию helper helperPlotWaveFormAndScalogram. Исходный код для этой вспомогательной функции можно найти в разделе Вспомогательные функции в конце этого примера.

waveForm = modTypesList(6);
waveNumber =  1;
signal_data = helper Plot Wave Form And Scalogram (data Directory, wave Form, wave Number);

Если вы скомпилировали исполняемый файл, который будет развернут на целевой объект, запишите выбранный вами сигнал в текстовый файл signalFile. Используйте putFile() функция аппаратного объекта для размещения текстового файла на целевом объекте. The workspaceDir свойство содержит путь к codegen папка на целевом объекте. The main функция в исполняемом файле считывает данные из текстового файла, заданного signalFile и записывает результаты классификации в resultFile.

signalFile = 'signalData.txt';
resultFile = 'predClassProb.txt'; % consistent with "main_mod_jetson.cu"

if CodeGenMode == 1
    fid = fopen(signalFile,'w');
    for i = 1:length(signal_data)
        fprintf(fid,'%f\n',real(signal_data(i)));
    end
    for i = 1:length(signal_data)
        fprintf(fid,'%f\n',imag(signal_data(i)));
    end
    fclose(fid);
    hwobj.putFile(signalFile,hwobj.workspaceDir);
end

Генерация кода GPU - Выполнение

Запустите исполняемый файл.

При запуске развернутого исполняемого файла удалите предыдущий файл результатов, если он существует. Используйте runApplication() функцию для запуска исполняемого файла на целевом компьютере, а затем и getFile() функция для извлечения результатов. Поскольку результаты могут не существовать сразу после runApplication() вызов функции возвращается и, чтобы разрешить задержки связи, установите максимальное время для извлечения результатов равным 90 секундам. Используйте evalc функция для подавления выхода в командной строке.

if CodeGenMode == 1 % run deployed executable
    maxFetchTime = 90;
    resultFile_hw = fullfile(hwobj.workspaceDir,resultFile);
    if ispc
        resultFile_hw = strrep(resultFile_hw,'\','/');
    end
    
    ta = tic;
    
    hwobj.deleteFile(resultFile_hw)
    evalc('hwobj.runApplication(Function_to_Gen,signalFile)');
    
    tf = tic;
    success = false;
    while toc(tf) < maxFetchTime
        try
            evalc('hwobj.getFile(resultFile_hw)');
            success = true;
        catch ME
        end
        if success
            break
        end
    end
    fprintf('Fetch time = %.3e sec\n',toc(tf));
    assert(success,'Unable to fetch the prediction')
    PredClassProb = readmatrix(resultFile);
    PredTime = toc(ta);
elseif CodeGenMode == 2 % run PIL executable
    sigData = [real(signal_data)';imag(signal_data)']';
    ta = tic;
    eval(sprintf('PredClassProb = %s_pil(single(sigData));',Function_to_Gen));
    PredTime = toc(ta);
    eval(sprintf('clear %s_pil;',Function_to_Gen)); % terminate PIL execution
end
Fetch time = 4.852e+00 sec

Генерация кода GPU - отображение результата

The resultFile содержит результаты классификации. Для каждого возможного типа модуляции сеть присвоила вероятность того, что сигнал был такого типа. Отобразите выбранный тип модуляции. Используйте функцию helper helperPredViz для отображения результатов классификации.

if CodeGenMode == 1
    helperPredViz                   % read fetched prediction results file
elseif CodeGenMode == 2
    helperPredVizPil(PredClassProb) % read workspace variable
end

fprintf('Expected Waveform: %s\n',waveForm);
Expected Waveform: B-FM

Сводные данные

В этом примере показано, как создать и развернуть исполняемый файл CUDA, который использует CNN для выполнения классификации модуляций. У вас также есть опция создать исполняемый файл, который запускается локально и соединяется с удаленным объектом. Полный рабочий процесс представлен в этом примере. После загрузки данных CWT используется для извлечения функций из формы волны. Затем SqueezeNet переобучается, чтобы классифицировать сигналы на основе их скалограмм. Две пользовательские функции создаются и компилируются на целевом устройстве NVIDIA. Результаты выполнения сравниваются с MATLAB.

Вспомогательные функции

helperPlotWaveFormAndScalogram

function sig = helperPlotWaveFormAndScalogram(dataDirectory,wvType,wvNum)
% This function is only intended to support wavelet deep learning examples.
% It may change or be removed in a future release.

waveFileName = sprintf('frame%s%05d.mat',wvType,wvNum);
load(fullfile(dataDirectory,wvType,waveFileName),'frame');
sig = frame;

cfs = cwt(sig,'morse',1,'VoicesPerOctave',48);
cfs = abs([cfs(:,:,1);cfs(:,:,2)]);

subplot(211)
plot(real(frame))
hold on
plot(imag(frame))
hold off
axis tight
legend('Real','Imag')
str = sprintf('Waveform: %s / Frame: %d\n Signal',wvType,wvNum);
title(str)

subplot(212)
imagesc(cfs)
title('Time-Frequency Representation')
%set(gca,'xtick',[]);
set(gca,'ytick',[]);

end

helperPredVizPil

function helperPredVizPil(PredClassProb)
% This function is only intended to support wavelet deep learning examples.
% It may change or be removed in a future release.

classNames = {'16QAM';'B-FM';'BPSK';'CPFSK';'DSB-AM';'GFSK';'PAM4';'SSB-AM'};
figure
bar(PredClassProb)
set(gca, 'XTickLabel' , classNames)
xlabel('Class Labels')
ylabel('Probability')
title('Modulation Classification Output')
axis tight
grid on

end

Похожие темы