exponenta event banner

Развертывание классификатора сигналов на NVIDIA Jetson с использованием вейвлет-анализа и глубокого обучения

В этом примере показано, как генерировать и развертывать исполняемый файл 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

SqueezeNet

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.m
function 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.m
function 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). Основной файл вызывает код, созданный для функции точки входа 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};

Создание кода 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
 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

Создание кода графического процессора - компиляция

Создайте объект конфигурации кода графического процессора, необходимый для компиляции. Используйте 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.

Ссылки

  1. Баим, Д. С., В. С. Колуччи, Э. С. Монрад, Х. С. Смит, Р. Ф. Райт, А. Лануэ, Д. Ф. Готье, Б. Дж. Рансил, В. Гроссман и Э. Браунвальд. «Выживаемость пациентов с тяжелой застойной сердечной недостаточностью, получавших пероральный милринон». Журнал Американского колледжа кардиологов. Том 7, номер 3, 1986, стр. 661-670.

  2. Гольдбергер А. Л., Л. А. Н. Амарал, Л. Гласс, Ж. М. Хаусдорф, П. Ч. Иванов, Р. Г. Марк, Ж. Е. Миетус, Г. Б. Муди, К. -К. Пэн и Х. Э. Стэнли. «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.

  3. Муди, Г. Б. и Р. Г. Марк. «Влияние базы данных аритмии 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

См. также

| | (кодер графического процессора)

Связанные темы