Этот пример показывает, как сегментировать человеческую электрокардиограмму (ECG) сигналы с помощью текущих нейронных сетей для глубокого обучения и анализа частоты времени.
Электрическое действие в основе может быть измерено как последовательность амплитуд далеко от базового сигнала. Для одного нормального цикла сердцебиения сигнал ECG может быть разделен на следующую морфологию удара [1]:
P волна — маленькое отклонение перед комплексом QRS представление предсердной деполяризации
Комплекс QRS — Само-амплитудный фрагмент heartbeat
T волна — маленькое отклонение после комплекса QRS представление желудочковой реполяризации
Сегментация этих областей форм волны ECG может обеспечить основание для измерений, полезных для оценки полного здоровья человеческого сердца и присутствия отклонений [2]. Вручную аннотирование каждой области сигнала ECG может быть утомительной и длительной задачей с потенциалом того, чтобы быть автоматизированным методами машинного обучения и обработкой сигналов.
Этот пример использует сигналы ECG от общедоступной Базы данных QT [3] [4]. Данные состоят примерно из 15 минут записей ECG от в общей сложности 105 пациентов. Чтобы получить каждую запись, ревизоры поместили два электрода в другие места на груди пациента, приводящей к двухканальному сигналу. База данных обеспечивает метки области сигнала, сгенерированные автоматизированной экспертной системой [2]. Этот пример стремится использовать решение для глубокого обучения обеспечить метку для каждой выборки согласно области, где выборка расположена. Этот процесс маркировки видимых областей через сигнал часто упоминается как сегментация формы волны.
Чтобы обучить глубокую нейронную сеть классифицировать области сигнала, можно использовать сеть Long Short-Term Memory (LSTM). Этот пример показывает, как методы предварительной обработки сигнала и анализ частоты времени могут использоваться, чтобы улучшать производительность сегментации LSTM. В частности, использование в качестве примера synchrosqueezed Фурье преобразовывает, чтобы представлять неустановившееся поведение сигнала ECG.
Первый шаг должен загрузить данные из Репозитория GitHub. Все браузеры имеют директорию Downloads, которая может быть идентифицирована через Настройки. Найдите файл QT_Database-master.zip
в той директории и переместите его в папку, где у вас есть разрешение записи. Этот пример принимает, что вы поместили файл в свою временную директорию, местоположение которой задано командой tempdir
MATLAB®. Если вы имеете данные в папке, отличающейся от tempdir
, изменяете имя каталога в последующих инструкциях. Запустите путем разархивации файла данных.
unzip(fullfile(tempdir,'QT_Database-master.zip'),tempdir)
Разархивация создает папку QT_Database-master
в вашей временной директории. Эта папка содержит текстовый файл README.md
и следующие файлы:
QTData.mat
Modified_physionet_data.txt
License.txt
QTData.mat
содержит данные, используемые в этом примере. Файл, который Modified_physionet_data.txt
обеспечивает исходным приписываниям для данных и описания операций, применился к каждой необработанной записи ECG.
load(fullfile(tempdir,'QT_Database-master','QTData.mat')) QTData
QTData = labeledSignalSet with properties: Source: {105×1 cell} NumMembers: 105 TimeInformation: "sampleRate" SampleRate: 250 Labels: [105×2 table] Description: "" Use labelDefinitionsHierarchy to see a list of labels and sublabels. Use setLabelValue to add data to the set.
QTData
является labeledSignalSet
, который содержит исходные сигналы ECG и соответствующие метки формы волны вместе в отдельном объекте. 105 двухканальных сигналов ECG содержатся в свойстве Source
. Свойство Labels
содержит таблицу меток формы волны. Каждый канал был маркирован независимо автоматизированной экспертной системой и обработан независимо для в общей сложности 210 сигналов ECG. Метки формы волны задают каждую выборку сигнала как принадлежащий одному из следующих классов: P, QRS, T, и N/A. Значение N/A соответствует выборкам за пределами волны P, комплекса QRS или волны T.
Используйте команду head
, чтобы осмотреть первые несколько строк таблицы, содержавшейся в свойстве Labels
QTData
.
head(QTData.Labels)
ans=8×2 table
WaveformLabels_Chan1 WaveformLabels_Chan2
____________________ ____________________
Member{1} [225000×2 table] [225000×2 table]
Member{2} [225000×2 table] [225000×2 table]
Member{3} [225000×2 table] [225000×2 table]
Member{4} [225000×2 table] [225000×2 table]
Member{5} [225000×2 table] [225000×2 table]
Member{6} [225000×2 table] [225000×2 table]
Member{7} [225000×2 table] [225000×2 table]
Member{8} [225000×2 table] [225000×2 table]
Каждая строка таблицы соответствует пациенту, и каждый столбец таблицы соответствует каналу. Используйте функцию getSignal
, чтобы извлечь данные сигнала для первого пациента. Используйте функцию getLabelValues
, чтобы извлечь метки для первого канала. Визуализируйте метки для первых 1 000 выборок с помощью функции помощника displayWaveformLabels
.
patientID = 1;
signalVals = getSignal(QTData,patientID);
labelVals = getLabelValues(QTData,patientID,'WaveformLabels_Chan1');
displayWaveformLabels(signalVals(1,1:1000),labelVals.Value(1:1000))
Осмотрите значения метки вокруг 150-й выборки, где сигнал изменяется быстро. Область отмечает конец комплекса QRS и перехода в выборки N/A.
val = labelVals.Value(145:155)
val = 11×1 categorical array
QRS
QRS
QRS
QRS
QRS
QRS
QRS
QRS
n/a
n/a
n/a
Обычная процедура классификации машинного обучения следующая:
Разделите базу данных на обучение и тестирующий наборы данных.
Обучите сеть с помощью обучающего набора данных.
Используйте обучивший сеть, чтобы сделать прогнозы на наборе данных тестирования.
Сеть обучена с 70% данных и протестирована с остающимися 30%. Чтобы предотвратить любое смещение, никакие данные, принадлежащие тому же пациенту, не совместно используются через набор обучающих данных и тестирование набора.
Для восстанавливаемых результатов, сброс генератор случайных чисел. Используйте свойство NumMembers
labeledSignalSet
извлечь количество пациентов. Используйте функцию dividerand
, чтобы переставить пациентов и использовать функцию subset
, чтобы разделить данные на обучение и тестирование labeledSignalSet
s.
rng default
[trainInd,~,testInd] = dividerand(QTData.NumMembers,0.7,0,0.3);
trainQT = subset(QTData,trainInd);
testQT = subset(QTData,testInd);
Чтобы ввести данные timeseries к сети, организуйте данные как массивы ячеек матриц с помощью функции помощника resizeSignals
. Эта функция помощника также делит данные на фрагменты с 5000 выборками, чтобы избежать чрезмерного использования памяти.
[signalsTrain,labelsTrain] = resizeSignals(trainQT); [signalsTest,labelsTest] = resizeSignals(testQT);
Во-первых, обучите сеть с помощью необработанных сигналов ECG от обучающего набора данных.
Задайте сетевую архитектуру перед обучением. Задайте sequenceInputLayer
размера 1, чтобы принять одномерные временные ряды. Задайте слой LSTM с режимом вывода 'sequence'
, чтобы обеспечить классификацию для каждой выборки в сигнале. Используйте 200 скрытых узлов для оптимальной производительности. Задайте fullyConnectedLayer
с выходным размером 4, один для каждого из классов формы волны. Добавьте softmaxLayer
и classificationLayer
, чтобы вывести предполагаемые метки.
layers = [ ... sequenceInputLayer(1) lstmLayer(200,'OutputMode','sequence') fullyConnectedLayer(4) softmaxLayer classificationLayer];
Выберите опции для учебного процесса, которые гарантируют хорошую производительность сети. Обратитесь к документации trainingOptions
для описания каждого параметра.
options = trainingOptions('adam', ... 'MaxEpochs',10, ... 'MiniBatchSize',50, ... 'InitialLearnRate',0.01, ... 'LearnRateDropPeriod',3, ... 'LearnRateSchedule','piecewise', ... 'GradientThreshold',1, ... 'Plots','training-progress',... 'Verbose',0);
Используйте команду trainNetwork
, чтобы обучить сеть LSTM. Из-за большого размера набора данных, этот процесс может занять несколько минут. Если ваша машина имеет графический процессор и Parallel Computing Toolbox™, то MATLAB автоматически использует графический процессор для обучения. В противном случае это использует центральный процессор.
Учебные подграфики точности и потери в фигуре отслеживают учебный прогресс через все итерации. Используя необработанные данные сигнала, сеть правильно классифицирует приблизительно 70% выборок как принадлежащий волне P, комплексу QRS, волне T или N/A.
net = trainNetwork(signalsTrain,labelsTrain,layers,options);
Классифицируйте данные о тестировании с помощью обученной сети LSTM и команды classify
. Задайте мини-пакетный размер 50, чтобы совпадать с опциями обучения.
predTest = classify(net,signalsTest,'MiniBatchSize',50);
Матрица беспорядка обеспечивает интуитивное, и информативное означает визуализировать производительность классификации. Используйте команду confusionchart
, чтобы вычислить полную точность классификации для прогнозов данных о тестировании. Для каждого входа преобразуйте массив ячеек категориальных меток к вектору - строке. Задайте нормированное столбцом отображение, чтобы просмотреть результаты как проценты выборок для каждого класса.
confusionchart([predTest{:}],[labelsTest{:}],'Normalization','column-normalized');
Используя необработанный сигнал ECG, как введено к сети, только приблизительно 35% выборок P-волны, 60% QRS-комплексных выборок и 60% выборок T-волны были правильны. Чтобы улучшать производительность, примените некоторое знание характеристик сигнала ECG до входа к нейронной сети для глубокого обучения, например, базовая линия, блуждающая вызванный дыхательным движением пациента.
Три морфологии удара занимает различные диапазоны частот. Спектр комплекса QRS обычно имеет центральную частоту приблизительно 10-25 Гц, и ее компоненты лежат ниже 40 Гц. P и волны T происходят на еще более низких частотах: P-волновые-компоненты ниже 20 Гц, и T-волновые-компоненты ниже 10 Гц [5].
Базовое блуждание является низкочастотным (<0,5 Гц) колебание, вызванное движением дыхания пациента. Это колебание независимо от морфологии удара и не предоставляет значимую информацию [6].
Разработайте полосовой фильтр с частотным диапазоном полосы пропускания [0.5, 40] Гц, чтобы удалить блуждание и любой высокочастотный шум. Удаление этих компонентов улучшает обучение LSTM, потому что сеть не изучает несоответствующие функции.
Fs = QTData.SampleRate; [~,dBP] = bandpass(signalsTrain{1},[0.5 40],Fs);
Задайте анонимную функцию, BPfun
, чтобы применить полосовой фильтр к каждому сигналу.
BPfun = @(X) filter(dBP,X); signalsFilteredTrain = cellfun(BPfun,signalsTrain,'UniformOutput',false); signalsFilteredTest = cellfun(BPfun,signalsTest,'UniformOutput',false);
Постройте сырые данные и отфильтрованные сигналы для типичного случая.
subplot(2,1,1) plot(signalsTrain{210}(2001:3000)) title('Raw') grid subplot(2,1,2) plot(signalsFilteredTrain{210}(2001:3000)) title('Filtered') grid
Обучите сеть LSTM на отфильтрованных сигналах ECG с помощью той же сетевой архитектуры.
filteredNet = trainNetwork(signalsFilteredTrain,labelsTrain,layers,options);
Предварительная обработка сигналов улучшает учебную точность до лучше, чем 80%.
Классифицируйте предварительно обработанные тестовые данные с обновленной сетью LSTM.
predFilteredTest = classify(filteredNet,signalsFilteredTest,'MiniBatchSize',50);
Визуализируйте производительность классификации как матрицу беспорядка.
figure confusionchart([predFilteredTest{:}],[labelsTest{:}],'Normalization','column-normalized');
Простая предварительная обработка улучшает классификацию P-волн приблизительно на 10%, QRS-комплексную классификацию на 10% и классификацию T-волн на 20%.
Общий подход для успешной классификации данных timeseries должен извлечь функции частоты времени и накормить ими сеть вместо исходных данных. Сеть затем изучает шаблоны через время и частоту одновременно [7].
synchrosqueezed Фурье преобразовывают (FSST), вычисляет спектр частоты для каждой выборки сигнала. Используйте функцию fsst
, чтобы осмотреть преобразование одного из учебных сигналов. Задайте окно Kaiser длины 128, чтобы обеспечить соответствующее разрешение частоты.
fsst(signalsTrain{1},Fs,kaiser(128),'yaxis')
Вычислите FSST каждого сигнала в обучающем наборе данных. Извлеките данные по частотному диапазону интереса, [0.5, 40] Гц, путем индексации соответствующего содержимого от преобразования выходные параметры. Обработайте действительные и мнимые части FSST как отдельные функции и подайте оба компонента в сеть.
Прежде, чем обучить сеть, стандартизируйте учебные функции путем вычитания среднего значения и деления на стандартное отклонение.
signalsFsstTrain = cell(size(signalsTrain)); meanTrain = cell(1,length(signalsTrain)); stdTrain = cell(1,length(signalsTrain)); for idx = 1:length(signalsTrain) [s,f,t] = fsst(signalsTrain{idx},Fs,kaiser(128)); f_indices = (f > 0.5) & (f < 40); signalsFsstTrain{idx}= [real(s(f_indices,:)); imag(s(f_indices,:))]; meanTrain{idx} = mean(signalsFsstTrain{idx},2); stdTrain{idx} = std(signalsFsstTrain{idx},[],2); end standardizeFun = @(x) (x - mean(cell2mat(meanTrain),2))./mean(cell2mat(stdTrain),2); signalsFsstTrain = cellfun(standardizeFun,signalsFsstTrain,'UniformOutput',false);
Повторите эту процедуру для данных о тестировании. Стандартизируйте функции тестирования с помощью среднего и стандартного отклонения от данных тренировки.
signalsFsstTest = cell(size(signalsTest)); for idx = 1:length(signalsTest) [s,f,t] = fsst(signalsTest{idx},Fs,kaiser(128)); f_indices = (f > 0.5) & (f < 40); signalsFsstTest{idx}= [real(s(f_indices,:)); imag(s(f_indices,:))]; end signalsFsstTest = cellfun(standardizeFun,signalsFsstTest,'UniformOutput',false);
Измените архитектуру LSTM так, чтобы сеть приняла спектр частоты для каждой выборки вместо одного значения. Осмотрите размер FSST, чтобы видеть количество частот.
size(signalsFsstTrain{1})
ans = 1×2
40 5000
Задайте sequenceInputLayer
40 входных функций. Сохраните остальную часть сетевых параметров неизменной.
layers = [ ... sequenceInputLayer(40) lstmLayer(200,'OutputMode','sequence') fullyConnectedLayer(4) softmaxLayer classificationLayer];
Обучите обновленную сеть LSTM с преобразованным набором данных.
fsstNet = trainNetwork(signalsFsstTrain,labelsTrain,layers,options);
Использование функций частоты времени улучшает учебную точность, которая теперь превышает 90%.
Используя обновленную сеть LSTM и извлеченные функции FSST, классифицируйте данные о тестировании.
predFsstTest = classify(fsstNet,signalsFsstTest,'MiniBatchSize',50);
Визуализируйте производительность классификации как матрицу беспорядка.
confusionchart([predFsstTest{:}],[labelsTest{:}],'Normalization','column-normalized');
Используя частоту времени представление улучшает классификацию P-волн на 50% (приблизительно с 35% до 85%), QRS-комплексную классификацию на 35% и классификацию T-волн на 25%.
Используйте displayWaveformLabels
, чтобы сравнить сетевой прогноз с заземляющими метками истины для одного сигнала ECG.
subplot(2,1,1) displayWaveformLabels(signalsTest{50}(1400:1900),labelsTest{50}(1400:1900)) title('Ground Truth') subplot(2,1,2) displayWaveformLabels(signalsTest{50}(1400:1900),predFsstTest{50}(1400:1900)) title('Predicted')
Этот пример показал, как предварительная обработка сигнала и анализ частоты времени могут улучшать производительность сегментации формы волны LSTM. Фильтрация полосы пропускания и основанный на Фурье synchosqueezing приводят к среднему улучшению через все выходные классы от 60% до более чем 85%.
[1] Макшарри, Патрик Э., и др. "Динамическая модель для генерации синтетических сигналов электрокардиограммы". IEEE® Transactions на Биоинженерии. Издание 50, № 3, 2003, стр 289–294.
[2] Laguna, Пабло, Рэймон Джейне и Пере Каминаль. "Автоматическое обнаружение контуров волны в мультиведущих сигналах ECG: Валидация с базой данных CSE". Компьютеры и Биомедицинское Исследование. Издание 27, № 1, 1994, стр 45–60.
[3] Голдбергер, Ари Л., Луис А. Н. Амараль, Леон Гласс, Джеффри М. Гаусдорф, Plamen Ch. Иванов, Роджер Г. Марк, Джозеф Э. Митус, Джордж Б. Муди, Чанг-Канг Пенг и Х. Юджин Стэнли. "PhysioBank, PhysioToolkit и PhysioNet: Компоненты Нового Ресурса Исследования для Комплексных Физиологических Сигналов". Циркуляция. Издание 101, № 23, 2000, стр e215–e220. [Циркуляция Электронные Страницы; http://circ.ahajournals.org/content/101/23/e215.full].
[4] Laguna, Пабло, Роджер Г. Марк, Ари Л. Голдбергер и Джордж Б. Муди. "База данных для Оценки Алгоритмов для Измерения QT и Других Интервалов Формы волны в ECG". Компьютеры в Кардиологии. Vol.24, 1997, стр 673–676.
[5] Sörnmo, Леиф и Пабло Лагуна. "Электрокардиограмма (ECG) обработка сигналов". Вайли Энкиклопедия Биоинженерии, 2006.
[6] Колер, B-U., Карстен Хенниг и Райнхольд Орглмайстер. "Принципы обнаружения программного обеспечения QRS". Разработка IEEE в Журнале Медицины и Биологии. Издание 21, № 1, 2002, стр 42–57.
[7] Salamon, Джастин и Хуан Пабло Белло. "Глубоко сверточные нейронные сети и увеличение данных для экологической звуковой классификации". Буквы Обработки сигналов IEEE. Издание 24, № 3, 2017, стр 279–283.