信息速览
过去十年房颤检测算法的成绩单上,几乎每一份都写着同一批名字:MIT-BIH 心律失常库、MIT-BIH 房颤库、长期房颤库、Icentia11k、中国生理信号挑战赛。它们支撑了绝大多数模型的训练与评测,也共同留下一个长期无人认领的空白——官方背景段写得很直白,这些库里没有一个来自日本人群的样本。这件事在方法学上不是无关紧要的注脚:族群、体型、就诊路径与抗凝用药习惯都会改变心电形态与节律分布,一个在欧美人群上调到高分、又在同源测试集上自证泛化能力的模型,换到东亚人群上是否还成立,此前没有公开数据能回答。
SHDB-AF 就是为了补这个洞而公开的。它由埼玉医科大学国际医疗中心与以色列理工学院的研究者共同整理,把日本一家医疗中心 2019 年 5 月至 2023 年 5 月间因临床医嘱所做的动态心电图重新整理,最终落下 128 段约二十四小时的双导联记录、122 名受试者,其中 98 段带心脏科医师做出的节律区间级人工标注,另外 30 段只有波形没有标注。它同时附上一张 45 列的电子病历临床表,把身高体重、房颤类型、消融史、起搏器、用药、超声与合并症一并给出——这在房颤类公开库里是罕见的配重。
它的代价同样清楚:单一机构、单一族群、一百多段记录、只有两个非标准导联、标注只覆盖室上性节律。它不是拿来训大模型的粮仓,而是一把用来检验"你的模型到底学到了什么"的尺子。一屏速览见下表。
| 维度 | 内容 |
|---|---|
| 全名 | SHDB-AF: a Japanese Holter ECG database of atrial fibrillation(Saitama Heart Database Atrial Fibrillation) |
| 发布方 | PhysioNet(由 MIT 计算生理学实验室维护) |
| 贡献者 | Kenta Tsutsui(埼玉医科大学国际医疗中心、帝京大学)、Shany Biton Brimer 与 Joachim Behar(以色列理工学院生物医学工程系) |
| 首次发布 | 2024 年 8 月 12 日,版本 1.0.0 |
| 最新版本与改动 | 版本 1.0.1;发布说明标注 2024 年 12 月 29 日,版本页与页面发布日期标注 2025 年 4 月 16 日 |
| 记录数 | 128 段 |
| 受试者数 | 122 名(98 段标注记录对应 93 名受试者) |
| 每段时长 | 约 24 小时(示例 001:17220000 采样点 ÷ 200 Hz = 86100 秒,约 23 小时 55 分) |
| 导联数与名称 | 2:ECG1(modified CC5)、ECG2(NASA 导联) |
| 采样率与存储 | 分发版本 200 Hz、16 位整数;原始采集为 125 Hz |
| 原始采集 | 日本一家医疗中心,2019 年 5 月至 2023 年 5 月,Fukuda 动态心电图记录仪 |
| 带标注记录数 | 98 段(其余 30 段仅有波形) |
| 节律类别 | 5 类:房颤、房扑、房性心动过速、其他室上性心动过速、其他 |
| 标注规模 | 官方给出五类心搏条数与区间条数,房颤约 251 万条心搏、809 个区间 |
| 标注方式 | 单名心脏科医师用 PhysioZoo 在安全服务器上做节律区间级标注,平均每条二十四小时记录约 45 分钟 |
| R 峰位置 | 由 epltd 实现(Pan-Tompkins)自动检测,ANNOTATORS 明示未经审核 |
| 临床元数据 | AdditionalData.csv,128 行 × 45 列 |
| 文件格式 | WFDB:.hea / .dat / .atr / .qrs,外加 CSV 与附属清单 |
| 整库体积 | 未压缩 8.3 GB,官方 ZIP 7.3 GB |
| 许可证 | Open Data Commons Attribution License v1.0(ODC-BY 1.0),开放访问无需注册 |
| 典型用途 | 房颤检测算法的跨人群外测、原始波形与 RR 间序两条路线的对照、AF 负荷估计、临床协变量建模 |
| DOI | 版本 1.0.1 为 10.13026/n6yq-fq90;最新版本为 10.13026/f5mp-gx65 |
§1 它要解决的具体麻烦
1.1 一个被默认的盲区
房颤检测是深度学习在心电领域落地最早、也最成功的一块。围绕它形成了两套主流技术路线:一套吃原始波形,用一维卷积或 Transformer 直接从电压序列里学特征;另一套只吃 RR 间序,把心跳间隔当作时间序列来分类。两条路线在各自的论文里都能拿到漂亮的数字,而这些数字几乎全部产自同源数据集——在 MIT-BIH 房颤库上训练,再在 MIT-BIH 房颤库上按记录切分测试。
问题在于,这种闭环只能证明"模型学会了这个库",不能证明"模型学会了房颤"。人群构成、采集设备、电极位置、预处理链、标注口径,五件事只要有一件变了,成绩就可能不认。要检验这一点,需要一个在五个维度上同时与主流库不同、且能公开获取的对照集。在此之前,东亚人群这一维度是缺的。
SHDB-AF 的官方背景段把这件事点破了:已公开的心电数据库里没有一个含日本人群样本。它给的不是"又一个房颤库",而是这个缺失维度上的第一份公开读数。
1.2 三条常见的错误期待
第一条,期待它能当训练集。 128 段、122 名受试者、单一机构。这个体量在长时程库里不算小,但放在深度学习里仍然属于"一两个 epoch 就能记住"的区间。想用它把模型训出来,会立刻过拟合;它能做的是外测、微调与对照。
第二条,期待它有心搏形态标签。 它没有。.atr 里标的是节律区间的起点与类型,不是每个心搏是正常、室早还是房早。想要做 N/S/V/F/Q 五分类,这份数据给不出标签。
第三条,期待 128 段全都有标注。 只有 98 段有。另外 30 段是官方明确说明"为补全数据集而纳入、无节律标注"的波形。把它们当标注数据读进去,会得到 30 段全空的标签。
1.3 它能给到的与给不到的
| 你的需求 | 它给的 | 够不够 |
|---|---|---|
| 房颤检测的跨人群外测 | 日本人群、另一家厂商设备、另一套预处理链 | 够,这是它最正的用法 |
| 原始波形路线与 RR 间序路线的对照 | 同一批记录两种输入都能构造 | 够,官方论文两条路线都跑过 |
| AF 负荷(房颤时间占比)估计 | 节律区间标注带起止时刻 | 够,但要按区间口径自己算 |
| 房颤与房扑、房速的细分类 | 五类节律标签,房扑与房速有独立标注 | 够做探索,类别体量差异大 |
| 心搏形态分类 | 无 | 不够,无心搏级形态标签 |
| 室性心律失常研究 | 无 | 不够,标注协议只覆盖室上性节律 |
| 心梗定位或十二导联形态学 | 只有两个改良导联 | 完全不够 |
| 临床预测建模(用药、消融、合并症) | 45 列电子病历字段 | 可做,但样本量只支持小规模探索 |
| 长期随访与结局分析 | 无 | 不够,无随访、无生存数据 |
1.4 你的处境与它能帮到的事
| 你的处境 | 它能帮你什么 | 下一步该做什么 |
|---|---|---|
| 你有一个在主流派颤库上训好的模型,想知道它是否真的泛化 | 提供一个在人群、设备、导联、预处理、标注口径上都不同的外测集 | 零样本跑一遍,把掉分幅度当作泛化读数;不要在本库上微调后再报告"泛化" |
| 你在做可穿戴单导联算法,担心导联配置换了就失效 | 两路改良双极导联(CC5 与 NASA),与常规单导联库不同 | 分导联报告结果,不要只报两路平均 |
| 你想比较"吃原始波形"与"吃 RR 间序"两条路线 | 同一批记录可同时构造两种输入,且官方两条路线都有基线 | 固定受试者划分,两条路线用同一份切分 |
| 你想把临床变量并入模型 | 45 列电子病历字段可与波形对齐 | 先把 Data_ID 与 Subject_ID 的对应关系理顺,一名受试者可能有多段 |
| 你在写综述,需要一个"东亚人群"的引用 | 它是目前公开库里这一格的代表 | 引用 Sci Data 论文与 PhysioNet 版本 DOI |
| 你想做大规模预训练 | 无 | 不适合,换大体量库 |
1.5 一句话判断
它的价值不在"多了一百段房颤",而在"多了一个此前没人能测的人群维度"——拿它当外测与对照,比拿它当训练数据更能问出真话。
1.6 不适合谁:四条边界
不适合拿来做主力训练。 122 名受试者的规模只够做微调与外测,不够做从零训练。
不适合拿来做形态学研究。 两个改良双极导联不是标准十二导联,ST 段、QRS 形态这类判读标准不能直接套用。
不适合拿来做室性心律失常。 标注协议明确只标注室上性节律,正常窦律与其他节律干脆不标。
不适合拿来做日期敏感的流行病学。 去标识化把与受试者直接相关的日期整体平移至少一年,真实日历时间不可复原。
§2 数据构成与规格
2.1 一段记录由四个文件组成
数据库沿用 WFDB(Waveform Database)格式。每段记录对应四个同名文件:.hea 是纯文本头文件,声明采样率、信号条数与增益;.dat 是二进制信号本体,两路交错存放;.atr 是节律标注文件;.qrs 是 R 峰位置文件。四者分工明确,缺一个都会让语义不完整。
这里有一个容易踩空的地方:.qrs 的存在会让很多人以为它就是标注。不是。ANNOTATORS 文件写得清清楚楚,atr 是 reference rhythm annotations,而 qrs 是 unaudited beat annotations——后者是算法跑出来的、未经人工审核的 R 峰序列。
| 文件 | 角色 | 示例体积(记录 001) |
|---|---|---|
001.hea |
头文件,声明 2 路、200 Hz、17220000 点 | 142 B |
001.dat |
两路信号本体 | 65.7 MB |
001.atr |
节律区间标注 | 280.9 KB |
001.qrs |
自动 R 峰位置,未审核 | 842.4 KB |
AdditionalData.csv |
全部记录的临床与人口学元数据 | 31.6 KB |
RECORDS.txt |
128 行记录名清单 | 512 B |
ANNOTATORS |
标注角色说明,两行 | 64 B |
SHA256SUMS.txt |
全量校验和 | 34.8 KB |
LICENSE.txt |
许可全文 | 19.9 KB |
README.md |
说明文档(内容滞后于 1.0.1) | 4.6 KB |
example.jpg |
一张示例心电图图 | 155.9 KB |
2.2 字段与列的完整字典
本库的"字段"分三层:头文件的关键字行、标注文件的类型与 aux_note、以及 CSV 的 45 列。
| 信息项 | 所在位置 | 取值形态 | 含义 | 使用注意 |
|---|---|---|---|---|
| 记录名 | .hea 第 1 行首字段 |
001 |
Data_ID,三位数字 | 与 CSV 的 Data_ID 对齐 |
| 信号条数 | .hea 第 1 行第 2 字段 |
2 |
导联数 | 全部记录均为 2 |
| 采样率 | .hea 第 1 行第 3 字段 |
200 |
每秒采样点数 | 分发版本已重采样,非原始 125 Hz |
| 采样点数 | .hea 第 1 行第 4 字段 |
17220000 |
总长度 | 逐记录不同,不能写死 |
| 文件名 | .hea 信号行第 1 字段 |
001.dat |
信号存放位置 | 两路共用一个 .dat |
| 存储格式 | .hea 信号行第 2 字段 |
16 |
16 位带符号整数 | 不是浮点 |
| 增益 | .hea 信号行第 3 字段 |
如 8105.23.../mV |
每毫伏对应的整数值 | 逐记录、逐导联不同 |
| ADC 零值 | .hea 信号行括号内 |
如 -9270 |
零电平对应的整数值 | 换算时先减零值 |
| 初始值 | .hea 信号行第 6 字段 |
如 -9267 |
首采样点整数值 | 用于校验读取是否连续 |
| 校验和 | .hea 信号行第 7 字段 |
如 62791 |
采样点累加和 | 校验 .dat 完整性 |
| 导联名 | .hea 信号行末字段 |
ECG1 / ECG2 |
通道标识 | 不是 I/II/V1 这类标准名 |
| 节律标签 | .atr 的 aux_note |
(AFIB 等 |
区间起点与类型 | 绝大多数条目的 aux_note 为空串 |
| 标注符号 | .atr 的 symbol |
" |
WFDB 的 NOTE 类型 | 不能当心搏类型读 |
| R 峰位置 | .qrs |
采样点序号 | 算法检测的心搏时刻 | 未经人工审核 |
AdditionalData.csv 的 45 列按语义分组如下:
| 分组 | 列数 | 列名 | 说明 |
|---|---|---|---|
| 标识与标注状态 | 3 | Data_ID、Subject_ID、Annotated |
Annotated 为布尔,98 真 30 假 |
| 体格 | 3 | Height、Weight、BMI |
来自电子病历,单位分别为米、千克 |
| 记录时间与场景 | 4 | Date_Holter、Holter_start_time、Holter_recording_length、Indication_Holter |
起始时间为当日相对时刻,长度为 hh:mm:ss |
| 人口学 | 3 | Age_at_Holter、Sex、Age_75_or_Older |
年龄为做 Holter 当年的岁数 |
| 房颤诊断与病程 | 4 | AF_Type、Previously_Documented_AFL、Date_of_First_Diagnosis_of_AF_AFL、AF_Duration_Months |
AF_Type 取阵发性、持续性、非房颤三值 |
| 消融史 | 7 | Previous_AF_Ablation、Date_1st_AF_Ablation、Ablation1_PVI、Ablation1_CTI、Ablation1_Others、Date_Redo_AF_Ablation、Redo_Detail |
首程与再程术式均有细分 |
| 起搏器 | 4 | PPM_on_Holter、PPM_after_Holter、PPM_Indication、PPM_Date |
记录时与记录后分别标记 |
| 用药 | 3 | Antiarrhythmic_Drug_nonBB、Anticoagulation、Antiarrhythmic_Drug_BB |
记录前的长期用药 |
| 超声心动 | 4 | Echo_Date、Echo_LAD、Echo_LVEF、Echo_LV_Asynergy |
左房内径与射血分数 |
| 瓣膜 | 4 | Moderate_or_Severe_MR、..._TR、..._AS、..._AR |
中重度返流与狭窄 |
| 合并症 | 5 | CHF、HTN、DM、Stroke、Vascular_Diseases |
布尔型合并症标记 |
| 备注 | 1 | Comments |
自由文本 |
2.3 一条记录的完整解剖
以 001 为例。头文件第一行与两行信号声明如下:
001 2 200 17220000
001.dat 16 8105.233566939608(-9270)/mV 16 0 -9267 62791 0 ECG1
001.dat 16 11470.645879660451(543)/mV 16 0 408 55919 0 ECG2
第一行读作:记录 001,两路信号,200 Hz,共 17220000 个采样点。17220000 ÷ 200 = 86100 秒,即 23 小时 55 分 0 秒——不是整整二十四小时,记录有剪裁,做逐段切窗时尾部的零头要单独处理。
两路信号的增益不同:ECG1 是 8105.23 个整数单位对应 1 毫伏,ECG2 是 11470.65。两路的 ADC 零值也不同,分别是 -9270 与 543。这意味着两路信号的绝对幅度不可直接比较,也意味着把整数值直接喂进模型会混入采集链的标定差异。正确做法是读到物理单位后再比较。
读取波形与两份标注的标准写法:
import wfdb
#-- 远程直读;pn_dir 指向 PhysioNet 上的库名
rec = wfdb.rdrecord('001', pn_dir='shdb-af')
rhythm = wfdb.rdann('001', 'atr', pn_dir='shdb-af')
rpeak = wfdb.rdann('001', 'qrs', pn_dir='shdb-af')
print(rec.fs, rec.sig_len, rec.sig_name) #-- 200 17220000 ['ECG1', 'ECG2']
print(rec.p_signal.shape) #-- (17220000, 2),已换算成毫伏
print(rhythm.ann_len, rpeak.ann_len) #-- 两份标注条数相同
print(rhythm.aux_note[:6]) #-- ['(AFIB', '', '', '', '', '']
p_signal 是按增益与零值换算后的浮点毫伏值,需要原始整数用 d_signal。aux_note 只在节律切换的那一拍写入标签,其余为空串——这一点决定了后面整条标注解析的写法。
2.4 节律标注的五类与区间语义
官方把节律分成五类,标签写在 aux_note 里,每条标记代表一个节律区间的开始,下一条标记出现即前一个区间结束。官方给出的心搏条数与区间条数如下:
| 标注 | 节律 | 心搏条数 | 区间条数 |
|---|---|---|---|
(N |
其他(含正常窦律,未标注) | 7,812,308 | 无 |
(AFIB |
心房颤动 | 2,512,959 | 809 |
(AFL |
心房扑动 | 195,659 | 45 |
(AT |
房性心动过速 | 48,800 | 57 |
(PAT / (NOD |
其他室上性心动过速(含预激、结内折返) | 4,416 | 9 |
区间的时长边界由官方给出:最短 2.5 秒,最长可达 24 小时,官方另给出区间时长中位数 47.5 秒与 17.0 至 270.25 秒的一段范围。这组数字说明两件事:一是阵发性事件的粒度跨度极大,从几秒到整段;二是房扑与房速的区间条数远少于房颤,做细分类时这两类的样本基础很薄。
还有一层要讲清楚:(N 不是"标注为正常",官方原文是"其他,例如正常窦律,未标注"。也就是说,非室上性节律区间在文件里没有显式标记,需要由相邻标记之间的空隙反推——这与 MIT-BIH 房颤库那种显式给 (N 的写法在语义上并不完全等价,做跨库标签映射时要当心。
2.5 与同类房颤库的字段差异
| 维度 | SHDB-AF | MIT-BIH 房颤库 | 长期房颤库 | PAF 预测挑战赛库 |
|---|---|---|---|---|
| 人群 | 日本单一中心 | 美国 | 美国 | 美国(含术后人群) |
| 导联 | 2(CC5、NASA) | 2 | 2 | 2 |
| 分发采样率 | 200 Hz | 250 Hz | 128 Hz | 128 Hz |
| 单段时长 | 约 24 小时 | 约 10 小时 | 24–25 小时 | 30 分钟窗口 |
| 标注层级 | 节律区间 | 心搏 + 节律 | 心搏 + 节律 | 阵发房颤预测标签 |
| 临床元数据 | 45 列 | 极少 | 极少 | 极少 |
| 许可 | ODC-BY 1.0 | ODC-BY 1.0 | ODC-BY 1.0 | ODC-BY 1.0 |
这张表要读的是最后一列之外的差异:SHDB-AF 在"人群"与"临床元数据"两行上与其他库不重叠,而在其他行上高度重叠。这正是它能当对照集的理由——变量控制得住,只有人群在变。
2.6 两个导联的物理含义
官方说明原始采集用 Fukuda 动态心电图记录仪,以 125 Hz 数字化,记录两路:modified CC5 与 NASA 导联。两者都是 Holter 常用的改良双极导联配置,用来在长时间佩戴中兼顾波形幅度与伪差抑制,它们的电极位置与标准十二导联里的任何一导都不等价。
这一点对使用者的直接影响是:不能把在这两路上学到的波形形态直接迁移到十二导联设备上,也不能反过来用十二导联的形态学判读标准来解释这两路。官方页面没有给出两个导联的精确电极坐标,属于本文未核验的内容;凡是要写进论文方法节的导联描述,建议直接引用官方原文的两个导联名,而不要自行推断坐标。
§3 它是谁的数据
3.1 贡献者与机构
三位署名作者分跨两地。Kenta Tsutsui(筒井健太)隶属埼玉医科大学国际医疗中心与帝京大学,是数据侧的临床端;Shany Biton Brimer 与 Joachim Behar 隶属以色列理工学院生物医学工程系,是算法与标注方法端。配套论文的完整作者名单还包括 Sellal、Oster、Mori、Ikeda、Arai、Nakano、Kato 等人。
这个组合解释了数据的形状:一家日本医疗中心有临床记录与伦理通道,一个以色列工程团队有标注工具与模型评测需求,两边合起来才凑得出"为检验泛化而采集"的数据集。伦理审批由埼玉医科大学国际医疗中心机构审查委员会给出,编号 2023-145;因研究为回顾性描述性,书面知情同意被豁免。
3.2 时间线
| 时间 | 事件 |
|---|---|
| 2019 年 5 月—2023 年 5 月 | 临床医嘱下的 Holter 记录采集窗口 |
| 2023 年 | 机构审查委员会批准,编号 2023-145 |
| 2024 年 6 月 22 日 | 预印本 arXiv:2406.16974 上线 |
| 2024 年 8 月 12 日 | PhysioNet 版本 1.0.0 首次发布 |
| 2024 年 12 月 29 日 | 发布说明标注版本 1.0.1 发布 |
| 2025 年 4 月 16 日 | 版本页与页面元数据标注的发布日期 |
| 2025 年 | 正式论文发表于 Scientific Data,第 12 卷 454 号 |
版本页与发布说明在 1.0.1 的日期上给出两个不同数字,本文在 §10 里单列说明,使用者引用时建议以页面给出的版本 DOI 为准。
3.3 采集场景与纳入排除
采集不是为研究设计的筛查,而是"主治医师依临床需要开具的动态心电图检查"。这个出发点决定了人群构成:来做 Holter 的人通常已有症状或已有诊断,不是自然人群。
纳入排除链条由官方给出:共收集 145 份 Holter 记录,128 份进入数据库,17 份因重复、临床信息缺失或信号质量差被排除。进入的 128 份中,98 份带节律标注,来自 93 名受试者;另外 30 份为补全数据集纳入,无标注。在带标注的这一批里,约 100 份按年龄、性别与房颤诊断做了分层抽样后重新标注,其中 80 份来自确诊房颤的受试者。
3.4 从原始记录到分发文件的四层加工
| 层次 | 处理 | 影响 |
|---|---|---|
| 第一层:采集 | Fukuda 记录仪,125 Hz,两路改良导联,约 24 小时 | 原始分辨率低于分发版本 |
| 第二层:滤波 | 零相位二阶 IIR 带通,通带 0.67–100 Hz | 基线漂移与高频噪声已被官方处理掉 |
| 第三层:重采样 | 抗混叠滤波后重采样至 200 Hz | 拿不到未滤波、未重采样的原始波形 |
| 第四层:标注 | epltd 实现 Pan-Tompkins 检 R 峰;心脏科医师用 PhysioZoo 标节律区间 | R 峰未审核;节律区间为人工 |
四层里最需要记住的是第二与第三层:预处理已经固化在数据里。想做"不同滤波策略对模型的影响"这类研究,这份数据给不出未滤波的对照组。反过来,这也意味着用它的结果与用其他库的结果对比时,预处理差异是被控制住的——这既是限制,也是它作为对照集的优点。
去标识化按 HIPAA 指南与当地法规执行:每位受试者被赋予 000 至 143 之间的随机三位标识,不足三位补零;与受试者直接相关的日期统一平移至少一年。
§4 它最独特的东西
4.1 稀缺性:第一个日本人群样本
官方背景段逐一列举了此前的公开库——MITDB、AFDB、LTAFDB、IRIDIA-AF、Icentia11k、CPSC2021——并给出结论:没有一个含日本人群样本。这不是修辞。房颤的患病率、卒中风险与抗凝策略在不同人群间的差异已有大量临床文献讨论,而算法侧的公开数据长期只覆盖欧美与中国的采集点,日本这一格是空的。
补上一格的难度不在技术,在伦理与协作。回顾性医疗数据的跨境共享需要机构审查、去标识化方案与明确的合作框架,这也解释了为什么这份数据直到 2024 年才出现,而不是在房颤算法热起来的那几年就出现。
4.2 差异化证据
| 维度 | SHDB-AF | 主流房颤库的常见状态 | 差异的意义 |
|---|---|---|---|
| 人群 | 日本单一中心 | 欧美为主 | 检验跨族群泛化的唯一公开抓手 |
| 采集指征 | 临床医嘱 | 混有筛查与研究队列 | 更接近真实就诊路径,也更偏已病人群 |
| 设备 | Fukuda | 多家厂商 | 采集链整体不同 |
| 原始采样率 | 125 Hz | 128–250 Hz 不等 | 分发版统一到 200 Hz,但采集链不同 |
| 导联 | 两个改良双极导联 | 两个改良或标准导联 | 与常规单导联设备的对应关系需自行验证 |
| 临床协变量 | 45 列 | 通常极少 | 支持协变量建模与分层分析 |
| 标注协议 | 只标室上性节律 | 多为心搏级 | 任务口径不同,不能混用 |
4.3 一个具体案例:记录 001
把 001 从头到尾读一遍,能看到这份数据的典型形态。CSV 里它对应 65 岁男性,Holter 指征是"消融后房颤监测",房颤类型为阵发性,既往有房扑记录、既往做过消融,服用氟卡尼与华法林,超声左房内径 40 毫米、射血分数 39%,记录起始于上午 10:10,时长 23:54:59。
波形侧:.hea 声明 200 Hz、17220000 点;.atr 与 .qrs 各有 143768 条标注,两者条数一致——这说明节律标注文件的每一条都挂在一个算法检出的 R 峰上,而不是独立的时间戳。第一条 aux_note 是 (AFIB,出现在第 1595 个采样点,也就是记录开始后约 8 秒。
这个案例把三件事同时展示了出来:临床表与波形可以对得上(Data_ID 即文件名);节律标注挂在 R 峰上而非独立时间轴;一个"消融后监测"的病例在记录一开始就在房颤里。第四件事是反面的——这条记录里房颤之外的区间在 .atr 里没有显式标签,得靠空隙反推。
4.4 标注粒度:区间级,不是心搏级
标注协议由官方说明:由一名心脏科医师(文中简称 MA)完成,使用 PhysioZoo 软件,通过安全服务器远程访问,遵守 HIPAA 与 GDPR;标注聚焦于室上性心律失常的四类——房颤、房扑、房性心动过速、其他室上性心动过速(含预激与结内折返),正常窦律与其他节律不标注。官方给出每条二十四小时记录的平均标注耗时约 45 分钟。
粒度选择的后果很实际:你能拿到"从几分几秒到几分几秒是房颤",拿不到"第几个心搏是房早"。做 AF 负荷、做发作次数、做持续时长分布都成立;做心搏形态分类、做室早检测都不成立。
4.5 边界条件
| 边界 | 官方说明 | 对使用者的含义 |
|---|---|---|
| 标注范围 | 仅室上性节律 | 室性事件无标签,不能当负样本 |
| 未标注区间 | 正常窦律与其他节律不标 | (N 是"未标注"而非"已标为正常" |
| 标注人数 | 一名心脏科医师 | 无复核人,无观察者间一致性可报 |
| R 峰来源 | 算法检测,ANNOTATORS 明示未审核 | 时刻类指标带有检测器误差 |
| 记录数上限 | 128 段,其中 98 段有标注 | 有效样本比表面数字少三成 |
| 时间信息 | 日期平移至少一年 | 不能做真实日历时间分析 |
| 机构 | 单一中心 | 只能做跨库,不能做跨中心 |
§5 怎么拿到:从目录树到可训练张量
5.1 目录结构与下载面
PhysioNet 的文件目录是扁平的:128 组文件加 7 个附属文件,全部堆在根目录,没有按年份或受试者分目录。
| 路径 | 内容 | 大小量级 |
|---|---|---|
/files/shdb-af/1.0.1/RECORDS.txt |
128 行记录名 | 512 B |
/files/shdb-af/1.0.1/ANNOTATORS |
标注角色说明 | 64 B |
/files/shdb-af/1.0.1/AdditionalData.csv |
临床与人口学元数据 | 31.6 KB |
/files/shdb-af/1.0.1/xxx.hea |
头文件 | 约 145 B/段 |
/files/shdb-af/1.0.1/xxx.dat |
两路信号 | 约 66 MB/段 |
/files/shdb-af/1.0.1/xxx.atr |
节律标注 | 数十 KB 至数百 KB/段 |
/files/shdb-af/1.0.1/xxx.qrs |
R 峰位置 | 数百 KB 至 1 MB/段 |
/files/shdb-af/1.0.1/SHA256SUMS.txt |
校验和清单 | 34.8 KB |
整库未压缩 8.3 GB,官方 ZIP 7.3 GB。这个体量对长时程库来说不算离谱,但也不是"随手下完"的级别——先下 CSV 与几段做管线验证,确认无误再拉全量,是更省时间的顺序。
5.2 批量下载
#-- 官方推荐的三种方式之一:整库 ZIP
wget -r -N -c -np https://physionet.org/files/shdb-af/1.0.1/
#-- 只下元数据与标注,跳过信号,先搭管线
wget -r -N -c -np -A "*.hea,*.atr,*.csv,*.txt" \
https://physionet.org/files/shdb-af/1.0.1/
#-- 同步后再用官方校验和清单核对
cd shdb-af/1.0.1 && sha256sum -c SHA256SUMS.txt | tail -5
第二条命令是有意为之:先只拉几 KB 级的头文件与标注文件,把切窗、标签映射、划分逻辑全部跑通,再去拉 8.3 GB 的信号。长时程库的常见浪费,是下载占了半天、管线却在最后一步才发现标签口径错了。
5.3 用 wfdb 流式读取
import wfdb
#-- 注意:官方清单名为 RECORDS.txt(带扩展名),与 PhysioNet 常见的 RECORDS 不同
with open('RECORDS.txt') as f:
names = [x.strip() for x in f if x.strip()]
print(len(names), names[0], names[-1])
#-- 只读标注,不落盘信号
ann = wfdb.rdann(names[0], 'atr', pn_dir='shdb-af')
print(ann.ann_len, ann.sample[:3], ann.aux_note[:3])
需要提醒的是,wfdb.get_record_list('shdb-af') 在这份数据上取不到清单(清单文件名带 .txt 后缀,与该函数默认的查找约定不符),直接用上面的读文件方式更稳。
5.4 切窗与转表
import wfdb
import numpy as np
import pandas as pd
FS = 200
WIN = 30 * FS #-- 三十秒一窗,房颤检测文献里的常见粒度
def windows(name, lead=0):
rec = wfdb.rdrecord(name, pn_dir='shdb-af')
out = []
for s in range(0, rec.sig_len - WIN, WIN):
out.append(rec.p_signal[s:s + WIN, lead].astype('float32'))
return np.stack(out) if out else np.empty((0, WIN))
df = pd.read_csv('AdditionalData.csv', dtype={'Data_ID': str})
print(df.shape, df['Annotated'].sum())
这段代码只解决"切出等长张量",标签要另走一步。切窗时还有两个细节:一是各段长度不同(示例 001 是 86100 秒而非 86400 秒),尾部零头要么丢弃要么单独处理;二是窗不能跨记录拼接,否则会把两个人的信号缝在一起。
5.5 节律标注的解析与映射
import wfdb
import pandas as pd
ann = wfdb.rdann('001', 'atr', pn_dir='shdb-af')
#-- aux_note 非空处即区间起点;空串处为区间内部
rows = []
for smp, note in zip(ann.sample, ann.aux_note):
if note:
rows.append({'sample': smp, 'sec': smp / 200.0, 'label': note})
seg = pd.DataFrame(rows)
seg['end_sec'] = seg['sec'].shift(-1)
print(seg.head())
print(seg['label'].value_counts())
这张表就是 AF 负荷、发作次数与发作时长统计的原料。口径要在方法节写清三条:区间的终点取下一标记的时刻还是记录末尾;不足一窗的碎区间如何处理;非房颤区间是显式构造还是按空隙反推。三条口径不同,同一份数据能算出三个不同的负荷数字。
5.6 五个最容易出错的地方
| 位置 | 错误写法 | 后果 | 正确做法 |
|---|---|---|---|
| 记录清单 | 用 wfdb.get_record_list |
取不到清单 | 直接读 RECORDS.txt |
| 编号遍历 | for i in range(1, 144) 拼文件名 |
16 个编号不存在,报 404 | 按清单遍历,编号不连续 |
| 标注解析 | 把 .atr 的 symbol 当心搏类型 |
全是 " 这一个 NOTE 符号 |
读 aux_note |
| 标签语义 | 把 (N 当"已标注为正常" |
伪造负样本 | 官方原文是"未标注" |
| 导联比较 | 两路整数值直接比大小 | 增益与零值不同,幅度不可比 | 用 p_signal,分导联报告 |
第五行还有个延伸问题:.qrs 的 R 峰是算法跑出来的、未审核的,凡是要算 RR 间序的研究,最好用自己的检测器重跑一遍再与官方序列对齐,把差异报告的出来。
§6 与库内条目的关系
6.1 关系图谱
SHDB-AF 在房颤类数据里的位置,可以用"人群 × 标注层级"两个轴摆出来:
| 相关条目 | 人群与规模 | 标注层级 | 与 SHDB-AF 的关系 |
|---|---|---|---|
| MIT-BIH 房颤库 | 美国,25 例 × 约 10 小时双导联 | 心搏 + 节律 | 互补:房颤检测的元基准,人群不同 |
| 长期房颤库(LTAFDB) | 美国,84 例 × 24–25 小时双导联 | 心搏 + 节律 | 互补:长期负荷的标准,人群不同 |
| PAF 预测挑战赛库 | 100 名受试者,双通道 128 Hz | 阵发房颤预测标签 | 分工不同:预测未来发作,不是检测当前节律 |
| 房颤终止挑战库 | 80 段一分钟双通道 | 终止标签 | 分工不同:研究发作如何结束 |
| Icentia11k | 11,000 名居家患者,单导联 | 心搏 + 节律 | 分工不同:大体量预训练,人群不同 |
| PhysioNet/CinC 2021 | 中国多中心,十二导联短片段 | 多标签诊断 | 分工不同:形态学诊断,非长时程节律 |
| 心内房颤库(IAFDB) | 8 位患者,心内八通道 | 房颤相关标注 | 分工不同:腔内信号,非体表 Holter |
| INCART 心律失常库 | 俄罗斯,75 段 × 30 分钟十二导联 | 心搏 | 分工不同:十二导联形态,非长时程节律 |
| ICU 床旁房颤数据集 | 加拿大,596 条十秒四导联 | 医师双标注 | 分工不同:短片段、床旁场景 |
6.2 检索路径
| 你要找的东西 | 检索词 | 会落到哪里 |
|---|---|---|
| 房颤检测的开山基准 | MIT-BIH AFDB、房颤长时程 |
§6.1 表第一行 |
| 日级房颤负荷标准 | LTAFDB、Long-Term AF |
§6.1 表第二行 |
| 发作预测而非检测 | PAF prediction |
§6.1 表第三行 |
| 大体量单导联预训练 | Icentia11k、single-lead |
§6.1 表第五行 |
| 十二导联形态学诊断 | CinC 2021、12-lead |
§6.1 表第六行 |
| 跨导联一致性 | INCART、12-lead 30 min |
§6.1 表第八行 |
| 东亚人群房颤 | SHDB-AF、Japanese Holter |
本文 |
6.3 与其他库的分工判据
选数据集时最实际的问题不是「哪个最好」,而是「哪个负责哪一段」。下面把常见房颤任务逐项拆开:
| 任务 | 主粮仓该用什么 | SHDB-AF 的位置 | 原因 |
|---|---|---|---|
| 房颤检测模型预训练 | Icentia11k、大体量单导联库 | 不参与 | 一百余段不足以预训练 |
| 房颤检测跨人群外测 | 无替代品 | 主力 | 唯一公开的日本人群样本 |
| 原始波形路线与 RR 间序路线对照 | 任一长时程库 | 主力之一 | 官方两条路线都给了基线 |
| AF 负荷量化方法学 | LTAFDB | 辅助 | 样本量小,但标注粒度够 |
| 房颤终止预测 | 房颤终止挑战库 | 不适用 | 无终止时刻标注 |
| 阵发房颤发作预测 | PAF 预测挑战赛库 | 不适用 | 任务是检测而非预测 |
| 心搏形态分类 | MIT-BIH 心律失常库 | 不适用 | 无心搏形态标签 |
| 临床协变量建模 | 无成熟对应 | 主力 | 45 列电子病历字段 |
| 十二导联形态学诊断 | CinC 2021、大库 | 不适用 | 只有两个改良导联 |
这张表最容易被高估的一行是第一行:把 SHDB-AF 当粮仓的人不少,但它真正的独占格只有"跨人群外测"与"协变量建模"两处。
§7 质量评估与局限性
7.0 阅读本节前的一个前置校正
先纠正一个常见误判:把 128 段当成"采集能力不足"。这份数据的原始收集量是 145 份,排除 17 份后留下 128 份,排除理由是重复、临床信息缺失与信号质量差——这是有标准的选择,不是规模不够。评价它时不能套用"越大越好"的尺子,而应该问:在它要回答的那个问题(跨人群泛化)上,它的样本够不够。
这个校正会改变五维评分的读法。规模一项它拿不到高分,但在"任务唯一性"上它几乎无可替代。
7.1 五维评分
按数据质量的常用维度打分,每项 1–5 分,分数针对"作为房颤检测算法研究数据"这个用途:
| 维度 | 分数 | 理由 |
|---|---|---|
| 数据规模 | 2 | 128 段、122 名受试者,训练不足,外测够用 |
| 标注质量 | 4 | 医师人工标注节律区间,但单一标注者、R 峰未审核 |
| 任务适配 | 5 | 跨人群外测与协变量建模几乎无替代品 |
| 文档完整 | 4 | 官方页把纳入排除、预处理、标注协议写清,但 README 滞后 |
| 可获取性 | 4 | 免注册、ODC-BY,但 8.3 GB 体量不小 |
五项合计 19 分(满分 25)。结构与 INCART 那类"小而不可替代"的库一致:规模拖后腿,其余四项稳健,适配性拉满。
7.2 标注质量的两层
第一层是类型与区间对不对。由一名心脏科医师用 PhysioZoo 完成,协议明确,聚焦室上性节律。这是它能当可信外测集的基础。但要如实说:官方页面在摘要里写"由心脏科 fellow 手工完成",在方法段写"由认证心脏科医师标注",两处措辞并不一致,本文未找到关于标注者人数与是否设复核人的进一步说明,属于未核验内容。
第二层是位置准不准。ANNOTATORS 文件把话挑明了:qrs 是 unaudited beat annotations。R 峰由 epltd 实现的 Pan-Tompkins 算法自动检测,没有人工审核。任何依赖精确时刻的指标——RR 间序、心率变异性、房颤发作起止的秒级界标——都会带上这份误差。
| 用途 | 位置误差的影响 | 建议 |
|---|---|---|
| 三十秒窗级房颤检测 | 小,窗内不靠单个 R 峰 | 可直接用 |
| RR 间序路线建模 | 中到大,误差直接进入输入 | 自行检测后与官方序列交叉验证 |
| 心率变异性 | 大 | 不适合直接用 |
| 发作起止时刻的秒级界标 | 中 | 报告时给出容差 |
7.3 已知的、可枚举的偏差
| 偏差 | 表现 | 影响 |
|---|---|---|
| 单一机构 | 全部来自日本一家医疗中心 | 设备、贴电极规范、判读习惯都单一 |
| 单一族群 | 日本人群 | 不能代表东亚其他人群,也不能代表欧美 |
| 采集指征偏斜 | 全部为临床医嘱下的检查 | 已病人群,正常对照不足 |
| 三成无标注 | 128 段中 30 段无节律标注 | 有效有监督样本只有 98 段 |
| 单一标注者 | 一名医师完成 | 无观察者间一致性可报 |
| 标注范围窄 | 只标室上性节律 | 室性事件无标签 |
| 预处理固化 | 已带通、已重采样 | 拿不到未处理波形做对照 |
| 时间平移 | 日期整体偏移至少一年 | 不能做真实日历分析 |
| 无随访 | 无结局、无重复检查 | 不能做纵向研究 |
| 文档滞后 | README 仍是 1.0.0 时代的列名 | 按 README 写的解析脚本会报错 |
最后一行值得单独强调:README.md 里列的仍是 Study ID、UID 这类旧列名,而 1.0.1 的 CSV 实际列名已改为 Data_ID、Subject_ID,并新增了 Holter_start_time、Holter_recording_length 两列。按 README 写解析脚本,第一步就会对不上列。
7.4 外部验证
官方背景段给出了两条技术路线在本库上的基线:ArNet2 用逐搏时间间隔做输入,在 SHDB 上取得 F1 0.92;RawECGNet 用原始单导联心电信号做输入,F1 0.93。这两个数字来自官方页面引用的两篇论文,是"有人这样用并给出了成绩"的证据,不是可以直接搬进对比表的第三方复现结果。
| 验证角色 | 做法 | 讲得通的地方 | 风险 |
|---|---|---|---|
| 跨人群外测 | 在欧美库上训练,本库零样本测试 | 人群、设备、预处理同时变化 | 掉分幅度同时含人群与设备两种因素,无法拆分 |
| 双路线对照 | RR 间序模型与原始波形模型同场比较 | 同一批记录、同一份标注 | 两路线的输入构造口径要写清 |
| 协变量建模 | 把 45 列临床字段并入模型 | 公开房颤库里少见的配重 | 122 名受试者只支持低维模型 |
| 微调与领域适应 | 本库上少量微调 | 可在报告里区分"零样本"与"见过本库" | 微调后不能再称跨人群泛化 |
第三行是个真实的机会:把房颤检测的判别结果与临床变量拼在一起做风险分层,在公开数据里能同时拿到波形与这么多临床字段的场景不多。风险也很清楚——样本量决定了只能做低维探索,任何"多变量深度学习预测"的设想在这里都撑不住。
7.5 它为何能持续
它没有扩版计划,也不会变大体量,但作为对照集的地位是稳的:东亚人群公开长时程房颤数据的门槛在伦理与协作,不在采集。只要这个门槛还在,新库就很难在这个格子里替代它。反过来,如果未来出现多中心的亚洲房颤库,它的角色会从"唯一的那一格"退到"最早的那一格"——但历史数据不会被撤,引用链也已经在论文里沉淀下来。
§8 生态位与历史
8.1 历史沿革
这份数据的诞生方式与上一代 PhysioNet 库截然不同。INCART、MIT-BIH 那批库是"机构整理已有记录后捐赠",属于数据富余的副产品;SHDB-AF 是"为了回答一个具体问题而回头整理数据"——官方说得很明白,数据最初是为评估 ArNet2 在不同分布偏移下的泛化性能而收集的。
这个出身决定了它的形状:规模由研究问题定,不由可得数据量定;标注协议围绕房颤设计,不追求全类型;临床字段被特意保留,因为要做分层分析。理解这一点,就不会再用"为什么只有一百多段"来质疑它。
8.2 与挑战赛的关系
它没有被用作任何一届 PhysioNet/CinC 挑战赛的数据源。这一点与 MIT-BIH 房颤库、长期房颤库、PAF 预测挑战赛库都不同——后三者分别是若干届赛题的直接来源,因而被大量论文反复使用。
缺少挑战赛曝光带来两个后果:一是引用量增长慢,二是使用者的口径更自由(没有官方赛题规定评测协议)。好处是数据没有被"赛题化"地裁剪成短片段,长时程与临床字段都保持了原样。
8.3 生态位:少数派对照集
| 角色 | 主力粮仓 | 对照尺 |
|---|---|---|
| 典型用法 | 大规模训练、预训练 | 外部测试、跨域评测、消融对照 |
| 需要的前提 | 数据量大、标签细 | 人群不同、设备不同、采集链不同 |
| 代表 | Icentia11k、CinC 2021 | SHDB-AF、INCART |
| 失败模式 | 过拟合、标签噪声累积 | 样本少导致结论不稳 |
SHDB-AF 坐在右边这一列,且比 INCART 更靠近"外测"这一端,因为它的人群维度是独占的。把对照尺当粮仓用,会立刻遇到规模瓶颈;把粮仓当对照尺用,会立刻遇到"自己测自己"。
8.4 谁在用它,用来做什么
从官方页面与配套论文看,使用者集中在三类:做跨人群泛化的算法组(把它当外测集)、做原始波形与 RR 间序两条路线比较的方法组、做临床协变量建模的转化研究组。第三类目前最少,但它是这份数据最独特的承载面。
官方页面显示引用它的公开文献数量仍是个位数,其中一篇是配套的数据描述论文本身。这个数字既是现状,也是提醒:它的价值还没被广泛兑现,同时也意味着"别人都这么做"的方法学惯性在这里还没有形成,使用者需要自己把口径写清楚。
§9 使用指引
9.1 三种角色的路径
| 角色 | 第一天 | 第一周 | 注意事项 |
|---|---|---|---|
| 算法研究者 | 下 CSV 与几条记录,跑通 §2.3 的读取 | 建立按受试者划分的外测基线,报告零样本掉分 | 不要在本库上微调后称泛化 |
| 设备工程师 | 分导联跑一遍,看两路差异 | 评估自己设备的导联配置与 CC5/NASA 的差距 | 两路增益不同,先换算物理单位 |
| 临床转化研究者 | 读 45 列字段,做可用性与缺失检查 | 做小规模协变量建模或分层分析 | 122 人只支持低维模型 |
9.2 一条最短的可用流程
#-- 1. 只下元数据与清单,先确认口径
wget -q https://physionet.org/files/shdb-af/1.0.1/RECORDS.txt
wget -q https://physionet.org/files/shdb-af/1.0.1/AdditionalData.csv
#-- 2. 按 Annotated 列分出有标注的 98 段
python3.11 - <<'PY'
import pandas as pd
df = pd.read_csv('AdditionalData.csv', dtype={'Data_ID': str})
ids = df.loc[df['Annotated'], 'Data_ID'].tolist()
print(len(ids), ids[:5])
PY
#-- 3. 只拉这 98 段的标注文件,跳过信号
while read r; do
wget -q "https://physionet.org/files/shdb-af/1.0.1/${r}.atr"
done < <(python3.11 -c "import pandas as pd;df=pd.read_csv('AdditionalData.csv',dtype={'Data_ID':str});print('\n'.join(df.loc[df['Annotated'],'Data_ID']))")
import wfdb
import pandas as pd
#-- 4. 解析区间,建立受试者级别的划分键
df = pd.read_csv('AdditionalData.csv', dtype={'Data_ID': str})
subj = dict(zip(df['Data_ID'], df['Subject_ID']))
ann = wfdb.rdann('001', 'atr', pn_dir='shdb-af')
labels = [(s, n) for s, n in zip(ann.sample, ann.aux_note) if n]
print(subj['001'], len(labels), labels[:3])
划分必须按 Subject_ID 而不是 Data_ID:122 名受试者对应 128 段记录,一名受试者可能贡献多段,按记录随机切分会把同一个人的不同记录分进两侧,结果虚高。
9.3 引用方式
PhysioNet 的惯例是引用数据集本身、配套论文与平台三处:
| 引用对象 | 内容 |
|---|---|
| 数据集 | Tsutsui, K., Biton Brimer, S., & Behar, J. (2025). SHDB-AF: a Japanese Holter ECG database of atrial fibrillation (version 1.0.1). PhysioNet. doi:10.13026/n6yq-fq90 |
| 配套论文 | Tsutsui, K., Brimer, S.B., Ben-Moshe, N. et al. SHDB-AF: a Japanese Holter ECG database of atrial fibrillation. Sci Data 12, 454 (2025). doi:10.1038/s41597-025-04777-4 |
| 平台 | PhysioNet 平台综述论文,按官方页面的 Cite 按钮生成 |
| 许可 | ODC-BY 1.0,须署名 |
写论文时建议同时注明四条:使用的版本号(1.0.1)、是否只用带标注的 98 段、划分是否按受试者、以及区间标签的解析口径(终点取法与窗内多标签的处理)。这四条不写清,复现就无从谈起。
§10 AI 使用声明
| 项目 | 声明 |
|---|---|
| 文本生成 | 本文由 AI 辅助撰写,编辑把关结构与事实 |
| 数字来源 | 规模、结构、边界三类数字来自 PhysioNet 官方页面与文件目录 |
| 文件核验 | RECORDS.txt、ANNOTATORS、AdditionalData.csv、001.hea、001.atr、001.qrs 经直接访问确认 |
| 不一致说明 | 版本 1.0.1 的日期在发布说明(2024-12-29)与版本页(2025-04-16)上不同;受试者数在 README(127)、摘要与临床表(122)之间不同;标注者身份在摘要(fellow)与方法段(认证医师)间措辞不同;README 列名与 1.0.1 实际列名不同 |
| 论文信息 | 仅依据官方页面给出的题录与摘要,未读全文 |
| 未核验内容 | 两个导联的精确电极坐标、标注者人数与复核人、各记录的房颤负荷、30 段无标注记录的选择标准、逐记录标注耗时 |
| 图像 | 无配图;封面为生成式提示词,不含真实心电图 |
| 免责 | 本文不构成临床建议;数据使用须遵守 ODC-BY 1.0 署名要求 |
常见误读(避坑清单)
| 说法 | 实际 | 证据 |
|---|---|---|
| 「它有 128 段标注数据」 | 只有 98 段带节律标注,30 段只有波形 | 官方摘要与 CSV 的 Annotated 列 |
| 「它有心搏形态标签」 | 只有节律区间标签,无 N/S/V/F/Q | 标注协议只覆盖室上性节律 |
「.qrs 就是标注」 |
是算法检测的 R 峰,ANNOTATORS 明示未审核 | ANNOTATORS 第二行 |
「(N 表示标注为正常」 |
官方原文是"其他,例如正常窦律,未标注" | 官方数据描述段 |
| 「它是 125 Hz」 | 分发版本 200 Hz,125 Hz 是原始采集率 | 官方预处理段与 .hea 第一行 |
| 「它能做十二导联形态学研究」 | 只有两个改良双极导联 | .hea 的 ECG1、ECG2 |
| 「按记录随机切分就可以了」 | 122 名受试者贡献 128 段,须按受试者划分 | CSV 的 Subject_ID 列 |
| 「README 里的列名就是 CSV 列名」 | README 停留在 1.0.0,列名已改 | README 写 Study ID/UID,CSV 实际为 Data_ID/Subject_ID |
| 「编号 001 到 143 都有」 | 有 16 个编号不存在 | 清单共 128 个,最大编号 143 |
| 「它的日期可以做流行病学分析」 | 与受试者相关的日期整体平移至少一年 | 官方去标识化段 |
FAQ
Q1:SHDB-AF 到底有多少段记录、多少名受试者?为什么不同地方写的数字不一样?
128 段记录、122 名受试者,其中 98 段带节律标注、来自 93 名受试者。数字打架的原因是几处官方材料不同步:PhysioNet 页面摘要与临床汇总表写 122,随库分发的 README.md 写 127,页面元数据描述里写过 100 名患者。以版本 1.0.1 的 CSV 为准最稳妥——直接读 AdditionalData.csv,数据行是 128 行,Subject_ID 去重后是 122 个,Annotated 为真的有 98 行。README 是 1.0.0 时代留下来的文件,列名都还没改,不要拿它当字段字典。
Q2:它能直接拿来做房颤检测模型的训练吗?
不建议作为主力训练集。122 名受试者、单一机构、单一族群,这个规模做从零训练会迅速过拟合,而且过拟合的方式很隐蔽:模型记住的是这一批人的房颤形态,而不是房颤本身。它更合适的三种用法是零样本外测、在严格控制下做小样本微调、以及作为两条技术路线的同场对照。若一定要微调,报告时必须明确区分"零样本成绩"与"见过本库后的成绩",否则泛化结论不成立。
Q3:.atr 里的标注应该怎么读?为什么每条的符号都一样?
.atr 用的是 WFDB 的 NOTE 类型,symbol 字段一律是 "(双引号字符),真正的信息在 aux_note 字段里。解析方式是遍历 aux_note,非空处即一个节律区间的起点,标签形如 (AFIB、(AFL、(AT、(PAT、(NOD;下一个非空处出现,前一个区间就结束了。空串处表示仍处在上一个区间内部,不代表任何独立标签。官方给出的数据也印证了这一点:房颤的区间条数只有 809 条,而心搏条数是 251 万级,两者不在同一个量级上。
Q4:它和 MIT-BIH 房颤库、长期房颤库该怎么分工?
三个库在任务上是重叠的,在人群上不重叠。MIT-BIH 房颤库是房颤检测的元基准,长期房颤库是日级房颤负荷与长期节律分类的标准,两者都来自美国采集点。SHDB-AF 的人群是日本,采集设备、原始采样率、预处理链与临床元数据配置都与前两者不同。合理的分工是:用前两者训练与调参,用 SHDB-AF 做跨人群外测;反过来拿它训练、拿前两者测试,得到的"泛化"结论会因为测试集与训练分布更接近而偏乐观。
Q5:临床元数据表能用来做什么,有什么坑?
AdditionalData.csv 有 128 行、45 列,覆盖体格、记录时间与指征、人口学、房颤类型与病程、消融史、起搏器、用药、超声、瓣膜、合并症与备注。它能支持的是小规模协变量建模、分层分析与病例描述。坑有三个:一是列数虽多、样本只有 122 人,任何高维模型都撑不住;二是字段名以 1.0.1 的 CSV 表头为准,README.md 里列的是旧名;三是与受试者相关的日期被整体平移至少一年,真实日历时间不可复原,凡是要按年份、季节做的分析都不成立。
术语表
| 术语 | 解释 |
|---|---|
| Holter | 便携式长时程心电监护,患者随身佩戴记录仪生活与睡眠 |
| 动态心电图 | 同 Holter,指连续记录二十四小时以上的体表心电 |
| 心房颤动 | 心房电活动紊乱,心室率绝对不规则的心律失常 |
| 心房扑动 | 心房快速而规整的折返性节律,与房颤常相互转换 |
| 房性心动过速 | 起源于心房的快速规整节律 |
| 阵发性 | 事件间歇出现并可自行终止,与持续性相对 |
| 导管消融 | 经导管破坏异常电通路以治疗心律失常的介入手段 |
| 肺静脉隔离 | 房颤消融的常见术式,隔离肺静脉与左房的电连接 |
| 改良 CC5 导联 | Holter 常用的双极改良导联之一,非标准十二导联 |
| NASA 导联 | Holter 常用的另一路改良双极导联配置 |
| 抗凝治疗 | 用药物降低血栓栓塞风险的长期治疗 |
| β 受体阻滞剂 | 一类控制心率与节律的常用药物 |
| 左房内径 | 超声测量的左心房大小,房颤评估常用指标 |
| 射血分数 | 超声测量的左心室每搏输出比例 |
| WFDB | PhysioNet 使用的波形数据库格式,含头文件、信号、注释 |
.hea |
纯文本头文件,声明采样率、增益、零值 |
.dat |
二进制信号文件,多路交错存放 |
.atr |
注释文件,本库存放节律区间标签 |
.qrs |
注释文件,本库存放自动检测的 R 峰位置 |
| aux_note | WFDB 注释里的附加文本字段,本库用它承载节律标签 |
| 增益 | 每毫伏对应的整数单位数,换算物理量时使用 |
| ADC 零值 | 零电平对应的整数值,换算时先减 |
| 带通滤波 | 只保留某段频率范围的滤波,本库为 0.67–100 Hz |
| 重采样 | 改变采样率,本库从 125 Hz 升到 200 Hz |
| Pan-Tompkins | 经典的实时 QRS 检测算法 |
| 节律区间标注 | 标注一段时间内的节律类型,与心搏级标注不同 |
| 心搏级标注 | 对每一次心搏标出位置与形态类型 |
| AF 负荷 | 房颤时间占记录总时长的比例 |
| 去标识化 | 移除或扰动可识别信息,本库采用随机编号与日期平移 |
| ODC-BY | 开放数据共享署名许可,允许商业使用但须署名 |
| PhysioNet | 由 MIT 等机构维护的生物医学信号数据平台 |
| 受试者级划分 | 同一名受试者的所有记录只进训练或只进测试 |
附录 A:核心数字核对表
| 项 | 值 | 来源 |
|---|---|---|
| 记录数 | 128 | 官方摘要;RECORDS.txt 逐行 |
| 受试者数 | 122 | 官方临床汇总表;CSV 去重 |
| 带节律标注的记录数 | 98 | 官方摘要;CSV 的 Annotated 列 |
| 带标注记录对应的受试者数 | 93 | 官方方法段 |
| 无标注记录数 | 30 | 官方方法段 |
| 原始收集记录数 | 145(排除 17) | 官方方法段 |
| 导联数 | 2(ECG1、ECG2) | 官方数据描述段;.hea |
| 原始采集采样率 | 125 Hz | 官方方法段 |
| 分发采样率 | 200 Hz | .hea 第一行 |
| 示例记录 001 采样点数 | 17220000 | 001.hea |
| 示例记录 001 时长 | 86100 秒,约 23 小时 55 分 | 17220000 ÷ 200 |
| 带通通带 | 0.67–100 Hz | 官方预处理段 |
| 节律类别数 | 5 | 官方数据描述段 |
| 房颤心搏条数 | 2,512,959 | 官方统计表 |
| 房颤区间条数 | 809 | 官方统计表 |
| 房扑区间条数 | 45 | 官方统计表 |
| 房速区间条数 | 57 | 官方统计表 |
| 其他室上速区间条数 | 9 | 官方统计表 |
| 区间时长边界 | 最短 2.5 秒,最长 24 小时 | 官方数据描述段 |
| 区间时长中位数 | 47.5 秒 | 官方数据描述段 |
| 临床元数据规模 | 128 行 × 45 列 | AdditionalData.csv 表头与数据行 |
| 单段信号体积 | 约 66 MB | 001.dat 目录标注 |
| 整库未压缩体积 | 8.3 GB | 官方文件页 |
| 官方 ZIP 体积 | 7.3 GB | 官方文件页 |
| 记录编号范围 | 001–143,实际存在 128 个 | RECORDS.txt |
| 受试者随机编号范围 | 000–143 | 官方去标识化段 |
| 采集窗口 | 2019 年 5 月—2023 年 5 月 | 官方方法段 |
| 伦理批件号 | 2023-145 | 官方伦理段 |
| 版本 1.0.0 发布 | 2024 年 8 月 12 日 | 官方版本历史 |
| 版本 1.0.1 日期 | 2024-12-29(发布说明)/ 2025-04-16(版本页) | 官方发布说明与版本页 |
| 许可 | ODC-BY 1.0 | 官方访问段 |
| DOI(v1.0.1) | 10.13026/n6yq-fq90 | 官方发现段 |
| 配套论文 | Sci Data 12, 454 (2025) | 官方引用段 |
附录 B:数字的来源分层
第一层:官方页面与官方文件。 记录数、受试者数、标注记录数、导联、采样率、采样点数、节律类别与条数、区间时长边界、临床表规模、体积、编号范围、采集窗口、版本日期、许可与 DOI,全部来自项目页的摘要、方法、数据描述与版本历史,以及 RECORDS.txt、ANNOTATORS、AdditionalData.csv、001 的头文件和两份标注文件。
第二层:论文题录。 配套论文的期刊、卷号与年份,以及两条技术路线在本库上的 F1 数值,来自官方页面给出的题录与背景段,未读全文。
第三层:未核验。 两个导联的精确电极坐标、标注者人数与是否设复核人、各记录的房颤负荷、30 段无标注记录的选择标准、逐记录的实际标注耗时。这些需要下载全量并查阅论文全文,本文按要求只做定性表述或留白。
附录 C:完整参考文献
| 编号 | 文献 | 链接 | 用途 |
|---|---|---|---|
| 1 | SHDB-AF v1.0.1 官方页 | https://physionet.org/content/shdb-af/1.0.1/ | 全文规模、结构、边界数字的来源 |
| 2 | SHDB-AF v1.0.1 文件目录 | https://physionet.org/files/shdb-af/1.0.1/ | 清单、头文件、CSV、标注文件 |
| 3 | Tsutsui K, Brimer SB, Ben-Moshe N, et al. Sci Data 12, 454 (2025) | https://doi.org/10.1038/s41597-025-04777-4 | 配套论文,数据描述 |
| 4 | Tsutsui K, Brimer SB, Ben-Moshe N, et al. arXiv:2406.16974 | https://arxiv.org/abs/2406.16974 | 预印本版本 |
| 5 | Biton S, et al. NPJ Digital Medicine 6, 44 (2023) | https://doi.org/10.1038/s41746-023-00776-2 | ArNet2 与泛化评测方法 |
| 6 | Ben-Moshe N, et al. RawECGNet, IEEE JBHI (2024) | 官方引用段给出 | 原始波形路线的对照模型 |
| 7 | PhysioNet 平台综述(Nature Health, 2026) | https://doi.org/10.1038/s44360-026-00096-z | 托管模式与引用规范 |
| 8 | MIT-BIH 房颤库(对照) | https://physionet.org/content/afdb/ | §2.5 与 §6 对比 |
| 9 | 长期房颤库(对照) | https://physionet.org/content/ltafdb/ | §2.5 与 §6 对比 |
| 10 | Icentia11k(对照) | https://physionet.org/content/icentia11k/ | §6 分工判据 |
附录 D:任务代码
任务一:建一条记录上的房颤负荷流水线
import wfdb
import numpy as np
import pandas as pd
FS = 200
def af_burden(name, pos=('AFIB',)):
#-- 读区间起点;空 aux_note 表示仍在上一个区间内
ann = wfdb.rdann(name, 'atr', pn_dir='shdb-af')
starts, labels = [], []
for smp, note in zip(ann.sample, ann.aux_note):
if note:
starts.append(smp)
labels.append(note.strip('('))
hdr = wfdb.rdheader(name, pn_dir='shdb-af')
#-- 最后一个区间的终点取记录末尾
ends = starts[1:] + [hdr.sig_len]
dur = (np.array(ends) - np.array(starts)) / FS
lab = np.array(labels)
total = hdr.sig_len / FS
af = dur[np.isin(lab, list(pos))].sum()
return {'record': name, 'total_sec': total,
'af_sec': float(af), 'burden': float(af / total),
'n_episode': int((lab == 'AFIB').sum())}
print(af_burden('001'))
任务二:按受试者分组的三十秒窗数据集
import wfdb
import numpy as np
import pandas as pd
FS, WIN = 200, 30 * FS
df = pd.read_csv('AdditionalData.csv', dtype={'Data_ID': str})
subj = dict(zip(df['Data_ID'], df['Subject_ID']))
annotated = df.loc[df['Annotated'], 'Data_ID'].tolist()
def label_at(ann, lo, hi):
#-- 窗内有任一区间起点属于目标节律即标为房颤,口径需写进方法节
for smp, note in zip(ann.sample, ann.aux_note):
if note and lo <= smp < hi and note.strip('(') == 'AFIB':
return 1
return 0
rows = []
for name in annotated[:5]:
rec = wfdb.rdrecord(name, pn_dir='shdb-af')
ann = wfdb.rdann(name, 'atr', pn_dir='shdb-af')
for lo in range(0, rec.sig_len - WIN, WIN):
rows.append({'record': name, 'subject': subj[name],
'start_sec': lo // FS,
'y': label_at(ann, lo, lo + WIN)})
print(pd.DataFrame(rows).shape)
第二段代码里的窗标签口径是最粗糙的一种(窗内出现房颤区间起点即标 1)。写正式实验时至少要改三处:换成"窗内房颤时长占比超过阈值"这类连续口径;把 Annotated 为假的 30 段排除;划分按 subject 而不是 record。
附录 E:如果只记五件事
| 序号 | 记住什么 | 为什么 |
|---|---|---|
| 1 | 128 段、122 名受试者、98 段有标注、2 导联、200 Hz | 这五个数字定义了一切用法与限制 |
| 2 | 它是跨人群外测集,不是训练粮仓 | 拿它做主力训练会过拟合且结论失真 |
| 3 | 节律标签在 .atr 的 aux_note,.qrs 是未审核 R 峰 |
解析方式与常见心电库完全不同 |
| 4 | 按 Subject_ID 划分,按 CSV 表头写解析 |
122 人对 128 段,README 已滞后 |
| 5 | 它唯一不可替代的是日本人群加 45 列临床字段 | 房颤类公开库里这两项此前都是空的 |
编辑说明
本文的核验时间为 2026 年 10 月 29 日。核对方式为直接访问 PhysioNet 项目页与文件目录,逐一确认 RECORDS.txt、ANNOTATORS、AdditionalData.csv、001.hea、001.atr、001.qrs 的可访问性与内容,并用 WFDB 工具远程读取过 001 的波形头与两份标注。论文侧只依据官方页面给出的题录与摘要,未读全文。
核实过程中发现的不一致均已写入 §10:版本 1.0.1 的日期在发布说明与版本页上不同;受试者数在 README 与页面摘要之间不同;标注者身份在摘要与方法段措辞不同;README 的列名停留在 1.0.0。本文在涉及这些数字时统一以 CSV 实际内容与页面摘要为准,并在正文中标注分歧。
未覆盖的内容包括:两个导联的精确电极坐标、标注者人数与观察者间一致性、各记录的房颤负荷、30 段无标注记录的选择标准、逐记录的实际标注耗时。这些需要下载全量并查阅论文全文后统计,本文按要求只写规模、结构、边界三类数字。SHDB-AF Holter 心电库(版本 1.0.1)是 PhysioNet 上首个公开的日本人群长时程房颤数据集,其定位与使用边界已在前文逐节说明。
相关数据集导航
以下为站内 AI-Ready 数据集百科中与本词条共享多个主题标签的相关数据集,按相关度降序排列:
- [mit-bih-afdb](https://www.qianfanghub.com/ai-ready-dataset/mit-bih-afdb/115)(共享标签:生理信号 / 心电信号 / 心血管疾病)
- [ltafdb](https://www.qianfanghub.com/ai-ready-dataset/ltafdb/668)(共享标签:生理信号 / 心电信号 / 心血管疾病)
- [afpdb](https://www.qianfanghub.com/ai-ready-dataset/afpdb/1435)(共享标签:生理信号 / 心电信号 / 心血管疾病 / 挑战赛数据集)
- [aftdb](https://www.qianfanghub.com/ai-ready-dataset/aftdb/1457)(共享标签:生理信号 / 心电信号 / 心血管疾病 / 挑战赛数据集)
- [incartdb](https://www.qianfanghub.com/ai-ready-dataset/incartdb/1440)(共享标签:生理信号 / 心电信号 / 心血管疾病)
- [icentia11k](https://www.qianfanghub.com/ai-ready-dataset/icentia11k/652)(共享标签:生理信号 / 心电信号 / 心血管疾病)
- [cinc-2021](https://www.qianfanghub.com/ai-ready-dataset/cinc-2021/644)(共享标签:生理信号 / 心电信号 / 心血管疾病 / 挑战赛数据集)
- [iafdb](https://www.qianfanghub.com/ai-ready-dataset/iafdb/1504)(共享标签:生理信号 / 心电信号 / 心律失常)
- [kingston-icu-af](https://www.qianfanghub.com/ai-ready-dataset/kingston-icu-af/1009)(共享标签:生理信号 / 心电信号 / 心律失常)
- [ecg-arrhythmia](https://www.qianfanghub.com/ai-ready-dataset/ecg-arrhythmia/1314)(共享标签:生理信号 / 心电信号 / 心血管疾病)
导航说明:本章节由全站统一标签体系自动计算生成(标签重合度算法),双向可达;点击链接可跳转至对应数据集词条。

