В этом примере показано, как генерировать и развертывать исполняемый файл CUDA ®, который классифицирует сигналы электрокардиограммы человека (ЭКГ), используя признаки, извлеченные непрерывным вейвлет-преобразованием (CWT) и предварительно обученной сверточной нейронной сетью (CNN).
SqueeeNet - это глубокий CNN, изначально предназначенный для классификации изображений в 1000 категорий. Мы повторно используем сетевую архитектуру CNN для классификации сигналов ЭКГ на основе их скалограмм. Скалограмма - это абсолютное значение CWT сигнала. После обучения SqueeEzNet классификации сигналов ЭКГ создается исполняемый файл CUDA, который генерирует скалограмму сигнала ЭКГ, а затем использует CNN для классификации сигнала. Исполняемый файл и CNN развертываются на аппаратном обеспечении NVIDIA.
В этом примере используются те же данные, что и при классификации временных рядов с использованием вейвлет-анализа и глубокого обучения (инструментарий вейвлет). В этом примере обучение передаче с помощью GoogLeNet и SqueeEcNet используется для классификации форм сигналов ЭКГ на одну из трех категорий. Описание данных и способ их получения повторяются здесь для удобства.
Данные ЭКГ получены от трех групп людей: лиц с сердечной аритмией (ARR), лиц с застойной сердечной недостаточностью (CHF) и лиц с нормальными синусовыми ритмами (СМП). Всего существует 162 записей ЭКГ из трех баз данных PhysioNet: база данных аритмии MIT-BIH [2] [3], база данных нормального синусового ритма MIT-BIH [3] и база данных застойной сердечной недостаточности BIDMC [1] [3]. Более конкретно, 96 записей от людей с аритмией, 30 записей от людей с застойной сердечной недостаточностью и 36 записей от людей с нормальными синусовыми ритмами. Цель состоит в том, чтобы обучить модель различать ARR, CHF и NSR.
Эти данные можно получить из репозитория MathWorks GitHub. Чтобы загрузить данные с веб-сайта, нажмите Code и выбрать Download ZIP. Сохранить файл physionet_ECG_data-main.zip в папке, в которой имеется разрешение на запись. В инструкциях для этого примера предполагается, что файл загружен во временный каталог. tempdir, в MATLAB. Измените последующие инструкции по распаковке и загрузке данных, если вы решили загрузить данные в папку, отличную от tempdir.
После загрузки данных из GitHub распакуйте файл во временном каталоге.
unzip(fullfile(tempdir,'physionet_ECG_data-main.zip'),tempdir)Распаковка создает папку physionet-ECG_data-main во временном каталоге. Эта папка содержит текстовый файл README.md и ECGData.zip. ECGData.zip файл содержит:
ECGData.mat
Modified_physionet_data.txt
License.txt
ECGData.mat содержит данные, используемые в этом примере. Текстовый файл Modified_physionet_data.txt требуется политикой копирования PhysioNet и предоставляет атрибуты источника для данных, а также описание этапов предварительной обработки, применяемых к каждой записи ЭКГ.
Расстегнуть молнию ECGData.zip в physionet-ECG_data-main. Загрузите файл данных в рабочую область MATLAB.
unzip(fullfile(tempdir,'physionet_ECG_data-main','ECGData.zip'),... fullfile(tempdir,'physionet_ECG_data-main')) load(fullfile(tempdir,'physionet_ECG_data-main','ECGData.mat'))
ECGData - это структурный массив с двумя полями: Data и Labels. Data поле представляет собой матрицу 162 на 65536, где каждая строка представляет собой запись ЭКГ, дискретизированную при 128 герц. Labels является массивом ячеек 162 на 1 диагностических меток, по одной метке для каждой строки Data. Тремя диагностическими категориями являются: 'ARR', 'CHF', и 'NSR'.
После загрузки данных необходимо сформировать скалограммы сигналов. Скалограммы являются «входными» изображениями для CNN.
Чтобы сохранить скалограммы каждой категории, сначала создайте каталог данных ЭКГ 'data' внутри tempdir. Затем создайте три подкаталога в 'data' по каждой категории ЭКГ. Вспомогательная функция helperCreateECGDirectories делает это для тебя. helperCreateECGDirectories принимает ECGDataимя каталога данных ЭКГ и имя родительского каталога в качестве входных аргументов. Вы можете заменить tempdir с другим каталогом, в котором имеется разрешение на запись. Исходный код для этой вспомогательной функции можно найти в разделе «Вспомогательные функции» в конце этого примера.
parentDir = tempdir;
dataDir = 'data';
helperCreateECGDirectories(ECGData,parentDir,dataDir)После создания папок создайте скалограммы сигналов ЭКГ в виде изображений RGB и запишите их в соответствующую подкаталогу в dataDir. Чтобы создать скалограммы, сначала предварительно вычислите банк фильтров CWT. Предварительное вычисление набора фильтров является предпочтительным способом при получении CWT многих сигналов с использованием одних и тех же параметров. Вспомогательная функция helperCreateRGBfromTF делает это. Исходный код для этой вспомогательной функции находится в разделе «Вспомогательные функции» в конце этого примера. Чтобы быть совместимым с архитектурой SqueezeNet, каждое изображение RGB - множество размера 227 на 227 на 3.
helperCreateRGBfromTF(ECGData,parentDir,dataDir)
Загрузите изображения скалограммы как хранилище данных изображения. imageDatastore функция автоматически помечает изображения на основе имен папок и сохраняет данные в виде ImageDatastore объект. Хранилище данных изображения позволяет хранить большие данные изображения, включая данные, которые не помещаются в память, и эффективно считывать пакеты изображений при обучении CNN.
allImages = imageDatastore(fullfile(tempdir,dataDir),... 'IncludeSubfolders',true,... 'LabelSource','foldernames');
Случайное разделение изображений на две группы, одна для обучения, а другая для проверки. Используйте 80% изображений для обучения, а остальные - для проверки. В целях воспроизводимости для случайного начального числа устанавливается значение по умолчанию.
rng default [imgsTrain,imgsValidation] = splitEachLabel(allImages,0.8,'randomized'); disp(['Number of training images: ',num2str(numel(imgsTrain.Files))]);
Number of training images: 130
disp(['Number of validation images: ',num2str(numel(imgsValidation.Files))]);Number of validation images: 32
SqueeeNet - это предварительно обученный CNN, который может классифицировать изображения на 1000 категорий. Вам нужно переучить SqueeExNet для нашей проблемы классификации ЭКГ. Перед переподготовкой необходимо изменить несколько сетевых уровней и задать различные варианты обучения. После завершения переподготовки вы сохраняете CNN в .mat файл. Исполняемый файл CUDA будет использовать .mat файл.
Укажите пробный индекс эксперимента и каталог результатов. При необходимости создайте каталог.
trial = 1; ResultDir = 'results'; if ~exist(ResultDir,'dir') mkdir(ResultDir) end MatFile = fullfile(ResultDir,sprintf('SqueezeNet_Trial%d.mat',trial));
Загрузить SqeeEcNet. Извлеките график слоев и проверьте последние пять слоев.
sqz = squeezenet; lgraph = layerGraph(sqz); 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
Для переподготовки SqueeExNet для классификации трех классов сигналов ЭКГ замените 'conv10' слой с новым сверточным слоем с числом фильтров, равным числу классов ЭКГ. Замените классификационный слой новым без меток классов.
numClasses = numel(categories(imgsTrain.Labels)); new_conv10_WeightLearnRateFactor = 1; new_conv10_BiasLearnRateFactor = 1; newConvLayer = convolution2dLayer(1,numClasses,... 'Name','new_conv10',... 'WeightLearnRateFactor',new_conv10_WeightLearnRateFactor,... 'BiasLearnRateFactor',new_conv10_BiasLearnRateFactor); lgraph = replaceLayer(lgraph,'conv10',newConvLayer); newClassLayer = classificationLayer('Name','new_classoutput'); lgraph = replaceLayer(lgraph,'ClassificationLayer_predictions',newClassLayer); lgraph.Layers(end-4:end)
ans =
5×1 Layer array with layers:
1 'new_conv10' Convolution 3 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
Создайте набор параметров обучения для использования с SqueeeNet.
OptimSolver = 'sgdm'; MiniBatchSize = 15; MaxEpochs = 20; InitialLearnRate = 1e-4; Momentum = 0.9; ExecutionEnvironment = 'cpu'; options = trainingOptions(OptimSolver,... 'MiniBatchSize',MiniBatchSize,... 'MaxEpochs',MaxEpochs,... 'InitialLearnRate',InitialLearnRate,... 'ValidationData',imgsValidation,... 'ValidationFrequency',10,... 'ExecutionEnvironment',ExecutionEnvironment,... 'Momentum',Momentum);
Сохраните все параметры в структуре. Обученная сеть и структура будут сохранены в .mat файл.
TrialParameter.new_conv10_WeightLearnRateFactor = new_conv10_WeightLearnRateFactor; TrialParameter.new_conv10_BiasLearnRateFactor = new_conv10_BiasLearnRateFactor; TrialParameter.OptimSolver = OptimSolver; TrialParameter.MiniBatchSize = MiniBatchSize; TrialParameter.MaxEpochs = MaxEpochs; TrialParameter.InitialLearnRate = InitialLearnRate; TrialParameter.Momentum = Momentum; TrialParameter.ExecutionEnvironment = ExecutionEnvironment;
Установите для случайного начального значения значение по умолчанию и выполните обучение сети. Сохраните обученную сеть, параметры пробной версии, время выполнения обучения и хранилище данных образа, содержащее изображения проверки. Процесс обучения обычно занимает 1-5 минут на настольном процессоре. Если вы хотите использовать обученный CNN из предыдущего испытания, установите trial к индексу этой пробной версии и LoadModel кому true.
LoadModel = false; if ~LoadModel rng default tic; trainedModel = trainNetwork(imgsTrain,lgraph,options); trainingTime = toc; fprintf('Total training time: %.2e sec\n',trainingTime); save(MatFile,'TrialParameter','trainedModel','trainingTime','imgsValidation'); else disp('Load ML model from the file') load(MatFile,'trainedModel','imgsValidation'); end
Initializing input data normalization. |======================================================================================================================| | Epoch | Iteration | Time Elapsed | Mini-batch | Validation | Mini-batch | Validation | Base Learning | | | | (hh:mm:ss) | Accuracy | Accuracy | Loss | Loss | Rate | |======================================================================================================================| | 1 | 1 | 00:00:02 | 26.67% | 25.00% | 4.1769 | 2.9883 | 1.0000e-04 | | 2 | 10 | 00:00:12 | 73.33% | 59.38% | 0.9877 | 1.1559 | 1.0000e-04 | | 3 | 20 | 00:00:21 | 60.00% | 56.25% | 0.9164 | 0.9182 | 1.0000e-04 | | 4 | 30 | 00:00:31 | 86.67% | 68.75% | 0.6698 | 0.7883 | 1.0000e-04 | | 5 | 40 | 00:00:40 | 66.67% | 68.75% | 0.9053 | 0.7489 | 1.0000e-04 | | 7 | 50 | 00:00:50 | 80.00% | 78.13% | 0.5422 | 0.6781 | 1.0000e-04 | | 8 | 60 | 00:00:59 | 100.00% | 81.25% | 0.4187 | 0.6124 | 1.0000e-04 | | 9 | 70 | 00:01:08 | 93.33% | 84.38% | 0.3561 | 0.5471 | 1.0000e-04 | | 10 | 80 | 00:01:18 | 73.33% | 84.38% | 0.5141 | 0.4765 | 1.0000e-04 | | 12 | 90 | 00:01:27 | 86.67% | 84.38% | 0.4220 | 0.4038 | 1.0000e-04 | | 13 | 100 | 00:01:36 | 93.33% | 90.63% | 0.1923 | 0.3476 | 1.0000e-04 | | 14 | 110 | 00:01:46 | 100.00% | 90.63% | 0.1472 | 0.3125 | 1.0000e-04 | | 15 | 120 | 00:01:55 | 100.00% | 93.75% | 0.0791 | 0.2777 | 1.0000e-04 | | 17 | 130 | 00:02:04 | 86.67% | 93.75% | 0.2486 | 0.2833 | 1.0000e-04 | | 18 | 140 | 00:02:14 | 100.00% | 93.75% | 0.0386 | 0.2288 | 1.0000e-04 | | 19 | 150 | 00:02:23 | 100.00% | 93.75% | 0.0487 | 0.2397 | 1.0000e-04 | | 20 | 160 | 00:02:32 | 100.00% | 93.75% | 0.0224 | 0.2041 | 1.0000e-04 | |======================================================================================================================|
Total training time: 1.61e+02 sec
Сохранение только обученной сети в отдельной .mat файл. Этот файл будет использоваться исполняемым файлом CUDA.
ModelFile = fullfile(ResultDir,sprintf('SqueezeNet_Trial%d.mat',trial)); OutMatFile = fullfile('ecg_model.mat'); data = load(ModelFile,'trainedModel'); net = data.trainedModel; save(OutMatFile,'net');
Используйте обученную сеть для прогнозирования классов для набора проверки.
[YPred, probs] = classify(trainedModel,imgsValidation); accuracy = mean(YPred==imgsValidation.Labels)
accuracy = 0.9375
Обобщите производительность обученной сети в наборе проверки с помощью таблицы путаницы. Отображение точности и отзыва для каждого класса с помощью сводок столбцов и строк. Сохраните фигуру. В таблице внизу таблицы путаницы показаны значения точности. В таблице справа от таблицы путаницы показаны значения отзыва.
figure confusionMat = confusionmat(imgsValidation.Labels,YPred); confusionchart(imgsValidation.Labels,YPred, ... 'Title',sprintf('Confusion Matrix on Validation (overall accuracy: %.4f)',accuracy),... 'ColumnSummary','column-normalized','RowSummary','row-normalized');

AccFigFile = fullfile(ResultDir,sprintf('SqueezeNet_ValidationAccuracy_Trial%d.fig',trial));
saveas(gcf,AccFigFile);Отображение размера обучаемой сети.
info = whos('trainedModel'); ModelMemSize = info.bytes/1024; fprintf('Trained network size: %g kB\n',ModelMemSize)
Trained network size: 2981.55 kB
Определите среднее время, необходимое сети для классификации изображения.
NumTestForPredTime = 20;
TrialParameter.NumTestForPredTime = NumTestForPredTime;
fprintf('Test prediction time (number of tests: %d)... ',NumTestForPredTime)Test prediction time (number of tests: 20)...
imageSize = trainedModel.Layers(1).InputSize; PredTime = zeros(NumTestForPredTime,1); for i = 1:NumTestForPredTime x = randn(imageSize); tic; [YPred, probs] = classify(trainedModel,x,'ExecutionEnvironment',ExecutionEnvironment); PredTime(i) = toc; end AvgPredTimePerImage = mean(PredTime); fprintf('Average prediction time (execution environment: %s): %.2e sec \n',... ExecutionEnvironment,AvgPredTimePerImage);
Average prediction time (execution environment: cpu): 2.94e-02 sec
Сохраните результаты.
if ~LoadModel save(MatFile,'accuracy','confusionMat','PredTime','ModelMemSize', ... 'AvgPredTimePerImage','-append') end
Скалограмма сигнала является входным «изображением» для глубокого CNN. Создайте функцию, cwt_ecg_jetson_ex, которая вычисляет скалограмму входного сигнала и возвращает изображение с заданными пользователем размерами. Изображение использует jet(128) colormap. %#codegen директива в функции указывает, что функция предназначена для генерации кода. При использовании coder.gpu.kernelfun pragma, генерация кода пытается отобразить вычисления в cwt_ecg_jetson_ex функции графическому процессору.
type cwt_ecg_jetson_ex.mfunction im = cwt_ecg_jetson_ex(TimeSeriesSignal, 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.kernelfun();
%% Create Scalogram
cfs = cwt(TimeSeriesSignal, 'morse', 1, 'VoicesPerOctave', 12);
cfs = abs(cfs);
%% Image generation
cmapj128 = coder.load('cmapj128');
imx = ind2rgb_custom_ecg_jetson_ex(round(255*rescale(cfs))+1,cmapj128.cmapj128);
% resize to proper size and convert to uint8 data type
im = im2uint8(imresize(imx, ImgSize));
end
Создайте функцию точки входа, model_predict_ecg.m, для генерации кода. Функция принимает сигнал ЭКГ в качестве входного сигнала и вызывает cwt_ecg_jetson_ex для создания изображения скалограммы. model_predict_ecg использует сеть, содержащуюся в ecg_model.mat файл для классификации сигнала ЭКГ.
type model_predict_ecg.mfunction PredClassProb = model_predict_ecg(TimeSeriesSignal) %#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();
% parameters
ModFile = 'ecg_model.mat'; % file that saves neural network model
ImgSize = [227 227]; % input image size for the ML model
% sanity check signal is a row vector of correct length
assert(isequal(size(TimeSeriesSignal), [1 65536]))
%% cwt transformation for the signal
im = cwt_ecg_jetson_ex(TimeSeriesSignal, ImgSize);
%% model prediction
persistent model;
if isempty(model)
model = coder.loadDeepLearningNetwork(ModFile, 'mynet');
end
PredClassProb = predict(model, im);
end
Чтобы создать исполняемый файл CUDA, который можно развернуть на целевом объекте NVIDIA, создайте пользовательский основной файл (main_ecg_jetson_ex.cu) и файл заголовка (main_ecg_jetson_ex.h). Можно создать пример основного файла и использовать его в качестве шаблона для перезаписи нового основного файла и файла заголовка. Дополнительные сведения см. в разделе GenerateExampleMain имущество coder.CodeConfig. Основной файл вызывает код, созданный для функции точки входа MATLAB. Основной файл сначала считывает сигнал ЭКГ из текстового файла, передает данные в функцию точки входа и записывает результаты прогнозирования в текстовый файл (predClassProb.txt). Чтобы максимизировать эффективность вычислений на GPU, исполняемый файл обрабатывает данные с одной точностью.
type main_ecg_jetson_ex.cu//
// File: main_ecg_jetson_ex.cu
//
// This file is only intended to support wavelet deep learning examples.
// It may change or be removed in a future release.
//***********************************************************************
// Include Files
#include "rt_nonfinite.h"
#include "model_predict_ecg.h"
#include "main_ecg_jetson_ex.h"
#include "model_predict_ecg_terminate.h"
#include "model_predict_ecg_initialize.h"
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
// Function Definitions
/* Read data from a file*/
int readData_real32_T(const char * const file_in, real32_T data[65536])
{
FILE* fp1 = fopen(file_in, "r");
if (fp1 == 0)
{
printf("ERROR: Unable to read data from %s\n", file_in);
exit(0);
}
for(int i=0; i<65536; i++)
{
fscanf(fp1, "%f", &data[i]);
}
fclose(fp1);
return 0;
}
/* Write data to a file*/
int writeData_real32_T(const char * const file_out, real32_T data[3])
{
FILE* fp1 = fopen(file_out, "w");
if (fp1 == 0)
{
printf("ERROR: Unable to write data to %s\n", file_out);
exit(0);
}
for(int i=0; i<3; i++)
{
fprintf(fp1, "%f\n", data[i]);
}
fclose(fp1);
return 0;
}
// model predict function
static void main_model_predict_ecg(const char * const file_in, const char * const file_out)
{
real32_T PredClassProb[3];
// real_T b[65536];
real32_T b[65536];
// readData_real_T(file_in, b);
readData_real32_T(file_in, b);
model_predict_ecg(b, PredClassProb);
writeData_real32_T(file_out, PredClassProb);
}
// main function
int32_T main(int32_T argc, const char * const argv[])
{
const char * const file_out = "predClassProb.txt";
// Initialize the application.
model_predict_ecg_initialize();
// Run prediction function
main_model_predict_ecg(argv[1], file_out); // argv[1] = file_in
// Terminate the application.
model_predict_ecg_terminate();
return 0;
}
type main_ecg_jetson_ex.h// // File: main_ecg_jetson_ex.h // // This file is only intended to support wavelet deep learning examples. // It may change or be removed in a future release. // //*********************************************************************** #ifndef MAIN_H #define MAIN_H // Include Files #include <stddef.h> #include <stdlib.h> #include "rtwtypes.h" #include "model_predict_ecg_types.h" // Function Declarations extern int32_T main(int32_T argc, const char * const argv[]); #endif // // File trailer for main_ecg_jetson_ex.h // // [EOF] //
Чтобы создать исполняемый файл, который можно развернуть на целевом устройстве, установите CodeGenMode равно 1. Если требуется создать исполняемый файл, который выполняется локально и удаленно подключается к целевому устройству, установите CodeGenMode равно 2.
main функция считывает данные из текстового файла, указанного signalFile и записывает результаты классификации в resultFile. Набор ExampleIndex для выбора репрезентативного сигнала ЭКГ. Этот сигнал используется для проверки исполняемого файла на соответствие classify функция. Jetson_BuildDir указывает каталог для выполнения удаленного процесса построения на конечном объекте. Если указанный каталог построения не существует на конечном объекте, то программное обеспечение создает каталог с заданным именем.
CodeGenMode =1; signalFile = 'signalData.txt'; resultFile = 'predClassProb.txt'; % consistent with "main_ecg_jetson_ex.cu" Jetson_BuildDir = '~/projectECG'; ExampleIndex = 1; % 1,4: type ARR; 2,5: type CHF; 3,6: type NSR Function_to_Gen = 'model_predict_ecg'; ModFile = 'ecg_model.mat'; % file that saves neural network model; consistent with "main_ecg_jetson_ex.cu" ImgSize = [227 227]; % input image size for the ML model switch ExampleIndex case 1 % ARR 7 SampleSignalIdx = 7; case 2 % CHF 97 SampleSignalIdx = 97; case 3 % NSR 132 SampleSignalIdx = 132; case 4 % ARR 31 SampleSignalIdx = 31; case 5 % CHF 101 SampleSignalIdx = 101; case 6 % NSR 131 SampleSignalIdx = 131; end signal_data = single(ECGData.Data(SampleSignalIdx,:)); ECGtype = ECGData.Labels{SampleSignalIdx};
Для взаимодействия с аппаратным обеспечением 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 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 и убедитесь, что компиляторы и библиотеки, необходимые для выполнения этого примера, правильно настроены на оборудовании.
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
Создайте объект конфигурации кода графического процессора, необходимый для компиляции. Используйте coder.hardware чтобы создать объект конфигурации для платформы Jetson и назначить его Hardware свойство объекта конфигурации кода cfg. Использовать 'NVIDIA Jetson' для TX1 Jetson или TX2 плат. Пользовательский основной файл - это оболочка, вызывающая функцию точки входа в сгенерированном коде. Пользовательский файл необходим для развернутого исполняемого файла.
Используйте coder.DeepLearningConfig для создания функции CuDNN глубокий объект конфигурации обучения и назначить его DeepLearningConfig свойства объекта конфигурации кода графического процессора. Генератор кода использует преимущества библиотеки глубоких нейронных сетей (cuDNN) NVIDIA ® CUDA ® для графических процессоров NVIDIA. cuDNN - GPU-ускоренная библиотека примитивов для глубоких нейронных сетей.
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 = fullfile('main_ecg_jetson_ex.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
Для создания кода CUDA используйте codegen и передать конфигурацию кода GPU вместе с размером и типом входа для model_predict_ecg функция точки входа. После завершения создания кода на хосте созданные файлы копируются и создаются на целевом компьютере.
codegen('-config ',cfg,Function_to_Gen,'-args',{signal_data},'-report');
Code generation successful: View report
Если вы скомпилировали исполняемый файл для развертывания в целевой объект, запишите пример сигнала ЭКГ в текстовый файл. Используйте putFile() функция аппаратного объекта для размещения текстового файла на целевом объекте. workspaceDir содержит путь к codegen папка на целевом объекте.
if CodeGenMode == 1 fid = fopen(signalFile,'w'); for i = 1:length(signal_data) fprintf(fid,'%f\n',signal_data(i)); end fclose(fid); hwobj.putFile(signalFile,hwobj.workspaceDir); end
Запустите исполняемый файл.
При запуске развернутого исполняемого файла удалите предыдущий файл результатов, если он существует. Используйте 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) 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 ta = tic; eval(sprintf('PredClassProb = %s_pil(signal_data);',Function_to_Gen)); PredTime = toc(ta); eval(sprintf('clear %s_pil;',Function_to_Gen)); % terminate PIL execution end
### Launching the executable on the target... Executable launched successfully with process ID 5672. Displaying the simple runtime log for the executable... Note: For the complete log, run the following command in the MATLAB command window: system(hwobj,'cat /home/ubuntu/projectECG/MATLAB_ws/R2021a/C/Users/pkostele/OneDrive_-_MathWorks/Documents/MATLAB/Examples/deeplearning_shared-ex54874305/model_predict_ecg.log')
Fetch time = 9.743e+00 sec
Используйте classify функция для прогнозирования меток класса для примерного сигнала.
ModData = load(ModFile,'net');
im = cwt_ecg_jetson_ex(signal_data,ImgSize);
[ModPred, ModPredProb] = classify(ModData.net,im);
PredCat = categories(ModPred)';Сравните результаты.
PredTableJetson = array2table(PredClassProb(:)','VariableNames',matlab.lang.makeValidName(PredCat)); fprintf('tPred = %.3e sec\nExample ECG Type: %s\n',PredTime,ECGtype)
tPred = 1.288e+01 sec Example ECG Type: ARR
disp(PredTableJetson)
ARR CHF NSR
_______ ________ ________
0.99872 0.001131 0.000153
PredTableMATLAB = array2table(ModPredProb(:)','VariableNames',matlab.lang.makeValidName(PredCat));
disp(PredTableMATLAB) ARR CHF NSR
_______ _________ __________
0.99872 0.0011298 0.00015316
Закройте аппаратное соединение.
clear hwobjВ этом примере показано, как создать и развернуть исполняемый файл CUDA, который использует CNN для классификации сигналов ECG. Также можно создать исполняемый файл, выполняемый локально и подключенный к удаленному целевому объекту. В этом примере представлен полный рабочий процесс. После загрузки данных CWT используется для извлечения признаков из сигналов ЭКГ. Затем SqueeExNet перестраивается для классификации сигналов на основе их скалограмм. На целевом устройстве NVIDIA создаются и компилируются две определяемые пользователем функции. Результаты исполняемого файла сравниваются с MATLAB.
Баим, Д. С., В. С. Колуччи, Э. С. Монрад, Х. С. Смит, Р. Ф. Райт, А. Лануэ, Д. Ф. Готье, Б. Дж. Рансил, В. Гроссман и Э. Браунвальд. «Выживаемость пациентов с тяжелой застойной сердечной недостаточностью, получавших пероральный милринон». Журнал Американского колледжа кардиологов. Том 7, номер 3, 1986, стр. 661-670.
Гольдбергер А. Л., Л. А. Н. Амарал, Л. Гласс, Ж. М. Хаусдорф, П. Ч. Иванов, Р. Г. Марк, Ж. Е. Миетус, Г. Б. Муди, К. -К. Пэн и Х. Э. Стэнли. «PhysioBank, PhysioToolkit и PhysioNet: компоненты нового исследовательского ресурса для сложных физиологических сигналов». Циркуляция. Том 101, номер 23: e215-e220. [Электронные страницы тиража ;http://circ.ahajournals.org/content/101/23/e215.full]; 2000 (13 июня). дои: 10.1161/01.CIR.101.23.e215.
Муди, Г. Б. и Р. Г. Марк. «Влияние базы данных аритмии MIT-BIH». IEEE Engineering in Medicine and Biology Magazine. Том 20. Номер 3, май-июнь 2001 года, стр. 45-50. (PMID: 11446209)
helperCreateECGDirectories
function helperCreateECGDirectories(ECGData,parentFolder,dataFolder) % This function is only intended to support wavelet deep learning examples. % It may change or be removed in a future release. rootFolder = parentFolder; localFolder = dataFolder; mkdir(fullfile(rootFolder,localFolder)) folderLabels = unique(ECGData.Labels); for i = 1:numel(folderLabels) mkdir(fullfile(rootFolder,localFolder,char(folderLabels(i)))); end end
helperPlotReps
function helperPlotReps(ECGData) % This function is only intended to support wavelet deep learning examples. % It may change or be removed in a future release. folderLabels = unique(ECGData.Labels); for k=1:3 ecgType = folderLabels{k}; ind = find(ismember(ECGData.Labels,ecgType)); subplot(3,1,k) plot(ECGData.Data(ind(1),1:1000)); grid on title(ecgType) end end
helperCreateRGBfromTF
function helperCreateRGBfromTF(ECGData,parentFolder, childFolder) % This function is only intended to support wavelet deep learning examples. % It may change or be removed in a future release. imageRoot = fullfile(parentFolder,childFolder); data = ECGData.Data; labels = ECGData.Labels; [~,signalLength] = size(data); fb = cwtfilterbank('SignalLength',signalLength,'VoicesPerOctave',12); r = size(data,1); for ii = 1:r cfs = abs(fb.wt(data(ii,:))); im = ind2rgb(im2uint8(rescale(cfs)),jet(128)); imgLoc = fullfile(imageRoot,char(labels(ii))); imFileName = strcat(char(labels(ii)),'_',num2str(ii),'.jpg'); imwrite(imresize(im,[227 227]),fullfile(imgLoc,imFileName)); end end