主要内容

利用长短期记忆网络对心电信号进行分类

这个例子展示了如何使用深度学习和信号处理对来自PhysioNet 2017挑战赛的心跳心电图(ECG)数据进行分类。特别地,这个例子使用了长短期记忆网络和时频分析。

简介

心电图记录一个人在一段时间内的心脏电活动。医生使用心电图直观地检测病人的心跳是正常还是不规则。

心房颤动(AFib)是一种不规则的心跳,发生在心脏的上室(心房)与下室(心室)的跳动不协调时。

本例使用了来自PhysioNet 2017挑战赛的心电数据[1]、[2]、[3.],下载网址为https://physionet.org/challenge/2017/.数据由一组以300hz采样的心电信号组成,并由一组专家分为四个不同的类别:正常(N)、AFib (a)、其他节律(O)和噪声记录(~)。这个例子展示了如何使用深度学习自动化分类过程。该程序探索了一个二元分类器,可以区分正常心电信号从信号显示AFib的迹象。

本例使用长短期记忆(LSTM)网络,这是一种循环神经网络(RNN),非常适合研究序列和时间序列数据。LSTM网络可以学习序列时间步长之间的长期依赖关系。LSTM层(lstmLayer(深度学习工具箱))可以向前看时间序列,而双向LSTM层(bilstmLayer(深度学习工具箱))可以从正反两个方向查看时间序列。本例使用双向LSTM层。

为了加速训练过程,请在带有GPU的机器上运行此示例。如果您的机器有GPU和并行计算工具箱™,那么MATLAB®自动使用GPU进行训练;否则,占用CPU。

加载和检查数据

运行ReadPhysionetData脚本,从PhysioNet网站下载数据,并生成mat文件(PhysionetData.mat),以适当的格式储存心电讯号。下载数据可能需要几分钟。使用只在以下情况下运行脚本的条件语句PhysionetData.mat当前文件夹中不存在。

如果~ isfile (“PhysionetData.mat”) ReadPhysionetData结束负载PhysionetData

加载操作将两个变量添加到工作区:信号而且标签信号是保存心电信号的单元阵列。标签是一个类别数组,其中保存了信号的对应地真值标签。

信号(1:5)
ans =5×1单元格数组{1×9000 double} {1×9000 double} {1×18000 double} {1×9000 double} {1×18000 double}
标签(1:5)
ans =5×1分类N N N a a

使用总结函数查看数据中包含了多少AFib信号和Normal信号。

总结(标签)
A 738n5050

生成信号长度的直方图。大多数信号有9000个样本长。

L = cellfun(@length,Signals);h =直方图(L);xticks (0:3000:18000);xticklabels (0:3000:18000);标题(“信号长度”)包含(“长度”) ylabel (“数”

可视化每个类的一个信号片段。AFib心跳间隔不规则,而正常心跳有规律。AFib心跳信号通常也缺乏P波,在正常心跳信号中,P波在QRS复合体之前跳动。正常信号图显示P波和QRS复波。

normal =信号{1};aFib =信号{4};Subplot (2,1,1) plot(normal)标题(“正常的节奏”xlim([4000,5200]) ylabel(“振幅(mV)”)文本(4330、150、“P”“HorizontalAlignment”“中心”)文本(4370、850、“QRS”“HorizontalAlignment”“中心”) subplot(2,1,2) plot(aFib)标题(心房纤维性颤动的xlim([4000,5200]) xlabel(“样本”) ylabel (“振幅(mV)”

为培训准备数据

在培训期间,trainNetwork函数将数据分割为小批量。然后,该函数在相同的小批处理中填充或截断信号,使它们都具有相同的长度。过多的填充或截断会对网络的性能产生负面影响,因为网络可能会根据添加或删除的信息错误地解释信号。

为避免过度填充或截断,请应用segmentSignals函数的心电信号,所以他们都是9000个样本长。该函数忽略小于9000个样本的信号。如果一个信号有超过9000个样本,segmentSignals将其分解为尽可能多的9000个样本段,并忽略剩余的样本。例如,一个18500个样本的信号变成两个9000个样本的信号,剩下的500个样本被忽略。

[信号,标签]= segmentSignals(信号,标签);

属性的前五个元素信号数组来验证每个条目现在是9000个样本长。

信号(1:5)
ans =5×1单元格数组{1×9000 double} {1×9000 double} {1×9000 double} {1×9000 double} {1×9000 double}

使用原始信号数据训练分类器

要设计分类器,请使用上一节中生成的原始信号。将信号分成训练集来训练分类器和测试集来测试分类器在新数据上的准确性。

使用总结函数表示AFib信号与正常信号的比值为718:4937,约为1:7。

总结(标签)
A 718 n 4937

因为大约7/8的信号是正常的,分类器会知道它可以通过简单地将所有信号分类为正常来实现较高的精度。为了避免这种偏差,可以通过复制数据集中的AFib信号来增加AFib数据,以便有相同数量的Normal和AFib信号。这种重复,通常称为过采样,是深度学习中使用的数据增强的一种形式。

根据它们的类别分割信号。

afibX =信号(标签==“一个”);afibY = Labels(标签==“一个”);normalX =信号(标签==“N”);normalY = Labels(标签==“N”);

下一步,使用dividerand将每个类的目标随机分为训练集和测试集。

[trainIndA,~,testIndA] = diverand (718,0.9,0.0,0.1);[trainIndN,~,testIndN] = dividerand(4937,0.9,0.0,0.1);XTrainA = afibX(trainIndA);YTrainA = afibY(trainIndA);XTrainN = normalX(trainIndN);YTrainN = normalY(trainIndN);XTestA = afibX(testIndA);YTestA = afibY(testIndA);XTestN = normalX(testIndN);YTestN = normalY(testIndN);

现在有646个AFib信号和4443个正常信号用于训练。为了实现每个类中相同数量的信号,使用前4438个Normal信号,然后使用repmat将第一个634 AFib信号重复七次。

测试有72个AFib信号和494个Normal信号。使用前490个正常信号,然后使用repmat将前70个AFib信号重复7次。默认情况下,神经网络在训练前随机打乱数据,确保相邻的信号并不都具有相同的标签。

XTrain = [repmat(XTrainA(1:634),7,1);XTrainN (1:4438)];YTrain = [repmat(YTrainA(1:634),7,1);YTrainN (1:4438)];XTest = [repmat(XTestA(1:70),7,1);XTestN (1:490)];YTest = [repmat(YTestA(1:70),7,1);YTestN (1:490);];

正常信号和AFib信号之间的分布现在在训练集和测试集中都是均匀平衡的。

总结(YTrain)
A 4438 n 4438
总结(欧美)
A 490 n 490

定义LSTM网络体系结构

LSTM网络可以学习序列数据时间步长之间的长期依赖关系。本例使用双向LSTM层bilstmLayer,因为它从前后两个方向观察序列。

因为每个输入信号都有一个维度,所以将输入大小指定为大小为1的序列。指定一个输出大小为100的双向LSTM层,并输出序列的最后一个元素。该命令指示双向LSTM层将输入的时间序列映射为100个特征,然后为全连接层准备输出。最后,指定两个类,包括大小为2的全连接层,然后是softmax层和classification层。

层= [...sequenceInputLayer (1) bilstmLayer (100“OutputMode”“最后一次”) fullyConnectedLayer(2) softmaxLayer分类层
2”BiLSTM BiLSTM与100个隐藏单元3”全连接2全连接层4”Softmax Softmax 5”分类输出crossentropyex

接下来指定分类器的训练选项。设置“MaxEpochs”到10,允许网络通过10次训练数据。一个“MiniBatchSize”Of 150指示网络一次查看150个训练信号。一个“InitialLearnRate”0.01有助于加快训练过程。指定一个“SequenceLength”将信号分解成更小的片段,这样机器就不会因为一次查看太多数据而耗尽内存。设置”GradientThreshold到1,通过防止梯度变得太大来稳定训练过程。指定“阴谋”作为“训练进步”生成随迭代次数增加而显示训练进度图形的图表。集“详细”来抑制与图中显示的数据相对应的表输出。如果你想看这张表,请设置“详细”真正的

本例使用自适应矩估计(ADAM)求解器。ADAM在rnn(如LSTMs)上的性能比默认的随机动量梯度下降(SGDM)求解器更好。

选项= trainingOptions(“亚当”...“MaxEpochs”10...“MiniBatchSize”, 150,...“InitialLearnRate”, 0.01,...“SequenceLength”, 1000,...“GradientThreshold”, 1...“ExecutionEnvironment”“汽车”...“阴谋”“训练进步”...“详细”、假);

培训LSTM网络

使用指定的训练选项和层结构训练LSTM网络trainNetwork.由于训练集很大,训练过程可能需要几分钟。

net = trainNetwork(XTrain,YTrain,图层,选项);

训练进度图的顶部子图表示训练精度,这是每个小批上的分类精度。当培训成功进行时,这个值通常会增加到100%。底部的子图显示了训练损失,这是每个小批上的交叉熵损失。当训练成功进行时,这个值通常会减小到零。

如果训练不收敛,图可能会在值之间振荡,而没有某种向上或向下的趋势。这种振荡意味着训练精度没有提高,训练损失没有减少。这种情况可能在训练开始时就发生,或者在训练精度得到初步提高后,图可能会停滞不前。在许多情况下,改变训练选项可以帮助网络实现收敛。减少MiniBatchSize或减少InitialLearnRate可能会导致更长的训练时间,但它可以帮助网络更好地学习。

分类器的训练精度在大约50%到60%之间振荡,在10个epoch结束时,它已经花了几分钟的时间来训练。

可视化训练和测试的准确性

计算训练精度,它表示分类器在其训练的信号上的精度。首先,对训练数据进行分类。

trainPred = category (net,XTrain,“SequenceLength”, 1000);

在分类问题中,混淆矩阵用于在一组已知真实值的数据上可视化分类器的性能。目标类是信号的真实标签,输出类是网络分配给信号的标签。坐标轴标签代表类别标签,AFib (A)和Normal (N)。

使用confusionchart命令来计算测试数据预测的总体分类精度。指定“RowSummary”作为“row-normalized”在行摘要中显示真阳性率和假阳性率。同时,指定“ColumnSummary”作为“column-normalized”在列摘要中显示阳性预测值和错误发现率。

LSTMAccuracy = sum(trainPred == YTrain)/ nummel (YTrain)*100
LSTMAccuracy = 61.7283
图confusionchart (YTrain trainPred,“ColumnSummary”“column-normalized”...“RowSummary”“row-normalized”“标题”“LSTM困惑表”);

现在用相同的网络对测试数据进行分类。

testPred =分类(net,XTest,“SequenceLength”, 1000);

计算测试精度,并将分类性能可视化为混淆矩阵。

LSTMAccuracy = sum(testPred == YTest)/ nummel (YTest)*100
LSTMAccuracy = 66.2245
图confusionchart(欧美、testPred“ColumnSummary”“column-normalized”...“RowSummary”“row-normalized”“标题”“LSTM困惑表”);

利用特征提取提高性能

从数据中提取特征有助于提高分类器的训练和测试精度。为了决定提取哪些特征,本示例采用了一种计算时频图像(如频谱图)的方法,并使用它们来训练卷积神经网络(cnn) [4]、[5]。

可视化每一种信号的频谱图。

Fs = 300;图次要情节(2,1,1);pspectrum(正常,fs,的谱图“TimeResolution”, 0.5)标题(“正常信号”次要情节(2,1,2);pspectrum (aFib fs,的谱图“TimeResolution”, 0.5)标题(“AFib信号”

由于本例使用LSTM而不是CNN,因此转换该方法使其适用于一维信号非常重要。时频矩从谱图中提取信息。每一个矩都可以作为一个一维特征输入到LSTM中。

探索时域中的两个TF矩:

  • 瞬时频率(instfreq

  • 谱熵(pentropy

instfreq函数估计信号随时间变化的频率,作为功率谱图的第一矩。该函数在时间窗口上使用短时傅里叶变换计算频谱图。在本例中,该函数使用255个时间窗口。函数的时间输出对应于时间窗口的中心。

可视化每一种信号的瞬时频率。

[instFreqA,tA] = instfreq(aFib,fs);[instFreqN,tN] = instfreq(normal,fs);图次要情节(2,1,1);情节(tN, instFreqN)标题(“正常信号”)包含(“时间(s)”) ylabel (瞬时频率的次要情节(2,1,2);instFreqA情节(tA)标题(“AFib信号”)包含(“时间(s)”) ylabel (瞬时频率的

使用cellfun申请instfreq函数到训练和测试集中的每个单元。

instfreqTrain = cellfun(@(x)instfreq(x,fs)',XTrain,“UniformOutput”、假);instfreqTest = cellfun(@(x)instfreq(x,fs)',XTest,“UniformOutput”、假);

谱熵测量信号的谱有多平坦。具有尖峰频谱的信号,如正弦波的和,具有较低的光谱熵。具有平坦频谱的信号,如白噪声,具有较高的光谱熵。的pentropy函数基于功率谱图估计谱熵。与瞬时频率估计的情况一样,pentropy使用255个时间窗口计算谱图。函数的时间输出对应于时间窗口的中心。

可视化每种类型信号的谱熵。

[pentropyA,tA2] = pentropy(aFib,fs);[pentropyN,tN2] = pentropy(normal,fs);图子图(2,1,1)图(tN2,pentropyN)标题(“正常信号”) ylabel (“谱熵”) subplot(2,1,2) plot(tA2,pentropyA)标题(“AFib信号”)包含(“时间(s)”) ylabel (“谱熵”

使用cellfun申请pentropy函数到训练和测试集中的每个单元。

pentropyTrain = cellfun(@(x)pentropy(x,fs)',XTrain,“UniformOutput”、假);pentropyTest = cellfun(@(x)pentropy(x,fs)',XTest,“UniformOutput”、假);

连接特征,这样新的训练和测试集中的每个单元都有两个维度,或两个特征。

XTrain2 = cellfun(@(x,y)[x;y],instfreqTrain,pentropyTrain,“UniformOutput”、假);XTest2 = cellfun(@(x,y)[x;y],instfreqTest,pentropyTest,“UniformOutput”、假);

可视化新输入的格式。每个单元不再包含一个9000个样本长的信号;现在它包含两个255个样本长的特征。

XTrain2 (1:5)
ans =5×1单元格数组{2×255 double} {2×255 double} {2×255 double} {2×255 double} {2×255 double}

数据标准化

瞬时频率和谱熵的均值相差近一个数量级。此外,瞬时频率平均值可能过高,使LSTM无法有效学习。当一个网络适合于具有大均值和大范围值的数据时,大输入可能会减慢网络的学习和收敛速度[6]。

意思是(instFreqN)
Ans = 5.5615
意思是(pentropyN)
Ans = 0.6326

使用训练集均值和标准偏差对训练集和测试集进行标准化。标准化,或z-评分,是在训练期间提高网络性能的一种流行方法。

XV = [XTrain2{:}];mu = mean(XV,2);sg = std(XV,[],2);XTrainSD = XTrain2;XTrainSD = cellfun(@(x)(x-mu)./sg,XTrainSD,“UniformOutput”、假);XTestSD = XTest2;XTestSD = cellfun(@(x)(x-mu)./sg,XTestSD,“UniformOutput”、假);

显示标准化的瞬时频率和谱熵的平均值。

instFreqNSD = XTrainSD{1}(1,:);pentropyNSD = XTrainSD{1}(2,:);意思是(instFreqNSD)
Ans = -0.3211
意思是(pentropyNSD)
Ans = -0.2416

修改LSTM网络架构

现在每个信号都有两个维度,有必要通过指定输入序列大小为2来修改网络架构。指定输出大小为100的双向LSTM层,并输出序列的最后一个元素。通过包含一个大小为2的全连接层,然后是一个softmax层和一个分类层来指定两个类。

层= [...sequenceInputLayer (2) bilstmLayer (100“OutputMode”“最后一次”) fullyConnectedLayer(2) softmaxLayer分类层
2 " BiLSTM BiLSTM带100个隐藏单元3 "全连接2 "全连接层4 " Softmax Softmax 5 "分类输出

指定培训选项。将最大epoch数设置为30,允许网络通过30次训练数据。

选项= trainingOptions(“亚当”...“MaxEpochs”30岁的...“MiniBatchSize”, 150,...“InitialLearnRate”, 0.01,...“GradientThreshold”, 1...“ExecutionEnvironment”“汽车”...“阴谋”“训练进步”...“详细”、假);

利用时频特征训练LSTM网络

使用指定的训练选项和层结构训练LSTM网络trainNetwork

net2 = trainNetwork(XTrainSD,YTrain,layers,options);

训练精度有很大提高。交叉熵损失趋向于0。此外,训练所需的时间减少,因为TF矩比原始序列短。

可视化训练和测试的准确性

使用更新后的LSTM网络对训练数据进行分类。将分类性能可视化为混淆矩阵。

trainPred2 = category (net2,XTrainSD);LSTMAccuracy = sum(trainPred2 == YTrain)/ nummel (YTrain)*100
LSTMAccuracy = 83.5962
图confusionchart (YTrain trainPred2,“ColumnSummary”“column-normalized”...“RowSummary”“row-normalized”“标题”“LSTM困惑表”);

利用更新后的网络对测试数据进行分类。绘制混淆矩阵以检查测试精度。

testPred2 = category (net2,XTestSD);LSTMAccuracy = sum(testPred2 == YTest)/ nummel (YTest)*100
LSTMAccuracy = 80.1020
图confusionchart(欧美、testPred2“ColumnSummary”“column-normalized”...“RowSummary”“row-normalized”“标题”“LSTM困惑表”);

结论

这个例子展示了如何使用LSTM网络建立一个分类器来检测ECG信号中的房颤。该程序使用过采样来避免分类偏差,当人们试图在主要由健康患者组成的人群中检测异常情况时,会出现这种分类偏差。使用原始信号数据训练LSTM网络,导致分类精度较差。对每个信号使用两个时频矩特征训练网络,可以显著提高分类性能,并减少训练时间。

参考文献

[1]基于短单导联心电图记录的房颤分类:2017年心脏病学挑战赛中的物理网络/计算。https://physionet.org/challenge/2017/

[2] Clifford, Gari,刘成宇,Benjamin Moody, Li-wei H. Lehman, Ikaro Silva, Qiao Li, Alistair Johnson和Roger G. Mark。“从短单导联心电图记录中进行房颤分类:2017年心脏病学挑战赛中的物理网络计算。”心脏病学计算(雷恩:IEEE)。Vol. 44, 2017, pp. 1-4。

[3]戈德伯格,a.l., L. A. N.阿马拉尔,L.格拉斯,J. M.豪斯多夫,P. Ch.伊万诺夫,R. G.马克,J. E.米耶图斯,G. B.穆迪,c . k。彭先生和斯坦利先生。PhysioBank, PhysioToolkit,和PhysioNet:复杂生理信号新研究资源的组成部分循环.第101卷,第23期,2000年6月13日,第e215-e220页。http://circ.ahajournals.org/content/101/23/e215.full

庞斯,乔迪,托马斯·利迪,泽维尔·塞拉。音乐驱动的卷积神经网络实验。第十四届基于内容的多媒体索引国际研讨会.2016年6月。

[5]王,D。“深度学习重塑助听器,”IEEE频谱《中国经济》2017年3月第3期,第32-37页。doi: 10.1109 / MSPEC.2017.7864754。

布朗利,杰森。如何在Python中为长短期记忆网络缩放数据.2017年7月7日。https://machinelearningmastery.com/how-to-scale-data-for-long-short-term-memory-networks-in-python/

另请参阅

功能

相关的话题