信息速览
2015 年 5 月 19 日,PhysioNet 上线了一份来自那不勒斯的数据库,缩写 SHAREE,全名 Smart Health for Assessing the Risk of Events via ECG Database。它收的是 139 名高血压患者的动态心电:每人一段名义 24 小时的三导联 Holter,128 Hz 采样,8 位精度,三份文件平铺在一个目录里。
这份数据真正稀缺的地方不在心电,而在心电之后的那一年。患者在停用降压药一个月后被记录,随后进入随访,其中 17 人发生了心肌梗死、卒中或晕厥,由高血压中心的事件裁定委员会逐例判定成标签。二十四小时的 Holter 到处都有,带着裁定结局的 139 条并不多。
决定它能不能用的是三件事:三个导联加 128 Hz、8 位精度,只够算节律不够看形态;QRS 标注由算法生成且未经人工校正;阳性只有 17 例,任何分层模型都在这个数字上做文章。一屏速览见下表。
| 维度 | 内容 |
|---|---|
| 官方全名 | Smart Health for Assessing the Risk of Events via ECG Database |
| 缩写 | SHAREE;所属项目名 SHARE(Smart Health and Artificial intelligence for Risk Estimation) |
| 发布平台 | PhysioNet,Database Open Access |
| 版本与日期 | 1.0.0,2015 年 5 月 19 日,此后未再改动 |
| DOI | 10.13026/C2RC7C |
| 作者 | Paolo Melillo、Raffaele Izzo、Ada Orrico、Paolo Scala、Marcella Attanasio、Marco Mirra、Nicola De Luca、Leandro Pecchia |
| 机构 | 那不勒斯第二大学、意大利教育大学科研部 SHARE 项目、费德里科二世大学、华威大学 |
| 数据来源 | 费德里科二世大学医院高血压中心 |
| 患者 | 139 名高血压患者,49 女 90 男 |
| 年龄 | 55 岁以上;官方写作 72 - 7 岁,应为 72±7 |
| 记录 | 每条名义 24 小时,三导联 III、V3、V5 |
| 采样与精度 | 128 Hz,8 位,增益 35(-5)/mV |
| 结局 | 随访期内 17 人发生事件:11 例心肌梗死、3 例卒中、3 例晕厥 |
| 附带信息 | info.txt 一张表,十四列人口学、血压、超声与结局 |
| 标注 | WQRS 算法生成,未经人工校正;标注者文件写作 qrs unaudited |
| 体积 | 未压缩 4.1 GB,压缩包 1.7 GB |
| 许可 | ODC-By 1.0,开放获取,须署名 |
| 资助 | PON04a3_00139,2007 至 2013 年国家研究竞争力计划 |
§1 它要解决的具体麻烦
1.1 二十四小时的心电遍地都是,带结局的很少
心率变异性与血管事件有关联,这在文献里早就有共识。难的是把它变成能用的预测工具:同一段 Holter,用不同的指标、不同的窗长、不同的算法,算出来的风险排序可以完全不同。要判断哪一种算法真的有效,需要一份同时具备三样东西的数据——足够长的连续心电、足够完整的人口学与超声协变量、以及一个不由算法而是由人判定的结局。
第三样最难凑。二十四小时动态心电在医院里是常规检查,一年做几十万例,但做完之后患者就散了,谁在半年后心梗、谁在一年内卒中,很少有人回头逐例追。要追,就得有随访团队、有全科医生配合、有一个能翻病历的裁定委员会。这部分成本远高于记录本身。
SHAREE 的立项理由就落在这上面。官方摘要的原话是「investigate the possibility to identify hypertensive subjects at higher risk to develop vascular events based on Heart Rate Variability analysis」,翻过来就是:用这批人,检验心率变异性到底能不能把高风险者挑出来。它不是为了做一份更大的心电库,而是为了给这个问题准备一份带答案的卷子。
这也解释了它的规模为什么不大。139 人在动态心电的尺度上不算多,但要给每一个人配上十二个月的随访、一次心脏超声、一次颈动脉超声、一张包含十四个字段的临床表,139 就是一个团队能扛住的量级。
1.2 三条常见的错误期待
第一条是把 SHAREE 想成可穿戴数据。名字里有 Smart Health,项目又挂着预防老年人跌倒与心血管事件的旗号,很容易让人以为是腕带或贴片采的连续监测。实际不是:它是门诊 Holter,患者到医院戴机、回家过一天、第二天回院拆机。没有加速度计,没有光电容积脉搏波,没有睡眠分期,也没有连续血压。想拿它做活动识别或睡眠研究,一样都用不上。
第二条是把它当诊断级心电。三个导联是 III、V3、V5,配 128 Hz 采样与 8 位量化。这套配置对 R 峰定位是够的——128 Hz 意味着每个采样点之间约 7.8 毫秒,正常窦性节律下足够把 R-R 间期算到毫秒级的近似——但对 ST 段抬高、T 波电交替、QRS 碎裂这类形态学特征就不够了。它是节律数据,不是形态数据。
第三条是以为下载下来就有一张特征表。库里只有原始波形、头文件、标注文件,加一张十四列的临床表。心率变异性指标一个都没有现成的,得自己从 R 峰序列算。而算哪几个指标、用多长的窗、要不要去掉异位搏动,每一个选择都会改变最终的风险排序,官方没有替你定。
三条期待指向同一个动作:把「有一份带结局的心电」听成「有现成的风险模型素材」。补上三个前提——它是 Holter 不是腕带、是节律不是形态、是原料不是成品——期待就会回落到它实际的位置。
1.3 它能给到的与给不到的
把需求拆成行逐条对照,比通读摘要更快判断该不该选它。
| 你的需求 | 它给的 | 够不够 |
|---|---|---|
| 长时程心电上算心率变异性 | 名义 24 小时连续三导联 | 够,且是这批人里最完整的一段 |
| 有硬终点的二分类标签 | 17 例事件,裁定委员会判定 | 够做可行性,不够做稳健评估 |
| 心血管危险因素的协变量 | 血压、体质量指数、吸烟、左室质量指数、内膜中层厚度、射血分数 | 够,覆盖主要传统因素 |
| 十二导联形态学分析 | 只有 III、V3、V5 | 不够 |
| 心律失常的逐搏人工标注 | 算法标注,未校正 | 勉强,须自行复核 |
| 房颤、室早等节律事件标签 | 官方未提供 | 不够,须自己检测 |
| 连续血压或呼吸信号 | 无 | 不够 |
| 用药与合并症明细 | 只写了停药一个月 | 不够 |
| 健康对照人群 | 无,全部是高血压患者 | 不够 |
| 跨种族、跨中心的外部验证 | 单中心意大利人群 | 不够 |
前四行是它能直接满足的,中间三行是要打折的,最后三行是明确给不了的。分界不在难度,而在数据类型:凡是从三导联波形与那张临床表能推出来的,它大体撑得住;凡是要靠其他通道、其他人群、其他时间点的,一律没有。
1.4 你的处境与它能帮到的事
下面这张表按处境组织,不按特性组织。左列是你眼下的状态,中列是它能帮上的部分,右列是接下来该做的一步。
| 你的处境 | 它能帮你什么 | 下一步该做什么 |
|---|---|---|
| 想验证某个心率变异性指标有没有预后价值 | 139 人、17 例事件的现成配对 | 先按患者切分做基线模型,再谈提升 |
| 手上只有健康人数据,缺带结局的对照 | 全部为高血压患者,风险谱集中 | 把它当阳性富集集,另找健康队列做参照 |
| 需要一份小到能塞进笔记本的 Holter 库 | 压缩后 1.7 GB,无子目录 | 先拉 RECORDS 与 info.txt,几十 KB 就能开工 |
| 做动态心电的 QRS 检测算法比较 | 算法标注在同一套文件里,可当弱参考 | 先人工核一段,量出标注本身的错误率 |
| 想研究停药前后的血压与心率关系 | 记录时处于停药一个月后的状态 | 把它明确定义为未治疗状态,不要外推到服药人群 |
| 需要多导联形态学做心肌缺血识别 | 只有三个导联 | 换十二导联库,这里只能做节律 |
| 项目要求可商用且零法律负担 | ODC-By 1.0 只要求署名 | 读一遍许可原文,把署名写进产品说明 |
1.5 一句话判断
它是一份用十二个月随访换来标签的二十四小时心电,规模小到只能做可行性研究,标签硬到能当基准用;把它当大数据会失望,把它当带答案的卷子会合用。
1.6 不适合谁:四条边界
第一条是追求样本量的深度学习项目。139 人、17 例阳性,任何患者级划分的测试集里最多只有三到四个事件。在这种规模上训练一个上万参数的模型,得到的不是性能而是拟合噪声的能力。想靠滑动窗口把样本数刷上去,就会踩到另一条更严重的错误——同一名患者的窗口同时出现在训练与测试两侧。
第二条是需要诊断级波形的项目。三个导联、128 Hz、8 位精度,对心肌缺血的 ST 段分析、对束支阻滞的形态判读、对早搏的定位,信息量都不够。它是节律数据的底子,不是形态数据的底子。
第三条是需要多病种、多中心外部验证的项目。全部患者来自那不勒斯一家医院的高血压中心,全部是意大利人,全部是停药后的高血压状态。跨中心的泛化能力无法从这份数据内部估计。
第四条是需要即用型管线的工程团队。库里没有特征表、没有基线模型、没有划分脚本,标注还要自己复核。从下载到第一张可解释的结果表,中间隔着一段不短的工程。
§2 数据构成与规格
2.1 一个扁平目录与三类文件
整个库没有子文件夹。139 条记录、每条约三份文件,加五个顶层辅助文件,全部平铺在同一层。这种结构在 PhysioNet 的老库上很常见,好处是路径简单,坏处是一旦解压到已有文件的目录里,几百个同名格式的文件会混在一起。
| 文件类型 | 角色 | 单件体积 | 是否必需 |
|---|---|---|---|
.dat |
三导联二进制波形 | 约 29.5 MB | 必需 |
.hea |
文本头文件,声明通道、采样率、增益 | 约 150 字节 | 必需,缺了无法解析波形 |
.qrs |
QRS 位置标注 | 数百 KB | 可选,但算心率变异性时几乎必需 |
RECORDS |
记录清单,一行一个记录号 | 834 字节 | 必需,用来遍历 |
info.txt |
临床信息表,制表符分隔 | 8 KB | 必需,标签全在这里 |
ANNOTATORS |
标注者定义 | 31 字节 | 说明用 |
README |
文字说明 | 3.3 KB | 说明用 |
SHA256SUMS.txt |
校验和 | 30.9 KB | 下载后核对用 |
.dat 与 .hea 的体积极不相称,这件事本身就说明数据的形状:一个 150 字节的文本文件,负责解释一个 29.5 MB 的二进制文件。头文件写错一个字符,整条记录就读不出来,而它恰恰是最容易被解压工具当成垃圾文件删掉的那一类。
2.2 字段与记录字典
库里的信息分两层。波形层由头文件声明,临床层由 info.txt 承载。两张表靠记录号连起来。
| 字段 | 所在 | 含义 | 取值或单位 |
|---|---|---|---|
| 记录号 | 头文件首行、文件名、清单 | 唯一标识 | 五位数,首位补零,如 01911 |
| 通道数 | 头文件首行第二字段 | 信号路数 | 固定 3 |
| 采样率 | 头文件首行第三字段 | 每秒采样点数 | 固定 128 |
| 每通道样本数 | 头文件首行第四字段 | 该通道总点数 | 八位数,随记录变化 |
| 起始时刻 | 头文件首行第五字段 | 记录开始时间 | 时:分:秒 |
| 增益 | 头文件通道行 | 数字量到毫伏的换算 | 35(-5)/mV |
| 精度 | 头文件通道行 | 量化位数 | 8 |
| 导联名 | 头文件通道行末列 | 通道对应的导联 | III、V3、V5 |
| 性别 | info.txt | 患者性别 | M 或 F |
| 年龄 | info.txt | 记录时年龄 | 岁,整数 |
| 体重 | info.txt | 千克 | 整数 |
| 身高 | info.txt | 厘米 | 整数 |
| 体表面积 | info.txt | 平方米 | 两位小数 |
| 体质指数 | info.txt | 千克每平方米 | 两位小数 |
| 吸烟 | info.txt | 是否吸烟 | yes 或 no |
| 收缩压 | info.txt | 毫米汞柱 | 整数 |
| 舒张压 | info.txt | 毫米汞柱 | 整数,表头误写作第二个 SBP |
| 最大内膜中层厚度 | info.txt | 毫米 | 一位小数,部分为 n/a |
| 左室质量指数 | info.txt | 克每平方米 | 整数,部分为 n/a |
| 射血分数 | info.txt | 百分比 | 整数,部分为 n/a |
| 结局 | info.txt | 随访期内事件 | none 或事件名 |
表头这一处值得单独说:info.txt 的列名里出现了两个相邻的 SBP,而表尾的字段说明里依次解释了 sBP 与 DBP。也就是说,第二列实际是舒张压,列名写错了一次。这不是数据错误,是表头错误,读表时按位置取不会出问题,按列名取就会把舒张压读成收缩压。
2.3 一条记录的完整解剖
拿编号 01911 的记录看一遍,结构就清楚了。头文件只有四行,每行都是空格分隔的固定字段。
01911 3 128 10322048 12:20:53
01911.dat 80 35(-5)/mV 8 0 0 -5979 0 III
01911.dat 80 35(-5)/mV 8 0 10 18199 0 V3
01911.dat 80 35(-5)/mV 8 0 20 26498 0 V5
首行五个字段:记录名、通道数 3、采样率 128、每通道样本数,以及记录开始的时刻。后三行是三个通道,前两列指向同一个二进制文件,格式码 80 表示 8 位,增益写作 35(-5)/mV,末列是导联名。三个通道交错存放在一个文件里,所以三行的文件名相同、只是通道顺序不同。
样本数除以采样率,就是这条记录的真实时长。10322048 除以 128 得 80641 秒,约 22.4 小时。换成编号 02012 的记录,样本数是 10967168,除以 128 得 23.8 小时。两条都在官方所说的名义 24 小时附近,但都不足 24 小时——「名义」这个词是准确的,实际长度由每个患者的佩戴与拆机时间决定。
shareedb-1.0.0/
01911.dat 01911.hea 01911.qrs
02012.dat 02012.hea 02012.qrs
02019.dat 02019.hea 02019.qrs
#-- 其余 136 条记录,命名同理,三条一组
RECORDS ANNOTATORS README info.txt SHA256SUMS.txt Figure1.jpg
目录这一层没有玄机,但有两个细节会影响脚本。第一,记录号在文件名里是五位数,01911 而不是 1911;第二,info.txt 里的记录号是去掉前导零的整数。两张表要连起来,必须先统一位数。
2.4 三种口径与一处差额
同一件事在官方文字里有三种说法,各有各的用途,混用会出错。
| 口径 | 说法 | 用途 | 与另一种口径的关系 |
|---|---|---|---|
| 时长 | 名义 24 小时 | 描述规模 | 按样本数换算普遍略短,如 22.4 小时 |
| 随访 | 12 个月 | 定义标签窗口 | 论文摘要写作「至少 12 个月」 |
| 标注后缀 | .qrs |
页面正文写法 | README 写作 .wqrs0 |
| 体积 | 未压缩 4.1 GB | 规划磁盘 | 压缩包 1.7 GB,比例约二点四比一 |
| 人数与记录数 | 139 与 139 | 一对一的对应 | 清单行数与信息表数据行数一致 |
标注后缀这一处是真实存在的两个口径。官方页面正文写「Annotation files (with the suffix .qrs)」,同一份材料的 README 写「with the suffix .wqrs0」,而目录里实际的文件是 .qrs。三个来源、两种写法,本篇只并列表述,不判断哪一个对;下载后以目录里的实际后缀为准即可。
随访时长这一处同样值得留意。页面写「followed up for 12 months」,论文摘要写「followed up for at least 12 months」。前者是一个固定的观察窗,后者允许有人被观察得更久。对建模的影响很直接:如果实际随访长度不一,那么同样标为阴性的人,被观察的时间并不相同,严格来说应当做生存分析而不是二分类。
2.5 与同类资源的规格差异
把这份数据放进长时程心电的谱系里,它的位置很清楚:时程最长,通道最少,标签最硬。
| 资源 | 时程 | 导联 | 采样 | 结局标签 |
|---|---|---|---|---|
| SHAREE | 名义 24 小时 | 3 | 128 Hz / 8 位 | 有,随访裁定 |
| 常见心律失常 Holter 库 | 十小时级 | 2 | 250 Hz / 12 位 | 无,只有节律标注 |
| 短片段诊断库 | 十秒级 | 12 | 500 Hz / 16 位 | 无,或只有诊断结论 |
| 重症监护波形库 | 数小时至数天 | 2 至 5 | 125 至 500 Hz | 有,院内结局 |
| 消费级腕带数据 | 数天至数月 | 单通道 | 25 至 250 Hz | 多为自报 |
横向比采样率,它排在末位;纵向比时程与标签的组合,它排在前列。这种形状决定了它的用法:不是拿来做信号质量的基准,而是拿来做「长时程节律与远期结局」的关联研究。任何需要看波形细节的任务,都不该从它起步。
§3 它是谁的数据:一个高血压门诊与一次停药
3.1 八位作者与四处署名
作者八人,署名机构四处。前两位作者同属那不勒斯第二大学与 SHARE 项目,中间几位来自费德里科二世大学转化医学系,最后一位来自华威大学工程学院。
| 作者 | 署名机构 | 署名性质 |
|---|---|---|
| Paolo Melillo | 那不勒斯第二大学;SHARE 项目 | 双署名,列首位 |
| Raffaele Izzo | 费德里科二世大学转化医学系 | 大学医院 |
| Ada Orrico | 那不勒斯第二大学;SHARE 项目 | 双署名 |
| Paolo Scala | SHARE 项目 | 项目方 |
| Marcella Attanasio | SHARE 项目 | 项目方 |
| Marco Mirra | 费德里科二世大学转化医学系 | 大学医院 |
| Nicola De Luca | 费德里科二世大学转化医学系 | 大学医院 |
| Leandro Pecchia | 华威大学工程学院 | 境外工科 |
署名结构是典型的「医院出病人、工科出方法」。费德里科二世大学的转化医学系承担招募、记录与随访,华威大学的工程学院与项目方的工程人员承担特征与分类器。这一点也解释了临床侧为什么比工程侧厚:十四个字段里有六个是超声与血压指标,而波形只有三个导联。
Melillo 与 Orrico 同时挂大学院系与 SHARE 项目,是两个体系之间的接口。README 给出的联系人也正是 Melillo 与 Pecchia 两位,一位在医学院,一位在工程学院,与数据的两条来源一一对应。
3.2 为什么是停药一个月之后
官方写明记录是在停用降压治疗一个月之后做的。这一句对理解数据至关重要,它决定了这批波形代表的是「未治疗状态下的血压与自主神经水平」,而不是患者日常服药时的状态。
停药一个月在临床上叫洗脱期,目的是让药物对心率与心率变异性的影响消退。不同的降压药对自主神经张力的作用方向不同:β 受体阻滞剂会压低心率、抬高部分心率变异性指标,利尿剂与钙拮抗剂的影响则更间接。如果不洗脱,患者之间的用药差异会变成一个巨大的混杂因素,把心率变异性与结局的关系彻底糊住。
代价是这群人在记录时血压是没被控制的。这既让数据更「干净」,也让数据更「极端」:它记录的是一群未经治疗的高血压患者的二十四小时,而不是真实世界里长期服药、血压部分达标的患者。把模型搬到真实门诊人群上,分布会偏移。
3.3 结局是怎么变成标签的
标签不是从病历里抄一个诊断名,而是由高血压中心的事件裁定委员会逐例判定。官方的描述是:依据患者病史、与转诊全科医生的联系、以及记录事件或心律失常发生的临床记录来裁定。
裁定覆盖的事件类别写得比较宽:致死性或非致死性急性冠脉综合征(含心肌梗死)、晕厥事件、冠脉血运重建、致死或非致死性卒中、短暂性脑缺血发作。这个清单里既有硬终点(心梗、卒中),也有相对软的终点(晕厥、血运重建)。把它们合并成一个二分类标签,是这类小样本研究的常见做法,代价是标签内部的异质性很高——一次晕厥与一次心梗,在同一个「事件」标签下权重相同。
官方给出的计数是十七人发生事件,其中十一例心肌梗死、三例卒中、三例晕厥。三个数字相加恰好等于十七,说明每人计一次,没有把同一人的多次事件拆开记。
3.4 它在 2015 年填的那一格
2015 年的 PhysioNet 上,长时程心电不少,带随访结局的很少。心律失常库有逐搏标注但没有预后标签;重症监护库有院内结局但时程短、人群完全不同;流行病学队列有结局但往往不给原始波形。
SHAREE 填的是中间那一格:给原始波形,也给随访结局,时程是完整的一天,代价是人数少、导联少。这一格在十年后仍然不拥挤,因为它的门槛不在数据量,而在随访。
§4 采集与标注:一天是怎么变成一条标签的
4.1 三个导联的选择
三个导联是 III、V3、V5。这个组合不是标准十二导联的子集随机抽样,而是一种针对节律与左室前侧壁的折中:III 导联对下壁与右心的电活动敏感,V3 位于胸前过渡区,V5 位于左腋前线覆盖左室侧壁。三导联 Holter 的常规配置通常接近 V1、V5 加一个肢体导联,这里的组合更偏向左室。
对心率变异性来说,导联选择的影响其实不大——R 峰在任何一个导联上都能定位,只要信噪比够。对形态学分析影响就大了:没有 V1,束支阻滞的分型做不了;没有 II 与 aVF 的系统组合,下壁缺血的判断不可靠。
| 导联 | 解剖指向 | 对节律分析 | 对形态分析 |
|---|---|---|---|
| III | 下壁、右心 | 够用 | 单独用价值有限 |
| V3 | 前壁过渡区 | 够用 | 可看前壁 |
| V5 | 左室侧壁 | 够用 | 可看侧壁 |
三个导联全部记录在同一个二进制文件里,按通道交替存放。读取时不用分别打开三个文件,但也意味着不能只下其中一个通道——想要 V5,就得把 III 与 V3 一起读进来。
4.2 案例:01911 这条记录
以编号 01911 的记录作为贯穿案例。它是清单里的第一条,也是库中结构最普通的一条:三导联齐全、时长二十二点四小时、结局为阴性。
它在 info.txt 里对应的一行是:男性,五十六岁,体重一百零五千克,身高一百八十厘米,体表面积二点二九平方米,体质指数三十二点四一,吸烟,血压一百四十比八十毫米汞柱,最大内膜中层厚度四毫米,左室质量指数一百二十三,射血分数六十六,结局为 none。
| 属性 | 值 | 说明 |
|---|---|---|
| 记录号 | 01911(文件名)与 1911(信息表) | 同一人,位数不同 |
| 时长 | 10322048 个样本,约 22.4 小时 | 由头文件样本数换算 |
| 起始时刻 | 12:20:53 | 中午开始,跨一个整夜 |
| 导联 | III、V3、V5 | 三通道同文件 |
| 标签 | none | 随访期内无事件 |
这条记录适合当参照点,原因是它把三类信息都摆在了明面上:波形层能算时长与导联,临床层能读到十四个字段,标签层给的是阴性。选它而不是选一条阳性记录,是因为阴性才是这个库的多数——一百三十九人里只有十七人发生事件,剩下的人长得都像它。
从这条记录还能看出一个容易忽略的细节:起始时刻是中午。二十四小时 Holter 的佩戴时间由门诊安排决定,不同的患者可能在一天中的任何时刻开始,这意味着「夜间段」在每条记录里的绝对位置并不相同。要比较夜间心率变异性,必须按起始时刻把时间轴换算成钟点,不能简单地取记录的前三分之一当夜间。
4.3 标注是算法给的,不是人给的
QRS 位置由 WQRS 检测器自动标记。这个方法基于长度变换,原始文献是 Zong、Moody 与 Jiang 在 2003 年计算机心脏病学会议上的一篇会议论文。官方明确写了「have not been corrected manually」,并且库里的 ANNOTATORS 文件把这类标注描述为 unaudited beat annotations。
这句话的分量比它看起来重。心率变异性的每一个指标都建立在 R-R 间期序列上,而 R-R 间期又完全依赖 R 峰位置。算法漏检一个搏动,就会把两个正常间期合并成一个近两倍长的心搏间期;算法多标一个位置,就会插入一个极短的间期。这两种错误在时域指标上表现为 SDNN 抬高,在频域指标上表现为低频功率虚增,而两者的方向恰好都是「让高风险者看起来更像高风险者」。
| 环节 | 做法 | 已知误差来源 | 是否可自查 |
|---|---|---|---|
| R 峰检测 | WQRS 长度变换 | 噪声段漏检、伪差误检 | 可,人工核一段 |
| 标注校正 | 无 | 全部保留 | 需自行处理 |
| 异位搏动剔除 | 官方未做 | 房早室早全部混入 | 需自行处理 |
| 心率变异性计算 | 官方未提供 | 无 | 需自行选择算法 |
因此这份数据的第一个工程动作不是训练模型,而是量出标注本身的错误率。做法很朴素:抽若干条记录,取若干段,人工标一遍 R 峰,与算法结果比对。这个数字决定了后面所有指标的置信度,而它只能在拿到文件之后才知道。
4.4 从 R 峰到风险:一条链上的三次损失
第一条链路是采样。128 Hz 的采样间隔约 7.8 毫秒,R 峰的定位精度不会优于这个量级。对正常窦性节律,R-R 间期在一秒上下,7.8 毫秒的量化误差对应不到百分之一的相对误差,可以接受。但对高频心率变异性成分——比如反映呼吸性窦性心律不齐的高频段——这个量化台阶已经开始吃掉信号。
第二条链路是量化。8 位精度意味着每个采样点只有二百五十六个取值,动态范围约四十八分贝。Holter 记录中基线漂移与肌电噪声都不小,8 位量化在低幅段会引入可见的台阶。对 R 峰检测影响有限,对波形形态分析影响明显。
第三条链路是窗长。二十四小时的数据不可能整段算一个指标——那样只能得到一个数,139 人只有 139 个样本。常规做法是切成五分钟或三十分钟的窗,每窗算一组指标。这一步把样本数从一百三十九放大到上千,也正是最容易被误用的地方:窗与窗之间高度相关,它们不是独立样本。
| 损失点 | 来源 | 受影响的分析 | 缓解方式 |
|---|---|---|---|
| 时间量化 | 128 Hz | 高频段功率 | 无,只能声明 |
| 幅度量化 | 8 位 | 波形形态、低幅成分 | 无,只能声明 |
| 窗切分 | 人为选择 | 独立性、样本量 | 按患者划分,窗内聚合 |
§5 怎么拿到,以及拿到之后怎么读
5.1 开放许可与三种下载方式
它是 PhysioNet 的开放资源,不需要注册、不需要签协议、不需要审批。页面写明:任何人都可以访问文件,只要遵守指定许可的条款。许可为开放数据共用署名 1.0,要求保留署名。
| 方式 | 命令或入口 | 适用场景 | 体积 |
|---|---|---|---|
| 网页逐件下载 | 目录页点选 | 只要清单与信息表 | 几十 KB |
| 整包压缩 | 压缩包入口 | 一次拿全 | 1.7 GB |
| 递归抓取 | wget 递归 | 断点续传、只取部分 | 视范围 |
| 对象存储同步 | aws s3 sync | 大批量、多机分发 | 4.1 GB |
先拉清单与信息表是个好习惯。它们加起来不到十 KB,却足以让你在看任何波形之前就知道这批人有多少、标签怎么分布、字段有没有缺。这一步不需要下载一个字节的心电。
#-- 先取三个小文件,几十 KB,够做一次可行性判断
BASE=https://physionet.org/files/shareedb/1.0.0
mkdir -p shareedb_meta && cd shareedb_meta
curl -sSLO "$BASE/RECORDS"
curl -sSLO "$BASE/info.txt"
curl -sSLO "$BASE/README"
wc -l RECORDS info.txt
#-- 确认可行后再整包下载,-c 支持断点续传
cd .. && wget -c https://physionet.org/content/shareedb/get-zip/1.0.0/ -O shareedb-1.0.0.zip
5.2 先读头文件,再谈别的
拿到文件后第一件事不是画图,是读头文件。WFDB 的 Python 客户端可以直接读,也可以自己按行切分——头文件的格式足够简单,不装库也能解析。
#-- 读头信息:通道名、采样率、样本数、单位
import wfdb
rec = wfdb.rdheader('shareedb-1.0.0/01911')
print('导联', rec.sig_name)
print('采样率', rec.fs, '通道数', rec.n_sig)
print('每通道样本数', rec.sig_len)
print('时长小时', round(rec.sig_len / rec.fs / 3600, 2))
print('增益', rec.adc_gain, '基线', rec.baseline, '单位', rec.units)
打印出来的 sig_len 除以 fs 就是时长。这一步能立刻回答一个常被问的问题:它到底是不是完整二十四小时。答案是名义上的,实际普遍略短。
5.3 把信息表和波形对上
两张表靠记录号连接,但位数不同:清单里是 01911,信息表里是 1911。不做补齐就直接合并,会得到一张空表,而且不会报错。
#-- 连接两张表:先把记录号统一成五位数
import pandas as pd
records = [ln.strip() for ln in open('shareedb_meta/RECORDS') if ln.strip()]
info = pd.read_csv('shareedb_meta/info.txt', sep='\t', dtype=str)
info = info[info['Record'].str.isdigit()].copy()
info['record_id'] = info['Record'].str.zfill(5)
print('清单条数', len(records), '信息表条数', len(info))
print('清单里有、信息表里没有', sorted(set(records) - set(info['record_id']))[:5])
print('信息表里有、清单里没有', sorted(set(info['record_id']) - set(records))[:5])
两个差集都应当为空。若不为空,说明记录号补位规则不是简单的五位补零,需要回头看头文件里的记录名再定规则。§4.2 的案例正是这种情况的最小样本:01911 与 1911 指的是同一个人,机器读不出来,人一眼能看出来。
5.4 从标注算 R-R 间期
标注文件里存的是 R 峰的采样点序号。相邻序号之差除以采样率,就是 R-R 间期。
#-- 读 QRS 标注,换算成以秒为单位的 R-R 序列
import numpy as np
import wfdb
ann = wfdb.rdann('shareedb-1.0.0/01911', 'qrs')
peaks = ann.sample
rr = np.diff(peaks) / 128.0
print('标注搏动数', len(peaks))
print('R-R 中位数(秒)', round(float(np.median(rr)), 3))
print('R-R 极短(<0.3 秒)个数', int((rr < 0.3).sum()))
print('R-R 极长(>2.0 秒)个数', int((rr > 2.0).sum()))
后两行不是心率变异性指标,是标注质量指标。极短与极长的间期大多来自误检、漏检或伪差,处理它们的第一步是先数清楚有多少,而不是直接删掉。
5.5 二十四小时怎么读进内存
一条记录的样本数是千万级,三个通道一起读,按 8 位存是三十兆字节上下,转成浮点就是百兆级。整库一百三十九条一起读会直接吃满普通机器的内存。正确做法是按段读。
#-- 分块读取:每次只取一小时,算完即弃
import numpy as np
import wfdb
CHUNK = 128 * 3600 #-- 一小时的点数
sig_len = wfdb.rdheader('shareedb-1.0.0/01911').sig_len
acc = []
for start in range(0, sig_len, CHUNK):
seg, _ = wfdb.rdsamp('shareedb-1.0.0/01911',
sampto=min(start + CHUNK, sig_len),
sampfrom=start)
acc.append(float(np.std(seg[:, 2]))) #-- 第三通道 V5 的段内标准差
print('段数', len(acc), '首段标准差', round(acc[0], 3))
分块读取除了省内存,还有一个好处:它天然按自然时间切片,方便后面把段映射到钟点上。§4.2 的案例里那条记录从中午开始,第一段对应的是下午,而不是凌晨。
5.6 标签只有一种,但要先想清楚单位
info.txt 的最后一列给出结局,取值为 none 或某个事件名。二值化只需要一行判断,难的是决定分析的统计单位:是人,还是窗。
#-- 建患者级标签表,窗级分析时用它做分组
import pandas as pd
info = pd.read_csv('shareedb_meta/info.txt', sep='\t', dtype=str)
info = info[info['Record'].str.isdigit()].copy()
info['record_id'] = info['Record'].str.zfill(5)
info['y'] = (info['Vascular event'].str.strip().str.lower() != 'none').astype(int)
print('患者数', len(info), '阳性数', int(info['y'].sum()))
print('阳性比例', round(info['y'].mean(), 3))
print(info.loc[info['y'] == 1, 'record_id'].tolist()[:5])
阳性名单只应当用来做划分,不应当用来做特征。任何以「这个人后来有没有事件」为输入构造的变量——比如把随访期间新加的检查结果并进来——都会造成标签泄漏,而这个库里恰好没什么可泄漏的,因为临床表只记了基线。
§6 与库内条目的关系
6.1 关系图谱
库内与心电相关的词条不少,各自占一格。SHAREE 与它们不是替代,而是分工。
| 词条 | 时程 | 关键差别 | 与本篇的关系 |
|---|---|---|---|
| SHAREE | 24 小时 | 三导联,带随访结局 | 唯一以预后标签为核心的一条 |
| 短片段高危分级库 | 两秒 | 按致命程度分级 | 片段级,无随访 |
| 静息心肺信号库 | 数十分钟 | 健康志愿者,含连续血压 | 人群相反,信号更全 |
| 心电身份库 | 二十秒 | 同一人多次采集 | 任务是识别不是预测 |
| 房颤长时程库 | 十小时 | 双导联,逐搏人工标注 | 标注质量更高,无结局 |
| 重症监护心电库 | 数小时 | 院内结局,十二导联 | 规模大得多,人群不同 |
这张表最该看的是第一列以外的两列。要标注质量,房颤库更好;要信号齐全,静息库更好;要人数,重症库更好。只有在「长时程加远期结局」这一格上,它没有直接对手。
6.2 检索路径
| 你要找的 | 库内路径 | 在本库的落点 |
|---|---|---|
| 带随访结局的心电 | 按标签筛心电信号与队列研究 | 本篇 |
| 心率变异性方法学 | 按关键词搜 HRV | 本篇与静息心肺库 |
| 逐搏人工标注 | 按标注方式筛 | 房颤库更合适 |
| 十二导联形态 | 按导联数筛 | 本篇不适用 |
| 健康对照 | 按人群筛 | 本篇不适用 |
| 可穿戴连续监测 | 按采集设备筛 | 本篇不适用,它是 Holter |
6.3 与大库的分工
如果把这份数据和院级大规模心电库放在一起,差别不在人数,而在标签的来源。大库的标签通常来自出院诊断编码,覆盖面广但噪声大;这份数据的标签来自一个专门为研究设立的事件裁定委员会,覆盖窄但每一条都经过人工确认。
前者适合做预训练与表征学习,后者适合做小样本的、标签可信的验证。一个常见的组合是:在大库上预训练,在这类小库上做结局相关的评估。这样既能用上规模,又不至于把评估建立在编码噪声上。
§7 质量评估与局限性
7.0 阅读本节前的一个前置校正
评估这类数据集时,一个常见的误判是拿数据量当质量指标:二十四小时乘三个通道乘一百三十九人,算出来是几十亿个采样点,看上去规模庞大。这个算法在这里是错的。
第一,采样点多不等于样本多。统计推断的单位是人,不是点。一百三十九个人就是一百三十九个观测,十七个阳性就是十七个观测。把窗口切开可以让特征矩阵变大,但不会让信息变多——窗与窗之间的相关性极高,切得越细,有效样本量越接近人数而不是窗数。
第二,时长长不等于信息密度高。二十四小时的价值在于覆盖了昼夜节律与夜间自主神经状态,而不在于它有多少个点。这条价值只需要几小时的连续记录就能拿到,多出来的部分主要是在增加噪声暴露的机会。
第三,导联少是结构性的限制,不是可以靠算法补的缺口。三个导联里没有的信息,任何模型都变不出来。
因此本节的评分不按采样点总数给分,只按「作为一份带结局的长时程心电,它能支撑什么样的结论」给分。§4.2 的案例可以拿来量一遍:这条记录能算二十四小时的心率变异性、能算昼夜差异、能与它的十四个临床字段配对;但它不能回答「这个人的 ST 段有没有变化」,也不能回答「他夜里有没有呼吸暂停」。同一份文件,能回答的问题与不能回答的问题,边界清楚得像一条线。
7.1 五维评分
评分用 DAIMS 五维框架,每一维给依据而不是结论。分数为编辑判断,供选型参考,不是官方数据。
| 维度 | 含义 | 分(5 制) | 依据 |
|---|---|---|---|
| D 数据完整度 | 波形、标注、临床表、结局是否齐 | 4.5 | 四样俱全,临床表十四列 |
| A 获取可及性 | 拿到数据的成本 | 4.5 | 开放许可,1.7 GB,无需注册 |
| I 信息深度 | 是否支持细粒度分析 | 3.5 | 三导联、128 Hz、8 位 |
| M 方法论成熟度 | 文档与标注的可靠性 | 3.0 | 标注未校正,表头有误,后缀两说 |
| S 场景覆盖 | 人群与条件的广度 | 2.0 | 单中心、139 人、17 例事件 |
五维的形状是两头高、中间平、尾端低:可及性与完整度极好,深度中等,覆盖最弱。选型时不要看总分,要看项目卡在哪一维。卡在「拿不到数据」,它几乎是最好拿的一份;卡在「样本不够」,它一定不是候选。
同一张评分对不同项目会给出相反结论。做方法学验证的团队看到 A 与 D 两项可以直接开工;做产品化风险模型的团队看到 S 这一项就该另找队列;做信号质量基准的团队看到 I 这一项会立刻排除它。这不是评分不稳,而是它把长板与短板都放在了极端位置。
7.2 文档与元数据的缺口
官方页面写得不算少,但有六处信息缺席。它们不是错误,只是没写。
采集年份没有任何交代。文件时间戳显示的是 2015 年初的整理时间,不是采集时间。资助编号对应 2007 至 2013 年的计划期,可以推测采集落在这段时间内,但这是推测,不是记载。
伦理批件号没有写。涉及人体数据的公开库通常会给出批件号或声明,这里两者都没有。使用者若要把结果用于发表,需要自己在论文里说明数据来源与合规路径。
入组是否连续没有说。139 个记录号散布在 1911 到 2425 之间,中间跳过了大量编号。跳过意味着筛选,而筛选准则没有公开。
随访的失访情况没有说。十七例事件是分子,分母是不是仍然一百三十九,官方没有明确。
用药与合并症没有逐人记录。只写了停药一个月,没有写原先用什么药、停了多久、有没有糖尿病或慢性肾病。
导联的位置与贴法没有写。三个导联名给了,但电极具体贴在哪里、由谁贴、有没有统一培训,都空缺。
| 缺口 | 影响 | 能否从别处补 |
|---|---|---|
| 采集年份 | 无法定位历史背景 | 只能推测到资助期内 |
| 伦理批件 | 发表的合规说明需自证 | 需联系作者 |
| 入组连续性 | 选择偏倚无法评估 | 不能 |
| 失访 | 分母不确定 | 不能 |
| 用药史 | 混杂因素无法调整 | 不能 |
| 电极贴法 | 跨记录可比性未知 | 不能 |
7.3 已知的、可枚举的偏差
偏一,性别。四十九女九十男,男性约占三分之二。女性的心电在振幅、QT 间期与心率变异性基线水平上都与男性有系统差异,训练集以男性为主,模型在女性上的表现无法从内部估计。
偏二,年龄。全部在五十五岁以上,官方给出的均值与离散度是七十二加减七。这个人群本身就是心血管事件的高发段,把模型外推到中年人群,阳性率会大幅下降。
偏三,人群状态。全部是高血压患者,且记录时处于停药一个月后的未治疗状态。真实门诊里绝大多数患者是服药的,血压与自主神经状态都不同。
偏四,中心与地域。单中心、单国、单一人种背景。跨中心的泛化没有任何内部证据。
偏五,标签合并。心梗、卒中、晕厥、血运重建、短暂性脑缺血被合并成一个二分类。晕厥的病理机制与心梗差别很大,合并之后标签的语义变宽,模型学到的可能是「这个人整体不健康」而不是某个具体机制。
| 偏差 | 类型 | 在模型里的表现 | 可控程度 |
|---|---|---|---|
| 性别失衡 | 人群 | 特征分布整体偏移 | 只能靠报告限定人群 |
| 年龄偏老 | 人群 | 阳性率虚高 | 不可控 |
| 未治疗状态 | 设计 | 血压与心率不可外推 | 需在报告中声明 |
| 单中心 | 设计 | 跨中心性能未知 | 待外部重复 |
| 标签合并 | 设计 | 语义变宽 | 可控,按事件类型重切 |
前三条是人群层面的,会以系统误差进入模型;后两条是设计层面的,会以不确定性的形式进入结论。对付前三条的办法只有一个:在报告里把适用人群写死,不要写「在高血压患者上有效」,要写「在这批七十二岁上下、停药一个月、意大利单中心的高血压患者上有效」。
7.4 外部验证矩阵
一份数据是否被外部工作用过,是它生命力的证据。下表列出四种可核验的信号。
| 信号类型 | 可核验形式 | 本篇状态 | 含义 |
|---|---|---|---|
| 作者自报的性能 | 同一论文的交叉验证结果 | 有 | 随机森林,灵敏度七成一,特异度八成八 |
| 第三方复现 | 别的团队用它出结果 | 未核实 | 需检索引用 |
| 平台关注度 | PhysioNet 当前版本浏览数 | 四百四十九 | 十余年累计,热度偏低 |
| 版本更新 | 是否有后续版本 | 无,仅 1.0.0 | 内容冻结于 2015 年 |
浏览数这一栏值得停一下。十余年四百四十九次,平均一年四十次上下,在 PhysioNet 上属于冷门。这个数字不代表数据不好,只代表它没有被广泛注意到。它的定位本来就偏——带结局的长时程心电是给特定问题用的,不是给入门练手用的。
作者自报的性能也要放回样本量里读。灵敏度七成一、特异度八成八,是在一百三十九人、十七例阳性上做交叉验证得到的。换成患者级划分,阳性测试集只有三到四例,任何一个病例的翻转都会让指标跳动十个点以上。这个数字应当被当作可行性证据,而不是性能基线。
7.5 它为何能持续:卖点是随访,不是波形
公开的心电会越来越多,采样率会越来越高,导联会越来越全,人数会越来越大。这些东西每一年都在被刷新。但有一样东西不容易被刷新:一百三十九个人、十二个月、逐例裁定的结局。
波形可以重采,随访不能重做。一个团队愿意花一年时间盯着患者有没有心梗,这件事的成本决定了这类数据的供给速度。它靠的是这个稀缺性活着,不是靠体量。
这也解释了它为什么能一直开放。它不含可识别的生物特征风险吗?其实含——心电本身有身份属性——但 2015 年的开放政策与今天的审查尺度不同,它就这样被留在了开放区。使用者应当自己承担合规判断,而不是把「它能公开下载」当成「怎么用都行」。
§8 生态位与历史
8.1 一条从读图到建模的路线
动态心电的用途在过去三十年里换过一次主轴。九十年代,Holter 的价值在于「抓到没抓到」:患者主诉心悸,戴一天,回来看有没有室早、有没有停搏。判读靠人眼翻纸带。
两千年之后,主轴慢慢转向「算出来什么」:心率变异性、心率震荡、T 波电交替,一批指标被提出,每一个都声称能预测死亡。指标多了,就需要有结局的数据来判断谁真谁假。
| 时期 | 主轴 | 判读方式 | 数据需求 |
|---|---|---|---|
| 九十年代 | 抓心律失常 | 人眼翻带 | 短段、少量人 |
| 两千年后 | 算风险指标 | 手工特征加统计 | 长时程、带结局 |
| 二零一零年代 | 端到端学习 | 模型直接吃波形 | 大规模、弱标签 |
| 现在 | 预训练加微调 | 大库预训练、小库评估 | 两者都要 |
SHAREE 站在第二段的末尾、第三段的起点。它诞生的动机是给手工指标提供检验场,而不是给深度模型提供训练集。用它做深度学习不是不行,但要注意它的规模是按「验证」设计的,不是按「训练」设计的。
8.2 SHARE 项目与那笔资助
官方致谢写明,这项工作由 2007 至 2013 年国家研究竞争力计划(覆盖卡拉布里亚、坎帕尼亚、普利亚与西西里四个大区)资助,编号 PON04a3_00139,项目名正是 Smart Health and Artificial intelligence for Risk Estimation。
这个项目名的落点是「六十五岁以上人群的心血管事件与跌倒预防」。数据里年龄下限五十五岁、均值七十二岁,与项目目标一致。换句话说,这份数据是一个更大计划的一块砖,不是一个独立的数据集项目。这也解释了它为什么只有一百三十九人却仍然值得发布:它的目的不是做大规模资源,而是把一个可复现的验证集放出来。
8.3 2015 年的 PhysioNet 与今天
2015 年的 PhysioNet 还处在「研究组自愿上传、平台做基础托管」的阶段。没有统一的元数据规范,没有 Croissant 描述,没有强制的数据卡。那时的开放库普遍长得像这份数据:一个扁平目录、一份 README、一张自制的信息表。
今天的平台要求更严,新上线的库通常配有结构化元数据、明确的许可 URI、以及更完整的采集说明。拿今天的标准去衡量一份十年前的库,会发现很多「缺口」——它们不是失误,是时代差异。
| 项 | 2015 年的常见做法 | 今天的常见做法 | 本库所处 |
|---|---|---|---|
| 元数据 | README 文字 | 结构化数据卡 | 文字 |
| 许可 | 页面一句话 | 许可 URI 与条款 | 已给 URI |
| 标注 | 算法生成即用 | 双人标注加一致性 | 算法 |
| 版本 | 一次发布不再改 | 语义化版本 | 仅 1.0.0 |
8.4 三条后继路线
第一条是把它当基线。任何新的心率变异性预后模型,都可以在这份数据上报一个数,作为与 2015 年那篇论文的可比点。这条路线不需要改动数据,只需要统一评估协议。
第二条是把它当外部验证集。在大库上训练的模型,拿到这份数据上测一次,看跨人群、跨设备的衰减。这条路线对它的规模要求不高,反而更喜欢它的人群特殊性。
第三条是把它当标注质量的研究对象。算法标注与人工标注的差异,在一份带结局的数据上会产生什么后果,是一个有意思的方法学问题。这条路线需要先人工标一小部分,成本可控。
§9 使用指引
9.1 三种角色的路径
| 角色 | 第一件事 | 第二件事 | 不要做的事 |
|---|---|---|---|
| 学生或入门者 | 先读 info.txt 与 RECORDS | 用单条记录跑通读取 | 一上来就切窗训练 |
| 方法研究者 | 量标注错误率 | 固定评估协议再比模型 | 拿窗口当独立样本 |
| 临床研究团队 | 明确人群与状态 | 把随访口径写成生存分析 | 把二分类当绝对风险 |
9.2 一条最短的可用流程
从零到第一个可解释的结果,最短是五步。全部以已下载为前提。
#-- 第一步:核对文件齐全,三件一组
ls shareedb-1.0.0/*.hea | wc -l
ls shareedb-1.0.0/*.dat | wc -l
ls shareedb-1.0.0/*.qrs | wc -l
#-- 第二步:核对清单与信息表条数一致
wc -l shareedb_meta/RECORDS
python3 -c "import pandas as pd; d=pd.read_csv('shareedb_meta/info.txt',sep='\t'); print(len(d))"
三个计数应当一致。若 .qrs 少于 .dat,说明有记录的标注缺失,这些记录算不了心率变异性,要么补检要么剔除。第三步是 §5.2 的读头,第四步是 §5.4 的算 R-R,第五步才进入建模。
9.3 引用方式
PhysioNet 的惯例是两段式:先引数据本身,再引平台。这份数据还要加第三段——原始论文,因为随访协议与裁定标准只在论文里。
Melillo, P., Izzo, R., Orrico, A., Scala, P., Attanasio, M., Mirra, M.,
De Luca, N., & Pecchia, L. (2015). Smart Health for Assessing the Risk of
Events via ECG Database (version 1.0.0). PhysioNet.
https://doi.org/10.13026/C2RC7C
Melillo, P., Izzo, R., Orrico, A., Scala, P., Attanasio, M., Mirra, M.,
De Luca, N., & Pecchia, L. (2015). Automatic prediction of cardiovascular
and cerebrovascular events using heart rate variability analysis.
PLoS ONE, 10(3), e0118504. https://doi.org/10.1371/journal.pone.0118504
| 引用对象 | 标识 | 用途 |
|---|---|---|
| 数据集 | 10.13026/C2RC7C | 说明版本与来源 |
| 论文 | 10.1371/journal.pone.0118504 | 说明协议、裁定与基线性能 |
| 平台 | 站内标准引用 | 说明托管方 |
§10 AI 使用声明
| 项 | 说明 |
|---|---|
| 内容性质 | 数据集介绍,不是临床指南 |
| 资料来源 | PhysioNet 项目页、库内 README 与信息表、Europe PMC 论文摘要 |
| 数字口径 | 以官方页面为准,冲突处并列 |
| 未核实项 | 采集年份、伦理批件、入组连续性、失访情况 |
| 代码状态 | 结构示范,路径按本地实际替换 |
| 使用风险 | 标签合并语义宽,阳性仅十七例 |
| 更新策略 | 库自 2015 年后未更新,平台改版时复核链接 |
| 免责 | 选型、合规与统计判断由使用者承担 |
常见误读(避坑清单)
| 常见说法 | 实际 | 证据 |
|---|---|---|
| 「它是可穿戴设备的连续监测数据」 | 是门诊三导联 Holter,戴一天回院拆机 | 官方描述与头文件导联配置 |
| 「它有一百三十九小时的记录」 | 是一百三十九条各约二十四小时,合计三千多小时 | 清单条数乘单条时长 |
| 「它是十二导联诊断级心电」 | 只有 III、V3、V5 三个导联 | 头文件通道行 |
| 「标注是医生逐搏标的」 | WQRS 算法生成,未人工校正 | 官方原句与标注者文件 |
| 「下载就能拿到心率变异性特征表」 | 只有波形、头文件、标注与临床表 | 目录列表 |
| 「十七例事件里有十七个不同病人」 | 是十七名患者各一次事件 | 十一加三加三等于十七 |
| 「信息表的记录号能直接连波形」 | 信息表无前导零,需补成五位 | 01911 对 1911 |
| 「随访正好十二个月」 | 页面写十二个月,摘要写至少十二个月 | 两处原文并存 |
| 「它是健康人群的对照数据」 | 全部为高血压患者,且停药一个月 | 官方数据描述节 |
| 「采样点几十亿个,样本量很大」 | 统计单位是人,只有一百三十九 | 清单条数 |
FAQ
Q1:这份数据一共有多少人、多少条记录?
139 名高血压患者,49 女 90 男,每人一条记录,因此记录数同样是 139。记录清单与信息表的数据行数一致,这一点可以在下载后立刻核对。
Q2:为什么叫 SHAREE,多的那个 E 是什么?
全名是 Smart Health for Assessing the Risk of Events via ECG Database,缩写取自五个实词的首字母,末尾的 E 来自 ECG。它所属的项目叫 SHARE,即 Smart Health and Artificial intelligence for Risk Estimation,两个名字不是同一个东西。
Q3:三个导联具体是哪些?
头文件里写明是 III、V3、V5,三条信号存在同一个二进制文件中,增益均为 35(-5)/mV。官方页面文字只说了「three ECG signals」,没有逐个列出,导联名要到 .hea 里读。
Q4:能不能直接下载,需不需要申请?
不需要。它是 PhysioNet 的开放资源,署明「任何人都可以访问,只要遵守许可条款」,许可为 ODC-By 1.0。压缩包 1.7 GB,未压缩 4.1 GB,直接取即可。
Q5:标签是怎么定义的?阳性有多少?
随访期内发生主要心脑血管事件即为阳性。官方写明 17 人发生事件,其中 11 例心肌梗死、3 例卒中、3 例晕厥。剩下的记录标为 none。
Q6:随访到底是十二个月还是更长?
两个口径并存。官方页面写「随访 12 个月」,同一项工作的论文摘要写「至少随访 12 个月」。若要做严格的生存分析,需要向作者确认实际随访分布。
Q7:QRS 标注能直接用吗?
可以直接读,但不建议直接用。官方明说标注由算法生成且未经人工校正,标注者文件也标为 unaudited。心率变异性对 R 峰误差很敏感,建议先抽段人工核对,量出错误率再用。
Q8:128 Hz 的采样率够算心率变异性吗?
对时域指标够,对高频段偏紧。128 Hz 对应约 7.8 毫秒的量化台阶,正常 R-R 间期在一秒上下,相对误差不到百分之一。做高频功率谱分析时,这个台阶会开始吃掉信号,需要在方法里声明。
Q9:能不能拿它训练深度学习模型?
能训,但不要指望泛化。139 人、17 例阳性,模型容量稍大就会过拟合。更合适的用法是把它当外部验证集或基线,而不是主训练集。
Q10:为什么记录号从 1911 开始,中间还跳号?
官方没有解释。139 个编号散布在 1911 到 2425 之间,说明这批人是从一个更大的编号空间里取出的子集。跳号意味着筛选,筛选准则未公开,做偏倚分析时要记住这一点。
Q11:它和重症监护心电库能互换吗?
不能。人群、场景、导联数、结局定义都不同。前者是门诊高血压患者的一天,后者是住院重症患者的数小时。唯一相通的是都可以算心率变异性,但基线水平不可比。
Q12:ODC-By 许可能商用吗?
它是署名型开放许可,不禁止商业使用,要求保留署名与来源说明。涉及再分发或嵌入产品时,应逐条读许可原文,不要按「开源即随便用」的常识推断。
术语表
| 术语 | 英文 | 含义 |
|---|---|---|
| 动态心电 | Holter | 连续记录二十四小时左右的便携心电 |
| 心率变异性 | HRV | 相邻心搏间期的波动程度 |
| 洗脱期 | wash-out | 停药一段时间以消除药物影响 |
| 事件裁定 | adjudication | 由委员会逐例判定终点事件是否发生 |
| 终点事件 | endpoint | 研究关注的目标事件,此处为心脑血管事件 |
| 左室质量指数 | LVMi | 左室质量除以体表面积 |
| 内膜中层厚度 | IMT | 颈动脉壁的超声测量值 |
| 射血分数 | EF | 每搏输出量占舒张末容积的比例 |
| 体表面积 | BSA | 由身高体重推算的体表总面积 |
| 体质指数 | BMI | 体重除以身高平方 |
| R 峰 | R peak | 心电图中振幅最高的尖峰 |
| R-R 间期 | RR interval | 相邻两个 R 峰之间的时间 |
| QRS 波群 | QRS complex | 心室除极对应的波形 |
| 长度变换 | length transform | WQRS 检测器使用的信号变换方法 |
| 标注 | annotation | 记录事件位置的附加文件 |
| 未校正 | unaudited | 未经人工复核的自动标注 |
| 头文件 | header | 声明通道、采样率与增益的文本 |
| 二进制波形 | binary signal | 按采样点顺序存放的原始数据 |
| 增益 | gain | 数字量换算成物理量的比例 |
| 量化位数 | bit depth | 每个采样点的二进制位数 |
| 导联 | lead | 一对电极构成的记录视角 |
| 窗 | window | 分析时切出的一段固定长度信号 |
| 标签泄漏 | leakage | 训练时混入了预测时不该知道的信息 |
| 生存分析 | survival analysis | 同时考虑事件与时间的统计方法 |
附录 A:核心数字核对表
| 项 | 值 | 来源 | 来源层级 |
|---|---|---|---|
| 患者数 | 139 | 官方页面摘要 | 官方页面 |
| 性别构成 | 49 女 90 男 | 官方页面数据描述 | 官方页面 |
| 年龄 | 55 岁以上,72±7 | 官方页面(原文作 72 - 7) | 官方页面 |
| 记录数 | 139 | RECORDS 行数 | 官方文件 |
| 通道数 | 3 | 头文件首行 | 官方文件 |
| 导联 | III、V3、V5 | 头文件通道行 | 官方文件 |
| 采样率 | 128 Hz | 官方页面与头文件 | 官方页面 |
| 精度 | 8 位 | 官方页面与头文件 | 官方页面 |
| 增益 | 35(-5)/mV | 头文件通道行 | 官方文件 |
| 单条样本数 | 10322048(01911) | 头文件首行 | 官方文件 |
| 单条时长 | 约 22.4 小时(01911) | 样本数除以采样率 | 推算 |
| 事件数 | 17 | 官方页面数据描述 | 官方页面 |
| 事件构成 | 11 心梗、3 卒中、3 晕厥 | 官方页面数据描述 | 官方页面 |
| 随访 | 12 个月 | 官方页面;摘要作至少 12 个月 | 官方页面 |
| 临床表列数 | 14 | info.txt 表头 | 官方文件 |
| 未压缩体积 | 4.1 GB | 官方页面 | 官方页面 |
| 压缩包体积 | 1.7 GB | 官方页面 | 官方页面 |
| 浏览数 | 449 | 官方页面侧栏 | 官方页面 |
| 伦理批件 | 未给 | 全文未见 | 未核实 |
附录 B:数字的来源分层
| 层级 | 定义 | 本库中的例子 |
|---|---|---|
| 官方页面 | 页面文字直接写明 | 人数、性别、年龄、采样率、事件数、体积、许可 |
| 官方文件 | 库内文件内容 | 导联名、样本数、增益、表头列名、记录号 |
| 论文摘要 | Europe PMC 收录 | 至少随访十二个月、随机森林性能 |
| 推算 | 由已知数字换算出 | 单条时长、全库总时长、阳性比例 |
界限要划清:附录 A 每一条都标了层级。标为推算的行,其分量低于标为官方页面的行。引用时优先引官方层级;推算值要么不写,要么写清换算式。
附录 C:完整参考文献
| 编号 | 文献 | 用途 |
|---|---|---|
| R1 | Melillo P, Izzo R, Orrico A, Scala P, Attanasio M, Mirra M, De Luca N, Pecchia L. Smart Health for Assessing the Risk of Events via ECG Database. PhysioNet, v1.0.0, 2015. doi:10.13026/C2RC7C | 数据集本体 |
| R2 | Melillo P, et al. Automatic prediction of cardiovascular and cerebrovascular events using heart rate variability analysis. PLoS ONE, 2015, 10(3): e0118504. doi:10.1371/journal.pone.0118504 | 协议、裁定与基线性能 |
| R3 | Zong W, Moody GB, Jiang D. A robust open-source algorithm to detect onset and duration of QRS complexes. Computers in Cardiology, 2003: 737-740 | 标注算法来源 |
| R4 | Devereux RB, Alonso DR, Lutas EM, et al. Echocardiographic assessment of left ventricular hypertrophy: comparison to necropsy findings. Am J Cardiol, 1986, 57(6): 450-458 | 左室质量公式来源 |
| R5 | Pollard T, et al. PhysioNet as a global platform for biomedical research. Nature Health, 2026. doi:10.1038/s44360-026-00096-z | 平台来源 |
附录 D:任务代码
三段代码分别对应三个最常见的起点。全部以文件已本地化为前提,路径按实际替换。
#-- 任务一:建患者级标签表,并按患者做分层划分
import pandas as pd
from sklearn.model_selection import StratifiedKFold
info = pd.read_csv('shareedb_meta/info.txt', sep='\t', dtype=str)
info = info[info['Record'].str.isdigit()].copy()
info['record_id'] = info['Record'].str.zfill(5)
info['y'] = (info['Vascular event'].str.strip().str.lower() != 'none').astype(int)
skf = StratifiedKFold(n_splits=5, shuffle=True, random_state=0)
for fold, (tr, te) in enumerate(skf.split(info, info['y'])):
print(fold, '训练阳性', int(info['y'].iloc[tr].sum()), '测试阳性', int(info['y'].iloc[te].sum()))
按患者划分是这条线上最要紧的纪律。五折之后,每一折的测试集只有三到四例阳性,指标会剧烈跳动——这不是模型不稳,是样本太薄,报告时应当给区间而不是给点估计。
#-- 任务二:从一条记录算四个最基础的心率变异性指标
import numpy as np
import wfdb
from scipy.signal import welch
ann = wfdb.rdann('shareedb-1.0.0/01911', 'qrs')
rr = np.diff(ann.sample) / 128.0
rr = rr[(rr > 0.3) & (rr < 2.0)] #-- 先剔除明显异常,再算指标
sdnn = float(np.std(rr, ddof=1))
rmssd = float(np.sqrt(np.mean(np.diff(rr) ** 2)))
pnn50 = float((np.abs(np.diff(rr)) > 0.05).mean())
f, p = welch(rr - rr.mean(), fs=4.0, nperseg=min(256, len(rr)))
lf = float(p[(f >= 0.04) & (f < 0.15)].sum())
hf = float(p[(f >= 0.15) & (f < 0.40)].sum())
print('SDNN', round(sdnn, 4), 'RMSSD', round(rmssd, 4), 'pNN50', round(pnn50, 4))
print('LF/HF', round(lf / hf, 3) if hf > 0 else 'inf')
注意这里先把 R-R 序列截断了一次。截断阈值会直接影响结果,0.3 与 2.0 是常见起点,不是标准;论文里必须写清楚用了什么阈值,否则同一份数据能算出不同的 SDNN。
#-- 任务三:按钟点切夜昼两段,比较同一人的夜间与日间
import numpy as np
import wfdb
rec = wfdb.rdheader('shareedb-1.0.0/01911')
start_sec = rec.base_time.hour * 3600 + rec.base_time.minute * 60 + rec.base_time.second
ann = wfdb.rdann('shareedb-1.0.0/01911', 'qrs')
clock = (ann.sample / rec.fs + start_sec) % 86400
hour = clock / 3600.0
night = (hour >= 0) & (hour < 6)
day = (hour >= 12) & (hour < 18)
rr = np.diff(ann.sample) / rec.fs
mid = (hour[:-1] + hour[1:]) / 2.0
print('夜间搏动数', int(night[:-1].sum()), '夜间 R-R 均值', round(float(rr[night[:-1]].mean()), 4))
print('日间搏动数', int(day[:-1].sum()), '日间 R-R 均值', round(float(rr[day[:-1]].mean()), 4))
第三段的关键在 start_sec。起始时刻读自头文件,§4.2 的案例是 12:20:53,如果不加这个偏移,所谓「夜间」就会落在记录的中段而不是真正的凌晨。这一步没有任何技术含量,却是把二十四小时数据从「一条长序列」变成「有昼夜结构的一天」的分界线。
附录 E:如果只记五件事
| 序 | 一句话 |
|---|---|
| 一 | 它是 2015 年 5 月上线的高血压动态心电库,139 人,每人一条名义 24 小时的三导联记录 |
| 二 | 三导联是 III、V3、V5,128 Hz、8 位,增益 35(-5)/mV,头文件里就能读到 |
| 三 | 它的核心资产是随访:17 人发生事件,由委员会逐例裁定,标签在 info.txt 最后一列 |
| 四 | ODC-By 1.0 开放,压缩包 1.7 GB,无需注册;标注由算法生成且未校正 |
| 五 | 它适合做可行性研究与外部验证,不适合做大规模训练;统计单位是人,不是窗口 |
编辑说明
本篇的核验方式是抓取 PhysioNet 项目页一次、库内 README 与 RECORDS 与 info.txt 各一次、Europe PMC 论文摘要一次,均在本轮完成。未做全库下载,因此所有关于信号内容的描述都止步于结构与元数据层面,不涉及任何波形数值。
三处未覆盖值得记录:一是采集年份,官方全文未提,只能由资助期推测;二是伦理批件号,页面与 README 均无;三是入组是否连续,记录号跳号只能说明有筛选,不能说明筛选准则。
口径上并列表述了四处:随访时长(页面十二个月对摘要至少十二个月)、标注后缀(页面 .qrs 对 README .wqrs0)、年龄写法(页面作 72 - 7,应为 72±7)、时长(名义二十四小时对按样本数换算的二十二点四小时)。四处均未判定对错,以文件实际内容为准。
正文中的中文数词与附录中的阿拉伯数字一一对应,不构成第二套口径。
相关数据集导航
以下为站内 AI-Ready 数据集百科中与本词条共享多个主题标签的相关数据集,按相关度降序排列:
- autonomic-aging-cardiovascular — 共享标签:生理信号 / 心电信号 / 队列研究 / 心血管疾病
- music-sudden-cardiac-death — 共享标签:生理信号 / 心电信号 / 队列研究 / 心血管疾病
- norwegian-athlete-ecg — 共享标签:生理信号 / 心电信号 / 队列研究 / 心血管疾病
- fantasia — 共享标签:生理信号 / 心电信号 / 队列研究 / 心血管疾病
- ecgcipa — 共享标签:生理信号 / 心电信号 / 队列研究 / 心血管疾病
- brugada-huca — 共享标签:生理信号 / 心电信号 / 队列研究 / 心血管疾病
- wctecgdb — 共享标签:生理信号 / 心电信号 / 心血管疾病
- ahadb — 共享标签:生理信号 / 心电信号 / 心血管疾病
- chfdb — 共享标签:生理信号 / 心电信号 / 心血管疾病
- crisdb — 共享标签:生理信号 / 心电信号 / 心血管疾病
导航说明:本章节由全站统一标签体系自动计算生成(标签重合度算法),双向可达;点击链接可跳转至对应数据集词条。

