信息速览
AAMI EC13 是一份关于床旁心电监护仪、心率计与报警系统的国家标准,编号里的 EC 指 Electrocardiograph。PhysioNet 上同名的那份数据,是它配套的测试波形:十条 WFDB 记录,每条一路心电,720 Hz 采样、12 位分辨率,整个包未压缩只有 1.1 MB。
它和一般数据集的关系是反过来的。别的数据集你问「它准不准」,答案取决于采集质量、标注一致性与人群代表性;这里你问「它该被判成什么」,答案写在标准条款里——某段波形出现后必须在这一秒数内报警,这是合规要求,不是从数据里统计出来的结论。所以它的价值不在样本量,而在于它是少数几种「正确答案不来自数据本身」的资源。
本文讲三件事:监护算法与诊断算法是两件不同的事;为什么合成波形反而是这类测试的正确选择;以及「在 AAMI 测试上通过」与「在 MIMIC 上 99%」为什么完全是两回事。一屏速览见下表。
| 维度 | 内容 |
|---|---|
| 中文名 | ANSI/AAMI EC13 心电监护测试波形 |
| 英文名 | ANSI/AAMI EC13 Test Waveforms |
| 制定方 | 美国医疗器械促进协会(AAMI) |
| 托管方 | PhysioNet(MIT 计算生理学实验室) |
| 发布版本 | 1.0.0,2003 年 1 月 3 日 |
| 记录数 | 10 条(Fig.3 组 4 条,Fig.4 组 6 条) |
| 采样率 | 720 Hz,12 位分辨率 |
| 单通道 | 是,每条记录仅一路 ECG |
| 记录长度 | 约 45 秒至 91 秒(按 720 Hz 折算) |
| 总未压缩体量 | 1.1 MB |
| 文件格式 | WFDB(.dat + .hea 成对) |
| 波形来源 | 合成与真实混合,比例未逐条公开 |
| 判读依据 | 标准正文 5.1.2.1 节 (e)(g) 段(需付费) |
| 数据许可 | ODC-BY 1.0 |
| 标准文本 | AAMI 出售,不随数据开放 |
| 配套工具 | WFDB 软件包、Matlab/Octave 波形生成器 |
| 核心用途 | 监护仪合规验收、算法边界测试 |
| 不适用 | 心律失常分类训练、人群性能统计 |
| 库内对照 | CinC 2015、ECG-Arrhythmia、LTAFDB |
§1 它要解决的具体麻烦
1.1 一句话:它让「这台监护仪靠不靠得住」有一份共同答卷
床旁监护仪每天发出成千上万次报警。大部分是对的,也有相当比例是虚惊,这一点在重症病房被反复记录,也是 2015 年 PhysioNet 挑战赛的出发点。一台设备到底判得好不好,如果每个厂家自己定题目、自己判卷,结果没法比较。AAMI EC13 做的就是统一出卷:把几种极限情况做成固定的波形,规定设备在每种情况下必须做出什么反应,然后在任何实验室、任何时间、对任何厂商都按同一套题测。
这个出发点决定了它的全部特征。题目要固定,所以波形数量少而边界极清晰;判分要有据,所以判据写成条款;结果要与具体病人无关,所以波形大多是合成的。这些在普通数据集里都是缺点——样本少、来源单一、没有人群分布——在这里反而是合格的必要条件。
理解这一点之后,很多看似矛盾的用法就顺了:它只有十条记录,却要求使用者读几十页标准;它开放免费下载,但没有标准就等于半张卷子。
| 它像什么 | 真实定位 | 用对的场景 | 用错的后果 |
|---|---|---|---|
| 训练数据 | 验收考题 | 算法定版前的边界回归 | 样本太少,指标无意义 |
| 评测基准 | 确定性验收表 | 医疗器械注册自测 | 与论文数字不可比 |
| 诊断心电库 | 监护报警测试集 | 心率计准确度核对 | 拿它证明诊断能力 |
1.2 三条常见的错误期待
第一条是「这是一个心律失常数据集,可以用来训练分类器」。十条记录、总时长以分钟计、没有事件标注,训练价值接近于零。它的真实身份是测试向量,和软件工程里的单元测试用例同一个性质:数量少、覆盖面刻意挑偏、通过即合格。
第二条是「既然开放下载,就可以随意引用里面的数值」。波形开放,标准不开放。离开了对条款的理解,你不知道这十段波形各自要验证什么,也不知道通过的门槛在哪里。多数误用恰恰发生在这里:有人把 §4.4 的案例中那条 aami4a 当成一段心动过速样本训模型,却不知道它前面那 30 秒三角波是标准规定的「突变前置」。
第三条是「合成数据不如真实数据,所以它只是凑数的」。在合规语境下正好相反:真实数据无法复现,合成数据可以逐比特复现。同一个测试在两家实验室跑出不同结论,对一家要申报的厂商是灾难。合成数据在这里不是妥协,是要求。
| 错误期待 | 背后的错误假设 | 实际情况 | 后果 |
|---|---|---|---|
| 这是心律失常训练集 | 波形多 = 样本多 | 十段,分钟级 | 模型欠拟合且无可比性 |
| 下载即自足 | 数据自带标签 | 判据在付费标准里 | 测试条件错配 |
| 真实优于合成 | 数据越真越好 | 合规要可复现 | 验收结论不可复现 |
| PhysioNet 收录 = 即插即用 | 平台标准统一 | 平台只做托管 | 忽略版本与条款 |
1.3 它能给到的与给不到的
| 你的需求 | 它给的 | 够不够 |
|---|---|---|
| 验证心率计的读数在大幅值信号下是否准确 | Fig.3 组四条不同幅值/形态的规则波形 | 够,这正是设计目的 |
| 验证心动过速判定的启动时延 | Fig.4 组带突变前置的快速波形 | 够,条件由标准规定 |
| 检查基线漂移下的检出稳定性 | 部分记录自带漂移与形态变化 | 部分够,条款另有限定 |
| 室颤、停搏、二联律等报警类型 | 不含 | 不够,须另找数据 |
| 心律失常分类模型的训练样本 | 分钟级、无标签 | 远远不够 |
| 人群层面的灵敏度/特异度 | 无人群、无阴性对照 | 不够 |
| 符合标准要求的完整测试流程 | 只给波形,流程在标准正文 | 不算够 |
| 可复现的回归测试向量 | 十条固定波形 + 校验和 | 够,且是少见的长处 |
| 设备界面与报警音的行为验证 | 与信号无关 | 不归它管 |
| 发表论文时可引用的性能数字 | 没有官方基准分数 | 不够 |
1.4 你的处境与它能帮到的事
| 你的处境 | 它能帮你什么 | 下一步该做什么 |
|---|---|---|
| 在做监护仪或可穿戴的报警算法,准备送检 | 提供与条款绑定的固定输入,先自查一遍 | 买标准正文,按 5.1.2.1 的顺序与时长搭测试台 |
| 论文里要说明算法在边界条件下不乱报 | 十条极限波形可当回归用例 | 只报「逐条通过/不通过」,不要报平均准确率 |
| 刚接手一段监护算法代码,想确认没写坏 | 跑一遍十分钟内能判断大幅值、快心率是否崩 | 把结果做成固定快照,纳入每次提交 |
| 想找室颤/室速数据训模型 | 帮不上 | 转去 CinC 2015 与病理性心律失常库 |
| 做可穿戴心率算法,被要求「通过 EC13」 | 说明这要求的具体含义 | 先确认适用的是 EC13 还是其后继版本 |
| 教学讲「标准与数据的区别」 | 一个极干净的案例 | 配合标准条款节号讲,比讲抽象概念有效 |
1.5 一句话判断
它不是一批数据,是一份考卷的题面;题目少不是缺陷,是出题方式决定的,而判卷标准不在题面上。
1.6 不适合谁:四条边界
第一,不适合任何以统计指标为核心的机器学习工作。 十条记录算不出有意义的灵敏度与特异度,也做不了交叉验证。哪怕把它们扩增成上万条,扩增出来的仍是同一批边界条件,信息量没有增加。
第二,不适合需要覆盖真实临床分布的场景。 真实病房里的假报警多由单导联伪差与低电压引起,这一点在多中心研究里反复出现;AAMI EC13 的十条波形不承担刻画这种分布的职责。要看真实分布,得去 CinC 2015 一类的数据。
第三,不适合单独作为合规证据。 波形是公开的,标准是付费的,测试台搭建、设备连接、判读记录都有条款约束。自己拿十条波形跑一遍,只能算预研,不能算送检。
第四,不适合与后继版本混用口径。 EC13 之后还有对报警系统提出更细要求的后续标准文本,两者在本篇数据所对应的条款上并不等价。引用时若只写「符合 AAMI」而不写年份与条款,结论无法复核。
§2 数据构成与规格
2.1 十行清单与两个家族
整份数据的入口是一份只有十行的纯文本清单。没有目录树、没有分层文件夹、没有按患者或按报警类型分组——一个扁平目录,十条记录,外加一份校验和文件。
十条记录分成两个家族。Fig.3 家族四条(a、b、c、d),对应标准文档中关于心率计准确度的一组插图,记录长度在四万三千到三万五千个采样点之间。Fig.4 家族六条,每条有 1x、0.5x、2x 三个倍率版本,记录长度都在六万五千个采样点附近,比 Fig.3 家族长出一半——因为每条前面要先播放约三十秒的三角波。
| 家族 | 记录 | 倍率 | 采样点数量级 | 折算时长 |
|---|---|---|---|---|
| Fig.3 | a / b / c / d | 无倍率概念 | 三万余至四万余 | 约 48 秒至 60 秒 |
| Fig.4 | a / b | 1x | 六万五千余 | 约 91 秒 |
| Fig.4 | a_d / b_d | 0.5x(名义为 d) | 六万五千余 | 约 91 秒 |
| Fig.4 | a_h / b_h | 2x(名义为 h) | 六万五千余 | 约 91 秒 |
记录名里的字母直接来自标准插图编号,不是描述性的。PhysioNet 页面特地说明了一处历史包袱:_d 后缀本意让人以为是 double(双幅),实际存放的是半幅版本;_h 本意让人以为是 half(半幅),实际是双幅版本。页面保留了 AAMI 给出的原名,理由是不想再引入新的混乱。
| 容易记错的点 | 字面理解 | 实际内容 | 如何核实 |
|---|---|---|---|
| _d 后缀 | double,双幅 | 半幅 0.5x | 读头文件注释与增益行 |
| _h 后缀 | half,半幅 | 双幅 2x | 读头文件注释与增益行 |
| 记录名含义 | 波形类型 | 仅插图编号 | 读 .hea 注释行 |
| aami4 开头 | 直接是快速波形 | 前三段是三角波 | 分段看波形形态 |
2.2 字段与记录的完整字典
WFDB 的一条记录由头文件与数据文件组成。头文件是纯文本,第一行给出记录名、通道数、采样频率与采样点总数,第二行起每个通道一行,用空格分隔的若干字段描述该通道的数据文件、存储格式、增益、位深、基线、初始值、信号名。
| 字段(按头文件列序) | 示例值(aami3a 通道行) | 含义 | 在本库中的作用 |
|---|---|---|---|
| 记录名 | aami3a | 首行第一个词 | 主键,对应 RECORDS 清单 |
| 通道数 | 1 | 首行第二个词 | 全部为单通道 |
| 采样频率 | 720 | 首行第三个词 | Hz,全库一致 |
| 采样点数 | 43081 | 首行第四个词 | 决定时长 |
| 数据文件名 | aami3a.dat | 通道行第一列 | 与头文件同名 |
| 存储格式 | 16 | 通道行第二列 | 16 位整型容器 |
| 增益 | 130 | 通道行第三列 | ADC 计数每毫伏 |
| 位深 | 12 | 通道行第四列 | 有效位数 12 |
| ADC 零点 | 2048 | 通道行第五列 | 数字量换算电压的基准 |
| 初值 | 2072 | 通道行第六列 | 首采样值,用于定点校验 |
| 校验值 | -11941 | 通道行第七列 | 全段求和校验 |
| 信号名 | ECG | 通道行末列 | 唯一信号描述 |
| 注释行 | # ANSI/AAMI EC13-1992, Figure 3a. |
以井号开头 | 只标插图编号,无判读信息 |
(表内的注释行在头文件里是以井号开头的一行,此处为避免与标题语法冲突做了转述。)
这张表最重要的信息是最后两行:头文件里除了「这是 Figure 3a」,没有任何关于这段波形该被如何判定的说明。判读信息全部在标准正文,头文件只负责让信号能被正确读出并换算成物理量。
| 规格项 | 数值 | 是否全库一致 | 影响的用法 |
|---|---|---|---|
| 采样频率 | 720 Hz | 是 | 时间分辨率约 1.4 毫秒 |
| 位深 | 12 位 | 是 | 动态范围约 4096 个计数 |
| 通道数 | 1 | 是 | 无多导联信息 |
| 增益 | 因记录而异(常见 40 至 160) | 否 | 换算电压时必须逐条读 |
| 数据类型 | 16 位整型容器 | 是 | 读入需按增益反算 |
| 注释 | 仅插图编号 | 是 | 无事件时间戳 |
2.3 一条记录的完整解剖
拿 aami3a 举例。头文件四行以内就能读完,第一行四个词,第二行十个字段,第三行一句注释。数据文件是定长整数流,每两个字节一个采样点,按增益与零点换算成毫伏。
#-- 取头文件并看清全部字段,不下载数据体
curl -s https://physionet.org/files/aami-ec13/1.0.0/aami3a.hea
#-- 首行四个词:记录名 通道数 采样频率 采样点数
#-- 第二行十个字段:文件名 格式 增益 位深 零点 初值 校验值 保留 保留 信号名
#-- 用 wfdb 读一条记录:时长、增益、首采样点
import wfdb
rec = wfdb.rdrecord("aami3a", pn_dir="aami-ec13/1.0.0")
print(rec.fs) #-- 720
print(rec.sig_len) #-- 43081
print(rec.sig_len / rec.fs) #-- 约 59.8 秒
print(rec.adc_gain) #-- 130 计数每毫伏
print(rec.adc_zero) #-- 2048
print(rec.p_signal[0][0]) #-- 首采样点换算后的毫伏值
换算关系是固定的:物理值等于数字量减零点,再除以增益。增益每条不同,所以任何跨记录的幅值比较都必须先换算,直接拿整型比较会得出错误结论。
| 分析层次 | 可得到的信息 | 需要的外部知识 |
|---|---|---|
| 文件层 | 记录名、文件大小、校验和 | 无 |
| 头文件层 | 采样率、增益、零点、时长 | WFDB 格式约定 |
| 信号层 | 采样点序列,可算心率与幅值 | 心电信号处理常识 |
| 判读层 | 这段波形该触发什么行为 | 标准正文,必需付费 |
2.4 记录规模与长度分布
按采样点数折算,十段记录的总时长在十二分钟上下。分布很不均匀:Fig.3 家族四条较短,Fig.4 家族六条因前置三角波而普遍在九十秒附近,且同一插图的不同倍率版本长度几乎相同——它们是同一条母波的派生,只是纵轴做了缩放。
| 记录 | 采样点数(约) | 时长(约) | 增益 | 所属插图 |
|---|---|---|---|---|
| aami3a | 43,081 | 59.8 秒 | 130 | Fig.3a |
| aami3b | 43,142 | 59.9 秒 | 130 | Fig.3b |
| aami3c | 43,144 | 59.9 秒 | 130 | Fig.3c |
| aami3d | 34,511 | 47.9 秒 | 130 | Fig.3d |
| aami4a | 65,211 | 90.6 秒 | 80 | Fig.4a 1x |
| aami4a_d | 65,214 | 90.6 秒 | 40 | Fig.4a 0.5x |
| aami4a_h | 65,207 | 90.6 秒 | 160 | Fig.4a 2x |
| aami4b | 65,238 | 90.6 秒 | 80 | Fig.4b 1x |
| aami4b_d | 65,239 | 90.6 秒 | 40 | Fig.4b 0.5x |
| aami4b_h | 65,237 | 90.6 秒 | 160 | Fig.4b 2x |
(表中采样点数取自各记录头文件首行,增益取自通道行第三列;时长为采样点数除以 720 后的近似值,未做逐点计时。)
从这张表能读出三件事。第一,Fig.4 家族的增益呈 40 / 80 / 160 的三档等差,正好对应 0.5x / 1x / 2x,也就是说幅值变化是在增益字段里体现的,不是把数据值改小。第二,同组记录的采样点数只差几十个点,说明派生时长度基本没动。第三,Fig.3d 明显短于同组其他三条,这一点在页面中没有解释,只能如实记录。
| 统计量 | Fig.3 家族 | Fig.4 家族 |
|---|---|---|
| 记录数 | 4 | 6 |
| 时长范围 | 约 48 至 60 秒 | 约 90.6 秒 |
| 增益取值 | 单一取值 | 三档等差 |
| 前置段 | 无 | 约 30 秒三角波 |
| 是否含倍率派生 | 否 | 是,两两成三 |
2.5 与同类资源的规格差异
把这份数据放在常见的心电资源里比较,差异一眼可见。MIT-BIH 心律失常库与 LTAFDB 这类长时程数据库的规格是为信号处理与节律分析设计的;CinC 2015 是为报警判别设计的,但用的是真实重症波形加人工真假标注;本篇是为验收设计的,规格极简,判据在标准里。
| 资源 | 记录/样本量 | 采样率 | 通道 | 标注形态 | 判据来源 |
|---|---|---|---|---|---|
| AAMI EC13 波形 | 10 条 | 720 Hz | 1 | 无标注文件 | 标准条款 |
| CinC 2015 | 千余条 ICU 记录 | 多为 250 Hz 级 | 多路(含 ABP 等) | 逐条真假报警标签 | 专家复核 |
| MIT-BIH 心律失常库 | 48 条半小时记录 | 360 Hz | 2 | 逐拍与节律注释 | 人工判读 |
| LTAFDB | 八十余条长时程 | 128 Hz | 2 | 逐拍与节律注释 | 人工判读 |
| ECG-Arrhythmia | 数万条十秒记录 | 500 Hz | 12 | 诊断编码 | 机器报告加专家复核 |
规格差异不是好坏之分,是用途之分。要统计性能,需要足够的样本与标注;要验收,需要边界清晰、条件确定的少量样本。二者在同一份数据上不可能同时满足,这也是为什么标准文本与开放数据库总是分开的两件事。
| 规格维度 | 本库的取舍 | 取舍的代价 | 换取的东西 |
|---|---|---|---|
| 样本量 | 十余条 | 无法统计 | 每条都可人工逐段核对 |
| 采样率 | 720 Hz | 体量偏大 | 快心率下波形不失真 |
| 通道数 | 单通道 | 无导联冗余 | 与条款的测试条件一致 |
| 标注 | 无 | 不能直接算指标 | 判据唯一,不存在标注歧义 |
| 来源 | 合成与真实混合 | 不代表人群 | 条件可控可复现 |
§3 它在标准体系里的位置:监护算法与诊断算法
3.1 两台机器虽然在读同一根导线
床旁监护仪和诊断心电图机都贴着电极、都看到心电波形,但它们回答的问题完全不同。诊断设备要回答「这是什么心律、有没有缺血、电轴偏不偏」,输出是一份可以归档的报告;监护仪只要回答「现在这一刻,病人的状况是不是需要人来」,输出只有两种状态:报,或者不报。
这个差别带动了一整串设计差异。监护仪是长时在线、单导联为主、以分钟到秒为响应尺度、以「不漏报」为第一优先;诊断设备是短时采样、多导联、以判读准确为第一优先、可以接受长一点的分析时间。把它们混为一谈,就会得出「监护算法准确率不如诊断算法,所以监护算法很差」这种错误结论——它们优化的根本不是同一个目标。
| 比较项 | 床旁监护仪 | 诊断心电图机 |
|---|---|---|
| 核心问题 | 现在要不要叫人 | 这份图是什么诊断 |
| 输入 | 单导联或少数导联,长时在线 | 十导或更多,短时采样 |
| 输出 | 报警/不报警、心率数值 | 结构化报告与诊断编码 |
| 首要错误代价 | 漏报致死性事件 | 误诊导致错误治疗 |
| 时间尺度 | 秒级响应 | 分钟级可接受 |
| 主要标准 | EC13 一类监护标准 | 诊断设备与心电数据交换标准 |
| 性能评价 | 报警时延、误报率 | 诊断一致率、编码准确率 |
| 数据形态 | 连续流 | 定长片段 |
3.2 报警时延为什么是核心指标
对致死性心律失常,监护仪的价值几乎全在「多快」。室颤持续几十秒就可能造成不可逆损伤,所以标准要为「事件出现后多久必须报警」划定上限,而不是笼统地要求「报警准确」。这也是为什么 EC13 的测试波形里,会专门构造「从规则节律突然跳变到快速心律失常」这种情形——考察的正是检测器在跳变瞬间的反应速度,而不是它对稳态信号的平均表现。
时延指标还有一个副作用:它把「宁可多报」变成了理性选择。要在时限内发现事件,检测器倾向于降低阈值,代价是误报率上升,于是临床端又不得不处理大量假报警。这个张力贯穿整个监护行业,任何只看时延不看误报、或只看误报不看时延的评价都是片面的。
| 指标 | 定义方向 | 过严的后果 | 过松的后果 |
|---|---|---|---|
| 报警时延 | 事件到报警的间隔 | 阈值抬高,漏报增加 | 阈值压低,假报警激增 |
| 误报率 | 无事件时的报警比例 | 提高阈值,时延变长 | 报警疲劳 |
| 心率测量误差 | 与参考心率的偏差 | 判据过紧,近似通过率低 | 数值不可信 |
| 心律识别正确率 | 检出类别与应有类别的吻合 | 覆盖不足 | 类型误判 |
3.3 标准条款与数据文件的分工
一条记录只告诉你「信号长这样」,条款才告诉你「看到这样必须怎样」。这一分工在 EC13 里体现得非常直接:PhysioNet 页面明确写明,这些波形的用法应参考标准正文中的某一节的第 (e) 与 (g) 段,记录名对应文档第 25、26 页的插图。换句话说,数据文件是插图,标准正文是图注加要求。
这个结构带来两个实际后果。其一,公开下载的数据不带标签,任何「在 AAMI EC13 上测得准确率」的说法都不成立——数据根本没有可算准确率的标注。其二,凡声称遵循 EC13 的产品,其证据链必须包含标准正文,而正文受版权保护,不能随数据一起公开分发。
| 层次 | 内容 | 是否开放 | 缺失时的后果 |
|---|---|---|---|
| 数据文件 | 十条波形 | 是,ODC-BY 1.0 | 无法复现测试输入 |
| 插图编号 | 头文件注释 | 是 | 无法对应条款 |
| 标准正文 | 测试条件与判据 | 否,需购买 | 无法判定通过与否 |
| 测试台要求 | 设备连接与呈现方式 | 否 | 实验室之间结果不可比 |
| 判读记录 | 原始记录与结论 | 厂商自存 | 无法向监管机构举证 |
3.4 2022 年前后的版本更替对这条数据的影响
本篇数据对应的标准是 2002 年版,文件在 2002 年底生成、2003 年初上线,此后未再改动。而监护报警的规范在此后又经历了一次较大的整合:原本分散在若干文件里的报警相关要求被收拢并细化,尤其是对报警时延的量化要求有所强化。
这意味着引用时必须写清版本。说「符合 AAMI EC13」在 2003 年是完整的表述,在今天则需要说明是 2002 年版,并交代与后续要求的关系。本篇数据本身没有变化,变化的是它所服务的规范环境。这个区分对做注册的团队是常识,对首次接触这套材料的研究者则常常是坑。
| 版本层面 | 本篇对应 | 变化情况 | 使用时的写法 |
|---|---|---|---|
| 标准文本 | 2002 年版插图与条款 | 后续有整合与细化 | 注明版本与节号 |
| 波形文件 | 2002 年底生成 | 未再更新 | 注明 PhysioNet 版本号 |
| 判读要求 | 附在正文 | 后出的要求更细 | 分别交代各自依据 |
| 注册资料 | 不涉及 | 由厂商按适用法规组织 | 不由本篇承担 |
§4 为什么合成波形是正确选择
4.1 可复现性优先于真实性
验收测试的第一要求是同样的输入得到同样的结论。真实病人做不到这一点:同一个人不可能每次都以同一幅度、同一心率、同一突变时刻重现室颤,即使录下来也会因电极位置、皮肤阻抗、设备前端滤波的细微差别而不同。用真实信号做验收,等于把「测试」变成了「抽检」。
合成信号则完全可控。幅值、心率、形态、突变时刻都能按条款精确设定,甚至可以做到同一段波形在不同实验室播放出完全相同的数值序列。本篇数据把这一条件做到极致:十条固定记录加一份校验和清单,任何人下载后都能逐一比对。
| 要求 | 真实临床信号 | 合成测试信号 | 对本库的意义 |
|---|---|---|---|
| 逐比特复现 | 不可能 | 可以 | 校验和可验证 |
| 边界条件可控 | 依赖运气 | 按参数设定 | 幅值、心率可精确指定 |
| 隐私风险 | 存在 | 基本无 | 可完全开放 |
| 覆盖罕见事件 | 需长时间搜索 | 可直接构造 | 快速心律失常可反复呈现 |
| 人群代表性 | 有 | 无 | 不能用于统计 |
4.2 半合成折中的实际形态
纯粹的合成信号干净得不像心电,检测器在这类信号上的表现可能高估。因此真正的测试集往往是半合成的:以真实心电片段为素材,再通过幅值缩放、心率加快、叠加漂移与噪声来构造边界条件。本篇数据的说明写明其中同时包含合成与真实波形,但没有逐条公开哪条是哪种。
这个信息缺口在使用时应当被承认,而不是被填平。若要在论文里讨论某条记录的来源性质,只能写到「页面称含合成与真实波形,具体对应关系未公开」;任何声称某条为合成或真实的断言,都缺少可公开复核的依据。
| 记录 | 页面是否声明来源 | 头文件是否含来源线索 | 可写的结论 |
|---|---|---|---|
| Fig.3 组 | 未逐条声明 | 无 | 只能写「混合来源」 |
| Fig.4 组 | 未逐条声明 | 无 | 只能写「混合来源」 |
| 倍率派生版 | 派生自同组母波 | 注释给出倍率 | 可写「同源派生」 |
4.3 病例级验证不能替代条款级验证
有人会主张:既然真实病例更接近临床,就应该用大量真实病例替代标准波形做验收。这个主张混淆了两件事。真实病例能告诉你算法在人群上的平均表现,却无法告诉你算法在条款规定的那几种极限条件下是否失效;反过来,十条边界波形能告诉你是否越界,却给不出平均表现。二者是两种证据,都需要,但不能互替。
在注册路径上,这个分工尤为明确:设备的性能声称要按适用标准验证,而算法泛化能力另有临床评价的路径。把公开数据集上的高分当作合规证据,是拿统计平均去回答确定性判定,逻辑上不成立。
| 证据类型 | 回答的问题 | 数据来源 | 是否可以互换 |
|---|---|---|---|
| 条款级验证 | 是否满足规定行为 | 标准波形与条款 | 否,不可由统计替代 |
| 人群级验证 | 平均表现如何 | 真实多中心数据 | 否,不可由条款替代 |
| 回顾性临床评价 | 在实际病房是否改善结局 | 院内数据与随访 | 否,层级更高 |
| 前瞻性试验 | 是否真的降低风险 | 前瞻设计 | 否,成本最高 |
4.4 案例:aami4a 与它前面的三十秒三角波
拿 aami4a 一条记录走完整个推理链,能看清这份数据的设计意图。它的头文件只有一行注释,说明对应 Figure 4a、倍率 1x;采样点六万余,折算九十秒出头;前三十秒是规则的三角波,之后才切换成快速心律波形。
这三十秒不是冗余。PhysioNet 页面写明,标准要求 Figure 4 的心动过速波形应在 Figure 6 规定的合成波形之后突然呈现。也就是说,三十秒三角波扮演的是「事件之前」的稳态,后面紧接的快速波形扮演的是「事件发生」的瞬间。检测器要做的,是在这个跳变之后尽快给出报警;如果它把三角波当成正常节律、又没有在跳变后被触发,就会被判为未通过。
| 片段 | 大致时长 | 扮演的角色 | 检验的能力 |
|---|---|---|---|
| 三角波段 | 约 30 秒 | 事件前的稳态 | 建立基线,避免提前触发 |
| 跳变 | 瞬间 | 事件发生 | 能否响应突变 |
| 快速波形段 | 约 60 秒 | 事件持续 | 报警是否维持而非抖动 |
由此可以推出 §4.4 的案例在实践中的两个用法。第一,拿它做回归:把检测器冻结,在 §4.4 的案例上跑一遍,记录首次报警的时刻,以后每次改动都比对这个时刻是否漂移。第二,拿它做参数敏感性分析:把检测阈值从最保守调到最激进,看首次报警时刻如何变化、三角波段是否被误触发。
#-- 读 aami4a,定位跳变附近的幅值变化,不依赖任何第三方检测器
import numpy as np
import wfdb
rec = wfdb.rdrecord("aami4a", pn_dir="aami-ec13/1.0.0")
x = rec.p_signal[:, 0]
fs = rec.fs
#-- 以 1 秒为窗,算窗内极差;三角波段极差稳定,跳变后会突变
win = fs
rng = np.array([x[i:i + win].ptp() for i in range(0, len(x) - win, win)])
t = np.arange(len(rng))
print("窗数", len(rng), "最大极差窗索引", int(rng.argmax()))
print("前 30 秒平均极差", float(rng[:30].mean()))
print("后段平均极差", float(rng[35:].mean()))
这段代码只做一件小事:把记录分成秒窗,看窗内极差在何处跃升。它不能代替检测器,但能验证「三十秒稳态之后有突变」这一事实是否与本机的读取结果一致,是接入前的第一道自检。
| 自检项 | 通过标准 | 不通过时优先排查 | 说明 |
|---|---|---|---|
| 首行字段 | 720 Hz、六万余点 | 下载是否完整 | 用校验和核对 |
| 增益换算 | 与头文件一致 | 是否漏读增益 | 直接算毫伏 |
| 前置段存在 | 前 30 秒幅值稳定 | 起点是否被裁掉 | 看首采样点 |
| 跳变位置 | 在 30 秒之后 | 窗长是否取错 | 用 1 秒窗 |
| 后段持续 | 幅值维持到末尾 | 是否被截断 | 看总时长 |
§5 取数、读出与接入
5.1 三条取数路径的取舍
整份数据只有 1.1 MB,取数的技术门槛几乎为零,真正的选择在「怎么取」与「取完之后怎么管」。三条常见路径:直接下载压缩包、用 wget 镜像目录、用 wfdb 库按需拉取。
压缩包适合离线留档,一次取全,校验和能一次核对;镜像目录适合做增量同步,脚本可重复执行;按需拉取适合在代码里直接用,不必先落地文件,但每次运行都要联网,在隔离环境里不可行。对校验敏感的场景(送检、论文附录)建议用第一种,并在附录里写出校验和比对结果。
| 路径 | 命令形态 | 适合场景 | 缺点 |
|---|---|---|---|
| 压缩包 | 浏览器下载 zip | 离线留档、送检 | 需手工解压 |
| 目录镜像 | wget 递归镜像 | 定期同步 | 会带上无关索引页 |
| 库内拉取 | wfdb 的 pn_dir 参数 | 脚本内直接读 | 需联网,需缓存 |
| 平台接口 | 走 PhysioNet 的 API 端点 | 批量元数据 | 波形仍需另取 |
#-- 一次性镜像全部记录(含校验和文件),约 1.1 MB
wget -r -N -c -np https://physionet.org/files/aami-ec13/1.0.0/
#-- 核对完整性:逐条比对 SHA256
cd aami-ec13/1.0.0 && sha256sum -c SHA256SUMS.txt
5.2 用 wfdb 直接读,不落盘
wfdb 库支持用 pn_dir 参数直接从 PhysioNet 读取,适合探索阶段。第一次访问会下载并缓存,之后走本地缓存。数据体很小,缓存策略不必优化,但要注意缓存目录的位置——在多用户机器上,缓存在共享目录里可能被其他进程写坏,届时读出的采样点会莫名缺失。
| 参数 | 作用 | 常用取值 | 注意 |
|---|---|---|---|
| pn_dir | 指定 PhysioNet 上的路径 | aami-ec13/1.0.0 |
必须带版本号 |
| physical | 是否返回物理量 | True(默认) | 为 False 时返回整型 |
| channels | 指定通道 | 只有 0 | 指定其他会报错 |
| sampfrom | 起始采样点 | 0 | 大文件可分段读 |
| sampto | 结束采样点 | 记录总长 | 越界会报错 |
#-- 逐条读出十条记录,打印时长与峰峰值(毫伏)
import wfdb
for name in ["aami3a", "aami3b", "aami3c", "aami3d",
"aami4a", "aami4a_d", "aami4a_h",
"aami4b", "aami4b_d", "aami4b_h"]:
rec = wfdb.rdrecord(name, pn_dir="aami-ec13/1.0.0")
x = rec.p_signal[:, 0]
print(f"{name:10s} 时长 {rec.sig_len / rec.fs:6.1f} 秒 峰峰值 {x.ptp():7.2f} 毫伏")
5.3 判定层要自己补
数据不提供标注,判定要自己实现。一个最小可用的判定器只需三步:估心率、判是否超过阈值、记录首次越阈时刻。把它写成函数,同一套参数在任何一条记录上都能复用,结果是可比的。
#-- 最小检测器:过阈值计数法估瞬时心率,输出首次报警时刻
import numpy as np
import wfdb
def first_alarm(name, thr_bpm=150, refresher=8.0):
rec = wfdb.rdrecord(name, pn_dir="aami-ec13/1.0.0")
x = rec.p_signal[:, 0]
fs = rec.fs
#-- 简易峰检测:取全段 90 分位作为峰值门限
pk = x > np.percentile(x, 90)
idx = np.where(pk[1:] & ~pk[:-1])[0] + 1
if len(idx) < 3:
return name, None
rr = np.diff(idx) / fs
bpm = 60.0 / np.convolve(rr, np.ones(3) / 3, mode="same")
hit = np.where(bpm > thr_bpm)[0]
if len(hit) == 0:
return name, None
return name, float(idx[hit[0]] / fs)
for n in ["aami4a", "aami4b"]:
print(first_alarm(n))
这个检测器非常粗糙,峰值门限是拍的,平滑窗长是拍的,阈值也是拍的。它存在的意义不是「通过 EC13」——它远达不到,也不该被当作合规工具——而是提供一个可复现的基线,让任何改动都能立刻看出影响。
| 检测环节 | 本示例的做法 | 对结果的影响 | 换成正式实现时应做什么 |
|---|---|---|---|
| 峰检测 | 90 分位硬阈值 | 大幅值段误检偏少 | 用自适应滤波与不应期 |
| 心率估计 | 三点滑动平均 | 对突变响应滞后 | 用中位数或状态机 |
| 判定阈值 | 单一固定值 | 无个体适应 | 按条款设定各类阈值 |
| 报警记录 | 首次越阈 | 不衡量持续抖动 | 记录首次与维持时长 |
| 重触发 | 未实现 | 漏掉抖动行为 | 加复位与去抖逻辑 |
5.4 与配套工具的配合
PhysioNet 上另有一个心电波形生成器,可用 Matlab 或 Octave 生成标准里规定但未做成文件的若干合成波形。它的意义在于补齐:页面说明除这十条之外,标准还规定了需要用生成器构造的波形。若测试流程要求全部波形,只下载本库是不够的。
| 资源 | 形态 | 覆盖 | 是否有版本管理 |
|---|---|---|---|
| aami-ec13 波形 | 十条固定记录 | Fig.3 与 Fig.4 | 有,1.0.0 |
| 波形生成器 | 脚本,参数化 | 标准中其余合成波形 | 有,独立版本 |
| WFDB 软件包 | 读写工具 | 全平台 | 有,独立版本 |
| 标准正文 | 文档 | 条款与判据 | 有,按版次出售 |
5.5 接入前的最小检查清单
把数据接进一条流水线之前,值得花十分钟做一遍这项自检。检查项都很朴素,但每一项都对应过一次实际的坑:读错增益导致毫伏值偏差数倍、裁掉前置段导致突变测试失效、把倍率版本混着统计导致结论翻倍。
| 检查项 | 怎么做 | 通过的样子 | 常见错法 |
|---|---|---|---|
| 记录齐全 | 与 RECORDS 清单比对 | 十条一条不少 | 只下了压缩包里的部分 |
| 完整性 | 跑 SHA256 校验 | 全部 OK | 忽略校验直接读 |
| 增益 | 打印每条增益 | 与头文件一致 | 用统一增益换算 |
| 时长 | 采样点除以采样率 | 与本文表格一致 | 把点数当秒数 |
| 前置段 | 看前 30 秒形态 | 三角波稳定 | 从跳变处开始切 |
| 倍率 | 分清 _d 与 _h | 知道 d 是半幅 | 按字面理解 |
5.6 把它放进版本控制的正确姿势
测试向量一旦定版,就不应该随数据源变化而漂移。推荐的姿势是把十条记录的校验和写进仓库,CI 里先校验再跑算法;任何一次校验失败都要停下来看,而不是跳过。这套做法在软件工程里是常规操作,在医疗算法团队里却常被忽略,原因往往是「数据是网上下的,反正不会变」。
数据确实很少变——这份从 2003 年起就没有再改过。但下载渠道会变、缓存会被污染、脚本可能误写了别的版本。把校验和纳入版本控制,成本接近于零,收益是把一次难查的诡异失败提前变成一行明确的报错。
#-- 在 CI 里先验校验和,再跑算法,失败即停
set -e
sha256sum -c SHA256SUMS.txt
python3 run_detector.py --records RECORDS --out report.json
python3 compare_baseline.py report.json baseline.json
| 环节 | 做什么 | 失败时的表现 | 处理方式 |
|---|---|---|---|
| 校验 | 比对 SHA256 | 一行 FAILED | 重新下载,不跳过 |
| 运行 | 跑检测器 | 报错或超时 | 看是否读错路径 |
| 比对 | 与基线快照比较 | 报警时刻漂移 | 判断是改进还是回归 |
| 归档 | 存报告与版本号 | 无 | 报告里写清数据版本 |
§6 与库内条目的关系
6.1 关系图谱
在进入并列比较之前,先说清一个容易被忽略的事实:§4.4 的案例里那条前置三角波的设计,与 CinC 2015 那种「每条记录对应一次真实报警」的组织方式几乎是相反的。前者是先摆一个稳定的「事件之前」,再让事件发生,考验反应速度;后者是直接给出一段带着报警的现场,让算法判断这次报警是不是真的。两种组织方式对应两种要回答的问题,这也是本篇与库内多数心电条目最根本的分野。
库内与心电有关的条目可以按「证据类型」排成一条线。一端是标准与测试波形,回答「在规定的输入下行为是否正确」;中间是带标注的公开数据库,回答「在真实记录上表现如何」;另一端是挑战赛数据,回答「在一套公开协议下与其他方法相比如何」。本篇在最左端,是这条线上样本最少、判据最硬的一环。
| 库内条目 | 关系类型 | 差异要点 | 何时选它 |
|---|---|---|---|
| CinC 2015 | 同任务不同证据层级 | 真实重症波形,逐条真假标签 | 要评估假报警抑制 |
| ECG-Arrhythmia | 诊断方向 | 十秒十二导,诊断编码 | 要做诊断分类 |
| LTAFDB | 长时程节律 | 长时间双导联,逐拍注释 | 要做节律与房颤分析 |
| MIT-BIH 心律失常库 | 经典参考库 | 小时级双导联,人工节律标注 | 要做逐拍算法 |
| DeepFake ECG | 合成方向 | 大规模合成正常心电 | 要做生成与检测 |
| 心电片段分级库 | 危急程度分级 | 两秒短片段,六级 | 要做危急度排序 |
这些条目彼此不构成替代关系。一个完整的算法评估链条通常要同时用到三端:先用标准波形确认不越界,再用公开数据库看平均表现,最后在挑战赛协议下与其他方法比较。跳过第一端,可能带着一个在边界条件下崩溃的算法去算平均分;只做第一端,则永远不知道平均分是多少。
| 链条环节 | 用哪类数据 | 回答的问题 | 跳过的风险 |
|---|---|---|---|
| 边界回归 | 本篇 | 是否越界 | 边界条件下崩溃未被发现 |
| 平均表现 | 带标注公开库 | 表现如何 | 数字漂亮但条件未知 |
| 横向比较 | 挑战赛数据 | 相对位置 | 无法与他法比较 |
| 外部验证 | 自备多中心 | 是否泛化 | 跨中心失效 |
6.2 检索路径
按任务检索:要验报警时延,进本篇;要判别真假报警,进 CinC 2015;要做诊断分类,进 ECG-Arrhythmia 与诊断方向条目;要做长时程节律,进 LTAFDB。
按方法检索:想知道「没有标注的数据怎么用」,进本篇 §5.3;想知道「有标注的数据怎么划分」,进带标注库的条目;想知道「合成数据怎么构造」,进合成方向条目。
按合规检索:本篇以及标准文本,是全库唯一一条以「标准条款」为判据的路径。
| 检索词 | 命中条目 | 命中的是哪一节 |
|---|---|---|
| 监护仪报警 | 本篇、CinC 2015 | 本篇 §3、§5 |
| 假报警 | CinC 2015、本篇 | CinC 2015 全篇、本篇 §3.2 |
| 测试波形 | 本篇 | §2 全节 |
| WFDB 格式 | 本篇、LTAFDB、MIT-BIH 系列 | 本篇 §2.2 |
| 合规验收 | 本篇 | §3、§5.6 |
| 合成心电 | DeepFake ECG、本篇 | 合成条目全篇、本篇 §4 |
§7 质量评估与局限性
7.0 阅读本节前的一个前置校正
在给这份数据打分之前,必须先纠正一个普遍存在的误判:凡是拿「样本量」「标注密度」「人群代表性」这三把尺子去量它的评估,方向都错了。这三把尺子衡量的是统计型数据集的优劣,而它根本不是统计型数据集。用它们去量,得到的低分只反映尺子不对,不反映数据不好。
第二个误判是把「没有标注」当成数据缺陷。在验收语境里,没有标注是必然的:判据在条款里,若再给一份标注,就出现了两套可能冲突的答案来源。它的「标注」就是标准正文,而正文不归 PhysioNet 管。
第三个误判是把「页面说明简短」当成信息量少。这十条记录的每一个字段都可逐字核对,头文件只有四五行,信息密度其实很高;真正缺的是判读规则,而这个缺口是有意的分工,不是遗漏。
校正之后,本节给出的评分才有意义:它的高分集中在「可复现」与「契约清晰」,低分集中在「规模」与「覆盖」,而后者对它的用途几乎不构成限制。
7.1 五维评分
采用 DAIMS 框架的五个维度,每维 5 分制。评分对象是这份公开波形本身,不包含标准正文——正文不在评价范围内,但它对可用性的影响在理由里注明。
| 维度 | 评分 | 理由 |
|---|---|---|
| 可得性(Accessibility) | 4.5 | 无需注册,1.1 MB,ODC-BY 1.0,可直接下载 |
| 可用性(Usability) | 3.0 | 读取容易,但判读必须依赖付费正文 |
| 标注质量(Annotation Quality) | 2.5 | 无标注文件;相当于把标注定义为条款,质量取决于条款完备度 |
| 方法学严谨性(Rigor) | 4.5 | 输入端完全确定,校验和齐全,条件由标准锁定 |
| 代表性与公平性(Representativeness) | 1.0 | 不追求人群代表性,本身就无人群概念 |
| DAIMS 综合 | 3.1 | 契约优先,规模让位 |
标度说明:可得性与严谨性两项的高分,与代表性和标注两项的低分,并不矛盾,因为它们衡量的是不同用途下的适配度。若把权重按「合规验收」重新分配,综合分会明显更高;本文不加权,只按通用框架给出,理由是通用分更能让不同背景的使用者各自换算。
| 维度 | 若用于合规验收 | 若用于机器学习 | 差异来源 |
|---|---|---|---|
| 可得性 | 4.5 | 4.5 | 无差异 |
| 可用性 | 4.0 | 1.5 | 判读依赖正文 |
| 标注质量 | 4.0 | 1.0 | 条款替代标注 |
| 严谨性 | 4.5 | 3.0 | 固定输入利于回归,不利于泛化 |
| 代表性 | 1.0 | 1.0 | 均不适用 |
7.2 各维度失分的具体位置
可用性失分在两处。第一处是判读:没有正文就不知道门槛,这使「自测自查」只能做一半——能验证读取与信号处理,不能给出合格结论。第二处是测试条件:标准对呈现方式、设备状态、记录填写都有要求,公开数据只提供波形。
标注质量一项按通用框架只能给低分,因为这个框架默认标注是「人给人看的内容打标签」。这里没有标签,有的是判据。若改按「判据是否明确」来评,它的分数应当很高,因为条款的确定性远高于多数人工标注。两种评法都成立,差别在于把「标注」定义成什么。
代表性一项给最低分,原因很直白:它压根不打算代表任何人。真实病房里报警的分布、患者的年龄结构、电极贴法、运动伪差,这些在这份数据里全部缺席,而且是有意缺席。
| 维度 | 主要失分点 | 失分方向 | 一句话 |
|---|---|---|---|
| 可用性 | 判据不在数据里 | 依赖外部购买 | 半成品,缺正文 |
| 标注质量 | 无标注文件 | 通用框架下不可比 | 判据说在条款里 |
| 代表性 | 无人群、无真实分布 | 不可外推 | 本就不为外推设计 |
| 严谨性 | 条件依赖正文描述 | 复现需购买 | 拿到正文则极稳 |
| 可得性 | 几乎无失分 | — | 十分钟可下完 |
7.3 已知的、可枚举的偏差
偏差在这里指的不是统计偏差,而是「拿它做某种用途时必然出现的系统性错误结论」。可枚举的至少有五条,每一条都对应过真实的误用。
| 偏差 | 机制 | 会诱导出的错误结论 | 规避方式 |
|---|---|---|---|
| 样本极小 | 十条,分钟级 | 报出的准确率无统计意义 | 只报逐条通过与否 |
| 边界挑选 | 波形专挑极限条件 | 平均表现被系统性低估或高估 | 不用于平均表现评估 |
| 无阴性对照 | 无正常人群段 | 算不出特异度 | 特异度另找数据 |
| 判据外部化 | 判读依赖正文 | 自行判定结论可能与官方不同 | 注明依据版本 |
| 命名反直觉 | _d 为半幅、_h 为双幅 | 倍率统计反了 | 读头文件再统计 |
此外还有一处需要如实记录的口径问题:Fig.3d 的时长明显短于同组其余三条,页面未给出解释。本文按头文件如实列出,不对原因作推断。若有人把它当作同规格的第四条,标注时长时就会出错。
| 记录 | 与同组的差异 | 页面是否解释 | 使用时怎么做 |
|---|---|---|---|
| aami3a / 3b / 3c | 长度接近 | — | 按头文件数值用 |
| aami3d | 短约十二秒 | 未解释 | 单独标注时长 |
| 4 家族各条 | 长度接近 | 前置三角波所致 | 注意裁切起点 |
7.4 外部验证矩阵
把这份数据与其他证据源并排,能看清它各自能回答什么。矩阵的每一行是一种验证方式,每一列回答「能否」「依据什么」。
| 验证方式 | 本篇能否提供 | 依据 | 替代来源 |
|---|---|---|---|
| 条款符合性 | 部分,需正文 | 波形 + 条款 | 标准正文 |
| 边界鲁棒性 | 能 | 十条极限波形 | 无 |
| 平均灵敏度/特异度 | 不能 | 无阴性、无标注 | CinC 2015 等 |
| 人群泛化 | 不能 | 无人群 | 多中心自备数据 |
| 跨中心一致性 | 部分 | 输入固定 | 实验室间比对 |
| 与文献数字可比 | 不能 | 无官方基准分 | 挑战赛协议 |
| 可重复性 | 能 | 校验和 + 固定输入 | — |
这张矩阵最有信息量的一行是最后一行。多数公开数据集无法保证「换个人下载得到同样结果」,因为版本会更新、划分会变、预处理脚本不随数据发布。这份数据在这一点上几乎做到了极致:版本号固定、校验和齐全、输入短到可以人工核对。它是一部可以当作「标尺」使用的数据,而不是一座矿山。
7.5 它为何能持续:标准不改,波形就不动
它之所以能被持续使用二十多年,原因不在维护活跃,而在维护对象本身几乎不需要维护。波形是标准的附属物,只要标准条款不变、插图不变,这十条记录就没有修改的必要。PhysioNet 做的是托管与格式规范化,不是内容演进。这种「以不变应万变」的生存逻辑,与依靠持续扩量来维持价值的数据库正好相反。
§8 生态位与历史
8.1 从一份行业标准到一份公开波形
EC13 的源头是行业对监护设备性能的共同要求。上世纪九十年代,床旁监护仪的算法五花八门,报警阈值各写各的,医院之间、厂家之间没法比较,监管侧也缺少统一的测试方法。AAMI 组织厂商、临床与工程界共同起草,把「设备在哪些条件下必须表现成什么样」写成可核查的条款。
2002 年版是这一脉络中的一个节点,本篇数据对应的正是它的插图。波形在 2002 年底由 AAMI 提供给 PhysioNet,2003 年初以 1.0.0 版本上线,此后未再改动。
| 时间 | 事件 | 形态 | 对使用者的意义 |
|---|---|---|---|
| 上世纪九十年代 | 监护性能要求开始标准化 | 行业标准起草 | 报警测试有了共同语言 |
| 1992 年 | 头文件注释标注的版本 | 标准版次 | 插图编号的来源 |
| 2002 年 | 现行版次出版 | 标准正文 | 本篇条款依据 |
| 2002 年底 | 波形交付 PhysioNet | 数据文件生成 | 形成 1.0.0 |
| 2003 年初 | 页面上线 | 公开托管 | 任何人可下载 |
| 此后 | 相关内容整合细化 | 新要求发布 | 引用须注版本 |
8.2 平台的角色:托管而非背书
PhysioNet 在这件事里的角色常被误读。它不是标准的制定者,也不对波形作判读;它做的是格式规范化、长期托管与引用登记。平台上的每个资源都有一个 DOI,本篇对应的是一个 2003 年登记的唯一标识,这使它在论文里可被精确引用。
理解这一点能避免两类误会。其一,把平台收录当成质量认证——平台收录的门槛是「可公开、可长期保存、有说明」,不是「科学上最优」。其二,把平台的引用格式当成数据集的学术引用——页面提示默认生成的引用指向平台本身,引用数据时应使用数据集的 DOI 与版本号。
| 角色 | 由谁承担 | 职责 | 不承担的 |
|---|---|---|---|
| 制定标准 | AAMI 与行业委员会 | 条款与判据 | 数据托管 |
| 提供波形 | AAMI | 插图对应的信号 | 在线分发 |
| 托管与检索 | PhysioNet | 格式、版本、DOI | 判读与认证 |
| 使用与测试 | 厂商与实验室 | 搭建测试台 | 修改波形 |
8.3 与后续规范的关系
本篇之后,监护报警的规范环境继续演进。一方面,报警相关的分散要求被收拢整合,形成了更系统的文档体系;另一方面,对报警时延等指标的量化要求被进一步明确,尤其是在致死性心律失常的响应时间上。这些变化没有改动本库的任何一条记录,但改变了「怎样才算通过」的回答方式。
对使用者的实际含义是:这份数据在今天仍然有用,因为插图未变;但判断「通过与否」必须用当前适用的规范,而不能想当然地沿用 2002 年版的表述。这一点在写注册材料时尤其重要。
| 层面 | 2002 年版 | 后续规范 | 本篇的应对 |
|---|---|---|---|
| 波形 | 插图 3、4 | 大体沿用 | 无需改 |
| 报警时延 | 有原则性要求 | 量化更细 | 引用须注版本 |
| 文档结构 | 分散 | 整合 | 说明对应关系 |
| 数据许可 | 由平台决定 | 由平台决定 | ODC-BY 1.0 |
8.4 它在今天的位置
在算法评测高度依赖大数据的今天,这样一份十二分钟、十条记录的波形显得不合时宜。但它占据的位置没有替代品:几乎所有公开数据库都在追逐规模与代表性,而「输入完全确定、判据由外部给定」的资源越来越少。它像一个标准砝码,不参与比赛,只用来校准天平。
这个位置也决定了它的使用者群体偏窄:主要是设备厂商的算法与注册团队、少数做监护算法的研究者,以及需要讲清「标准测试」与「统计评测」区别的教学者。规模小不是它的问题,把它当规模数据用才是。
| 使用群体 | 主要用途 | 使用频率 | 常见误区 |
|---|---|---|---|
| 设备厂商算法团队 | 定版前边界回归 | 每个版本一次 | 拿它做性能宣称 |
| 注册与合规 | 自测与举证准备 | 按申报节奏 | 忽略正文版本 |
| 学术研究者 | 边界鲁棒性对照 | 偶发 | 报平均准确率 |
| 教学 | 讲标准与数据的区别 | 每学期 | 只讲波形不讲条款 |
| 可穿戴团队 | 参考心率计测试 | 看情况 | 误以为适用 |
§9 使用指引
9.1 三种角色的路径
合规角色的路径最短但门槛最高:先确认适用的规范版本,购买正文;按正文搭建测试台,确认播放设备与增益换算;逐条跑完并保留原始记录;把结果与条款逐项对照。这份数据在这一路径里只承担「输入」一角,其余全靠正文与流程。
算法角色的路径围绕回归展开:先把读取与换算做对,跑一遍拿到基线;把基线冻结成快照;此后每次改动都重跑并与快照比对;出现漂移时区分是改进还是退化。这一路径不需要正文,但结论只能写成「相对基线如何」,不能写成「是否符合标准」。
研究角色的路径重在诚实:可以把这十条作为极端条件下的对照实验,用来展示算法在边界上的行为;论文中必须说明样本量、无标注、判据不在数据里这三件事;不得把逐条结果折算成准确率与其他数据集比较。
| 角色 | 第一步 | 最关键的一步 | 绝不能做的 |
|---|---|---|---|
| 合规 | 买正文确认版本 | 按条款搭测试台 | 用自测结论代替送检 |
| 算法 | 读通头文件与增益 | 冻结基线快照 | 改动后不重跑 |
| 研究 | 明确样本量与无标注 | 如实描述证据层级 | 折算准确率做比较 |
| 教学 | 先讲条款再讲波形 | 让学生自己推判据 | 只演示波形形态 |
9.2 一条最短的可用流程
从零到能判断「算法在这批边界波形上是否异常」,最短的流程是四步:取数、校验、读通一条、跑全十条。四步合计十几分钟,不需要任何标注。
#-- 1 取数(约 1.1 MB)并校验
wget -r -N -c -np https://physionet.org/files/aami-ec13/1.0.0/
cd aami-ec13/1.0.0 && sha256sum -c SHA256SUMS.txt
wc -l RECORDS
#-- 2 读通一条,确认增益与时长与头文件一致
import wfdb
rec = wfdb.rdrecord("aami3a", pn_dir="aami-ec13/1.0.0")
print(rec.fs, rec.sig_len, rec.adc_gain, rec.adc_zero)
assert rec.fs == 720
assert abs(rec.sig_len / rec.fs - 59.8) < 0.1
#-- 3 跑全十条,输出一张可存档的基线表
import json
import wfdb
rows = []
for name in open("RECORDS").read().split():
rec = wfdb.rdrecord(name, pn_dir="aami-ec13/1.0.0")
x = rec.p_signal[:, 0]
rows.append({
"record": name,
"seconds": round(rec.sig_len / rec.fs, 1),
"gain": float(rec.adc_gain[0]),
"ptp_mv": round(float(x.ptp()), 3),
})
json.dump(rows, open("baseline.json", "w"), ensure_ascii=False, indent=2)
print(len(rows), "条记录已写入 baseline.json")
#-- 4 之后每次改动都与基线比较,只看漂移,不看绝对值
import json
base = {r["record"]: r["ptp_mv"] for r in json.load(open("baseline.json"))}
now = {r["record"]: r["ptp_mv"] for r in json.load(open("current.json"))}
for k in base:
d = now[k] - base[k]
flag = "漂移" if abs(d) > 1e-6 else "一致"
print(f"{k:10s} {base[k]:8.3f} -> {now[k]:8.3f} {flag}")
| 步骤 | 产物 | 耗时量级 | 失败时的信号 |
|---|---|---|---|
| 取数 | 目录与十条记录 | 分钟以内 | 校验和不过 |
| 读通一条 | 确认采样率与增益 | 数分钟 | 断言失败 |
| 跑全十条 | 基线表 json | 数分钟 | 记录数不是十条 |
| 比对 | 漂移清单 | 秒级 | 大量行标为漂移 |
这条流程不涉及任何标准条款,因此它的产出只能用于团队内部回归,不能对外宣称符合性。把这个边界写在流程文档的开头,比写在结尾有效。
9.3 引用方式
引用这份数据时,三样东西都要写:数据集本身、它对应的标准正文、以及所依据的版本。只写其中之一都不完整——只写数据,读者不知道判据;只写标准,读者无法复现输入;不写版本,两年后无法核对。
| 引用对象 | 必要信息 | 从哪取 | 漏写会怎样 |
|---|---|---|---|
| 波形数据 | 名称、版本号、DOI、平台 | 数据集页面 | 输入不可复现 |
| 标准正文 | 名称、年份、出版机构 | 标准封面 | 判据无法核对 |
| 条款位置 | 节号与段落 | 正文 | 通过标准不明确 |
| 配套工具 | 名称与版本 | 各自页面 | 合成波形缺失 |
§10 AI 使用声明
| 项目 | 说明 |
|---|---|
| 写作方式 | 人机协作,结构与论点由编辑确定,模型承担资料整理与初稿 |
| 资料核验 | 2026-10-27 访问数据集主页与文件目录,逐条读十条头文件首行与通道行 |
| 论文来源 | Europe PMC 检索,读摘要,未取全文 |
| 未核验 | 标准正文全部条款、真实与合成波形的逐条对应、测试台搭建要求 |
| 来源层级 | 页面与头文件为一级,论文摘要为二级,推算为三级,均已标注 |
| 事实与判断 | 规模、字段、许可为事实,DAIMS 评分为编辑判断 |
| 更新承诺 | 数据不再更新,本篇随平台版本与规范更替修订 |
| 责任边界 | 不构成医学建议,不替代合规审查与送检 |
10.1 关于「十条」这个数的说明
派发材料曾按「150 多条记录、含室颤与二联律」描述本资源。逐条核对文件目录与 RECORDS 清单后,确认实际为十条记录,且头文件判读层不含室颤、停搏一类条目。本篇按核对结果写作,未沿用派发描述中的规模与内容。
| 项 | 派发描述 | 核对结果 | 处理 |
|---|---|---|---|
| 记录数 | 150 余条 | 10 条 | 按核对值 |
| 内容 | 含室颤、二联律、噪声段 | 仅 Fig.3 与 Fig.4 两族 | 按核对值 |
| 判读 | 疑似自带标注 | 仅插图编号注释 | 按核对值 |
| 定位 | 生理信号 | 生理信号(一致) | 保留 |
常见误读(避坑清单)
这些误读大多来自同一个源头:把 §4.4 的案例那样的测试向量,当成一批可以拿来算分的样本。下表逐条给出说法、实际与证据。
| 说法 | 实际 | 证据 |
|---|---|---|
| 这是一个心律失常波形库,有一百多条记录 | 共十条记录,两个插图家族 | 文件目录与 RECORDS 清单只有十行 |
| 里面有室颤、停搏、二联律 | 只有 Figs.3 与 4 对应的两类波形 | 十条头文件注释仅标注插图编号 |
| 下载后就能算出报警准确率 | 数据无标注文件,判据在付费正文 | 头文件仅四五行,无事件标记 |
| _d 是双幅版、_h 是半幅版 | 正好相反,_d 为半幅、_h 为双幅 | 数据集页面明文说明命名与实际相反 |
| 数据开放所以标准也可自由分发 | 波形 ODC-BY 1.0,正文受版权保护 | 页面许可与出版方说明 |
| 合成波形质量差,应换真实数据验收 | 验收要求可复现,合成是要求不是妥协 | 固定输入 + 校验和 |
| 是 PhysioNet 收录的所以经过质量认证 | 平台负责托管与格式规范,不做判读 | 页面写的是使用条款与引用信息 |
| 在 AAMI 波形上通过等于临床可用 | 只说明边界条件下未越界 | 无人群、无阴性对照 |
| 十条记录说明数据过时无用 | 插图未变,标准地位未变 | 版本 1.0.0 自 2003 年未改 |
| 可以直接并入 CinC 2015 一起训练 | 采样率、任务、标注形态全不同 | 720 Hz 单通道无标注 vs 多路有标签 |
FAQ
Q1:AAMI EC13 是数据集还是标准?
两者都是,但主次必须分清:AAMI EC13 是一份付费的国家标准,PhysioNet 上开放的是它配套的十条测试波形。波形离开正文就没有判读依据。
Q2:只有十条记录,能做机器学习吗?
不能当作训练集或统计意义上的测试集。它的用途是确定性验收:把算法固定下来,逐条看在大幅值、快心率、突变等条件下的输出是否正确。
Q3:为什么测试信号多是合成的?
合规测试需要可复现。真实患者无法按需反复出现室颤或心率突变,合成信号能精确控制幅值、心率与突变时刻,换一家实验室也得同一结果。
Q4:在 AAMI 波形上跑通,是否等于在 MIMIC 上也好?
不等于。AAMI 检验的是边界条件下的确定性行为,MIMIC 一类数据检验的是真实分布上的统计表现,两者互补但不能互替。
Q5:记录名里的 _d 和 _h 是什么意思?
页面明确说明命名与实际相反:_d 是半幅 0.5x,_h 是双幅 2x。头文件注释也写明了倍率,可直接核对。
Q6:aami4 开头的记录为什么前面有一段规则波?
因为标准要求心动过速波形在另一段合成波形之后突然呈现,前置的约三十秒三角波就是「事件之前」的稳态,用来检验检测器对突变的响应。
Q7:缺少标注怎么办?
不需要补标注。判据写在标准正文里,补一套标注反而会造成两套答案。要做统计评测,请换用带标签的公开数据库。
Q8:为什么增益每条都不一样?
倍率版本通过增益区分:半幅、原幅、双幅对应三档增益。这是同一母波的派生方式,换算成毫伏后幅值才可比。
Q9:它和 CinC 2015 是什么关系?
互补。CinC 2015 用真实重症波形加人工真假标签评估假报警抑制,本篇用固定边界波形做验收。前者回答平均表现,后者回答是否越界。
Q10:今天还该用 2002 年版吗?
波形本身可用,因为它对应标准插图且未变;但合格判定必须依据当前适用的规范版本,引用时要写清版本与条款位置。
Q11:能不能拿它当论文的主要实验结果?
不建议。样本量与标注形态都不支撑统计结论。可以作为极端条件下的补充对照,并如实说明证据层级。
Q12:为什么没有患者信息?
它不按患者组织。测试对象是设备,输入是信号,患者层面的信息既不必要也会带来隐私与许可负担。
术语表
| 术语 | 含义 | 在本篇的位置 |
|---|---|---|
| AAMI | 美国医疗器械促进协会 | 标准制定方 |
| EC13 | 心电监护仪、心率计与报警的标准编号 | 全篇对象 |
| 测试波形 | 用于验收设备行为的固定信号 | §2 主体 |
| 心率计 | 从心电中估算心率的模块 | §3.1 对比对象 |
| 报警时延 | 事件发生到报警的间隔 | §3.2 核心指标 |
| 假报警 | 无相应事件却报警 | §3.2 张力来源 |
| Fig.3 / Fig.4 | 标准文档中的插图编号 | 记录名来源 |
| 倍率版本 | 同一母波的半幅与原幅与双幅 | 六条 Fig.4 记录 |
| 三角波前置 | 突变之前约三十秒的稳态 | §4.4 的案例 |
| WFDB | 生理信号存储与交换格式 | §2.2 字段 |
| 头文件 | 描述采样与增益的纯文本 | §2.2 |
| 数据文件 | 定长整型采样序列 | §2.2 |
| 增益 | ADC 计数与毫伏的换算系数 | §2.3 |
| ADC 零点 | 数字量的基线值 | §2.3 |
| 校验值 | 全段求和的定点校验 | §5.1 |
| ODC-BY | 开放数据署名许可 | 数据许可 |
| 合规验收 | 按标准判定的合格与否 | §1 定位 |
| 统计评测 | 按人群分布的平均表现 | §3 对比 |
| 确定性输入 | 每次运行完全相同的信号 | §4.1 |
| 半合成 | 真实素材加参数化改造 | §4.2 |
| 回归测试 | 改动后与基线比对 | §5.6 |
| 基线快照 | 冻结的结果记录 | §5.6 |
| DAIMS | 数据质量五维框架 | §7.1 |
| 规则波 | 用于建立基线的稳定形态 | §4.4 |
| 突变 | 节律在短时间内的跳变 | §4.4 |
附录 A:核心数字核对表
| 项 | 值 | 来源 | 来源层级 |
|---|---|---|---|
| 记录数 | 10 | RECORDS 清单 | 一级 |
| 采样频率 | 720 Hz | 数据集页面与全部头文件 | 一级 |
| 分辨率 | 12 位 | 数据集页面与头文件 | 一级 |
| 通道数 | 1 | 全部头文件 | 一级 |
| 总未压缩体量 | 1.1 MB | 数据集页面 | 一级 |
| 版本号 | 1.0.0 | 数据集页面 | 一级 |
| 发布日期 | 2003-01-03 | 数据集页面 | 一级 |
| DOI | 10.13026/C2WC7M | 数据集页面 | 一级 |
| 数据许可 | ODC-BY 1.0 | 数据集页面 | 一级 |
| 对应标准版次 | 2002 年版 | 数据集页面引用 | 一级 |
| 参考条款 | 5.1.2.1 节 (e)(g) 段 | 数据集页面 | 一级 |
| 前置三角波 | 约 30 秒 | 数据集页面 | 一级 |
| aami3a 采样点数 | 43,081 | 头文件 | 一级 |
| aami3d 采样点数 | 34,511 | 头文件 | 一级 |
| aami4a 采样点数 | 65,211 | 头文件 | 一级 |
| Fig.3 组增益 | 130 | 头文件 | 一级 |
| Fig.4 组增益 | 40 / 80 / 160 | 头文件 | 一级 |
| 合成与真实的比例 | 未公开 | 页面未逐条说明 | 未核实 |
| 标准正文条款全文 | 未获取 | 需付费 | 未核实 |
附录 B:数字的来源分层
第一级:官方页面与头文件。 数据集页面的说明文字给出记录性质、采样规格、许可、版本与条款位置;十条头文件给出采样点数与增益。这一级的数字可逐字复核,本篇的规模与结构描述全部出自此。
第二级:论文摘要。 假报警在重症病房普遍存在、单导联伪差是主要成因这两点,来自 Europe PMC 收录的摘要,只读摘要未取全文。摘要给出的是背景事实,不是本篇数据的属性。
第三级:推算。 时长由采样点数除以采样频率得到,是确定的算术;「总时长十二分钟上下」是十条时长求和后的概数;「覆盖六种边界条件」一类表述是归纳,不是官方口径。
| 层级 | 来源 | 可信度 | 本篇用法 |
|---|---|---|---|
| 一级 | 数据集页面、十条头文件、目录清单 | 高,可逐字复核 | 规模、字段、许可、条款位置 |
| 二级 | Europe PMC 论文摘要 | 中高,经同行评议 | 背景事实,不用于数据属性 |
| 三级 | 算术推算与归纳 | 中,可自行重算 | 时长、概数、分类归纳 |
附录 C:完整参考文献
- Association for the Advancement of Medical Instrumentation. Cardiac monitors, heart rate meters, and alarms (ANSI/AAMI EC13:2002). Arlington, VA: AAMI, 2002.
- PhysioNet. ANSI/AAMI EC13 Test Waveforms, version 1.0.0. 2003. DOI: 10.13026/C2WC7M. https://physionet.org/content/aami-ec13/1.0.0/
- Moody G. WFDB Software Package. PhysioNet. DOI: 10.13026/gjvw-1m31.
- Harriott F. ECG waveform generator for Matlab/Octave. PhysioNet. https://physionet.org/content/ecgwavegen/
- Falasca A, et al. Reduction of false alarms in the intensive care unit using an optimized machine learning based approach. npj Digital Medicine, 2019;2:86. DOI: 10.1038/s41746-019-0160-7
- Aboukhaled K, et al. Reducing false alarm rates for critical arrhythmias using the arterial blood pressure waveform. Journal of Biomedical Informatics, 2008. DOI: 10.1016/j.jbi.2008.03.003
附录 D:任务代码
任务一:逐条核验头文件与页面是否一致。 输出一张表,把采样率、时长、增益、插图编号并排列出,用于交稿前自证。
#-- 逐条读头文件,核对采样率与插图注释
import re
import urllib.request
BASE = "https://physionet.org/files/aami-ec13/1.0.0/"
names = urllib.request.urlopen(BASE + "RECORDS").read().decode().split()
for n in names:
txt = urllib.request.urlopen(BASE + n + ".hea").read().decode()
lines = txt.strip().splitlines()
head = lines[0].split()
fs, npts = int(head[2]), int(head[3])
note = next((ln for ln in lines if ln.startswith("#")), "")
fig = re.search(r"Figure\s*\w+", note)
print(n, fs, round(npts / fs, 1), fig.group(0) if fig else "-")
任务二:把十条记录画成一张缩略图,人工过目。 画出来的图能一眼看出前置三角波与倍率差异,比读数字直观。
#-- 十条记录压平成一行小图,便于人工检查形态
import matplotlib.pyplot as plt
import wfdb
names = ["aami3a", "aami3b", "aami3c", "aami3d",
"aami4a", "aami4a_d", "aami4a_h",
"aami4b", "aami4b_d", "aami4b_h"]
fig, axes = plt.subplots(len(names), 1, figsize=(12, 10), sharex=True)
for ax, n in zip(axes, names):
rec = wfdb.rdrecord(n, pn_dir="aami-ec13/1.0.0")
t = [i / rec.fs for i in range(rec.sig_len)]
ax.plot(t, rec.p_signal[:, 0], lw=0.4)
ax.set_ylabel(n, rotation=0, ha="right", fontsize=8)
axes[-1].set_xlabel("seconds")
plt.tight_layout()
plt.savefig("aami-ec13-overview.png", dpi=150)
| 任务 | 输入 | 输出 | 用途 |
|---|---|---|---|
| 头文件核对 | RECORDS 清单 | 规格表 | 交稿自证 |
| 缩略图 | 十条记录 | 一张 PNG | 人工过目 |
| 基线表 | 十条记录 | json | 回归对照 |
| 漂移比对 | 两份 json | 差异清单 | 版本管理 |
附录 E:如果只记五件事
- 它是标准的附属物,判据写在付费正文里,不在数据里。
- 十条记录、十二分钟上下、1.1 MB,规格极简,边界极清晰。
- _d 是半幅、_h 是双幅,与字面相反,读头文件再统计。
- 合规看「逐条是否越界」,统计看「平均表现」,两者不可互替。
- 把它当标尺,不要当矿山。
编辑说明
本篇于 2026-10-27 完成核验。资料来自两处:数据集主页与文件目录,以及十条记录的头文件。头文件逐条读取,采样点数、增益、插图注释均为文件原文,未做推断。论文证据来自 Europe PMC 摘要检索,只读摘要,未取全文。
未覆盖的内容包括:标准正文的全部条款与判读门槛、真实与合成波形的逐条对应关系、测试台的搭建与计量要求、设备端报警逻辑的具体实现。这些无法从公开资料确认,已在相应位置标注为未核实。
页面对命名问题的说明与头文件注释可直接对照:页面称 _d 为半幅、_h 为双幅,头文件注释分别写 0.5x 与 2x,两者一致。Fig.3d 时长明显短于同组其余三条,页面未提供解释,本篇按头文件如实列出,未对原因作推断。
派发材料中关于本资源规模与内容的描述(一百多条记录、含室颤与二联律)与核对结果不符,已按核对值写作,并在 §10.1 与避坑清单中说明。
本篇定位为数据集百科,不是合规指南。任何依据本篇做出的合格与否判断均不成立,送检请以标准正文与法定检验机构结论为准。
相关数据集导航
以下为站内 AI-Ready 数据集百科中与本词条共享多个主题标签的相关数据集,按相关度降序排列:
- argo — 共享标签:生理信号 / 心电信号
- icehg-ds — 共享标签:生理信号 / 心电信号
- meditation — 共享标签:生理信号 / 心电信号
- nifecgdb — 共享标签:生理信号 / 心电信号
- deap — 共享标签:生理信号 / 医疗NLP
- ecg-capable-smartwatches — 共享标签:生理信号 / 心电信号
- szdb — 共享标签:生理信号 / 心电信号
- edb — 共享标签:生理信号 / 心电信号
- wctecgdb — 共享标签:生理信号 / 心电信号
- adfecgdb — 共享标签:生理信号 / 心电信号
导航说明:本章节由全站统一标签体系自动计算生成(标签重合度算法),双向可达;点击链接可跳转至对应数据集词条。

