Этот пример показывает рабочий процесс, чтобы классифицировать человеческую электрокардиограмму (ECG) сигналы с помощью Непрерывного преобразования вейвлета (CWT) и глубокой сверточной нейронной сети (CNN). Этот пример также предоставляет информацию о том, как сгенерировать и развернуть код и CNN для предсказания на цели Raspberry Pi (устройство ARM®-based).
SqueezeNet является глубоким CNN, первоначально спроектированным, чтобы классифицировать изображения на 1 000 категорий. В примере Классифицируют Временные ряды Используя Анализ Вейвлета и Глубокое обучение (Wavelet Toolbox), SqueezeNet переобучен, чтобы классифицировать формы волны ECG на основе их scalograms. scalogram является представлением частоты времени сигнала и является абсолютным значением CWT сигнала. Мы снова используем переобученный SqueezeNet в этом примере.
В этом примере используются данные о ECG PhysioNet. Данные о ECG получены из трех групп людей: люди с сердечной аритмией (ARR), люди с застойной сердечной недостаточностью (CHF) и люди с нормальными ритмами пазухи (NSR). Набор данных включает 96 записей от людей с ARR, 30 записей от людей со швейцарским франком и 36 записей от людей с NSR. 162 записи ECG от трех Физиосетевых баз данных: База данных Аритмии MIT-BIH [2] [3], MIT-BIH Нормальная База данных Ритма Пазухи [3] и База данных Застойной сердечной недостаточности BIDMC [1] [3]. Сокращенные данные о ECG вышеупомянутых ссылок могут быть загружены с репозитория GitHub.
Процессор ARM, который поддерживает расширение NEON
ARM Вычисляет версию 19.05 Библиотеки (на целевом оборудовании ARM)
Переменные окружения для компиляторов и библиотек
Интерфейс MATLAB Coder для пакета поддержки Библиотек Глубокого обучения
Для поддерживаемых версий библиотек и для получения информации о подготовке переменных окружения, смотрите Необходимые условия для Глубокого обучения для MATLAB Coder (MATLAB Coder). Этот пример не поддерживается в MATLAB Online™.
Базовая функция в сгенерированном исполняемом файле, processECG
, использование 65 536 выборок данных о ECG с одинарной точностью, как введено. Функция:
Берет CWT данных о ECG.
Получает scalogram из коэффициентов вейвлета.
Преобразует scalogram в волшебника RGB размерности 227 227 3. Это делает изображение совместимым с архитектурой сети SqueezeNet.
Выполняет предсказание, чтобы классифицировать использование изображений SqueezeNet.
type processECG
function [YPred] = processECG(input) % processECG function - converts 1D ECG to image and predicts the syndrome % of heart disease % % This function is only intended to support the example: % Signal Classification Code Generation Using Wavelets and % Deep Learning on Raspberry Pi. It may change or be removed in a % future release. % Copyright 2020 The MathWorks, Inc. % colourmap for image transformation persistent net jetdata; if(isempty(jetdata)) jetdata = colourmap(128,class(input)); end % Squeezenet trained network if(isempty(net)) net = coder.loadDeepLearningNetwork('trainedNet.mat'); end % Wavelet Transformation & Image conversion cfs = ecg_to_Image(input); image = ind2rgb(im2uint8(rescale(cfs)),single(jetdata)); image = im2uint8(imresize(image,[227,227])); % figure if isempty(coder.target) imshow(image); end % Prediction [YPred] = predict(net,image); %% ECG to image conversion function cfs = ecg_to_Image(input) %Wavelet Transformation persistent filterBank [~,siglen] = size(input); if isempty(filterBank) filterBank = cwtfilterbank('SignalLength',siglen,'VoicesPerOctave',6); end %CWT conversion cfs = abs(filterBank.wt(input)); end %% Colourmap function J = colourmap(m,class) n = ceil(m/4); u = [(1:1:n)/n ones(1,n-1) (n:-1:1)/n]'; g = ceil(n/2) - (mod(m,4)==1) + (1:length(u))'; r = g + n; b = g - n; r1 = r(r<=128); g1 = g(g<=128); b1 = b(b >0); J = zeros(m,3); J(r1,1) = u(1:length(r1)); J(g1,2) = u(1:length(g1)); J(b1,3) = u(end-length(b1)+1:end); feval = str2func(class); J = feval(J); end end
Создайте объект настройки генерации кода для генерации исполняемой программы. Задайте генерацию Кода С++.
cfg = coder.config('exe'); cfg.TargetLang = 'C++';
Создайте coder.ARMNEONConfig
объект. Задайте ту же версию библиотеки ARM Compute как та на Raspberry Pi. Задайте архитектуру Raspberry Pi.
dlcfg = coder.DeepLearningConfig('arm-compute'); dlcfg.ArmComputeVersion = '19.05'; dlcfg.ArmArchitecture = 'armv7';
Установите DeepLearningConfig
свойство настройки генерации кода возражает против объекта настройки глубокого обучения. Сделайте Исходные Комментарии MATLAB видимыми в объекте настройки во время генерации кода.
cfg.DeepLearningConfig = dlcfg; cfg.MATLABSourceComments = 1;
Используйте Пакет поддержки MATLAB для функции Пакета поддержки Raspberry Pi, raspi
, создать связь с Raspberry Pi. В следующем коде, замене:
'raspiname'
с именем вашего Raspberry Pi
'pi'
с вашим именем пользователя
'password'
с вашим паролем
r = raspi('172.18.76.69','pi','raspberry');
Создайте coder.Hardware
объект для Raspberry Pi и присоединения это к объекту настройки генерации кода.
hw = coder.hardware('Raspberry Pi');
cfg.Hardware = hw;
Задайте папку сборки на Raspberry Pi.
buildDir = '~/remdirECG';
cfg.Hardware.BuildDir = buildDir;
C++ основной файл считывает данные о входе ECG, вызывает processECG
функция, чтобы выполнить предварительную обработку и глубокое обучение с помощью CNN на данных о ECG и отображений вероятность классификации.
Задайте основной файл в объекте настройки генерации кода. Узнать больше о генерации и настройке main_ecg_raspi.cpp
, означайте генерацию Автономных Исполняемых файлов C/C++ из кода MATLAB (MATLAB Coder).
cfg.CustomSource = 'main_ecg_raspi.cpp';
codegen
Используйте codegen
функция, чтобы сгенерировать Код С++. Когда codegen
используется с Пакетом поддержки MATLAB для Оборудования Raspberry Pi, исполняемый файл основан на плате Raspberry Pi.
Убедитесь, что установили переменные окружения ARM_COMPUTELIB
и LD_LIBRARY_PATH
на Raspberry Pi. Смотрите необходимые условия для глубокого обучения для MATLAB Coder (MATLAB Coder).
codegen -config cfg processECG -args {ones(1,65536,'single')} -d arm_compute
Deploying code. This may take a few minutes.
Чтобы протестировать сгенерированный код на Raspberry Pi, скопируйте сигнал входа ECG в директорию сгенерированного кода. Можно найти эту директорию вручную или при помощи raspi.utils.getRemoteBuildDirectory
API. Эта функция перечисляет директории двоичных файлов, которые сгенерированы при помощи codegen
.
applicationDirPaths = raspi.utils.getRemoteBuildDirectory('applicationName','processECG')
applicationDirPaths=1×4 cell array
{1×1 struct} {1×1 struct} {1×1 struct} {1×1 struct}
Полный путь к удаленному каталогу сборки выведен из настоящей рабочей директории. Если вы не знаете который applicationDirPaths
запись содержит сгенерированный код, используйте функцию помощника helperFindTargetDir
. В противном случае задайте соответствующую директорию.
directoryUnknown = true; if directoryUnknown targetDirPath = helperFindTargetDir(applicationDirPaths); else targetDirPath = applicationDirPaths{1}.directory; end
Текстовый файл input_ecg_raspi.csv
содержит выборки ECG представительного сигнала ARR. Чтобы скопировать файл, требуемый запускать исполняемую программу, используйте putFile
, который доступен с Пакетом поддержки MATLAB для Оборудования Raspberry Pi.
r.putFile('input_ecg_raspi.csv', targetDirPath);
Для графического представления первые 1 000 выборок могут быть построены при помощи этих шагов.
input = dlmread('input_ecg_raspi.csv'); plot(input(1:1000)) title('ARR Signal')
Запустите исполняемую программу на Raspberry Pi из MATLAB и направьте выход назад к MATLAB. Входное имя файла передается как параметр командной строки для исполняемого файла.
exeName = 'processECG.elf'; % executable name fileName = 'input_ecg_raspi.csv'; % Input ECG file that is pushed to target command = ['cd ' targetDirPath ';./' exeName ' ' fileName]; output = system(r,command)
output = 'Predicted Values on the Target Hardware ARR CHF NSR 0.806078 0.193609 0.000313103 '
Baim, D. S. В. С. Колуччи, Э. С. Монрэд, Х. С. Смит, Р. Ф. Райт, А. Лэноу, Д. Ф. Готье, Б. Дж. Рэнсил, В. Гроссман и Э. Бронвалд. "Выживание пациентов с тяжелой застойной сердечной недостаточностью отнеслось с устным milrinone". Журнал американского Колледжа Кардиологии. Издание 7, Номер 3, 1986, стр 661–670.
Голдбергер А. Л., Л. А. Н. Амарал, 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.
Капризный, G. B. и Р. Г. Марк. "Удар Базы данных Аритмии MIT-BIH". Разработка IEEE в Журнале Медицины и Биологии. Издание 20. Номер 3, мочь-июнь 2001, стр 45–50. (PMID: 11446209)
helperFindTargetDir
function targetDir = helperFindTargetDir(dirPaths) % % This function is only intended to support wavelet deep learning examples. % It may change or be removed in a future release. % find pwd p = pwd; if ispc % replace blank spaces with underscores p = strrep(p,' ','_'); % split path into component folders pSplit = regexp(p,filesep,'split'); % Since Windows uses colons, remove any colons that occur for k=1:numel(pSplit) pSplit{k} = erase(pSplit{k},':'); end % now build the path using Linux file separation pLinux = ''; for k=1:numel(pSplit)-1 pLinux = [pLinux,pSplit{k},'/']; end pLinux = [pLinux,pSplit{end}]; else pLinux = p; end targetDir = ''; for k=1:numel(dirPaths) d = strfind(dirPaths{k}.directory,pLinux); if ~isempty(d) targetDir = dirPaths{k}.directory; break end end if numel(targetDir) == 0 disp('Target directory not found.'); end end