十二导联做满半小时 — INCART 心律失常库

75 段 30 分钟 / 12 导联 257 Hz / 逐搏标注

来源 https://physionet.org/content/incartdb/1.0.0/发布时间: 2026-10-27最后更新: 2026-10-27 阅读 30
十二导联做满半小时 — INCART 心律失常库

信息速览

数据集名称十二导联做满半小时 — INCART 心律失常库
数据类型时序信号,波形,人工标注,元数据
规模32 名患者 / 75 段记录
接入方式https://physionet.org/content/incartdb/1.0.0/
AI 就绪度

三十秒的门诊心电图里,十二个导联同时在看同一颗心脏;二十四小时的 Holter 里,只有两三个导联在整夜盯着它。两件事在临床上各有各的位置,却几乎从不合流——十二导联的诊断价值来自导联间的关系(心梗的定位、束支阻滞的分型都靠它),长时程的价值来自时间上的覆盖(阵发性事件只在某个夜里出现)。而公开数据集的取舍也一直是二选一:十二导联的库通常每段只给十秒,长时程的库通常只给一到两个导联。

INCART 是这条分界线上的一个例外。圣彼得堡心脏病技术研究所把为冠心病检查所做的 Holter 记录重新切成半小时一段,保留了全部十二个标准导联,配上逐搏注释,在 2008 年交给了 PhysioNet。它因此能回答一个别处很难回答的问题:同一次心律失常发作,在十二个导联上的表现差异有多大——有些房颤在 V1 清晰得像教科书,在肢体导联上却几乎看不出来;用一个导联训练出来的模型,会在这类记录上系统性地漏诊。

它的代价同样明确:只有 75 段、32 名患者、单一中心、俄罗斯人群,标注以心搏为主而非节律为主。它不是规模上的大库,是一件稀缺的"对照工具"。一屏速览见下表。

维度 内容
全名 St Petersburg INCART 12-lead Arrhythmia Database
发布方 PhysioNet(原始数据由俄罗斯圣彼得堡 Institute of Cardiological Technics 贡献)
首次发布 2008 年 5 月 1 日,版本 1.0.0
最近改动 2015 年 9 月 18 日,重算头文件校验和,信号与标注未改
记录数 75 段
患者数 32 名(17 男、15 女,18–80 岁,平均 58 岁)
每段时长 30 分钟
导联数 12(I、II、III、aVR、aVL、aVF、V1–V6)
采样率与分辨率 257 Hz,16 位带符号整数存储,增益 250–1100 ADC 单位/毫伏
每段采样点 462600
原始来源 32 份冠心病检查 Holter
标注规模 合计超过 175,000 条心搏标注
标注生成方式 自动初标 + 人工修正,遵循 PhysioBank 标准心搏注释定义
文件格式 WFDB:.hea 头文件 / .dat 信号 / .atr 注释
许可 ODC-BY 1.0,无需注册
典型用途 心搏分类的跨库测试、房颤检测、单导联与多导联对比、噪声鲁棒性评估

§1 它要解决的具体麻烦

1.1 每一段心电图都是"半个证据"

心电图在诊断链条上有两种价值,对应两种完全不同的采集姿态。第一种是"形态价值":十二个导联从不同角度切开心电向量,ST 段抬高在哪几个导联上出现、QRS 波群的宽度落在哪个区间,都能指向具体的心肌壁与传导通路。这种价值对导联数极度敏感,少一个 V1,右束支阻滞的分型就无从谈起。第二种是"节律价值":心房是规整地放电还是一团颤动、室性早搏是一天几个还是几分钟一个、心动过缓发生在凌晨几点。这种价值对覆盖时长极度敏感,对导联数要求不高——一个足够干净的 II 导联就能判断大部分节律问题。

临床为了拿到这两种价值,付出了两笔不同的代价。门诊十二导联只需躺十秒钟,便宜、快速、不打扰患者,但只能看到十秒钟的节律;Holter 要背一整天,能抓住阵发性事件,但要背十二个电极会让患者无法正常工作与睡觉,于是退到两到三个导联。这就是为什么临床上不存在"十二导联二十四小时"的常规检查——不是没人想过,是患者背不动。

公开数据集继承了同样的分界。十二导联的库,比如各家医院贡献的诊断级数据库,普遍给的是十秒一类的短片段;长时程的库,比如 MIT-BIH 房颤库、长期房颤库,普遍是一到两导联配二十小时以上的覆盖。两者各自成为成熟的任务基准,但它们共同缺了一个维度:跨导联的一致性。

1.2 三条常见的错误期待

第一条,期待它是"高质量的十二导联诊断数据"。它的原始记录来自 Holter,电极是贴在体表、在患者走动时录的,噪声水平明显高于静息十二导联机打的十秒图。把它当诊断级的形态学标准来用,会立刻遇到基线漂移与肌电干扰(§7.3)。

第二条,期待它有"房颤逐段标签"。它的注释文件是心搏级的,AFIB 这类节律标注是否存在、覆盖多少,取决于标注者对每一段的处理,官方页面并没有承诺逐段节律标签。想用做房颤二分类,标签得自己从心搏序列或诊断描述里推(§2.2)。

第三条,期待它能代表"健康人的十二导联"。全部患者都是为冠心病检查而来,官方明确说筛选时优先选了心电图与缺血、冠心病、传导异常、心律失常相符的人。它是一个"异常偏多"的人群,正常心搏的多样性反而不足。

1.3 它能给到的与给不到的

你的需求 它给的 够不够
心搏级别的形态分类(N/S/V/F/Q) 十七万余条心搏标注,十二导联同步 够,且可以同时评估单导联与多导联的差距
房颤检测的训练与测试 心搏序列 + 部分记录诊断中含房颤或阵发性房颤 可做,但标签需二次加工
长时程节律负荷统计 每段三十分钟,可以算单位时间负荷 够做片段级,不足以做日级负荷
心梗的导联定位 十二导联齐全,部分记录描述含 ST 改变 不够,无导联级 ST 定量标注
束支阻滞分型 十二导联齐全,部分记录诊断含束支阻滞 可做探索,样本太少不足以训练
健康人群基线 — 不够,全部为冠心病人群
多中心泛化验证 单一中心、单一国家 不够,只能做"跨库"而不是"跨中心"
可穿戴单导联算法评测 可从十二导联中抽出任一导联 够,这是它最有价值的用法之一

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

你的处境 它能帮你什么 下一步该做什么
你已用 MIT-BIH 心律失常库训好一个心搏分类器,想证明它不只是记住了那 47 个人 提供同一套注释码、另一套设备与人群的外部测试集,标注可直接映射 先跑零样本外测拿到掉分幅度,再决定是否做微调;按患者编号划测试集
你在做可穿戴单导联房颤检测,担心模型只在"好导联"上有效 同一段时间里有十二个导联,可逐导联训练、逐导联评测,量化导联位置造成的性能差 固定患者划分,训练集与测试集使用同一导联,再单独跑"训练用 II、测试用 V1"的错配实验
你要做噪声鲁棒性研究,缺一个干净的噪声源 长度三十分钟、十二导联同步,便于叠加同源噪声并保持导联间关系 用标准噪声库按目标信噪比叠加,记录每个导联的原始信噪比作为协变量
你在教心电图判读,需要一个"同一发作、多种表现"的例子 可截取同一时间窗内十二导联波形做对照教学 用 §2.3 的读取流程导出图像,注意标注位置可能有偏移
你想做一个十二导联节律分类模型,但手里只有短片段库 提供长时程上下文,可以把十秒片段放进三十分钟背景里比较 先确认你要的是片段级还是记录级标签,后者需自建
你在核对某个公开结果的复现性 规模小、下载快,适合做快速复现基线 全量只有几十兆,可一次下完(§5.2)

1.5 一句话判断

它不适合当"更大的训练集",而适合当"更锋利的尺子":在同一段时间轴上量出十二个导联之间的差异,而这个差异正是单导联模型最容易忽略的东西。

1.6 不适合谁:四条边界

不适合拿来做规模训练。 75 段、32 名患者,深度学习模型一两轮就能记住全部。想用数据量换性能的项目,用它会立刻过拟合。

不适合拿来做正常人群建模。 全部患者为冠心病检查人群,平均年龄 58 岁,异常心搏比例偏高。用它训练出的"正常心搏"表征,会偏向这一人群的形态。

不适合拿来做药物或干预研究。 记录里没有用药信息、没有随访、没有结局变量。唯一的临床上下文是 .hea 里一行诊断与一行心电图特征摘要。

不适合做严格的节律界标研究。 心拍注释的位置由算法在十二导联上综合确定,官方明确说明位置未经人工逐条校正。用它算 RR 间期、做心率变异性,误差会直接进入结果。

§2 数据构成与规格

2.1 一段记录由三个文件组成

数据库采用 WFDB(Waveform Database)格式,这是 PhysioNet 自 1980 年代沿用至今的物理信号存储规范。每一段记录对应同名的三个文件:.hea 是纯文本头文件,声明采样率、信号条数、每条信号的增益与基线并附患者信息;.dat 是二进制信号本体,按采样点交错存放十二个导联的整数值;.atr 是二进制注释文件,存放事件位置与类型。

三者缺一不可。只拿 .dat 无法还原毫伏值,因为没有增益;只拿 .atr 无法知道这些时刻对应什么波形。这也是为什么把数据转成通用格式(比如 CSV 或 NumPy)是有损操作——头文件里的增益、基线、导联名会被压进列头,注释里的类型码会被压成字符串,后续再想回到原始语义就得靠映射表(§5.4)。

数据库根目录下还有几个附属文件。RECORDS 列出全部记录名;ANNOTATORS 说明注释文件的角色(只有一行:atr reference beat annotations);record-descriptions.txt 与 files-patients-diagnoses.txt 把头文件里散落的诊断信息汇总成两个便于阅读的清单,前者按记录列出心电图特征,后者按患者列出所属记录与诊断。

2.2 字段/记录的完整字典

下表把头文件、注释文件、附属清单里的信息项逐条列出。需要强调:本库的"字段"不是表格列,而是 WFDB 头文件的关键字行与注释类型码。

信息项 所在位置 取值形态 含义 使用注意
记录名 .hea 第 1 行首字段 I01–I75 记录标识 字面量就是文件名前缀
信号条数 .hea 第 1 行第 2 字段 12 导联数 全部记录均为 12
采样率 .hea 第 1 行第 3 字段 257 每秒采样点数 非 250 也非 360,插值前要重采样
采样点数 .hea 第 1 行第 4 字段 462600 总长度 除以采样率正好 1800 秒
文件名 .hea 信号行第 1 字段 I01.dat 信号存放在哪个文件 多导联共用同一个 .dat
存储格式 .hea 信号行第 2 字段 16 16 位带符号整数 不是浮点
增益 .hea 信号行第 3 字段 如 306 ADC 单位/毫伏 逐记录不同,250–1100
位分辨率 .hea 信号行第 4 字段 16 ADC 位数 实际有效位受增益影响
ADC 零值 .hea 信号行第 5 字段 0 零电平对应的整数值 换算时先减零值
初始值 .hea 信号行第 6 字段 如 1161 首采样点整数值 2015 年修订补齐
校验和 .hea 信号行第 7 字段 如 -11409 采样点累加和 用于校验 .dat 完整性
块大小 .hea 信号行第 8 字段 0 每帧字节数 本库用自动计算
导联名 .hea 信号行第 9 字段 I…V6 解剖位置 顺序固定,12 行一一对应
年龄 .hea 注释行 65 患者年龄 以 #<age>: 开头
性别 .hea 注释行 F / M 患者性别 以 #<sex>: 开头
诊断 .hea 注释行 自由文本 临床诊断 以 #<diagnoses> 开头
患者编号 .hea 注释行 1–32 来源 Holter 序号 以 # patient 开头,划分数据集的关键
心电图特征 .hea 注释行 自由文本 如 PVCs, noise 也是 record-descriptions.txt 的内容
心搏位置 .atr 采样点序号 事件发生时刻 已由算法在十二导联综合定位
心搏类型 .atr 类型码 如 N、V、L 见下表
节律变换 .atr + 节律切换处 覆盖率因记录而异

心搏类型码沿用 PhysioBank 的标准定义,本库声明遵循该标准。最常出现的几类如下:

类型码 含义 映射到 AAMI 五分类
N 正常心搏 N
L 左束支阻滞心搏 N
R 右束支阻滞心搏 N
B 未分型束支阻滞心搏 N
A 房性早搏 S
a 伴差异性传导的房性早搏 S
J 交界性早搏 S
S 室上性早搏或异位搏动 S
V 室性早搏 V
r R-on-T 室性早搏 V
F 室性融合波 F
e 房性逸搏 Q
j 交界性逸搏 Q
n 室上性逸搏 Q
E 室性逸搏 Q
f 起搏与正常心搏融合 F
Q 无法分类的心搏 Q
? 学习阶段未分类 Q

官方说明全部患者都没有起搏器、多数有室性早搏,所以实际出现的类型集中在上面几类;/(起搏心搏)理论上不应出现,但代码里做了保留是为了兼容其他库。

2.3 一条记录的完整解剖

以 I01 为例。头文件第一行 I01 12 257 462600 说明:记录名 I01,12 个导联,257 Hz,共 462600 个采样点。462600 ÷ 257 = 1800,即 1800 秒整,也就是三十分钟——每一段都被精确切到整分钟,这一点让按分钟切窗变得非常省事。

接下来是 12 行信号声明。以 I01 的 II 导联为例:

I01.dat 16 306 16 0 457 21378 0 II

从右往左读:导联名 II;格式 16(16 位整数);.dat 内的间距是 0(表示由 wfdb 自动按 12 条 16 位信号计算帧长);校验和 21378;初始值 457;ADC 零值 0;位分辨率 16;增益 306(即 306 个整数值对应 1 毫伏,约 3.27 微伏/单位);文件名 I01.dat。

增益这一项在本库里跨度很大。I01 的十二个导联增益都在 306 附近,而 I75 的部分导联增益是 612。同一个数据库内不同记录增益不同,意味着"整数值直接喂进模型"的写法会把绝对幅度信息搅乱——必须按 .hea 换算成毫伏,或至少先按增益归一。这是本库一个容易踩的坑,因为它不像单一增益的库那样在文档里反复提醒。

文件末尾三行注释给出了患者上下文:

#<age>: 65 <sex>: F <diagnoses> Coronary artery disease, arterial hypertension
\# patient 1
\# PVCs, noise

把后面几行连起来读:I01 来自 1 号患者,65 岁女性,诊断为冠心病合并动脉高血压,这段三十分钟里能看到室性早搏,并且有噪声段。record-descriptions.txt 里对应的一行就是 PVCs, noise。

读取信号与注释的标准写法:

import wfdb
import numpy as np

#-- 远程直读,无需先下载;pn_dir 指向 PhysioNet 上的库名
rec = wfdb.rdrecord('I01', pn_dir='incartdb')
ann = wfdb.rdann('I01', 'atr', pn_dir='incartdb')

print(rec.fs, rec.sig_len, rec.sig_name[:3])    #-- 257 462600 ['I', 'II', 'III']
print(rec.p_signal.shape)                       #-- (462600, 12) 已换算成毫伏
print(ann.sample[:5], ann.symbol[:5])

#-- 统计心搏类型
from collections import Counter
print(Counter(ann.symbol).most_common(10))

p_signal 是已按增益与零值换算过的浮点毫伏值;如果需要原始整数,用 d_signal。ann.sample 是采样点序号,除以 257 即得秒数。

2.4 记录与患者的映射关系

患者的分布并不均匀:有的患者贡献了一段,有的贡献了五六段。官方说明同一患者编号下的记录都来自同一次 Holter,因此患者内部的相关性极强。

患者编号 记录数(官方清单所见) 说明
单人一段 多数患者 单次 Holter 只切出一段
单人两段及以上 少数患者 例如 2 号患者对应 I03、I04、I05 三段
合计 75 段 / 32 名患者 平均每人 2.3 段左右

上表前两行只做定性描述,具体每人的段数应以 files-patients-diagnoses.txt 为准。这个平均值的含义很直接:如果按记录做随机划分,测试集里大约每三个人就有两人在训练集里有"同一次 Holter 的兄弟段"。这是本库最容易被低估的泄漏源(§7.3)。

泄漏的机制值得拆开讲。同一次 Holter 的多段记录,共享的不只是同一个人,而是同一批电极、同一个放大器、同一段体位变化、同一套背景噪声。十二导联的增益与基线在整次记录里恒定,所以某段里出现的工频干扰形态、某个导联接触不良造成的固定偏移,会在兄弟段里原样重现。模型只要学会"这个偏移模式下该输出什么",就能在测试集里白拿分,而这个能力到真实的另一家医院就完全失效。

更隐蔽的是节律层面的相关。同一次记录里,如果患者在上午九点处于房颤、十点转复,那么被切成两段之后,一段是房颤、一段是窦律,但两段的心房形态特征(f 波振幅、P 波电轴)来自同一颗心脏。按记录随机切分时,测试段里"这个人特有的"房颤波形正在训练段里被见过。这解释了为什么一些文献里按记录切分得到的成绩那么好,换了按患者切分就掉一截——差异不来自模型强弱,来自切分口径。

正确做法很朴素:从头文件读出 # patient,把患者编号作为分组键,用 GroupKFold 或直接按编号区间切。判断标准只有一条——同一个人绝不出现在两侧。

2.5 与同类资源的字段差异

对比项 INCART MIT-BIH 心律失常库 MIT-BIH 房颤库 长期房颤库
导联数 12 2 2 2
单段时长 30 分钟 30 分钟 10 小时 24–25 小时
采样率 257 Hz 360 Hz 250 Hz 128 Hz
记录数 75 48 段 25 段 84 段
患者数 32 47 名 25 名 84 名
心搏级标注 有 有 有 有
节律级标注 部分(视记录) 部分 有 有
人群 冠心病检查人群 心律失常门诊与住院人群 阵发性或持续性房颤 长期房颤
主要用途 跨库测试、导联对比 心搏分类基准 房颤检测与终止预测 长程房颤负荷

这张表要说清的只有一件事:INCART 在"导联数"这一列上唯一性地突出,在"时长"与"规模"两列上都不占优。它的定位不是替代任何一个库,而是补上别人补不了的那一列。

2.6 十二个导联各自的物理含义

用法上的差异,根子在这十二个导联各自测的是心电向量在不同方向的投影。把它们按方向排好,很多「为什么某个导联更清楚」的问题就有了答案:

导联 安放位置 观察的主要方向 常见失真来源
I 右臂—左臂 左右方向 双臂活动导致的基线漂移
II 右臂—左腿 上下偏左 呼气末段体位变化
III 左臂—左腿 上下偏左(与 II 互补) 与 II 高度相关,异常时两者一起偏
aVR 右上 右上方 幅度小,量化噪声占比高
aVL 左肩 左上方 易受投影抵消,房性活动弱
aVF 左下 正下方 下壁缺血观察点
V1 胸骨右缘第 4 肋间 前后偏右 呼吸造成的基线起伏最明显
V2 胸骨左缘第 4 肋间 前后偏右 同上
V3 V2 与 V4 中点 前后 电极贴合度对幅度影响大
V4 左锁骨中线第 5 肋间 前后偏左 心尖搏动造成的运动伪迹
V5 左腋前线第 5 肋间 左外侧 运动伪迹
V6 左腋中线第 5 肋间 左外侧 幅度衰减

Holter 的十二导联并不是门诊机的标准几何——门诊机是十个电极、靠电阻网络合成出十二个导联,Holter 则要兼顾患者活动,电极位置与连线方式会做取舍。这意味着本库的十二导联在绝对幅度上与门诊机不可直接比。用它做「十二导联诊断学」的研究时,这一点要写进方法节;用它做「同一记录的导联间相对差异」的研究时,这个差异不影响结论——还是 §4.3 的案例给出的那个道理:横向比较比绝对值可靠。

§3 它是谁的数据:一个研究所的 Holter 遗产

3.1 贡献者与机构

数据库由俄罗斯圣彼得堡的心脏病技术研究所(Institute of Cardiological Technics,简称 Incart)贡献。官方页面把初始开发归于 Viktor Tihonenko 与 Alexander Khaustov,附加核验由 Sergey Ivanov 与 Alexei Rivin 完成,问题与更正的联系人是 Evgeniy Yakushenko。机构名里的 “Technics” 值得留意——它是一个面向心脏诊断技术的研究所,而不是单纯的临床科室,这解释了为什么这批数据从诞生起就带着"可被算法使用"的自觉:切段对齐到整分钟、注释遵循国际通用码表、头文件里把患者上下文写得齐整。

3.2 时间线

时间 事件 意义
2008-05-01 数据库在 PhysioNet 上线,版本 1.0.0 首次公开
2015-09-18 头文件修订,补齐校验和与初始值 信号与标注未动,只改元数据
2017 作为来源之一被大型房颤分类挑战赛使用 用户面从心搏分类扩展到节律分类
近年 被大量用作跨库外部测试集 定位从"可训练库"转向"可验证库"

第三、四行属于使用侧的观察,不是官方版本的变更记录,这里列出是为了说明它身份的变化(§8)。

3.3 采集场景:为冠心病检查而做的 Holter

官方原话是:原始记录取自接受冠心病检查的患者。筛选入册时,优先选心电图与缺血、冠心病、传导异常及心律失常相符的对象。这句话包含了两层筛选:第一层是临床指征——这些人本来就被怀疑有冠心病;第二层是数据挑选——从这批里再挑出心电图有"料"的。

由此可以推出它的人群画像:年龄 18–80 岁,平均 58 岁,男女比例接近均衡(17 男、15 女),无起搏器植入,多数有室性早搏。官方诊断分布表如下:

诊断 患者数 备注
急性心肌梗死 2
短暂性缺血发作(心绞痛) 5
陈旧性心肌梗死 4
冠心病合并高血压 7 其中 4 例心电图符合左心室肥厚
窦房结功能不全 1
室上性异位搏动 18 最常见
心房颤动或室上性心动过速 3 其中 2 例为阵发性房颤
WPW 综合征 2
房室传导阻滞 1
束支传导阻滞 3

这些诊断在必要时经酶学检测、冠状动脉造影、电生理检查与压力监测确认。把这张表加总会超过 32,因为一名患者可以有多个诊断——这正是它的价值所在:它不是"每人一个标签"的干净分类集,而是真实的多病共存。

3.4 数据来源的三个层次

理解这份数据要先分清三层:Holter 记录(原始,未公开)、三十分钟段(公开的基本单位)、心搏标注(公开的监督信号)。第一层不可得,说明为什么同一患者的段间相关性无法从公开数据里彻底消除;第二层决定了每段的边界都是人为切的,切点可能落在一次心律失常的中途;第三层决定了监督信号的时间粒度是心搏而不是秒。

§4 它最独特的东西:同一段时间里的十二个视角

4.1 十二导联与长时程的交集为什么稀缺

临床上做十二导联需要十根电极,做二十四小时需要患者带着记录仪生活。两者叠加,患者体验与信号质量的代价都很大,所以常规检查里不存在这种组合。公开数据集的稀缺也来自同一个现实约束:愿意公开十二导联长时程数据的机构,必须本来就有一批做了十二导联 Holter 的患者。

这正是 INCART 的来历。它不是为了做数据集而专门采集的,而是既有临床流程的副产品——研究所本来就在为冠心病患者做 Holter,把记录切段、标注、捐赠,成本远低于从零采集。

所以它的稀缺性不是"采集得精细",而是"恰好存在"。这也解释了它为什么一直只有 75 段:不是没人想要更多,而是愿意再捐一个 12 导联 Holter 队列的机构太少。

4.2 十二个导联看同一件事,结果差多少

十二导联的解剖含义可以用一句话概括:肢体导联(I、II、III、aVR、aVL、aVF)看额面,胸前导联(V1–V6)看横面。心房电活动的主向量大致朝左下后方,所以在 V1 上投影最强,信号最清楚;在 aVL 上往往接近垂直,幅度最小。

这个几何关系直接决定了它在算法评测里的用途:

导联 主要朝向 对心房活动的敏感度 对室性早搏形态的区分度
II 下壁 高(P 波明显) 中
V1 右前胸 最高(房颤 f 波最清楚) 高(可辨左右束支图形)
aVR 右上 极性相反 中
aVL 左肩 低(易被投影抵消) 低
V5 / V6 左腋 中 中

上表的"敏感度"是根据导联电轴得出的定性判断,本库本身并不提供这种逐导联的统计。它的价值在于给你一个可以做实验的场地:把同一批记录在不同的导联上各跑一遍,差异会自己显现出来。

4.3 案例:同一段房颤在 II 导联与 V1 导联上的差别

取 I50。record-descriptions.txt 里它的描述是 PVCs, tachycardia, atrial fibrillation, ST depression——室性早搏、心动过速、心房颤动、ST 段压低,四件事挤在三十分钟里。这是一段理想的观察样本:底部节律是房颤,中间还混着室早与 ST 改变。

用 §2.3 的代码读出这段信号后,取同一时间窗(比如第 600 秒到第 620 秒)画 II 与 V1:

import wfdb
import numpy as np

rec = wfdb.rdrecord('I50', pn_dir='incartdb')
fs = rec.fs
a, b = int(600 * fs), int(620 * fs)
lead2 = rec.p_signal[a:b, rec.sig_name.index('II')]
v1    = rec.p_signal[a:b, rec.sig_name.index('V1')]

#-- 用简单的差分能量比较两个导联的"可见度"
for name, x in (('II', lead2), ('V1', v1)):
    print(name, '峰峰值 mV =', round(float(np.ptp(x)), 3),
          ' 一阶差分均方 =', round(float(np.mean(np.diff(x) ** 2)), 6))

把这段实验的三种典型结果记下来,就成了后续讨论的支点:

观察 II 导联 V1 导联 对模型的含义
f 波可见度 常被 T 波与基线漂移淹没 细碎波动更清楚 单导联 II 的房颤检测容易漏掉低幅房颤
QRS 形态 下壁轴,室早常呈主波向下 右胸轴,室早常呈主波向上 同一室早两个导联的形态几乎相反
噪声敏感性 易受肌电干扰 更易受呼吸基线漂移 噪声鲁棒性评测需按导联分别报告

这不是一个"发现",而是一个可以用它自己验证的观察。§4.3 的案例在全文出现三次,分别在 §3 解释数据组织方式、§5 讲读取流程、§7 讲误判来源——之所以反复回来,是因为它把"十二导联"这个卖点从抽象的好处变成了一个可以复现的小实验。

4.4 标注的粒度:心搏级清楚,节律级模糊

这是它的第二层特色,也是它最容易被误判的地方。心搏标注非常规整:每段三十分钟,段落内每一次 QRS 都被标出类型,合计超过十七万条。这个量级意味着全库平均每分钟约 80 个心搏,符合静息到轻度活动的范围。

但节律标注不一样。PhysioBank 的标准注释体系里有 + 表示节律变换,其后可以带节律类型;本库官方页面并没有说明节律标注的覆盖策略。因此,"这一段是不是房颤"这个判断,从 .atr 里读不出来,只能从"心搏序列是否绝对不规则"或"诊断描述里有没有写房颤"间接推。

这两种推法各有代价:前者需要算法,且会在频发早搏时误判;后者只有粗粒度,因为一条记录里可能只有局部是房颤(I71 的描述就是 paroxysmal atrial fibrillation,阵发性意味着大部分时间可能不是)。

4.5 边界条件:什么情况下它不再适用

把它的优点说透之后,必须把「什么时候不该抬出它」也列清楚。下面这张表不是免责声明,而是使用判断:

条件 是否适用 判断依据
你要证明模型能处理门诊级静息十二导联 不适用 它是 Holter 记录,行动状态与门诊静息不同
你要评估模型对运动伪迹的鲁棒性 适用,而且是少有的适用场景 十二导联同时受同一段运动影响,可分别看
你要做导联缺失下的补全实验 适用 十二导联齐全,可任意遮蔽再重建
你要做 12 导联的房颤逐段分类 谨慎 节律标签不全,需自建口径并公开验证
你要做长时程(小时级)节律负荷 不适用 单段只有三十分钟,无法跨小时累计
你要做多中心外部验证 只算半边 它是外中心,但只有一处,不能代表多中心
你要做儿童或青少年心电模型 不适用 年龄下限 18 岁
你要做起搏心律识别 不适用 官方说明全部患者无起搏器

这张表最有用的两行是第三行与第六行。第三行说的补全实验,是它被低估的用途:十二导联齐全意味着你可以人为遮蔽某几个导联,训练一个「从可见导联重建被遮蔽导联」的模型,而重建得好不好可以逐导联量化。这类实验在单导联库里根本做不了。第六行则提醒:用它做外测得到的是「从一个中心跨出去」的结果,不是「跨多个中心」的结果;论文里写成后者,就是夸大。

§5 怎么拿到:从目录树到可训练张量

5.1 目录结构与下载面

PhysioNet 的文件目录是扁平的:根目录下直接放 75 组三个文件,加上几个附属清单,没有按患者或日期分的子目录。

路径 内容 大小量级
/files/incartdb/1.0.0/RECORDS 75 行记录名 数百字节
/files/incartdb/1.0.0/ANNOTATORS 注释角色说明 一行
/files/incartdb/1.0.0/record-descriptions.txt 每段的特征摘要 数千字节
/files/incartdb/1.0.0/files-patients-diagnoses.txt 患者与诊断清单 数千字节
/files/incartdb/1.0.0/Ixx.hea 头文件 约 1 KB
/files/incartdb/1.0.0/Ixx.dat 十二导联信号 约 11 MB/段
/files/incartdb/1.0.0/Ixx.atr 注释 数千字节到数十 KB

官方没有提供打包的整库压缩包,只有逐文件目录。全量按每段约十一兆估算,体量在几百兆级,可以一次下完——这是它相对大多长时程库的一个实用优点。

5.2 批量下载

#-- 只下一次,存到本地目录;--recursive 会把目录树按原样拉开
wget --no-parent --recursive --level=1 --accept=hea,dat,atr,txt \
     --directory-prefix=incartdb \
     https://physionet.org/files/incartdb/1.0.0/

#-- 核对记录数:RECORDS 末行没有换行,wc -l 会少算一条
python3.11 - <<'PY'
import urllib.request
names = urllib.request.urlopen(
    'https://physionet.org/files/incartdb/1.0.0/RECORDS').read().decode().split()
print(len(names), names[0], names[-1])
PY

第二段特意写出来,是因为 wc -l 在这里会给出 74 而不是 75。文件最后一行 I75 之后没有换行符,行计数习惯的统计会漏掉它。同样的情况在按行读取 RECORDS 的脚本里也会出现——如果不做 split 直接 line.strip,最后一行仍然被读到,但如果用 count('\n') 就错了。

5.3 用 wfdb 直接流式读取

import wfdb
import numpy as np

names = wfdb.get_record_list('incartdb')
print(len(names))                       #-- 75

#-- 逐段流式读取,不落盘;只统计心搏类型分布
from collections import Counter
tot = Counter()
for name in names:
    ann = wfdb.rdann(name, 'atr', pn_dir='incartdb')
    tot.update(ann.symbol)
print(tot.most_common(12))

get_record_list 从 RECORDS 解析,能正确处理末行无换行的情况。这个接口的好处是不需要本地磁盘,代价是每段要重新走网络,全库过一遍要一段时间。

5.4 转成通用的表结构

如果下游是 PyTorch 或 TensorFlow 的常规管线,通常需要切成定长片段。切窗策略直接决定任务难度:

import wfdb
import numpy as np
import pandas as pd

FS = 257
WIN = 10 * FS      #-- 十秒一窗,与常规十二导联诊断的时长相仿

rows = []
for name in ['I01', 'I02', 'I03']:
    rec = wfdb.rdrecord(name, pn_dir='incartdb')
    ann = wfdb.rdann(name, 'atr', pn_dir='incartdb')
    #-- 每个心拍落在哪个窗里
    win_of_beat = ann.sample // WIN
    for w in np.unique(win_of_beat):
        sel = win_of_beat == w
        #-- 取该窗内的多数心搏类型作为窗标签(示例口径,换口径请显式改)
        label = pd.Series(ann.symbol[sel]).value_counts().index[0]
        seg = rec.p_signal[w * WIN:(w + 1) * WIN]
        if seg.shape[0] < WIN:
            continue
        rows.append({'record': name, 'win': int(w), 'label': label,
                     'lead_II': seg[:, 1].astype('float32')})
df = pd.DataFrame(rows)
print(df.shape, df['label'].value_counts().head())

这段代码只用三条记录演示口径。上正式实验时有三处必须改:一是患者编号要从 .hea 的 # patient 行读进来跟着一行走,否则后面按患者划分无从下手;二是窗标签的口径要写进方法节,否则复现不了;三是只留了 II 导联一列,做多导联模型时要把十二列都留住——这正是本库和其他单导联库最根本的区别。

5.5 心搏级注释的读取与 AAMI 映射

import wfdb

AAMI = {'N': 'N', 'L': 'N', 'R': 'N', 'B': 'N',
        'A': 'S', 'a': 'S', 'J': 'S', 'S': 'S',
        'V': 'V', 'r': 'V',
        'F': 'F', 'f': 'F',
        'e': 'Q', 'j': 'Q', 'n': 'Q', 'E': 'Q', 'Q': 'Q'}

ann = wfdb.rdann('I50', 'atr', pn_dir='incartdb')
mapped = [AAMI.get(s, 'skip') for s in ann.symbol]
print(len(mapped), mapped[:8])

映射表不是这个库独有的,它来自心电算法评价的通行分组:把各种束支阻滞与正常心搏并作 N,把室上性早搏与房性早搏并作 S,把室性与 R-on-T 并作 V,把融合波作 F,其余作 Q。做跨库对比时必须用同一张表,否则数字不可比。

5.6 五个最容易出错的地方

位置 错误写法 后果 正确做法
统计记录数 wc -l RECORDS 得 74 少一条记录 按空白切分计数
幅度换算 直接用 d_signal 训练 不同记录增益不同,幅度不可比 用 p_signal 或先除增益
数据集划分 按记录随机切分 同一次 Holter 泄漏 按 # patient 分组
重采样 当成 250 Hz 处理 时间轴偏 3% 显式按 257 Hz 重采样
注释位置 当作精确 R 峰 RR 间期有系统误差 需要精确定位时自行检测

§6 与库内条目的关系

6.1 关系图谱

INCART 在心电类条目里的位置,可以用"导联数 × 时长"两个轴摆出来:

条目 导联 时长 与 INCART 的关系
PhysioNet/CinC 2017 1 数十秒 同为房颤检测来源,规模大得多但只有单导联
MIT-BIH 房颤库 2 10 小时 互补:它长、INCART 宽
长期房颤库 2 24–25 小时 互补:它是日级负荷的标准,INCART 是片段级
十二导联心律失常库(PTB-XL 类) 12 10 秒 直接对照:同为十二导联,一个长一个短
Georgia 十二导联挑战库 12 10 秒 直接对照:人群不同(美国东南部),时长相同
本库 12 30 分钟 两个维度同时不短的少数几个之一

这条关系线的意义在于:如果你要论证"多导联比单导联好",只用短片段库说服力有限,因为短片段库的标签是诊断级的、人群是筛查人群;INCART 提供的是同一段连续记录内的对照,噪声、患者、时段都相同,只有导联在变。这是最干净的对照组。

6.2 检索路径

你要找的东西 检索词 会落到哪里
同一套注释码的其他库 PhysioBank annotation、MIT-BIH §2.2 的类型码表在多个库通用
房颤长时程对照 AFDB、Long-Term AF、LTAFDB §6.1 表
十二导联短片段对照 PTB-XL、Georgia、12-lead §6.1 表与 §2.5
可穿戴单导联评测 CinC 2017、single-lead AF §1.4 的处境表
噪声鲁棒性 NSTDB、noise stress §5.6 的噪声叠加做法
挑战赛来源 CinC 2017、challenge §8.2

6.3 与其他库的分工判据

选数据集时最实际的问题不是「哪个最好」,而是「哪个负责哪一段」。下面把常见的心电任务逐项拆开,看 INCART 该站在哪一格:

任务 主粮仓该用什么 INCART 的位置 原因
心搏形态分类的预训练 大体量十二导联短片段库 只在外部测试出现 样本太少,预训练会记死
房颤检测的预训练 单导联大规模库 可在外部测试或严控下做微调 标签需二次加工
跨导联一致性研究 无可替代 主力 十二导联同步且长
导联遮蔽与补全 无可替代 主力 同上
噪声鲁棒性评测 噪声库加任一长时程库 主力之一 十二导联可分别报告
心率变异性研究 位置标注更严谨的库 辅助 位置未逐条校正
儿科心电模型 儿科专库 不适用 年龄下限 18 岁
闭环诊断报告生成 配报告的影像与信号库 不适用 只有诊断摘要,没有长文本

这张表的前两行是大多数人的真实处境:他们已经有主粮仓,缺的是一个不撒谎的裁判。被高估的用法是第三到第五行之外的所有行——把 INCART 当主粮仓的人不少,但真正需要它的场景集中在导联维度上。

§7 质量评估与局限性

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

先纠正一个常见的误判:把小样本库的问题当成"质量差"。INCART 的 75 段不是采集能力不足,而是可捐赠的十二导联 Holter 队列本来就少(§4.1)。评价它的时候不能套用"越大越好"的尺子,而应该问:在它能回答的那个问题上,它的样本够不够?

这个校正会改变五维评分的读法。规模一项它拿不到高分,但在"任务唯一性"上它几乎无可替代。把这两件事混在一起看,就会得出"不值得用"的错误结论。

7.1 五维评分

按 DAIMS 的常用维度打分,每项 1–5 分,分数针对"作为心电算法研究数据"这个用途:

维度 分数 理由
数据规模 2 75 段、32 名患者,训练不足,测试够用
标注质量 4 自动初标加人工修正,但位置未逐条校正
任务适配 5 十二导联加长时程,跨导联研究几乎没有替代品
文档完整 4 官方页面把人群、诊断、格式、注意事项写得清楚
可获取性 5 免注册、ODC-BY、体量小,一次下完

五项合计 20 分(满分 25)。这个分数结构说明它不是"全能型"选手:规模拖后腿,其余四项稳健,其中适配性拉满。

7.2 标注质量的两层

第一层是类型对不对。官方说明标注由自动算法生成后再人工修正,遵循标准定义。人工修正保证了类型的高准确度,这是它能在多个跨库研究中当"可信外部测试集"的基础。

第二层是位置准不准。官方同时明确:心拍位置由算法在十二导联上综合确定,位置本身没有人工校正,可能有偶发错位。这句话常被略过,但它对下游影响很实:任何依赖 R 峰精确时刻的指标(RR 间期、心率变异性的高频成分、QT 间期)都会带上这份误差。

用途 位置误差的影响 建议
心搏分类 小,因为分类靠形态而非时刻 可直接用
心率变异性 中到大,直接进入 RR 序列 先做自检测 R 峰再对齐
QT / 复极分析 大,需逐搏定位 不适合直接用
房颤检测 中,节律不规则性可由误差部分吞掉 配合自检测交叉验证

7.3 已知的、可枚举的偏差

偏差 表现 影响
单人中心 全部患者来自圣彼得堡一家机构 设备、贴电极规范、判读习惯都单一
人群偏斜 冠心病检查人群,平均 58 岁 健康青年的正常形态样本少
筛选偏斜 优先选心电图"有料"的人 正常段落比例低于自然人群
段间相关性 同一 Holter 切出多段 随机切分会导致乐观偏差
标注位置 算法定中,未逐条校正 时间敏感指标有误差
节律标签不全 以心搏类型为主 节律任务需二次加工
2015 年修订 只改头文件 用旧版头文件的人校验和对不上

7.4 外部验证矩阵

INCART 在这几年最常被引用的方式,是当"别人家的测试集"。这类用法可以从公开论文摘要里看出轮廓。

验证角色 做法 讲得通的地方 风险
跨库心搏分类 在 MIT-BIH 上训练,本库零样本测试 注释码同源,可直接映射 人群与设备差异会同时被算作"泛化"
跨库房颤检测 在短片段库上训练,本库外测 长时程片段更接近真实使用 标签口径需自己统一
轻量模型部署评估 在本库上跑量化与嵌入式推理 无注册本库,评测链完整 只看心搏级,看不到节律级
噪声注入 叠加噪声库做压力测试 十二导联可分别报告 本库本身噪声已偏高,叠加要谨慎

外部研究里已经能看到这种用法的原话:一篇 2026 年关于轻量心电分类的对照研究,明确把本库作为外部测试集,与 MIT-BIH 的分组切分一起评估量化与嵌入式部署;同期多篇心搏分类论文也在跨库设置里把它列为外测目标。这些引用说明它作为"外部集"的身份已经稳定,但它作为"训练集"的地位从未确立。

值得注意的是,那类轻量研究给出的结论往往并不乐观:在 MIT-BIH 自身的分组测试里表现还可以的模型,换到本库外测时,稀有类的召回会明显下滑。这个下滑不是评测过失,而是跨库差异的真实读数——设备带宽不同、人群不同、噪声谱不同,三者叠加。对本库的使用者来说,这意味着一个具体的用法建议:把它当"说不"的工具比当"说好"的工具更有价值。如果你的模型在本库外测上掉得厉害,那说明它在单库内的成绩里有相当一部分来自记住而不是学会;如果掉得不多,才值得进一步讨论。

反过来也要防止把外测成绩当作绝对标准。本库只有 75 段、32 名患者,一次外测的成绩波动很大,不同随机种子的差异可能与模型版本的差异同量级。合理的做法是固定患者划分与随机种子,在同一份划分上比较不同模型,而不是跨论文比较绝对数值。固定种子这件事在单库实验里常被省略,在做外测时却几乎是必需的,因为样本太小,一次划分的偶然性足以颠倒排名。

7.5 它为何能持续:稀缺的不是数据量,是那个组合

它没有更新、没有扩版,却一直被引用,原因是它占着一个别人不愿再占的坑:十二导联加三十分钟。新增这样的库需要一家机构本来就有一批十二导联 Holter 并且愿意公开,这个前提比"再采一批十秒图"难得多。只要这个组合仍然稀缺(§4.1),它作为对照组的价值就不会被新库替代。

§8 生态位与历史

8.1 历史沿革

INCART 诞生在 PhysioNet 数据捐赠的高峰期。2000 年代中后期,PhysioNet 已经积累了 MIT-BIH 系列的多套库,形成了"注释码统一、格式统一"的联邦式生态。INCART 的加入方式很典型:一家临床机构把已有的记录按规范整理后捐献,平台负责长期托管。这种模式让它在没有基金续命的情况下存活了将近二十年。

8.2 与挑战赛的关系

它对更广的用户群体而言,第一次大规模曝光来自 2017 年的房颤分类挑战赛。那届挑战赛把训练集的来源分散到多个数据库,本库是其中之一,比赛给出的训练规模是八千余条单导联记录。这里有个常被混淆的点:挑战赛用的是从本库抽取单导联片段后的形态,而不是原始的十二导联三万分钟整体;参与者的模型看到的是片段,不是完整的半小时。

这个细节值得强调,因为它解释了为什么很多人"觉得"用过 INCART,其实只见过它被切片之后的样子。原始库的十二导联同步关系,在挑战赛的数据发布里被拆掉了。

8.3 生态位:对照尺而不是主力粮仓

角色 主力粮仓 对照尺
典型用法 大规模训练、预训练 外部测试、跨域评测、消融对照
需要的前提 数据量大、标签细 人群不同、设备不同、导联配置不同
代表库 MIT-BIH、短片段十二导联大库 本库、其他小体量跨中心库
失败模式 过拟合、标签噪声累积 样本太少导致结论不稳

INCART 坐在右边这一列。把对照尺当粮仓用,会立刻遇到规模瓶颈;把粮仓当对照尺用,会立刻遇到"自己测自己"的问题。两者不能互换。

8.4 谁在用它,用来做什么

从公开文献的摘要看,使用者集中在三类:做跨库泛化的信号处理组(把它当外部集)、做轻量部署的工程组(把它当真实难度基准)、做多导联方法的研究组(把它当唯一有十二导联长时程的舞台)。第三类最少,但正是它最不可替代的位置。

§9 使用指引

9.1 三种角色的路径

角色 第一天 第一周 注意事项
算法研究者 读官方页面与头文件,跑通 §2.3 的读取 建立按患者划分的基线,做单导联与多导联对照 先定标签口径再动手(§5.4)
设备工程师 抽 II 导联与 V1 导联各跑一遍 量化导联位置造成的性能差,做噪声注入 报告要分导联,不要只报平均
教学与临床工程 截取 §4.3 的案例时段 做十二导联对照的教学图 标注位置未校正,图上要说明

9.2 一条最短的可用流程

#-- 1. 取记录清单
curl -sL https://physionet.org/files/incartdb/1.0.0/RECORDS -o RECORDS

#-- 2. 读头文件里的患者编号,建立分组表
for r in $(cat RECORDS); do
  echo -n "$r "
  curl -sL "https://physionet.org/files/incartdb/1.0.0/${r}.hea" \
    | grep '^# patient' | awk '{print $3}'
done > record2patient.txt

#-- 3. 按患者编号分组划分(示例:患者 1-24 训练,25-32 测试)
awk '$2<=24{print $1}' record2patient.txt > train.txt
awk '$2>24{print $1}'  record2patient.txt > test.txt
wc -l train.txt test.txt
import wfdb
import numpy as np

def load_lead(name, lead):
    rec = wfdb.rdrecord(name, pn_dir='incartdb')
    return rec.p_signal[:, rec.sig_name.index(lead)], rec.fs

x, fs = load_lead('I50', 'V1')
print(x.shape, fs)      #-- 462600 个采样点,257 Hz

上面 bash 段里的第二步会发起 75 次请求。想要更省事,可以直接用官方的 files-patients-diagnoses.txt,它已经把患者与记录对好了。

9.3 引用方式

PhysioNet 的惯例是引用数据集本身加平台:

引用对象 内容
数据集 St Petersburg INCART 12-lead Arrhythmia Database, version 1.0.0. PhysioNet. 2008.
平台 PhysioNet 平台综述论文(2026 年发表于 Nature Health),按官方页面的 Cite 按钮生成
联系人 官方页面给出的机构联系人,用于报告错误

写论文时建议同时注明:使用的版本号(1.0.0)、是否使用 2015 年修订后的头文件、以及划分方式是否按患者。

§10 AI 使用声明

项目 声明
文本生成 本文由 AI 辅助撰写,编辑把关结构与事实
数字来源 规模、结构、边界三类数字来自 PhysioNet 官方页面与文件目录
文件核验 RECORDS、I01.hea、I75.hea、两个附属清单经直接访问确认
记录数不一致 RECORDS 末行无换行导致行计数少一,已在 §5.2 说明
论文信息 仅参考 Europe PMC 摘要,未读全文
未核验内容 各心搏类型的具体条数、节律标注的覆盖率
图像 无配图;封面为生成式提示词,不含真实心电图
免责 本文不构成临床建议;数据使用须遵守 ODC-BY 1.0 署名要求

常见误读(避坑清单)

说法 实际 证据
「它有七十四条记录」 七十五段,wc -l 少算是因为末行无换行 RECORDS 末行是 I75 且无换行符
「它是十二导联二十四小时」 每段三十分钟,切自更长的 Holter 头文件 462600 采样点 ÷ 257 Hz = 1800 秒
「它有房颤的逐段标签」 心搏级注释为主,节律标签不完整 ANNOTATORS 只写 reference beat annotations
「它可以直接训练心搏分类器」 能训,但 32 名患者一两轮就记全 官方记录名清单仅 75 条
「十二导联齐全就能做心梗定位」 无逐导联 ST 定量标注 诊断是整段摘要,不是导联级标签
「它的增益都一样,可以直喂整数」 逐记录不同,官方说 250–1100 I01 与 I75 头文件增益不同
「按记录随机切分就可以」 同一患者的多段来自同一次 Holter 头文件 # patient 说明
「它是 250 Hz」 257 Hz 头文件第 1 行第 3 字段
「它是健康人基线」 全部为冠心病检查人群 官方人群描述
「它和 MIT-BIH 是同一批人」 不同国家、不同机构、不同人群 官方贡献机构为圣彼得堡研究所

FAQ

Q1:INCART 到底有多少条记录?为什么有人说是七十四?
七十五段,编号 I01 到 I75。说七十四的人大多是用 wc -l RECORDS 数的,而该文件最后一行没有换行符,行计数会漏掉最后一条。用空白切分或逐行读到文件尾就不会出错。

Q2:它能直接拿来做房颤检测吗?
可以,但要先确认标签口径。.atr 给的是心搏类型,房颤得靠心搏序列的不规则性或诊断描述间接判断。有研究组用官方记录的诊断文本拼出节律标签,那是二次加工,论文里要写清。

Q3:为什么它常被当作 MIT-BIH 心律失常库的跨库测试集?
两者用同一套注释码与同一套读写工具,映射到 AAMI 五分类很直接。同时它来自另一个国家、另一套设备、另一批患者,正好检验模型跨域后的表现。

Q4:十二导联是不是意味着可以做心梗定位?
导联配置具备条件,标注不具备。数据库没有逐导联的 ST 段定量标注,部分记录描述里写了 ST 改变,但那是整段定性摘要。

Q5:训练集和测试集该怎么分?
按患者编号分,不按记录编号分。头文件里的 # patient 说明多段来自同一次 Holter,随机按记录切分会把同一患者带进两侧,结果虚高。

Q6:为什么采样率是 257 Hz 这种奇怪的值?
这是原始 Holter 设备的采样率,没有重采样到 250 Hz。做跨库拼接时要么全部重采样到统一值,要么在时间轴上显式按 257 Hz 换算,否则会有百分之三左右的时间偏差。

Q7:标注准确吗?
类型准确度较高,因为是自动初标加人工修正;位置准确度一般,官方明确说位置由算法在十二导联上综合确定且未逐条校正。所以形态类任务可以直接用,时刻类任务要小心。

Q8:它和 CinC 2017 挑战赛的数据是什么关系?
本库是那届挑战赛的训练来源之一,但挑战赛用的是从中抽取的单导联片段,不是原始十二导联整体。想研究跨导联差异,必须用原始库。

Q9:体量有多大?能一次下完吗?
全量在几百兆级,可以一次下完。官方没有整库压缩包,是逐文件目录,用 wget 递归或 wfdb 流式读取都可以。

Q10:能不能用它做健康人正常心搏的参考?
不太合适。全部患者为冠心病检查人群,平均 58 岁,且筛选时偏向心电图有异常的人,正常心搏的形态多样性不足。

Q11:它的许可允许商业使用吗?
ODC-BY 1.0 允许,包括商业用途,条件是署名。引用时要写清数据集名称、版本与来源,具体条款以官方许可全文为准。

Q12:为什么只有 75 段?官方没有扩版计划吗?
官方没有给出扩版说明。从数据来源看,十二导联 Holter 在临床上本就不常见,能贡献这类记录的机构有限,这更像是现实约束而不是计划中断。

术语表

术语 解释
Holter 便携式长时程心电监护,患者随身携带记录仪生活
十二导联 I、II、III、aVR、aVL、aVF 加 V1–V6,临床标准配置
逐搏标注 对每一次心搏标出位置与类型
WFDB PhysioNet 使用的波形数据库格式,含头文件、信号、注释
.hea 纯文本头文件,声明采样率、增益、患者信息
.dat 二进制信号文件
.atr 二进制注释文件
增益 每毫伏对应的 ADC 整数值,换算物理量时使用
ADC 零值 零电平对应的整数值,换算时先减
校验和 采样点累加和,用于检测文件是否完整
AAMI 五分类 心电算法评价的通行分组:N、S、V、F、Q
心房颤动 心房电活动紊乱,心室率绝对不规则
阵发性 事件间歇出现而非持续存在
室性早搏 心室提前除极的心搏,形态宽大
束支阻滞 束支传导受阻,QRS 增宽并可分型
ST 段改变 复极异常,可提示缺血
患者级划分 同一患者的所有记录只进训练或只进测试
跨库测试 在一个库训练、另一个库测试,衡量泛化
节律注释 标注一段时间内的节律类型,与心搏级不同
单导联偏倚 模型只在特定导联有效,换导联即失效
ODC-BY 开放数据共享署名许可
PhysioNet 由 MIT 等机构维护的生物医学信号数据平台

附录 A:核心数字核对表

项 值 来源 来源层级
记录数 75 官方页面;RECORDS 逐行 官方页面
患者数 32 官方页面 官方页面
性别构成 17 男、15 女 官方页面 官方页面
年龄范围 18–80 岁,平均 58 官方页面 官方页面
每段时长 30 分钟 官方页面;头文件 462600/257 官方页面
导联数 12 官方页面;头文件 官方页面
采样率 257 Hz 官方页面;头文件 官方页面
每段采样点 462600 I01.hea、I75.hea 官方文件
增益范围 250–1100 官方页面 官方页面
注释总量 超过 175,000 条 官方页面 官方页面
记录名格式 I01–I75 RECORDS 官方文件
注释角色 reference beat annotations ANNOTATORS 官方文件
许可 ODC-BY 1.0 官方页面 官方页面
首版日期 2008-05-01 官方页面 官方页面
修订日期 2015-09-18 官方页面版本历史 官方页面
单段信号体积 约 11 MB I01.dat 响应头 官方文件

附录 B:数字的来源分层

第一层:官方页面与官方文件。 记录数、患者数、时长、导联、采样率、增益范围、注释总量、许可、日期。这些数字来自项目主页的摘要与数据描述段,以及 RECORDS、头文件、两个附属清单。

第二层:论文摘要。 关于它作为外部测试集的用法、以及与轻量化部署评测的关系,来自 Europe PMC 返回的摘要。摘要只能支撑"有人这样用",不能支撑"这样用效果如何"。

第三层:未核实。 各心搏类型的具体条数、节律标注在多少条记录里出现、噪声段的分布。这些需要逐条下载统计,超出了本篇的范围,正文中凡是涉及的地方都只做定性表述。

附录 C:完整参考文献

编号 文献 链接 用途
1 St Petersburg INCART 12-lead Arrhythmia Database v1.0.0 https://physionet.org/content/incartdb/1.0.0/ 全部规模、结构、边界数据的来源
2 该库的 PhysioNet 文件目录 https://physionet.org/files/incartdb/1.0.0/ RECORDS、头文件、附属清单
3 PhysioNet 平台综述(2026,Nature Health) https://doi.org/10.1038/s44360-026-00096-z 托管模式与引用规范
4 PhysioBank 注释定义 https://physionet.org/physiobank/annotations.shtml 心搏类型码的标准含义(经归档页核对)
5 Europe PMC 检索:跨库心电分类与轻量部署 https://www.ebi.ac.uk/[europepmc](https://www.qianfanghub.com/ai-ready-dataset/europepmc/1353)/ 外部用法与验证角色
6 MIT-BIH 心律失常库(对照) https://physionet.org/content/mitdb/ §2.5 与 §6.1 的对比
7 MIT-BIH 房颤库(对照) https://physionet.org/content/afdb/ §2.5 与 §6.1 的对比
8 PhysioNet/CinC 2017 挑战赛(来源之一) https://physionet.org/content/challenge-2017/ §8.2 与 FAQ Q8

附录 D:任务代码

任务一:按患者划分的跨库心搏分类骨架

import wfdb
import numpy as np

AAMI = {'N': 'N', 'L': 'N', 'R': 'N', 'B': 'N', 'A': 'S', 'a': 'S',
        'J': 'S', 'S': 'S', 'V': 'V', 'r': 'V', 'F': 'F', 'f': 'F',
        'e': 'Q', 'j': 'Q', 'n': 'Q', 'E': 'Q', 'Q': 'Q'}

def patient_of(name):
    #-- 读头文件第 4 行之后的注释,找 # patient
    h = wfdb.rdheader(name, pn_dir='incartdb')
    return h.comments[-2] if len(h.comments) >= 2 else ''

def beats(name, half=36):
    rec = wfdb.rdrecord(name, pn_dir='incartdb', physical=True)
    ann = wfdb.rdann(name, 'atr', pn_dir='incartdb')
    xs, ys = [], []
    for s, sym in zip(ann.sample, ann.symbol):
        if sym not in AAMI:
            continue
        if s - half < 0 or s + half >= rec.sig_len:
            continue
        xs.append(rec.p_signal[s - half:s + half, :].T)   #-- 12 x 72
        ys.append(AAMI[sym])
    return np.array(xs, dtype='float32'), np.array(ys)

for n in wfdb.get_record_list('incartdb')[:3]:
    x, y = beats(n)
    print(n, patient_of(n), x.shape, np.unique(y))

任务二:同一时段十二导联的可见度对比

import wfdb
import numpy as np

rec = wfdb.rdrecord('I50', pn_dir='incartdb')
fs = rec.fs
start, end = 600, 900          #-- 看五分钟
lo, hi = int(start * fs), int(end * fs)

rows = []
for i, lead in enumerate(rec.sig_name):
    x = rec.p_signal[lo:hi, i]
    rows.append((lead, float(np.ptp(x)), float(np.std(np.diff(x)))))

for lead, p2p, dv in sorted(rows, key=lambda r: -r[2]):
    print(f'{lead:>3}  峰峰值 {p2p:6.2f} mV  差分标准差 {dv:.4f}')

第二段代码给的是"导联间差异"的一个最粗糙的度量。它的用途不是下结论,而是暴露出差异确实存在——在某些记录上,V1 的差分标准差可以是 aVL 的数倍。拿到这个表再去设计更有针对性的实验。

附录 E:如果只记五件事

序号 记住什么 为什么
1 75 段,32 名患者,每段 30 分钟,12 导联,257 Hz 这四个数字定义了一切用法与限制
2 它是"对照尺"而不是"粮仓" 拿它做主力训练会过拟合,拿它做外部测试最有价值
3 十六万余条心搏标注,节律标注不完整 心搏分类可直接用,房颤要二次加工
4 按患者划分,不按记录划分 同一 Holter 的泄漏会让结果虚高
5 它唯一不可替代的地方是十二个导联同步 跨导联差异研究几乎找不到第二个这样的库

编辑说明

本文的核验时间为 2026 年 10 月 27 日。核对方式为直接访问 PhysioNet 项目页与文件目录,逐一确认 RECORDS、I01.hea、I75.hea、ANNOTATORS、两个附属清单的可访问性与内容;论文侧只检索了 Europe PMC 的摘要,未读全文。记录数 75 与 wc -l 得到的 74 之间的一字之差,原因是 RECORDS 末行无换行符,这一点在 §5.2 与 FAQ 第 1 问里各说明一次。未覆盖的内容包括:各心搏类型的具体条数、节律标注的覆盖率、噪声段的分布、以及逐段诊断与记录描述的完整对应关系。这些需要下载全量后统计,本文按要求只写规模、结构、边界三类数字。


相关数据集导航

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

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

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

返回 AI-Ready 数据集