Разверните классификатор сигнала на NVIDIA Джетсон Используя анализ вейвлета и глубокое обучение

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

SqueezeNet является глубоким CNN, первоначально спроектированным, чтобы классифицировать изображения на 1 000 категорий. Мы снова используем сетевую архитектуру CNN, чтобы классифицировать сигналы ECG на основе их scalograms. scalogram является абсолютным значением CWT сигнала. После учебного SqueezeNet, чтобы классифицировать сигналы ECG, вы создаете исполняемый файл CUDA, который генерирует scalogram сигнала ECG и затем использует CNN, чтобы классифицировать сигнал. Исполняемый файл и CNN оба развертываются на оборудовании NVIDIA.

Этот пример использует те же данные, как используется в, Классифицируют Временные ряды Используя Анализ Вейвлета и Глубокое обучение (Wavelet Toolbox). В том примере передача обучения с GoogLeNet и SqueezeNet используется, чтобы классифицировать формы волны ECG в одну из трех категорий. Описание данных и как получить его, повторяется здесь для удобства.

Описание данных о ECG и загрузка

Данные о ECG получены из трех групп людей: люди с сердечной аритмией (ARR), люди с застойной сердечной недостаточностью (CHF) и люди с нормальными ритмами пазухи (NSR). Всего от трех Физиосетевых баз данных существует 162 записи ECG: База данных Аритмии MIT-BIH [2] [3], MIT-BIH Нормальная База данных Ритма Пазухи [3] и База данных Застойной сердечной недостаточности BIDMC [1] [3]. А именно, 96 записей от людей с аритмией, 30 записей от людей с застойной сердечной недостаточностью и 36 записей от людей с нормальными ритмами пазухи. Цель состоит в том, чтобы обучить модель различать ARR, швейцарский франк и 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 политики и обеспечивает исходные приписывания для данных, а также описание шагов предварительной обработки применилось к каждой записи ECG.

Разархивируйте 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 матрица, где каждая строка является записью ECG, произведенной на уровне 128 герц. Labels 162 1 массив ячеек диагностических меток, одной метки для каждой строки Data. Три диагностических категории: 'ARR', 'CHF', и 'NSR'.

Извлечение признаков

После загрузки данных необходимо сгенерировать scalograms сигналов. scalograms являются "входными" изображениями к CNN.

Чтобы сохранить scalograms каждой категории, сначала создайте директорию 'data' данных о ECG в tempdir. Затем создайте три подкаталога в 'data' названный в честь каждой категории ECG. Функция помощника helperCreateECGDirectories делает это для вас. helperCreateECGDirectories принимает ECGData, имя директории данных о ECG и имя родительского каталога как входные параметры. Можно заменить tempdir с другой директорией, где у вас есть разрешение записи. Можно найти исходный код для этой функции помощника в разделе Supporting Functions в конце этого примера.

parentDir = tempdir;
dataDir = 'data';
helperCreateECGDirectories(ECGData,parentDir,dataDir)

После создания папок создайте scalograms сигналов ECG, когда RGB отображает, и запишите им в соответствующий подкаталог в dataDir. Чтобы создать scalograms, сначала предварительно вычислите набор фильтров CWT. Предварительное вычисление набора фильтров является предпочтительным методом при получении CWT многих сигналов с помощью тех же параметров. Функция помощника helperCreateRGBfromTF делает this.The исходный код для этой функции помощника, находится в разделе Supporting Functions в конце этого примера. Чтобы быть совместимым с архитектурой SqueezeNet, каждое изображение RGB является массивом размера 227 227 3.

helperCreateRGBfromTF(ECGData,parentDir,dataDir)

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

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

allImages = imageDatastore(fullfile(tempdir,dataDir),...
    'IncludeSubfolders',true,...
    'LabelSource','foldernames');

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

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

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

Задайте испытательный индекс эксперимента и директорию результатов. При необходимости создайте директорию.

trial = 1;
ResultDir = 'results';
if ~exist(ResultDir,'dir')
    mkdir(ResultDir)
end
MatFile = fullfile(ResultDir,sprintf('SqueezeNet_Trial%d.mat',trial));

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

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

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

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

Создайте набор опций обучения, чтобы использовать с SqueezeNet.

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;

Установите случайный seed на значение по умолчанию и обучите сеть. Сохраните обучившие сеть, испытательные параметры, учебное время выполнения, и отобразите datastore, содержащий изображения валидации. Учебный процесс обычно занимает 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

Генерация кода графического процессора — задает функции

scalogram сигнала является входом "изображение" к глубокому CNN. Создайте функцию, cwt_ecg_jetson_ex, это вычисляет scalogram входного сигнала и возвращает изображение в пользовательских заданных измерениях. Изображение использует jet(128) палитра. %#codegen директива в функции указывает, что функция предназначается для генерации кода. При использовании coder.gpu.kernelfun прагма, генерация кода пытается сопоставить расчеты в 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, для генерации кода. Функция берет сигнал ECG, как введено и вызывает cwt_ecg_jetson_ex функция, чтобы создать изображение scalogram. model_predict_ecg функционируйте использует сеть, содержавшуюся в ecg_model.mat файл, чтобы классифицировать сигнал ECG.

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 Coder). Основной файл вызывает код, сгенерированный для функции точки входа MATLAB. Основной файл сначала читает сигнал ECG из текстового файла, передает данные функции точки входа и пишет результаты предсказания в текстовый файл (predClassProb.txt). Чтобы максимизировать КПД расчета на графическом процессоре, исполняемый файл обрабатывает данные с одинарной точностью.

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 выбрать представительный сигнал ECG. Вы будете использовать этот сигнал протестировать исполняемый файл против 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 = один (ECGData.Data (SampleSignalIdx, :));
ECGtype = ECGData.Labels {SampleSignalIdx};

Генерация кода графического процессора — связывает с оборудованием

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

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

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 функция, чтобы создать настройку возражает для платформы Джетсона и присвоить ее Hardware свойство объекта cfg настройки кода. Используйте 'NVIDIA Jetson' для Jetson TX1 или плат TX2. Пользовательский основной файл является оберткой, которая вызывает функцию точки входа в сгенерированном коде. Пользовательский файл требуется для развернутого исполняемого файла.

Используйте coder.DeepLearningConfig (GPU Coder) функция, чтобы создать CuDNN объект настройки глубокого обучения и присвоение это к DeepLearningConfig свойство объекта настройки графического процессора кода. Генератор кода использует в своих интересах библиотеку глубокой нейронной сети NVIDIA® CUDA® (cuDNN) для 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 = 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 функционируйте и передайте настройку графического процессора кода наряду с размером и типом входа для model_predict_ecg функция точки входа. После того, как генерация кода на хосте завершена, сгенерированные файлы скопированы и основаны на цели.

codegen('-config ',cfg,Function_to_Gen,'-args',{signal_data},'-report');
Code generation successful: View report

Генерация кода графического процессора — выполняется

Если вы скомпилировали исполняемый файл, который будет развернут на цели, запишите сигнал ECG в качестве примера в текстовый файл. Используйте 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 используется, чтобы извлечь функции из сигналов ECG. Затем SqueezeNet переобучен, чтобы классифицировать сигналы на основе их scalograms. Две пользовательских функции созданы и скомпилированы на целевом устройстве NVIDIA. Результаты исполняемого файла по сравнению с MATLAB.

Ссылки

  1. Baim, D. S. В. С. Колуччи, Э. С. Монрэд, Х. С. Смит, Р. Ф. Райт, А. Лэноу, Д. Ф. Готье, Б. Дж. Рэнсил, В. Гроссман и Э. Бронвалд. "Выживание пациентов с тяжелой застойной сердечной недостаточностью отнеслось с устным milrinone". Журнал американского Колледжа Кардиологии. Издание 7, Номер 3, 1986, стр 661–670.

  2. Голдбергер А. Л., Л. А. Н. Амарал, L. Стекло, Дж. М. Гаусдорф, P. Ch. Иванов, Р. Г. Марк, Дж. Э. Митус, Г. Б. Муди, C.-K. Пенг и Х. Э. Стэнли. "PhysioBank, PhysioToolkit и PhysioNet: Компоненты Нового Ресурса Исследования для Комплексных Физиологических Сигналов". Циркуляция. Издание 101, Номер 23: e215–e220. [Циркуляция Электронные Страницы; http://circ.ahajournals.org/content/101/23/e215.full]; 2000 (13 июня). doi: 10.1161/01. CIR.101.23.e215.

  3. Капризный, G. B. и Р. Г. Марк. "Удар Базы данных Аритмии MIT-BIH". Разработка IEEE в Журнале Медицины и Биологии. Издание 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

Смотрите также

(Wavelet Toolbox) | (GPU Coder) | (Wavelet Toolbox)

Похожие темы