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

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

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

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

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

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

Разархивация создает папку 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'.

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

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

Постройте представителя каждой категории ECG. Функция помощника helperPlotReps делает это. helperPlotReps принимает ECGData как введено. Можно найти исходный код для этой функции помощника в разделе Supporting Functions в конце этого примера.

helperPlotReps(ECGData)

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

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

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

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

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)')

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

helperCreateRGBfromTF(ECGData,parentDir,dataDir)

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

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

allImages = imageDatastore(fullfile(parentDir,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, архитектура которого поддерживает изображения размера 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, последний learnable слой в 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. Установите случайный seed на значение по умолчанию и обучите сеть. Учебный процесс обычно занимает 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™ Установки 2019.2. Установить Xilinx Vivado toolpath, введите:

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

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

Создайте объект WorkFlow

Используйте 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]

Скомпилируйте сеть Modified 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]

Поток битов программы на 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 создает директорию данных в родительском каталоге, затем создает три подкаталога в директории данных. Подкаталоги называют в честь каждого класса сигнала ECG, найденного в 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 строит первую тысячу выборок представителя каждого класса сигнала ECG, найденного в 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 сигнализирует и генерирует scalograms от коэффициентов вейвлета. Функция помощника изменяет размер scalograms и пишет им в диск как 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