主要内容

小波时间散射心音图数据的分类

这个例子展示了如何将人类心音图(PCG)录音使用小波时间散射和支持向量机(SVM)分类器。金宝app心音图声录音的声音由心脏的收缩和舒张期阶段。心脏听诊继续发挥重要的诊断作用评估心脏健康。不幸的是,世界上许多地区缺乏足够数量的医务人员训练心脏听诊。因此,有必要开发可靠的自动解释心音图数据的方法。

这个示例使用小波散射特性PCG分类器。在小波散射,数据传播通过一系列的小波变换,非线性,平均生产低温度差的表示的数据。这些低温度差表示作为分类器的输入。这个例子是一个二元分类问题,每个PCG记录是“正常”或“不正常”。

关于术语的:在小波散射的上下文中,术语“时间窗”是指样品的数量将采样后得到的输出平滑操作。有关更多信息,请参见时间窗口

数据描述

这个示例使用心音图(PCG)数据从残疾人获得正常和不正常的心脏功能。数据集由3829录音,2575人与正常心脏功能和1254条记录的人不正常的心脏功能。每个记录长10000样品和2千赫采样。这是5秒的心音图数据。数据集是由使用的培训和验证数据在2016年心脏病挑战生理网计算[1][2]。

下载数据

第一步是下载的数据GitHub库。下载数据,点击代码并选择下载ZIP。保存文件physionet_phonocardiogram-main.zip在一个文件夹,你有写权限。说明对于这个示例假设您已经下载了文件到临时目录,(tempdir在MATLAB™)。修改后续说明压缩和加载数据如果您选择下载文件夹中的数据不同tempdir

该文件physionet_phonocardiogram-main.zip包含

  • PCG_Data.zip

  • README.md

和PCG_Data。zip包含

  • heartSoundData.mat

  • extrafiles.mat

  • Modified_physionet_data.txt

  • License.txt。

heartSoundData.mat拥有在本例中使用的数据和类标签。. txt文件,Modified_physionet_data。txt,生理网复制政策要求并提供源数据的归因以及每道信号的描述heartSoundData.mat在原始生理网数据对应一个文件。extrafiles.mat还包含源文件Modified_physionet_data归因和解释。txt文件。唯一的文件要求运行示例heartSoundData.mat

加载数据

如果你遵循下载指令在前面的小节中,输入以下命令解压两个存档文件。

解压缩(fullfile (tempdir,“physionet_phonocardiogram-main.zip”),tempdir)解压缩(fullfile (tempdir,“physionet_phonocardiogram-main”,“PCG_Data.zip”),fullfile (tempdir“PCG_Data”))

你解压后PCG_Data。zip文件,数据加载到MATLAB。

负载(fullfile (tempdir“PCG_Data”,“heartSoundData.mat”))

heartSoundData与两个字段是一个结构数组:数据数据是一个10000 -,- 3829矩阵,每一列是一个首选的记录。是3829 - 1分类数组的诊断标签,一个用于每一列的数据。因为这是一个二元分类问题,类是“正常”和“不正常”。如前所述,有2575个正常记录和1254年异常记录。等价于67.25%的例子数据来自人与正常心脏功能有32.75%来自人与心功能异常。您可以验证通过输入:

总结(heartSoundData.Classes)
正常2575异常1254
countcats (heartSoundData.Classes)。/笔(countcats (heartSoundData.Classes))
ans =2×10.6725 - 0.3275

小波散射网络

使用waveletScattering构造小波时间散射网络。设置不变规模匹配的信号长度。默认的散射网络有两个小波变换(滤波器)。第一个小波滤波器组有八个小波每八度。第二个过滤器银行有一个小波每八度。设置“OptimizePath”财产真正的

N = 1 e4;sn = waveletScattering (“SignalLength”N“InvarianceScale”N“OptimizePath”,真正的);

建立训练集和测试集

辅助功能,partition_heartsounds分区,3829年的观察,70%(2680)与1802年正常训练集和878异常。剩下的1149条记录(376年773正常和异常)举行的测试集预测。随机数生成器的种子内部的helper函数是可重复的结果。的代码partition_heartsounds和其他辅助函数中使用这个例子支持功能部分中给出的例子。金宝app

[trainData, testData trainLabels testLabels] =partition_heartsounds(70年,heartSoundData.Data heartSoundData.Classes);

你可以检查每个类的数量在训练集和测试集。

总结(trainLabels)
正常1802异常878
总结(testLabels)
正常773异常376

注意训练集和测试集的分区,这样的比例“正常”和“不正常”记录的训练集和测试集的比例是一样的整体数据。你可以用下面的证实了这一点。

countcats (trainLabels)。/笔(countcats (trainLabels))
ans =2×10.6724 - 0.3276
countcats (testLabels)。/笔(countcats (testLabels))
ans =2×10.6728 - 0.3272

散射特性

获得2680的散射变换训练集录音。多元时间序列,散射变换假设每一列是一个单独的信号。使用“日志”选项来获得散射系数的自然对数。

trainData scat_features_train = featureMatrix (sn,“转换”,“日志”);

对于给定的散射参数,scat_features_train是279 - 5 - 2680矩阵。有279 5散射散射路径和windows的2680信号。为了通过SVM分类器,重塑的张量为13400 - 279矩阵每一行代表一个单一的散射窗口在279年散射路径。总行数等于5的产品和2680(训练数据的记录数)。

Nseq =大小(scat_features_train, 2);scat_features_train =排列(scat_features_train [2 3 1]);scat_features_train =重塑(scat_features_train,大小(scat_features_train 1) *大小(scat_features_train, 2), []);

重复这个过程的测试数据。

testData scat_features_test = featureMatrix (sn,“转换”,“日志”);scat_features_test =排列(scat_features_test [2 3 1]);scat_features_test =重塑(scat_features_test,大小(scat_features_test 1) *大小(scat_features_test, 2), []);

这里我们复制标签,这样我们有一个标签为每个散射的时间窗口。

[sequence_labels_train, sequence_labels_test] =createSequenceLabels_heartsounds (Nseq trainLabels testLabels);

支持向量机的训练数据。在这个例子中,我们使用一个三次多项式的内核。拟合后的支持向量机训练数据,我们执行一个5倍交叉验证对训练数据来估计泛化误差。这里每个散射窗口单独分类。

rng默认的;classificationSVM = fitcsvm (scat_features_train,sequence_labels_train,“KernelFunction”,多项式的,“PolynomialOrder”3,“KernelScale”,“汽车”,“BoxConstraint”, 1“标准化”,真的,“类名”分类({“正常”,“异常”}));kfoldmodel = crossval (classificationSVM,“KFold”5);

计算损失的比例和显示混淆矩阵。

predLabels = kfoldPredict (kfoldmodel);损失= kfoldLoss (kfoldmodel) * 100;流(“损失百分比% 2.2 f \ n”、损失);
损失是0.96%
精度= 100 -损失;流(“精度是% 2.2 f % \ n”、准确性);
精度是99.04%
confmatCV = confusionchart (sequence_labels_train predLabels);

注意,每次散射网络结果在大约99%的准确率窗口单独分类。然而,性能实际上是比这个值,因为我们有五个散射windows /记录和99%的准确率分别是基于分类所有窗口。在这种情况下,使用一个多数票获得每记录一个类任务。类对应于模式的选票投票5个窗户。如果没有找到独特的模式,helperMajorityVote散射的窗口设置为分类“NoUniqueMode”来表示一个分类错误。这导致了混乱中的一个额外的列矩阵。

类=分类({“异常”,“正常”});ClassVotes = helperMajorityVote (predLabels、trainLabels、类);CVaccuracy =总和(eq (ClassVotes trainLabels))。/元素个数(trainLabels) * 100;流(“真正的交叉验证的准确性是% 2.2 f %。\ n ',CVaccuracy);
真正的交叉验证的准确性为99.89%。

显示多数投票分类混淆矩阵。

cmCV = confusionchart (trainLabels ClassVotes);

交叉验证的准确性的训练数据是99.89%。有两个正常记录,并被错误地归类为不正常。一个异常记录属于正常水平。

使用支持向量机模型适合的训练数据进行类预测了测试数据。

predTestLabels =预测(classificationSVM scat_features_test);

确定测试集上的预测精度使用多数投票。

ClassVotes = helperMajorityVote (predTestLabels、testLabels、类);testaccuracy =总和(eq (ClassVotes testLabels))。/元素个数(testLabels) * 100;流(测试精度是% 2.2 f %。\ n ',testaccuracy);
测试精度为91.82%。
cmt = confusionchart (testLabels ClassVotes);

1149年的测试记录,大约92%被正确归类为“正常”或“不正常”。773年的正常PCG录音测试集,732被正确分类。376年的异常记录在测试集,323被正确分类。

精度、召回和F1的分数

在分类任务中,一个类的精度是正确的积极成果的数量除以数量的积极成果。换句话说,所有的记录,分类器分配给定的标签,比例实际上属于类。召回的定义是正确的标签的数量除以标签对于一个给定的类的数量。具体来说,属于一个类的所有记录,什么比例我们作为这个类的分类标签。分类器判断的准确性,你最好想好精度和召回。例如,假设我们有一个分类器,标记每个PCG记录为异常。我们的回忆异常类将为100%。所有记录属于异常类可能会异常的标签。然而,精度很低。因为我们的分类器标记所有记录异常,会有2575在这种情况下,假阳性的精度1254/3829,或32.75%。 The F1 score is the harmonic mean of precision and recall and provides a single metric that summarizes the classifier performance in terms of both recall and precision. The helper function,helperF1heartSounds、计算精度、召回和F1分数为测试集上的分类结果表中,并返回结果。

PRTable = helperF1heartSounds (cmTest.NormalizedValues);disp (PRTable)
精密召回F1_Score _____ ______月______异常正常93.248 94.696 93.967 88.736 85.904 87.297

在这种情况下,异常和正常组织的F1分数确认我们的模型具有良好的精度和召回。在二进制分类简单确定精度和召回直接从混淆矩阵。看到这,情节混淆矩阵又方便。

cmt = confusionchart (testLabels ClassVotes);

召回的异常类是异常记录的数量确认为异常,即进入第二行第二列的混淆矩阵的总和除以条目在第二行。精密的异常类是真正的异常记录总数的比例异常的识别分类器。对应于第二行第二列中的条目的混淆矩阵之和除以第二列的条目。F1的调和平均数是分数。

RecallAbnormal = cmTest.NormalizedValues(2, 2) /笔(cmTest.NormalizedValues (2:));PrecisionAbnormal = cmTest.NormalizedValues(2, 2) /笔(cmTest.NormalizedValues (:, 2));F1Abnormal = harmmean ([RecallAbnormal PrecisionAbnormal]);流(' RecallAbnormal = % 2.3 f \ nPrecisionAbnormal = % 2.3 f \ nF1Abnormal = % 2.3 f \ n ',100 * 100 * RecallAbnormal PrecisionAbnormal, 100 * F1Abnormal);
RecallAbnormal = 85.904 PrecisionAbnormal F1Abnormal = 87.297 = 88.736

重复以上为正常类。

RecallNormal = cmTest.NormalizedValues(1,1) /笔(cmTest.NormalizedValues (1:));PrecisionNormal = cmTest.NormalizedValues(1,1) /笔(cmTest.NormalizedValues (: 1));F1Normal = harmmean ([RecallNormal PrecisionNormal]);流(' RecallNormal = % 2.3 f \ nPrecisionNormal = % 2.3 f \ nF1Normal = % 2.3 f \ n ',100 * 100 * RecallNormal PrecisionNormal, 100 * F1Normal);
RecallNormal = 94.696 PrecisionNormal F1Normal = 93.967 = 93.248

总结

这个例子使用小波时间散射强劲识别人类正常心音图录音或异常的二元分类问题。小波散射只需要一个参数的规范,规模不变的长度,为了生产的低温度差表示PCG数据,使得支持向量机分类器精确模型两组之间的差异。金宝app小波散射金宝app的支持向量机分类器能够实现性能优越的精度和召回两组尽管显著不平衡数量的正常和异常PCG录音在训练集和测试集。

引用

  1. 不,a . L。,L. A. N. Amaral, L. Glass, J. M. Hausdorff, P. Ch. Ivanov, R. G. Mark, J. E. Mietus, G. B. Moody, C.-K. Peng, and H. E. Stanley. "PhysioBank, PhysioToolkit, and PhysioNet: Components of a New Research Resource for Complex Physiologic Signals".循环。23号卷。101年,2000年6月13日,pp. e215-e220。http://circ.ahajournals.org/content/101/23/e215.full

  2. 刘等人。“一个开放的访问数据库心音评估算法”。生理测量。37卷,12号,2016年11月21日,2181 - 2213页。https://www.ncbi.nlm.nih.gov/pubmed/27869105

金宝app支持功能

partition_heartsounds创建指定的比例组成的训练集和测试集的数据。函数还保留了异常的比例在每组和正常PCG录音。

函数[trainData, testData trainLabels testLabels] = partition_heartsounds (percent_train_split、数据标签)%这个函数只支持小波的散射金宝app%的心音图分类数据的例子。它可能改变或%在将来发布的版本中移除。%的标签在心音数据并不是连续的。percent_train_split = percent_train_split / 100;%每一列是一个观察NormalData =数据(:,标签= =“正常”);AbnormalData =数据(:,标签= =“异常”);LabelsNormal =标签(标签= =“正常”);LabelsAbnormal =标签(标签= =“异常”);Nnormal =大小(NormalData, 2);Nabnormal =大小(AbnormalData, 2);num_train_normal =圆(percent_train_split * Nnormal);num_train_abnormal =圆(percent_train_split * Nabnormal);rng默认的;Pnormal = randperm (Nnormal num_train_normal);Pabnormal = randperm (Nabnormal num_train_abnormal);notPnormal = setdiff (1: Nnormal, Pnormal);notPabnormal = setdiff (1: Nabnormal, Pabnormal);trainNormalData = NormalData (:, Pnormal);trainNormalLabels = LabelsNormal (Pnormal);trainAbnormalData = AbnormalData (:, Pabnormal);trainAbnormalLabels = LabelsAbnormal (Pabnormal);testNormalData = NormalData (:, notPnormal); testNormalLabels = LabelsNormal(notPnormal); testAbnormalData = AbnormalData(:,notPabnormal); testAbnormalLabels = LabelsAbnormal(notPabnormal); trainData = [trainNormalData trainAbnormalData]; trainData = (trainData-mean(trainData))./std(trainData,1); trainLabels = [trainNormalLabels; trainAbnormalLabels]; testData = [testNormalData testAbnormalData]; testData = (testData-mean(testData))./std(testData,1); testLabels = [testNormalLabels; testAbnormalLabels];结束

createSequenceLabels_heartsounds为散射小波时间序列创建类标签。

函数[sequence_labels_train, sequence_labels_test] = createSequenceLabels_heartsounds (Nseq、trainLabels testLabels)%这个函数只支持小波的散射金宝app%的心音图分类数据的例子。它可能改变或%在将来发布的版本中移除。Ntrain =元素个数(trainLabels);Nseq trainLabels = repmat (trainLabels ', 1);sequence_labels_train =重塑(trainLabels Nseq * Ntrain 1);元=元素个数(testLabels);Nseq testLabels = repmat (testLabels ', 1);sequence_labels_test =重塑(testLabels nt * Nseq 1);结束

helperMajorityVote实现多数投票支持基于模式分类。如果没有独特的模式存在,投票NoUniqueMode返回,以确保一个分类错误记录。

函数[ClassVotes, ClassCounts] = helperMajorityVote (predLabels、origLabels类)%这个函数支持小波工具箱的例子。金宝app它可能变化百分比或在将来的版本中被删除。%进行分类数组如果标签还没有直言predLabels =分类(predLabels);origLabels =分类(origLabels);%预计predLabels和origLabels分类向量npr =元素个数(predLabels);Norig =元素个数(origLabels);Nwin = npr / Norig;predLabels =重塑(predLabels Nwin Norig);ClassCounts = countcats (predLabels);[mxcount, idx] = max (ClassCounts);ClassVotes =类(idx);%检查任何关系的最大值,并确保它们标记为%如果模式出现不止一次错误modecnt = modecount (ClassCounts mxcount);ClassVotes (modecnt > 1) =分类({“NoUniqueMode”});ClassVotes = ClassVotes (:);% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -函数modecnt = modecount (ClassCounts mxcount) modecnt =正(大小(ClassCounts, 2), 1);数控= 1:尺寸(ClassCounts, 2) modecnt (nc) = histc (ClassCounts(:,数控),mxcount (nc));结束结束% EOF结束

helperF1heartSounds计算精度、召回和F1分数为分类器的结果。

函数PRTable = helperF1heartSounds (confmat)%这个函数只支持小波的散射金宝app%的心音图分类数据的例子。它可能改变或%在将来发布的版本中移除。precisionAB = confmat(2, 2) /笔(confmat (:, 2)) * 100;precisionNR = confmat(1,1) /笔(confmat (: 1)) * 100;recallAB = confmat(2, 2) /笔(confmat (2:)) * 100;recallNR = confmat(1,1) /笔(confmat (1:)) * 100;F1AB = 2 * (precisionAB * recallAB) / (precisionAB + recallAB);F1NR = 2 * (precisionNR * recallNR) / (precisionNR + recallNR);% MATLAB构建一个表来显示结果。PRTable = array2table ([precisionAB recallAB F1AB;precisionNR recallNR F1NR),“VariableNames”,{“精度”,“回忆”,“F1_Score”},“RowNames”,{“异常”,“正常”});结束

另请参阅

相关的例子

更多关于