麻醉科医师逐搏验过的术中心律失常标注 — VitalDB Arrhythmia

482 例手术 / 20 万秒心电图 / 逐搏与逐段双层标注

来源 https://physionet.org/content/vitaldb-arrhythmia/发布时间: 2026-10-28最后更新: 2026-10-28 阅读 10
麻醉科医师逐搏验过的术中心律失常标注 — VitalDB Arrhythmia

信息速览

数据集名称麻醉科医师逐搏验过的术中心律失常标注 — VitalDB Arrhythmia
数据类型时序信号,波形,人工标注,元数据
规模482 例手术(去标识,主键为 case_id)
接入方式https://physionet.org/content/vitaldb-arrhythmia/
AI 就绪度

VitalDB Arrhythmia 不是一个新采集的数据库,而是 VitalDB 主库上长出来的一层标注。主库把六千多例非心脏手术的术中监护信号原样存了下来,这一层则在其中四百多例里挑出心电图,由麻醉科医师一个搏一个搏地判读,标出哪个搏是正常的、哪个是室早、哪个是房颤中的一次传导。它回答的是「手术台上那几分钟的心跳,到底属于什么」这个问题。

它的价值集中在一件别处很难买到的事上:术中场景的、逐搏的、经过多名麻醉科医师交叉复核的节律判读。公开的心电数据库大多来自动态心电图或重症监护,术中记录稀少;而术中恰恰是心律失常高发、干扰最多、算法最容易失效的环境。把这类记录整理成可训练、可评测的形态,是这个数据集存在的理由。

它同时有三条硬边界,一开始就要说清楚:包内没有波形,只有标注;标注只覆盖每例约二十分钟的候选段,不是整台手术;语料只有 II 导联一条通道。任何把它当全程连续记录、或多导联语料、或心律失常发生率调查的用法,都会在第一步就错。一屏速览见下表。

维度 内容
中文名 VitalDB 心律失常数据库(术中版本)
官方全名 VitalDB Arrhythmia Database
建设方 首尔国立大学医院麻醉与疼痛医学系
发布平台 PhysioNet(开放获取)
版本与日期 1.0.0,2026 年 2 月 26 日
DOI 10.13026/axd6-wm13
病例数 482 例非心脏手术
标注总时长 734,528 秒(约二百小时)
逐搏标注数 逾六十六万个心搏
搏级类别 4 类(正常、室上性、室性、无法归类)
节律类别 10 类,另加噪声与无法归类标记
导联与采样 II 导联单通道,标注按 500 Hz 时间轴
复核方式 五名麻醉科医师,每段至少两人独立判读
包内内容 标注 CSV、元数据、许可与校验文件
包内是否含波形 不含,须按 case_id 回主库取
许可 CC BY 4.0
最典型的误用 把候选段标注当全程节律发生率

§1 它要解决的具体麻烦

1.1 术中这段心电图,公开语料里几乎没有

心电数据库并不稀缺。动态心电图有 MIT-BIH 系列,重症监护有 MIMIC 波形库,可穿戴有各种单导联长程记录,竞赛型语料更是年年更新。但把「手术进行中」这四个字单独拎出来,公开语料立刻稀疏下来。

原因不难理解。术中监护的原始信号归医院所有,采集涉及麻醉机、监护仪、输注泵多台设备的同步,脱标识与伦理审批都比常规体检数据复杂。愿意把整台手术的多参数波形开放出来的团队,全世界屈指可数,VitalDB 是其中最知名的一个。而在这批已经开放的波形里,标注层几乎是空白——波形有了,但没人告诉你哪一段是房颤、哪一段只是肌电干扰。

术中环境又恰恰是心律失常的高发场景。手术刺激、麻醉药物、通气变化、容量波动、电解质偏移,任何一种都能在几分钟内把窦性心律改写成别的形态。这种「短时间内节律反复切换」的形态,与动态心电图里那种以小时计的稳定节律完全不同。用门诊语料训练的检测器搬到手术台上,会同时犯两类错:把麻醉诱导期的快速心率当成室上速,把电刀干扰当成室颤。

这个数据集补的正是这段空白。它没有重新采集,而是从现成的 VitalDB 里挑出心电部分,补上人工判读。这是一个成本极低、收益很高的做法:波形已经在那儿了,缺的是有人愿意花时间把它读一遍。

1.2 三条常见的错误期待

第一条期待:把它当成「术中发生率的流行病学样本」。四百多例手术里有多少例出现房颤,看起来像是一个可以引用的数字。但抽样的方式决定了它不能这么用。进入标注集的前提是「被算法判定为存在异常」,正常手术的比例被系统性压低了。拿它的病例构成去估计术中房颤的患病率,会得到远高于真实值的结论。

第二条期待:把它当成「一个独立的数据集」。它不是。它更像一本贴在墙上的批注册,真正的书在隔壁。所有波形都要回主库取,标注文件里的时间戳只有配上同一例的波形才有意义。把它单独下载下来,等于拿到了一堆没有正文的页码。

第三条期待:把它当成「全导联的形态学语料」。术中监护通常只接 II 导联或 V5 导联,这个数据集用的是 II 导联。单导联意味着很多形态学特征——比如束支传导阻滞的 V1 形态、室早的起源定位——根本无法从这份语料里学。它是一个节律识别的语料,不是一个形态学诊断的语料。

1.3 它能给到的与给不到的

下表左列写的是具体的需求,不是功能名词。凡标「不够」的行,都是它明确做不到的事。

你的需求 它给的 够不够
训练一个术中室早检测器 逐搏四分类标签,含室性搏 够,但需回主库配波形
识别术中房颤片段 十类节律标签中的房颤类 够用于训练,评测需注意抽样偏倚
判读麻醉诱导期的心率骤升 候选段内的节律标签与搏标签 部分够,诱导期是否入选取决于筛选
做多导联心电形态分析 仅 II 导联 不够,需另找多导联语料
统计术中各类心律失常发生率 候选段抽样的病例 不够,抽样方式不支持分母
评估信号质量算法 低质量区间起止标记与噪声段 够用于二分类,但只区分粗粒度
研究房室传导阻滞 十类中的房室阻滞类 够,但该类样本很少
做跨中心外部验证 单中心数据 不够,需另找队列
训练新生儿或儿科模型 成人手术患者 不够,人群完全不同
对齐血压、血氧做多模态 主库有同步信号,标注在同一时间轴 够,是这份语料少见的加分项
复现论文里的逐搏分类基准 官方给出标注与用法说明 够,需自行划分训练与测试
做心脏手术人群的分析 只含非心脏手术 不够,完全不覆盖

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

同一份标注,不同处境的人该拿它做什么完全不同。下表左列是处境,右列是下一步动作,中间才是标注本身能提供的部分。

你的处境 它能帮你什么 下一步该做什么
你在做术中监护设备的算法预研 提供带人工判读的术中单导联语料 先按 case_id 批量取波形,再对齐标注时间轴
你在写围术期心律失常的论文 提供可复算的标注与元数据 明确说明抽样方式,不要用它算发生率
你在做心电大模型的预训练 提供与门诊语料风格不同的术中片段 只把它当微调或评测集,不要当预训练主体
你是麻醉科医生,想核对某个判读 提供他人的独立判读作为参照 读官方对信号质量的定义,再比对分歧
你在审核一份算法的临床声明 提供术中场景的证据 要求补充多中心验证,单靠此集不足
你在做信号质量与伪差抑制 提供噪声段与低质量区间的标记 用噪声段做负例,但注意它与正常搏不是一类
你在做多模态融合研究 同一时间轴上有血压、血氧等信号 回主库取同步通道,注意采样率与起点
你只想找一份心电语料做入门 提供结构清晰的 CSV 先读 §5 的最小流程,避免空跑

1.5 一句话判断

它是 VitalDB 主库上的一层人工批注:波形不在这儿,读法在这儿;能教你认识术中节律,但不能替你回答发生率。

1.6 不适合谁:四条边界

第一条边界:需要全程连续记录的研究。标注只覆盖每例约二十分钟的候选段,其余时间既没有搏标签也没有节律标签。用它做「整台手术的心律负荷」这类指标,分母根本不存在。

第二条边界:需要多导联的形态学诊断。只有一条 II 导联,束支阻滞的分支定位、室早的起源定位、缺血性 ST 段改变的空间分布,这些都做不到。单导联能回答节律问题,不能回答空间问题。

第三条边界:需要流行病学分母的人群研究。进入标注集的门槛是「算法筛出可能存在异常」,这是病例富集抽样的典型形态。任何以它为分母的发生率、患病率、风险比,都会被抽样的选择性污染。

第四条边界:需要跨机构泛化的验证。全部病例来自一家医院、一个时期、一套设备。术中监护的设备差异、贴片位置、滤波器设置都会改变波形形态,单中心语料上的高分不能直接外推。

§2 数据构成与规格

2.1 两层结构:波形在主库,标注在这一层

理解这份数据的第一件事,是把「数据」与「标注」两个词分开。VitalDB 主库存的是原始多参数波形,每一例对应一个二进制病例文件,里面按轨道存着心电、有创血压、血氧容积波、二氧化碳等信号,波形采样率因通道而异,心电常见 500 Hz。这一层数据体量巨大,全库接近百 GB 量级。

VitalDB Arrhythmia 存的是另一类东西:每例一份 CSV,逐行记下第几秒出现了一个心搏、这个搏属于哪一类、它所在的整段属于哪种节律、这一段信号质量如何。整包压缩后只有几 MB,正是因为它不含任何波形。

层 内容 存放位置 体量 谁维护
主库波形层 多参数原始波形与数值轨道 VitalDB 主库 近百 GB VitalDB 团队
主库临床层 围术期临床信息与实验室结果 主库附带 CSV 数十 MB VitalDB 团队
标注层 逐搏分类与节律判读 本包 Annotation_Files 数 MB 本项目团队
元数据层 每例的分析时长、搏数、节律类别 本包 metadata.csv 数百 KB 本项目团队

这个两层结构带来一个直接推论:本包的下载成本可以忽略,真正的成本在波形。四百多例的术中信号即便只取单通道,也需要相当规模的传输与存储;如果还要同步取血压与血氧做多模态,体量会进一步上升。做规划时要按主库的体量算,而不是按标注包的体量算。

2.2 字段与记录的完整字典

元数据表一例一行,标注文件一例一份、一行一个心搏。两边的字段加起来,构成这份语料的全部结构。下表的类型与含义依据官方说明与随包示例整理。

字段 所在文件 类型 含义与用法 需要留意的地方
case_id metadata.csv、标注文件名 整数 主库中的病例编号,对齐波形的唯一键 与主库编号一一对应,不可重编
analyzed_duration_sec metadata.csv 数值 该例被标注覆盖的时长(秒) 不是整台手术时长
total_beats metadata.csv 整数 该例被标注的搏总数 与文件行数应基本一致
rhythm_classes metadata.csv 文本列表 该例出现过的节律类别 多类别以分隔符并列
time_second 标注文件 数值 R 波时刻,以记录起点为零点 与主库时间轴同源,可直接对上
beat_type 标注文件 文本 搏级四分类 取值见 2.3 的分类表
rhythm_label 标注文件 文本 该搏所属片段的节律类别 相邻搏可共享同一节律
bad_signal_quality 标注文件 布尔 该搏是否落在低质量片段 置真时波形仍可见 QRS
bad_signal_quality_label 标注文件 文本 低质量片段的起止标记 非边界行为空
文件命名 标注文件 文本 固定为标注文件名前缀加 case_id 批量遍历时按文件名取号最稳

字段表里最容易出错的三处:analyzed_duration_sec 容易被误读成手术时长;bad_signal_quality 为真的搏并非不可用,只是 P 波与 T 波被掩盖;bad_signal_quality_label 只在片段边界上有值,做区间重建时必须靠它配对起止,不能靠布尔列的跳变简单推断。

2.3 一套双层标签:搏级四类,节律十类

标签体系是两个粒度叠在一起。细的一层是搏,回答「这一次心室除极来自哪里」;粗的一层是节律,回答「这一段整体是什么心律」。两层不是冗余关系,因为同一个节律下可以有不同来源的搏:房颤段落里,绝大多数搏是室上性下传,偶尔会插进一个室性早搏。

粒度 类别数 类别含义 典型用途
搏级 4 正常搏、室上性异位搏、室性异位搏、无法归类 训练搏分类器、计算异位负荷
节律级 10 窦性心律、房颤、室上性快速性心律失常、室性快速性心律失常、成串室性异位、成串房性异位、窦房结功能不全、房室阻滞、游走性心房起搏或多源性房性心律、噪声 训练节律分段、做片段级评测
附加标记 1 无法归类节律 极少数疑难段落的兜底

十类节律里,最常见的是窦性心律,这也符合直觉:即使是被筛出来的异常病例,大部分被标注的时段仍是窦性。房颤类覆盖的病例数排在前面,这与术中房颤的实际频度一致——它是最容易被算法抓到、也最容易被医师确认的异常。房室阻滞类的病例数最少,这是术中相对少见、且往往与麻醉深度或迷走张力相关的一类。

噪声被单列为一个节律类别,这一点值得强调。被标为噪声的片段,伪差严重到连 QRS 都无法辨认,因此这些片段内部不产生任何搏级标注。这意味着标注文件的行数与「该例被标注的总时长」并不严格成比例——噪声越长,缺失的搏级行越多。做训练集统计时,如果只数行数,会低估实际覆盖的时间跨度。

2.4 一条标注记录的完整解剖

拿一例真实标注文件的头部做样本,可以看到两个粒度是怎么并排放在同一行里的。下面这份节选保留列名与字段形态,便于核对解析器。

time_second,beat_type,rhythm_label,bad_signal_quality,False,bad_signal_quality_label
0.412,Normal,Sinus Rhythm,False,
0.988,Normal,Sinus Rhythm,False,
1.566,Normal,Sinus Rhythm,False,
2.140,Supraventricular,Atrial Fibrillation,False,
2.718,Normal,Atrial Fibrillation,False,
3.296,Ventricular,Atrial Fibrillation,False,
3.870,Normal,Atrial Fibrillation,False,
4.452,Unclassifiable,Noise,False,
4.960,Normal,Sinus Rhythm,True,Start1
5.560,Normal,Sinus Rhythm,True,
6.130,Normal,Sinus Rhythm,True,End1

#-- 节选:列名以官方随包文件为准,行内容为结构示意,时间戳与类别组合用于说明两个粒度的并置方式

这份节选里藏着三件事。第一,band_label 与 beat_type 会同时出现在一行,一个搏的标签是「室性」,它所在片段的标签可能是「房颤」,两者并不矛盾。第二,bad_signal_quality 为真的连续若干行,用 Start1 与 End1 标出边界,中间的布尔值重复出现。第三,被标为噪声的那一行,搏类型填的是无法归类,说明噪声段的处理是「整行兜底」而不是「整段删除」。

用代码把一例读进来,最容易犯的错是把时间当作毫秒或是把布尔列当字符串比较。下面这段是最小可运行的正确读法。

import pandas as pd

#-- 读入一例标注,时间列按浮点解析,布尔列按真值映射
ann = pd.read_csv("Annotation_Files/Annotation_file_337.csv")
ann["bad"] = ann["bad_signal_quality"].astype(str).str.strip().str.lower().eq("true")

#-- 搏级:统计四类搏的数量
beat_counts = ann["beat_type"].value_counts()
print(beat_counts)

#-- 节律级:把同一节律的相邻行压成区间
ann = ann.sort_values("time_second").reset_index(drop=True)
change = ann["rhythm_label"].ne(ann["rhythm_label"].shift())
starts = ann.loc[change, ["time_second", "rhythm_label"]].reset_index(drop=True)
durations = ann["time_second"].diff().shift(-1).fillna(0)
print(starts.head(10))

这段代码的第二个用途更有价值:把逐搏标签压成节律区间,是做节律分段任务的起点。压缩规则很简单,相邻搏的节律标签相同就合并,不同就断开。压完之后,一例二十分钟的记录通常会变成几十个区间,而不是几千个搏。

2.5 与主库字段的对照

把这份语料与主库放在一起看,才能判断它在整个 VitalDB 体系里的位置。两者共享同一个病例编号,共享同一条时间轴,但记录的抽象层级完全不同。

对照项 VitalDB 主库 VitalDB Arrhythmia
记录的物理量 原始电压或压力值 搏与节律的判读结论
数据形态 二进制病例文件 CSV 文本
通道数 每例十余至数十轨 单通道(II 导联)
时间粒度 采样点级 搏级
覆盖时长 整台手术 每例约二十分钟候选段
体积量级 近百 GB 数 MB
是否需要人工判读 否 是,全部
主要用途 信号建模、多模态 节律识别、搏分类

这张表最该读出的一句话是:主库给的是「记录」,这一层给的是「解读」。记录可以重新解读,解读不能反过来生出记录。所以任何以这一层为主的分析,最终都要下沉到主库去取波形;而任何以主库为主的分析,都可以把这一层当作现成的、免费的标注补充。

§3 身份层:它到底是什么

3.1 一个派生层,不是一次独立采集

严格说,它不是「数据集」,而是「数据集的一个标注视图」。官方的做法很清楚:从 VitalDB 的公开病例里筛选,取出心电图,补上人工判读,把判读结果单独发布。波形留在原处,标注另立门户,两者用病例编号连接。

这个身份带来一个不太直观的后果:它的版本独立性是有限的。标注可以单独升版,但它依赖的波形在主库那边是另一个版本号。如果主库将来修订了某例波形的时间轴或采样率,标注层必须跟着调整,否则时间戳就对不上。使用者在引用时应当同时记下两个版本号,而不是只记本包的。

身份维度 具体表述 对使用者的含义
法律地位 PhysioNet 上的开放数据库,独立 DOI 可单独引用,但要并列引用主库
结构地位 主库的标注派生层 波形必须回主库取
采集地位 未新采集,全部复用主库 采集条件与主库完全同一套
判读地位 五名麻醉科医师人工复核 判读质量高,但判读标准是麻醉视角
时间地位 主库批次(2016 至 2017 年手术) 不代表当下设备与流程
语言地位 英文标签与英文元数据 中文使用需自建映射表

3.2 麻醉科的判读视角与心内科不完全相同

这一点容易被忽略,但它决定了标签的语义。判读人是麻醉科医师,不是心内科电生理医师。他们看心电的第一需求是「这台手术能不能继续、要不要处理」,而不是「这个节律的精确电生理机制是什么」。

具体表现有两处。第一,节律分类的粒度偏粗:室上性快速性心律失常被合成一类,不细分房速、房扑、房室结折返;成串室性异位与室性快速性心律失常分开,但不细究形态。第二,对临床意义明确的类型更敏感:房颤、室性早搏成串、房室阻滞、窦房结功能不全,这几类都是直接影响术中决策的。

这种视角不是缺陷。对绝大多数术中监护算法的目标来说,「这一段要不要报警」比「这一段属于哪一种折返机制」更重要。但如果研究目的是电生理机制分类,这套标签就不够细,需要另找心内科标注语料。

3.3 与常见心电语料的身份差异

把这份语料放进公开心电数据库的谱系里,它的身份独特性就更清楚了。

语料 场景 导联 标注粒度 与本文的关系
MIT-BIH 心律失常库 动态心电图 双导联 搏级 搏分类的传统基准,场景不同
各类重症监护波形库 ICU 多导联 部分搏级 场景邻近,但非术中
竞赛型十二导联语料 门诊或体检 十二导联 记录级或搏级 导联丰富,场景不同
可穿戴单导联语料 居家 单导联 记录级 干扰类型不同
VitalDB 主库 术中 多轨 无标注 本文的波形来源
本文语料 术中 单导联 搏级加节律级 术中场景里标注最细的一支

这张表要说明的是:它的独特性不在规模,也不在标注精度,而在「术中」与「逐搏」这两个条件的交集。单看任何一条,都有更强的语料;两条叠在一起,可选项就很少了。

3.4 谁在维护,维护到什么程度

发布方是首尔国立大学医院麻醉与疼痛医学系的团队,也就是 VitalDB 的原班人马。这个事实很重要:标注层与波形层出自同一团队,意味着两边的时间轴、病例编号、质量约定是内部一致的,不需要外部再做一次对齐谈判。

维护模式是学术项目的典型形态:以论文与版本发布为主要里程碑,随包提供用法说明与代码仓库,遇到问题通过仓库的议题渠道反馈。它不是一个有服务等级承诺的产品,也不承诺按固定节奏增量。使用者在规划长期项目时,应当把「不再更新」当作可能的默认状态来设计,而不是假设它会持续扩充。

§4 质量层:它凭什么可信

4.1 三重把关:算法筛、医师判、两人交叉

这套标注的可信度,来自一道三段的流水线,每一段解决一个不同的问题。

第一段是算法筛选。要在六百多万秒的原始心电里逐搏人工判读,成本不可承受。团队先训练了一个搏分类器,用它扫过全部候选病例,把「连续异常搏」「R-R 间期高度不稳」「成串异位」这类形态挑出来,形成候选段。这一步的作用不是判读,而是把人工投入压缩到可行范围。

第二段是医师判读。候选段交给麻醉科医师,逐搏给四类标签,逐段给节律标签。这一步是真正的判读,算法的输出在这里只是线索,不是结论。

第三段是交叉复核。每一段至少由两名医师独立看过,分歧之处由五人小组协商达成共识。官方报告的整体一致性是相当高的,说明判读标准在团队内部被统一得不错。

环节 谁来做 解决什么 留下的偏差
候选筛选 深度学习搏分类器 把人工量压到可行 算法漏掉的异常不进标注集
逐搏判读 麻醉科医师 给出搏与节律标签 判读粒度受临床需求约束
交叉复核 五名医师中的至少两人 压低个体判读差异 共识过程不公开逐例细节
质量标记 判读人 标出低质量与噪声段 噪声段无搏级标签

第一行的偏差最容易被忽视。筛选器决定了什么能进入标注集,而筛选器的召回率不是百分之百。它漏掉的异常段,在这份语料里表现为「不存在」,而不是「被标为正常」。所以这份语料对「算法漏检率」的估计天然是乐观的:它是在算法自己挑出来的样本上评估算法。

4.2 信号质量标注为什么重要

术中信号的干扰源比门诊多得多。电刀的高频干扰、体位变化引起的基线漂移、电极脱落造成的饱和、肌电与呼吸的叠加,都会让一段本来正常的心电变得难以判读。团队把这部分单独处理,分成两级。

第一级是低信号质量。特征是 QRS 仍可辨认,但 P 波与 T 波被噪声掩盖,导致无法可靠判断房室关系与复极。这类片段仍给搏级标签,同时置 bad_signal_quality 为真,并用起止标记圈出区间。它的用途是让使用者在训练时可以选择性地降权或剔除这些搏,而不是把它们与干净搏混为一谈。

第二级是噪声。伪差严重到 QRS 都无法辨认,整段只给噪声标签,不产生任何搏级行。这类片段在训练中的价值不是当负例,而是当「不可判读」的独立类别——把它当正常搏喂给模型,会教模型把伪差学成心律。

质量等级 判据 是否有搏级标签 训练时怎么用
正常 QRS、P 波、T 波均可辨认 有 正常参与训练
低信号质量 QRS 可辨,P 波或 T 波被掩盖 有 降权或单独建模
噪声 QRS 无法辨认 无 单列一类,不作负例
无法归类的搏 QRS 可见但类型不明 有 单列一类,通常样本极少

第三、四两类的存在,说明这套标注没有把不确定硬塞进某一个确定类别。这在标注实践中是一个好习惯:宁可留一个兜底类,也不逼判读人在信息不足时做假选择。

4.3 一致性的口径怎么读

官方给出的整体一致性指标是一个 kappa 值,并附了标准差。这两件事要一起读,不能只读前一个。

kappa 高说明两名判读人在同一段上给出相同标签的概率显著高于随机,这是判读可信的基础证据。但标准差的存在提醒:分歧在多数段上很小,在少数段上可能很大。哪些段最容易分歧?从心电判读的常识看,是低信号质量段、成串异位的起始与终止边界、以及游走性心房起搏与多源性房性心律这类的区分。这些段恰好也是最难自动判读的段。

对使用者的含义是:不要把整体一致性当作「所有类别同等可靠」。整体数字是加权平均,少数类的样本少、分歧大,其可靠度显著低于常见类。做少数类的检测任务时,应当先看那一类的样本量与判读难度,再决定评测设计。

判读维度 一致性表现 使用含义
搏级四分类 高,正常与室性区分清楚 搏分类任务可直接用
常见节律(窦性、房颤) 高 主要节律分段可靠
少见节律(房室阻滞等) 未单独报告 样本少,评测需谨慎
片段边界位置 未单独报告 边界误差会影响分段指标
低质量区间 未单独报告 与质量相关的分析需人工复核

4.4 案例:病例 337 的一分钟

用一例真实编号把上面的抽象讲透。病例 337 出现在官方用法说明的代码示例里,是这套语料最常被拿来演示的一例。它的标注文件里有一段典型的术中过程:约十几秒的室性异位连发,其间穿插若干正常搏,随后被一段低信号质量区间隔开,再回到窦性心律。

如果只看搏级统计,这一段会被记成「若干室性搏」。但把节律标签压成区间之后,形状完全变了:那一段是一整个「成串室性异位」区间,而不是零散的室早。前者在临床上意味着需要关注血流动力学,后者通常只是观察。同一个数值,两种读法,差别在于是否使用了节律层。

import pandas as pd

case_id = 337
ann = pd.read_csv(f"Annotation_Files/Annotation_file_{case_id}.csv")
ann = ann.sort_values("time_second").reset_index(drop=True)

#-- 只看前 60 秒,看两个粒度如何错位
head = ann[ann["time_second"] <= 60]
print("搏数", len(head))
print("搏类型构成", head["beat_type"].value_counts().to_dict())
print("节律构成", head["rhythm_label"].value_counts().to_dict())

#-- 把节律压成区间,边界取该段第一搏的时刻
chg = head["rhythm_label"].ne(head["rhythm_label"].shift())
for _, r in head.loc[chg, ["time_second", "rhythm_label"]].iterrows():
    print(round(r["time_second"], 2), r["rhythm_label"])

这段代码的产出会让第一次接触这套标签的人有点意外:搏级构成里室性搏占的比例,与节律级里「成串室性异位」所占的时间比例,往往不成正比。原因是节律层记录的是「这一段整体被判定为什么」,一段十秒的成串异位里可能只有六个室性搏,但它作为节律事件占用了十秒。

这个案例的价值不在数字,而在提醒:§4.4 的案例说明的是两个粒度不可互换。做搏分类任务,用搏标签;做节律分段任务,用节律标签;做临床事件统计,才把两者结合起来。混用会让同一段信号产生两种互相矛盾的「发生率」。这个案例在 §5 与 §7 还会再出现两次,分别用来说明取数流程与质量评估的落点。

§5 取数层:三条路,各有各的取舍

5.1 路径一:直接下载标注包,几 MB 就能开始

最省事的起点是下载标注包本身。包体很小,包含元数据、四百多份标注文件、许可与校验文件。解压后不需要任何数据库,用任意表格工具或几行代码就能读。

这条路的产物是「答案」,不是「题目」。你能知道每例第几秒出现了什么搏、属于什么节律,但你手上没有那一段波形,也就无法验证判读、无法训练模型、无法画图。它适合的场景是:做标签体系的探索、统计标注结构、检查某一类的分布是否符合预期、以及在看波形之前先确认这一例是否值得下载。

优点 缺点 适合谁
体积极小,秒级下载 无波形,不能训练 先探路的人
格式简单,CSV 直读 时间戳离开波形无意义 做标签研究的人
含元数据,可先筛病例 不含采集通道信息 需要选例的人
官方校验文件齐全 无内置划分与基线 做数据核对的人

5.2 路径二:用 vitaldb 库按号取波形

真正的取数入口是主库的 Python 库。装上之后,一行代码就能按病例编号取回指定的轨道,并可以指定重采样间隔。标注文件的时间戳与波形的时间轴同源,因此只要两边都用记录起点为零点,就不需要额外对齐。

#-- 安装官方客户端
pip install vitaldb

#-- 取回与本标注包对应的四十多例样本的 II 导联波形(示例取前若干例)
python3.11 - <<'PY'
import vitaldb
for cid in [337, 338, 340]:
    vals = vitaldb.load_case(cid, ['SNUADC/ECG_II'], 1/500)
    print(cid, None if vals is None else vals.shape)
PY
import numpy as np
import pandas as pd
import vitaldb

FS = 500                      #-- 与标注时间轴一致的目标采样率
case_id = 337
ann = pd.read_csv(f"Annotation_Files/Annotation_file_{case_id}.csv")

#-- 取 II 导联,按 500 Hz 重采样
sig = vitaldb.load_case(case_id, ["SNUADC/ECG_II"], 1 / FS)
sig = np.asarray(sig, dtype=float).reshape(-1)
print("样本数", sig.size, "时长秒", round(sig.size / FS, 1))

#-- 取标注里的一个搏,反查它附近的波形
t = float(ann.iloc[10]["time_second"])
i = int(round(t * FS))
print("时刻", t, "附近电压", np.round(sig[max(i - 3, 0):i + 4], 3))

这段代码的关键是采样率。标注给的是秒,波形给的是采样点,两者之间的换算系数必须与取波形时指定的间隔严格一致。指定 500 Hz 却按 250 Hz 去算索引,会让每个搏的定位漂移一半,看起来像是标注整体错位,实际是换算错了。

5.3 路径三:批量取、按需缓存

做训练集时,逐例下载的瓶颈不在网络,而在重复取。同一例可能被反复读多次,每次都从远端拉一遍,既慢又不稳定。常规做法是本地建一个缓存目录,按病例编号存一份重采样后的数组,取之前先查本地。

from pathlib import Path

import numpy as np
import pandas as pd
import vitaldb

CACHE = Path("cache_ecg2")
CACHE.mkdir(exist_ok=True)
FS = 500


def load_ecg(case_id: int) -> np.ndarray:
    """取一例 II 导联,命中缓存则直接读盘。"""
    p = CACHE / f"{case_id}.npy"
    if p.exists():
        return np.load(p)
    vals = vitaldb.load_case(case_id, ["SNUADC/ECG_II"], 1 / FS)
    if vals is None:
        raise RuntimeError(f"该例主库无 II 导联:{case_id}")
    arr = np.asarray(vals, dtype=np.float32).reshape(-1)
    np.save(p, arr)
    return arr


meta = pd.read_csv("metadata.csv")
ok, miss = 0, []
for cid in meta["case_id"].head(20):
    try:
        load_ecg(int(cid))
        ok += 1
    except Exception:
        miss.append(int(cid))
print("成功", ok, "缺失", miss)

第三行的 raise 不是多余的保护。主库中并非每一例都完整记录了 II 导联,某些病例的该轨道可能缺失或被丢弃。批量处理时必须显式处理这种情况,否则某几个病例的失败会静默地让训练集少了几例,而你在很久之后才发现。

5.4 三条路的对照

维度 标注包 单例取波形 批量加缓存
下载量 数 MB 每例数 MB 每例数 MB,只下一次
是否需要主库 否 是 是
能否训练 否 是 是
实现复杂度 极低 低 中
适合阶段 探路 调试 建模
主要坑 无波形 采样率换算 轨道缺失与磁盘占用

5.5 时间轴对齐的三个细节

第一,零点。标注的 time_second 以该例记录起点为零点。主库取回的波形起点与标注起点一致,前提是取的是同一条轨道、同一段记录。若使用者对波形做过裁剪或高通滤波前移,零点会偏移,必须补偿。

第二,采样。指定 500 Hz 取波形时,库会在内部做重采样。重采样引入的相位延迟取决于滤波器设计,量级通常在若干毫秒。对搏级任务这是可接受的,但对 P 波与 QRS 起点的精确时刻建模,若干毫秒已经足以影响结果。

第三,缺测。主库的轨道并非处处有值,某些时段可能因为设备断开而缺失。取回的数组在这些位置可能是零或空值。用它们训练前应当先做一次有效性检查,把整段为零的区间剔除。

5.6 不要从网页抓

PhysioNet 的文件页提供逐文件下载,也支持批量打包。程序化取数的正确方式是直接走文件目录的静态链接或官方客户端,而不是解析文件列表页的 HTML。文件列表页的结构会随平台改版变动,按页面结构写的爬虫在改版后会静默失效,取到的可能是错误页而不是数据。官方给出的批量入口与校验文件足以完成下载与完整性核对,没有必要绕。

§6 与库内条目的关系

6.1 关系图谱

这份语料与库内几条记录的关系,可以用一张图说清。核心是 VitalDB 主库,本文是它的一条分支;旁边是从术中信号衍生出的其他研究方向,如低血压预测与无创血压估计;再远处是通用的心电语料,它们与本文共享场景的一部分,但不共享病例。

库内记录 与本文的关系 能否直接连接 连接键
VitalDB 主库 父子:波形在彼,标注在此 必须连接才能训练 case_id
术中低血压预测类记录 兄弟:同一批波形,不同任务 可,共享病例 case_id 与时间轴
通用心律失常语料 场景互补,人群不同 不可直接连 无,仅概念层对齐
重症监护波形库 场景邻近,标注体系不同 不可直接连 无
可穿戴心电语料 干扰类型不同 不可直接连 无
麻醉深度类记录 同一主库的不同信号 可,共享病例 case_id

这张表最该读出的一句话是:它与主库的关系是「必须连接」,与其余记录的关系是「只能对照」。前者是物理同源,后者是概念相邻。把两种关系混为一谈,就会写出「可以合并训练」这种错误的结论。

6.2 检索路径

在库里找与它相关的内容,有三条入口。按来源找:所属机构是首尔国立大学医院麻醉与疼痛医学系。按场景找:标签为生理信号且关键词含术中或围术期。按数据形态找:标注为人工标注、内容为时序信号。

检索意图 关键词 预期命中 说明
术中信号总库 VitalDB、术中、生命体征 主库记录 波形来源
术中心电标注 心律失常、逐搏、ECG 本文 标注来源
术中其他任务 低血压、无创血压、心输出量 主库派生的任务记录 同批病例
通用心电语料 MIT-BIH、动态心电图 通用心电记录 场景不同
监护设备算法 信号质量、伪差 相关方法记录 可作负例来源

6.3 与主库的分工

分工可以一句话概括:主库负责「记录」,本文负责「判读」。主库的强项是多参数、全程、高采样;本文的强项是逐搏、有医师背书、开箱即用。任何需要「信号加解释」的研究,都必须两边一起用。

这个分工也解释了两者的引用关系。官方明确要求同时引用主库,原因不是礼貌,而是方法学上的必要:本文的结论只有在波形可复现的前提下才成立,而波形在另一边。

§7 质量评估与局限性

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

在打分之前,必须先纠正一个常见的错位:很多人拿「竞赛数据集」的尺子来量它,期待它给出标准的训练测试划分、现成的基线分数、以及均衡的类别分布。这三样它都没有。这是误判,因为它从一开始就不是按竞赛数据集设计的。

它是按「临床判读记录」设计的。这意味着它保留了真实判读中的不均衡、不确定与边界模糊,而这些恰恰是临床场景的真实形态。评价它的正确尺子,是「在术中节律这个切面上,它的判读有多可信、覆盖有多完整」,而不是「它有多像一个可以直接打榜的基准」。

同一个错位还有一个变体:拿「全量覆盖」去要求它,说标注只覆盖二十分钟太短。这也是误判。全量覆盖意味着要对数百小时的信号逐搏判读,成本高出一个数量级;团队选择在候选段上做深,是在成本与价值之间的取舍。§4.4 的案例里那段十几秒的成串异位,就是在候选段内部被完整读出来的——覆盖短,但读得深。

7.1 五维评分

维度 分数(5 分制) 依据
完整性 Completeness 3.0 只覆盖候选段,非全程;单导联
准确性 Accuracy 4.5 五名医师交叉复核,一致性好
一致性 Consistency 4.0 标签体系清晰,两层粒度定义明确
时效性 Timeliness 2.5 采集于数年前,设备与流程已变化
可用性 Usability 4.0 开放、免申请、格式简单,但需配主库
可链接性 Linkability 4.5 与主库多参数同轴,多模态潜力大

准确性与可链接性给高分,是因为这两项确实是它的强项:判读有医师背书,时间轴与主库共享。完整性与时效性给低分,同样有据:覆盖不全程,采集年代较早。可用性扣的一分不在开放程度,而在「必须有另一个数据集才能用」这个门槛。

7.2 DAIMS 六维评估

DAIMS 是一套面向数据供给方与使用方之间契约的框架,六个维度分别问:数据是否被描述清楚、质量是否被声明、访问是否受限、使用条款是否清楚、标识是否稳定、供给是否可持续。

DAIMS 维度 评分(5 分制) 具体表现
数据描述 5 字段、节律类别、质量定义、用法示例齐备
数据质量 4 交叉复核流程公开;未见逐类一致性报告
数据访问 5 开放获取,无需申请,静态链接稳定
数据使用 5 CC BY 4.0,允许商用,条款清晰
数据标识 4 有 DOI 与版本号;依赖主库版本,需并列记录
数据供给 3 学术项目,无更新承诺,扩展节奏未知

供给维度给三分是有理由的:四百多例、单一版本,没有看到明确的增量路线图。这不构成缺陷,但它意味着规划长期项目时,应当假设这是静态语料,把扩展性建立在自己的补充计划上。

7.3 已知的、可枚举的偏差

把偏差逐条列出,比说「存在偏差」有用。下面每一条都能在官方说明里找到依据,或者能从数据设计逻辑推出来。

偏差 机制 方向 影响谁
候选门控偏差 只有被算法判为可能的段才入选 异常富集,正常被压低 发生率估计
算法召回偏差 筛选器漏掉的异常不进入语料 对漏检率的估计偏乐观 算法评测
候选段截断 只读每例约二十分钟 长时段演变被切掉 趋势类任务
单导联限制 仅 II 导联 空间信息缺失 形态学任务
单中心限制 一家医院、一套设备 泛化被高估 外部验证
人群限制 仅非心脏手术、成人 心脏手术与儿科缺席 适用范围
判读视角 麻醉科医师而非电生理医师 节律分类偏粗 机制类研究
噪声段无标签 严重伪差段不产生搏级行 有效时长被高估 时长统计

第一行与第二行要合起来看。筛选与召回共同决定了语料的选择性:它既偏向异常的段落,又偏向算法能认出的异常。这两重偏向叠加,使得在这份语料上训练和评测的模型,其表现不能直接外推到「全部术中信号」。这是最需要在使用者心里留下印记的一条。

第三行的后果常被低估。术中节律的演变往往是分钟级的:一次体位改变引起的迷走反射、一次快速输血引起的电解质波动,都可能在一两分钟内完成从窦性到异位再回到窦性的循环。候选段截断之后,这些「过程」在语料里变成了「片段」,模型学到的是片段分类,不是过程追踪。

7.4 外部验证矩阵

验证类型 具体证据 结论
判读人间验证 五名麻醉科医师交叉复核 标签可信度有直接证据
一致性量化 官方报告整体 kappa 与标准差 总体一致性好,少数类未单列
来源一致性 波形与标注同源同轴 时间对齐无需外部校准
方法可复现 随包提供用法示例与代码仓库 取数与对齐路径明确
多中心验证 未见公开报告 泛化能力未知
跨导联验证 未见,语料本身单导联 不可评估
任务级基准 官方未给标准划分与基线 复现需自建协议

七类里有四类成立,三类缺失。缺失的三类恰好是外部效度的三个方向:跨中心、跨导联、跨任务协议。这说明它在内部效度上做得很扎实,在外部效度上留白明显。

7.5 它为何能持续:波形已经存在,缺的只是判读

一份标注语料要活下来,通常需要两条腿:可持续的数据来源,与可持续的判读投入。它的特殊之处在于第一条腿是现成的。

第一层是波形的零成本复用。VitalDB 主库已经存在、已经脱标识、已经开放、已经被大量研究引用。本项目不需要重新采集,也不需要重新走伦理与数据治理流程,只需要在主库上叠加一层判读。这让它的边际成本主要落在医师时间上,而不是采集与合规上。

第二层是临床需求的持续性。术中监护设备每年出货量巨大,算法从「阈值报警」向「节律识别」迁移是确定的趋势。任何做这条路线的团队都需要术中场景的标注语料,而公开选项极少。需求在,语料就有被引用的理由。

第三层是判读标准的可传承。五名医师、明确的节律类别定义、两级质量标记,这套标准一旦写下来,就可以被后来的标注工作沿用甚至扩展。扩充不需要从零定义标签体系,只需要按同一套规则继续读。

三层叠起来,就是它的生存逻辑:主库供波形,需求供动机,标准供扩展。§4.4 的案例里的那一分钟,之所以能被反复引用,正因为它同时展示了这三层——波形来自主库,判读来自医师,标签体系让这一段可以被别人复用。

§8 生态位与历史

8.1 从主库到标注层的三年

时间线要从 VitalDB 主库说起。主库在 2022 年以论文与开放数据的形式发布,覆盖数年间在一家医院手术室采集的数千例非心脏手术。它的出现填补了「术中多参数波形开放」这个空白,随后被大量用于低血压预测、无创血压估计、心输出量估计等任务。

时间 事件 意义
2022 年 VitalDB 主库论文与数据发布 术中波形开放
2022 至 2025 年 主库被大量用于术中监护任务研究 波形层形成生态
2025 年前后 心律失常标注工作启动 标注层开始
2026 年 2 月 本标注集 1.0.0 发布 术中逐搏标注首次公开
后续 未见明确的扩展路线图 静态语料

这段历史说明一件事:标注层不是凭空出现的,它是主库生态成熟之后的自然延伸。先用起来,再发现缺标注,再补标注,这是开源数据常见的演化路径。

8.2 为什么是心律失常,而不是别的

主库可以派生的标注方向很多:低血压事件、血氧下降、心律失常、机械通气事件。团队先做了心律失常,有几个可解释的原因。

其一是判读可行性。心电判读有成熟的类别体系与相对明确的边界,医师之间的分歧可以被压到较低水平。相比之下,低血压事件的边界取决于定义阈值与基线选择,标注一致性天然更低。

其二是自动化筛选的可行性。搏分类在算法上已经相对成熟,用一个分类器做候选筛选的召回率可以做得比较高,从而把人工量压下来。别的任务未必有同样好用的筛选器。

其三是临床价值明确。术中房颤、室性心律失常、房室阻滞都会直接影响血流动力学与手术进程,是麻醉科最关心的心电问题。

8.3 在公开心电语料谱系里的位置

谱系位置 代表语料 本文的差异
门诊十二导联 各类竞赛语料 单导联、术中、无标准划分
动态心电图 MIT-BIH 系列 场景不同,标注传统更久
重症监护 各类 ICU 波形库 场景邻近,标注体系不同
术中 VitalDB 主库(无标注) 本文是唯一有逐搏标注的术中支
可穿戴 单导联长程记录 干扰类型与人群不同

这个位置有一个副作用:它既是「术中」,又是「单导联」,因此既不能被十二导联语料替代,也不能被可穿戴语料替代。它填补的是两个维度交叉处的一个小格子,格子小,但别处没有。

8.4 生态位的两面

一面是不可替代。术中加逐搏的组合,公开语料里目前只有它。任何做术中节律识别的团队,绕不开它。

另一面是不可扩张。单中心、单导联、单批病例,决定了它无法通过简单扩充变成「通用的术中节律语料」。要扩张,必须引入新的中心、新的设备、新的导联配置,那是另一项工程的规模。

这两面并存,就是它的生态位:小而必用,用而不够。理解这一点,才不会对它提出超出设计的目标。

§9 使用指引

9.1 三种角色的路径

角色 目标 最短路径 主要风险
算法工程师 训练并评测搏分类器 下载标注、批量取波形、自建划分 抽样偏倚导致过优估计
临床研究者 描述术中节律现象 用标注做探索,回波形核对 误用候选段算发生率
设备开发者 评估产品在术中的表现 作为外部测试集之一 单中心结果不足以支撑声明

第二类角色最需要克制。用这份语料做「术中房颤有多少」这类描述,看起来顺手,但抽样已经破坏了分母。正确做法是用它描述「房颤在术中的形态特征」,而不是「房颤在术中的频度」。

9.2 一条最短的可用流程

从零到跑通一个搏分类实验,最短的路径是四步:下载标注、批量取波形、切窗、训练。下面的脚本把前两步串起来,并给出切窗的基本形态。

import numpy as np
import pandas as pd
import vitaldb

FS = 500
WIN_L, WIN_R = 0.3, 0.4          #-- 取 R 波前 300 毫秒、后 400 毫秒
LABEL_MAP = {"Normal": 0, "Supraventricular": 1, "Ventricular": 2, "Unclassifiable": 3}

meta = pd.read_csv("metadata.csv")
case_ids = [int(c) for c in meta["case_id"]][:5]

X, y = [], []
for cid in case_ids:
    ann = pd.read_csv(f"Annotation_Files/Annotation_file_{cid}.csv")
    sig = vitaldb.load_case(cid, ["SNUADC/ECG_II"], 1 / FS)
    if sig is None:
        continue
    sig = np.asarray(sig, dtype=np.float32).reshape(-1)
    for _, r in ann.iterrows():
        c = int(round(float(r["time_second"]) * FS))
        a, b = c - int(WIN_L * FS), c + int(WIN_R * FS)
        if a < 0 or b > sig.size:
            continue
        X.append(sig[a:b])
        y.append(LABEL_MAP.get(str(r["beat_type"]).strip(), 3))

X = np.stack(X)
y = np.asarray(y)
print("样本", X.shape, "类别", np.bincount(y))

这段代码刻意留了两处可改。第一处是窗宽,三百与四百毫秒是一个够用的默认值,做节律判别时可以放宽到前后各一秒。第二处是噪声与低质量段的处理,示例里没有剔除,正式训练时应当用 §2.2 的布尔列把它们筛掉或降权。

9.3 训练集划分的三条建议

第一条,按病例划分,不按搏划分。同一例内的相邻搏高度相关,按搏随机划分会把同一段信号拆到训练与测试两侧,导致测试分数虚高。这是心电任务里最常见的划分错误。

第二条,把低质量段单列。它们要么剔除,要么单独作为一个评测子集,用来观察模型在噪声下的退化。混进主集会让「总体准确率」掩盖掉这个退化。

第三条,报表要给类别分布。这里只有四类,但极少类(无法归类)的样本量很小,用一个总体准确率会严重误导。至少给出每类的样本量与每类的指标。

9.4 引用方式

正式引用要两件一起做:引用本文语料,并引用主库。前者给出版本与 DOI,后者给出波形的来源与原始描述。只在正文提一句「数据来自 VitalDB」而不引主库,在方法学上是不完整的。

Eun D, Shim K, Lee H, Lim Y, Lim H, Lee H, Lee H-C.
VitalDB Arrhythmia Database (version 1.0.0). PhysioNet. 2026.
doi:10.13026/axd6-wm13

Lee H-C, Park Y, Yoon SB, Yang SM, Park D, Jung C-W.
VitalDB, a high-fidelity multi-parameter vital signs database in surgical patients.
Scientific Data. 2022;9:279. doi:10.1038/s41597-022-01411-5

第二条是主库的文献引用,具体卷期与页码以期刊页面为准。使用方法上,引用时还应当说明本文用的是哪个版本、用了哪些病例、以及是否做过筛选——这些信息决定了别人能不能复现。

§10 AI 使用声明

事项 声明内容
写作方式 由 AI 辅助起草,事实性数字经人工对照官方页面核对
数据获取方式 全部数字来自 PhysioNet 项目主页及其说明、文件、引用子页
未覆盖的部分 未下载全量标注包做逐条统计,未运行官方代码
数字口径 规模类数字取官方摘要表述,未做二次核算
可复算性 附录 A 标注每项数字的来源层级
已知局限 官方内部若存在口径差异,本文按单一来源处理
使用建议 引用前请对照官方页面当前版本复核
责任边界 本文不构成对任何算法的性能评价

常见误读

常见说法 实际 证据
「这是 VitalDB 主库的新版本」 是主库之上的标注派生层,波形仍在主库 官方说明包内不含波形
「下载就能训练」 必须回主库按编号取波形 包内只有标注 CSV 与元数据
「覆盖整台手术」 只覆盖每例约二十分钟候选段 官方在局限部分明确写出
「可以算术中房颤发生率」 候选段抽样,分母被破坏 进入语料的前提是被算法筛出
「有多导联波形」 只有 II 导联 官方用法示例仅取该轨道
「噪声段是正常搏的负例」 噪声段无搏级标签,单列为节律类 官方对噪声的定义
「低质量段不可用」 QRS 仍可辨,可降权使用 官方对低质量的定义
「四类搏标签可以细分成十几种」 搏级只有四类,细分在节律层 两级标签体系
「标注未经医师确认」 五名麻醉科医师交叉复核 官方描述判读流程
「可以直接拿来打榜」 无标准划分、无官方基线 包内不含实验协议

FAQ

Q1:VitalDB Arrhythmia 与 VitalDB 主库是什么关系?
它是主库的标注衍生层。四百多例病例全部来自主库,波形仍存放在主库,本包只给标注与元数据。两者必须配合使用,引用时也要同时给出。

Q2:数据包里为什么没有波形文件?
官方为了分发效率把标注与波形分开。波形体量大得多,放在主库里由使用者按需取;标注很小,单独发一个包更便于快速分发与版本管理。

Q3:标注是否覆盖整台手术?
不覆盖。标注集中在每例约二十分钟的候选段,是筛选后的人工判读结果。不能当作全程连续的搏级记录,也不能用它算术中某类心律失常的发生率。

Q4:可以直接拿它训练多导联心电模型吗?
不能直接拿。它只给 II 导联单通道标注。回主库取其他通道是可以的,但那些通道没有对应标注,标签无法平移过去。

Q5:许可允许商用吗?
允许。CC BY 4.0 允许商用与改编,条件是署名、注明版本与 DOI、说明是否修改。同时引用主库是官方明确要求,否则方法学链条不完整。

Q6:能否用它证明某个算法的临床可用性?
只能作为术中场景的证据之一。单中心、单导联、候选段抽样三重限制叠加,外部验证仍须另有队列,不能仅凭此集下结论。

Q7:五名医师的判读一定比一名更可靠吗?
在分歧可协商的前提下通常是。多名独立判读能压低个体偏差,但代价是少数类的分歧可能被多数意见抹平。官方报告的整体一致性指标是高,但未逐类给出。

Q8:为什么只有非心脏手术?
主库本身以非心脏手术为主,因为这类手术的术中监护更依赖常规多参数记录,且伦理与数据开放的边界更清楚。心脏手术的体外循环与特殊监护不在其中。

Q9:时间戳与主库波形对不上怎么办?
先查采样率换算是否一致,再查是否对波形做过裁剪或滤波。前两步都对上,且仍有整体偏移,则应检查取的是否为同一条轨道、同一段记录。

Q10:能不能用它做信号质量算法?
可以,但只到粗粒度。它把质量分成正常、低质量、噪声三级,足够做三分类或二分类,不足以训练精细的伪差类型识别。

Q11:为什么不能按搏随机划分训练测试?
同一例内的相邻搏高度相关。按搏随机划分会把同一段信号的邻域拆到两侧,测试分数会虚高。正确做法是按病例划分。

Q12:这份语料会继续扩充吗?
官方未给出明确路线图。规划长期项目时,应当把它当作静态语料,扩展性建立在自己的补充计划上,而不是假设它会持续增量。

术语表

术语 英文 含义
搏级标签 Beat-level label 对单个心搏的类别判定,本文为四类
节律标签 Rhythm label 对一段连续心电的整体心律判定,本文为十类
室上性搏 Supraventricular beat 起源在心室以上的异位搏
室性搏 Ventricular beat 起源于心室的异位搏
成串室性异位 Patterned ventricular ectopy 连续出现的室性异位搏
成串房性异位 Patterned atrial ectopy 连续出现的房性异位搏
窦房结功能不全 Sinus node dysfunction 窦房结起搏或传导功能异常
房室阻滞 Atrioventricular block 房室传导延迟或中断
游走性心房起搏 Wandering atrial pacemaker 起搏点在心房内游走
多源性房性心律 Multifocal atrial rhythm 多个心房起搏点交替
室上性快速性心律失常 Supraventricular tachyarrhythmia 心室以上的快速心律
室性快速性心律失常 Ventricular tachyarrhythmia 心室来源的快速心律
低信号质量 Bad signal quality QRS 可辨但 P 波或 T 波被噪声掩盖
噪声段 Noise 伪差严重到 QRS 无法辨认的片段
候选段 Candidate segment 被算法筛出、交由医师判读的片段
判读人间一致性 Inter-rater reliability 不同判读人之间结论的一致程度
一致性系数 Cohen’s kappa 扣除随机一致后的一致性度量
主库 Parent database 存放原始波形的 VitalDB
派生标注层 Annotation layer 在主库之上叠加的人工判读结果
II 导联 Lead II 术中常用的单导联心电配置
重采样 Resampling 把波形转换到目标采样率的过程
时间轴零点 Time zero 标注与波形共同采用的时间起点
心跳零基线 Baseline 电压参考水平,用于判断波形偏移
逐搏标注 Beat-wise annotation 每个心搏都有独立标签的标注方式
节律分段 Rhythm segmentation 把连续记录切分为等节律区间的任务
病例编号 case_id 主库与标注层共享的唯一标识
心脏手术 Cardiac surgery 本文不覆盖的一类手术
围术期 Perioperative period 手术前中后的整体时间段

附录 A:核心数字核对表

项 值 来源 来源层级
病例数 482 例 官方摘要与页面概览 官方页面
标注总时长 734,528 秒 官方摘要 官方页面
逐搏标注数 逾六十六万个 官方摘要 官方页面
搏级类别数 4 类 官方摘要 官方页面
节律类别数 10 类 官方摘要 官方页面
每例覆盖时长 约二十分钟 官方局限说明 官方页面
导联配置 II 导联单通道 官方用法示例 官方页面
标注采样时间轴 500 Hz 官方用法示例 官方页面
判读人数 5 名麻醉科医师 官方摘要 官方页面
每段判读人数 至少 2 人 官方摘要 官方页面
整体一致性 官方报告的 kappa 值 官方摘要 官方页面
包体大小 未压缩约二十兆字节量级 官方文件页 官方页面
许可 CC BY 4.0 官方许可页 官方页面
版本与日期 1.0.0,2026 年 2 月 官方页面 官方页面
病例来源年份 与主库同批,数年前采集 主库描述 官方页面

附录 B:数字的来源分层

层级 说明 本文中的例子
官方页面 直接取自 PhysioNet 项目页、说明页、文件页、引用页 病例数、时长、类别数、许可、版本
论文摘要 官方未在页面给出、仅见于相关工作摘要 未见本文采用此类数字
未核实 官方未说明、本文仅作量级描述 包体精确字节数、各节律类别的病例分布

凡属第三层的表述,本文一律用「数十兆字节量级」「数十个区间」这类概数,不写具体到个位的数字。这样做不是回避,而是因为这类数字随版本变动,写死反而会误导。

附录 C:完整参考文献

序号 文献 用途
1 Eun D, Shim K, Lee H 等. VitalDB Arrhythmia Database. PhysioNet, 2026. doi:10.13026/axd6-wm13 本文语料的正式引用
2 Lee H-C, Park Y, Yoon SB 等. VitalDB. Scientific Data, 2022;9:279 波形的正式引用
3 PhysioNet 平台自身的方法学文章 平台层面的引用
4 术中低血压预测相关工作 说明主库的派生方向
5 动态心电图搏分类的经典工作 说明搏级标注的传统
6 心电信号质量评估相关工作 说明质量标记的意义

附录 D:任务代码

把一个完整的最小实验跑通,需要把标注、波形、切窗、划分四件事串起来。下面的脚本给出按病例划分的基本形态,可以直接改为正式训练。

import numpy as np
import pandas as pd

FS = 500
WIN = (int(0.3 * FS), int(0.4 * FS))
MAP = {"Normal": 0, "Supraventricular": 1, "Ventricular": 2}


def build(meta_path, ann_dir, loader):
    """按病例聚合样本,返回 (X, y, case_of_row)。"""
    meta = pd.read_csv(meta_path)
    X, y, case = [], [], []
    for cid in meta["case_id"]:
        cid = int(cid)
        ann = pd.read_csv(f"{ann_dir}/Annotation_file_{cid}.csv")
        sig = loader(cid)
        if sig is None:
            continue
        for t, bt, bad in zip(ann["time_second"], ann["beat_type"], ann["bad_signal_quality"]):
            if str(bad).strip().lower() == "true":
                continue
            lab = MAP.get(str(bt).strip())
            if lab is None:
                continue
            c = int(round(float(t) * FS))
            a, b = c - WIN[0], c + WIN[1]
            if a < 0 or b > sig.size:
                continue
            X.append(sig[a:b])
            y.append(lab)
            case.append(cid)
    return np.stack(X), np.asarray(y), np.asarray(case)


def split_by_case(case_ids, seed=0):
    """按病例划分,避免同例相邻搏同时落入训练与测试。"""
    rng = np.random.default_rng(seed)
    uniq = np.unique(case_ids)
    rng.shuffle(uniq)
    cut = int(len(uniq) * 0.8)
    train, test = set(uniq[:cut]), set(uniq[cut:])
    return train, test


#-- loader 由使用者替换成基于 vitaldb 的取数函数

附录 E:如果只记五件事

第一,它是标注层,不是波形层。波形在主库,标注在这里,两者用病例编号连接,引用要两份一起给。

第二,它的覆盖是候选段,不是全程。每例约二十分钟,且进段门槛是算法筛出异常,所以不能用它算发生率。

第三,它的独特性在「术中」与「逐搏」的交集。单看任何一条都有更强的语料,两条叠起来可选的就很少了。

第四,两级标签不能混用。搏级四类回答「这一次除极来自哪里」,节律级十类回答「这一段整体是什么」,任务不同,取标签的层级就不同。

第五,划分一定按病例。按搏随机划分会让同例相邻搏分落两侧,测试分数虚高,这是这类语料最常见的错误。

编辑说明

核验时间:2026 年 10 月 28 日。核对方式:访问 PhysioNet 的项目主页面、数据说明子页、文件子页与引用子页,逐页读取官方表述;未下载全量标注包做逐条统计,也未运行官方示例代码,因此文中凡涉及包内文件内部结构、各节律类别的病例构成、包体精确字节数等内容,均按官方文字描述转述而不给出逐项统计值。规模类数字(病例数、总时长、逐搏标注数、类别数)取自官方摘要,未做二次核算。文中出现的一致性系数只以「官方报告的 kappa 值」表述,未复述具体数值与标准差,原因是该指标随版本与统计口径可能调整,写死数值对使用者的决策没有增量。病例 337 的一段标注用于结构示意,其中时间戳与标签组合用于说明两个粒度的并置方式,不作为该例的真实判读结果引用。若官方将来调整字段命名或节律类别定义,以官方页面当前版本为准。


相关数据集导航

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

  • ucddb — 共享标签:生理信号 / 多模态
  • neurovault — 共享标签:多模态 / 医学问答与基准
  • rnacentral — 共享标签:多模态 / 医学问答与基准
  • rfam — 共享标签:多模态 / 医学问答与基准
  • seed — 共享标签:生理信号 / 医学问答与基准
  • cded — 共享标签:生理信号 / 多模态
  • kiel-cardio — 共享标签:生理信号 / 多模态
  • eye-tracking-ecg — 共享标签:生理信号 / 多模态
  • wesad — 共享标签:生理信号 / 多模态
  • qt-database — 共享标签:生理信号 / 医学问答与基准

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

返回 AI-Ready 数据集