深度学习

理解和使用深度学习网络

用LSTM网络对心电信号进行分类

今天我想重点讲一个深度学习的信号处理应用。这个例子,来自信号处理工具箱文档,展示了如何使用深度学习和信号处理对来自PhysioNet 2017挑战赛的心跳心电图数据进行分类。特别地,该示例使用长短期记忆(LSTM)网络和时频分析。这个例子需要Neural Network Toolbox™。

内容

介绍

心电图记录了一段时间内一个人心脏的电活动。医生用心电图来直观地检测病人的心跳是正常还是不规则。心房纤颤(AFib)是一种不规则的心跳,当心脏的上腔室(心房)与下腔室(心室)的跳动不协调时发生。本例使用了来自PhysioNet 2017 Challenge[1],[2],[3]的心电数据https://physionet.org/challenge/2017/.这些数据由一组以300赫兹采样的心电信号组成,由一组专家分为四类:正常(N)、非正常(a)、其他节律(O)和噪声记录(~)。这个例子展示了如何使用深度学习自动化分类过程。该程序探索了一种可以区分正常心电信号和显示AFib信号的二值分类器。这个例子使用了长短期记忆(LSTM)网络,这是一种非常适合研究序列和时间序列数据的递归神经网络(RNN)。LSTM网络可以学习序列时间步长之间的长期依赖关系。LSTM层(lstmLayer)可以正向查看时间序列,而双向LSTM层(bilstmLayer)可以从正反两个方向看时间序列。这个例子使用了一个双向LSTM层。为了加速训练过程,请在带有GPU的机器上运行此示例。如果您的机器有GPU和并行计算工具箱™,那么MATLAB®自动使用GPU进行训练;否则,使用CPU。

加载并检查数据

运行ReadPhysionetData脚本从PhysioNet网站下载数据,并生成一个MAT-file (PhysionetData.mat),其中包含适当格式的心电信号。下载数据可能需要几分钟。
ReadPhysionetData负载PhysionetData
加载操作将两个变量添加到工作区:信号标签信号是保存心电信号的细胞阵列。标签是一个类别数组,其中保存信号的相应地真值标签。
信号(1:5)标签(1:5)
ans = 5×1 cell array {1×9000 double} {1×9000 double} {1×18000 double} {1×9000 double} {1×18000 double} ans = 5×1 categorical array N N N A A
使用总结函数中有738个AFib信号和5050个Normal信号。
总结(标签)
A 738 n 5050
生成信号长度的直方图。注意,大多数信号都是9000个样本长。
L = cellfun (@length,信号);h =直方图(左);xticks (0:3000:18000);xticklabels (0:3000:18000);标题(“信号长度”)包含(“长度”) ylabel (“数”
可视化来自每个类的一个信号的片段。AFib的心跳间隔是不规则的,而正常的心跳是有规律的。AFib心跳信号也经常缺乏P波,它在正常心跳信号的QRS复合体之前跳动。正常信号的图显示了P波和QRS波复合体。
正常={1}信号;aFib ={4}信号;次要情节(2,1,1)情节(正常的)标题(“正常的节奏”) xlim((4000、5200))ylabel (“振幅(mV)”)文本(4330、150、“P”“HorizontalAlignment”“中心”)文本(4370、850、“QRS”“HorizontalAlignment”“中心”) subplot(2,1,2) plot(aFib) title(心房纤维性颤动的) xlim((4000、5200))包含(“样本”) ylabel (“振幅(mV)”

准备培训数据

在培训期间,trainNetwork函数将数据分割为小批量。然后,该函数在同一小批量中填充或截断信号,使它们具有相同的长度。过多的填充或截断会对网络的性能产生负面影响,因为网络可能会根据添加或删除的信息错误地解释信号。为避免过度填充或截断,请应用segmentSignals功能,所以它们都是9000个样本长。该功能忽略小于9000个样本的信号。如果一个信号有超过9000个样本,segmentSignals将其分解成尽可能多的9000个样本片段,并忽略其余的样本。例如,一个有18500个样本的信号变成了两个有9000个样本的信号,剩下的500个样本被忽略。
[信号,标签]= segmentSignals(信号,标签);
查看|Signals|数组的前5个元素,以验证每个条目现在是9000个样本长。
信号(1:5)
Ans = 5×1 cell array {1×9000 double} {1×9000 double} {1×9000 double} {1×9000 double} {1×9000 double}

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

要设计分类器,请使用前一节中生成的原始信号。将信号分割为训练集来训练分类器和测试集来测试分类器对新数据的准确性。使用总结函数显示有718个AFib信号和4937个Normal信号,比例为1:7。
总结(标签)
A 718 n 4937
由于87.3%的信号是Normal,分类器会知道,只要将所有信号都分类为Normal,就可以达到较高的准确率。为了避免这种偏差,通过在数据集中复制AFib信号来增加AFib数据,使正常信号和AFib信号的数量相同。这种重复,通常称为过采样,是深度学习中使用的数据增强的一种形式。根据信号的类别来划分。
afibX(标签= = =信号“一个”);afibY =标签(标签= =“一个”);normalX(标签= = =信号“N”);= = =饱和标签(标签“N”);
下一步,使用dividerand将每个班级的目标随机划分为训练集和测试集。
[trainIndA, ~, testIndA] = dividerand(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 =饱和(trainIndN);XTestA = afibX (testIndA);YTestA = afibY (testIndA);XTestN = normalX (testIndN);YTestN =饱和(testIndN);
目前训练有639个AFib信号和4441个Normal信号。要在每个类中实现相同数量的信号,首先使用4438个Normal信号,然后使用repmat将前634个AFib信号重复七次。用于测试的有71个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)];欧美= [repmat (YTestA(1:70), 7日,1);YTestN (1:490);];
在训练集中和测试集中,Normal和AFib信号之间的分布现在是均匀平衡的。
摘要(YTrain)摘要(欧美)
A 4438 n 4438 A 490 n 490

定义LSTM网络架构

LSTM网络可以学习序列数据时间步长之间的长期依赖关系。本例使用双向LSTM层bilstmLayer,因为它在前后两个方向上都观察序列。因为每个输入信号都有一个维度,所以指定输入大小为大小为1的序列。指定一个输出大小为100的双向LSTM层并输出序列的最后一个元素。该命令指示双向LSTM层将输入时间序列映射为100个特性,然后为完全连接层准备输出。最后,通过包含大小为2的完全连接层,然后是softmax层和分类层来指定两个类。
层= [...sequenceInputLayer (1) bilstmLayer (100“OutputMode”“最后一次”(2) softmaxLayer classificationLayer
Layer = 5x1 Layer array with layers: 1 '' Sequence Input Sequence Input with 1 dimensions 2 '' BiLSTM BiLSTM with 100 hidden units 3 '' Fully Connected 2 Fully Connected Layer 4 '' Softmax Softmax 5 '' Classification Output crossentropyex
接下来为分类器指定训练选项。将'|MaxEpochs|'设置为10,以允许网络通过训练数据10次。'|MiniBatchSize|'值为150,指示网络一次查看150个训练信号。'|InitialLearnRate|'的0.01有助于加快训练过程。指定一个“SequenceLength”将信号分解成更小的片段,这样机器就不会因为一次查看过多的数据而耗尽内存。将'|GradientThreshold|'设置为1,以防止梯度变得过大,从而稳定训练过程。指定“阴谋”作为“训练进步”生成随着迭代次数增加而显示训练进度的图形。设置“|详细|”禁止与图中显示的数据对应的表输出。如果你想看这张桌子,就去“详细”真正的.本例使用自适应矩估计(ADAM)求解器。ADAM在lstm这样的递归神经网络(RNNs)中比默认的SGDM (SGDM)求解器表现更好。
选择= trainingOptions (“亚当”...“MaxEpochs”10...“MiniBatchSize”, 150,...“InitialLearnRate”, 0.01,...“SequenceLength”, 1000,...“GradientThreshold”, 1...“阴谋”“训练进步”...“详细”、假);

培训LSTM网络

使用指定的训练选项和层架构对LSTM网络进行训练trainNetwork.由于训练集很大,训练过程可能需要几分钟。
网= trainNetwork (XTrain、YTrain层,选择);
训练进度图的顶部子图表示训练准确率,即每个小批上的分类准确率。当培训成功进行时,这个值通常会增加到100%。底部的子图显示了训练损失,这是每个小批上的交叉熵损失。当训练成功进行时,这个值通常会降至零。如果训练不收敛,图可能会在值之间振荡,而不会朝着某个向上或向下的方向。这种振荡意味着训练精度没有提高,训练损失没有减少。这种情况可能在训练开始时就出现,或者在训练准确性初步提高后,情节可能会趋于平稳。在许多情况下,改变训练选项可以帮助网络实现收敛。减少MiniBatchSize |或递减|InitialLearnRate可能会导致更长的训练时间,但它可以帮助网络更好地学习。分类器的训练精度在50%到60%之间波动,在10个纪元结束时,它已经花费了几分钟的时间来训练。

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

计算训练准确率,它表示分类器对所训练信号的准确率。首先,对训练数据进行分类。
XTrain trainPred =分类(净,“SequenceLength”, 1000);
在分类问题中,混淆矩阵用于可视化分类器在一组已知真值的数据上的性能。目标类是信号的地面真实标签,输出类是网络分配给信号的标签。轴上的标签代表类标签,AFib (A)和Normal (N)。绿色的单元格代表正确分类的信号,红色的单元格代表错误分类的信号。浅灰色的单元格提供行和列摘要。右下角的单元格显示总体精度。
plotconfusion (YTrain’,trainPred’,“训练的准确性”
混淆矩阵显示,81.7%的ground-truth AFib信号被正确分类为AFib, 31.1%的ground-truth Normal信号被正确分类为Normal。此外,54.2%的AFib信号实际上是AFib, 63.0%的Normal信号实际上是Normal。整体训练准确率为56.4%。现在对测试数据进行分类。
XTest testPred =分类(净,“SequenceLength”, 1000);
计算测试准确率,表示分类器对新信号的准确率。
plotconfusion(欧美’,testPred’,的测试精度
这个混淆矩阵类似于训练混淆矩阵。总体检测准确率为55.8%。

通过特征提取提高性能

从数据中提取特征有助于提高分类器的训练和测试精度。为了确定要提取哪些特征,本例采用了一种计算时频图像(如光谱图)的方法,并使用它们来训练卷积神经网络(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(正常,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(正常,fs);图subplot(2,1,1) plot(tN2,pentropyN) title(“正常信号”) ylabel (“谱熵”) subplot(2,1,2) plot(tA2,pentropyA) title(“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 cell array {2×255 double} {2×255 double} {2×255 double} {2×255 double} {2×255 double}

标准化的数据

瞬时频率和谱熵的平均值几乎相差一个数量级。此外,瞬时频率均值可能过高,导致LSTM无法有效学习。当网络拟合的数据均值大、取值范围大时,大的输入会减慢网络[6]的学习和收敛速度。
的意思(instFreqN) (pentropyN)
Ans = 5.5615 Ans = 0.6326
使用训练集均值和标准偏差对训练集和测试集进行标准化。标准化,或z评分,是一种在训练中提高网络性能的流行方法。
十五= [XTrain2 {}):;μ=意味着(十五,2);sg =性病(十五,[],2);XTrainSD = XTrain2;XTrainSD = cellfun (@ (x)(即xμ)。/ sg, XTrainSD,“UniformOutput”、假);XTestSD = XTest2;XTestSD = cellfun (@ (x)(即xμ)。/ sg, XTestSD,“UniformOutput”、假);
显示了标准化瞬时频率和谱熵的方法。
instFreqNSD = XTrainSD {1} (1:);pentropyNSD = XTrainSD {1} (2:);的意思(instFreqNSD) (pentropyNSD)
Ans = -0.3202

修改LSTM网络结构

既然每个信号都有两个维度,就有必要通过指定输入序列大小为2来修改网络结构。指定一个输出大小为100的双向LSTM层,并输出序列的最后一个元素。指定两个类,包括大小为2的完全连接层,然后是softmax层和分类层。
层= [...sequenceInputLayer (2) bilstmLayer (100“OutputMode”“最后一次”(2) softmaxLayer classificationLayer
Layer = 5x1 Layer array with layers: 1 " Sequence Input Sequence Input with two dimensions 2 " BiLSTM BiLSTM with 100 hidden units 3 " Fully Connected 2 Fully Connected Layer 4 " Softmax Softmax 5 " Classification Output crossentropyex
指定培训选项。设置最大纪元数为30,允许网络通过30次训练数据。
选择= trainingOptions (“亚当”...“MaxEpochs”30岁的...“MiniBatchSize”, 150,...“InitialLearnRate”, 0.01,...“GradientThreshold”, 1...“阴谋”“训练进步”...“详细”、假);

用时频特征训练LSTM网络

使用指定的训练选项和层架构对LSTM网络进行训练trainNetwork
net2 = trainNetwork (XTrainSD、YTrain层,选择);
训练的准确率有了很大的提高,现在已经超过了90%。交叉熵损失趋向于0。此外,由于TF矩比原始序列短,训练所需的时间也减少了。

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

对培训数据进行分类。绘制混淆矩阵以检验训练的准确性。整体训练准确率为95.8%。96.8%的AFib信号被正确分类为AFib, 94.7%的Normal信号被正确分类为Normal。
trainPred2 =分类(net2 XTrainSD);plotconfusion (YTrain’,trainPred2’,“训练的准确性”
对测试数据进行分类。绘制混淆矩阵以检查测试的准确性。总体检测精度为93.2%。94.3%的AFib信号被正确分类为AFib, 92.0%的Normal信号被正确分类为Normal。
testPred2 =分类(net2 XTestSD);plotconfusion(欧美’,testPred2’,的测试精度

结论

这个例子展示了如何使用LSTM网络构建分类器来检测心电信号中的心房颤动。该程序使用过采样,以避免在主要由健康患者组成的人群中检测异常情况时发生的分类偏差。使用原始信号数据对LSTM网络进行训练,分类精度较差。利用每个信号的两个时频矩特征对网络进行训练,显著地提高了分类性能,同时减少了训练时间。

参考文献

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

[2] Clifford, Gari, Chengyu Liu, Benjamin Moody, Li-wei H. Lehman, Ikaro Silva, Qiao Li, Alistair Johnson, Roger G. Mark。基于单导联心电图记录的心房颤动分类:物理网络计算在心脏病学中的挑战2017计算在心脏病学(雷恩:IEEE)。2017年第44卷(印刷中)。

A. L. Goldberger, A. L. A. N. Amaral, L. Glass, J. M. Hausdorff, P. Ch. Ivanov, R. G. Mark, J. E. miietus, G. B. Moody, C.-K。彭,还有h·e·斯坦利。“PhysioBank, PhysioToolkit和PhysioNet:复杂生理信号新研究资源的组成部分”。循环.Vol. 101, No. 23, 13 June 2000, pp. 215$-$e220。< http://circ.ahajournals.org/content/101/23/e215.full

[4] Pons Jordi Thomas Lidy和Xavier Serra。“实验音乐驱动的卷积神经网络”。第十四届基于内容的多媒体索引国际研讨会.2016年6月。

[5], D。“深度学习彻底改造了助听器,”IEEE频谱$-$37。doi: 10.1109 / MSPEC.2017.7864754。

[6] Brownlee,杰森。如何在Python中扩展长短期内存网络的数据.2017年7月7日。https://machinelearningmastery.com/how-to-scale-data-for-long-short-term-memory-networks-in-python/

本示例的实用函数

函数[signalsOut, labelsOut] = segmentSignals(signalsIn,labelsIn)%SEGMENTSIGNALS使得输入数组中的所有信号都为9000样本长targetLength = 9000;signalsOut = {};labelsOut = {};idx = 1:numel(signalsIn) x = signalsIn{idx};y = labelsIn (idx);确保列向量x = x (:);%计算信号中targetlength样本块的个数numSigs =地板(长度(x) / targetLength);如果numSigs = = 0继续结束%截断为targetLength的倍数x = x (1: numSigs * targetLength);%创建一个和targetLength信号一样多的矩阵M =重塑(x, targetLength numSigs);%重复numsig标签次数y = repmat (y, [numSigs, 1]);%垂直连接到单元格数组signalsOut = [signalsOut;mat2cell (M。”(numSigs, 1)));% #好< AGROW >labelsOut = [labelsOut;cellstr (y)];% #好< AGROW >结束labelsOut =分类(labelsOut);结束




发布与MATLAB®R2017b

|
  • 打印
  • 发送电子邮件

评论

要留下评论,请点击在这里登录到您的MathWorks帐户或创建一个新帐户。