信息速览
心电图记录的是电,测不到"动"。心脏每收缩一次,血液被射进主动脉,胸骨会跟着产生一次幅度极小、持续几十毫秒的加速度——把这段加速度记下来,就是心震图(seismocardiogram,SCG)。它不需要电极贴片,一枚贴在心口的 MEMS 加速度计就够,因此被看作无感心率监测的一条备选路线。问题是这条路要走通,得先回答一个很朴素的问题:从振动里算出来的心跳时刻,和从心电里算出来的,差多少。
CEBSDB 就是为这个问题建的库。20 名自述健康的年轻人仰卧在普通单人床上,胸前贴一枚三轴加速度计,身上接两路心电电极,胸腹间绑一条压阻式呼吸带;先安静躺五分钟,再听约五十分钟古典音乐,音乐停后再躺五分钟。四个通道同步采,每通道每秒五千个采样点,一共 60 条记录、接近二十小时。
它的用法很窄,但窄得有价值:心电图在这套数据里不是被测对象,而是尺子——同一时刻的机械振动与电活动并排躺着,任何"从振动推心搏"的算法都可以拿电的答案去对。一屏速览见下表。
| 维度 | 内容 |
|---|---|
| 全名 | Combined measurement of ECG, Breathing and Seismocardiograms DataBase(CEBSDB) |
| 发布方 | PhysioNet 托管,数据由西班牙加泰罗尼亚理工大学(UPC)电子工程系生物医学电子仪器组贡献 |
| 首次发布 | 2014 年 12 月 12 日,版本 1.0.0 |
| 后续版本 | 无,十余年只有 1.0.0 |
| 记录数 | 60 条(b 系列 20 条、m 系列 20 条、p 系列 20 条) |
| 受试者 | 20 名,19–30 岁,12 男 8 女,自述健康,均为白人 |
| 每人体量 | 3 条:基线五分钟、音乐中约五十分钟、音乐后五分钟 |
| 通道数 | 4:心电 I、心电 II、胸带呼吸、胸骨心震图 |
| 采样率与位深 | 每通道 5 kHz,16 位整数存储 |
| 模拟带宽 | 心电 0.05–150 Hz;呼吸 0.05–10 Hz;心震图 0.5–100 Hz |
| 采集设备 | Biopac MP36,呼吸带 SS5LB,加速度计 LIS344ALH,电极 3M Red Dot 2560 |
| 总时长 | 约 19.9 小时(按 60 份头文件核算) |
| 数据体积 | 未压缩 2.7 GB,ZIP 包 1.6 GB |
| 文件格式 | WFDB:.hea 头文件 / .dat 信号 / .atr 注释 |
| 许可 | ODC-By 1.0,免注册 |
| 典型用途 | 心震图心搏检测、RR 间期一致性、呼吸对 RR 的影响、静息心率变异 |
§1 它要解决的具体麻烦
1.1 心电之外,还有一条测心跳的路
心率的临床测量几乎被心电垄断:R 峰是电活动里最锐利的特征,抗噪好、判读标准统一、设备便宜。但它有个物理前提——电极必须与皮肤接触。干电极会随汗液漂移,长时间贴片会让皮肤发红,洗澡、运动、睡眠翻身都会破坏接触。可穿戴产业这些年反复尝试绕开电极,光电容积脉搏波(PPG)是最成功的一条,腕表上的绿光几乎成了标配;但 PPG 测的是末梢血容量的变化,受灌注、体温、佩戴松紧影响,运动伪迹也重。
心震图是第三条路。胸骨的机械振动直接来自心脏射血,物理链路比 PPG 短,不需要与皮肤做电学接触,一枚加速度计贴住胸壁即可。它对体位敏感、对传感器位置敏感,个体间形态差异大,这既是它的难点,也是它值得被独立研究的原因。把心震图做成可用的心率源,需要的不是更多临床数据,而是一批"两种模态同时、同一时刻、同一采样率"的对照记录。
CEBSDB 提供的就是这批对照记录。它设计时就写明了两个目的:一是检验用两个不同导联测 RR 序列时,微小检测误差是否受呼吸影响;二是比较从心电得到的 RR 序列与从心震图得到的替代序列,并据此优化心震图的心搏检测器。两个目的共用一个前提——同步。
1.2 三条常见的错误期待
第一条,把它当成可穿戴落地数据。受试者全程仰卧不动、清醒、在安静房间里,传感器由实验人员贴好。真实可穿戴场景里的行走、坐起、说话、翻身,一个都没有。它是"理想条件下的模态对照",不是"部署条件下的性能证明"。用它的成绩去承诺产品指标,会高估一个量级。
第二条,把它当成心电数据库使用。心电只有 I、II 两个肢体导联,采样率高达 5 kHz 但带宽只有 0.05–150 Hz,没有胸导联、没有诊断标注、没有临床结局。它的人群是 19–30 岁的健康年轻人,心律失常几乎不存在(官方只提到 4 号受试者有少量异位搏动)。拿它做心律失常分类,等于用健康人学病理。
第三条,把它当成大规模训练集。60 条记录、20 个人、约二十小时,信号总量在生理信号库里属于小体量。深度学习模型在这样的规模上很容易把受试者记死——尤其是心震图,波形形态与胸壁厚度、脂肪分布、传感器贴合角度强相关,20 个人就是 20 种形态。它的正确位置是验证集与消融实验台,不是预训练语料。
1.3 它能给到的与给不到的
| 你的需求 | 它给的 | 够不够 |
|---|---|---|
| 心震图心搏检测算法的开发与调参 | 20 人 × 三段、每段四通道同步,心电可作参考 | 够,这是它最本职的用途 |
| 从心震图算 RR 间期并与心电对比 | 同一时刻的两路信号,5 kHz 同步,无需配准 | 够,且是公开库里少见的配置 |
| 呼吸对 RR 序列的影响分析 | 独立呼吸通道,与心电同源同步 | 够,可直接做呼吸相位分层 |
| 双导联 QRS 时刻差异研究 | I、II 两路心电同采,时刻差可逐搏计算 | 够做方法学,但样本只有 20 人 |
| 心律失常分类训练 | 官方只提到 1 名受试者有少量异位搏动 | 不够,几乎没有病理样本 |
| 可穿戴运动场景鲁棒性 | 全程仰卧不动 | 不够,场景完全错配 |
| 心震图跨人群泛化 | 20 名年轻白人,无年龄跨度 | 不够,人群极窄 |
| 多导联心电形态学 | 只有 I、II 两个肢体导联 | 不够,无法做胸导联相关任务 |
| 长时程心率变异(昼夜节律) | 单条最长五十分钟 | 不够,只能做短时程分析 |
| 睡眠分期或呼吸事件检测 | 有呼吸带,但无睡眠、无事件标注 | 不够,只能做呼吸波形本身 |
1.4 你的处境与它能帮到的事
| 你的处境 | 它能帮你什么 | 下一步该做什么 |
|---|---|---|
| 你在做贴片式或床垫式心率监测,手上有加速度信号但没有金标准 | 提供心电与心震图严格同步的对照,心电可当参考时刻 | 先固定一套检波规则再比较,别在两套规则之间来回换 |
| 你要验证"呼吸会不会让 RR 序列带上周期性误差" | 独立呼吸通道与心电同源,可直接按吸气/呼气相位分组 | 用呼吸带做相位标记,再统计 RR 差异随相位的分布 |
| 你在写心震图检测器的论文,需要公开可复现的评测集 | 60 条记录、统一格式、免注册,别人能原样跑通 | 明确写出用了哪几条、如何划分受试者、参考时刻怎么定 |
| 你在教生物医学信号处理,想找一个"一门课能讲完"的库 | 四个通道各代表一种物理量,体积适中,读取只需一个工具包 | 从基线五分钟的 b 系列入手,先讲形态再讲检测 |
| 你在做多模态融合的早期探索,需要干净的同步数据 | 电、机械、呼吸三种模态同轴 | 先做单模态基线,再做融合,报告增益而不是只报绝对值 |
| 你要做心率变异性的短时程分析 | 单条最长五十分钟,足够做五分钟与五分钟滚动的频域指标 | 注意去除异位搏动与坏导联段(§4.4 的案例) |
| 你在评估某个开源心震图模型的真实性 | 体量小、下载快、人群干净,适合当"能不能跑通"的第一道关 | 先跑零样本,再决定是否微调 |
| 你要做临床人群的心震图研究 | 全为健康年轻人 | 不够,需另找患者队列 |
1.5 一句话判断
它的价值不在样本量,而在同一根时间轴上同时摆着"电的心跳"与"机械的心跳"——前者当尺子,后者当被测对象,这是心震图研究最难自建的条件。
1.6 不适合谁:四条边界
不适合做规模训练的人。 20 名受试者意味着任何以受试者为单位的统计,有效样本量都是 20,不是 60。三个阶段的记录彼此高度相关,把它们当成三条独立样本,是这类数据最常见的误用。
不适合做临床人群建模的人。 全部受试者自述健康、19–30 岁、无用药记录、无既往病史,官方只提到 4 号受试者有少量异位搏动。想研究房颤、心衰、心肌缺血的人,在这里找不到样本。
不适合做运动与自由活动场景的人。 采集时要求受试者"非常安静地仰卧",全程清醒。心震图在行走时的运动伪迹与静息时完全不是同一类问题,用它调出来的滤波器在真实场景里会失效。
不适合把注释当绝对金标准的人。 官方页面与 README 都没有写注释是怎么产生的、两路注释各代表什么。注释文件确实存在且格式规范,但它的语义要靠使用者自己核对,不能默认它就是"逐搏人工确认的 R 峰"。
§2 数据构成与规格
2.1 一个扁平目录,六十组三个文件
项目目录是扁平的,没有按受试者或阶段建的子目录。根目录下直接摊开 60 组文件,加上四份文本清单。命名规则一眼可读:首字母表示测量阶段,后三位表示受试者编号。
| 路径 | 内容 | 量级 |
|---|---|---|
RECORDS |
60 行,每行一条记录的 .dat 与 .hea 文件名 |
约 300 字节 |
RECORDS.txt |
同一份清单的纯文本版 | 约 2 KB |
README.txt |
数据库说明:目的、人群、设备、带宽、采样率 | 约 3 KB |
info.txt |
20 名受试者的人口学与生活习惯摘要 | 约 2 KB |
SHA256SUMS.txt |
全部文件的校验和 | 约 13 KB |
bxxx.hea / .dat / .atr |
基线五分钟记录 | 每条约 10–12 MB |
mxxx.hea / .dat / .atr |
音乐期间约五十分钟记录 | 每条约 110–120 MB |
pxxx.hea / .dat / .atr |
音乐后五分钟记录 | 每条约 12 MB |
.hea 是纯文本,只有五六行,用 curl 直接读一眼就能确认采样率与通道;.dat 是二进制,四个通道按帧交错存放 16 位整数;.atr 是二进制注释,体量从几千字节到几十千字节不等。三者缺一不可,只拿 .dat 无法还原物理量,只拿 .atr 无法知道那些时刻对应什么波形。
2.2 字段与记录的完整字典
这里的"字段"不是表格列,而是 WFDB 头文件的关键字位与注释项。把它们逐条列清楚,接入时就不必反复翻文档。
| 信息项 | 所在位置 | 取值形态 | 含义 | 使用注意 |
|---|---|---|---|---|
| 记录名 | .hea 第 1 行首字段 |
b001–p020 |
记录标识 | 首字母即阶段,后三位即受试者 |
| 通道数 | .hea 第 1 行第 2 字段 |
4 |
信号条数 | 全部记录均为 4 |
| 采样率 | .hea 第 1 行第 3 字段 |
5000 |
每秒采样点 | 四通道相同,无逐通道差异 |
| 采样点数 | .hea 第 1 行第 4 字段 |
如 1500000 |
总长度 | 除以 5000 得秒数 |
| 文件名 | 信号行第 1 字段 | b001.dat |
信号存放处 | 四通道共用一个 .dat |
| 存储格式 | 信号行第 2 字段 | 16 |
16 位带符号整数 | 不是浮点 |
| 增益 | 信号行第 3 字段 | 如 33722.0181(-14974)/mV |
每毫伏对应的整数 | 四通道差异极大 |
| ADC 分辨率 | 信号行第 4 字段 | 16 |
位深 | 有效位受增益影响 |
| ADC 零值 | 信号行第 5 字段 | 0 |
零电平对应整数 | 换算时先减零值 |
| 初始值 | 信号行第 6 字段 | 如 -16060 |
首采样点整数 | 用于校验 |
| 校验和 | 信号行第 7 字段 | 如 15465 |
采样点累加和 | 用于校验 .dat 完整性 |
| 块大小 | 信号行第 8 字段 | 0 |
每帧字节数 | 由工具自动推算 |
| 通道名 | 信号行第 9 字段 | I / II / RESP / SCG |
物理量标签 | 顺序固定 |
| 阶段说明 | .hea 末行注释 |
如 #Baseline for subject 1 |
人读的阶段描述 | 三种固定句式,可解析 |
| 注释位置 | .atr |
采样点序号 | 事件时刻 | 除以 5000 得秒 |
| 注释符号 | .atr |
N |
心搏类型 | 只见正常心搏一类 |
| 注释通道 | .atr |
0 / 1 |
两路注释 | 逐周期交替出现 |
| 年龄 | info.txt |
19–30 |
受试者年龄 | 整数,单位岁 |
| 性别 | info.txt |
male / female |
受试者性别 | 12 男 8 女 |
| 生活习惯 | info.txt |
自由短语 | 吸烟、咖啡、活动量 | 非结构化,需自己映射 |
四个通道的增益差别值得单独说一句。以 b001 为例,I 导联的增益是每毫伏三万余个整数单位,心震图通道只有两千余,呼吸通道四万余。增益大意味着同样的电压被放大得更细,量化噪声更小;增益小则相反。
| 通道 | 名称 | 物理量 | 带宽 | 单位标注 | b001 的增益 |
|---|---|---|---|---|---|
| 1 | I |
心电,左右方向投影 | 0.05–150 Hz | mV | 每毫伏三万余单位 |
| 2 | II |
心电,上下偏左投影 | 0.05–150 Hz | mV | 每毫伏七万余单位 |
| 3 | RESP |
胸廓周长变化 | 0.05–10 Hz | mV | 每毫伏四万余单位 |
| 4 | SCG |
胸骨加速度 | 0.5–100 Hz | mV | 每毫伏两千余单位 |
跨记录的差异比通道之间的差异更大。取四条记录的头文件对照,心震图通道的增益从七十余到四千余,跨度接近七十倍;II 导联从七千余到八万余,也有十倍。
| 记录 | I 导联 | II 导联 | 呼吸 | 心震图 |
|---|---|---|---|---|
| b001 | 33722 | 72230 | 40950 | 2462 |
| m001 | 37081 | 70430 | 9088 | 74 |
| p001 | 49928 | 84945 | 11110 | 4948 |
| m018 | 22724 | 7893 | 6605 | 750 |
这带来两个直接后果。同一记录内,四个通道的整数刻度不可等价比较;跨记录比同一通道的幅度,更要先按各自的增益归一。把原始整数直接喂进模型,等于让模型同时面对四把尺子和六十套刻度——它学到的可能是增益差异,而不是生理差异。
2.3 一条记录的完整解剖
取 b001。头文件第一行是 b001 4 5000 1360050:记录名 b001,四个通道,5 kHz,共 1360050 个采样点。1360050 ÷ 5000 = 272.01 秒。这是全库最短的一条——标称"五分钟"的基线段,实际第一条只录了四分半,之后 19 条基线记录都是整整 300 秒。
接下来四行信号声明,以心震图那一行为例:
b001.dat 16 2462.6354(3908)/mV 0 0 0 29704 0 SCG
从右往左读:通道名 SCG;块大小 0(由工具按四通道 16 位自动推算帧长);校验和 29704;初始值 0;ADC 零值 0;位分辨率 16;增益 2462.6354,括号里的 3908 是基线值;存储格式 16 位整数;文件名 b001.dat。
最后一行注释是 #Baseline for subject 1。三种阶段的注释句式固定:#Baseline for subject N、#Long measurement for subject N、#After music listening for subject N。这意味着阶段信息既可以从记录名首字母读,也可以从头文件注释读,两者一致。
读取这条记录只需要三行:
import wfdb
rec = wfdb.rdrecord('b001', pn_dir='cebsdb')
print(rec.fs, rec.sig_len, rec.sig_name) #-- 5000 1360050 ['I', 'II', 'RESP', 'SCG']
print(rec.p_signal.shape, rec.units) #-- (1360050, 4) ['mV', 'mV', 'mV', 'mV']
p_signal 已按增益与零值换成浮点,d_signal 保留原始整数。注意 units 四个通道全是毫伏——心震图那一行也一样,这是本库最需要留意的一处标注习惯(§7.3)。
2.4 b、m、p 三段设计:同一个人,三个状态
三段不是随便切的,它们对应实验设计的三个测量窗口。理解这一点,才知道哪些分析可以跨段做、哪些必须段内做。
| 前缀 | 阶段 | 标称时长 | 实际时长(按头文件) | 设计意图 |
|---|---|---|---|---|
b |
基线,入室静息 | 5 分钟 | 272–300 秒 | 传感器刚贴好、受试者刚躺下,作为参照状态 |
m |
听古典音乐期间 | 约 50 分钟 | 2841.5–3000 秒 | 长时程记录,情绪与自主神经状态可能变化 |
p |
音乐结束后 | 5 分钟 | 300 秒 | 与基线对照,看音乐停止后是否残留差异 |
官方对音乐这一段只写了"听古典音乐约五十分钟",没有写曲目、音量、播放设备,也没有写是否随机、是否所有人相同。这意味着"音乐"这个变量在库里是不可分解的:你无法把某一段的变化归因于某首曲子或某个节奏,只能整体当作"一段较长的、可能有情绪影响的静息期"。
三段的时长并不一致,这一点在拼接时很关键。m 系列的 20 条里有两条略短于五十分钟(m001 与 m007),其余正好 3000 秒;b 系列除 b001 外都是 300 秒整。切窗时不要假设所有记录等长,应该逐条读 sig_len。
| 组合方式 | 是否合理 | 理由 |
|---|---|---|
| 同一受试者的 b、m、p 各取一段做训练与测试 | 不合理 | 同一人、同一副胸骨、同一套电极,泄漏极强 |
| 只用 b 系列训练、只用 p 系列测试 | 勉强可用 | 仍是同一批人,只是状态不同 |
| 按受试者留一法(19 人训练、1 人测试) | 推荐 | 20 人正好做留一或五折分组 |
| 把 60 条当 60 个独立样本随机切 | 常见但错误 | 同一人的三条会分到两侧(§4.4 的案例给出一个具体后果) |
| 只用 m 系列做长时程分析 | 合理 | 单条足够长,可做五分钟滚动指标 |
2.5 与同类资源的字段差异
把 CEBSDB 放在几套常被拿来对比的公开库中间,差异立刻清楚:它不是心电库,也不是呼吸库,而是"同步模态"库。
| 对比项 | CEBSDB | INCART | BIDMC PPG | PICS |
|---|---|---|---|---|
| 记录数 | 60 | 75 | 53 | 10 |
| 受试者数 | 20 | 32 | 53 | 10 |
| 单条时长 | 5 分钟 / 约 50 分钟 | 30 分钟 | 8 分钟 | 20–70 小时 |
| 通道 | 心电 ×2、呼吸、心震图 | 心电 ×12 | PPG、呼吸、心电 | 心电、呼吸 |
| 采样率 | 5 kHz | 257 Hz | 125 Hz | 500 / 250 / 50 Hz |
| 人群 | 健康年轻人 | 冠心病检查人群 | ICU 患者 | 早产儿 |
| 核心用途 | 模态对照 | 心律失常 | 呼吸率估算 | 新生儿监护 |
| 逐搏标注 | 有,语义未文档化 | 有,类型齐全 | 有 | 有 |
这张表要说清的只有一件事:在"心电 + 机械振动"这一格上,公开库里几乎没有第二个选项。INCART 的十二导联再全,也没有加速度计;BIDMC 的呼吸标签再细,也没有胸骨振动。CEBSDB 的稀缺性来自通道组合,不来自规模。
2.6 四个通道各自在测什么
理解通道的物理含义,比记住字段名更有用,因为它决定了哪些量可以互相比、哪些不能。
| 通道 | 传感器 | 测的物理量 | 主要干扰 | 与心跳的关系 |
|---|---|---|---|---|
I |
体表电极(右上—左上) | 心电向量在左右方向的投影 | 电极接触、基线漂移 | R 峰对应心室除极 |
II |
体表电极(右上—左下) | 心电向量在上下偏左方向的投影 | 呼吸引起的电轴摆动 | 同上,幅度通常更大 |
RESP |
胸带压阻元件 | 胸廓周长随呼吸的变化 | 体位、带子松紧 | 与心跳无直接关系,与呼吸同相 |
SCG |
三轴加速度计(胸骨) | 胸壁的微小加速度 | 体动、说话、呼吸带来的整体位移 | 与射血相关的机械事件 |
心震图的波形有几组约定俗成的成分:收缩期的主峰(常被记作 MC)、主动脉瓣开放(AO)、主动脉瓣关闭(AC)、快速充盈(RF)等。它们与心电的对应关系不是固定的,会随胸壁厚度、传感器位置、体位变化。这正是本库存在的意义——要研究这种对应关系,必须有同步的心电做锚。
呼吸通道在这里不只是"附带信息"。它承担了第二个研究目的:两个导联的 QRS 时刻差是否随呼吸摆动。呼吸会改变心脏在胸腔内的位置与电轴方向,理论上会让不同导联看到的同一搏动在时间上产生微小偏移。要验证这一点,需要三样东西同时在场——两路心电、一路呼吸、足够高的采样率。CEBSDB 三样都有,而且采样率高到能把毫秒级的差异量出来。
§3 它是谁的数据:一间仪器实验室的静息实验
3.1 贡献者与机构
数据由加泰罗尼亚理工大学(Universitat Politècnica de Catalunya,UPC)电子工程系生物医学电子仪器组(IEB)的 Miguel Ángel García González 与 Ariadna Argelagós Palou 采集并整理。机构在巴塞罗那,实验室的方向是生物医学电子仪器——不是临床科室,也不是流行病学队列。这个身份决定了数据的性格:通道少但每个通道都采得很"满",采样率高、带宽宽、同步严格,配套的是两篇方法学论文而不是临床描述。
| 项目 | 内容 |
|---|---|
| 采集机构 | UPC 电子工程系生物医学电子仪器组(IEB) |
| 主要贡献者 | Miguel Ángel García González、Ariadna Argelagós Palou |
| 合作者 | Mireya Fernández-Chimeno、Juan Ramos-Castro(两篇论文的共同作者) |
| 地点 | 西班牙巴塞罗那 |
| 托管方 | PhysioNet |
| 资助 | 西班牙 MINECO 项目 PSI2011-29807-C02(论文致谢中列出) |
3.2 时间线
| 时间 | 事件 | 意义 |
|---|---|---|
| 2013 年 9 月 | 在 Computing in Cardiology 发表心震图心搏检测器比较研究 | 库的一部分数据在此文中被使用与描述 |
| 2014 年 | 在 IFMBE 会议论文集发表导联间 QRS 位置差异与呼吸关系的研究 | 库的第二个研究目的对应的产出 |
| 2014 年 12 月 12 日 | 数据库在 PhysioNet 上线,版本 1.0.0 | 首次也是唯一一次公开发布 |
| 2019 年 2 月 20 日 | 目录内补入校验和文件 | 只加校验,信号未动 |
第三行之后的空白同样有信息量:十余年间没有 1.1 版,没有增补记录,也没有勘误。对一个 60 条记录的库来说,这不是异常,而是常态——它的价值在发布那一刻就已经固定,后续维护只需要保证文件不坏。
3.3 采集场景:一张普通单人床上的五十分钟
官方描述很具体:受试者被要求"非常安静地仰卧在一张舒适的传统单人床上,保持清醒"。传感器贴好之后,先录五分钟基线;然后开始播放古典音乐,录约五十分钟;音乐结束后再录五分钟。整个过程没有体位改变、没有任务、没有药物干预。
| 环节 | 操作 | 时长 | 记录编号 |
|---|---|---|---|
| 贴传感器 | 两路心电电极、胸带、胸骨加速度计 | 未记录 | — |
| 基线 | 静卧,不说话 | 5 分钟 | b001–b020 |
| 音乐 | 静卧听古典音乐 | 约 50 分钟 | m001–m020 |
| 恢复 | 音乐停止后继续静卧 | 5 分钟 | p001–p020 |
这个设计有一个隐含假设:五十分钟的静卧足以让自主神经状态发生变化,而变化会体现在心率与呼吸上。库本身不提供任何"状态"标签,也不提供受试者主观感受,所以这个假设能不能成立,要靠使用者自己从信号里找证据。
3.4 人群:二十个年轻人,一份很短的清单
受试者信息集中在 info.txt,每人一行,包含年龄、种族、吸烟、近期咖啡摄入、生活方式五项。清单很短,短到可以整段读完,但也短到做不了任何分层分析。
| 项目 | 分布 | 说明 |
|---|---|---|
| 人数 | 20 | 编号 001–020 |
| 年龄 | 19–30 岁 | 集中在二十岁出头,最小 19、最大 30 |
| 性别 | 12 男、8 女 | 男性偏多 |
| 种族 | 全部标注为白人 | 单一族群 |
| 吸烟 | 1 人吸烟(019 号) | 其余 19 人自述不吸烟 |
| 咖啡 | 部分人"近期摄入" | 未量化剂量与时间 |
| 生活方式 | 分"久坐"与"健康"两类 | 自述,无客观指标 |
| 既往病史 | 未提供 | 仅声明"自述健康" |
| 用药 | 未提供 | — |
| BMI | 未提供 | 论文的子集给出了均值,全库无逐人数据 |
这张表最需要注意的是最后三行。没有病史、没有用药、没有体重指数,意味着任何"健康"相关的建模都缺少协变量;而"自述健康"这四个字在方法学上只排除明显患病者,不排除未诊断的问题。论文用的 17 人子集给出了年龄 24.7±3.9 岁、BMI 24.7±3.9、6 女 11 男,与全库的 20 人并不完全重合——差的三个人是哪三个,官方没有说明。
3.5 数据来源的三个层次
理解这份数据要分清三层:原始模拟信号(不可得,只在采集卡里存在过)、公开的四通道数字记录(基本单位,60 条)、心搏注释(监督信号,语义未文档化)。第一层决定了任何"原始波形"的讨论都只能是推断;第二层决定了每条记录的边界都是人为按阶段切的;第三层决定了监督信号的时间粒度是心搏,但它的来源与可靠性要自己核。
§4 它最独特的东西:电与机械同轴
4.1 为什么"同步"比"多通道"更难
多通道数据不难找,难的是通道之间严格同步。心电与心震图若分别采集、事后按时间戳对齐,两个时钟的漂移会直接变成毫秒级误差,而这个误差恰好与研究目标同量级——心震图的机械事件相对 R 峰的延迟只有几十毫秒,检测误差的目标是几毫秒。时钟差一点点,结论就翻。
CEBSDB 用一台 Biopac MP36 采全部四个通道,采样时钟只有一个,四路信号在硬件层面就是同一时基。这是它能被当作方法学基准的根本原因,也是自己搭实验最难复现的部分——要同时接心电放大器、呼吸带、加速度计并保证同一采样时钟,需要一台多通道生理记录仪。
| 同步方式 | 时间误差量级 | 对 RR 研究的影响 |
|---|---|---|
| 单机多通道同步采样(本库) | 由采样率决定,微秒级 | 可忽略 |
| 两台设备各自采集、按时间戳对齐 | 毫秒到数十毫秒 | 与目标误差同量级,结论不可靠 |
| 事后按形态特征对齐 | 依赖算法,误差不可控 | 相当于把被测误差混进参考 |
4.2 双导联心电在这里不是冗余
十二导联库里,多用几个导联是为了看不同角度;这里用两个导联,目的不同——是为了量"同一搏动在两个导联上的时刻差"。I 导联与 II 导联看的是心电向量在不同方向的投影,同一个 QRS 波群到达两个导联的峰值时刻并不严格相同,差值在毫秒量级。这个差值会不会随呼吸周期摆动,是本库第二个研究目的的核心问题。
| 现象 | 机制 | 在本库里怎么观察 |
|---|---|---|
| 两导联 QRS 峰值不同时 | 心电向量投影方向不同 | 逐搏算 I 与 II 的峰值时刻差 |
| 差值随呼吸变化 | 呼吸改变心脏位置与电轴 | 用呼吸带相位分层统计差值 |
| 幅度随呼吸起伏 | 胸廓充盈改变导电路径 | 看 R 峰幅度的低频包络 |
| 检测误差被呼吸调制 | 阈值法在幅度低谷时更容易漏检 | 比较检出率随呼吸相位的差异 |
这也解释了一个常见误解:有人以为两个导联是用来做"导联冗余"提高抗噪的。在这个库里,冗余是副作用,主作用是提供一对可比对的时刻。
4.3 心震图的三种典型用法
同一份数据,不同的人会拿它做三件不同的事,难度依次上升。
| 用法 | 做法 | 依赖什么 | 难度 |
|---|---|---|---|
| 心搏检测 | 从 SCG 通道检出动心周期,与心电对时刻 | 单个通道的峰值检测 | 中 |
| RR 序列重建 | 用检测到的心震时刻算间期,与心电 RR 比 | 检测稳定性 + 时刻精度 | 中高 |
| 形态与生理关联 | 分析 SCG 各成分与呼吸、心率的关系 | 波形分段与生理先验 | 高 |
第一件事是入门,第二件事是论文里最常见的评测,第三件事才是这份数据真正稀缺的地方——因为要研究形态,必须有可对照的电活动与呼吸相位,而这两样在别的公开库里很少同时出现。
4.4 案例:m018 第三十四分钟起的那四分钟
官方在页面底部列了两条"已发现的异常",第二条是:m018 的 II 导联在第三十四分钟到第三十八分钟之间电极接触不良,信号质量差。这条提示看似琐碎,实际是这份数据最好用的一个教学样本。
把它拆开看,能同时说明四件事。第一,坏段是有边界的不只是"整条记录差"——三十四分钟之前和三十八分钟之后,同一导联是好的,所以按段丢弃比整条丢弃更合理。第二,同一条记录里 I 导联没有报问题,说明双导联在这里起到了互为备份的作用;如果只采了一个导联,这四分钟就只能整段作废。第三,任何以 II 导联为参考时刻的 RR 序列,在这四分钟里都会出现成串的伪间期,而这些伪间期会被后续的频域分析放大成假的低频功率。第四,如果训练时把 60 条记录随机切分,m018 的其余部分可能落进训练集、这四分钟落进测试集,模型就会在一个"参考本身是错的"样本上被评分。
| 观察点 | 具体表现 | 处理建议 |
|---|---|---|
| 坏段边界 | 第三十四分钟起、第三十八分钟止 | 按时间窗剔除,不要整条丢弃 |
| 影响通道 | 仅 II 导联 | 该段改用 I 导联做参考 |
| 对 RR 的影响 | 出现成串伪间期与漏检 | RR 序列先做异常间期过滤 |
| 对频域的影响 | 伪间期抬高低频功率 | 分析前做插值或分段剔除 |
| 对划分的影响 | 同一受试者的三段高度相关 | 按受试者划分,不按记录划分 |
§4.4 的案例在后面的取数流程、偏差清单与最短流程里各出现一次,因为它是这份数据里唯一被官方点名的"已知缺陷",也是最容易被忽略的一处。另一个被点名的异常是 4 号受试者的少量异位搏动,尤其集中在 m004——那条记录不适合拿去做"纯正常心搏"的基线。
4.5 标注的粒度:有文件,但语义要自己核
.atr 文件对每条记录都存在,格式是标准的 WFDB 注释,可以直接用工具读。但官方页面与 README 都没有写这些注释是谁标的、按什么规则标的、符号代表什么。核对一个文件可以看到它的内部结构:
| 观察项 | 结果 | 含义 |
|---|---|---|
| 符号种类 | 只有正常心搏一类 | 没有室性、房性等分类 |
| 注释通道 | 两个(0 与 1) | 每个心动周期有两条注释 |
| 配对间隔 | 十余毫秒 | 同一搏动的两个基准点 |
| 相邻对间隔 | 约一秒量级 | 与静息心率吻合 |
| 辅助文本 | 空 | 没有节律标记或备注 |
两个通道各代表什么,官方没有说明。从配对间隔的量级,以及同一批作者另一篇论文专门讨论"导联间 QRS 位置差异"这一事实推断,较可能是 I、II 两个导联各自的 QRS 基准点;但这只是推断,不能当作官方口径写进方法节。稳妥的做法是把它当"参考候选",用自己实现的检波器与它对齐后再决定信不信。
4.6 边界条件:什么情况下它不再适用
| 条件 | 是否适用 | 判断依据 |
|---|---|---|
| 研究静息状态下的心震图检测 | 适用,且是设计目标 | 采集时要求仰卧不动、清醒 |
| 研究运动或日常活动下的检测 | 不适用 | 全程无体位改变、无行走 |
| 研究呼吸对 RR 的调制 | 适用 | 独立呼吸通道与心电同源 |
| 研究心律失常 | 不适用 | 官方仅提到 1 人少量异位搏动 |
| 研究心震图跨人群差异 | 谨慎 | 20 人、同一族群、同一年龄段 |
| 做长时程心率变异(小时级) | 不适用 | 单条最长五十分钟 |
| 做传感器位置敏感性研究 | 不适用 | 位置由实验人员固定,无重复贴放 |
| 做算法可复现性验证 | 适用 | 免注册、格式标准、体量小 |
§5 怎么拿到:从目录树到可训练张量
5.1 下载面与体量
官方提供整库 ZIP 与逐文件目录两条路。ZIP 包 1.6 GB,解开后 2.7 GB;逐文件下载适合只要其中几条的场景。全部文件免注册、免申请,直接 curl 或 wget 即可。
| 下载方式 | 体量 | 适合谁 | 注意 |
|---|---|---|---|
| 整库 ZIP | 1.6 GB 压缩 / 2.7 GB 解压 | 要全量做实验的人 | 解压后磁盘要留足三倍空间 |
| AWS 开放桶同步 | 同上 | 有云环境的人 | 免密钥,配合 --no-sign-request |
| 逐文件目录 | 按条计 | 只想跑通流程的人 | 一条 m 记录就有一百余兆 |
| 工具包远程直读 | 按需 | 快速探索的人 | 每次读取都会发起网络请求 |
单条记录的体积可以直接估出来:四通道 × 5 kHz × 2 字节 = 每秒四万字节,五分钟约 12 MB,五十分钟约 120 MB。这也是为什么 m 系列不适合反复全量下载——二十条约 2.4 GB,几乎占了整库的九成。
| 记录类型 | 采样点 | 时长 | .dat 体积 |
|---|---|---|---|
| 基线(b) | 1500000 | 300 秒 | 约 11.4 MB |
| 音乐中(m) | 15000000 | 3000 秒 | 约 114 MB |
| 音乐后(p) | 1500000 | 300 秒 | 约 11.4 MB |
5.2 读一条记录
最快的方式是用 WFDB 工具包远程直读,不必先下载整库。
import wfdb
rec = wfdb.rdrecord('m001', pn_dir='cebsdb')
print(rec.fs, rec.sig_len, rec.sig_name, rec.units)
#-- 5000 14246750 ['I', 'II', 'RESP', 'SCG'] ['mV', 'mV', 'mV', 'mV']
x = rec.p_signal #-- 形状 (14246750, 4),已是浮点物理量
print(x.shape, x[:, 3].std())
pn_dir 里的库名就是项目短名 cebsdb,工具会自动拼出文件路径。第一次读会把 .dat 拉到本地缓存,后续再读同一记录就不再走网络。
若要把全量落到本地,用命令行更省事:
#-- 只取清单与头文件,先看清结构
curl -sL https://physionet.org/files/cebsdb/1.0.0/RECORDS -o RECORDS
for r in b001 m001 p001; do
curl -sL "https://physionet.org/files/cebsdb/1.0.0/${r}.hea" -o "${r}.hea"
done
#-- 取一条完整记录(三个文件缺一不可)
for ext in hea dat atr; do
curl -sL "https://physionet.org/files/cebsdb/1.0.0/b001.${ext}" -o "b001.${ext}"
done
ls -lh b001.*
5.3 读注释,并按通道拆开
注释文件里的两条通道需要分别取出,否则会把"同一搏动的两个时刻"误当成"两个搏动"。
import wfdb
import numpy as np
ann = wfdb.rdann('b001', 'atr', pn_dir='cebsdb')
chan = np.asarray(ann.chan)
samp = np.asarray(ann.sample)
print(sorted(set(ann.symbol))) #-- ['N'],只有一类
print(chan[:6]) #-- [1 0 1 0 1 0],两路交替
ch0 = samp[chan == 0] / 5000.0 #-- 一路注释的时刻(秒)
ch1 = samp[chan == 1] / 5000.0
print(ch0[:5], ch1[:5])
print('两路条数', len(ch0), len(ch1))
如果两路条数不等,说明有搏动只在其中一路被标出——这是判断注释完整性的第一个线索,比直接相信注释更可靠。
5.4 降采样与滤波:先把物理量摆正
5 kHz 对心电是过剩的(诊断级通常 500 Hz 足够),对心震图则刚好——它的有效成分集中在几十赫兹,5 kHz 能保留足够的形态细节。做算法时通常先降到 1 kHz,把计算量降下来,再按通道分别滤波。
import numpy as np
from scipy import signal
def load_1k(name):
rec = wfdb.rdrecord(name, pn_dir='cebsdb')
x = rec.p_signal
#-- 抗混叠后降到 1 kHz
x1k = signal.resample_poly(x, up=1, down=5, axis=0)
return x1k, rec.fs // 5, rec.sig_name
x, fs, names = load_1k('b001')
print(x.shape, fs) #-- (272010, 4) 1000
i_ecg = names.index('I')
s_scg = names.index('SCG')
#-- 心电:0.5–40 Hz 带通;心震图:5–30 Hz 带通
b1, a1 = signal.butter(4, [0.5, 40], btype='band', fs=fs)
b2, a2 = signal.butter(4, [5, 30], btype='band', fs=fs)
ecg = signal.filtfilt(b1, a1, x[:, i_ecg])
scg = signal.filtfilt(b2, a2, x[:, s_scg])
print(ecg.std(), scg.std())
滤波频段不是随手定的。心震图的能量主要集中在 5–30 Hz,这一点在两篇配套论文里都用到了:一篇用连续小波变换在 5–30 Hz 之间选尺度,另一篇用窄带带通做检测。心电则相反,压掉 40 Hz 以上能去掉肌电,压掉 0.5 Hz 以下能去掉呼吸漂移。
| 通道 | 常用分析带宽 | 理由 | 不建议的做法 |
|---|---|---|---|
| 心电 I / II | 0.5–40 Hz | 保 QRS 主能量、去肌电与漂移 | 保留 150 Hz 全带宽直接做检波 |
| 呼吸 | 0.05–0.5 Hz | 呼吸主频在 0.2–0.4 Hz | 用 5 Hz 以上带宽,会混入心跳 |
| 心震图 | 5–30 Hz | 心搏机械成分集中区 | 用 0.5 Hz 高通后直接取峰值 |
5.5 按阶段与受试者组织数据
把 60 条记录组织成可训练的结构,关键是把"受试者"当成分组键,而不是把记录当成独立样本。
import re
import wfdb
import pandas as pd
rows = []
for name in wfdb.get_record_list('cebsdb'):
m = re.match(r'^([bmp])(\d{3})$', name)
if not m:
continue
phase, sid = m.group(1), int(m.group(2))
h = wfdb.rdheader(name, pn_dir='cebsdb')
rows.append({
'record': name, 'subject': sid, 'phase': phase,
'fs': h.fs, 'sig_len': h.sig_len,
'seconds': h.sig_len / h.fs,
})
df = pd.DataFrame(rows).sort_values(['subject', 'phase'])
print(df.groupby('phase')['seconds'].agg(['count', 'min', 'max']))
print(df.groupby('subject').size().value_counts())
跑完这段会得到两张核对表:每个阶段的条数与时长范围,以及每个受试者的记录数分布。后者应该全是 3——如果某人是 2,说明有记录缺失或命名不合规,值得先查清楚再往下做。
5.6 从信号到心搏:一条最小的管线
把前面几步串起来,就是一条可以直接跑的最小管线:读信号、降采样、滤波、用 I 导联检波、以检波结果为参考评估心震图。
import numpy as np
import wfdb
from scipy import signal
def beats_from_ecg(x, fs):
#-- 简化版 Pan-Tompkins:平方、滑动积分、自适应阈值
d = np.diff(x)
sq = d ** 2
win = int(0.15 * fs)
integ = np.convolve(sq, np.ones(win) / win, mode='same')
thr = 0.35 * np.percentile(integ, 99)
above = integ > thr
edges = np.flatnonzero(np.diff(above.astype(int)) == 1)
keep = []
for e in edges:
lo, hi = max(0, e - int(0.05 * fs)), min(len(x), e + int(0.05 * fs))
keep.append(lo + int(np.argmax(np.abs(x[lo:hi]))))
return np.array(keep)
rec = wfdb.rdrecord('b001', pn_dir='cebsdb')
x = rec.p_signal[:, rec.sig_name.index('I')]
fs = rec.fs
pk = beats_from_ecg(x, fs)
rr = np.diff(pk) / fs * 1000.0
print('检出', len(pk), '个心搏,RR 中位数', round(float(np.median(rr)), 1), 'ms')
这条管线的输出不是结论,而是基准。把它换成从 SCG 通道检波,再与这条基准逐搏对齐,就得到论文里那类"误差标准差 + 超阈比例"的指标。注意参考时刻的定义会直接影响指标——用 R 峰还是用模板相关后的修正点,差别在毫秒量级,而这个量级正是要测的东西,所以参考定义必须在方法节写明。
5.7 上手前的三条自查
正式跑算法之前,建议先花十分钟把三件事查一遍。它们都不需要写复杂代码,但能挡掉后面大部分的"结果不对劲"。
| 检查 | 怎么做 | 不合格的样子 | 处理 |
|---|---|---|---|
| 刻度一致 | 读四条头文件的增益,比同一通道的量级 | 两条记录的心震图增益差数十倍 | 换算物理量后再比,或按记录做 z 分数 |
| 时长一致 | 读 sig_len / fs,看是否等于标称时长 |
某条 b 记录只有 272 秒 | 切窗按实际长度,不按常量 |
| 段内平直 | 算每个通道的峰峰值与过零率 | 某段峰峰值接近零或长期饱和 | 按 §4.4 的案例定位坏段并剔除 |
第二条最容易被忽略,因为"五分钟"这个标称值写在文档里,写代码时很容易直接乘 5。实际的采样点数存在逐条差异,只有逐条读 sig_len 才不会在末尾切出越界索引。
第三条的意义在于把"信号质量"从主观判断变成可量化的检查。峰峰值过小说明传感器可能脱开,过大且长期贴边说明饱和,过零率异常升高则常见于电极接触不良。这三种情况在本库里都有对应的官方提示:4 号受试者的异位搏动与 m018 的坏段。
| 指标 | 正常区间的定性判断 | 异常时的常见原因 |
|---|---|---|
| 峰峰值 | 与同类记录的同一通道同量级 | 脱开、增益设置不同 |
| 过零率 | 心电低于心震图,呼吸最低 | 电极接触不良、肌电干扰 |
| 相邻峰间隔 | 集中在某个均值附近 | 漏检、误检、异位搏动 |
§6 与库内相邻数据集的关系
6.1 关系图谱
在站内已有的生理信号记录里,CEBSDB 的位置可以用"模态"与"场景"两个轴摆出来。
| 站内记录 | 模态 | 场景 | 与 CEBSDB 的关系 |
|---|---|---|---|
| INCART 心律失常库 | 十二导联心电 | Holter 长时程 | 互补:它管电的宽度,本库管电与机械的对照 |
| adfecgdb 胎儿心电库 | 腹壁心电 + 头皮直接心电 | 产程监护 | 同为"一路信号当另一路的参考"的结构 |
| BIDMC PPG 呼吸基准 | PPG + 呼吸 + 心电 | ICU 患者 | 同为多模态同步,但人群与场景相反 |
| PICS 早产儿心肺库 | 心电 + 呼吸 | 新生儿监护 | 同类通道组合,人群极端不同 |
| ACTES 递增负荷骑行 | 逐搏记录 | 运动试验 | 对照:运动 vs 静息,正好是本库缺的那一半 |
| AAMI EC13 测试波形 | 合成与真实心电 | 设备合规测试 | 用途不同:那是标准件,这是研究数据 |
6.2 检索路径
| 你要找的东西 | 检索词 | 会落到哪里 |
|---|---|---|
| 心震图相关的其他公开数据 | seismocardiogram、SCG、accelerometer chest |
本库是少数几个之一 |
| 呼吸与心率的耦合 | respiratory sinus arrhythmia、RSA |
§4.2 与 §5.6 |
| 心电与机械模态对齐 | modality alignment、synchronization |
§4.1 |
| 可穿戴心率基准 | wearable、PPG、heart rate benchmark |
§2.5 的对比表 |
| 心搏检测评测协议 | QRS detection benchmark、Seismocardiogram detector |
§5.6 与附录 D |
6.3 与其他库的分工判据
| 任务 | 主粮仓该用什么 | 本库的位置 | 原因 |
|---|---|---|---|
| 心电心搏分类的训练 | 大体量多导联心电库 | 不用 | 只有 20 人、两个导联、无病理 |
| 心震图检测器开发 | 本库几乎无可替代 | 主力 | 同步心电做参考是硬条件 |
| 呼吸率估算模型 | 带呼吸标注的大库 | 辅助 | 有呼吸波形但无呼吸率标注 |
| 运动场景鲁棒性 | 含活动的可穿戴数据 | 不用 | 全程仰卧 |
| 新生儿或 ICU 监护 | PICS、BIDMC 一类 | 不用 | 人群完全错配 |
| 信号处理教学 | 任一小体量多模态库 | 主力之一 | 四通道各代表一种物理量 |
这张表最实用的是第二行与第四行。第二行说明它不可替代的地方在哪里;第四行提醒,任何以"可穿戴"为名的性能声明,用它做验证都不成立。
§7 质量评估与局限性
7.0 阅读本节前的一个前置校正
先纠正一个容易出现的误判:把 60 条记录、20 个人的规模直接判定为"质量差"。规模与质量是两件事。这份数据的采集质量相当高——单机四通道同步、5 kHz 采样、带宽覆盖各模态主能量区、受试者全程不动、异常点被官方逐条列出。它的规模小是设计选择,不是能力不足:做模态对照只需要几十个人,做预训练才需要几万人。
这个校正会改变下面五维评分的读法。规模一项它拿不到高分,文档一项因为缺少注释说明也要扣分,但在"同步质量"与"任务唯一性"上它接近满分。把三项混在一起看,会得出"不值得用"的错误结论;分开看才知道该在什么时候用它。
7.1 五维评分
按 DAIMS 的常用维度打分,每项 1–5 分,分数针对"作为心震图与心电对照研究数据"这个用途:
| 维度 | 分数 | 理由 |
|---|---|---|
| 数据规模 | 2 | 20 人、60 条、约二十小时,训练不足,验证够用 |
| 采集质量 | 5 | 单机同步、5 kHz、带宽匹配各模态,异常点有清单 |
| 标注完整 | 3 | 注释文件存在且格式规范,但语义未文档化 |
| 文档说明 | 4 | 设备、带宽、人群、实验流程写得清楚,缺注释与单位说明 |
| 任务适配 | 5 | 心电与心震图同轴,公开库里几乎找不到替代 |
| 可获取性 | 5 | 免注册、ODC-By、单个 ZIP 可下完 |
六项合计 24 分(满分 30)。分数结构说明它不是全能型选手:规模与标注拖后腿,采集质量与适配性拉满。这个组合正好对应它的定位——一把尺子,不是一个粮仓。
7.2 标注质量的两层
第一层是有没有。答案是有,而且每条记录都有,格式统一,工具链直接可读。这一点比很多只给波形的库要好。
第二层是信不信。这里的信息缺口明显:官方没写谁标的、用什么方法标的、两路注释各代表什么、符号体系是否有扩展。文件里只有正常心搏一类符号,没有节律标记、没有噪声标记、没有质量标记。这意味着注释能回答"心跳大概在哪儿",不能回答"这一搏是不是异常"。
| 用途 | 注释够不够 | 建议 |
|---|---|---|
| 心震图检测器的粗对齐 | 够 | 可直接当初始参考 |
| RR 间期的精确评估 | 勉强 | 建议用自检波结果做交叉验证 |
| 心律失常分析 | 不够 | 库内几乎没有病理样本 |
| 信号质量评估 | 不够 | 无质量标记,需自建规则 |
| 教学演示 | 够 | 配合心电通道讲形态最直观 |
7.3 已知的、可枚举的偏差
| 偏差 | 表现 | 影响 |
|---|---|---|
| 人群偏窄 | 19–30 岁、同一族群、自述健康 | 形态多样性不足,跨人群泛化无从评估 |
| 体位单一 | 全程仰卧不动 | 与真实可穿戴场景错配 |
| 单中心单设备 | 一台 MP36、一套电极、一名操作者 | 设备与操作差异无法被建模 |
| 单位标注习惯 | 四通道统一标 mV,含心震图 | 加速度换算需自建,跨记录幅度比较有风险 |
| 注释语义缺失 | 两路注释未文档化 | 参考时刻的定义权在使用者手里 |
| 已知坏段 | m018 的 II 导联 34–38 分钟 | 按段剔除,参考 §4.4 的案例 |
| 已知异位搏动 | 4 号受试者,集中于 m004 | 做"纯正常"基线时需排除 |
| 阶段时长不齐 | b001 只有 272 秒,两条 m 记录短于 3000 秒 | 切窗代码不能假设等长 |
| 音乐变量不可分解 | 未给曲目、音量、播放方式 | 无法做"某类音乐"的效应分析 |
这张表里被低估的是第四行。单位标注问题不会让程序报错,只会让幅度比较悄悄失真——两条记录的心震图通道增益可能相差数十倍(§2.2 的四条记录对照从七十余到四千余),直接比峰值等于在比放大倍数。
7.4 外部验证矩阵
这份数据在文献里的角色,可以从两篇配套论文看出轮廓:它既是方法研究的实验材料,也是后续同类研究的对照来源。
| 验证角色 | 做法 | 讲得通的地方 | 风险 |
|---|---|---|---|
| 检测器横向比较 | 同一批记录上跑多种检测器,比误差与漏检率 | 参考唯一、场景统一,比较公平 | 只有 20 人,排名对个体敏感 |
| 与心电 RR 的一致性 | 以心电为金标准,量心震图 RR 的偏差 | 同步质量高,误差可归因于算法 | 参考本身也有毫秒级不确定度 |
| 呼吸调制分析 | 按呼吸相位分层统计误差 | 呼吸通道独立同源 | 呼吸相位提取方法会影响结论 |
| 跨库外测 | 在别处训练,在本库测试 | 人群与设备都不同,是真实跨域 | 只能说明"换个场景会掉分",不能定量泛化 |
两篇配套论文给出的参考数字值得记住,但要看清口径:在 17 名受试者的子集上,四种心震图检测器与心电 RR 序列相比,误差标准差平均略高于 2 毫秒,误差超过 30 毫秒的间期占比约在 3.5% 上下。这个量级说明"静息、安静环境下用心震图算 RR 是可行的",但它成立的前提是环境安静、受试者不动、检测器参数经过自适应调整——三个前提在真实场景里都不稳定。
7.5 它为何能持续:因为那道对照题一直有人要做
它没有更新、没有扩版,却被反复引用,原因不是数据本身多好,而是它占着一个别人不愿重复搭的台子:单机四通道同步、心电与心震图同轴、免注册可下载。重新搭一次这样的实验,需要一台多通道生理记录仪、一套胸骨加速度计、二十个愿意躺一小时的人,以及一次伦理审批。对大多数做算法的组来说,用现成数据比自建便宜两个数量级。只要心震图还有人研究,这道对照题就一直有人要做,这个台子就一直有人用。
§8 生态位与历史
8.1 历史沿革
CEBSDB 诞生在 PhysioNet 数据捐赠的成熟期。2010 年代前后,平台已经形成了"统一格式、统一注释体系、机构自愿捐赠"的模式,UPC 这类仪器实验室正好是理想的捐赠方——他们本来就在做心震图方法学研究,实验数据在论文发表后顺手整理成 WFDB 格式交上去,成本很低。
| 阶段 | 时间 | 状态 |
|---|---|---|
| 实验与论文 | 2012–2013 | 17 人子集用于检测器比较研究 |
| 第二篇论文 | 2014 | 导联间 QRS 位置差异与呼吸的关系 |
| 公开捐赠 | 2014 年 12 月 | 20 人全量上线,1.0.0 版 |
| 长期托管 | 2015 至今 | 无版本更新,仅补校验和 |
8.2 从论文子集到公开全量
一个容易被忽略的细节:论文用的是 17 人,公开库是 20 人。多出来的三个人既没有在论文里出现,也没有单独的说明。这带来两个实际后果:一是论文里报告的误差指标不能直接当作全库的基线,因为测试人群不同;二是复现论文结果时,需要先确定那 17 个人是谁——而库里没有给出子集清单,只能按论文的年龄与性别分布去猜,猜不准。
| 项目 | 论文子集 | 公开全量 |
|---|---|---|
| 人数 | 17 | 20 |
| 年龄 | 24.7±3.9 岁 | 19–30 岁 |
| 性别 | 6 女、11 男 | 8 女、12 男 |
| 记录 | 未说明用了哪些 | 60 条 |
| 结果指标 | 误差标准差、超阈比例 | 无官方基线 |
8.3 生态位:模态对照的参考台
| 角色 | 主力粮仓 | 参考台 |
|---|---|---|
| 典型用法 | 大规模训练、预训练 | 算法验证、消融、方法学对照 |
| 需要的前提 | 样本多、标签细 | 同步严格、场景受控、可复现 |
| 代表库 | 大型心电库、可穿戴队列 | 本库、其他小体量多模态库 |
| 失败模式 | 过拟合、标签噪声 | 样本太少导致结论不稳 |
它坐在右边这一列。把参考台当粮仓用,会立刻遇到规模瓶颈;把粮仓当参考台用,会立刻遇到"自己测自己"的问题。
8.4 谁在用它,用来做什么
从公开文献看,使用者集中在三类:做心震图检测算法的信号处理组,把它当标准测试场;做多模态融合的研究组,把它当"两模态严格同步"的少数选项;做生理机制研究的人,用它看呼吸如何调制心搏时刻。第三类最少,但最贴近这份数据的设计初衷。
§9 使用指引
9.1 三种角色的路径
| 角色 | 第一天 | 第一周 | 注意事项 |
|---|---|---|---|
| 算法研究者 | 读官方页面与 README,跑通 §5.2 的读取 | 建立心电参考基线,再替换成心震图检测 | 参考时刻的定义要先定死 |
| 可穿戴工程师 | 抽 b 系列五条跑检波 | 评估静息条件下的上限,再决定是否值得迁移 | 别把静息成绩当产品指标 |
| 教学人员 | 取一条 b 记录画四通道波形 | 讲清电、机械、呼吸三种物理量的差别 | 心震图单位要口头说明一次 |
| 生理机制研究者 | 用呼吸带做相位标记 | 统计 RR 差异随相位的分布 | 剔除异位搏动与坏段 |
9.2 一条最短的可用流程
#-- 1. 只取基线五条,先跑通
for r in b001 b002 b003 b004 b005; do
for ext in hea dat atr; do
curl -sL "https://physionet.org/files/cebsdb/1.0.0/${r}.${ext}" -o "${r}.${ext}"
done
done
#-- 2. 确认头文件里的采样率与通道名
head -n 5 b001.hea
import wfdb
import numpy as np
#-- 3. 读本地文件,确认通道与采样率
rec = wfdb.rdrecord('b001')
print(rec.sig_name, rec.fs, rec.p_signal.shape)
#-- 4. 按秒切窗,取第 60 到 120 秒,看心震图这段是否平直
lo, hi = 60 * rec.fs, 120 * rec.fs
seg = rec.p_signal[lo:hi, :]
print(seg.shape, round(float(np.ptp(seg[:, 3])), 4))
第三段读的是上一步已经下到当前目录的文件,不需要再联网。最后一行输出的是心震图通道在六十秒窗内的峰峰值,用来确认这一段既没有脱落也没有饱和——这个检查比看波形图快,适合在批量处理前先跑一遍。
9.3 引用方式
| 引用对象 | 内容 |
|---|---|
| 数据集 | Combined measurement of ECG, Breathing and Seismocardiograms DataBase, v1.0.0. PhysioNet. 2014. |
| DOI | 10.13026/C2KW23 |
| 原始论文 | García-González 等,心震图心搏检测器比较,Computing in Cardiology 2013 |
| 第二篇论文 | García-González 等,导联间 QRS 位置差异与呼吸,IFMBE Proceedings 41,2014 |
| 平台 | PhysioNet 平台综述论文,按官方页面 Cite 按钮生成 |
写方法节时建议注明:用了哪几条记录、按什么单位划分、参考时刻如何定义、是否剔除 m018 的坏段与 m004 的异位搏动。这四项决定了结果能不能被别人复现。
§10 AI 使用声明
| 项目 | 声明 |
|---|---|
| 文本生成 | 本文由 AI 辅助撰写,结构与事实经人工核对 |
| 数字来源 | 规模、结构、边界三类数字来自 PhysioNet 官方页面与官方文件 |
| 文件核验 | 页面正文、README、info.txt、60 份头文件、b001 注释文件经直接访问确认 |
| 论文信息 | 阅读了 Computing in Cardiology 2013 全文;第二篇仅见题录 |
| 未核验内容 | 注释两路的具体语义、心震图通道对应哪一轴、加速度换算系数 |
| 计算口径 | 总时长由逐条头文件的采样点数除以采样率累加得出 |
| 图像 | 无配图;封面为生成式提示词,不含真实波形 |
| 免责 | 本文不构成临床建议;数据使用须遵守 ODC-By 1.0 署名要求 |
常见误读(避坑清单)
| 说法 | 实际 | 证据 |
|---|---|---|
| 「它有六十个人」 | 20 个人,60 条记录,每人三条 | 记录名首字母分三组,后三位只有 001–020 |
| 「心震图通道单位是毫伏」 | 标注是毫伏,物理量是加速度 | 头文件四通道均写 /mV,与传感器物理量不符 |
| 「各记录增益差不多,可直接比幅度」 | 心震图增益跨度接近七十倍 | b001 与 m001 的 .hea 第三字段对照 |
| 「注释是人工逐搏确认的 R 峰」 | 两路注释,语义未文档化 | 官方页面与 README 均未说明注释来源 |
| 「它是五十分钟连续记录」 | 每人三段,最短五分钟,最长五十分钟 | 头文件采样点数除以 5000 |
| 「按记录随机切分就行」 | 同一人的三条必须整体划分 | 记录名后三位即受试者编号 |
| 「它是可穿戴验证集」 | 全程仰卧不动、清醒 | 官方实验流程描述 |
| 「它有十二导联」 | 只有 I、II 两个肢体导联 | 头文件通道名 |
| 「它采样率是 250 Hz 一类」 | 5 kHz,四通道相同 | 头文件第 1 行第 3 字段 |
| 「m018 整条不能用」 | 只有 II 导联第三十四到三十八分钟差 | 官方异常说明 |
| 「它是 60 个独立样本」 | 有效样本量是 20 个受试者 | 每人三条高度相关 |
FAQ
Q1:CEBSDB 有多少条记录,为什么是三条一组?
共 60 条,20 名志愿者每人三条。b 开头是入室后的五分钟基线,m 开头是听古典音乐期间约五十分钟,p 开头是音乐结束后五分钟。同一编号的三条来自同一个人、同一次实验,只有阶段不同。
Q2:心震图通道能直接当加速度用吗?
不能。头文件把四个通道的单位统一写成毫伏,心震图通道也不例外,而它的物理量应是加速度。官方没给换算系数,也没说这一路对应三轴中的哪一轴或是合成幅值。跨记录比较幅度前必须先自己标定。
Q3:它的注释能直接训练心搏检测器吗?
可以当初始参考,但不能当金标准。注释文件里每个心动周期有两条注释,分属两个通道,符号只有正常心搏一类。官方没写这两路各代表什么,建议先用 I 导联自检波对齐一次再决定。
Q4:为什么它常被用来评估从心震图算 RR 的方法?
因为它把心电与心震图放在同一根时间轴上,采样率同为 5 kHz,同步误差只由采集系统决定。心电 R 峰当参考时刻,心震图的机械振动当被测对象,两者的差就是方法误差,不需要额外配准。
Q5:训练集和测试集该怎么划分?
按受试者编号划分。同一个人的三条记录共享同一副胸骨、同一套电极位置、同一段呼吸习惯,随机按记录切分会把受试者特有的形态泄漏到测试集。只有 20 个人,建议留一法或五折分组交叉验证。
Q6:它能不能用来做心律失常分类?
不建议。全部受试者自述健康,官方只提到 4 号受试者有少量异位搏动,尤其集中在 m004。库内几乎没有病理样本,训练分类器学不到异常形态。
Q7:为什么采样率要 5 kHz 这么高?
心震图的有效成分在几十赫兹,5 kHz 能保留足够的形态细节,也便于做毫秒级的时刻对齐。代价是体积大:一秒四万字节,五十分钟一条就有一百余兆。做算法时通常先降到 1 kHz。
Q8:m018 那条记录的 II 导联有问题,还能用吗?
能,但第三十四到三十八分钟这一段要处理。官方说明是电极接触不良导致的信号质量差,I 导联未受影响,所以这段可以改用 I 导联做参考,或按时间窗剔除。
Q9:它和 INCART 之类的心电库是什么关系?
互补而不是替代。INCART 提供十二导联长时程心电,用来研究电活动本身;CEBSDB 提供两路心电加一路胸骨加速度,用来研究电与机械的对应。两者的任务对象不同。
Q10:体量多大,能一次下完吗?
未压缩 2.7 GB,ZIP 包 1.6 GB,可以一次下完。只是 m 系列占了九成体积,如果只做流程验证,先下 b 系列五条就够,总共几十兆。
Q11:它的许可允许商业使用吗?
ODC-By 1.0 允许,包括商业用途,条件是署名。引用时写清数据集名称、版本、DOI 与来源,具体条款以许可全文为准。
Q12:为什么十年没有更新?
官方没有给出扩版说明。从数据性质看,这类实验每增加一个人都要重走一次贴传感器、躺一小时的流程,增量成本高而边际价值低,1.0.0 覆盖了它想回答的问题,没有非更新不可的理由。
术语表
| 术语 | 解释 |
|---|---|
| 心震图(SCG) | 记录胸壁因心脏搏动产生的微小加速度信号 |
| 心电(ECG) | 记录心肌电活动在体表形成的电位差 |
| 心冲击图(BCG) | 记录身体整体因射血产生的位移,频段低于心震图 |
| RR 间期 | 相邻两次 R 峰之间的时间,反映瞬时心率 |
| 心率变异性 | RR 间期的波动,反映自主神经调节 |
| 呼吸性窦性心律不齐 | 心率随呼吸周期波动的正常现象 |
| AO 点 | 主动脉瓣开放对应的机械事件,心震图主要成分之一 |
| MC 点 | 收缩期主峰,心震图里幅度最大的成分 |
| 检波 | 从信号里找出心搏时刻的算法过程 |
| 参考时刻 | 评测时用作"正确答案"的心搏时刻 |
| 漏检与误检 | 漏掉真实心搏 / 把非心搏判成心搏 |
| 呼吸相位 | 呼吸周期中的相对位置,吸气与呼气对应不同相位 |
| 胸带压阻 | 用电阻变化测胸廓周长的传感器原理 |
| MEMS 加速度计 | 微机电加速度传感器,心震图的常用器件 |
| WFDB | PhysioNet 使用的波形数据库格式 |
.hea |
纯文本头文件,声明采样率、通道、增益 |
.dat |
二进制信号文件,多通道按帧交错 |
.atr |
二进制注释文件,存放事件时刻与符号 |
| 增益 | 每毫伏对应的整数值,换算物理量时使用 |
| ADC 零值 | 零电平对应的整数,换算时先减 |
| 抗混叠 | 降采样前先低通,避免高频折叠进低频 |
| 带通滤波 | 只保留某频段,压掉更高与更低的成分 |
| 分组交叉验证 | 以受试者为组划分训练与测试 |
| 数据泄漏 | 测试信息以某种方式进入训练,导致成绩虚高 |
| ODC-By | 开放数据共享署名许可 |
附录 A:核心数字核对表
| 项 | 值 | 来源 | 来源层级 |
|---|---|---|---|
| 记录数 | 60 | 官方页面;RECORDS 清单 | 官方页面 |
| 受试者数 | 20 | 官方页面;info.txt | 官方页面 |
| 每人记录数 | 3 | 记录名规则与官方流程描述 | 官方页面 |
| 通道数 | 4 | 全部 60 份头文件 | 官方文件 |
| 采样率 | 5 kHz | 官方页面;头文件 | 官方页面 |
| 位深 | 16 位 | 头文件信号行 | 官方文件 |
| 心电带宽 | 0.05–150 Hz | 官方页面;README | 官方页面 |
| 呼吸带宽 | 0.05–10 Hz | 官方页面;README | 官方页面 |
| 心震图带宽 | 0.5–100 Hz | 官方页面;README | 官方页面 |
| 基线段时长 | 272–300 秒 | 逐条头文件 | 官方文件 |
| 音乐段时长 | 2841.5–3000 秒 | 逐条头文件 | 官方文件 |
| 音乐后段时长 | 300 秒 | 逐条头文件 | 官方文件 |
| 总时长 | 约 19.9 小时 | 由头文件采样点累加得出 | 推算 |
| 未压缩体积 | 2.7 GB | 官方页面 | 官方页面 |
| 心震图增益跨度 | 74–4948(四条记录对照) | b001、m001、p001、m018 头文件 | 官方文件 |
| ZIP 体积 | 1.6 GB | 官方页面 | 官方页面 |
| 年龄范围 | 19–30 岁 | info.txt | 官方文件 |
| 性别构成 | 12 男 8 女 | info.txt | 官方文件 |
| 许可 | ODC-By 1.0 | 官方页面 | 官方页面 |
| DOI | 10.13026/C2KW23 | 官方页面 | 官方页面 |
| 发布日期 | 2014-12-12 | 官方页面 | 官方页面 |
附录 B:数字的来源分层
第一层:官方页面与官方文件。 记录数、受试者数、通道、采样率、三段流程、各路带宽、设备型号、传感器型号、电极型号、许可、DOI、发布日期、体积、两条已知异常。这些来自项目主页、README 与 info.txt。
第二层:头文件与注释文件的逐条核对。 各段实际时长、采样点数、每通道增益、注释的通道数与符号种类。这些不是官方文字描述,而是文件本身的字段,可直接复现。
第三层:论文与推算。 17 人子集的年龄、性别、BMI 与误差指标来自 Computing in Cardiology 2013 全文;总时长由逐条采样点累加得出;注释两路的语义属推断,未获官方确认。
附录 C:完整参考文献
| 编号 | 文献 | 链接 | 用途 |
|---|---|---|---|
| 1 | CEBSDB 项目页 v1.0.0 | https://physionet.org/content/cebsdb/1.0.0/ | 全部规模、结构、边界数据 |
| 2 | 项目文件目录 | https://physionet.org/files/cebsdb/1.0.0/ | 头文件、清单、info.txt |
| 3 | García-González 等,心震图心搏检测器比较,CinC 2013 | http://www.cinc.org/archives/2013/pdf/0461.pdf | 实验流程、子集人群、误差指标 |
| 4 | García-González 等,导联间 QRS 位置差异与呼吸,IFMBE 2014 | https://doi.org/10.1007/978-3-319-00846-2_238 | 第二个研究目的 |
| 5 | PhysioNet 平台综述 | https://doi.org/10.1038/s44360-026-00096-z | 托管与引用规范 |
| 6 | WFDB 格式说明 | https://physionet.org/physiobank/wfdb/ | 三件套格式与读取方式 |
附录 D:任务代码
任务一:把两路注释拆开并检查一致性
import wfdb
import numpy as np
def split_ann(name):
ann = wfdb.rdann(name, 'atr', pn_dir='cebsdb')
samp = np.asarray(ann.sample)
chan = np.asarray(ann.chan)
return {c: samp[chan == c] for c in np.unique(chan)}
for name in ['b001', 'b002', 'm004', 'm018']:
d = split_ann(name)
info = {c: len(v) for c, v in d.items()}
gap = []
if 0 in d and 1 in d:
a, b = d[0], d[1]
n = min(len(a), len(b))
gap = (b[:n] - a[:n]) / 5000.0 * 1000.0
print(name, info, '成对中位间隔 ms =',
round(float(np.median(gap)), 2) if len(gap) else None)
任务二:心电参考与心震图检波的误差对比框架
import numpy as np
import wfdb
from scipy import signal
def ref_beats(ecg, fs):
d = np.diff(ecg)
integ = np.convolve(d ** 2, np.ones(int(0.15 * fs)) / int(0.15 * fs), 'same')
thr = 0.35 * np.percentile(integ, 99)
edges = np.flatnonzero(np.diff((integ > thr).astype(int)) == 1)
out = []
for e in edges:
lo, hi = max(0, e - int(0.05 * fs)), min(len(ecg), e + int(0.05 * fs))
out.append(lo + int(np.argmax(np.abs(ecg[lo:hi]))))
return np.array(out)
def test_beats(scg, fs):
b, a = signal.butter(4, [5, 30], btype='band', fs=fs)
s = signal.filtfilt(b, a, scg)
env = np.abs(signal.hilbert(s))
thr = 0.5 * np.percentile(env, 99)
edges = np.flatnonzero(np.diff((env > thr).astype(int)) == 1)
out = []
for e in edges:
lo, hi = max(0, e - int(0.05 * fs)), min(len(s), e + int(0.05 * fs))
out.append(lo + int(np.argmax(env[lo:hi])))
return np.array(out)
rec = wfdb.rdrecord('b002', pn_dir='cebsdb')
fs = rec.fs
ref = ref_beats(rec.p_signal[:, 0], fs)
tst = test_beats(rec.p_signal[:, 3], fs)
print('参考', len(ref), '检出', len(tst))
#-- 逐搏配对,只保留 30 ms 内的偏差
pairs = [(r, t) for r in ref for t in tst if abs(r - t) < 0.03 * fs]
err = np.array([(t - r) / fs * 1000.0 for r, t in pairs])
print('配对数', len(err), '误差中位数 ms', round(float(np.median(np.abs(err))), 2))
这两段代码的作用是搭一个可比较的框架,不是给出结论。参考与检波的规则一旦确定,换任何检测器都能放进同一个框架里跑,这样不同方法之间的差异才可归因。
附录 E:如果只记五件事
| 序号 | 记住什么 | 为什么 |
|---|---|---|
| 1 | 20 人、每人三段、共 60 条,四通道 5 kHz | 这几个数字决定了它全部用法与限制 |
| 2 | 心电是尺子,心震图是被测对象 | 它的全部价值建立在同步上 |
| 3 | 心震图单位标 mV,物理量是加速度 | 跨记录比较幅度前必须自建标定 |
| 4 | 按受试者划分,不按记录划分 | 同一人三条记录的泄漏会让结果虚高 |
| 5 | 全程仰卧不动、健康年轻人 | 任何可穿戴性能声明都不能用它背书 |
编辑说明
本文的核验时间为 2026 年 10 月 28 日。核对方式为直接访问 PhysioNet 项目页与文件目录,读取页面正文、README.txt、info.txt,并逐条取回 60 份头文件核对采样点数与通道声明;注释文件只取 b001 一份做结构核对。论文侧阅读了 Computing in Cardiology 2013 全文,第二篇仅见题录。未覆盖的内容包括:注释两路的具体语义、心震图通道对应三轴中的哪一轴或是否为合成幅值、加速度换算系数、受试者层面的原始临床记录。这些官方均未公布,正文涉及处只做定性表述并标注为推断。
相关数据集导航
以下为站内 AI-Ready 数据集百科中与本词条共享多个主题标签的相关数据集,按相关度降序排列:
- cardiac-accel-canine-porcine — 共享标签:生理信号 / 心电信号 / 可穿戴传感 / 心血管疾病
- tollet — 共享标签:生理信号 / 心电信号 / 可穿戴传感 / 心血管疾病
- icentia11k — 共享标签:生理信号 / 心电信号 / 可穿戴传感 / 心血管疾病
- cinc-2011 — 共享标签:生理信号 / 心电信号 / 可穿戴传感 / 心血管疾病
- butppg — 共享标签:生理信号 / 心电信号 / 可穿戴传感 / 心血管疾病
- cardiowave-portable — 共享标签:生理信号 / 心电信号 / 可穿戴传感 / 心血管疾病
- auricle-wearable-cv — 共享标签:生理信号 / 心电信号 / 可穿戴传感 / 心血管疾病
- butqdb — 共享标签:生理信号 / 心电信号 / 可穿戴传感
- drivedb — 共享标签:生理信号 / 心电信号 / 可穿戴传感
- physionet-cinc-2017 — 共享标签:生理信号 / 心电信号 / 可穿戴传感 / 心血管疾病
导航说明:本章节由全站统一标签体系自动计算生成(标签重合度算法),双向可达;点击链接可跳转至对应数据集词条。

