自发室速前的千次心跳 — MVTDB 心内电图 RR 间期库

78 例植入式除颤器患者 / 135 对间期序列 / 只有时间戳没有波形

来源 https://physionet.org/content/mvtdb/1.0/发布时间: 2026-10-28最后更新: 2026-10-28 阅读 11
自发室速前的千次心跳 — MVTDB 心内电图 RR 间期库

信息速览

数据集名称自发室速前的千次心跳 — MVTDB 心内电图 RR 间期库
数据类型时序信号,元数据,人工标注
规模78 例受试者 / 135 对序列(捕获段 135 条、基线段 135 条)
接入方式https://physionet.org/content/mvtdb/1.0/
AI 就绪度

MVTDB 是 PhysioNet 上一份来源特殊的心律失常数据:不含任何心电波形,只有一串串数字。每个数字是一拍心跳与下一拍之间的间隔,单位毫秒。被记录的人身上装着一台植入式心律转复除颤器,设备在探测到危险心律的那一刻,把此前存进缓冲的一千多个间隔整段交出。

官方全名是 Spontaneous Ventricular Tachyarrhythmia Database,美敦力公司提供,2007 年 5 月 2 日以 1.0 版上线。库里共 135 对序列,来自 78 例患者,每对一半是被抓住的室速或室颤片段,另一半是同一台设备、同一个人随访时取回的基线心律。它回答「发作之前节律有没有可识别的前兆」,而不是「发作时波形长什么样」。

这个名字里的 MVTDB 是个需要澄清的旧称:官方全名里并不存在 MVT 这个连续缩写,M 指美敦力,VT 指室性心动过速,DB 指数据库,合称美敦力室速库,与 MIT-BIH 心律失常库不是同一份数据。弄清这一点,关于「为什么没有导联、没有波形」的疑问就一并消解了。一屏速览见下表。

维度 内容
官方全名 Spontaneous Ventricular Tachyarrhythmia Database
中文名 自发室性快速心律失常数据库
缩写拆解 M=Medtronic,VT=Ventricular Tachyarrhythmia,DB=Database;官方全名中无 MVT 连写
提供方 Medtronic, Inc.(美敦力)
托管平台 PhysioNet,Open Access 栏目
当前版本 1.0,2007 年 5 月 2 日发布
DOI 10.13026/C25K5D
受试者 78 例,全部植入 Jewel Plus ICD 7218,无起搏器
序列规模 135 对(捕获段 135 条 + 基线段 135 条,共 270 条)
每段长度 捕获段 1024 个间期;基线段 986 至 1022 个
数据形态 每行一个整数,单位毫秒,10 ms 粒度
信号类型 RR 间期序列,无心内电图、无体表心电波形
四个子集 MRVT 58 对 / MRVF 25 对 / MultiVT 48 对 / MultiVF 4 对
采集截止 1997 年 1 月 3 日之前
地域 美国与加拿大
体量 未压缩 2.5 MB,压缩包 2.6 MB
许可 Open Data Commons Attribution License v1.0
配套表格 phys.xls,含事件时间、分类与患者病史

§1 它要解决的具体麻烦

1.1 猝死预测的瓶颈不在算法,在「事件发生前那几分钟长什么样」

植入式除颤器最有效的功能是把致命心律电回去,最被诟病的却是来者不拒:只要间期满足程控判据就放电,不管这次是否真的危险,病人被误放电电醒是这类设备的老问题。方向只有两个:把判据调得更聪明,或在发作之前就有所察觉。

后一条路需要极难拿到的数据。真实的室速与室颤发作大多发生在院外、人独处时,监护仪留不下记录,等送到急诊事件已经过去。能自发把发作前那段时间存下来的设备,只有植入体内的那类,而这批记录几乎全锁在厂商手里。

MVTDB 是这批记录里漏出来的一小块。美敦力整理设备里存下的快照,把能配上基线对照的部分交了出来。它不讲波形只讲节律,不求覆盖人群,只求让发作前的那段间期序列与平时的间期序列可以被并排比较。

这也解释了它的体量为何这么小。能被拿来配对的事件,先要设备真的触发并留下快照,再要在随访时被完整读出,最后还要能在同一患者身上找到一段可比的基线。三道筛子叠在一起,一百四十余例研究人群最后只剩 78 例、135 对。数据小不是整理的疏忽,而是采集条件本身的上限。

1.2 三条常见的错误期待

第一条,期待它是心电数据库。 名字里有 tachyarrhythmia,很容易被归进心电那类,默认它像其他心电库那样有导联、有采样率、有波形。实际上它一个字节的波形都没有,打开任何序列文件只是一列整数。

第二条,期待它规模可观。 135 对序列拆开看只是 78 例患者,且按四个子集组织,MultiVT 就有 48 对而 MultiVF 只有 4 对。加总得到的一百多对,并不意味着有一百多个独立观察。

第三条,期待它有逐搏诊断标签。 唯一的标签是文件名里 vt、vf、mr 三个字母与表格里的两种分类栏,想训练心搏分类模型,这里没有监督信号。

三条期待背后是同一个误会:把名字当成了内容。名字里的 tachyarrhythmia 说的是它记录的病,不是它记录的信号;名字里的 database 说的是它的组织形式,不是它的规模。看名字先入为主,再打开文件就会连续落空。避开这个误会的办法很简单,先看官方数据描述那一段,它第一句就说明了数据是间期序列,不含波形。

还有一条不那么常见、但确实会发生的误会:把它当成某份著名心电库的子集。常见于文献综述转引时,把库名缩写拆错,再据此以为它是另一份数据的变体。核对一次提供方就能排除,而提供方在官方页面上写得很清楚。

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

你的处境 它能帮你什么 下一步该做什么
你在给除颤器写「减少不必要放电」的算法,手头只有厂家给的模拟数据 提供真实设备探测时刻前的一段真实节律 先按患者分组,再在配对结构上做前后对比
你在做时间序列异常检测,想找一个「有明确事件边界」的公开集 事件边界天然存在,即序列最后一个间期 把哪一条算作事件起点需要自己定义,官方没给
你在写心率变异性与恶性心律失常关系的综述 有可引用的配对设计,且许可允许转载图表 逐条核对四个子集的样本量,别把总数当独立例数
你刚接触 PhysioNet,需要一个极简格式入门 文件是纯文本一列整数,没有复杂头结构 用它练熟读文件、画间期序列、算基本指标
你在做可穿戴设备的房颤之外心律预警 提供「发作前」这类正样本的思路与对照设计 注意人群差异,植入器患者不等于一般人群
你要训练深度模型,需要长序列 每条仅一千个间期,库总量不到二十兆 更适合当外部验证集,不是主训练集
你在评估某算法是否只在自家数据上有效 一份来源完全独立、设备型号封闭的外部集 固定超参不动,只换评测数据

1.4 一句话判断

它不提供病症的画像,只提供时间的刻度:把「发作之前那一千拍」与「平时那一千拍」放在一起,让人有机会回答「在室速真正开始之前,心跳的节奏有没有先变过」。

1.5 不适合谁:四条边界

不适合做波形研究。 任何以心电图形态为输入的模型在这里都没有入口,库中不存在采样信号,只有事件间隔,没有折中余地。

不适合做设备横向比较。 全部受试者都用同一型号设备:Medtronic Jewel Plus ICD 7218。不同厂商的感知算法、探测判据都不同,用这一个库得出的阈值结论迁移到别家设备上没有依据。

不适合把序列当独立样本。 一名患者可能贡献十几条序列,MultiVT 专收同一患者的更早事件。按序列随机划分,训练集会混入与测试集几乎同源的片段,指标被高估。

不适合做室颤的专项结论。 MultiVF 只有 4 对,MRVF 25 对。室颤与室速机制不同,混进一个筐里会让本已单薄的室颤部分失去分辨力。

1.6 与临床监护场景的三处错位

这份数据常被拿去做院外预警的原型,用它可以,但要先认清三处错位。第一处是采集设备:本库用的是植入式除颤器的感知通道,电极贴在心内膜上,R 波锐利、伪迹少,间期接近理想条件;贴片、腕表、床旁监护仪要过皮肤接触与运动干扰,同一人同一天的间期形态会有可观差别,测量精度不在一个量级。

第二处是人群状态:本库的对象是已植入除颤器的高危患者,临床监护面对的是住院或社区的一般人群。这一条决定基准率,装过设备的人事件发生率远高于一般人群,放到一般人群里,同一模型的阳性预测值会明显下降。

第三处是事件定义:本库的「事件」是设备判据触发的那一刻,临床上的室速是医生看电图判的,报警规则又是另一套口径。同一段节律完全可能被一方判为发作、被另一方判为噪声,边界处两者并不一致(§7.2)。

§2 数据构成与规格

2.1 四个目录,两套等价表述

解压后根目录下只有四项实体内容:RRdata1、mr、data、images,加一份 phys.xls 与一份校验清单。前两个是美敦力交来的原始文本,后一个是 PhysioNet 为兼容自己的工具链重新生成的一套文件。两套表达的是同一批间期,只是格式不同。

原件与转换件并存的做法在平台上不算常见。原始文本是表格软件导出的纯文本,一行一个毫秒整数,对人友好、对程序不友好:没有采样率,没有通道数,没有记录名对照表。平台因此另建一套 WFDB 风格文件,.hea 写元信息,.qrs 存逐条间期的注释。两套都能直接用,选哪套取决于你用不用 WFDB 工具。

RRdata1 与 mr 各 135 条,分别是捕获段与基线段,一列毫秒整数,前者固定 1024 行,后者行数不固定,是最直接的正样本与对照来源。data 里每对序列各有一组 .hea 加 .qrs,共 135 组,供 WFDB 工具读取。images 放的是解释人工分类依据的示意图,PNG 格式,数量若干。根目录那份 phys.xls 每对一行、含病史,SHA256SUMS.txt 则是逐文件哈希,用于校验完整性。

2.2 字段与文件的完整字典

这个库没有数据库,没有字段表,所有信息分散在文件名、头文件、注释文件和表格里。下表把四处合并。

信息项 存放位置 取值或范围
患者编号 文件名前四位 四位数,如 0003、8076
事件类型 文件名中间两位 vt、vf、mr
序列序号 文件名末位 数字,或 a(基线段的特殊情况)
通道数 .hea 首行第二列 恒为 0
采样率字段 .hea 首行第三列 恒为 1000,占位
序列长度字段 .hea 首行第四列 恒为 0
逐间期注释 .qrs 二进制 每间期一个字节
间期数值 原始文本或注释解码 毫秒整数,10 的倍数
事件日期时间 phys.xls 日期加时刻
设备分类 phys.xls 设备当时的判定
人工分类 phys.xls VT、VF 或 SVT
性别、身高体重、年龄 phys.xls 数值,缺值记为 A
心脏病史、心律失常史 phys.xls 文本描述
射血分数、NYHA 分级 phys.xls 数值,缺值记为 A
事件时用药 phys.xls 药名列表
波形采样、真实采样率 无 库里不存在
事件终止时刻、起点定义 无 官方未提供

头文件里那三个 0 与 1000 常被误读。它们不是测量值,而是 WFDB 对「没有信号通道」的记录留的占位:通道数写 0,长度写 0,采样率字段按规范填一个非零数以免除零。真正的时间信息在注释文件里,每个间期一条注释,注释的采样位置是序号累加值。

2.3 一条序列的完整解剖

取 0003.vt1 为例。文件名拆成三段:0003 是患者编号,vt 表示这是探测到室速的片段,1 表示该患者的第一条室速事件。它在 RRdata1 目录里,对应 data 目录下的 0003_vt1.hea 与 0003_vt1.qrs,以及基线侧的 mr/0003.mr1。

import urllib.request

base = "https://physionet.org/files/mvtdb/1.0/RRdata1"
raw = urllib.request.urlopen(f"{base}/0003.vt1").read().decode()
rr = [int(x) for x in raw.split() if x.strip()]
print("间期个数:", len(rr))
print("前十个:", rr[:10])
print("末十个:", rr[-10:])
print("最小值:", min(rr), "最大值:", max(rr))

这段代码不依赖任何专业库。得到的 rr 是长度为 1024 的整数表,最后一项就是设备首次探测到室速之前的那一个间期。按同一路径还能直接取到 data/0003_vt1.hea,它只有一行,内容是 0003_vt1 0 1000 0。序列止于探测,不含探测之后的内容,所以用这条数据看不到设备放电、也看不到心律被终止。

这条序列的三个数字与一处命名,是读库里任何一条序列都用得上的模板。三个数字指 1024、10 与那个占位的一千:前者是缓冲容量,中者是截断粒度,后者不是采样率。一处命名指 vt、vf、mr 三个两字母标记,它们同时是文件名的中段与官方分类的口径。记住这四样,再去看目录结构就不容易迷路。

值得展开的是「配对」这件事。官方用 sequence pair 这个词来指一组「捕获段加基线段」。配对不是按时间邻近做的:基线段是随访时设备的缓冲当前状态,采集时刻通常晚于事件,具体晚多少官方只给了日期时间,没有给两者的时差统计。这意味着配对回答的是「这个人平时的节律」,不是「发作前几分钟的节律」。

0003.vt1 与 0003.mr1 这一对,正是后面反复出现的那个样本(§4.2)。先把它记住,等到讨论配对结构、事件边界与评测协议时,都会回到它身上。

2.4 四个子集与它们的边界

官方把 135 对分成四个子集,划分依据是「事件是否是该患者的首次」以及「事件类型」。这个划分方式直接决定了每一类的生理含义与样本量。

MRVT 有 58 对,收的是每位发生过室速患者最接近的那一次室速配对,一对大致对应一名患者,接近独立;MRVF 有 25 对,同一定义,只是事件换成室颤,覆盖室颤人群;MultiVT 有 48 对,收的是全部更早的室速配对,重复患者多,不能当独立样本;MultiVF 只有 4 对,是全部更早的室颤配对,小得只够定性。

官方在此明确提醒:合并子集要小心,避免让某位拥有大量配对的患者主导结论。这是对使用方式的约束,不只是建议。MRVT 加 MRVF 合计 83 对,接近患者覆盖,但因有患者同时有室速与室颤,两个子集有重合。官方数据描述段写五例、子集划分段写六例,两处口径不一致,差额构成未说明。

还有个小细节值得记:有五例同时有两种事件的患者,其首次室颤对应的基线被命名为 mra 而不是 mr1,以免与首次室速的基线撞名。这个后缀没有出现在任何字段里,只在官方文档的示例表中列出,解析文件名时若只认数字后缀,会把这几条基线漏掉。

§3 它是谁的数据:一台设备三年的缓冲

3.1 提供方与整理者

数据由美敦力公司提供。官方页面署名两位原始文档撰写者:美敦力的 Ann M. Pearson 与 Walter H. Olson,说明文字在提交平台时经过编辑。与多数由医院或大学署名的库不同,这里是一家器械厂商。

平台侧的责任是托管,页脚注明由 MIT Laboratory for Computational Physiology 维护,主要工作是把厂商交来的文本整理成 WFDB 兼容文件,并保留原件,让两种口径都能查。

六个角色分工很干净:数据由 Medtronic 的植入设备在真实患者体内探测并缓存,筛选与分类也由 Medtronic 按形态判据逐条人工复核,最终交出 135 对序列与病例表格;文档由 Pearson 与 Olson 撰写,内容即数据描述与分类判据;PhysioNet 负责生成 .hea 与 .qrs 转换件;MIT LCP 负责访问、校验与版本。生理事件出自厂商设备,格式出自平台,两者界限分明。

正因为源头是器械厂商,这份数据的入口和出口都带着产品属性:入口决定了只有装着特定型号设备的患者才能进来,出口决定了只有随访时被程控仪读出的缓冲才出得去。厂商愿意交出这一批,却没有理由交出更多,库为何在 1.0 停下也就有了解释(§7.5)。

3.2 时间线

时间线上的节点不多,但都可在目录列表与官方页面上逐一核对。事件采集期止于 1997 年 1 月 3 日,这是官方给出的截止日;同年 7 月,原始文本文件留下时间戳;7 月 30 日,病例表格留下时间戳;2006 年 11 月,目录结构被调整;2007 年 5 月 2 日,PhysioNet 以 1.0 版发布;2012 年 2 月 25 日,转换件目录被重整;2019 年 2 月 20 日,补入 SHA256 校验清单。

落差值得注意:事件截止于 1997 年 1 月,原始文件在同年 7 月整理,平台发布却要等到十年之后的 2007 年 5 月。这十年里发生了什么,官方没有交代。可以确认的只有结果:这份数据在 1990 年代末就已经整理完毕,它进入公共视野的时间比数据本身晚了整整十年。

3.3 采集链:从感知到快照再到随访

理解这个库,最好把它想成一条五步的流水线。

患者体内
  心内电图四通道数字化
        |
        v
  自动调整阈值的感知放大器
        |
        v
  逐搏 RR 间期(Tip-Ring 通道)
        |
        v
  1024 格环形缓冲,不断覆写
        |
   触发探测判据 ==> 存快照(止于探测时刻)
        |
        v
  随访:程控仪取回快照 + 再取一份缓冲当前态
        |
        v
  Medtronic 人工复核 -> 135 对序列

这条链条上有三个环节决定了数据的性格。第一,间期只在 Tip-Ring 这一路上测,其它三路电图不参与。第二,缓冲是环形覆写,所以「发作前多久」不是可以选择的长短,而是缓冲容量乘上当时的间期长度。第三,快照在触发瞬间截止,所以看到的是「进入事件」而不是「事件全过程」。

3.4 设备里那四路电图是什么

官方列出了设备数字化的四路心内电图通道,每一路由两个电极的电位差构成。HVA 到 HVB 是外壳到线圈,构成高电压通道,属于除颤回路的一部分;P-/S 到 P+/S 是尖端到环,即感知通道,所有 RR 间期都取自这一路;HVA 到 P+/S 是外壳到环,P-/S 到 HVB 是尖端到线圈,后两路是混合通道。

四路里只有尖端到环这一路测间期,因为它离心内膜最近,R 波最锐、信噪比最好,另三路服务除颤与形态判读。所有间期因此都可追溯到同一路信号,不同患者之间的测量口径一致,可比性相对高。

这也是为什么本库没有「导联」这个字段。体表心电要靠多导联从不同角度逼近同一个心电向量,而植入电极已经在心腔内,四路电图是设备的内部接法,不是给外部使用者选视角用的。拿体表心电的导联概念来读它,多半会失望;把它当成一台机器的四根内部引线,反倒顺当。对使用者来说,四路之中真正被数据化的只有一路,其余三路的存在只是说明设备如何形成判读。

3.5 受试者画像

官方给出的受试者信息分为两组。一组是纳入条件:植入 Jewel Plus ICD 7218、无起搏器、在美国与加拿大、事件发生在 1997 年 1 月 3 日之前。另一组是表格里的个体字段:性别、身高、体重、年龄、心脏病史、心律失常史、射血分数、NYHA 分级、事件时用药。

纳入条件直接框定了使用者能做的事:人数 78 例,这是有效样本量的上限,而不是总数的上限;研究原有人数 142 例,六十余例未进入最终库;设备全部为 Jewel Plus ICD 7218,单一厂商、单一型号,跨设备比较无从谈起;全部无起搏器,排除了起搏节律的干扰;地域只有美国与加拿大,属于发达国家的植入人群;事件全部在 1997 年 1 月 3 日之前,带着上一代设备的印记。

3.6 一个患者的完整档案长什么样

病例表格是库里唯一能给出「人」的部分。每一对序列在表里占一行:两侧文件名、事件日期时间、设备分类、人工分类、电图来源、备注,再加患者层面的性别、身高、体重、年龄、心脏病史、心律失常史、植入与取出日期、射血分数、用药、心功能分级。

这些字段可以按功能叠成六块。事件区块放两侧文件名、日期时间与两种分类,用来定位序列并确认配对;设备区块放植入与取出日期、有无预存,用来判断记录时段与设备代次;人口区块放性别、身高、体重、年龄,是可以直接入模的协变量;心脏区块放心脏病史、手术史与心律失常史,用来解释基线段里的提前搏动;功能区块放射血分数与心功能分级,是心功能状态的粗分类;用药区块放事件时服用的抗心律失常药,是影响发作阈值的潜在因素。

它的价值不在字段多,而在能把序列连回人。只做序列层面分析,报告里就没有任何协变量,在本库上尤其浪费。边界也要清楚:缺值记作字母 A;没有随访结局字段;没有可回溯标识,无法与登记系统对接。

§4 它最独特的东西:配对,而不是波形

4.1 为什么配对比波形更稀缺

公开心电数据很多,带室速片段的也不少,但「同一设备、同一人、一次发作加一次平时」的配对结构极罕见。原因是采集条件:配对要有能长期贴身记录、又能在两次不同场合给出可比数据的设备。监护仪只在病床边,Holter 最长二十来小时且无法标记事件,只有植入式设备做得到。

配对的好处很直接:它消掉了人与人之间差异这个最大混淆因素。比较发作段与基线段时,被比较的两段来自同一颗心脏、同一个电极位置、同一套感知参数。剩下能解释差异的,就只有时间与生理状态本身。

换个角度对照会更清楚。跨人对照不消除任何混杂,却能回答人群层面的风险因素;长时程的自身前后对照消除个体差异,代价是状态随时间漂移,只适合看缓慢演变的趋势;无对照单组几乎不解决问题,只够做描述。本库的配对设计消掉个体差异、电极位置、设备参数三项,换来的是「基线与事件时差不固定」这一条新偏倚,因此它最适合回答的,只能是发作前的节律是否异常。

4.2 案例:把一对序列摊在桌上

选 0003.vt1 及其基线 0003.mr1 作贯穿案例,理由是它落在库里最「标准」的位置:患者编号小、事件序号为 1、类别是室速、基线后缀是常规的数字而非特殊后缀。三处都没有走到边界,讲解起来不需要额外解释例外。

这一对的两侧差别,用眼睛就能看出来。基线段的间期在九百毫秒上下小幅摆动,偶有几次突然拉长到一千二百毫秒再回落的短促跳动——那是带代偿间歇的提前搏动,官方表格里称之为患者的心律失常史。捕获段的间期则从七百多毫秒起步,逐渐压到六百多,最后一段落到四百毫秒左右。

import urllib.request

base = "https://physionet.org/files/mvtdb/1.0"

def load(path):
    raw = urllib.request.urlopen(f"{base}/{path}").read().decode()
    return [int(x) for x in raw.split() if x.strip()]

vt = load("RRdata1/0003.vt1")
mr = load("mr/0003.mr1")
for name, seq in (("vt", vt), ("mr", mr)):
    print(name, "长度", len(seq),
          "均值", round(sum(seq) / len(seq), 1),
          "最短", min(seq), "最长", max(seq))

两侧的均值差在两百毫秒上下,这个差距在间期尺度上意味着心率从每分钟六十几下跳到八十多下。但真正有意思的不是均值,而是「什么时候开始变的」。中间那段「逐渐变短」是整个案例的核心:它说明进入室速不是一瞬间的跳变,而是有一个可观察的过渡(§7.2)。

import urllib.request

base = "https://physionet.org/files/mvtdb/1.0"

def load(path):
    raw = urllib.request.urlopen(f"{base}/{path}").read().decode()
    return [int(x) for x in raw.split() if x.strip()]

vt = load("RRdata1/0003.vt1")

#-- 把序列按每 128 个间期一段切分,看各段均值怎么走
step = 128
for i in range(0, len(vt), step):
    chunk = vt[i:i + step]
    print(i, len(chunk), round(sum(chunk) / len(chunk), 1))

#-- 再算一次从第几个间期起跌破了基线的九成
mr = load("mr/0003.mr1")
base_mean = sum(mr) / len(mr)
first_drop = next((k for k, v in enumerate(vt) if v < 0.9 * base_mean), -1)
print("跌破基线九成的第一个间期下标", first_drop)

输出是一条单调向下的曲线,末段最低。这条曲线本身就是这个库最想被看到的东西——设备探测的那一刻,其实已经是曲线走完大半之后的事。§4.2 的案例在后面的篇幅里还会多次被提到,因为它同时支撑三件事:配对结构的演示、事件边界的讨论、以及「预测窗口」这个说法为何难以定义。

4.3 人工分类靠的是什么,以及为什么复现不了

官方专门用一节讲分类判据。每条序列对都要把捕获段对应的心内电图与基线段的窦律电图逐项比较,比五个形态学特征。

五个特征各有取值。波形看逐搏是否同一形状,取单形、多形或多态;过基线成分数统计每个成分至少占峰峰值一成的个数,取一、二或三;初始斜率看第一个成分朝上还是朝下,取正或负;最大成分位置看最大的成分排在第几位;切迹看某个成分内部有没有凹口,取有或无。

判读规则很直接:五个特征里只要有一项与配对的窦律电图不同,就判为室速或室颤;五项全同而抗心动过速起搏后间期拉长至少六十毫秒,判为正确探测;五项全同而设备放电,判为室上速误判。

这套判据解释了分类怎么来的,短板也同样明显:判据的输入是电图,而电图不在库里。拿到数据的人无法复核某一条到底是室速还是室上速,只能接受表格里那一栏分类。这是可验证性上最大的缺口,与 §4.2 的案例那种打开文件就能自己看的体验正相反。

4.4 它支撑的四类实验

按文献用法可以归成四类。第一类是发作前征兆检测,用配对比较做前向验证,它给的是真实事件边界与对照,结论强度中等,因为样本按患者算偏小。第二类是间期序列的异常检测,不做监督,把基线当正常分布建模,它给的是干净对照段,结论强度也中等,依赖阈值设定。第三类是心率变异指标与事件的关系,逐段算指标,每段都能算时频特征,但缺独立外部验证,结论偏弱。第四类是设备探测逻辑的离线复盘,用间期重演判据,它能给事件前后的完整序列,只能复演到间期这一层。

第一类文献最多,也是被引用的主要原因。第二类适合不碰标签的研究者:把基线段当正常分布,看捕获段有多少落在尾部。第三类争议最大,心率变异指标对窗长极敏感而各序列窗长不一致。第四类是技术性用途,把真实间期喂进自研判据,看能否在同一位置触发。

4.5 与库内资源的并列定位

五种资源放在一条时间轴上,差距一目了然。本库的事件前后十余分钟、只有 RR 间期、序列级标注、含室速段,缺口是无波形;CUDB 是事件前后约八分半、单导联心电、只标室颤段起止、含室速段,缺口是无配对对照;AHA 室性心律失常库是整段三小时、双导联动态心电、逐搏多类,缺口是开放出来的量极小;MIT-BIH 心律失常库每段三十分钟、双导联心电、逐搏多类,包含室速段,缺口同样是无配对对照;CAST RR 间期子研究库接近二十四小时、只有 RR 间期、标注是结局,缺口是不含发作片段。

上表与 §6.1 的分工一致:波形与配对两件事在公开资源里从未同时出现。本库占住配对这一端,另三家占住波形这一端,CAST 则占住长时随访一端。三者的问题各不相同,任何试图用其中一份回答另一份的问题都会错位。

§5 怎么拿到:从一个文本文件到可训练的序列集

5.1 目录与体积

整库未压缩 2.5 MB,压缩包 2.6 MB。这个体积在任何按 TB 计的影像库面前都显得微不足道,但它的信息密度并不低:每一行都是一个生理事件的时间戳。按文件类拆开看,捕获段与基线段各 135 份纯文本,转换件 135 组共 270 个文件,病例表格与校验清单各一份,另有一批判据示意图。

data 目录由转换件构成,每个转换件与原始文本质子相同、表达方式不同。只做间期分析,完全不碰转换件也可以;要用现成的生理信号工具链把它们当长记录来画图,转换件更省事。

5.2 批量获取

官方给出三条路径,任选其一,都不需要登录或签署协议。

第一条是整包下载:用 curl 取压缩包再解压,适合一次拿全。第二条是递归抓取,只按后缀收文本序列,即 wget -q -r -N -c -np 配一个通配后缀;注意 *.vt? 这类写法依赖 wget 的匹配语义,不同发行版行为略有差异,更稳妥的做法是不加过滤直接抓整棵树。第三条是从公开桶同步,用 aws s3 sync --no-sign-request 指向 s3://physionet-open/mvtdb/1.0/,适合已经在用对象存储的场景。

三条路径的摩擦几乎为零,这一点与同平台需要凭证的临床波形库不同,也是它常被选作教学示例的原因之一。

5.3 建立索引

文件名是唯一的主键来源,解析它只需要按点的位置切一刀。

索引表只需要五个字段:patient 取点号前四位,是分组划分的依据;kind 取点号后两字母,判定这是捕获段还是基线段;seq 取两字母后的剩余部分,用于配对与排序;n 是逐行计数的长度,用于检查是否落在预期区间;mean 由自行计算得出,用于快速筛查异常文件。

import os
import urllib.request

base = "https://physionet.org/files/mvtdb/1.0"

def parse(name):
    pid, rest = name.split(".")
    kind = rest[:2]
    seq = rest[2:]
    return pid, kind, seq

#-- 先取两份清单,再拼成配对表
def listing(sub):
    html = urllib.request.urlopen(f"{base}/{sub}/").read().decode()
    import re
    return sorted(set(re.findall(r'>(\d{4}\.[a-z]{2}[a-z0-9]+)<', html)))

cap = listing("RRdata1")
bas = listing("mr")
pairs = {}
for name in cap:
    pid, kind, seq = parse(name)
    key = pid if kind == "vf" else pid
    pairs.setdefault(pid, []).append((kind, seq))
print("捕获段", len(cap), "基线段", len(bas), "患者", len(pairs))

配对不是「序号相同的两条」,这一点最容易想当然。官方给出的六例示例表显示,同一患者的室速与室颤各有自己的序号体系,首次室颤的基线可能是 mra 也可能是 mr1,取决于是否与首次室速的基线撞名。稳妥的做法是把同一患者的全部序列拉出来,按表格里的时间去对应,而不是靠序号猜。

5.4 形成一个可用的序列集

序列长度不一致,直接堆成张量会失败。两种处理方式:截到公共最短长度,或按固定窗长分块。前者损失信息,后者引入跨段的伪相关。

import urllib.request

base = "https://physionet.org/files/mvtdb/1.0"

def load(sub, name):
    raw = urllib.request.urlopen(f"{base}/{sub}/{name}").read().decode()
    return [int(x) for x in raw.split() if x.strip()]

cap = load("RRdata1", "0003.vt1")
bas = load("mr", "0003.mr1")
print("捕获段", len(cap), "基线段", len(bas))

#-- 取两侧各自的最后 500 个间期,长度对齐
win = 500
a = cap[-win:]
b = bas[-win:]
print("对齐后", len(a), len(b))
print("捕获段均值", sum(a) / win, "基线均值", sum(b) / win)

用末段而非首段的理由:捕获段末项正对探测时刻,取尾窗即取事件跟前;基线段末尾是随访当时的最新状态,取尾窗即取离事件最近的平时。两边都取尾部,是让比较尽量靠近事件的折中。

堆成张量后形状是固定的:第零维是序列条数,配对后取 135,不配对取 270;第一维是间期个数,500 到 1024 不等,窗长必须统一;第二维只有 1,因为只有间期这一个通道;数据类型取整数更省,浮点也只是换一种写法;整个张量压缩后不足 1 MB,可以全部常驻内存,不必分块加载。

5.5 按患者分组的评测协议

这是本库最重要的一条使用纪律:划分单位必须是患者,不是序列。理由在 §1.5 提过,这里给出具体做法。

import random

#-- 按患者划分,保证一个人的所有序列只落在一边
patients = sorted({p for p in pairs})
random.Random(20261028).shuffle(patients)
cut = int(len(patients) * 0.8)
train_p, test_p = set(patients[:cut]), set(patients[cut:])
print("训练患者", len(train_p), "测试患者", len(test_p))

八二划分落到患者层面后,两区的序列数并不相等,这是正常的:患者贡献极不平均,有的只有一对,有的十几对。报告时把五件事写清即可:样本量同时给出几例患者与几对序列,不要只写序列总数;指标先按患者聚合再平均,不要全部序列混算;划分固定随机种子并按患者切,不要按文件打乱;MRVT 与 MRVF 分别报,不要四个子集合并;置信区间按患者自助抽样,不要按序列抽。

5.6 六个最容易出错的地方

六个坑按隐蔽程度排:最隐蔽的是把 .hea 里那个整齐的一千当成采样率,它只是占位字段,间期没有采样率;最常见的是把对数当例数,按患者去重后是 78 例,数一遍编号就能发现;最危险的是按序号配对,测试时不会暴露,跑全量才会出现某几对明显错配,正确做法是查官方示例表或按时间对齐;最容易被静默吞掉的是漏收字母后缀,少数基线会消失而程序不报错;最容易被忽略的是混用四个子集,会让贡献多的患者权重被放大;最后一条是以为能拿到事件全过程,序列确实止于探测,没有终止段。

§6 与库内条目的关系

6.1 关系图谱

在心电与恶性心律失常这一类资源里,MVTDB 的位置可以由三个问题定出来:有没有波形、有没有事件前后对比、有没有逐搏标注。本库在第一个上是「没有」,第二个上是「有」,第三个上是「没有」。这三问之所以够用,是因为它们各自对应一种研究动作:有波形才谈得上形态学方法,有前后对比才谈得上发作前分析,有逐搏标注才谈得上监督学习。一个库在这三问上的答案,基本决定了它能进入哪一类论文的方法段。

各家资源在这三问上的答案,正好把谱系拉开。CUDB 是单导联连续心电、每段约八分半、标注只给室颤段的起止,含室扑与室颤,但无配对;AHA 室性心律失常库是双导联三小时动态心电、逐搏多类标注、按等级分组,开放出来的量极少;MIT-BIH 心律失常库是双导联三十分钟、逐搏多类,含室速段,是心搏分类的通用基准;INCART 心律失常库是十二导联三十分钟、逐搏多类,含室速段,优势在导联多;CAST RR 间期子研究库只有间期、时间尺度长、标注是结局,没有发作段;CHF2DB 心衰间期库同样只有间期,连事件边界都没有;VTaC 报警基准是多模态波形配双人标注,任务是判真假报警;ARGO 心内电图集有心内电图与标测图、逐点标注、包含诱发的室速,数量级比本库更小。

与 CUDB 的差别最需要说清。两者都聚焦恶性室性心律失常,都被用来做室颤相关研究,标题里也都有室性心律失常的字样。但 CUDB 给出的是连续心电,标注只分室颤段的起止,定位是「让检测算法有一个事件边界可以去撞」;MVTDB 给出的是间期,没有波形,定位是「让预测研究有一个发作前的窗口可以去看」。一个是事后确认,一个是事前试探,用途不重叠。

与 AHA 室性心律失常库 的差别在时间跨度:AHA 是每条三小时的动态心电,适合评估室性异位负荷;本库每段只有十几分钟,且落在事件前后,适合研究事件时刻的节律。

与 MIT-BIH 心律失常库 的差别是结构性的。MIT-BIH 有导联、有采样率、有逐搏标注,是心搏分类的通用基准;本库没有导联、没有采样率、没有逐搏标注,且多出一层配对设计。两者在文献里常被同一个综述提到,但从未被互换使用。

与 CAST RR 间期子研究库 和 CHF2DB 的差别在事件。三者都是「只有间期没有波形」,取数方式也一样简单,但 CAST 的事件边界是随访结局,CHF2DB 没有事件边界。若把三者拼成一份间期合集,得到的是一批没有统一事件定义的序列,反而丧失各自的设计价值。

与 VTaC 的差别在任务。VTaC 是床旁监护仪的室速报警基准,关心的是「这条报警是真是假」,输入是多模态波形;MVTDB 关心的是「发作前节律有没有变」,输入是间期。两个问题在临床上相邻,在数据上毫无交集。

6.2 检索路径

按需求找库,比按名字找库有效。要发作前的间期征兆,首选本库,没有同类可替代,判断依据是是否要求配对设计;只要室颤段起止标注,去 CUDB,次选 MIT-BIH 心律失常库,看的是标注是否只分起止;做逐搏心搏分类,去 MIT-BIH 心律失常库,次选 INCART,看的是要不要逐搏标签;评估室性异位负荷,去 AHA 室性心律失常库,次选 MIT-BIH 心律失常库,看的是有没有三小时跨度;只有间期的长时随访,去 CAST RR 间期子研究库,次选 CHF2DB,看的是要不要结局标签;判监护仪报警真假,只有 VTaC;做心内电图的电生理标测,只有 ARGO。

值得先记住的是最后一问:想同时拿到波形与配对间期,公开资源里没有现成的一份。常见的折中是拿本库做「发作前状态」的分析,再用 CUDB 或 MIT-BIH 的波形做「事件检测」,两个结果拼在一篇论文里,但两者并不是同一个人、同一台设备,不能声称端到端。

§7 质量评估与局限性

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

给这份数据打分前,必须先纠正一个错位:把它当「心电数据集」评价,再因它没有波形而扣分。这是误判。官方标题写的是序列,数据构成写的是间期,取数说明写的是毫秒整数。按心电的尺子量它不及格,按配对间期集的尺子量它有一批别处找不到的东西。

校正之后的评价标准应该换成三条:事件边界是否真实、对照是否同源、格式是否可用。三条它都站得住——边界是设备真正触发的那一刻,对照来自同一个人同一台设备,格式简单到用标准库就能读。它站不住的是另外三条:能否推到医院场景、能否支撑波形方法、能否做跨设备结论。

7.1 五维评分

按千方医数集的框架,评价分规模、结构、标注、边界、可用性五个维度。这一分层与 DAIMS(Data and AI Management Standards)的思路一致:先看数据本身,再看治理条件与使用边界,而不是只看体量。五个维度各有分工,规模问的是够不够用,结构问的是好不好切,标注问的是能不能信,边界问的是会不会越界,可用性问的是能不能上手。分开打分的意义在于,它们之间并不能互相抵偿:规模小不能靠可用性高来补,标注弱也不能靠结构齐整来补。

五维的分数是这样的:规模两分,依据是 78 例、135 对,这已是一个设备型号能给出的极限,不能算多;结构四分,配对明确、原件与转换件并存,目录简单,两套格式可选;标注两分,只有序列级类别加表格病史,无逐搏、无波形可复核;边界三分,人群与设备都窄,但边界清晰,适合做什么很明确;可用性五分,两兆多、开放、无需协议,十分钟能跑通。

五项得分不加权的话是十六分,属于中下。但这个分数只在「通用心电」这个语境下成立。换到「发作前预测」这个语境,结构与可用性的权重上升,规模与标注的权重下降,总分立刻上来。

7.2 事件边界的定义问题

库里所有序列都止于同一个物理时刻:设备首次判定进入室速或室颤。这个定义很硬,也很麻烦。

常见的四种口径各有归属。「设备探测时刻」的起点在序列末项之后,由设备程控判据定义,可复现,但随设备型号变;「室速形态起始」的起点是电图上第一个异常形态,靠人工判读,需要电图,而库内没有;「心率首次超阈值」的起点是间期首次短于某个值,由研究者自定,可得,但阈值任意;「症状出现」的起点是患者自觉,来自病史,只有部分患者有记录。

四种口径给出四个不同的「事件时刻」,彼此可差出几十秒到几分钟。所谓「提前多少秒预警」在本库上没有唯一答案,报出的提前量取决于你把哪一刻算作起点。

§4.2 的案例正是这个问题的实例。那条序列的间期在中段就开始稳步变短,如果按形态起始算,过渡段可能从序列中段就开始了;如果按设备探测算,起点在末项。同一段数据,两种口径能差出数百拍。

口径不同,写进论文的结论也会跟着变。按设备探测算,预警窗口的平均长度会偏长,因为过渡段被整段算进了「提前」;按形态起始算,窗口会短得多,也更接近临床上能观察到的起点,代价是这个起点需要电图,而本库不提供,只能由使用者用间期阈值自行近似。最稳妥的处理不是选一种口径并宣称它正确,而是明写自己用了哪一种、阈值取在哪,让后来的人能用同一口径复算。官方只给了设备探测这一种,其余三种都属于使用者的推断,这一点在写限制部分时应当说明。

7.3 已知的、可枚举的偏差

八项偏差可以分成两类。前四项由数据来源本身决定,无法从数据内部校正:设备全是同一型号码,人群全是已植入除颤器的患者,地域只有美国与加拿大,事件全部落在 1997 年之前。后四项属于选取与测量环节的痕迹:一百四十余例只留下 78 例,其排除标准未完全公开;有的患者贡献十几对序列,合并子集时会失衡;基线与事件之间的时差不固定,对照的接近程度因而参差;间期被截断到 10 ms,毫秒级差别不可恢复。

八项里只有两项能部分处理,一是按患者加权,二是用表格里的日期时间估计配对时差。用这份数据得到的任何结论,适用范围不是「心电领域」,而是「1990 年代中期、北美、已植入特定型号除颤器的高危患者」。把这句话写进限制部分,比任何技巧都管用。

7.4 外部验证矩阵

结论要往外推,得四处去试。第一处是其它 ICD 厂商的公开数据:同一套算法换个数据重跑,预期结论会明显衰减,衰减多少正是要报告的东西。第二处是 CAST 间期库:比较同类指标的分位位置,形态相似但分布不同,可作为统计口径的旁证。第三处是 CUDB 与 MIT-BIH 的波形:把间期检测与波形检测对齐,两种口径的差异会被量化出来。第四处是一般人群心电库:比较静息心率与变异水平,本库人群心率偏快、变异偏乱。

第二处与第四处最常被忽略。很多人直接把间期指标与教科书参考值对比,忘了受试者是高危植入人群,心跳本来就偏快、变异本来就偏大,用一般人群的参考值去标记异常,几乎每条都会被标出来。

7.5 它为何能持续:一份没人能替代的对照

这份数据能在平台上放将近二十年不修订,原因不是它做得好,而是它稀缺。想做「发作前与平时」的配对比较,公开资源里找不到第二份带有明确设备触发边界的间期集。自采一份同类数据,需要病人体内已经装着可读出的设备,还需要厂商点头交数据,后者几乎是不可完成的条件。

它靠的是来源上的不可复制性,而不是持续的维护投入。这也解释了版本号为何停在 1.0:没有新数据可以加,也不存在需要修订的错误被报出来。它像一块从更早时代切下来的标本,放在那里本身就够用(§8.3)。

这类资源的价值与维护工作量是脱钩的。维护投入趋于零,对使用者的价值却不随之下降,因为需要它的人要的正是那个 1990 年代的、装在特定设备里的、被触发时刻截断的窗口。任何补采都发生在今天,补不出那个年代。

§8 生态位与历史

8.1 历史沿革

1990 年代是植入式除颤器快速铺开的十年。设备能救命,但误放电的问题从第一代起就存在,厂商与医生都想找到「发作前是否有征兆」的线索。当时能做的分析只有一类:把设备里存下的间期序列拿出来,看看有没有可分辨的规律。

按阶段看,它可以切成五段。1990 年代前期是厂商内部研究,数据不出厂、结论不公开,数据正是在此阶段产生的;1997 年是数据整理与交付,原始文件在厂商内部整理完毕,文件时间戳即在此;2007 年是公共发布,经平台整理后开放,首次可被外部使用;2010 年代是方法扩散,时间序列的新方法陆续被拿来试,它由此成为标准测试样本;此后至今是小库稳定期,新方法仍要外部验证,它依旧是少数配对来源。

从 1997 年整理到 2007 年上线隔了十年。官方没有解释这段滞留,只有结果:数据进入公共视野的时间比被采集晚了十年以上。这十年恰是除颤器从单腔走向双腔、判据从简单走向形态的时期,发布时它已带有上一代设备的印记。

8.2 与后续研究的关系

这份数据在文献里出现的方式很固定:作为「发作前间期序列」的公开来源被引用,然后用一种新的时间序列方法在上面试一遍。

五个方向与它关系各异。网络化时间序列分析把它当源头,典型用法是把间期序列转成图,看连通性怎么变;心率变异与事件关系把它当参照,比较配对两侧的指标差异;机器学习预测模型拿它训练或验证,用配对结构做二分类;信号处理新方法把它当测试床,在极短序列上验证可行性;设备判据复盘是工程用途,用真实间期重演探测逻辑。

第一行有具体例子:有研究把间期序列转成带一个可调参数的规则图,逐窗算图的度,发现发作段与对照段的图度差在某窗附近出现极小值随后迅速抬升,据此提出可在发作前几十分钟看到结构变化的读法。结论建立在小样本上,作者把「回顾性」写进了结论。这说明它最典型的用法不是训练大模型,而是给新方法一个有事件边界的试验场。

8.3 生态位:一个事件窗口,而非一个人群

一句话概括:它提供的是一段窗口,不是一个群体。窗口的价值在于边界清楚,群体的价值在于覆盖全面,这份数据只有前者。

按资源定位分四类,它只落在两类上。窗口型资源要边界清楚、有对照、格式简单,它满足;人群型资源要大、有代表性,它不满足,一般人群心电库才是那一类;基准型资源要有官方划分与评分口径,它也不满足,挑战赛数据才提供这些;教学型资源要体量小、格式简单,它又满足,反倒是波形库需要专门工具才能打开。

这个定位还解释了它的所有表面特征:没有人种与地域多样性,因为窗口不在乎;没有波形,因为窗口只看时间;配对结构必须存在,因为窗口要有参照;样本量小,因为能提供窗口的设备本来就不多。它也解释了另一件事:为什么它的引用次数不算高,却在预测类论文里反复出现——研究者要的不一定是一大批数据,而是一批有事前、有事中、有平时的对照。

8.4 谁在用它,用来做什么

时间序列研究者拿它验证新方法,得到的是有边界的真实序列,障碍在样本量小。除颤器工程师拿它做判据复盘,得到的是真实设备触发前的间期,障碍在只能验间期这一层。心律失常研究者拿它找发作前征兆,得到的是配对对照,障碍在无波形佐证。教师拿它做间期与心率的演示,得到的是极简格式,障碍在缺配套练习。数据工程师拿它测流水线,得到的是纯文本与易校验,障碍在体量太小。综述作者拿它引配对设计的先例,得到的是可引用的来源,障碍在需自行核对人数。

第三类与第六类容易被低估。临床研究者引它,多为说明「发作前间期确有变化」这个前提不是凭空假设;综述作者则把它当作配对设计在心律失常数据上的早期实践来引。两种引用都不跑实验,却都依赖它存在。

§9 使用指引

9.1 三种角色的路径

三条路径的共同起点一样:取一条捕获段、取它的配对基线、把两条画在同一张图上。差别只在之后往哪走。

算法研究者的目标是做发作前预测,先读一对序列并画图确认末项位置,再按患者划分建评测,最后换一份外部数据复核。设备工程师的目标是复盘探测判据,先取捕获段末段间期,再用自家判据重演触发,最后与设备实际触发位置比对。教学者的目标是讲清楚间期是什么,先取一条序列画折线,再对比配对两侧,最后让学生各自标事件起点。

读反了末项位置,后面全倒;判据不重演一遍,就不知道设备何时提前或滞后触发;学生各自标出的起点不同,恰说明事件起点是口径问题而非事实问题。

三条路径在时间投入上差别很大。第一条要跑完整评测,动辄以天计;第二条只需一段捕获段,一小时能出结论;第三条更快,取一对画出来就能开讲。投入不同,交付物也不同:第一条交指标表,第二条交判据与真实触发的偏差,第三条交一份标注分歧清单。三者共用同一份数据,却几乎不会互相踩到,这也是小库的好处之一——它小到可以在一门课、一个下午、一次组会里被完整走一遍。

三条路径共享的那个起点,正是 §4.2 的那一对序列。换一对也行,只要它落在标准位置上,同样的流程一样能跑通。

9.2 一条最短的可用流程

从零到一张能放进报告的图,最短是五步。

import urllib.request
import statistics

base = "https://physionet.org/files/mvtdb/1.0"

def load(sub, name):
    raw = urllib.request.urlopen(f"{base}/{sub}/{name}").read().decode()
    return [int(x) for x in raw.split() if x.strip()]

#-- 1 取一对
cap = load("RRdata1", "0003.vt1")
bas = load("mr", "0003.mr1")

#-- 2 把间期换算成瞬时心率(次/分)
def hr(seq):
    return [round(60000.0 / v, 1) for v in seq]

hc, hb = hr(cap), hr(bas)

#-- 3 分四段看走向
def quartiles(seq):
    k = len(seq) // 4
    return [round(statistics.mean(seq[i * k:(i + 1) * k]), 1) for i in range(4)]

print("捕获段四段均值", quartiles(cap))
print("基线段四段均值", quartiles(bas))

#-- 4 心率对照
print("捕获段平均心率", round(statistics.mean(hc), 1))
print("基线段平均心率", round(statistics.mean(hb), 1))

输出的关键在那行四段均值:单调下降说明事件有过渡,突然跳变说明是骤发。两种形态临床意义不同,本库足够看出两者都存在,却不足以说哪一种更常见。

import urllib.request
import statistics

base = "https://physionet.org/files/mvtdb/1.0"

def load(sub, name):
    raw = urllib.request.urlopen(f"{base}/{sub}/{name}").read().decode()
    return [int(x) for x in raw.split() if x.strip()]

#-- 在一对序列上算相邻间期的绝对差,看节律的粗糙度
for sub, name in (("RRdata1", "0003.vt1"), ("mr", "0003.mr1")):
    seq = load(sub, name)
    d = [abs(seq[i + 1] - seq[i]) for i in range(len(seq) - 1)]
    print(name, "平均绝对差", round(statistics.mean(d), 1),
          "中位数", statistics.median(d))

两段代码跑完,报告里大抵会放四样东西:一条折线图,一条配对对照的均值或中位数,一个可交代的事件起点口径,以及一句关于样本量的说明。四样都不复杂,难点始终在第一样之后——你得说清自己把哪一刻算作事件起点,否则「提前多久」这个数字没法被别人复算。

相邻间期差是一个极简的节律粗糙度指标。它的好处是只看局部,不被整体长度影响,所以配对两侧即使长度不同也能比较。坏处同样明显:它对偶尔出现的提前搏动极其敏感,一次代偿间歇就能把均值拉高很多。§4.2 的案例里,基线序列就夹着若干次这样的搏动,如果用均值做比较,会误以为基线也不稳。

9.3 引用方式

引用的写法分三层。第一层是数据集本身,写全称加版本加提供方,即 Spontaneous Ventricular Tachyarrhythmia Database Version 1.0 from Medtronic, Inc.;第二层是位置,给出官方项目 URL,要可解析;第三层是平台,按 PhysioNet 的标准引用格式附上平台综述论文。许可一层注明 ODC-BY 1.0 与署名要求。

官方另有一条使用要求:不得改动数据或心律分类。这属于使用纪律而非法律条款,ODC-BY 本身允许改动,但改过之后不宜再沿用原名,目的是让不同文献之间保持可比。

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

报告出稿前,先过三道数目核对。第一道是条数:捕获段与基线段各 135 条,少了就说明抓取时漏了字母后缀,正则要把 mra 一并认下,否则配对表里会出现有发作没对照的空洞,而代码不报错。第二道是长度:捕获段全部为 1024,基线段落在 986 到 1022 之间,两个数对调通常意味着目录读反了。第三道是人数:按患者编号去重后应有 78 例,只统计捕获段会得到同一个数,但只统计某一子集就会偏少。

三道都对上,再谈指标。数目对不上的报告,指标再漂亮也不可信。

§10 AI 使用声明

本页由人工智能辅助撰写,事实与表述经人工校核,依据只有官方项目页、目录列表、头文件与抽样文件内容、以及论文摘要。未下载整库做分布统计,未做频次或空值分析;数字口径以官方为准,官方内部不一致处并列两口径,不确定处标注「官方未公布」或「工作描述」。封面图由生成模型按风格提示词产出,不含真实数据。

常见误读(避坑清单)

说法 实际 证据
MVTDB 是 MIT-BIH 的变体 旧命名 M 指美敦力,与 MIT-BIH 库无关 官方提供方为 Medtronic
它是心电波形库 全库只有 RR 间期,无任何波形 官方数据描述只提间期序列
有 135 名患者 78 例患者、135 对序列 官方两处数字口径不同
每个患者只有一对 MultiVT 与 MultiVF 专收更早事件 四个子集的划分定义
序列能看到事件终止 捕获段止于首次探测 官方对缓冲快照的说明
.hea 里的 1000 是采样率 是占位字段,间期无采样率 头文件三处 0 与 1000
间期精确到毫秒 截断到 10 ms 的整数倍 官方对截断的说明
有逐搏诊断标签 只有序列级类别与表格病史 目录中无逐搏注释
可以按序列随机划分 同一患者多条序列会泄漏 官方对合并子集的提醒
人工分类可以直接复核 判据的输入电图不在库里 官方分类判据与文件构成

FAQ

问 答 出处
MVTDB 里的 MVT 怎么展开? 官方全名里没有这三个连续字母。按旧命名惯例理解为 Medtronic Ventricular Tachyarrhythmia Database,M 指提供方,VT 才是室速。它与 MIT-BIH 心律失常库不是同一份数据。 §1.1、§3.1
有多少患者、多少条记录? 78 例患者,135 对序列,共 270 条序列。捕获段与基线段各一半,每对一一对应。患者数与序列对数不是同一个量,做统计时报前者更能反映有效样本量。 §2.4
里面有心电图吗? 没有。全库只有 RR 间期数值。设备取回快照时确实附带几秒高分辨率心内电图,但官方说明这些电图不收录在库内。 §2.1、§3.3
每条序列多长? 捕获段固定 1024 个间期,基线段在 986 至 1022 之间,约合十二到十六分钟。官方没有给每条序列的起始钟点。 §2.3
为什么基线段不到 1024 个? 随访取数时缓冲最近端的若干间期在读取中丢失,数量不固定,缺口是读取环节留下的。 §6.1
能不能拿它训练波形模型? 不能。库里没有任何采样信号,头文件里的 1000 是占位而非采样率。基于波形的方法在此没有输入。 §1.5、§5.6
可以商用吗? 可以。ODC-BY 1.0 允许商用,需署名,并写作带版本与提供方全称的引用形式。 §9.3
能改成自己的格式再分发吗? 许可允许改动,但官方要求不要改动数据与心律分类,以便文献间保持可比。 §9.3
它和 CUDB 有什么区别? CUDB 是连续心电、只标室颤段起止;本库是间期、无波形、有配对对照。一个做检测,一个做发作前分析。 §6.1
适合当教学材料吗? 适合入门,格式是最简单的文本一列整数。缺点是没有配套练习,事件起点的定义要讲清。 §9.1
四个子集该怎么用? 主结论用 MRVT 与 MRVF,两者各患者最多一对,接近独立;另两个子集适合做补充分析。 §2.4
事件起点怎么定义? 官方只给了设备探测时刻,即序列末项。按形态起始需要电图,而电图不在库里,只能自定阈值口径。 §7.2

术语表

术语(英文) 在本库中的含义
RR 间期(RR interval) 相邻两次心室除极之间的时间,本库唯一变量
室性心动过速(VT) 起源于心室的快速心律,记作 vt
心室颤动(VF) 心室无序颤动的致死性心律,记作 vf
基线序列(most recent) 随访时取回的近期节律,记作 mr
序列对(sequence pair) 捕获段与其基线段的组合,共 135 组
植入式心律转复除颤器(ICD) 能探测并电击终止恶性心律的植入设备
心内电图(intracardiac electrogram) 电极直接记录的心电,本库不提供
感知放大器(sense amplifier) 自动调整阈值以检出 R 波的电路
环形缓冲(circular buffer) 不断覆写的固定容量存储区,容量 1024 格
快照(snapshot) 触发时存下的缓冲内容,止于首次探测
程控仪(programmer) 与植入设备通讯并读取数据的桌面设备
探测判据(detection interval) 判定心动过速的间期阈值,满足即存快照
抗心动过速起搏(ATP) 用快速起搏终止室速的疗法
室上性心动过速(SVT) 起源在心室以上的快速心律,常被误判
单形、多形、多态 依次指逐搏同形、形态逐搏变化、至少两种可分辨形态
切迹(notching) 波形成分内部的凹口,形态判据之一
截断(truncation) 间期向下取整到 10 ms,非四舍五入
射血分数与 NYHA 分级 心功能的两项指标,只出现在病例表格里
配对设计与患者级划分 前者是同源两段互照,后者按患者切分训练与测试
外部验证(external validation) 在另一份数据上复核结论

附录 A:核心数字核对表

下表把本页用到的关键数字集中列出,每一项都注明来源位置与来源层级,便于逐条回查。层级口径与附录 B 一致:标注「官方」的可以直接引用,标注「推导」的需自行复算,标注「工作描述」的属于推断。

项 值 来源 来源层级
患者数 78 官方数据描述段 官方
研究总人数 142 官方数据采集段 官方
序列对数 135 官方摘要句 官方
捕获段长度 1024 官方缓冲说明与抽样核对 官方
基线段长度 986 至 1022 官方数据描述段 官方
子集 MRVT 58 官方子集表 官方
子集 MRVF 25 官方子集表 官方
子集 MultiVT 48 官方子集表 官方
子集 MultiVF 4 官方子集表 官方
间期粒度 10 ms 官方截断说明 官方
心内电图通道 4 官方数据描述段 官方
设备型号 Jewel Plus ICD 7218 官方数据描述段 官方
采集截止日 1997-01-03 官方数据采集段 官方
发布日期 2007-05-02 官方页面 官方
版本 1.0 官方页面 官方
许可 ODC-BY 1.0 官方页面 官方
DOI 10.13026/C25K5D 官方页面 官方
未压缩体量 2.5 MB 官方文件区 官方
压缩包体量 2.6 MB 官方下载区 官方

附录 B:数字的来源分层

官方页面一层,是项目页正文与文件区直接给出的,包括患者数、序列对数、子集划分、体量、版本、许可与 DOI。官方文件一层,来自抽样读取的序列、头文件与目录列表,包括捕获段 1024 行、基线段行数、头文件三处占位。论文摘要一层,是引用本库的方法类论文,包括回顾性预警窗口的说法与其作者。推导一层,由官方数字直接换算,包括序列时长、心率换算与内存占用。工作描述一层,依生理常识写出、官方未逐条说明,包括单形与多形的临床含义、事件过渡的三种形态。

前两层可以直接引用;第三层用于说明研究背景;第四层可复算;第五层必须标注为推断,不能当作结论。

分层的用处在于,看到任何一个数字时都能知道它有多硬。官方页面给的数最硬,因为它同时出现在正文与文件区;官方文件里抽样核到的次之,因为它依赖抽样的时机;论文摘要里的说法要转述,因为它的口径属于那篇论文;推导出来的数可以复算,算错能查;工作描述最软,写它是为了让定义能读通,而不是为了断言生理事实。写限制部分时,把属于第五层的句子挑出来,通常能省下不少返工。

前两层可以直接引用;第三层用于说明研究背景;第四层可复算;第五层必须标注为推断,不能当作结论。

附录 C:完整参考文献

序号 文献 用途
1 Medtronic, Inc. Spontaneous Ventricular Tachyarrhythmia Database, Version 1.0. PhysioNet, 2007. DOI 10.13026/C25K5D. 官方数据页与数据描述
2 Pearson AM, Olson WH. 数据库原始说明文字,收录于上述官方页面。 采集链与分类判据的出处
3 Zamudio GS, Márquez MF, José MV. Anticipation of ventricular tachyarrhythmias by a novel mathematical method. PLOS ONE, 2020. 引用本库的典型方法类研究
4 Kolk MZH, et al. Machine learning of electrophysiological signals for the prediction of ventricular arrhythmias. eBioMedicine, 2023. 该方向的系统性回顾背景
5 Pollard T, et al. PhysioNet as a global platform for biomedical research. Nature Health, 2026. 平台引用
6 Goldberger A, et al. PhysioBank, PhysioToolkit, and PhysioNet. Circulation, 2000. 平台与格式背景
7 Swarna US, Callans DJ, Schwartzman D, Gottlieb CD, Marchlinski FE. 右室心内膜电图区分室速形态的研究。 官方页面列出的形态判读依据

附录 D:任务代码

一段把四个子集理清、按患者分组、输出配对摘要的脚本。

import re
import urllib.request
import statistics

base = "https://physionet.org/files/mvtdb/1.0"

def listing(sub):
    html = urllib.request.urlopen(f"{base}/{sub}/").read().decode()
    return sorted(set(re.findall(r'>(\d{4}\.[a-z]{2}[a-z0-9]+)<', html)))

def load(sub, name):
    raw = urllib.request.urlopen(f"{base}/{sub}/{name}").read().decode()
    return [int(x) for x in raw.split() if x.strip()]

cap = listing("RRdata1")
bas = listing("mr")
print("捕获段", len(cap), "基线段", len(bas))

#-- 按患者归组
by_pid = {}
for n in cap:
    by_pid.setdefault(n.split(".")[0], {"vt": 0, "vf": 0})[n.split(".")[1]] += 1
print("患者数", len(by_pid))

#-- 取第一个有室速事件的患者做一次配对摘要
pid = sorted(p for p in by_pid if by_pid[p]["vt"] > 0)[0]
vt_name = f"{pid}.vt1"
mr_name = f"{pid}.mr1"
a = load("RRdata1", vt_name)
b = load("mr", mr_name)
print(pid, "捕获段", len(a), "基线段", len(b))
print("捕获段均值", round(statistics.mean(a), 1))
print("基线段均值", round(statistics.mean(b), 1))
print("比值", round(statistics.mean(a) / statistics.mean(b), 3))

脚本最后打印的比值是一个粗糙但直观的指标:捕获段间期越短,比值越小,心率越快。它不能替代任何正式统计,只适合在开工前扫一遍数据是否读对了。

附录 E:如果只记五件事

如果只留五行,就留下面这张表。它回答的是五个最容易在一句话里说错的问题:谁给的、有什么、缺什么、最适合干什么、最容易被误用成什么。

序 要点 一句话
1 它是谁的 美敦力交给平台的一批植入设备缓冲快照
2 它有什么 78 例患者、135 对 RR 间期,无波形
3 它缺什么 无心电图、无逐搏标签、无事件终止段
4 它最适合 发作前间期征兆研究、配对对照分析
5 它最容易被误用 把序列当独立样本,或把它当心电波形库

五条里第一至第三条属于事实,第四、第五条属于判断。事实部分可以逐条回到官方页面核对;判断部分取决于研究目的,换一个语境,第四条就可能改写。比如在教学场景里,它最适合的其实是「用最简单的格式讲清 RR 间期是什么」,而不是发作前征兆研究。

编辑说明

本页事实以 PhysioNet 官方项目页 1.0 版为准,辅以目录列表与抽样文件内容的核对。凡官方未公布的项,均标注为未公布;凡依生理常识写出的解释,均标注为工作描述。正文未做分布统计,未下载整库做二次分析,抽样只读了少数几个文件的头部几行与行数。

命名上的两处不一致已按官方原文并列处理:同时有室速与室颤的患者,数据描述段写五例,子集划分段的示例表列了六例;两者指向的口径可能不同,差额构成官方未说明。序列时长是从间期均值推算的,官方未直接给出分秒数。

页面中反复出现的 0003.vt1 与 0003.mr1 是贯穿案例,首次出现在 §2.3,并在 §4.2、§7.2、§9.2 等处回指。选择它是因为患者编号小、序号为 1、类别为标准室速、基线后缀为常规数字,四处都不落在例外上。


相关数据集导航

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

  • wctecgdb — 共享标签:生理信号 / 心电信号 / 心血管疾病
  • ahadb — 共享标签:生理信号 / 心电信号 / 心血管疾病
  • chfdb — 共享标签:生理信号 / 心电信号 / 心血管疾病
  • crisdb — 共享标签:生理信号 / 心电信号 / 心血管疾病
  • cudb — 共享标签:生理信号 / 心电信号 / 心血管疾病
  • ltdb — 共享标签:生理信号 / 心电信号 / 心血管疾病
  • ltstdb — 共享标签:生理信号 / 心电信号 / 心血管疾病
  • iafdb — 共享标签:生理信号 / 心电信号 / 心血管疾病
  • nsrdb — 共享标签:生理信号 / 心电信号 / 心血管疾病
  • stdb — 共享标签:生理信号 / 心电信号 / 心血管疾病

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

返回 AI-Ready 数据集