简介
人类的心电图活动可以作为远离基线信号的幅值序列来测量。对于单个正常心跳周期,ECG 信号可分为以下几种心跳形态 [1]:
P 波 - 表示心房去极化的 QRS 复波前的小偏移
QRS 复波 - 心跳的最大幅值部分
T 波 - 表示心室复极化的 QRS 复波后的小偏移
ECG 波形的这些区域的分割可作为基础测量数据用于评估人类心脏整体健康和异常状况 [2]。手动注释 ECG 信号的每个区域可能是一项乏味且耗时的任务。信号处理和深度学习方法有助于简化注释并自动对关注区域进行注释。
此示例使用来自公开可用的 QT 数据库的 ECG 信号 [3] [4]。这些数据由总共 105 名患者大约 15 分钟的 ECG 录音片段组成,采样率为 250 Hz。为了获得每个录音片段,检查人员将两个电极放置在患者胸部的不同位置,以产生双通道信号。该数据库提供由自动专家系统生成的信号区域标签 [2]。此示例旨在使用深度学习解决方案根据样本所在的区域为每个 ECG 信号样本提供标签。这种对信号中的关注区域加标签的过程通常称为波形分割。
为了训练深度神经网络来对信号区域分类,可以使用长短期记忆 (LSTM) 网络。此示例说明如何使用信号预处理方法和时频分析来提高 LSTM 分割性能。具体而言,该示例使用傅里叶同步压缩变换来表示 ECG 信号的非平稳行为。
下载并准备数据
105 个双通道 ECG 信号的每个通道由自动专家系统独立标注并独立处理,总共 210 个 ECG 信号,它们与区域标签一起存储在 210 个 MAT 文件中。这些文件可在以下位置获得:https://www.mathworks.com/supportfiles/SPT/data/QTDatabaseECGData.zip。
将数据文件下载到您的临时目录中,临时目录的位置由 MATLAB® 的 tempdir 命令指定。如果要将数据文件放在不同于 tempdir 的文件夹中,请在后续说明中更改目录名称。
% Download the data
dataURL = 'https://www.mathworks.com/supportfiles/SPT/data/QTDatabaseECGData1.zip';
datasetFolder = fullfile(tempdir,'QTDataset');
zipFile = fullfile(tempdir,'QTDatabaseECGData.zip');
if ~exist(datasetFolder,'dir')
websave(zipFile,dataURL);
unzip(zipFile,tempdir);
end
unzip 操作会在您的临时目录中创建 QTDatabaseECGData 文件夹,其中包含 210 个 MAT 文件。每个文件在变量 ecgSignal 中包含一个 ECG 信号,在变量 signalRegionLabels 中包含一个区域标签表。每个文件还在变量 Fs 中包含信号的采样率。在此示例中,所有信号的采样率均为 250 Hz。
创建一个信号数据存储来访问文件中的数据。此示例假设数据集已存储在临时目录中的 QTDatabaseECGData 文件夹下。如果不是这样,请更改下面代码中数据的路径。使用 SignalVariableNames 参数指定要从每个文件中读取的信号变量名称。
sds = signalDatastore(datasetFolder,'SignalVariableNames',["ecgSignal","signalRegionLabels"])
sds =
signalDatastore with properties:
Files:{
'/tmp/QTDataset/ecg1.mat';
'/tmp/QTDataset/ecg10.mat';
'/tmp/QTDataset/ecg100.mat'
... and 207 more
}
AlternateFileSystemRoots: [0×0 string]
ReadSize: 1
SignalVariableNames: ["ecgSignal" "signalRegionLabels"]
每次调用 read 函数时,数据存储都会返回一个包含 ECG 信号和区域标签表的二元素元胞数组。使用数据存储的 preview 函数,可以看到第一个文件的内容是长度为 225000 个采样的 ECG 信号和一个包含 3385 个区域标签的表。
data = preview(sds)
data=2×1 cell array
{225000×1 double}
{ 3385×2 table }
查看区域标签表的前几行,注意每行都包含区域范围索引和区域类值(P、T 或 QRS)。
head(data{2})
ans=8×2 table
ROILimits Value
__________ _____
83 117 P
130 153 QRS
201 246 T
285 319 P
332 357 QRS
412 457 T
477 507 P
524 547 QRS
使用 signalMask 对象可视化前 1000 个采样的标签。
M = signalMask(data{2});
plotsigroi(M,data{1}(1:1000))
通常的机器学习分类过程如下:
将数据库分成训练数据集和测试数据集。
使用训练数据集训练网络。
使用经过训练的网络对测试数据集进行预测。
用 70% 的数据对网络进行训练,用其余的 30% 对网络进行测试。
为了获得可重现的结果,请重置随机数生成器。使用 dividerand 函数获得随机索引来对文件进行乱序处理,使用 signalDatastore 的 subset 函数将数据分成训练数据存储和测试数据存储。
rng default
[trainIdx,~,testIdx] = dividerand(numel(sds.Files),0.7,0,0.3);
trainDs = subset(sds,trainIdx);
testDs = subset(sds,testIdx);
在此分割问题中,LSTM 网络的输入是 ECG 信号,输出是与输入信号长度相同的标签序列或标签掩膜。网络任务将用信号采样点所属区域的名称来标注每个信号采样点。因此,有必要将数据集中的区域标签变换为包含针对每个信号采样点的各个标签的序列。使用变换后的数据存储和 getmask 辅助函数来变换区域标签。getmask 函数添加一个标签类别 "n/a",用于标注不属于任何关注区域的样本。
type getmask.m
function outputCell = getmask(inputCell)
%GETMASK Convert region labels to a mask of labels of size equal to the
%size of the input ECG signal.
%
% inputCell is a two-element cell array containing an ECG signal vector
% and a table of region labels.
%
% outputCell is a two-element cell array containing the ECG