一百条两分钟心电 — TWADB 微伏级交替库

100 条 / 70 条真实 + 32 条合成 / 105 MB

来源 https://physionet.org/content/twadb/1.0.0/发布时间: 2026-10-28最后更新: 2026-10-28 阅读 10
一百条两分钟心电 — TWADB 微伏级交替库

信息速览

数据集名称一百条两分钟心电 — TWADB 微伏级交替库
数据类型时序信号,波形,元数据,原始数据链接
规模100 条记录(70 条真实 + 32 条合成),真实部分来自 53 份原始记录
接入方式https://physionet.org/content/twadb/1.0.0/
AI 就绪度

T-Wave Alternans Challenge Database(下称 TWADB)是 PhysioNet 为第九届 PhysioNet/Computers in Cardiology 挑战赛组装的题库,2008 年 9 月 22 日以 1.0.0 版发布。它收录 100 条多通道心电,每条约两分钟,500 Hz 采样、16 位精度,多数是标准十二导联,少数只有 2 至 3 路信号;配套的还有一份把 100 条记录从低到高排序的参考名次表。整包未压缩 105.0 MB,按 ODC-BY 1.0 开放,作者是 MIT 计算生理实验室的 George B. Moody。

它要抓的现象叫 T 波交替(T-wave alternans,TWA):同一导联上相邻心搏的 T 波一强一弱地交替,幅度常在微伏级。这类差异在常规显示尺度下看不见,靠肉眼判读不可能,只能交给算法;而算法要证明自己会看,就需要一批「答案已知」的波形。TWADB 就是为这件事准备的:它不提供微伏真值,提供的是一个排序——哪条记录的交替比哪条更强。

这决定了它的用法与绝大多数心电库不同:它更像一份考卷而不是一本教材,能验证你的方法会不会排序,不能告诉你某个人的 TWA 是多少微伏。它的价值集中在复极末段这一微小尺度上,与 ST 段偏移那类毫伏级改变不是同一件事。一屏速览见下表。

维度 内容
全名 T-Wave Alternans Challenge Database
简称与目录名 TWADB / twadb
发布方 PhysioNet(MIT Laboratory for Computational Physiology)
作者 George B. Moody
首次发布 2008 年 9 月 22 日,1.0.0 版
缘起 第九届 PhysioNet/Computers in Cardiology 挑战赛(2008)
记录数 100 条(twa00 至 twa99)
来源构成 70 条真实片段 + 32 条合成波形;真实片段来自 53 份原始记录
导联 多数 12 导联,少数 2 或 3 路
采样与精度 500 Hz,16 位,标称正负 32 毫伏
单条时长 约两分钟(按头文件样本数折算 120 至 129 秒)
文件构成 每条 .hea + .dat + .qrs 三件套
标注 QRS 心搏时刻;另有独立参考名次表(1 至 100)
体积 未压缩 105.0 MB
许可 ODC-BY 1.0
DOI 10.13026/C2B59B
官方入口 https://physionet.org/content/twadb/1.0.0/

§1 它要解决的具体麻烦

1.1 一个看不见、测不准、却和猝死挂钩的现象

T 波交替的描述很朴素:同一导联上,相邻心搏的 T 波在两个(偶尔更多)形态之间轮替。它不是 T 波变高变矮,而是整个复极末段的形状在两拍之间来回切换。官方给了一个关键限定:这种现象一般出现在病人自身心率升到每分钟 90 至 120 次时,静息心率下往往看不见。

它的麻烦在于三个「不」,每个都直接决定了数据该怎么组织。

难点 具体表现 官方依据
不可见 微伏级的幅度,在标准显示尺度下用眼睛看不出来 1981 年 Adam、Akselrod、Cohen 首次报告微伏级 TWA
被当成罕见 Hering 首次报告之后整整一个世纪都被视为罕见征象 官方称首次报告已是一百年前的事
不可测 要与基线漂移、呼吸调制、电极接触、肌电干扰区分 官方列举十余类算法并存
无公认标尺 频谱、复解调、过零计数、Capon、Poincaré、似然比等方法各说各话 方法多到本身就说明「怎么量」没有定论

官方页面把可用方法分成几大族,各族的输入与盲区不同,这也是「没有公认标尺」的技术根源。

方法族 代表做法 依赖什么 主要盲区
频域 频谱分析、周期图、Capon 滤波 交替的周期稳定性 非平稳段与心率漂移
解调 复解调、主成分周期图 载频附近的窄带能量 载频估计误差
相关类 相关系数过零计数、Poincaré 映射 逐拍形态相似度 噪声与异位搏动
统计类 最大似然、广义似然比、移动平均 噪声模型假设 模型失配

于是这个领域长期存在一个尴尬:现象被公认与猝死风险相关,量化却没有金标准。TWADB 的设计正是绕开这个尴尬——它不比绝对值,比排序。

难点 具体表现 对数据的要求
不可见 微伏级,标准尺度下看不出 需要高分辨率数字波形,不靠图
只在特定心率出现 官方称多在每分钟 90 至 120 次 记录里得真有这个心率段
与呼吸调制混淆 呼吸本身让 T 波幅度周期起伏 需要足够长,能分辨两种周期
无公认量法 官方列出十余类算法并存 需要一份大家都能对着比的题库
与 ST 段改变不同层 ST 是毫伏级偏移,TWA 是微伏级交替 不能用同一套标注习惯对待

1.2 三条常见的错误期待

三条期待都落空,但落空的方式不同,纠正起来也不同。

错误期待 会被读成什么 实际是什么 纠正办法
有逐条微伏真值 以为是带量化标签的训练集 只有 1 至 100 的序数名次 改用排序指标,别做回归
是心律失常分类库 以为能拿来训诊断模型 无诊断无节律,心搏全标正常 换带诊断的心电库
是自然人群样本 以为能算患病率与分布 32 条合成,70 条选摘片段 只做方法学,不做人群推断

第一条需要额外说明:官方确实要求参赛者「估一个峰值幅度」,但那只用于生成内部名次,单位随意、只要求同一份提交内部一致;组织方从未把任何一份估计当真值公开。

常见期待 实际情况 依据
有逐条 TWA 微伏标注 只有 1 至 100 的参考名次 官方 about-records.txt 第 2 列
是心律失常分类库 无诊断、无节律标签,心搏全标正常 官方 Data Description
是人群样本 32 条合成,70 条真实来自 53 份原始记录 官方来源表逐行统计
是十二导联统一格式 多数 12 导联,少数 2 或 3 路 头文件首行通道数
是新建采集 全部来自已有库的片段与合成 官方来源表第 3、4 列

1.3 它能给到的与给不到的

先看它真正给得出来的四件事。

你的需求 它给的 够不够
验证 TWA 检测算法的排序能力 100 条混排记录 + 一份参考名次 够,这是它唯一的原生用途
研究微伏级交替的波形形态 500 Hz、16 位、十二导联的真实片段 够,且分辨率优于多数 Holter 库
提取带标定幅度的合成信号 32 条合成波形,含注入 TWA 的一批 够,适合做方法自检
观察同一病人在不同时段的交替 同一原始记录被切成多段 勉强,能对比但不能定位时间

再看它给不出来的五件事,这些不是缺得可惜,而是结构上不可能。

你的需求 它给不了什么 原因
拿到可回归的微伏标签 只有序数名次,无名次到幅度的换算 官方只按排序计分
做心梗或心律失常分类 无诊断标签,心搏注释不分类型 标签层为空
评估跨人群泛化 来源混杂且无人口学字段 无法分层
训练端到端深度模型 无官方划分,同源记录跨段 须自建按来源分组
与 ST 段改变做同批比较 仅含 ST 库片段,不含 ST 标注 需回源库取标注

1.4 你的处境与它能帮到的事

做研究与做工程的处境不同,先按角色对号。

你的处境 它能帮你什么 下一步该做什么
你写了一个 TWA 检测器,苦于没有公认题库对照 提供与 2008 年挑战赛同一份记录与同一套排序口径 用 Kendall tau 复算自己的名次,与官方名次比
你要向评审专家证明方法不是过拟合 100 条里 32 条是合成,可单独拿出来做留出 按来源分组切分,合成组只做测试
你在做复极微伏级变化的信号处理 500 Hz、16 位、增益明确的十二导联片段 先用 0.5 微伏量化步长核对噪声底
你在复现 2008 年挑战赛的榜单 参考名次、参赛论文、开源代码都在 从挑战赛项目页取 about-records 与论文

使用者未必都是算法岗,另三种处境更常见。

你的处境 它能帮你什么 下一步该做什么
你手上只有静息短记录,看不到交替 来源里含运动负荷与 Holter 片段,心率更高 先按 RR 间期筛出高心率段再分析
你要做心电基础模型的自监督预训练 100 条两分钟、格式统一、许可宽松 只当预训练语料的一小撮,不要当评测集
你需要判断某个病人是否需要 ICD 无个体诊断、无随访结局 换带结局的队列数据,别用它

1.5 一句话判断

它是一份考卷而不是一本教材:不给微伏答案,只给谁比谁强的排序,用来证明你的算法真的会看那一点点交替。

1.6 不适合谁:四条边界

四条边界各自对应一类会被劝退的需求,先看清楚再决定要不要往下读。

不适合谁 触发条件 后果 该去哪里
要绝对幅度的人 报告需写成「TWA 为 3.2 微伏」 名次无换算关系 自建标定或只报排序
做监督分类的人 需要诊断、节律或结局标签 标签层为空 换带诊断的心电库
按记录随机切分的人 默认样本独立同分布 同源片段跨集,指标虚高 按来源记录分组
当人群样本的人 想算患病率或幅度分布 来源经挑选且含合成 换队列或筛查数据

其中第二条最容易被低估。没有诊断标签不只是「少一列」,而是整条监督学习链路都缺因变量:既不能做二分类,也不能做多标签,连弱监督都要自己另找标签源。第三条则相反,它看起来只是一行代码的差别,实际决定了你报出的指标能不能站住。

边界 触发条件 后果 替代做法
绝对幅度 报告需给微伏数 名次无换算关系 自建标定,或只用排序结论
监督分类 需要诊断或节律标签 标签层为空 换带诊断的心电库
独立同分布假设 按记录随机切分 同源片段跨集,指标虚高 按来源记录分组切分
人群推断 需要患病率或分布 来源经挑选且含合成 换队列或筛查数据

§2 数据构成与规格

2.1 一个扁平目录,三个文件一条记录

下载解开后是一个没有子目录的文件夹,100 条记录平铺在同一层,文件名就是 twa 加两位流水号,从 twa00 排到 twa99。每条记录由三个同名文件组成,扩展名分别是 hea、dat、qrs。目录里另有三份非记录文件:记录清单、注释器清单、校验清单。官方用一句话交代了这个结构,没有提供任何结构化索引或元数据表。

值得注意的是编号与内容无关。编号是混排的,想按来源分组必须去读另一份来源表。

编号 来源代码 原始记录 通道数
twa00 sdd sddb/30 2
twa01 syn stwdb/c111 12
twa04 lts ltstdb/s30801 3
twa34 syn stwdb/a112 12

光看编号猜不出来源。

层级 文件 数量 说明
根目录 无子目录 1 全部记录与清单混放
头文件 twaNN.hea 100 文本,给出通道数、采样率、增益、导联名
数据体 twaNN.dat 100 二进制,16 位整数交错存放
心搏注释 twaNN.qrs 100 二进制,WFDB 注释格式,仅 QRS 时刻
记录清单 RECORDS 1 约 600 字节,每行一条记录名
注释器清单 ANNOTATORS 1 21 字节,只有一行 qrs beat annotations
校验清单 SHA256SUMS.txt 1 22.1 KB,2019 年 2 月 20 日补入
参考名次表 不在本库内 1 在挑战赛项目页,文件名 about-records.txt

体积上有一个可以直接观察的规律:.dat 的大小与通道数成正比。

通道数 典型 .dat 体积 折算采样点 折算时长
2 路 234.4 KB 59999 约 120 秒
3 路 351.6 KB 59999 约 120 秒
12 路 1.3 至 1.4 MB 61415 至 64513 约 123 至 129 秒

换算下来都是约六万个采样点乘 2 字节乘通道数。整包未压缩 105.0 MB,其中绝大部分是十二导联记录的波形数据。

2.2 字段与记录的完整字典

这个库没有字段表。所有结构化信息都在头文件里,而头文件只描述波形怎么解码,不描述这条记录是谁、从哪来、有没有病。下表把能从头文件与来源表里读到的信息合并列出,并标明哪些字段本库不提供。

信息项 存放在哪 取值或范围 是否每条都有
记录名 文件名 twa00 至 twa99 是
通道数 头文件首行第 2 列 2、3 或 12 是
采样率 头文件首行第 3 列 500,或 500/250 是
采样点数 头文件首行第 4 列 约 59999 至 64513 是
数据文件名 通道行第 1 列 与记录同名加 .dat 每通道一行
存储格式 通道行第 2 列 16(16 位整数) 每通道一行
增益 通道行第 3 列 2000 ADC 单位/毫伏 每通道一行
ADC 分辨率 通道行第 4 列 16 每通道一行
ADC 零点 通道行第 5 列 0 每通道一行
初始值 通道行第 6 列 各通道不同 每通道一行
校验和 通道行第 7 列 各通道不同 每通道一行
块大小 通道行第 8 列 0 每通道一行
导联名 通道行第 9 列 I 至 V6,或 ECG1/ECG2,或 E-S/A-S/A-I 每通道一行

上表是解码波形所需的最小集合,缺一项就读不出正确的毫伏值。下表是标签与来源侧的信息,它们不在头文件里,而在库外那份来源表里。

信息项 存放在哪 取值或范围 是否每条都有
心搏时刻 .qrs 注释 采样点序号 是
心搏类型 .qrs 注释 一律为正常 是
参考名次 来源表第 2 列 1 至 100 是
来源库代码 来源表第 3 列 inc/lts/nsr/ptb/ptbc/sdd/syn/sync 是
原始记录名 来源表第 4 列 如 ltstdb/s30801 是

还有一类信息本库完全不提供,它们恰恰是多数下游任务最想要的。

缺失信息 官方是否提供 影响的下游任务
年龄 否 年龄分层、儿科与成人对比
性别 否 性别差异分析
诊断 否 一切监督分类
用药 否 药物对复极的影响
采集设备 否 设备间域偏移分析
采集日期 否 季节与昼夜效应
信号质量标注 否 质量筛选与加权
TWA 微伏值 否 绝对幅度回归

有一处容易读错:通道行里的初始值与校验和逐通道不同,那是 WFDB 的解码起点与数据校验,不是病人编号,也不是设备序列号。另一处是 500/250 这种写法,它表示采样率 500 Hz、而时间基准的计数器频率是 250 Hz——含义见 §2.4。

2.3 一条记录的完整解剖

取 twa04。它是全库真实片段里名次第三高的一条,来源是长时程 ST 库的一份三通道记录 ltstdb/s30801,两个信息都写在来源表里,头文件里看不出来。

#-- 头文件是纯文本,一条 curl 就能看完,不必下载整包
curl -s https://physionet.org/files/twadb/1.0.0/twa04.hea

返回四行。

twa04 3 500/250 59999
twa04.dat 16 2000 16 0 -5210 15678 0 E-S
twa04.dat 16 2000 16 0 331 6102 0 A-S
twa04.dat 16 2000 16 0 280 -30003 0 A-I

四行文本各有分工,读法如下。

行 字段 本例取值 含义
首行 记录名 twa04 与文件名一致
首行 通道数 3 决定 .dat 里交错几路
首行 采样率/计数器 500/250 波形 500 Hz,注释基准 250 Hz
首行 采样点数 59999 三路各自的长度
通道行 存储与增益 16 2000 16 0 16 位、2000 单位/毫伏、零点 0
通道行 初始值与校验 -5210 15678 解码起点与校验,非病人编号
通道行 导联名 E-S 长时程库的三通道命名

三个导联名 E-S、A-S、A-I 是长时程库的命名,官方未在页面上解释缩写含义,也未给电极位置。

把 2000 单位/毫伏与 16 位整数放在一起算,可用的量程约为正负 16.4 毫伏,相邻整数之间的电压差是 0.5 微伏。这个数字很关键:TWA 常在几微伏量级,也就是说它只占四到二十个最小刻度。

量 数值 算法 性质
增益 2000 ADC 单位/毫伏 头文件通道行 官方给出
位深 16 位有符号 头文件通道行 官方给出
可表示量程 约正负 16.4 毫伏 32768 ÷ 2000 推算
量化步长 0.5 微伏 1000 ÷ 2000 推算
TWA 典型幅度 几微伏,约 4 至 20 个刻度 文献量级 定性

官方摘要把量程写作正负 32 毫伏,与按增益算出的正负 16.4 毫伏差一倍,两个口径并存,官方未说明差额来源;对使用者而言,有意义的是 0.5 微伏这个量化步长,它决定了微伏级分析的下限。

#-- 读一条记录:信号、导联名、采样率、心搏时刻
import wfdb

rec = wfdb.rdrecord("twa04", pn_dir="twadb/1.0.0")
ann = wfdb.rdann("twa04", "qrs", pn_dir="twadb/1.0.0")

print(rec.record_name, rec.sig_name)        #-- ['E-S', 'A-S', 'A-I']
print(rec.fs, rec.sig_len)                  #-- 500 59999
print(rec.p_signal.shape)                   #-- (59999, 3)
print(len(ann.sample), ann.symbol[:5])      #-- 心搏数与头五个心搏类型

跑完之后会看到 rec.fs 是 500,rec.sig_len 是 59999,rec.p_signal 的形状是五万九千九百九十九行三列,单位已按增益换算成毫伏。ann.symbol 里全是 N,这不是「这条记录没有异位搏动」的证据,而是官方在说明里明确写过的一句话:少数记录含有异位搏动,但所有心搏在 .qrs 文件里一律标成正常。

2.4 采样、计数器与那 4 毫秒的网格

官方摘要给的是「500 Hz、16 位、正负 32 毫伏」三个统一数字,但逐条看头文件会发现采样率一栏有两种写法:500 与 500/250。前者表示采样与时间基准都是 500 Hz,后者表示波形以 500 Hz 存储,而注释时间戳的计数器只有 250 Hz。

记录 通道数 采样率字段 采样点数 折算时长 心搏时刻精度
twa00 2 500/250 59999 120.0 秒 4 毫秒
twa02 2 500/250 59999 120.0 秒 4 毫秒
twa04 3 500/250 59999 120.0 秒 4 毫秒

十二导联那一组则是另一种情形。

记录 通道数 采样率字段 采样点数 折算时长 心搏时刻精度
twa34 12 500 61415 122.8 秒 2 毫秒
twa01 12 500 61551 123.1 秒 2 毫秒
twa72 12 500 64513 129.0 秒 2 毫秒

这张表说明两件事,第二件比第一件更容易被忽略。

观察 含义 后果
时长落在 120 至 129 秒 官方说的「约两分钟」准确,最长最短差约 7% 切窗长度按 120 秒设才不丢信息
心搏时刻精度不统一 250 Hz 源的片段只能落在 4 毫秒网格 逐拍对齐会引入系统偏差

做逐拍对齐、算 T 波窗口内的差值时,4 毫秒的抖动足以让微伏级的比较产生系统偏差,因此要么统一重采样到同一网格,要么按计数器频率分组处理。

2.5 与库内同类心电资源的规格差异

心电库里「标注」二字的含义差别极大。下表把库内几个常被拿来比较的 PhysioNet 心电库按规格排开,重点看标注层级与记录形态,而不是看谁更大。

资源 记录形态 单条时长 标注层级 与本库的关系
TWADB 2 至 12 路片段 约 2 分钟 仅 QRS 时刻 + 外部名次 本库
LTSTDB 2 或 3 路 Holter 21 至 24 小时 逐搏 + ST 事件 + 节律 + 临床摘要 本库 12 条片段的来源
MIT-BIH ST Change 2 路运动负荷 20 至 40 分钟 无注释、无临床对应 与 ST 段改变同族,未进本库
MIT-BIH VFDB 2 路 Holter 数十分钟 室颤、室速事件 恶性室性心律失常,事件级
MIT-BIH NSRDB 2 路 Holter 约 24 小时 心搏 + 信号质量 本库 6 条片段的来源
PTB Diagnostic 12 导联 + 3 Frank 约 2 分钟 临床摘要 本库 30 条片段的来源

看完这张表就能明白 TWADB 的位置:它把几类形态完全不同的记录强行拉平成「两分钟、500 Hz、十六位」的统一格式,代价是丢掉了所有源库的标注,只留下 QRS 时刻,再在库外补一份排序。它换来的是一份可以横向比较的同构题库。

维度 TWADB 的取舍 对使用者的含义
时长 截到约两分钟 记录数够多,单条信息量少
导联 保留源库原样(2、3、12) 需处理变长通道
标注 只保留 QRS 节律、ST、质量标签全部丢失
真值 库外名次 标签与波形分离在两个地址
人群 混合来源 无法做分层或患病率

§3 身份层:这一百条记录到底是谁的

3.1 一个人的组装,一个学会的年会

TWADB 的作者栏只有 George B. Moody 一人,隶属 MIT 计算生理实验室,也就是 PhysioNet 的运营方。这个身份组合解释了它的性质。

项目 内容 含义
作者 George B. Moody(单人署名) 组装者即平台运营方
机构 MIT Laboratory for Computational Physiology PhysioNet 的所在地
发布日 2008 年 9 月 22 日 与挑战赛公布成绩同日
版本 1.0.0 定版后未再修订
性质 竞赛题库 不是独立采集的临床数据库

挑战赛本身从 2008 年 3 月 17 日启动。官方页面把这次比赛称为这一系列年度公开挑战赛的第九届,主题是 T 波交替的检测与量化。参赛者要在 9 月 1 日中午之前提交一份纯文本报名表,为每条记录填一个 TWA 峰值幅度估计;如果方法只能检测不能量化,检测到的填 1,未检测到的填 0。另有开源组,提交源代码即可参与,两组都可以拿奖。

时间 事件 出处
2008-03-17 挑战赛启动,主题定为 TWA 检测与量化 挑战赛项目页
2008-04-17 数据提名截止 挑战赛项目页
2008-04-27 首批成绩开始回邮 挑战赛项目页
2008-08 最终参考名次汇总 挑战赛项目页
2008-09-01 报名与源码提交截止 挑战赛项目页
2008-09-17 会议全体会议颁奖 挑战赛项目页
2008-09-22 本库 1.0.0 发布,成绩公布 本库页面
2019-02-20 补入 SHA256SUMS 校验清单 目录时间戳

3.2 八类来源代码:一份混编的名单

这是 TWADB 最容易被忽略、也最该先看的一张表。官方在挑战赛项目里放了一份纯文本来源表,第 3 列用三个字母的代码标明每条记录的出身,第 4 列给出原始记录名。八类代码覆盖了三种性质完全不同的东西:真实临床记录、真实健康记录、人工合成波形。

代码 含义 原始库 本库中的例子
inc 圣彼得堡心电技术研究所十二导联心律失常库 INCART twa12 ← incartdb/I24
lts 长时程 ST 库 LTSTDB twa04 ← ltstdb/s30801
nsr MIT-BIH 正常窦性心律库 NSRDB twa10 ← nsrdb/19090
ptb PTB 诊断心电库(患者部分) PTB 诊断库 twa11 ← ptbdb/patient049/s0178lre
ptbc PTB 诊断心电库(健康受试者部分) PTB 诊断库 twa39 ← ptbdb/patient243/s0472_re
sdd 猝死 Holter 库 SDDB twa00 ← sddb/30
syn 注入标定幅度 TWA 的合成心电 STWDB twa34 ← stwdb/a112
sync 不含 TWA 的对照合成心电 STWDB twa52 ← stwdb/f001

真实部分的六个代码对应五个人们熟悉的心电库(PTB 的患者与健康两部分算两类记录),合成部分的两个代码同出一源。分组时可以先按「真实/合成」切一刀,再按母库切第二刀。

分组维度 分组结果 组数 用途
真实 / 合成 六个真实代码 vs 两个合成代码 2 做留出集时最稳的一刀
母库 INCART、LTST、NSR、PTB、SDDB、STWDB 6 分层报告与来源归因
原始记录 53 份真实记录 + 32 条合成 85 交叉验证的分组键

这张表解释了一件事:官方摘要里说的「受试者包括心肌梗死、短暂缺血、室性快速心律失常患者以及健康对照」,其实是把来源库的人群特征转述了一遍,本库自身并不携带任何一个人的诊断。

3.3 一百条记录,五十三份原始记录

把来源表第 3、4 列拼起来去重,可以得到一个比「100 条」更接近真相的数字:70 条真实片段只对应 53 份不同的原始记录。也就是说有十余条真实记录是同一份长记录被切成两段甚至更多段后分别命名的。

层面 数量 说明
文件级记录数 100 twa00 至 twa99,每条三件套
真实片段 70 六个真实来源代码之和
真实原始记录 53 按来源库与原始记录名去重
合成波形 32 syn 与 sync 两类,各自唯一
独立信号源合计 85 53 份真实记录 + 32 条合成波形

重复的形态有两种,都不是错误,而是出题时的正常做法。

重复形态 例子 成因
同一份 Holter 取两段 sddb/52 → twa02 与 twa05 长记录里交替强度随心率变化
同一次十二导联检查取两段 incartdb/I40 → twa26 与 twa27 两分钟窗口可切多段
同一份三通道记录取两段 ltstdb/s30761 → twa14 与 twa32 同上

同一份记录里,交替强度本来就会随心率与时间变化,两段刚好构成一对难易不同的样本。问题是这个设计对建模者不友好:任何按记录随机划分训练集与测试集的做法,都会让同一份原始记录的两段分居两侧,模型只要记住这个人或这段噪声的指纹,就能在测试集上拿到虚高的排序相关性。§4.2 的案例会把这个效应算给你看。

3.4 那三十二条合成波形

合成记录来自一个专门的合成 TWA 库。官方摘要的说法是,库里包含「含有标定幅度 T 波交替的合成病例」,而来源表把合成部分进一步分成 syn(注入 TWA)与 sync(不含 TWA 的对照)两类。命名规律也能看出成对设计:a101 至 a112、b101 至 b111、c101 至 c112、d101 至 d110、e101 至 e112,以及 f000、f001 两个对照。

合成部分的价值在于「答案本来就知道」。真记录的 TWA 幅度要靠算法估计,合成的可以按注入参数反推,因此它适合做方法自检。

用途 做法 前提
单调性自检 在合成组上看估计值是否随注入幅度单调 注入档位需从生成论文查
上限探测 看算法在高幅度端是否饱和 合成最高档即名次 100
通道一致性 同一段十二导联上比较各导联估计 合成多为十二导联
阴性对照 两条 sync 记录不应被判为高交替 f000、f001 两条

真要用它做标定,得回到生成合成的原始论文去核对每个档位的微伏数,本库页面没有给出。

合成族 记录名范围 本库中的编号 类别
a 族 a101 至 a112 twa34、twa50、twa64、twa76、twa79、twa51 syn
b 族 b101 至 b111 twa17、twa29、twa33、twa78、twa97、twa98 syn
c 族 c101 至 c112 twa01、twa15、twa28、twa69、twa88、twa91 syn
d 族 d101 至 d110 twa06、twa09、twa21、twa30、twa67、twa70 syn
e 族 e101 至 e112 twa13、twa35、twa73、twa82 syn

另一类合成是对照组,只有两条。

合成族 记录名范围 本库中的编号 类别
f 族 f000、f001 twa52、twa81 sync

需要提醒的是,合成库自身的项目页在 PhysioNet 上返回 404,官方也没有在本库页面上公布每个注入档位的微伏值。所以「标定幅度」这四个字目前只能当作定性描述:知道答案存在,但无法从公开页面读出具体数字。真要用它做标定,得回到生成合成的原始论文去核对。

3.5 它不属于任何一类常规数据集

把上面几条合起来看,TWADB 的身份很特殊:它既有真实临床波形,又有合成波形;既是一份数据,又是一份考卷;既公开了记录,又把标签放在另一个项目里。

身份维度 它是什么 它不是什么
数据性质 挑战赛题库,赛后定版公开 长期维护的临床数据库
标签形态 库外一份序数排名 库内逐条微伏标注
人群 五个库的片段 + 合成 某个中心、某段时间的连续队列
格式 统一成 500 Hz、16 位的 WFDB 保留源库原始采样与标注
维护状态 2008 年定版,2019 年补校验 有版本迭代与勘误流程

这种结构在 PhysioNet 上并不罕见——挑战赛数据几乎都是这样组织的——但它对使用者提出的要求比普通数据库高:必须同时打开两个地址,才能把波形和标签对上。

§4 质量层:那份名次到底能当多少真值用

4.1 序数不是标尺

参考名次的生成方式写在挑战赛规则里,值得逐句拆开。参赛者为每条记录估一个 TWA 峰值幅度,单位随意,但同一份提交内部必须一致。组织方先按每份提交内部的幅度把 100 条记录排成 1 到 100 的名次;再对每条记录取所有提交名次的中位数;最后按中位数再排一次,得到参考名次。官方来源表里第 2 列就是这个参考名次,数值越大表示被参赛者群体判定为 TWA 越强。

这意味着三件事,每一件都会改变建模时的做法。

推论 具体内容 建模时的后果
集体判断 名次是参赛者估计的产物,不是仪器读数 换一批队伍,名次会变
只保序不保距 相邻名次之间的实际幅度差不等 不能当连续值做回归
受方法谱影响 当年队伍多用频谱类与相关类 名次编码的是「这批方法能否区分」
名次的属性 具体含义 建模时的后果
类型 序数(1 至 100) 只能用排序类指标评估
来源 参赛者估计的中位名次再排序 反映集体判断,非物理测量
间距 不等距 不能当连续值做回归
方向 数值越大 TWA 越强 注意别反向解读
覆盖 100 条全覆盖,无缺失 无「未标注」样本可用作负例

4.2 案例:s30801 的两段,一份记录的两个名次

这是全库最值得摊开看的一处结构。来源表里有两行都指向 ltstdb/s30801:

twa04	3	lts	ltstdb/s30801
twa89	71	lts	ltstdb/s30801

两行的第 3、4 列完全一致,第 2 列相差 68 位。打开两个头文件,通道数都是 3,导联名都是 E-S、A-S、A-I,采样点数都是 59999,采样率字段都是 500/250。也就是说,这是同一份三通道长记录里截出的两个两分钟片段,波形在格式上完全同构,唯一不同的是它们在名次表里的位置:一个排第 3,一个排第 71。

信息点 twa04 twa89 说明
参考名次 3 71 相差 68 位
来源代码 lts lts 同一个库
原始记录 ltstdb/s30801 ltstdb/s30801 同一份记录
通道数 3 3 同构
导联名 E-S / A-S / A-I E-S / A-S / A-I 同构
采样点数 59999 59999 同长
采样率字段 500/250 500/250 同心搏网格
初始值 -5210 / 331 / 280 10 / 61 / 100 片段起点不同

这个案例的含义有三层,从生理一直落到工程。

层次 含义 对使用的约束
生理 同一份记录里 TWA 强度随时间剧烈变化 与官方强调的「与心率相关」一致
标注 名次是片段级标签,不能上推到病人级 只能说这两分钟,不能说这个人
工程 按记录随机切分会让同源片段跨集 必须以原始记录名分组
原始记录 两个片段 名次 名次差
ltstdb/s30801 twa04 / twa89 3 / 71 68
sddb/34 twa22 / twa68 17 / 59 42
sddb/30 twa00 / twa63 1 / 52 51

两边分属不同母库,重复的形态不完全一样。

原始记录 两个片段 名次 名次差
ltstdb/s30721 twa43 / twa77 31 / 57 26
incartdb/I25 twa44 / twa84 32 / 66 34
ltstdb/s30761 twa14 / twa32 11 / 18 7

4.3 名次顶端全是合成的

把来源表按名次从 100 往回读,会看到一个清楚的分界:名次 81 到 100 这二十条,来源代码全部是 syn;名次 1 到 20 的二十条里,没有一个 syn。真实片段与合成波形在名次轴上几乎不重叠,合成整体落在高 TWA 一侧。

名次区间 主要来源 含义
81 至 100 全部 syn 注入幅度最大的合成波形,如 twa34(100)、twa72(99)
61 至 80 syn 为主,夹杂 lts、ptb 弱注入合成与强交替真实片段混排
21 至 60 真实片段为主 名次中段,真实记录的主要分布区
1 至 20 全部真实片段(sdd、lts、ptb、nsr、inc) 交替最弱的真实记录,twa00 为 1

这个分界有两种读法,取舍取决于任务。

读法 理由 适用任务
别混着用 合成与真实差异太大,模型可能只学到「像不像合成」 训练排序模型
补高幅度端 真实片段整体偏弱,高幅度区只有合成覆盖 幅度量化的敏感性分析

4.4 它支撑的四类实验

实验类型 具体做法 需要注意
排序能力评测 算你的幅度估计与参考名次的 Kendall tau 只用 100 条,置信区间宽
合成组自检 只在 32 条合成上验证单调性 无公开注入幅度,只能定性
算法敏感性分析 比较不同窗口长度、不同导联对名次的影响 名次不等距,差异要谨慎解读
抗噪鲁棒性 人为加噪后看名次漂移 与 2008 年参赛条件不同,需说明

四类实验里,只有第一类与原始设计完全对齐。第二类受限于注入幅度未公开,第三、第四类则是这份数据被二次利用的常见方向,官方并未为其设计标注。

4.5 边界条件:什么时候它不再适用

四条边界里,前两条是结构性的(数据里就没有),后两条是使用性的(数据里有,但用法不对就会失真)。结构性的没有绕法,使用性的可以通过协议规避。

边界 触发条件 后果 替代做法
个体风险 需要 ICD 适应症判断 无名次到风险的换算 用带结局的队列
高心率覆盖 需心率 90 至 120 段 部分片段未达该区间 先按 RR 筛段再统计
绝对幅度 跨记录比微伏 缩放系数未公布 只做同记录内比较
导联推断 需要电极位置 非十二导联记录无说明 只用十二导联子集

§5 工具层:从目录到可训练张量

5.1 三条取数路径与体积账

官方页面给了三种取法,指向同一份内容:整包 ZIP、wget 递归抓取、aws s3 同步公开桶。三条都不需要登录,也不需要申请。体积上,未压缩总量 105.0 MB,ZIP 也标 105.0 MB,说明数据本身以 16 位整数存放,压缩比很低。

路径 命令要点 适用场景
整包 ZIP 页面上的 Download 按钮 一次性拿全量,最省事
逐文件抓取 wget -r -N -c -np 只要几十条,省带宽
对象存储 aws s3 sync --no-sign-request 服务器上批量拉取
Python 客户端 wfdb.rdrecord(..., pn_dir=...) 边读边算,不必落盘

第四条路径官方没写,但 WFDB 的 Python 包支持直接从 PhysioNet 读取,适合只跑几段做验证的场景。它内部仍走 HTTP,速度取决于单条记录大小,十二导联记录一条约 1.3 MB。

5.2 批量获取与目录核对

#-- 只下头文件和注释,跳过 .dat,用来先摸清结构
wget -r -N -c -np --accept "*.hea,*.qrs,RECORDS,ANNOTATORS" \
  https://physionet.org/files/twadb/1.0.0/

#-- 核对记录数与通道数分布:首行字段依次是 名字 通道数 采样率 采样点数
for f in twadb/1.0.0/*.hea; do
  head -1 "$f"
done | awk '{print $2}' | sort | uniq -c

#-- 校验完整性(2019 年补入的清单)
cd twadb/1.0.0 && sha256sum -c SHA256SUMS.txt | tail -3

三段命令各管一件事,按顺序跑就是一次完整的取数。

段 做什么 产出 体积
第一段 只下头文件与注释 100 组文本元数据 几十 KB
第二段 按通道数汇总 2、3、12 三档计数 屏幕输出
第三段 校验整包 逐文件一致性结论 屏幕输出
#-- 三条记录的头文件首行对照(原样摘录)
twa00 2 500/250 59999
twa01 12 500 61551
twa04 3 500/250 59999

5.3 读进内存:通道数不一致怎么办

十二导联、三通道、两通道混在一个库里,最直接的处理是补齐到同一张量,同时用一个通道掩码告诉模型哪些位置是真的。下面是能直接跑的最小版本。

#-- 统一读成 12 通道张量,缺的通道补零,掩码记录真通道
import numpy as np
import wfdb

TARGET_LEADS = ["I", "II", "III", "aVR", "aVL", "aVF",
                "V1", "V2", "V3", "V4", "V5", "V6"]

def load_record(name):
    rec = wfdb.rdrecord(name, pn_dir="twadb/1.0.0")
    sig = np.zeros((rec.sig_len, len(TARGET_LEADS)), dtype=np.float32)
    mask = np.zeros(len(TARGET_LEADS), dtype=np.float32)
    for j, lead in enumerate(rec.sig_name):
        if lead in TARGET_LEADS:
            i = TARGET_LEADS.index(lead)
            sig[:, i] = rec.p_signal[:, j]
            mask[i] = 1.0
    return sig, mask, rec.fs

sig, mask, fs = load_record("twa01")
print(sig.shape, mask.sum(), fs)   #-- (61551, 12) 12.0 500

对非标准导联名(ECG1、E-S 等)的处理有三种,选哪种要在报告里写清楚。

策略 做法 代价
丢弃 只留十二导联子集 样本量减少,名次分布改变
按序填充 按通道顺序填进前几列并标掩码 通道语义丢失
独立成组 2 路、3 路、12 路各训一个模型 实现复杂,组间不可比

如果模型对导联语义敏感,只有第一种或第三种可行;如果只做与导联无关的时序特征,第二种最省事。三种做法都不改变一个事实:通道数不一致是这份数据固有的形态,任何「读成整齐矩阵」的代码都必须显式处理它。

5.4 注释与那 4 毫秒的网格

#-- 心搏时刻按计数器频率对齐;500/250 的记录只有 4 毫秒精度
import wfdb
import numpy as np

rec = wfdb.rdrecord("twa04", pn_dir="twadb/1.0.0")
ann = wfdb.rdann("twa04", "qrs", pn_dir="twadb/1.0.0")

print(ann.fs, rec.fs)                 #-- 注释采样率与波形采样率
rr = np.diff(ann.sample) / rec.fs     #-- 以秒为单位的 RR 间期
print(rr.min(), rr.max(), rr.mean())  #-- 极短与极长的 RR 要先排除
print(set(ann.symbol))                #-- 只有 'N'

ann.fs 就是头文件里斜杠后面那个数字,500/250 的记录会读到 250。

字段 本例 含义
ann.fs 250 注释的时间基准,决定网格
ann.sample 递增整数 心搏所在的采样点序号
ann.symbol 全为 N 类型一律正常,异位未单列
rec.fs 500 波形采样率,与注释基准可不同
rec.p_signal 浮点毫伏 已按增益换算

心搏时刻落在 4 毫秒的整数倍上,而波形是 2 毫秒一个点。做逐拍叠加(把每个心搏的 T 波窗口切出来平均)时,这个 2 毫秒的错位会让叠加结果在时间轴上轻微抹平,微伏级的差异首当其冲。稳妥的做法是先把波形按 ann.fs 重采样,或者用互相关把每个窗口对齐到亚采样精度。

5.5 把名次接回波形

标签在另一个地址,需要下载后按记录名合并。这张表是纯文本、制表符分隔、带说明段与表头,四列的含义如下。

列 内容 用途
第 1 列 本库记录名 与 .hea 文件名对齐
第 2 列 参考名次 1 至 100 唯一的标签
第 3 列 来源库代码 分层与留出
第 4 列 原始记录名 分组键,防同源泄漏

直接按列数过滤比猜行号可靠,因为说明段的行数会随版本变动。

#-- 来源表前有说明段,按「四列且首列以 twa 开头」过滤出数据行
import pandas as pd

rows = []
for line in open("about-records.txt", encoding="utf-8"):
    parts = line.rstrip("\n").split("\t")
    if len(parts) == 4 and parts[0].startswith("twa") and parts[1].isdigit():
        rows.append(parts)

ranks = pd.DataFrame(rows, columns=["record", "rank", "source_type", "source_record"])
ranks["rank"] = ranks["rank"].astype(int)
print(len(ranks), ranks["rank"].min(), ranks["rank"].max())
print(ranks.groupby("source_record")["record"].count().sort_values().tail(5))

最后一行会打印出被切成多段的原始记录,正是 §4.2 的案例里那几组。做切分时应以 source_record 为分组键,而不是以 record 为分组键。

5.6 六个最容易出错的地方

坑 症状 原因 解法
把名次当幅度回归 均方误差很低但排序相关性很差 序数当连续值用 改用 Kendall tau 或 Spearman
按记录随机切分 测试集指标异常高 同源片段跨集 以 source_record 分组
直接把 100 条当独立样本 置信区间估得过窄 独立信号源只有 85 按 85 计有效样本量

后三个坑属于数据形态,症状更隐蔽。

坑 症状 原因 解法
以为心搏全是正常 节律分析结果与预期不符 官方明说异位也被标成正常 自己跑 QRS 检测或排除
忽略 4 毫秒网格 逐拍叠加后 T 波变钝 计数器频率 250 Hz 先重采样或亚采样对齐
找 stwdb 项目页 返回 404 该合成库未单独立页 走来源表与生成论文

§6 与库内条目的关系

6.1 关系图谱:母库、子片段与邻居

TWADB 在库内的位置不是「又一个心电库」,而是「从几个心电库里切出来的一层薄片」。70 条真实片段全部可以追到五个母库,血缘关系决定了分工:母库给完整记录与全套标注,本库给统一格式的两分钟切片与一个排序。

母库 供片数 母库给什么 本库留下了什么
长时程 ST 库 12 21 至 24 小时 Holter、逐搏 ST 标注、临床摘要 三通道两分钟片段 + QRS 时刻
PTB 诊断库 30 十二导联 + 三 Frank、诊断与人口学 十二导联两分钟片段
猝死 Holter 库 10 室速室颤事件、部分逐搏标注 两通道两分钟片段
圣彼得堡十二导联库 10 十二导联、诊断 十二导联两分钟片段
正常窦律库 6 约 24 小时、心搏与质量标注 两通道两分钟片段

最需要讲清的是它与长时程 ST 库的那条边。两个库看的是同一颗心脏、同一段复极过程,但看的尺度完全不同:ST 段改变是毫伏级的电平偏移,持续几十秒到几分钟,靠逐搏的 ST 电平序列就能标出来;TWA 是微伏级的形态交替,逐拍之间来回切换,靠单看任何一拍都看不出来,必须在几十拍上做频谱或相关分析。前者是「这一段抬高了多少」,后者是「相邻两拍差了零点几微伏」。库内只有本库以后者为对象。

维度 TWADB LTSTDB MIT-BIH ST Change VFDB
关注对象 复极末段的微伏级交替 ST 段的毫伏级偏移 运动负荷下的 ST 改变 室速、室颤事件
幅度量级 微伏级(常在个位数) 毫伏级(0.1 毫伏起算) 毫伏级 毫伏级,形态整体改变
时间尺度 逐拍交替(约 1 秒周期) 事件级(数十秒到数分钟) 事件级 事件级(数秒到数分钟)
标注 仅 QRS + 库外序数名次 逐搏 + ST 事件 + 节律 + 临床摘要 无注释 事件起止
单条时长 约两分钟 21 至 24 小时 20 至 40 分钟 数十分钟
采样 500 Hz 250 Hz 360 Hz 250 Hz
与本库的关系 本库 本库 12 条片段的母库 同族但未进本库 同族但未进本库

第二层关系是「同族邻居」。库内还有若干心电库各有独占的生态位:正常窦律库独占「被判读为无显著心律失常的长记录」,运动伪迹库独占「同一贴片在三种动作下的四路信号」,威尔逊中心电端库独占「三十七路直接测量的电位参考」。它们不是替代关系,因为各自回答的问题不同。

库内资源 独占的东西 与本库的交集 与本库的分界
LTSTDB 缺血事件的逐搏 ST 标注与临床摘要 12 条片段同源 它标 ST 电平,本库只留 QRS
MIT-BIH ST Change 运动负荷下的真实 ST 改变 同为运动/负荷场景 它无标注,本库有名次
MIT-BIH NSRDB 判读为正常的二十四小时节律 6 条片段同源 它 128 Hz,本库重采样到 500 Hz

前三个是本库的母库,后三个是同族邻居。

库内资源 独占的东西 与本库的交集 与本库的分界
MIT-BIH VFDB 室颤室速的事件级标注 同为猝死风险主题 它标事件,本库标交替强弱
PTB Diagnostic 十二导联 + 三 Frank 的临床摘要 30 条片段同源 它有诊断,本库剥离了诊断
ECGPedia 类十二导联库 大体量、带诊断标签 同为十二导联 它不针对微伏级交替

6.2 检索路径:三条能立刻用的线索

库内检索有三条线索,按任一条走都能落到本库,但要注意别串到邻居。

线索 检索词 会命中 会串到谁
主题词 T 波交替、TWA、复极、猝死风险 本库 ST 段库、VFDB
数据形态 两分钟、500 Hz、十二导联 本库与 PTB 片段 长时程库
标注形态 序数名次、排序、Kendall tau 本库与其它挑战赛库 分类标注库
你想找的东西 检索词 会命中 不该命中
微伏级复极交替 T 波交替、TWA、复极 本库 ST 段库
缺血事件的逐搏标注 ST 段、缺血、ST 事件 LTSTDB 本库
运动负荷下的 ST 改变 运动负荷、ST Change ST Change 库 本库
挑战赛题库 挑战赛、Challenge、CinC 本库与其它挑战赛库 常规临床库
排序型标签 名次、排序、Kendall tau 本库 分类标注库
十二导联两分钟 十二导联、两分钟 本库、PTB 片段 长时程库

6.3 组合使用的三条路线

三条路线各有收益与风险,选哪条取决于你缺标签还是缺格式。

路线 组合方式 收益 风险
母库取标注 本库跑通口径,母库看细节 有标签也有统一格式 片段与母库记录需按名对齐
预训练与评测分离 本库预训练,母库评测 避免考题泄漏 两库分布不同需说明
负例构造 本库 + 正常窦律库 负例有临床判读支撑 只能算弱负例

§7 质量评估与局限性

7.0 阅读本节前的一个前置校正

评价这份数据前,要先换掉一个默认框架。多数心电库的默认框架是「波形 + 逐条标签」,于是评分自然落在「标签是否准确、覆盖是否完整」上。用这套框架看本库,会得出「标签只有名次、没有微伏值,质量不合格」的结论——这是误判,因为它评价的是一个本库从未声称自己是的东西。

本库声称自己是题库。题库的合格标准是不同的三条:题目是否有区分度、答案口径是否公开可复算、题目与答案是否可被独立获取。按这三条看,它的设计是自洽的:100 条记录混排、参考名次公开、来源表逐条可查、参赛论文与开源代码都在。真正该批评的地方不在「没有微伏值」,而在「序数标签被后来的使用者当成连续值用」——这是使用侧的误用,不是数据侧的缺陷。

第二个前置校正是样本单位。100 条不等于 100 个独立病人,真实部分只有 53 份原始记录,加上 32 条合成才是 85 个独立信号源。把 100 当独立样本去算置信区间,会系统性低估不确定性。

7.1 五维评分

维度 评分 依据
可得性 5 / 5 三条下载路径均免登录,ODC-BY 1.0 允许商用
格式规范 5 / 5 标准 WFDB 三件套,wfdb 包直接可读,2019 年补了校验清单
标注完备度 2 / 5 只有 QRS 时刻;TWA 侧只有库外序数名次
规模 2 / 5 100 条约两分钟,合计约三小时四十分钟信号
可复现性 4 / 5 名次、来源表、参赛论文、开源代码齐全;注入幅度未公开扣一分

按 DAIMS 框架的五个维度逐项看,强项集中在「拿到」与「读进来」:许可干净、格式标准、校验齐全、客户端一行代码可读。弱项在「标注」这一层——责任被推给了库外一份只提供序数的纯文本。可持续性中等偏上:不会被更新,但也不会消失。

DAIMS 维度 本库表现 关键证据
数据可得性 强 免登录、三路径、ODC-BY 1.0
互操作性 强 WFDB 标准格式、导联名部分标准化
可复用性 中 无诊断标签,二次利用需自建标签
数据质量 中 波形质量高,标签为序数
可持续性 中偏强 归档稳定,无版本迭代

7.2 标注的真实覆盖范围

库内标注只有一种:QRS 心搏时刻,由算法生成,覆盖全部记录,且官方明确说明所有心搏一律标成正常。它能用于切拍、算心率、算 RR 变异性,不能用于节律分类,也不能判断某条记录是否干净。

库外标注只有一种:参考名次。它覆盖全部 100 条记录,无缺失,但只有序数。它不能告诉你某个片段的 TWA 是 2 微伏还是 20 微伏,只能告诉你它在参赛者眼里排第几。

标注 覆盖 粒度 能做什么 不能做什么
QRS 时刻 100 / 100 逐搏 切拍、心率、RR 分析 节律分类、异位识别
参考名次 100 / 100 逐条 排序评测、难易分层 幅度回归、阈值判定
来源代码 100 / 100 逐条 分组切分、来源分层 病人级推断
导联名 100 / 100 逐通道 通道对齐 电极位置推断
诊断 0 / 100 无 无 一切临床分层
微伏值 0 / 100 无 无 绝对幅度报告

7.3 已知的、可枚举的偏差

四条偏差里,前三条来自数据组装,第四条来自评测机制。五个母库各有入组标准——猝死 Holter 库收记录期间发生持续室性快速心律失常与心搏骤停者,PTB 以心梗后为主,长时程 ST 库以短暂缺血为主,正常窦律库排除显著心律失常——拼在一起得到的是几类高风险人群的拼盘,不是自然人群。片段偏差指每条只截约两分钟,而 TWA 与心率强相关,窗口未必覆盖心率升高的时刻。改造偏差指官方明说部分记录经重采样与重缩放,缩放系数未公布,跨记录比绝对幅度缺依据。标注偏差指名次编码的是「这批方法能否区分」,而不是「生理上交替有多强」。

偏差 来源 影响面 缓解方式
来源偏差 五个母库各自的入组标准 人群推断、患病率 按来源分层报告
片段偏差 两分钟截取,未按心率选段 高交替样本偏少 先按 RR 筛段
改造偏差 重采样与重缩放 绝对幅度、高频形态 只做同记录内比较
标注偏差 名次来自参赛者群体判断 标签含义受方法谱影响 视为相对排序而非生理量
合成偏差 32 条合成占名次高端 训练时可能学到「像不像合成」 训练与测试分源

7.4 外部验证矩阵

一份数据能不能用,最终要看它能不能被外部证据支撑。本库的外部支撑相当完整:官方论文给了设计与规则,参赛论文给了方法谱与成绩,母库给了原始记录与临床背景。

外部资源 能给什么 不能给什么
Moody 2008 挑战赛论文 设计动机、评分规则、数据构成 逐条微伏真值
参赛队伍论文(会议文集) 各类方法的成绩与误差模式 统一的幅度标定
长时程 ST 库 12 条片段的完整标注与临床摘要 TWA 幅度
PTB 诊断库 30 条片段的诊断与人口学 TWA 幅度

官方与会议文集属于一手证据,母库属于可回溯的二层证据。

外部资源 能给什么 不能给什么
猝死 Holter 库 10 条片段的事件背景 TWA 幅度
正常窦律库 6 条片段的长时程节律 TWA 幅度
生理信号质量通用指标 可用于自建质量筛选 官方未提供质量标签

7.5 它为何能持续:题库一旦被引用就成了基准

一份 2008 年定版、此后再不更新的数据,按理早该被遗忘。它没有,原因不在数据本身,而在它承担的角色:这个领域唯一一份「大家一起做过、成绩公开、规则统一」的题库。新方法想声称自己在 TWA 检测上有进步,最省事的对照就是回到这里复算名次。这种「共同参照系」的效应会自我强化。

支撑层 作用 依赖谁
归档层 地址不变,版本可追溯 PhysioNet 长期托管
口径层 论文与榜单使规则可查 会议论文集与挑战赛页
溯源层 片段可回溯到母库 五个母库持续在线

三层都不依赖作者本人维护,作者退休、方法过时,都不影响它继续被引用。

§8 生态位与历史

8.1 一条从「罕见征象」到「公开题库」的线

官方页面把这条线讲得清楚,只是分散在几段里。起点是 Hering 在一百年前首次报告 T 波交替;此后近一个世纪它被当成罕见征象,因为肉眼看不见微伏级差别。1981 年 Adam、Akselrod 与 Cohen 在第八届 Computers in Cardiology 上首次报告微伏级 TWA,把「看不见」变成「可以算」。此后二十五年,经验证据把 TWA 的幅度、出现时的心率与猝死风险连在一起。

到 2008 年,方法已经多到需要一场统一评测:官方页面列出的技术路线包括频谱分析、复解调、相关系数过零计数、主成分的周期图分析、Capon 滤波、Poincaré 映射、周期变换、统计检验、移动平均、最大似然与广义似然比。方法谱这么宽,缺的不是算法,是可比性。第九届挑战赛就是在这个背景下开的题。

时间 节点 意义
约 1908 年前 Hering 首次报告 T 波交替 现象被记录,但被认为罕见
1981 Adam、Akselrod、Cohen 报告微伏级 TWA 从肉眼判读转向信号分析
1981 至 2006 方法谱扩张,证据积累 幅度、心率、风险三者关联确立
2008-03 第九届挑战赛开题 首次统一评测 TWA 检测与量化
2008-09 本库定版,成绩公布 题库与榜单同时落地
2019-02 补入 SHA256SUMS 归档层加固,内容未变

8.2 用排序代替测量的评测机制

挑战赛最值得学的一点是它绕开了「没有金标准」的死结。既然没人能给出可信的微伏真值,那就不比绝对值,比排序:每份提交把 100 条记录按自己的估计从低到高排一遍,组织方取各条记录在所有提交里的中位名次,得到参考排序,再用 Kendall tau 相关系数衡量每份提交与参考排序的一致程度,1 是完全一致,-1 是完全相反。

三个好处各自对应一类工程问题,也各有一份代价。

好处 解决的工程问题 代价
单位无关 不同实现的输出不可比 无法跨提交比绝对值
对系统偏差不敏感 各法系统性偏高偏低 掩盖了标定差异
可比 方法谱再宽也能同榜 名次受队伍构成影响
机制要素 规则 对使用者的含义
提交内容 每条记录一个 TWA 幅度估计 只需相对大小,不需绝对标定
单位 任意,内部一致即可 不能跨提交比绝对值
评分 与参考排序的 Kendall tau 评估指标应为排序相关性
提交次数 最多五次,可选其一计分 存在对榜调参的空间
参考排序 参赛者中位名次再排序 集体判断,非物理测量
开源组 提交源码另设奖项 方法与实现可查

这套机制也留下了两个后遗症。一是名次本身带噪声:中位名次依赖参赛队伍构成,换一批队伍,名次会变。二是榜单可被拟合:五次提交的机会足以让队伍针对 100 条记录微调阈值,这也是为什么后来的使用者不该把这 100 条当独立测试集——它们已经被反复看过十七年。

8.3 生态位:题库、切片与对照,三合一

把本库放进 PhysioNet 的心电谱系里看,它占的是一个窄而清晰的位置:它是「按统一格式切好的、带统一排序口径的两分钟片段集」。母库提供深度(长时程、逐搏标注、临床摘要),它提供可比性(同格式、同长度、同一套名次)。两者不是竞争关系,而是上下游关系。

作为数据它很薄——只有约三小时四十分钟信号、一种标注、无人口学;作为基准它很硬——十七年里凡是要在 TWA 上做对照的工作,几乎都会回到这份名次上。薄与硬同时成立,正是题库类数据集的特点。

8.4 谁在用它,用来做什么

使用者类型 典型用法 需要自行补的东西
信号处理研究者 验证新的交替检测或量化算法 排序评测脚本、分组切分
心电算法团队 作为模型的一个外部对照集 通道补齐、采样对齐
教学者 演示微伏级差异为何肉眼不可见 放大绘图、逐拍叠加

前两类是研究者,后三类是使用者与复现者。

使用者类型 典型用法 需要自行补的东西
挑战赛复现者 复算 2008 年榜单 参赛论文、开源代码
数据管理者 作为「题库型数据集」的组织范例 无

8.5 二十年后它剩下什么

它剩下的不是波形——同样的波形在母库里都有,而且更完整。它剩下的是那份名次,以及围绕名次形成的一套口径:无金标准时怎么评测、不同来源的记录怎么拉平成同构样本、标签与波形分离后怎么对齐。这三件事的方法学价值,超过了三小时四十分钟信号本身。

§9 使用指引

9.1 三种角色的路径

角色 目标 最短路径 预计工作量
算法研究者 证明方法能排序 读头文件 → 读名次表 → 算 tau 半天可跑通
数据工程师 接入自有流水线 通道补齐 → 重采样对齐 → 分组切分 一到两天
临床研究者 了解 TWA 与风险的关系 读官方背景段与综述,不必下载 一小时
教学者 做课堂演示 取一条十二导联记录画逐拍 T 波 两小时

9.2 一条最短的可用流程

#-- 1. 取元数据与名次表(几十 KB,不必下整包)
wget -q https://physionet.org/files/challenge-2008/1.0.0/about-records.txt
wget -q -O twa01.hea https://physionet.org/files/twadb/1.0.0/twa01.hea

#-- 2. 装客户端
python3.11 -m pip install --quiet wfdb pandas scipy
#-- 3. 跑通「读一条 → 算 RR → 与名次对齐」的最小闭环
import wfdb
import numpy as np
import pandas as pd
from scipy.stats import kendalltau

rec = wfdb.rdrecord("twa01", pn_dir="twadb/1.0.0")
ann = wfdb.rdann("twa01", "qrs", pn_dir="twadb/1.0.0")
rr = np.diff(ann.sample) / rec.fs
hr = 60.0 / np.median(rr)
print(rec.record_name, rec.sig_name[:3], round(hr, 1))

rows = []
for line in open("about-records.txt", encoding="utf-8"):
    p = line.rstrip("\n").split("\t")
    if len(p) == 4 and p[0].startswith("twa") and p[1].isdigit():
        rows.append(p)
ranks = pd.DataFrame(rows, columns=["record", "rank", "src", "src_rec"])
ranks["rank"] = ranks["rank"].astype(int)
print(ranks[ranks.record == "twa01"].to_dict("records"))

#-- 4. 假设你已对全部 100 条算出估计值 my_est(长度 100,顺序与 ranks 一致)
#-- 评估只看排序一致性,不看绝对值误差
#-- tau, p = kendalltau(my_est, ranks["rank"])
#-- print("Kendall tau =", round(tau, 3))

第 3 步的心率说明这条十二导联记录处在什么状态;第 4 步是评测骨架,注释掉是因为 my_est 需要你自己的算法生成。最后一行用的是排序相关系数而非均方误差,这是本库最容易被忽略的用法约束(§4.2 的案例已从标签结构上说明原因)。

9.3 引用方式

官方要求引用两件事:原始论文与 PhysioNet 平台本身。原始论文的完整信息写在页面顶部,格式如下。

#-- 数据集原始论文(官方指定引用)
Moody GB. The PhysioNet/Computers in Cardiology Challenge 2008:
T-Wave Alternans. Computers in Cardiology 35:505-508; 2008.

#-- 数据本体
T-Wave Alternans Challenge Database (version 1.0.0). PhysioNet.
DOI: 10.13026/C2B59B. https://physionet.org/content/twadb/1.0.0/

#-- 平台引用(官方另行给出的标准引用)
Pollard T, Moody BE, Lehman L, et al. PhysioNet as a global platform
for biomedical research. Nature Health. 2026. doi:10.1038/s44360-026-00096-z

三方署名缺一不可:论文说明设计,DOI 定位版本,平台声明来源。ODC-BY 1.0 的义务是署名,不含担保——把名次当微伏值用出的错,许可方不承担。

9.4 复现一份最小报告的四步检查

步骤 要写清什么 常见缺失
数据范围 用了 100 条中的哪几条、按什么筛 只说「用了 TWADB」
切分方式 是否按 source_record 分组 按记录随机切分
评测指标 Kendall tau 或 Spearman,附实现 用均方误差
合成处理 合成组是否进入训练 混入后未说明

§10 AI 使用声明

项目 说明
数据性质 公开研究数据,含真实临床心电片段与人工合成波形,非诊断用途
允许用途 算法研究、方法评测、教学演示、模型预训练与对照实验
不建议用途 个体风险预测、临床决策、医疗器械验证、监管申报的直接证据
伦理边界 原始记录已在母库中按各自伦理与许可公开;本库未新增人体研究

后四项约束的是用途边界,与数据本身无关。

项目 说明
隐私 无姓名、无病历号、无日期;但十二导联波形本身具备生物识别潜力
合成数据标注 32 条合成波形不得当作真实病例陈述
引用义务 ODC-BY 1.0 要求署名,须同时引用论文与平台
版本状态 1.0.0,2008 年定版;2019 年仅补校验清单,内容未变

常见误读(避坑清单)

常见说法 实际情况 证据
「TWA 是 T 波电轴偏移」 TWA 是相邻心搏 T 波形态的强弱交替,不是电轴转动 官方背景段:两种形态轮流出现
「库里有每条记录的 TWA 微伏值」 只有 1 至 100 的参考名次 来源表第 2 列,全为整数名次
「名次 50 就是 50 微伏」 名次与幅度之间没有公布换算 官方评分规则:只按排序计分
「100 条就是 100 个病人」 真实部分仅 53 份原始记录,加合成共 85 个信号源 来源表第 3、4 列去重
「心搏都标成 N,说明没有异位」 官方明说异位搏动也一律标成正常 Data Description 末句

后五条偏用法,踩中不会立刻报错,但会让结论站不住。

常见说法 实际情况 证据
「两分钟记录里一定有 TWA」 TWA 多在心率为每分钟 90 至 120 次时出现 官方背景段
「这是新建采集的数据」 全部来自五个已有库的片段与两组合成 来源表与摘要
「合成部分没有用,可以全删」 合成占据名次高端,提供真实数据缺的高幅度段 名次 81 至 100 全为 syn
「按记录随机切分就可以」 同源片段跨集会导致指标虚高 §4.2 的案例
「采样率统一 500 Hz,时间精度也统一」 部分记录计数器只有 250 Hz,心搏落在 4 毫秒网格 头文件 500/250

FAQ

Q1:TWADB 这个名字该怎么拆?
T-Wave Alternans Challenge Database。T-Wave Alternans 是 T 波交替,Challenge 说明它是为挑战赛组装的题库,Database 是 PhysioNet 对数据集的统称。目录名取前四个词的首字母加 db,得到 twadb。

Q2:TWA 与 ST 段改变有什么本质区别?
量级与时间尺度都不同。ST 段改变是毫伏级的电平偏移,持续数十秒以上;TWA 是微伏级的形态交替,逐拍来回切换。前者看一段时间的电平趋势,后者看相邻两拍之间的细微差别。

Q3:为什么官方不给微伏真值?
因为该领域没有公认的量化金标准。官方页面列举了十余类算法并存,各法的绝对输出不可比。组织方于是改用排序:不比谁测得准,比谁排得对。

Q4:名次可以直接当回归标签吗?
不建议。名次是序数,间距不等,直接回归会把「名次差 1」当成「幅度差一个单位」。如果一定要用连续标签,至少要做保序变换,并在报告中说明这是代理标签。

Q5:怎么避免同源片段造成的泄漏?
按来源表第 4 列的原始记录名分组,用分组切分(GroupKFold 之类)而不是随机切分。真实部分的分组数是 53,不是 70。

Q6:合成的 32 条该怎么用?
两种用法:一是单独作为方法自检集,看估计值随注入幅度是否单调;二是放在训练集里扩充高幅度端,但测试集必须是真实片段。混着评测会高估真实场景的表现。

Q7:能不能只用十二导联的记录?
可以。按头文件首行通道数筛出 12 的那些即可,剩下的是 2 路与 3 路记录。代价是样本量减少,且高名次的合成记录多为十二导联,筛完会改变名次分布。

Q8:它适合做心电基础模型的预训练吗?
适合当小配料,不适合当主粮。三小时四十分钟的信号量对预训练而言太少,格式统一、许可干净是它的优点,规模是硬伤。

Q9:为什么说它已经被「看过十七年」?
挑战赛期间参赛队伍最多可提交五次,赛后论文与代码公开,此后不断有人复算。100 条记录的每一处细节都已被反复检视,它不再具备盲测集的性质。

Q10:如果我要做临床研究,该从哪入手?
不要从这份数据入手。先读官方背景段与综述类文献,理解 TWA 与猝死风险的证据链,再去找带随访结局的队列数据。本库适合做方法学,不适合做结局研究。

Q11:许可允许商用吗?
ODC-BY 1.0 允许商用、再分发与改编,条件是署名。署名对象包括数据集本身与 2008 年的挑战赛论文。许可不提供任何担保。

术语表

术语 含义
TWA T-wave alternans,T 波交替,相邻心搏 T 波形态的强弱交替
复极 心室肌细胞恢复静息电位的过程,对应心电图的 T 波
微伏级 幅度在个位数到数十微伏,约为 1 毫伏的百分之一量级
参考名次 由参赛者估计的中位名次再排序得到的 1 至 100 序数
Kendall tau 排序相关系数,1 为完全一致,-1 为完全相反
中位名次 某条记录在所有提交中的名次的中位数
WFDB PhysioNet 的波形数据库格式,.hea 头文件 + .dat 数据体
.hea 文本头文件,给出通道数、采样率、增益、导联名
.dat 二进制数据体,16 位整数按通道交错存放
.qrs 心搏注释文件,只含 QRS 时刻,类型一律为正常
增益 每毫伏对应的 ADC 单位数,本库多为 2000
ADC 零点 数字化时的基线偏移值

下半部分是格式与工程侧的词,读代码时会反复遇到。

术语 含义
计数器频率 注释时间戳的时间基准,500/250 表示 250 Hz
重采样 改变采样率,本库把部分片段统一到 500 Hz
重缩放 改变幅度标度,本库未公布系数
Holter 长时程便携心电记录,通常 21 至 24 小时
运动负荷试验 让受试者运动以提高心率,观察心电改变
猝死(SCD) sudden cardiac death,症状出现后短时间内的自然死亡
ICD 植入式心律转复除颤器
序数标签 只有大小顺序、没有等距含义的标签
分组切分 按分组键(如原始记录)划分数据集,防止同源泄漏
泄漏 训练集与测试集含同源样本,导致指标虚高
合成波形 由模型生成并注入已知幅度 TWA 的信号
通道掩码 标记张量中哪些通道是真实信号的 0/1 向量

附录 A:核心数字核对表

项 值 来源 来源层级
记录数 100 官方摘要与目录 官方页面
真实片段数 70 来源表逐行统计 官方附文件
合成波形数 32 来源表逐行统计 官方附文件
真实原始记录数 53 来源表第 3、4 列去重 官方附文件
独立信号源 85 上两项相加 推算
采样率 500 Hz 官方摘要与头文件 官方页面
位深 16 位 官方摘要与头文件 官方页面
标称量程 正负 32 毫伏 官方摘要 官方页面

剩下的是推算值、计数与版本信息,来源已在最后一列标注。

项 值 来源 来源层级
量化步长 0.5 微伏 由增益 2000 单位/毫伏与 16 位推算 推算
单条时长 120 至 129 秒 头文件样本数除以采样率 官方附文件
未压缩体积 105.0 MB 官方文件区 官方页面
发布日 2008-09-22 官方页面 官方页面
版本 1.0.0 官方页面 官方页面
DOI 10.13026/C2B59B 官方页面 官方页面
许可 ODC-BY 1.0 官方页面 官方页面

附录 B:数字的来源分层

层级 数字 说明
官方页面直接给出 100 条、500 Hz、16 位、正负 32 毫伏、105.0 MB、2008-09-22、1.0.0、ODC-BY 1.0、DOI 摘要、文件区、版本区逐字可查
官方附文件可数 70 / 32 / 53 / 85、每条的通道数与采样点数 about-records.txt 与各 .hea
由官方数字推算 0.5 微伏量化步长、120 至 129 秒时长、约三小时四十分钟总时长 增益与样本数换算,非官方表述
未核实 每个合成档位的注入微伏值、每条片段的原始缩放系数、各片段的采集日期 官方未公开,stwdb 页返回 404

附录 C:完整参考文献

编号 文献 用途
C1 Moody GB. The PhysioNet/Computers in Cardiology Challenge 2008: T-Wave Alternans. Computers in Cardiology 35:505-508; 2008. 数据集原始论文
C2 T-Wave Alternans Challenge Database v1.0.0. PhysioNet. DOI 10.13026/C2B59B. 数据本体
C3 PhysioNet/Computers in Cardiology Challenge 2008 项目页(含 about-records.txt) 参考名次与来源表
C4 Long-Term ST Database 12 条片段的母库
C5 PTB Diagnostic ECG Database 30 条片段的母库

另有平台侧与工具侧的文献,供引用时补齐。

编号 文献 用途
C6 MIT-BIH Sudden Cardiac Death Holter Database 10 条片段的母库
C7 St. Petersburg INCART 12-lead Arrhythmia Database 10 条片段的母库
C8 MIT-BIH Normal Sinus Rhythm Database 6 条片段的母库
C9 Pollard T, Moody BE, Lehman L, et al. PhysioNet as a global platform for biomedical research. Nature Health. 2026. 平台引用

附录 D:任务代码

把前面的步骤连成一条可运行的流水线:读元数据、按来源分组切分、只用排序指标评估。

#-- 端到端骨架:读来源表 → 分组切分 → 排序指标评估
import numpy as np
import pandas as pd
from scipy.stats import kendalltau
from sklearn.model_selection import GroupKFold

rows = []
for line in open("about-records.txt", encoding="utf-8"):
    p = line.rstrip("\n").split("\t")
    if len(p) == 4 and p[0].startswith("twa") and p[1].isdigit():
        rows.append(p)

df = pd.DataFrame(rows, columns=["record", "rank", "src", "src_rec"])
df["rank"] = df["rank"].astype(int)
df["group"] = df["src_rec"]

ranks = df["rank"].to_numpy()
groups = df["group"].to_numpy()
my_est = -ranks.astype(float)        #-- 占位:换成你的算法输出,方向需与 rank 一致

gkf = GroupKFold(n_splits=5)
scores = []
for tr, te in gkf.split(ranks, ranks, groups=groups):
    tau, _ = kendalltau(my_est[te], ranks[te])
    scores.append(tau)
print("fold tau:", np.round(scores, 3), "mean:", round(float(np.mean(scores)), 3))

my_est 那一行只是让脚本能跑通的占位符,真实使用时换成你的算法输出,并确保方向与 rank 一致(数值越大表示交替越强)。切分用的是 GroupKFold,分组键取原始记录名,这样同一份记录的两个片段不会被拆到两侧。

附录 E:如果只记五件事

序 一句话
1 它是 2008 年挑战赛的题库,100 条约两分钟的多通道心电,500 Hz、16 位。
2 TWA 指 T 波交替,微伏级、肉眼不可见、多在心率 90 至 120 次时出现。
3 标签是库外一份 1 至 100 的参考名次,只有顺序,没有微伏值。
4 70 条真实片段只来自 53 份原始记录,按记录随机切分必泄漏。
5 它测的是复极末段的微伏级交替,不是 ST 段的毫伏级偏移,两者别混。

编辑说明

核验时间 2026 年 10 月 28 日。核验方式为逐个访问官方页面与官方附文件:https://physionet.org/content/twadb/(HTTP 200)、挑战赛项目页 https://physionet.org/challenge/2008/(HTTP 200)、来源表 about-records.txt、若干条记录的 .hea 头文件、RECORDS 与 ANNOTATORS 清单。所有规模数字取自官方页面;70 / 32 / 53 / 85 四个数由来源表逐行计数与去重得到,计数方法已写在附录 A 的「来源」列。量化步长、时长换算、总时长三项为推算值,非官方表述,已在附录 B 单列。未覆盖的内容:每个合成档位的注入微伏值、每条片段的原始缩放系数、各片段的采集日期与采集地;合成库的项目页在 PhysioNet 上返回 404,相关信息未能从公开页面取得。


相关数据集导航

以下为站内 AI-Ready 数据集百科中与本词条共享多个主题标签的相关数据集,按相关度降序排列:

  • afpdb — 共享标签:生理信号 / 心电信号 / 挑战赛数据集 / 心血管疾病
  • incartdb — 共享标签:生理信号 / 心电信号 / 挑战赛数据集 / 心血管疾病
  • aftdb — 共享标签:生理信号 / 心电信号 / 挑战赛数据集 / 心血管疾病
  • cinc-2011 — 共享标签:生理信号 / 心电信号 / 挑战赛数据集 / 心血管疾病
  • butppg — 共享标签:生理信号 / 心电信号 / 挑战赛数据集 / 心血管疾病
  • ecg-image-database — 共享标签:生理信号 / 心电信号 / 挑战赛数据集 / 心血管疾病
  • cinc-2021 — 共享标签:生理信号 / 心电信号 / 挑战赛数据集 / 心血管疾病
  • ltafdb — 共享标签:生理信号 / 心电信号 / 挑战赛数据集 / 心血管疾病
  • cinc-2020 — 共享标签:生理信号 / 心电信号 / 挑战赛数据集 / 心血管疾病
  • georgia-12-lead-ecg-challenge — 共享标签:生理信号 / 心电信号 / 挑战赛数据集 / 心血管疾病

导航说明:本章节由全站统一标签体系自动计算生成(标签重合度算法),双向可达;点击链接可跳转至对应数据集词条。

返回 AI-Ready 数据集