Классификация сигналов ECG с помощью сети DAG, развернутой в FPGA

Этот пример показывает, как классифицировать сигналы электрокардиограммы (ЭКГ) человека путем развертывания обученной направленной сети ациклического графика (ДАГ).

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

GoogLeNet и SqueezeNet - глубокие CNN, изначально разработанные для классификации изображений в 1000 категориях. Мы повторно используем сетевую архитектуру CNN, чтобы классифицировать сигналы ЭКГ на основе изображений из CWT данных временных рядов. Данные, используемые в этом примере, являются общедоступными от PhysioNet.

Описание данных

В этом примере вы используете данные ЭКГ, полученные от трех групп людей: лиц с сердечной аритмией (ARR), лиц с застойным сердечным отказом (CHF) и лиц с нормальными синусовыми ритмами (NSR). Всего вы используете 162 записи ЭКГ из трех баз данных PhysioNet: базы данных аритмии MIT-BIH [3] [7], базы данных нормального синусового ритма MIT-BIH [3] и базы данных застойной сердечной недостаточности BIDMC [1] Более конкретно, 96 записей от лиц с аритмией, 30 записей от лиц с застойным сердечным отказом и 36 записей от лиц с нормальными синусовыми ритмами. Цель состоит в том, чтобы обучить классификатор для различения ARR, CHF и NSR.

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

Первый шаг - загрузка данных из репозитория GitHub. Чтобы загрузить данные с сайта, нажмите Code и выберите Download ZIP. Сохраните файл physionet_ECG_data-main.zip в папке, в которой у вас есть разрешение на запись. Инструкции для этого примера предполагают, что вы загрузили файл во временную директорию tempdir, в MATLAB. Измените последующие инструкции для распаковки и загрузки данных, если вы решите загрузить данные в папку, отличную от tempdir. Если вы знакомы с Git, можно скачать последнюю версию инструментов (git) и получить данные из системной командной строки с помощью git clone https://github.com/mathworks/physionet_ECG_data/.

После загрузки данных с GitHub разархивируйте файл во временной директории.

unzip(fullfile(tempdir,'physionet_ECG_data-main.zip'),tempdir)

Unzipping создает папку physionet-ECG_data-main во временной директории. Эта папка содержит текстовый файл README.md и ECGData.zip. The 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. The Data поле представляет собой 162 на 65536 матрицу, где каждая строка является дискретизацией записи ЭКГ в 128 герц. Labels - массив ячеек 162 на 1 с диагностическими метками, по одному для каждой строки Data. Три диагностические категории: 'ARR', 'CHF', и 'NSR'.

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

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

Постройте график представителя каждой категории ЭКГ. Функция помощника helperPlotReps делает это. helperPlotReps принимает ECGData как вход. Исходный код для этой вспомогательной функции можно найти в разделе Вспомогательные функции в конце этого примера.

helperPlotReps(ECGData)

Создайте представления частоты и времени

После создания папок создайте частотно-временные представления сигналов ЭКГ. Эти представления называются скалограммами. Скалограмма является абсолютным значением коэффициентов CWT сигнала.

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

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

Fs = 128;
fb = cwtfilterbank('SignalLength',1000,...
    'SamplingFrequency',Fs,...
    'VoicesPerOctave',12);
sig = ECGData.Data(1,1:1000);
[cfs,frq] = wt(fb,sig);
t = (0:999)/Fs;figure;pcolor(t,frq,abs(cfs))
set(gca,'yscale','log');shading interp;axis tight;
title('Scalogram');xlabel('Time (s)');ylabel('Frequency (Hz)')

Используйте функцию helper helperCreateRGBfromTF чтобы создать скалограммы в виде изображений RGB и записать их в соответствующий подкаталог в dataDir. Исходный код для этой вспомогательной функции находится в разделе Вспомогательные функции в конце этого примера. Чтобы быть совместимым с архитектурой GoogLeNet, каждое изображение RGB - массив размера 224 на 224 на 3.

helperCreateRGBfromTF(ECGData,parentDir,dataDir)

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

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

allImages = imageDatastore(fullfile(parentDir,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

SqueezeNet - глубокий CNN, архитектура которого поддерживает изображения размера 227 227 3. Несмотря на то, что размеры изображений различны для GoogLeNet, вы не должны генерировать новые изображения RGB в размерностях SqueezeNet. Можно использовать исходные изображения RGB.

Груз

Загрузка пользовательской нейронной сети SqueezeNet.

sqz = squeezenet;

Извлеките график слоев из сети. Подтвердите, что SqueezeNet имеет меньше слоев, чем GoogLeNet. Также подтвердите, что SqueezeNet сконфигурирован для изображений размера 227 227 3

lgraphSqz = layerGraph(sqz);
disp(['Number of Layers: ',num2str(numel(lgraphSqz.Layers))])
Number of Layers: 68
disp(lgraphSqz.Layers(1).InputSize)
   227   227     3

Изменение параметров сети SqueezeNet

Чтобы переобучить SqueezeNet для классификации новых изображений, внесите изменения, аналогичные тем, которые были сделаны для GoogLeNet.

Просмотрите последние шесть слои сети.

lgraphSqz.Layers(end-5:end)
ans = 
  6×1 Layer array with layers:

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

Замените 'drop9' слой, последний слой отсева в сети, с слоем отсева вероятности 0,6.

tmpLayer = lgraphSqz.Layers(end-5);
newDropoutLayer = dropoutLayer(0.6,'Name','new_dropout');
lgraphSqz = replaceLayer(lgraphSqz,tmpLayer.Name,newDropoutLayer);

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

numClasses = numel(categories(imgsTrain.Labels));
tmpLayer = lgraphSqz.Layers(end-4);
newLearnableLayer = convolution2dLayer(1,numClasses, ...
        'Name','new_conv', ...
        'WeightLearnRateFactor',10, ...
        'BiasLearnRateFactor',10);
lgraphSqz = replaceLayer(lgraphSqz,tmpLayer.Name,newLearnableLayer);

Замените слой классификации новым слоем без меток классов.

tmpLayer = lgraphSqz.Layers(end);
newClassLayer = classificationLayer('Name','new_classoutput');
lgraphSqz = replaceLayer(lgraphSqz,tmpLayer.Name,newClassLayer);

Осмотрите последние шесть слоев сети. Подтвердите, что отсева, сверточные и выходные слои были изменены.

lgraphSqz.Layers(63:68)
ans = 
  6×1 Layer array with layers:

     1   'new_dropout'       Dropout                  60% dropout
     2   'new_conv'          Convolution              3 1×1 convolutions with stride [1  1] and padding [0  0  0  0]
     3   'relu_conv10'       ReLU                     ReLU
     4   'pool10'            Global Average Pooling   Global average pooling
     5   'prob'              Softmax                  softmax
     6   'new_classoutput'   Classification Output    crossentropyex

Подготовка данных RGB для SqueezeNet

Изображения RGB имеют размерности, соответствующие архитектуре GoogLeNet. Создайте хранилища данных дополненных изображений, которые автоматически изменяют размер существующих изображений RGB для архитектуры SqueezeNet. Для получения дополнительной информации смотрите augmentedImageDatastore.

augimgsTrain = augmentedImageDatastore([227 227],imgsTrain);
augimgsValidation = augmentedImageDatastore([227 227],imgsValidation);

Установите опции обучения и обучите SqueezeNet

Создайте новый набор опций обучения для использования с SqueezeNet. Установите значение по умолчанию для случайного начального числа и обучите сеть. Процесс обучения обычно занимает 1-5 минут на настольном центральном процессоре.

ilr = 3e-4;
miniBatchSize = 10;
maxEpochs = 15;
valFreq = floor(numel(augimgsTrain.Files)/miniBatchSize);
opts = trainingOptions('sgdm',...
    'MiniBatchSize',miniBatchSize,...
    'MaxEpochs',maxEpochs,...
    'InitialLearnRate',ilr,...
    'ValidationData',augimgsValidation,...
    'ValidationFrequency',valFreq,...
    'Verbose',1,...
    'ExecutionEnvironment','cpu',...
    'Plots','training-progress');

rng default
trainedSN = trainNetwork(augimgsTrain,lgraphSqz,opts);
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:06 |       20.00% |       53.12% |       4.2000 |       1.2709 |          0.0003 |
|       1 |          13 |       00:00:16 |       60.00% |       62.50% |       0.9170 |       0.9294 |          0.0003 |
|       2 |          26 |       00:00:25 |       60.00% |       59.38% |       0.7670 |       0.8397 |          0.0003 |
|       3 |          39 |       00:00:35 |       60.00% |       62.50% |       0.7033 |       0.7413 |          0.0003 |
|       4 |          50 |       00:00:42 |       70.00% |              |       0.7629 |              |          0.0003 |
|       4 |          52 |       00:00:44 |       70.00% |       81.25% |       0.5941 |       0.6664 |          0.0003 |
|       5 |          65 |       00:00:53 |       90.00% |       84.38% |       0.4883 |       0.5273 |          0.0003 |
|       6 |          78 |       00:01:02 |       90.00% |       84.38% |       0.3627 |       0.3791 |          0.0003 |
|       7 |          91 |       00:01:11 |       90.00% |       87.50% |       0.2145 |       0.3710 |          0.0003 |
|       8 |         100 |       00:01:17 |       90.00% |              |       0.3157 |              |          0.0003 |
|       8 |         104 |       00:01:20 |       80.00% |       84.38% |       0.2166 |       0.3212 |          0.0003 |
|       9 |         117 |       00:01:29 |      100.00% |       90.62% |       0.0720 |       0.2111 |          0.0003 |
|      10 |         130 |       00:01:38 |       90.00% |       90.62% |       0.2510 |       0.1933 |          0.0003 |
|      11 |         143 |       00:01:47 |      100.00% |       93.75% |       0.0443 |       0.1763 |          0.0003 |
|      12 |         150 |       00:01:51 |      100.00% |              |       0.1377 |              |          0.0003 |
|      12 |         156 |       00:01:56 |       90.00% |       90.62% |       0.1190 |       0.3878 |          0.0003 |
|      13 |         169 |       00:02:04 |       80.00% |       87.50% |       0.4859 |       0.4950 |          0.0003 |
|      14 |         182 |       00:02:13 |      100.00% |       87.50% |       0.0395 |       0.3245 |          0.0003 |
|      15 |         195 |       00:02:22 |      100.00% |       84.38% |       0.0399 |       0.2639 |          0.0003 |
|======================================================================================================================|

Осмотрите последний слой сети. Подтвердите, что слой Classification Output включает три класса.

trainedSN.Layers(end)
ans = 
  ClassificationOutputLayer with properties:

            Name: 'new_classoutput'
         Classes: [ARR    CHF    NSR]
    ClassWeights: 'none'
      OutputSize: 3

   Hyperparameters
    LossFunction: 'crossentropyex'

Вычислите точность SqueezeNet

Оцените сеть с помощью данных валидации.

[YPred,probs] = classify(trainedSN,augimgsValidation);
accuracy = mean(YPred==imgsValidation.Labels);
disp(['SqueezeNet Accuracy: ',num2str(100*accuracy),'%'])
SqueezeNet Accuracy: 84.375%

Создайте целевой объект

Используйте dlhdl.Target Класс создать целевой объект с пользовательским именем для целевого устройства и интерфейсом для подключения целевого устройства к хосту-компьютеру. Опции интерфейса JTAG и Ethernet. Чтобы использовать JTAG, Установите Xilinx™ Vivado™ Design Suite 2019.2. Чтобы задать траекторию инструмента Xilinx Vivado, введите:

% hdlsetuptoolpath('ToolName', 'Xilinx Vivado', 'ToolPath', 'C:\Xilinx\Vivado\2019.2\bin\vivado.bat');

hTarget = dlhdl.Target('Xilinx','Interface','Ethernet');

Создайте объект рабочий процесс

Используйте dlhdl.Workflow класс, чтобы создать объект. Когда вы создаете объект, задайте сеть и имя битового потока. Укажите сохраненную предварительно обученную нейронную сеть alexnet в качестве сети. Убедитесь, что имя битового потока соответствует типу данных и плате FPGA, на которую вы нацелены. В этом примере целевой платой FPGA является плата Xilinx ZCU102 SoC. Битовый поток использует один тип данных.

hW=dlhdl.Workflow('Network', trainedSN, 'Bitstream', 'zcu102_single','Target',hTarget)
hW = 
  Workflow with properties:

            Network: [1×1 DAGNetwork]
          Bitstream: 'zcu102_single'
    ProcessorConfig: []
             Target: [1×1 dlhdl.Target]

Скомпилируйте измененную сеть SqueezeNet DAG

Чтобы скомпилировать trainedSN Сеть DAG, запустите метод компиляции dlhdl.Workflow объект.

dn = hW.compile          
### Compiling network for Deep Learning FPGA prototyping ...
### Targeting FPGA bitstream zcu102_single ...
### The network includes the following layers:

     1   'data'                    Image Input              227×227×3 images with 'zerocenter' normalization                     (SW Layer)
     2   'conv1'                   Convolution              64 3×3×3 convolutions with stride [2  2] and padding [0  0  0  0]    (HW Layer)
     3   'relu_conv1'              ReLU                     ReLU                                                                 (HW Layer)
     4   'pool1'                   Max Pooling              3×3 max pooling with stride [2  2] and padding [0  0  0  0]          (HW Layer)
     5   'fire2-squeeze1x1'        Convolution              16 1×1×64 convolutions with stride [1  1] and padding [0  0  0  0]   (HW Layer)
     6   'fire2-relu_squeeze1x1'   ReLU                     ReLU                                                                 (HW Layer)
     7   'fire2-expand1x1'         Convolution              64 1×1×16 convolutions with stride [1  1] and padding [0  0  0  0]   (HW Layer)
     8   'fire2-relu_expand1x1'    ReLU                     ReLU                                                                 (HW Layer)
     9   'fire2-expand3x3'         Convolution              64 3×3×16 convolutions with stride [1  1] and padding [1  1  1  1]   (HW Layer)
    10   'fire2-relu_expand3x3'    ReLU                     ReLU                                                                 (HW Layer)
    11   'fire2-concat'            Depth concatenation      Depth concatenation of 2 inputs                                      (HW Layer)
    12   'fire3-squeeze1x1'        Convolution              16 1×1×128 convolutions with stride [1  1] and padding [0  0  0  0]  (HW Layer)
    13   'fire3-relu_squeeze1x1'   ReLU                     ReLU                                                                 (HW Layer)
    14   'fire3-expand1x1'         Convolution              64 1×1×16 convolutions with stride [1  1] and padding [0  0  0  0]   (HW Layer)
    15   'fire3-relu_expand1x1'    ReLU                     ReLU                                                                 (HW Layer)
    16   'fire3-expand3x3'         Convolution              64 3×3×16 convolutions with stride [1  1] and padding [1  1  1  1]   (HW Layer)
    17   'fire3-relu_expand3x3'    ReLU                     ReLU                                                                 (HW Layer)
    18   'fire3-concat'            Depth concatenation      Depth concatenation of 2 inputs                                      (HW Layer)
    19   'pool3'                   Max Pooling              3×3 max pooling with stride [2  2] and padding [0  1  0  1]          (HW Layer)
    20   'fire4-squeeze1x1'        Convolution              32 1×1×128 convolutions with stride [1  1] and padding [0  0  0  0]  (HW Layer)
    21   'fire4-relu_squeeze1x1'   ReLU                     ReLU                                                                 (HW Layer)
    22   'fire4-expand1x1'         Convolution              128 1×1×32 convolutions with stride [1  1] and padding [0  0  0  0]  (HW Layer)
    23   'fire4-relu_expand1x1'    ReLU                     ReLU                                                                 (HW Layer)
    24   'fire4-expand3x3'         Convolution              128 3×3×32 convolutions with stride [1  1] and padding [1  1  1  1]  (HW Layer)
    25   'fire4-relu_expand3x3'    ReLU                     ReLU                                                                 (HW Layer)
    26   'fire4-concat'            Depth concatenation      Depth concatenation of 2 inputs                                      (HW Layer)
    27   'fire5-squeeze1x1'        Convolution              32 1×1×256 convolutions with stride [1  1] and padding [0  0  0  0]  (HW Layer)
    28   'fire5-relu_squeeze1x1'   ReLU                     ReLU                                                                 (HW Layer)
    29   'fire5-expand1x1'         Convolution              128 1×1×32 convolutions with stride [1  1] and padding [0  0  0  0]  (HW Layer)
    30   'fire5-relu_expand1x1'    ReLU                     ReLU                                                                 (HW Layer)
    31   'fire5-expand3x3'         Convolution              128 3×3×32 convolutions with stride [1  1] and padding [1  1  1  1]  (HW Layer)
    32   'fire5-relu_expand3x3'    ReLU                     ReLU                                                                 (HW Layer)
    33   'fire5-concat'            Depth concatenation      Depth concatenation of 2 inputs                                      (HW Layer)
    34   'pool5'                   Max Pooling              3×3 max pooling with stride [2  2] and padding [0  1  0  1]          (HW Layer)
    35   'fire6-squeeze1x1'        Convolution              48 1×1×256 convolutions with stride [1  1] and padding [0  0  0  0]  (HW Layer)
    36   'fire6-relu_squeeze1x1'   ReLU                     ReLU                                                                 (HW Layer)
    37   'fire6-expand1x1'         Convolution              192 1×1×48 convolutions with stride [1  1] and padding [0  0  0  0]  (HW Layer)
    38   'fire6-relu_expand1x1'    ReLU                     ReLU                                                                 (HW Layer)
    39   'fire6-expand3x3'         Convolution              192 3×3×48 convolutions with stride [1  1] and padding [1  1  1  1]  (HW Layer)
    40   'fire6-relu_expand3x3'    ReLU                     ReLU                                                                 (HW Layer)
    41   'fire6-concat'            Depth concatenation      Depth concatenation of 2 inputs                                      (HW Layer)
    42   'fire7-squeeze1x1'        Convolution              48 1×1×384 convolutions with stride [1  1] and padding [0  0  0  0]  (HW Layer)
    43   'fire7-relu_squeeze1x1'   ReLU                     ReLU                                                                 (HW Layer)
    44   'fire7-expand1x1'         Convolution              192 1×1×48 convolutions with stride [1  1] and padding [0  0  0  0]  (HW Layer)
    45   'fire7-relu_expand1x1'    ReLU                     ReLU                                                                 (HW Layer)
    46   'fire7-expand3x3'         Convolution              192 3×3×48 convolutions with stride [1  1] and padding [1  1  1  1]  (HW Layer)
    47   'fire7-relu_expand3x3'    ReLU                     ReLU                                                                 (HW Layer)
    48   'fire7-concat'            Depth concatenation      Depth concatenation of 2 inputs                                      (HW Layer)
    49   'fire8-squeeze1x1'        Convolution              64 1×1×384 convolutions with stride [1  1] and padding [0  0  0  0]  (HW Layer)
    50   'fire8-relu_squeeze1x1'   ReLU                     ReLU                                                                 (HW Layer)
    51   'fire8-expand1x1'         Convolution              256 1×1×64 convolutions with stride [1  1] and padding [0  0  0  0]  (HW Layer)
    52   'fire8-relu_expand1x1'    ReLU                     ReLU                                                                 (HW Layer)
    53   'fire8-expand3x3'         Convolution              256 3×3×64 convolutions with stride [1  1] and padding [1  1  1  1]  (HW Layer)
    54   'fire8-relu_expand3x3'    ReLU                     ReLU                                                                 (HW Layer)
    55   'fire8-concat'            Depth concatenation      Depth concatenation of 2 inputs                                      (HW Layer)
    56   'fire9-squeeze1x1'        Convolution              64 1×1×512 convolutions with stride [1  1] and padding [0  0  0  0]  (HW Layer)
    57   'fire9-relu_squeeze1x1'   ReLU                     ReLU                                                                 (HW Layer)
    58   'fire9-expand1x1'         Convolution              256 1×1×64 convolutions with stride [1  1] and padding [0  0  0  0]  (HW Layer)
    59   'fire9-relu_expand1x1'    ReLU                     ReLU                                                                 (HW Layer)
    60   'fire9-expand3x3'         Convolution              256 3×3×64 convolutions with stride [1  1] and padding [1  1  1  1]  (HW Layer)
    61   'fire9-relu_expand3x3'    ReLU                     ReLU                                                                 (HW Layer)
    62   'fire9-concat'            Depth concatenation      Depth concatenation of 2 inputs                                      (HW Layer)
    63   'new_dropout'             Dropout                  60% dropout                                                          (HW Layer)
    64   'new_conv'                Convolution              3 1×1×512 convolutions with stride [1  1] and padding [0  0  0  0]   (HW Layer)
    65   'relu_conv10'             ReLU                     ReLU                                                                 (HW Layer)
    66   'pool10'                  Global Average Pooling   Global average pooling                                               (HW Layer)
    67   'prob'                    Softmax                  softmax                                                              (SW Layer)
    68   'new_classoutput'         Classification Output    crossentropyex with 'ARR' and 2 other classes                        (SW Layer)

4 Memory Regions created.

Skipping: data
Compiling leg: conv1>>fire2-relu_squeeze1x1 ...
Compiling leg: conv1>>fire2-relu_squeeze1x1 ... complete.
Compiling leg: fire2-expand1x1>>fire2-relu_expand1x1 ...
Compiling leg: fire2-expand1x1>>fire2-relu_expand1x1 ... complete.
Compiling leg: fire2-expand3x3>>fire2-relu_expand3x3 ...
Compiling leg: fire2-expand3x3>>fire2-relu_expand3x3 ... complete.
Do nothing: fire2-concat
Compiling leg: fire3-squeeze1x1>>fire3-relu_squeeze1x1 ...
Compiling leg: fire3-squeeze1x1>>fire3-relu_squeeze1x1 ... complete.
Compiling leg: fire3-expand1x1>>fire3-relu_expand1x1 ...
Compiling leg: fire3-expand1x1>>fire3-relu_expand1x1 ... complete.
Compiling leg: fire3-expand3x3>>fire3-relu_expand3x3 ...
Compiling leg: fire3-expand3x3>>fire3-relu_expand3x3 ... complete.
Do nothing: fire3-concat
Compiling leg: pool3>>fire4-relu_squeeze1x1 ...
Compiling leg: pool3>>fire4-relu_squeeze1x1 ... complete.
Compiling leg: fire4-expand1x1>>fire4-relu_expand1x1 ...
Compiling leg: fire4-expand1x1>>fire4-relu_expand1x1 ... complete.
Compiling leg: fire4-expand3x3>>fire4-relu_expand3x3 ...
Compiling leg: fire4-expand3x3>>fire4-relu_expand3x3 ... complete.
Do nothing: fire4-concat
Compiling leg: fire5-squeeze1x1>>fire5-relu_squeeze1x1 ...
Compiling leg: fire5-squeeze1x1>>fire5-relu_squeeze1x1 ... complete.
Compiling leg: fire5-expand1x1>>fire5-relu_expand1x1 ...
Compiling leg: fire5-expand1x1>>fire5-relu_expand1x1 ... complete.
Compiling leg: fire5-expand3x3>>fire5-relu_expand3x3 ...
Compiling leg: fire5-expand3x3>>fire5-relu_expand3x3 ... complete.
Do nothing: fire5-concat
Compiling leg: pool5>>fire6-relu_squeeze1x1 ...
Compiling leg: pool5>>fire6-relu_squeeze1x1 ... complete.
Compiling leg: fire6-expand1x1>>fire6-relu_expand1x1 ...
Compiling leg: fire6-expand1x1>>fire6-relu_expand1x1 ... complete.
Compiling leg: fire6-expand3x3>>fire6-relu_expand3x3 ...
Compiling leg: fire6-expand3x3>>fire6-relu_expand3x3 ... complete.
Do nothing: fire6-concat
Compiling leg: fire7-squeeze1x1>>fire7-relu_squeeze1x1 ...
Compiling leg: fire7-squeeze1x1>>fire7-relu_squeeze1x1 ... complete.
Compiling leg: fire7-expand1x1>>fire7-relu_expand1x1 ...
Compiling leg: fire7-expand1x1>>fire7-relu_expand1x1 ... complete.
Compiling leg: fire7-expand3x3>>fire7-relu_expand3x3 ...
Compiling leg: fire7-expand3x3>>fire7-relu_expand3x3 ... complete.
Do nothing: fire7-concat
Compiling leg: fire8-squeeze1x1>>fire8-relu_squeeze1x1 ...
Compiling leg: fire8-squeeze1x1>>fire8-relu_squeeze1x1 ... complete.
Compiling leg: fire8-expand1x1>>fire8-relu_expand1x1 ...
Compiling leg: fire8-expand1x1>>fire8-relu_expand1x1 ... complete.
Compiling leg: fire8-expand3x3>>fire8-relu_expand3x3 ...
Compiling leg: fire8-expand3x3>>fire8-relu_expand3x3 ... complete.
Do nothing: fire8-concat
Compiling leg: fire9-squeeze1x1>>fire9-relu_squeeze1x1 ...
Compiling leg: fire9-squeeze1x1>>fire9-relu_squeeze1x1 ... complete.
Compiling leg: fire9-expand1x1>>fire9-relu_expand1x1 ...
Compiling leg: fire9-expand1x1>>fire9-relu_expand1x1 ... complete.
Compiling leg: fire9-expand3x3>>fire9-relu_expand3x3 ...
Compiling leg: fire9-expand3x3>>fire9-relu_expand3x3 ... complete.
Do nothing: fire9-concat
Compiling leg: new_conv>>relu_conv10 ...
Compiling leg: new_conv>>relu_conv10 ... complete.
Compiling leg: pool10 ...
Compiling leg: pool10 ... complete.
Skipping: prob
Skipping: new_classoutput
Creating Schedule...
.......................................
Creating Schedule...complete.
Creating Status Table...
......................................
Creating Status Table...complete.
Emitting Schedule...
......................................
Emitting Schedule...complete.
Emitting Status Table...
........................................
Emitting Status Table...complete.

### Allocating external memory buffers:

          offset_name          offset_address    allocated_space 
    _______________________    ______________    ________________

    "InputDataOffset"           "0x00000000"     "24.0 MB"       
    "OutputResultOffset"        "0x01800000"     "4.0 MB"        
    "SchedulerDataOffset"       "0x01c00000"     "4.0 MB"        
    "SystemBufferOffset"        "0x02000000"     "28.0 MB"       
    "InstructionDataOffset"     "0x03c00000"     "4.0 MB"        
    "ConvWeightDataOffset"      "0x04000000"     "12.0 MB"       
    "FCWeightDataOffset"        "0x04c00000"     "0.0 MB"        
    "EndOffset"                 "0x04c00000"     "Total: 76.0 MB"

### Network compilation complete.
dn = struct with fields:
             weights: [1×1 struct]
        instructions: [1×1 struct]
           registers: [1×1 struct]
    syncInstructions: [1×1 struct]

Программа Bitstream на FPGA и загрузка сетевых весов

Чтобы развернуть сеть на оборудовании Xilinx ZCU102, запустите функцию развертывания dlhdl.Workflow объект. Эта функция использует выход функции компиляции, чтобы запрограммировать плату FPGA с помощью файла программирования. Он также загружает веса и смещения сети. Функция развертывания начинает программировать устройство FPGA, отображает сообщения о прогрессе и времени развертывания сети.

hW.deploy
### FPGA bitstream programming has been skipped as the same bitstream is already loaded on the target FPGA.
### Loading weights to Conv Processor.
### Conv Weights loaded. Current time is 12-Jan-2021 16:28:17

Загрузка изображения для предсказания и запуск предсказания

idx=randi(32);
testim=readimage(imgsValidation,idx);
im=imresize(testim,[227 227]);
imshow(testim)

[YPred1,probs1] = classify(trainedSN,im);
accuracy1 = (YPred1==imgsValidation.Labels);
[YPred2,probs2] = hW.predict(single(im),'profile','on');
### Finished writing input activations.
### Running single input activations.


              Deep Learning Processor Profiler Performance Results

                   LastFrameLatency(cycles)   LastFrameLatency(seconds)       FramesNum      Total Latency     Frames/s
                         -------------             -------------              ---------        ---------       ---------
Network                    8847610                  0.04022                       1            8847610             24.9
    conv1                   626502                  0.00285 
    pool1                   579473                  0.00263 
    fire2-squeeze1x1        308065                  0.00140 
    fire2-expand1x1         305121                  0.00139 
    fire2-expand3x3         305091                  0.00139 
    fire3-squeeze1x1        624849                  0.00284 
    fire3-expand1x1         305136                  0.00139 
    fire3-expand3x3         305587                  0.00139 
    pool3                   290789                  0.00132 
    fire4-squeeze1x1        262881                  0.00119 
    fire4-expand1x1         263129                  0.00120 
    fire4-expand3x3         262617                  0.00119 
    fire5-squeeze1x1        703951                  0.00320 
    fire5-expand1x1         262552                  0.00119 
    fire5-expand3x3         262599                  0.00119 
    pool5                   216737                  0.00099 
    fire6-squeeze1x1        192738                  0.00088 
    fire6-expand1x1         142333                  0.00065 
    fire6-expand3x3         142132                  0.00065 
    fire7-squeeze1x1        286437                  0.00130 
    fire7-expand1x1         142363                  0.00065 
    fire7-expand3x3         142079                  0.00065 
    fire8-squeeze1x1        364915                  0.00166 
    fire8-expand1x1         240660                  0.00109 
    fire8-expand3x3         240946                  0.00110 
    fire9-squeeze1x1        483766                  0.00220 
    fire9-expand1x1         240624                  0.00109 
    fire9-expand3x3         241242                  0.00110 
    new_conv                 93673                  0.00043 
    pool10                    6135                  0.00003 
 * The clock frequency of the DL processor is: 220MHz
accuracy2 = (YPred==imgsValidation.Labels);
[val,idx]= max(YPred2);
trainedSN.Layers(end).ClassNames{idx}
ans = 
'CHF'

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

helperCreateECGDataDirectories создает директорию данных в родительской директории, затем создает три подкаталога в директории данных. Подкаталоги названы в честь каждого класса сигнала ЭКГ, найденного в ECGData.

function helperCreateECGDirectories(ECGData,parentFolder,dataFolder)
% This function is only intended to support the ECGAndDeepLearningExample.
% 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 строит графики первых тысяч выборок представителя каждого класса сигнала ЭКГ, обнаруженного в ECGData.

function helperPlotReps(ECGData)
% This function is only intended to support the ECGAndDeepLearningExample.
% 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 использует cwtfilterbank (Wavelet Toolbox), чтобы получить непрерывное вейвлет сигналов ECG и генерирует скалограммы из вейвлет-коэффициентов. Функция helper изменяет размер скалограмм и записывает их на диск как изображения jpeg.

function helperCreateRGBfromTF(ECGData,parentFolder,childFolder)
% This function is only intended to support the ECGAndDeepLearningExample.
% 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,[224 224]),fullfile(imgLoc,imFileName));
end
end