信息速览
一个人整夜躺在一间贴满电极的房间里,鼻子下面插着气流管,胸口与腹部各绑一条呼吸带,手腕上有一条动脉管路在持续测压。这些信号被同时写到纸上,或者写进磁带。第二天早上,医生翻看这一叠资料,每三十秒划一格,决定这一格算浅睡还是深睡,以及中间有没有停止呼吸。
这就是多导睡眠图。它出现于上世纪七十年代,是睡眠医学的临床金标准,也是所有后续自动化分期方法的参照物。MIT-BIH 多导睡眠图数据库记录的是这项检查在八十年代末的样子:十六名因打鼾与白天嗜睡被送进波士顿一家医院睡眠实验室的男性,一段两小时到七小时不等的整夜信号,以及一份按当时标准划出的分期表。
库名 slpdb 里的 SLP 指的是 polysomnography,也就是多导睡眠图,不是睡眠一词的缩写。这一点常被误读,误读之后往往会把它当成某个睡眠分期基准的别称。本篇按官方页面与文件本身的口径把这个库讲清楚:它测了什么、怎么标、能用在哪、在哪会失灵。一屏速览见下表。
| 维度 | 内容 |
|---|---|
| 全名 | MIT-BIH Polysomnographic Database |
| 库名缩写 | slpdb(SLP 指 polysomnography,多导睡眠图) |
| 发布方 | PhysioNet,托管于 MIT 计算生理实验室 |
| 整理者 | George B. Moody |
| 首次发布 | 1999 年 8 月 3 日,版本 1.0.0 |
| DOI | 10.13026/C23K5S(最新版 10.13026/3p18-8q66) |
| 配套论文 | Ichimaru 与 Moody,《Psychiatry and Clinical Neurosciences》1999 年第 53 卷增刊 |
| 受试者 | 16 名男性成人,平均 40 岁,范围 32 至 56 岁 |
| 记录数 | 18 段 |
| 每段时长 | 2 至 7 小时,合计约 85.6 小时 |
| 采样率 | 250 Hz,每样本 12 位 |
| 通道 | 4 路或 7 路,随记录而变 |
| 信号种类 | 心电、脑电、眼电、肌电、有创血压、血氧、鼻与胸腹呼吸、心输出量 |
| 分期标准 | Rechtschaffen 与 Kales 五期 |
| 标注粒度 | 30 秒一格,含睡眠期与呼吸事件符号 |
| 文件格式 | WFDB(头文件 + 波形 + 注释) |
| 体积 | 未压缩 632.3 兆字节 |
| 许可 | ODC-BY 1.0,免注册 |
| 缺什么 | 健康对照、多导脑电、AASM 分期、完整整夜覆盖 |
§1 它要解决的具体麻烦
1.1 睡眠信号曾经只活在纸上
在数字存储普及之前,一次多导睡眠检查留下来的是一卷卷热敏纸。纸带很宽,几十路信号并排走,医生用尺子和彩色笔在上面标出分期。这份记录能看,但不能算。
不能算的意思是:想在整夜信号上做一次频谱分析,得先把纸带扫描、对齐、手工描点,再输进计算机。换一个方法就得重来一遍。不同中心之间的记录也无法直接比较,因为纸速、增益、导联位置全凭各家习惯。
这个库最初的动机就写在官方背景里:把多导睡眠记录做成数字格式,让波形与标注能一起被机器读。它明确说自己沿用了 MIT-BIH 心律失常库的做法,最初以 CD-ROM 分发。这一点很重要——它不是一个为比赛准备的数据集,而是把一种纸面检查搬进计算机的一次工程尝试。
于是它的设计目标也很清楚:服务于睡眠呼吸暂停的生理学研究、非线性动力学分析、自动信号处理方法的开发与评估,以及睡眠生理与分期的教学。这四项目标里,只有第三项与今天的机器学习工作流部分重叠。
1.2 三条常见的错误期待
第一条,期待它是 sleep 的缩写,因而是个睡眠分期基准。 slpdb 里的 SLP 来自 polysomnography。它是多导睡眠图,不是睡眠本身;它是检查,不是基准。库里确实有分期标注,但分期只是它附带的一层信息,主体是那几路生理波形。
这个误读会连带出第二个问题:把它当成睡眠分期的训练集。18 段记录、16 个人、单导脑电,用这个体量训练分期模型,参数还没收敛就过拟合了。
第二条,期待它有几十路标准脑电。 官方写的是单导脑电,而且导联在记录之间并不统一:早期几段用中央与耳垂之间的导联,中期换成中央与枕部,后期又回到中央与耳垂。指望在里面找到一条从头前到枕部的梯度,会失望。
第三条,期待它按现行的分期标准标注。 官方写明按 Rechtschaffen 与 Kales 的标准分期,也就是 1968 年提出、七十到八十年代通行的五期体系。它与后来的 AASM 体系并不等价,把 W、1、2、3、4、R 直接映射成 W、N1、N2、N3、R,会在 3 与 4 这两期上出错。
1.3 它能给到的与给不到的
| 你的需求 | 它给的 | 够不够 |
|---|---|---|
| 整夜生理信号的长时段观察 | 18 段,每段 2 至 7 小时 | 够,正是它的设计用途 |
| 呼吸暂停事件与分期的配对 | 同一份注释里既有分期符号也有事件符号 | 够,两类标签同源 |
| 有创血压与心输出量的连续曲线 | 多数记录含动脉压,部分含心输出量 | 够,这是它最稀有的部分 |
| 自主神经与呼吸的耦合分析 | 心电、呼吸、血压同时存在 | 够,三路时间对齐 |
| 深度学习分期训练 | 16 人、单导脑电 | 不够,容量差一到两个数量级 |
| 多导脑电的空间分析 | 只有一路,且导联不统一 | 不够 |
| AASM 标准的五类分期 | 只有 R&K 六符号 | 不够,需自行映射且不可逆 |
| 健康人与患者的对照 | 全部为 OSA 评估者 | 不够,没有对照组 |
1.4 你的处境与它能帮到的事
| 你的处境 | 它能帮你什么 | 下一步该做什么 |
|---|---|---|
| 你在做呼吸暂停的生理机制,想看看暂停前后血压怎么变 | 有创血压与呼吸事件在同一时间轴上 | 先按 §5.3 把事件注释读出来,再对齐血压 |
| 你在验证一个自动分期模型,想知道它跨中心还能不能用 | 一份 1990 年代的参照读数,标准与今天不同 | 先把 R&K 映射到 AASM,再报告混淆矩阵 |
| 你要做非线性动力学,需要一个长时段的多通道样例 | 每段数小时连续记录,采样 250 赫兹 | 挑一段七路齐全的,按 §4.4 的案例先看清噪声 |
| 你在教学,要讲清一次睡眠检查的完整链路 | 从电极、管路到注释符号,全部有据可查 | 用四路的那一段做演示,学生一眼能看懂 |
| 你要训练一个分期模型 | 16 人、单导脑电 | 换库,把它当外部验证集 |
| 你要做多模态融合 | 信号种类多,但脑电只有一路 | 可以拿来做早期融合的玩具实验 |
1.5 一句话判断
它不是一份用来训练模型的数据,而是一份用来理解「睡眠这一整夜在被仪器观测时究竟长什么样」的原始档案。
1.6 不适合谁:四条边界
不适合拿它训练深度学习分期模型。 16 名受试者、18 段记录、单导脑电,这三条中的任何一条都足以让训练不成立。把它当主训练集,得到的模型学到的是这 16 个人的脑电与呼吸习惯,换一家医院就失效。
不适合拿它做标准脑电分析。 单导意味着没有空间信息,导联不统一意味着连"同一位置"都不能保证。做频段功率可以,做相干、空间滤波或源定位都不成立。
不适合拿它直接与 AASM 标注的库比较。 分期体系不同,事件定义也不同。任何跨库的准确率对比,都必须先说明映射规则,否则比较的是两套判据而不是两个模型。
不适合拿它代表一般人群。 全部受试者是男性,且都是从 60 人队列里挑出的睡眠呼吸暂停评估对象。关于女性、儿童或健康人的任何推论,都超出了这批数据的边界。
§2 数据构成与规格
2.1 一个扁平目录、十八组三件套
整个库的顶层是扁平的。每段记录对应三个文件:一个波形数据文件、一个头文件、一个注释文件。文件名共用同一个主干,靠扩展名区分。
主干名有三种形态:slp01a、slp02b 这类带后缀的,表示同一名受试者的不同时段;slp03 这类不带后缀的,表示一整段;slp67x 这种带 x 的,官方未说明它对应哪一名受试者。记录清单 RECORDS 逐行列出这十八个主干名。
| 顶层项 | 体积 | 作用 | 能否省 |
|---|---|---|---|
十八对 .dat 与 .hea |
主体 | 波形与头信息 | 不能 |
十八个 .st 与 .st- |
主体 | 睡眠分期与事件注释 | 不能,标签都在这里 |
十八个 .ecg 与 .ecg- |
辅助 | 心搏逐拍注释 | 分析心率时必需 |
十八个 .xws |
极小 | 查看器的窗口设置 | 可以省,与数据无关 |
| RECORDS | 113 字节 | 十八行主干名 | 不能,是遍历入口 |
| README.st | 335 字节 | 分期与事件符号释义 | 不能,是唯一的标签字典 |
| ANNOTATORS | 137 字节 | 注释文件的来源说明 | 建议留 |
| dbcal | 1.2 KB | 各信号的默认标定与绘图刻度 | 建议留 |
| SHA256SUMS.txt | 8.4 KB | 全库校验和 | 建议留,用于完整性核对 |
体积上有一条明显的分层:四路记录的 .dat 多在十到三十一兆之间,七路记录多在三十到五十九兆之间。单段最大的是 slp41,五十八点六兆;最小的是 slp01a,十点三兆。这个分层完全由通道数与时长决定,没有额外的压缩。
.st- 与 .st 成对出现,.ecg- 与 .ecg 也成对出现,这是一处需要留意的细节。官方没有解释为什么同时保留两版;从文件修改时间看,不带减号的版本更晚。稳妥的做法是用不带减号的那一份,并在方法里写明选了哪一版。
2.2 字段与记录的完整字典
头文件是本库唯一的结构化元信息。它的第一行描述整段记录,之后每路信号一行。以 slp37 为例,第一行是记录名、通道数、采样率、每样本的采样点数、样本总数、起始时刻与起始日期。
| 头文件字段 | slp37 的取值 |
含义与注意点 |
|---|---|---|
| 记录名 | slp37 | 与文件名主干一致 |
| 通道数 | 7 | 本段为七路,另有四路与六路的记录 |
| 采样率 | 250/0.033333333 | 每秒二百五十个采样点 |
| 采样点计数 | 5250000 | 与采样率相除得时长 |
| 起始时刻 | 0:08:30 | 多数记录跨零点,所以从午夜后计时 |
| 起始日期 | 10/8/1989 | 日/月/年,不是月/日/年 |
| 信号行格式 | 文件名 格式 增益 位宽 基线 初值 校验 块长 描述 | 格式码 212 表示 12 位打包 |
信号行的字段顺序固定,但内容随记录而变。第一路固定是心电,第二路固定是动脉压,第三路固定是脑电,之后是呼吸与其他。也就是说,通道的语义由描述字符串给出,而不是由位置决定。
| 信号描述 | 单位 | 出现记录数 | 说明 |
|---|---|---|---|
| ECG | 毫伏 | 18 | 全部记录都有,用于逐拍心率 |
| BP | 毫米汞柱 | 18 | 有创动脉压,全部记录都有 |
| EEG(四种导联之一) | 毫伏 | 18 | 单导,导联随记录而变 |
| Resp(鼻腔、胸部、腹部或合计) | 升 | 18 | 一路或两路,命名不统一 |
| EOG(右眼) | 毫伏 | 8 | 只有七路记录的后期批次有 |
| EMG(下颌) | 毫伏 | 6 | 六段七路记录里出现 |
| SV | 毫升 | 5 | VEST 系统的心输出量 |
| SO2 | 百分比 | 5 | 血氧饱和度 |
八个种类里,前三路是全部记录共有的骨架,后五种是批次差异。这条规律决定了任何跨记录的分析都必须先按通道筛选,不能假定通道数一致。
还有一处必须点明:把采样率那一项写成小数时分母时,官方头文件用的是 0.033333333,它与 1/30 只差最后一两位。若严格照字面相乘,十八段记录合计会算成七百多小时;按 250 赫兹的标准口径相乘,合计约八十五点六小时,与官方「2 至 7 小时」的区间吻合。差异来自这个近似分母,根子在 WFDB 的头文件字段规定,不在数据本身。
2.3 一条记录的完整解剖
把 slp37 从头拆一遍,能看清这批数据的组织逻辑。它是一段七路记录,五十二万五千个采样点乘七路,约三兆个采样值。
#-- 逐层解剖一段记录:头、通道、时长
import wfdb
rec = wfdb.rdheader("slp37")
print("通道数", rec.n_sig)
print("采样率", rec.fs)
print("时长秒", rec.sig_len / rec.fs)
print("起始", rec.base_time, rec.base_date)
for i, name in enumerate(rec.sig_name):
print(i, name, rec.units[i])
#-- 注释里有哪些种类,取前三个文件的符号集合
ann = wfdb.rdann("slp37", "st")
print("注释条数", len(ann.sample), "符号集合", sorted(set(ann.symbol)))
跑完会看到三层:头文件给出七路信号与统一采样率;波形文件按 212 格式打包,每三个字节装两个采样点,字节次序与位序在 WFDB 里有明确规定;注释文件按符号流存放,每个符号带一个采样点位置。
再往下看注释的时间轴。分期注释的间隔固定为一秒,而每一格代表的时长是三十秒,也就是说每三十条注释里只有第一条携带分期语义。这个设计来自注释文件格式本身:注释以固定节拍写入,节拍由注释文件头部声明。
| 解剖层级 | 内容 | 数量 | 备注 |
|---|---|---|---|
| 库 | 十八段记录 | 18 | 扁平存放 |
| 记录 | 一名受试者的一段整夜 | 2 至 7 小时 | 主干名唯一 |
| 文件三件套 | 头、波形、注释 | 3 类 | 另有心搏注释与查看器配置 |
| 信号 | 一路生理量 | 4、6 或 7 | 种类由描述串给出 |
| 采样点 | 一路信号的一个时刻 | 每秒 250 个 | 12 位量化 |
| 分期格 | 三十秒一格 | 时长除以三十 | 每格覆盖整段 |
| 事件 | 一次暂停或低通气 | 不等 | 与分期符号同处一份注释 |
2.4 十八段记录的通道与时长分布
把十八段记录按通道数分组,结构立刻清晰:前八段是四路,中间一段是六路,后九段是七路。这个顺序与采集时间基本吻合,反映的是监测方案的逐步扩充,并非数据缺失。
| 记录 | 通道数 | 时长(小时) | 脑电导联 | 脑电之外的呼吸与辅助信号 |
|---|---|---|---|---|
| slp01a | 4 | 约 2.0 | C4-A1 | 呼吸合计一路 |
| slp01b | 4 | 约 3.0 | C4-A1 | 鼻腔呼吸 |
| slp02a | 4 | 约 3.0 | O2-A1 | 鼻腔呼吸 |
| slp02b | 4 | 约 2.3 | O2-A1 | 鼻腔呼吸 |
| slp03 | 4 | 约 6.0 | C3-O1 | 鼻腔呼吸 |
| slp04 | 4 | 约 6.0 | C3-O1 | 鼻腔呼吸 |
| slp14 | 4 | 约 6.0 | C3-O1 | 鼻腔呼吸 |
| slp16 | 4 | 约 6.0 | C3-O1 | 鼻腔呼吸 |
| slp32 | 7 | 约 5.3 | C4-A1 | 鼻腔、胸部、眼电、肌电 |
| slp37 | 7 | 约 5.8 | C4-A1 | 鼻腔、腹部、眼电、肌电 |
| slp41 | 7 | 约 6.5 | C4-A1 | 鼻腔、腹部、眼电、肌电 |
| slp45 | 7 | 约 6.3 | C3-O1 | 鼻腔、腹部、眼电、肌电 |
| slp48 | 7 | 约 6.3 | C3-O1 | 鼻腔、胸部、眼电、肌电 |
| slp59 | 7 | 约 4.0 | C3-O1 | 鼻腔、腹部、心输出量、血氧 |
| slp60 | 7 | 约 5.9 | C3-O1 | 鼻腔、腹部、心输出量、血氧 |
| slp61 | 6 | 约 6.2 | C3-O1 | 腹部、心输出量、血氧 |
| slp66 | 7 | 约 3.7 | C3-O1 | 鼻腔、腹部、心输出量、血氧 |
| slp67x | 7 | 约 1.3 | C3-O1 | 鼻腔、胸部、心输出量、血氧 |
三种导联的分布也有规律:C4-A1 出现在早期与中段,C3-O1 出现在中后段,O2-A1 只在两段记录里出现。想按导联分组做分析,只能得到两三组各自很小的样本。
时长短的记录有三段:slp67x 约一点三小时,slp01a 约两小时,slp02a 与 slp02b 约两到三小时。官方给出的区间是 2 至 7 小时,slp67x 已经落到区间之外,这是本库内部一处尚未说明的不一致:官方按整段记录描述,而短记录可能只是同一夜的片段。
2.5 与同类资源的字段差异
把本库放进睡眠类资源里横向比,最能看出它的位置:信号种类最杂,通道数最少,分期标准最老。
| 字段维度 | 本库 | 大型队列 PSG | 现代临床 PSG | 单导或可穿戴设备 |
|---|---|---|---|---|
| 受试者规模 | 16 | 数千至上万 | 数百 | 数十至数千 |
| 每夜记录完整性 | 多为 2 至 7 小时 | 多为完整整夜 | 多为完整整夜 | 多为完整整夜 |
| 脑电通道数 | 1 | 2 至 6 | 6 至 19 | 1 至 2 |
| 有创血压 | 有 | 无 | 无 | 无 |
| 心输出量 | 部分有 | 无 | 无 | 无 |
| 分期体系 | R&K 五期 | 多为 AASM | AASM | 多为 AASM |
| 事件标注 | 合并符号 | 分列的多类标签 | 分列的多类标签 | 常缺失 |
| 许可 | 免注册 | 多为申请制 | 多为申请制 | 各异 |
它的信息密度集中在「有创血压与心输出量」这两列——这两样今天在睡眠监测里几乎绝迹,因为都需要血管内置管。其它维度大多落后,尤其受试者规模与分期标准的年代感。
2.6 六百多兆的体积与三条获取路径
官方给出的未压缩体积是六百三十二点三兆字节,整包 ZIP 是六百三十二点四兆。两者的差别来自压缩包自身的目录开销。对一个八十五小时、四到七路、250 赫兹的库来说,这个数字可以自己验算:八十五点六小时乘三千六百秒乘二百五十赫兹乘七路乘一点五字节,量级正好对上。
获取方式有三条:整包 ZIP、wget 递归、AWS 开放桶同步。前两条从同一个目录取文件,第三条从公开桶取同一批对象。三条内容一致。对一个六百多兆的库,三者的差别主要在断点续传与并行度上。
2.7 用一行命令把主干名与文件对齐
#-- 只取记录清单与注释说明,不必先下整包
BASE="https://physionet.org/files/slpdb/1.0.0"
mkdir -p slpdb && cd slpdb
curl -sSL -O "$BASE/RECORDS"
curl -sSL -O "$BASE/README.st"
curl -sSL -O "$BASE/ANNOTATORS"
#-- 核对清单行数应为十八
wc -l RECORDS
#-- 顺带看一眼分期符号的释义
cat README.st
wc -l 输出十八说明清单完整。同时拿到的 README.st 只有三百多字节,却是全库唯一解释 W、1、2、3、4、R 与 H、OA、CA 这些符号含义的文件,先读它比先下波形更划算。
§3 它是谁的记录:一间睡眠实验室与一次 CD-ROM 工程
3.1 一位整理者与一家实验室
官方页面把作者写成 George Moody 一人,机构记为 MIT 计算生理实验室。这不是说整夜监测由他完成:采集在波士顿的贝斯以色列医院睡眠实验室进行,是他把记录整理成可在机器间流转的数字格式并托管到平台上。
配套论文的作者是两人:Ichimaru 与 Moody。前者来自日本,工作与睡眠生理有关;后者是 MIT 一侧的工程负责人。论文标题直译是《光盘版多导睡眠图数据库的开发》。
| 角色 | 姓名或机构 | 承担的工作 | 出处 |
|---|---|---|---|
| 页面署名 | George Moody | 数字格式整理、注释复核、平台托管 | 官方页面 |
| 论文第一作者 | Ichimaru | 睡眠生理与分期判读 | 配套论文 |
| 论文第二作者 | Moody | 数据工程与工具开发 | 配套论文 |
| 采集地点 | 贝斯以色列医院睡眠实验室 | 整夜监测、原始记录 | 官方摘要 |
| 托管机构 | MIT 计算生理实验室 | 格式维护、版本发布 | 官方页面 |
页面只署一人、论文署两人,这是平台与期刊的署名习惯不同所致,两处以并列方式呈现即可,不必判断哪个「更对」。
3.2 配套论文说了什么
论文摘要不长,但把动机与边界都交代了。它说这项工作的产出是一个光盘版的睡眠数据集合,数据来自 16 名睡眠呼吸暂停患者,信号包括脑电、肌电、眼电、有创血压、呼吸波、血氧饱和度与用 VEST 方法测得的心输出量。光盘里另含分析多导数据的程序。
摘要还写了三类潜在使用者:研究睡眠呼吸暂停期间临床生理或非线性动力学的研究者;为睡眠呼吸暂停数据开发自动分析算法的工程师;学习睡眠生理的学生。这三类与官方页面的四个用途高度重合,只是没有单独提教学与分期。
值得注意的是一处口径差异。论文摘要称数据来自 16 名睡眠呼吸暂停患者,属于明确的患病人群;官方摘要则说受试者是从 60 名「有或无睡眠呼吸暂停」的男性中选出的,并称选择这 16 段的理由是要覆盖不同严重程度。两个说法不矛盾,但严格程度不同:前者默认全部患病,后者留了「或」的余地。引用时宜按官方页面写。
3.3 时间线
从监测到最后一次补录校验和,这批数据跨了整整三十年。
| 时间 | 事件 | 依据 |
|---|---|---|
| 1989 年 1 月至 1990 年 1 月 | 十八段记录陆续采集,头文件起始日期覆盖这一年 | 各记录头文件 |
| 1991 年至 1992 年 | 头文件与注释完成最后修订,多数在 1992 年 3 月 | 文件清单的修改时间 |
| 1996 年 2 月 | 分期注释集中重做一轮 | .st 文件修改时间 |
| 1999 年 4 月 | 配套论文发表于精神病学与临床神经科学期刊 | 论文卷期 |
| 1999 年 8 月 3 日 | PhysioNet 正式发布 1.0.0 版 | 官方页面 |
| 2002 年 11 月至 12 月 | 两段记录的头与心搏注释再次修正 | 文件清单的修改时间 |
| 2019 年 4 月 2 日 | 波形统一重写,并补录校验和清单 | 文件清单的修改时间 |
有两个细节值得记住。第一,数据先采集、后发表,中间隔了近十年,其间一直在做格式转换与注释修订。第二,2019 年那一次统一重写说明波形文件被重新生成过一次,但版本号没动,仍是 1.0.0;若在 2018 年之前下载过,文件内容与现在可能不一致。
3.4 采集现场:七支笔、一条动脉管路
官方对采集条件的描述集中在信号清单上,对设备的交代很少。但头文件的物理单位与注释说明已经把现场交代得差不多。
心电来自胸壁电极;脑电只有一路,按国际布点放在中央或枕部,参考同侧耳垂;眼电放在右眼外侧;下颌肌电贴在下巴上。呼吸至少有一路,早期是鼻腔热敏或压力信号,后期加上胸腹两条呼吸带。血氧是一条指夹式探头。血压不是袖带测的,而是动脉内置管后连续读数,单位是毫米汞柱。心输出来自一套贴胸的电阻抗设备。
| 采集要素 | 取值 | 后果 |
|---|---|---|
| 心电 | 胸壁电极,毫伏 | 逐拍检出的基础,全部记录都有 |
| 脑电 | 单导,四种导联 | 有节律但无空间信息 |
| 眼电 | 右眼,仅后期批次 | 早期记录无法区分快速眼动 |
| 肌电 | 下颌,仅部分七路记录 | 早期记录缺少肌张力参照 |
| 血压 | 动脉内置管,连续 | 波形随脉搏起伏,含呼吸调制 |
| 呼吸 | 鼻腔或胸腹带,升 | 有相对量,无绝对潮气量的保证 |
| 血氧 | 指夹式,百分比 | 只在五段记录中出现 |
| 心输出量 | 胸壁电阻抗,毫升 | 只在五段记录中出现,需专用设备 |
有创血压这一项影响最深。它带来的是连续的、逐拍的血压波形,而不是袖带式的一次读数;这条曲线里既有心跳造成的脉冲,也有呼吸带入的缓慢起伏。研究呼吸与循环耦合的人,正是看中了这一点。代价是这类信号今天几乎拿不到:内置管属于有创操作,只有临床监测场景才做。
3.5 两个口径:16 与 18
有一处必须摊开来讲,因为它会直接影响样本量的写法。
官方摘要是这么说的:从 60 名男性受试者的队列中选出 16 段多导记录。可记录清单里实实在在列着十八行,且文件名显示两名受试者各有两段。
| 口径 | 数量 | 构成 | 出处 |
|---|---|---|---|
| 官方摘要 | 16 | 受试者数或「选出的记录数」 | 官方页面与论文摘要 |
| 记录清单 | 18 | RECORDS 逐行 | 官方文件 |
| 受试者数 | 16 | 两名各两段,另有一段未标明归属 | 由文件名推断 |
差额有两处来源。第一,两名受试者各有两段,以 a 与 b 后缀区分,所以 18 段只对应 16 个人。第二,slp67x 的归属没有被说明,官方只说它来自同一批受试者,没有指明是第几位。
稳妥的写法是:写作「16 名受试者、18 段记录」,并在方法里交代两段重复与一段归属不明。按段统计会把样本量报到十八,按人统计只能报十六,两个数字之间的差不是误差,是设计。凡是按受试者划分训练与测试的工作,这条必须写清楚,否则同一名受试者的两段会跨到两侧。
§4 它最独特的东西:一条动脉管路与一次持续气道正压
4.1 它测的是治疗前后
这个库的采集目的写在官方摘要里:受试者因评估慢性阻塞性睡眠呼吸暂停而接受监测,并为测试持续气道正压这一标准治疗的疗效而入组。持续气道正压是给睡眠时上气道一个正压,把塌陷的咽部撑开;对多数阻塞性呼吸暂停患者,它能显著减少或消除气道阻塞。
这个目的决定了它的样本构成与时间结构。样本全部是疑似或确诊的阻塞型患者,没有单纯打鼾者作对照;时间上多为治疗前后的对照,而不是健康与患病的对照。
| 设计要素 | 本库做法 | 常见替代 | 后果 |
|---|---|---|---|
| 对照类型 | 治疗前后或事件前后 | 健康组对照 | 无健康基线 |
| 受试者来源 | 单一实验室的 60 人队列 | 多中心 | 单中心偏倚无法内部估计 |
| 性别构成 | 全部男性 | 男女混合 | 无法讨论性别差异 |
| 严重程度 | 刻意覆盖不同高低 | 单一层次 | 可做分层,但每层样本很少 |
| 记录长度 | 2 至 7 小时,多为治疗段 | 完整整夜 | 入睡与清晨常缺失 |
第四条是人为设计的结果,官方摘要明说选择这 16 段的理由是覆盖不同严重程度。这是一个优点:它避免了全部选重度患者造成的偏倚。代价是每一层的样本量都不足。
4.2 注释符号:一套两用的编码
全库的标签系统压缩在一张很短的符号表里。读这一小段,就掌握了全库的标签语义。
| 符号 | 含义 | 类别 |
|---|---|---|
| W | 清醒 | 睡眠期 |
| 1 | 第一期 | 睡眠期 |
| 2 | 第二期 | 睡眠期 |
| 3 | 第三期 | 睡眠期 |
| 4 | 第四期 | 睡眠期 |
| R | 快速眼动期 | 睡眠期 |
| H | 低通气 | 事件 |
| HA | 伴觉醒的低通气 | 事件 |
| OA | 阻塞型呼吸暂停 | 事件 |
| X | 伴觉醒的阻塞型呼吸暂停 | 事件 |
| CA | 中枢型呼吸暂停 | 事件 |
| CAA | 伴觉醒的中枢型呼吸暂停 | 事件 |
| L | 腿部运动 | 事件 |
| LA | 伴觉醒的腿部运动 | 事件 |
| A | 未特指觉醒 | 事件 |
| MT | 体动时间 | 事件 |
这套编码有一个设计上的特点:觉醒信息被编进了事件符号里,而不是单独一个标签。所以一段记录里同时有「阻塞型暂停」与「伴觉醒的阻塞型暂停」两种符号,二者的区别只在一个字母。做事件计数时要先想清楚是否合并,合并与不合并得到的计数不同。
还有一处常被忽略:体动时间是独立符号,不属于任何睡眠期。若按六类分期做干净的多分类,这些格子必须先被剔除或重定义,否则类别数与官方给的六符号对不上。
4.3 分期体系:五期时代的分法
官方写明分期按 Rechtschaffen 与 Kales 的标准。这套标准把整夜切成三十秒一格,每格标一个符号;它与今天的 AASM 标准最大的差别在深睡:老体系把慢波睡眠分成 3 期与 4 期,新体系合并为一期。
| 老体系符号 | 含义 | 新体系对应 | 映射是否唯一 |
|---|---|---|---|
| W | 清醒 | W | 是 |
| 1 | 第一期 | N1 | 大致是,边界判据不同 |
| 2 | 第二期 | N2 | 大致是,纺锤与 K 复合波规则有别 |
| 3 | 第三期 | N3 | 否,需与 4 合并 |
| 4 | 第四期 | N3 | 否,需与 3 合并 |
| R | 快速眼动期 | R | 是 |
映射在中间两行与深睡两行都不唯一。前两行的差别在于判据:老体系里第一期的判据与 AASM 的 N1 不完全相同,边界上的格子会落到不同类;后两行则是体系本身的结构差异。做跨库比较时,只能把 3 与 4 合并后再比,且必须说明合并规则。
4.4 案例:slp37 的十七分钟
拿一段具体记录走一遍,比抽象描述有用。选 slp37,因为它在七路那批里通道最全:心电、动脉压、脑电、鼻腔呼吸、腹部呼吸、右眼电、下颌肌电,正好七路。
打开它的头文件:七路信号、采样率二百五十、采样点计数五百二十五万,换算下来约五点八小时,起始时刻是零时八分三十秒,起始日期是一九八九年八月十日。头文件末尾还有一行说明,坦白承认血压的增益与基线是推测出来的,并给出改前的旧值。
这一段的设计用途可以从信号编排看出来:眼电与肌电同时存在,说明这一夜既做分期也做快速眼动判读;腹部呼吸带与鼻腔气流同时存在,说明要区分中枢型与阻塞型暂停;动脉压连续记录,说明还要看暂停终止时血压的瞬间变化。
§4.4 的案例里有一处细节值得单独提:slp37 的头文件是少数带修订说明的,它写下「血压增益与基线是推测的,旧值有误」。这句话的分量在于,它承认了标定靠推断。任何一个想从血压绝对值出发的结论,都应以这句话为前提。
再看它缺什么。这段时间只有五点八小时,不是完整一夜;眼电只有右眼一路,做左右眼差分不可能;肌电只有下颌,没有胫骨前肌,所谓腿部运动只有符号,没有对应的肌电曲线可供核对。§4.4 的案例说明白了一件事:通道多不等于信息全,多出来的主要是呼吸与循环,睡眠一侧始终只有一路脑电。
4.5 边界条件:什么情况下它不再适用
五种情况下这批数据会失效,且失效方式各不相同。
第一种,任务从「患者」变成「人群」。 全部受试者是男性阻塞型患者,没有健康对照。要做正常睡眠结构的基线,这里没有。
第二种,需要完整整夜。 多数记录是二到七小时,入睡初段或清晨段落常常不在。要算整夜睡眠效率,分母就不完整。
第三种,需要多导脑电。 只有一路,且导联在记录间变化。任何以空间信息为前提的方法都用不了。
第四种,需要与现代设备对齐。 血压是有创的,心输出量靠电阻抗法,两者与今天的无创设备不可比。
第五种,需要与 AASM 标准直接对齐。 分期体系与事件定义都不同,只能映射后比较,不能等同。
§5 怎么拿到:从记录清单到分期序列
5.1 目录结构与下载面
官方给三条路:浏览器点 ZIP、wget 递归、AWS 开放桶同步。文件扁平,脚本遍历很直接:读 RECORDS 得到十八个主干名,再按扩展名拼出三件套。
| 下载方式 | 命令要点 | 适合场景 | 注意 |
|---|---|---|---|
| ZIP | 页面按钮 | 一次性拿全量 | 六百多兆,视带宽几分钟到十几分钟 |
| wget 递归 | 加 -r -N -c -np |
需要续传 | 会连目录索引一起拉 |
| AWS 同步 | s3 sync --no-sign-request |
批量、可并行 | 需要装命令行工具 |
| 逐文件 | 只按主干名拼 URL | 只取几段做实验 | 最省流量,适合教学 |
因为体积中等,第三条与第一条的实际差别不大。真正值得挑的是第四种:做教学演示取两段就够,做跨记录分析才需要全量。
5.2 批量下载
下面这段把全量拉到本地,并按主干名把三件套下全。
#-- 按 RECORDS 逐段拉取三件套
BASE="https://physionet.org/files/slpdb/1.0.0"
mkdir -p slpdb && cd slpdb
curl -sSL -O "$BASE/RECORDS"
for r in $(cat RECORDS); do
for ext in hea dat st ecg; do
f="$r.$ext"
if [ ! -s "$f" ]; then
curl -sSL --retry 3 -o "$f" "$BASE/$f"
fi
done
done
#-- 顺带拿说明、标定与校验和
for f in README.st ANNOTATORS dbcal SHA256SUMS.txt; do
curl -sSL -O "$BASE/$f"
done
#-- 核对:应为十八个波形文件
ls slp*.dat | wc -l
for r in $(cat RECORDS) 按清单顺序遍历,避免自己拼编号时漏掉 slp67x 这种特殊名。最后一行输出十八说明波形下全。若某个文件只有几百字节,多半是中断留下的残片,删掉重下;校验和清单可以确认。
#-- 校验完整性,失败会打印文件名
sha256sum -c SHA256SUMS.txt --quiet || echo "有文件校验失败"
5.3 读头、读注释、确认时长
读进来之后第一件事不是滤波,是先确认采样率、通道名与注释类型。这一步决定了后面能不能对上。
#-- 读一段记录的头,逐路打印名称与单位
import wfdb
rec = wfdb.rdheader("slp37")
print("通道", rec.n_sig, "采样率", rec.fs)
print("时长小时", round(rec.sig_len / rec.fs / 3600, 2))
for i in range(rec.n_sig):
print(i, rec.sig_name[i], rec.units[i], rec.adc_gain[i])
#-- 看注释文件里存在哪些标注类型
print(wfdb.rdann("slp37", "st").aux_note[:5])
输出应能看到七路信号、采样率二百五十、五点八小时左右的时长。若读到的通道数是四或六,说明取到了另一段记录,先核对主干名。
第二步是把分期序列还原成一个符号列表。注释以固定节拍写入,每条带一个采样点位置,隔三十秒出现一次携带分期语义的注释。
#-- 把 st 注释还原为按三十秒排列的分期序列
import wfdb
ann = wfdb.rdann("slp37", "st")
stages = []
for pos, sym, aux in zip(ann.sample, ann.symbol, ann.aux_note):
if aux.strip():
stages.append((round(pos / 250), aux.strip()))
print("首格与末格", stages[0], stages[-1])
print("格数", len(stages))
aux_note 是携带文字的辅助字段,分期与事件符号都写在这里。首格与末格的秒数应能覆盖整段记录的前后两端;若相差很远,先确认 st 与 .st- 是否取错版本。
5.4 换到 EDF 与多进程读取
不是所有工具链都吃 WFDB。时间对齐类工具更习惯 EDF,所以常见的做法是先转换再分析。
#-- 把一段 WFDB 记录转成 EDF,保留全部通道
python3 -c "
import wfdb
rec = wfdb.rdrecord('slp37')
wfdb.wrsamp('slp37_edf_tmp', fs=rec.fs,
units=rec.units, sig_name=rec.sig_name,
p_signal=rec.p_signal, fmt=['16'] * rec.n_sig)
print('写出通道数', rec.n_sig)
"
转换会丢掉注释,所以分期与事件必须单独导出成表,再用时间轴对齐。若注释与波形在同一条管线里处理,直接用 WFDB 读写更省事,不必绕道 EDF。
批量读十八段时会遇到一个实际问题:七路乘数小时乘二百五十赫兹,单段解包后内存可达数百兆。稳妥的做法是按段处理、用完即弃,或者只读需要的通道。
#-- 按段累加,避免同时把所有记录读进内存
import wfdb, numpy as np
rows = []
for name in open("RECORDS").read().split():
h = wfdb.rdheader(name)
rows.append((name, h.n_sig, round(h.sig_len / h.fs / 3600, 2)))
for r in rows:
print(r)
print("总小时", round(sum(r[2] for r in rows), 1))
这里的总小时应落在八十五量级。若算出来的数字是七百多,说明采样率被当成了三十三,回头检查头文件里那个近似分母的读法。
5.5 一个容易踩的坑:按段还是按人
这个库最大的陷阱不在读文件,在划分。十八段只对应十六名受试者,其中两名各有两段。
#-- 按受试者归并,看看哪些编号重复出现
import re, collections
names = open("RECORDS").read().split()
subject = [re.sub(r"[abx]$", "", n) for n in names]
cnt = collections.Counter(subject)
print("段数", len(names), "受试者数", len(set(subject)))
print("重复出现的受试者编号", [k for k, v in cnt.items() if v > 1])
输出应显示十八段、十六名,且 slp01 与 slp02 各出现两次。slp67x 被归到了 slp67 名下,这只是一个命名上的假设;官方没有说它属于谁,所以任何以它为主体的结论都该注明这一点。
按受试者留一验证时,要保证同一人的两段落在同一侧。这一步看着琐碎,却是所有跨人结论的前提。
5.6 五个最容易出错的地方
| 出错点 | 表现 | 原因 | 处理 |
|---|---|---|---|
| 把 SLP 当成 sleep | 找不到「标准分期数据集」 | SLP 指多导睡眠图 | 按库名全称检索 |
| 假定通道数一致 | 读到四路或六路时维度报错 | 通道随批次而变 | 先读头,按 n_sig 分支 |
| 直接套 AASM 五类 | 类别数对不上 | 只有 R&K 六符号 | 先合 3 与 4,再映射 |
| 把事件与分期混为一谈 | 干净多分类里混进事件符号 | 两者共用一份注释 | 按符号表分列 |
| 按段随机划分 | 跨人准确率虚高 | 两人各有两段 | 按受试者归并后划分 |
最后一条值得多说一句。十八段里两段来自同一人,若随机按段切,这两段很可能一训练一测试,模型学到的是这位受试者的生理指纹。受试者只有十六人,随便泄漏一个人就占了测试集的六分之一。
§6 与库内条目的关系
6.1 关系图谱
站内与睡眠有关的记录已经很多,分成了好几代。与本库最需要划清界限的,是分期基准这一族(多中心、AASM 标注、上百人),以及临床综合记录与儿童队列这两族。
| 库内记录 | 与本库的关系 | 主要差别 |
|---|---|---|
| sleep-edf | 同为 PhysioNet 托管的 PSG | 它是多夜分期基准、AASM 标注、数十人,脑电两导以上 |
| isruc-sleep | 同为分期基准族 | 它一人一夜、双专家 AASM 评分,本库为单人单次 R&K |
| mass | 同为整夜 PSG 档案 | 它按子集组织、AASM 与 R&K 双标,本库只有 R&K |
| capsleep | 同为含病理人群的睡眠库 | 它 108 条整夜记录、含健康对照,本库 18 段、无对照 |
| cps-dataset-sleep | 同为临床诊断性 PSG | 它最多 36 路通道与 81 类事件、需签署协议,本库免注册、四到七路 |
| cinc-2018-sleep-arousal | 同为带事件标签的 PSG | 它近两千例、逐采样点觉醒标签,本库事件为 30 秒粒度 |
| shhs | 同为睡眠队列 | 它上万人、多导脑电、申请制,本库 16 人、免注册 |
| hmc-sleep-staging | 同为分期任务 | 它为单中心小样本但按 AASM,本库为老体系 |
规律很清楚:本库是站内少数「信号种类最杂、通道数最少、年代最早、体量最小」的睡眠记录。其它库用规模和标准化的标注换通用性,它用稀缺的有创信号和原始的时间结构换独特性。
与 cps-dataset-sleep 的差别尤其要写清:两者都来自临床诊断场景,都带呼吸事件,但 cps-dataset-sleep 是 2021 到 2022 年采集的现代设备、最多三十六个通道、八十多类事件、需要培训与协议;本库是 1989 到 1990 年的老设备、四到七路、事件符号十几个、免注册。一个是今天临床的完整切片,一个是三十年前的有限切片加一条今天拿不到的动脉管路。人群也不同:那一份是 113 名成人混合性别,这一份是 16 名男性。
与 sleep-edf、isruc-sleep、mass 这一族的差别可以归成三点。第一是通道:它们有两导以上脑电,本库只有一导。第二是标注:它们按 AASM,本库按 R&K,类别不可直接对齐。第三是人群:它们多为多中心或多夜,本库单中心单夜、全部男性患者。做分期模型的人应该去这一族,做呼吸循环耦合的人才会走到本库。
6.2 检索路径
站内检索用 slug slpdb,或全名 MIT-BIH Polysomnographic Database。中文关键词建议用「有创血压」或「心输出量」再加睡眠,因为单搜「睡眠」会返回几十条分期基准;用「MIT-BIH」也能精确命中,但要注意它同时是心律失常库的名字,须再补一个词区分。
按需求找:要分期基准与跨中心验证,去 sleep-edf 或 isruc-sleep;要带健康对照与多类事件,去 capsleep;要现代临床的综合记录,去 cps-dataset-sleep;要逐采样点的觉醒标签,去 cinc-2018-sleep-arousal;要上万人的流行病学队列,去 shhs。只有需要「连续有创血压与心输出量」这一条时,本库才是首选。
6.3 三张对照表:人群、标注、信号
三个维度分开列,因为它们恰好决定了一个睡眠库能做什么。
第一张是人群与规模。
| 库 | 人群 | 受试者 | 性别 |
|---|---|---|---|
| 本库 | 男性 OSA 评估者 | 16 | 全男 |
| sleep-edf | 健康志愿者与睡眠障碍者混合 | 数十 | 混合 |
| isruc-sleep | 睡眠障碍与健康 | 一百余 | 混合 |
| capsleep | 健康与多类病理 | 一百余人 | 混合 |
| cps-dataset-sleep | 临床诊断成人 | 一百余 | 混合 |
第二张是标注体系,决定能不能直接比较。
| 库 | 分期体系 | 分期粒度 | 事件标注 | 是否含人体评分对照 |
|---|---|---|---|---|
| 本库 | R&K 五期 | 30 秒 | 十余种合并符号 | 单次判读 |
| sleep-edf | AASM | 30 秒 | 少 | 单次判读 |
| isruc-sleep | AASM | 30 秒 | 少 | 双专家独立评分 |
| capsleep | AASM 与 R&K | 30 秒 | CAP 相位 | 单次判读 |
| cinc-2018 | 觉醒标签 | 逐采样点 | 唤醒 | 单次判读 |
第三张是信号构成,这一维最容易被忽略,却直接决定能做什么分析。
| 库 | 脑电通道 | 有创血压 | 心输出量 | 血氧 | 眼电与肌电 |
|---|---|---|---|---|---|
| 本库 | 1 | 有 | 部分有 | 部分有 | 部分有 |
| sleep-edf | 2 | 无 | 无 | 有 | 有 |
| isruc-sleep | 3 至 6 | 无 | 无 | 有 | 有 |
| capsleep | 3 至 19 | 无 | 无 | 有 | 有 |
| cps-dataset-sleep | 多导 | 无 | 无 | 有 | 有 |
把三张表叠起来看,本库的位置很清楚:人群最窄、标注最老、信号最奇。它占的是「带循环参数的老式睡眠档案」这个角。把它当 sleep-edf 的替代品,第一步就撞上通道数与标准;把它当呼吸循环研究的素材,才用对了地方。
6.4 与站外同类资源的区别
站外常被拿来比较的有三类。第一类是大型流行病学队列的 PSG 子集,样本上万、多导脑电、申请制访问,适合做人群层面的关联分析。本库体量不足其千分之一,但免注册,适合先跑通流程。
第二类是商业可穿戴设备的睡眠数据,通道只有加速度与心率,标签来自厂商算法。它们的样本极大但标签是估的;本库样本极小但标签由人判。两者不能互相替代,一个是广度,一个是深度。
第三类是同期制作的生理信号库,比如心律失常库。它们与本库共享格式与工具链,同一套读取代码能读两边;区别在于本库的信号种类更杂、时长更长、标注层级更多。
§7 质量评估与局限性
7.0 阅读本节前的一个前置校正
先校正一个几乎一定会犯的误判:把「只有 16 人」读成「数据质量差」。
这两件事在这个库上方向恰好不同。16 人是入组筛选的结果:从一个 60 人队列里按严重程度分层挑出,目的不是扩大样本,而是让每种严重程度都能被看到。质量的高低要看信号是否完整、标注是否可复核,而不是看人头数。按人头数扣分的是「规模」,不是「质量」。
校正之后,五维评分的读法也要跟着变。规模分低衡量的是「能不能喂饱模型」,而不是「记录得规不规矩」。真正该扣分的地方在别处:脑电只有一路、导联不统一、分期体系过时、短记录与官方区间对不上、部分信号的标定靠推断。这些是结构与文档的欠缺,与采集质量本身无关。
还有一个误判要提:把「有创血压」当成负担。对今天的工程实践,它确实让数据不可复现——没人会为了对照再给受试者插一根管。但对研究呼吸与血压耦合的人,这正是唯一拿得到的东西。同一个特征在不同用途下的正负号不同,这是判断任何采集选择时的前提。
7.1 五维评分
按 DAIMS 的常用维度打分,每项一至五分,分数针对「作为呼吸循环耦合与老式分期参照」这个用途。
| 维度 | 分数 | 理由 |
|---|---|---|
| 数据规模 | 2 | 16 人、18 段、85 小时,训练容量不足,长时段观察够用 |
| 标注质量 | 3 | 30 秒分期与事件同源,符号表清楚,但体系过时、单次判读 |
| 任务适配 | 3 | 呼吸与循环耦合是强项,分期与多导脑电是弱项 |
| 文档完整 | 3 | 符号表与头文件规范清楚,通道差异与 x 记录未说明 |
| 可获取性 | 5 | 免注册、ODC-BY、体积中等,三条下载路径都可用 |
合计十六分(满分二十五)。这个分布说明它不是全能选手:规模是硬伤,可获取性拉满,其余三项在中间档。与分期基准族相比,它在「容易拿到」上领先,在「能拿来做多少种任务」上落后。
「标注质量」若按「符号是否正确」打分可以给四分,因为符号表短而清楚,几乎没有歧义;若按「能支撑多少分析」打分,三分都偏高。它是少而准,不是多而全。
7.2 标注质量的两层
第一层是符号是否正确。全库的标签字典只有十六个符号,全部写在 README.st 里,一屏就能读完。这种极简设计带来一个好处:不存在「标注文件格式不统一」这类故障,读注释就够。
第二层是符号能承载多少信息。这一层它很薄。分期只有六类,事件只有十类,且全部是格级的,没有逐秒的呼吸暂停起止与持续时长,没有呼吸暂停指数,也没有各期的比例。血压、心率、呼吸这些连续量可以从波形自己算,但算出来的东西没有金标准可对。
还有一处需要说明:注释是单次判读。官方没有提到两名判读人员独立评分,也没有给出评分者之间的一致性。与后来那些双专家评分的库相比,这里没有可用来估计标注噪声的第二条读数。
7.3 已知的、可枚举的偏差
| 偏差 | 表现 | 影响 |
|---|---|---|
| 全部男性 | 16 人无一例外 | 无法讨论性别差异 |
| 无健康对照 | 全部为 OSA 评估者 | 没有正常睡眠结构的基线 |
| 单中心 | 一家医院的一间实验室 | 中心效应无法从内部估计 |
| 单导脑电 | 一路,导联四种 | 无空间信息,跨记录不可比 |
| 记录不完整 | 2 至 7 小时,短于整夜 | 睡眠效率与总睡眠时间算不准 |
| 分期体系过时 | R&K 五期 | 与 AASM 库不可直接比较 |
| 单次判读 | 未报告评分者一致性 | 标注噪声不可估 |
| 血压标定 | 部分记录自承靠推断 | 绝对血压值不可信 |
| 事件粒度粗 | 30 秒一格 | 无法得到精确的暂停时长 |
| 一段归属不明 | slp67x 未指明受试者 | 按人统计时有一个人数悬空 |
前四条是结构性的,改不了;中间三条是历史条件带来的,只能交代清楚;最后三条是文档与工程问题,靠读取与说明可以缓解。
有一处统计上的提醒:这个库的天然统计单位是人,不是格。八十五小时按三十秒切是万级格子,但同一晚相邻的格子高度相关,独立性不成立。直接按格数算显著性,等于把一个人的一夜当成几千个独立样本,结论会被严重高估。
7.4 外部验证矩阵
这个库在文献里的用法,可以归成四类角色。判断依据是官方用途说明与论文摘要,不涉及具体数值比较。
| 验证角色 | 做法 | 讲得通的地方 | 风险 |
|---|---|---|---|
| 呼吸暂停生理机制 | 事件前后对齐血压与心率 | 有创血压与事件同源 | 16 人,难以分层 |
| 非线性动力学方法 | 在长时段多路信号上算复杂度指标 | 数小时连续、250 赫兹 | 短记录样本少,噪声不均 |
| 自动分期的外部检验 | 把在别处训练的模型拿来测 | 老体系参照,检验年代稳健性 | 类别需先映射,否则不可比 |
| 睡眠与循环耦合 | 呼吸带与血压同轴分析 | 两者在多数记录中都有 | 心输出量只在五段里有 |
第一类与第四类最贴合它的设计目的,因为它们正是论文自己做的事:暂停终止时的心血管变化、睡眠分期对呼吸与心率关系的影响。第二类在九十年代用得很多,靠的是它长时段的连续性。第三类最容易被误做,因为「外部验证」这个词容易让人忽略标准差异。
还有一个不常被提起却很合适的用法:教学。一次检查、七个通道、一张十六行的符号表,链路每一环都能在一节课里讲完,文件也小到只取一段就能演示。
7.5 它为何能持续:靠一条今天插不进去的管子
它自 1999 年发布以来只有一个版本,作者没有持续维护,却在三十年后仍被引用。原因不在规模,在于它保存了一份成本极高、今天几乎无法复制的观测:同一个人整夜里,逐拍的动脉压、逐拍的呼吸与单导脑电连续并存。
要做这件事,得在睡眠监测的受试者身上留一条动脉管路,同时保持整夜监测。这在临床上是可行的,因为重症或研究场景本来就要监测血压;但在今天,让健康人或轻症患者为了数据集而接受有创操作,伦理审查几乎不会通过。所以这份记录是特定历史条件的产物,而不是一份可以重做的数据。
成本也是原因。重做一次需要一间睡眠实验室、七路以上的放大器、一套电阻抗心输出量设备、一名能操作动脉管路的技师,以及一整夜的床位;下载只要六百多兆。
边界同样明确:一旦课题转向分期模型的训练、多导脑电的空间分析或现代设备的可比性,短板立刻暴露。
§8 生态位与历史
8.1 历史沿革
这批数据诞生于 PhysioNet 平台成型的前夜。平台最初以心律失常库起步,之后陆续接收其他类型的生理记录;本库与心律失常库共用一套文件格式与读取工具,等于把「多参数、长时段」这一路扩展补齐。
它的加入方式很典型:MIT 一侧负责格式转换与注释整理,采集方提供原始记录,最终以 CD-ROM 分发,后来整体迁到平台上托管。这让它在没有后续基金、没有维护团队的情况下活了三十年,也让文档停在「一次讲清」的状态——没有勘误,也没有补充说明。
从工具链也能读出年代。CD-ROM 附带的是 C 语言与 shell 脚本写的查看与分析工具,支持逐拍心率、血压与心室容积分析,以及傅里叶与最大熵谱分析。它们决定了当时的使用方式:拿到光盘的人在本地装工具,对着波形一段段看。
8.2 与挑战赛和聚合库的关系
它没有进过任何挑战赛。分区之后的睡眠类挑战赛大多围绕微觉醒检测与分期,赛题要的是规模与统一点位,与本库的体量与单导结构都不相称。这意味着它没有官方划分、没有排行榜、也没有社区基线,同时也不会被刷分式的研究快速消耗。
它与聚合型资源的关系恰好相反。聚合库用规模与统一标注换通用性,代价是把单次检查磨平;本库规模小、标注老,但每个字段都对应一个真实的采集决定。
它的出现时机也值得一提:那正是把生理信号当作非线性动力学对象来研究的几年,而连续数小时、250 赫兹、多通道同时存在,恰好适合做复杂度分析。
8.3 生态位:稀有病种信号的一端
把站内外睡眠库按信号稀缺性排:可穿戴设备最普遍,分期基准居中,本库最稀,因为它带着有创血压与心输出量。
它因此有两个稳定用途:一是呼吸循环耦合的参照物,二是教学素材——只取一段就能把一次检查讲完整。
这个位置不容易被替代:拼一个更大的睡眠库不难,难的是把动脉压与心输出量放进去。
8.4 谁在用它,用来做什么
从官方列出的用法看,引用集中在三个方向:呼吸、心率与血压的非线性动力学;暂停终止时的心血管变化;睡眠期对呼吸与心率关系的影响。
还有一类不常被提及的用法:读取工具的回归测试。它十几行代码就能读完,却包含非标准时间字段、两版注释与特殊的 x 命名。
三类用法都不要求大样本。课题一旦要求几百人以上,它就会被换掉。
§9 使用指引
9.1 三种角色的路径
生理研究方向的最短路径。 先读 README.st 的十六行符号表,再挑一段七路记录(推荐 §4.4 的案例),把血压与呼吸并排画出来,确认自己理解了暂停终止那一刻血压的抬升。然后按受试者分层,看严重程度不同的记录里这个抬升是否一致。
信号处理方法方向的最短路径。 先按 §5.3 读头确认通道数,再按 §5.4 转成 EDF 或就地处理。做分期实验时把 3 与 4 合并,做事件检测时先决定伴觉醒与不伴觉醒是否合并。别一上来就按格随机切。
工程落地方向的最短路径。 先确认要的是离线分析还是在线监测。离线可直接用;在线要自己定义事件窗口与时间标签,这批数据帮不上忙,把它当「呼吸事件的离线上限」估计更合适。
| 角色 | 先做什么 | 别做什么 | 预期产出 |
|---|---|---|---|
| 生理研究 | 并排画血压与呼吸 | 忽略暂停前后的对齐点 | 暂停终止的循环反应 |
| 信号处理 | 读头确认通道数 | 假定七路 | 可复现的特征基线 |
| 工程落地 | 分清离线与在线 | 指望它给出逐秒事件 | 事件检测的上界估计 |
| 教学 | 取一段四路的做演示 | 一上来就讲七路 | 完整链路的一次直观演示 |
9.2 先建一份本地索引
#-- 把十八段记录汇总成一张索引表
import pandas as pd, wfdb, re
rows = []
for name in open("RECORDS").read().split():
h = wfdb.rdheader(name)
rows.append({"rec": name, "nsig": h.n_sig,
"hours": round(h.sig_len / h.fs / 3600, 2),
"subject": re.sub(r"[abx]$", "", name)})
idx = pd.DataFrame(rows)
print(idx["nsig"].value_counts().to_dict())
print("受试者数", idx["subject"].nunique(), "总小时", round(idx["hours"].sum(), 1))
通道分布应为四、六、七三档,受试者数为十六,总小时落在八十五量级。
9.3 一条最短的可用流程
从零到第一个诚实可比的数字,下面这段够用。它不追求性能,只保证每一步都对得上。
#-- 最小可用流程:一段记录的分期序列与事件计数
import wfdb, collections
def load_stage(name="slp03"):
ann = wfdb.rdann(name, "st")
out = []
for pos, aux in zip(ann.sample, ann.aux_note):
tag = aux.strip()
if not tag:
continue
#-- 一格可能同时带分期与事件,用空格切开
parts = tag.split()
out.append((round(pos / 250), parts[0], parts[1:]))
return out
seq = load_stage()
stage_cnt = collections.Counter(p[1] for p in seq)
event_cnt = collections.Counter(e for p in seq for e in p[2])
print("分期符号", dict(stage_cnt))
print("事件符号", dict(event_cnt))
输出是两个计数器。它们只用来确认解析正确,不做分布结论——本库不足以支撑人群层面的比例推断。
换留一受试者验证时测试集须以人为单位,理由见 §5.5。
9.4 引用方式
官方要求同时引用两件东西:原始论文与 PhysioNet 平台。论文那一条是 Ichimaru 与 Moody 于 1999 年发表在《Psychiatry and Clinical Neurosciences》第 53 卷的文章,页码 175 至 177,题为《Development of the polysomnographic database on CD-ROM》。平台那一条按现行建议引用其平台综述。
数据写到版本级:名称、版本 1.0.0、DOI 10.13026/C23K5S、访问日期。若做过导联统一、重采样或合并 3 与 4,须在方法里写明,因为这些步骤会改变复现结果。
§10 AI 使用声明
| 项目 | 声明 |
|---|---|
| 文本生成 | 本文由 AI 辅助撰写,编辑负责结构与事实核对 |
| 数字来源 | 规模、结构、边界三类数字取自 PhysioNet 官方页面与官方文件 |
| 文件核验 | RECORDS、README.st、ANNOTATORS、dbcal 与十八个头文件经直接访问确认 |
| 口径冲突 | 官方摘要写 16、记录清单列 18,已在本篇并列呈现并说明差额来源 |
| 论文信息 | 仅参考 Europe PMC 返回的摘要与题录,未读全文 |
| 未核验内容 | 全部注释文件逐格内容、各记录的实际分期比例、血压标定的真实值 |
| 图像 | 无配图;封面为生成式提示词,不含真实波形 |
| 免责 | 本文不构成任何临床或工程建议;使用须遵守 ODC-BY 1.0 署名条款 |
常见误读(避坑清单)
| 说法 | 实际 | 证据 |
|---|---|---|
| 「slpdb 是 sleep 的缩写,属于睡眠分期基准」 | SLP 指 polysomnography,即多导睡眠图 | 官方全名与项目标题 |
| 「它有上百名受试者」 | 16 名受试者、18 段记录 | 官方摘要与 RECORDS 十八行 |
| 「每人一夜、共十六夜」 | 两人各两段,另有一段归属未说明 | 文件名后缀与 RECORDS |
| 「都是完整整夜记录」 | 时长多为 2 至 7 小时,短记录在区间之外 | 各头文件的采样点计数 |
| 「有几十路脑电」 | 单导脑电,导联有四种 | 各头文件的脑电描述串 |
| 「按 AASM 标准分期」 | 按 Rechtschaffen 与 Kales 五期 | 官方摘要与 README.st |
| 「每段记录通道数都一样」 | 四路、六路、七路三种 | 十八个头文件的通道数字段 |
| 「标签里有逐秒的暂停起止」 | 事件与分期同为 30 秒一格 | 注释节拍与符号表 |
| 「血压是袖带测的」 | 动脉内置管连续测压 | 头文件的单位与官方摘要 |
| 「可以当主训练集训分期模型」 | 16 人、单导,容量不足 | 官方规模与通道构成 |
FAQ
Q1:slpdb 里的 SLP 是 sleep 吗?
不是。SLP 指 polysomnography,也就是多导睡眠图。全名是 MIT-BIH Polysomnographic Database。库里确实有睡眠分期标注,但分期只是它附带的一层信息,主体是多路生理波形。
Q2:一共有多少受试者、多少段记录?
官方写 16 名受试者、18 段记录。差额来自两名受试者各有两段(a 与 b 后缀),另有一段以 x 标记、官方未指明归属。RECORDS 逐行列出这十八个主干名。
Q3:为什么有的记录只有四路信号?
早期批次的记录只有心电、血压、单导脑电与一路呼吸,头文件里没有眼电与下颌肌电。后期批次才扩到七路。做分期要眼电与肌电时,只能从七路的那九段里选。
Q4:采样率是多少?
二百五十赫兹,每样本 12 位。头文件里采样率一项写成分数形式,分母用的是零点零三三三三三三,这是一个近似值;严格照字面乘会算成七百多小时,按二百五十赫兹算则合计约八十五点六小时,与官方时长区间吻合。
Q5:分期用的哪套标准,能和 AASM 库直接比吗?
用的是 Rechtschaffen 与 Kales 五期,符号为 W、1、2、3、4、R。与 AASM 的差别主要在深睡:老体系把慢波分成 3 与 4,新体系合并为 N3。直接比要先合并,并说明合并规则。
Q6:适合做深度学习分期吗?
可以作为外部验证集,不适合作为主训练集。16 名受试者、18 段记录、单导脑电,训练容量差一到两个数量级。若已有在别处训练好的模型,它适合用来检验跨中心与跨年代的稳健性。
Q7:有创血压会影响使用吗?
影响的是可比性,不是可用性。它是连续的逐拍动脉压,比袖带的一次读数信息量大,但与今天的无创设备不能直接对照。另外部分记录的头文件自承增益与基线靠推断,绝对血压值不宜当真。
Q8:为什么会有 .st 与 .st- 两份注释?
官方没有解释。从修改时间看,不带减号的版本更晚,可能是在原版基础上重做或修订过的。稳妥的做法是用不带减号的那份,并在方法里写明选了哪一版。
Q9:slp67x 属于哪位受试者?
官方只说它来自同一批受试者,没有指明是哪一位。按文件名可归到第 67 号,但这是一个命名上的假设。任何以它为主体的结论都应注明这一点。
Q10:许可允许商用吗?
ODC-BY 1.0 允许,包括商业用途,条件是署名。署名要覆盖数据集本身、PhysioNet 平台与原始论文三层,具体条款以官方许可全文为准。
Q11:官方有扩版计划吗?
页面只显示一个版本,1999 年首发,2019 年补录校验和,之后无数值或结构上的更新说明。从文档形态看,扩版的可能性不大。
Q12:它能和 sleep-edf 拼在一起用吗?
技术上可以,但要先解决三件事:分期体系映射、通道数对齐、采样率是否一致。拼起来适合做跨年代的稳健性检验,不适合把两边的格直接混成一个训练集,因为标注判据不同。
术语表
| 术语 | 解释 |
|---|---|
| 多导睡眠图 | 同时记录脑电、眼电、肌电、呼吸与心电等多项生理信号的整夜检查 |
| 阻塞型睡眠呼吸暂停 | 睡眠时上气道反复塌陷导致气流停止或显著减少的疾病 |
| 中枢型呼吸暂停 | 呼吸中枢发出的驱动不足导致的气流停止,与气道是否堵塞无关 |
| 持续气道正压 | 睡眠时经由面罩给气道一个恒定正压,撑开咽部以消除阻塞 |
| 低通气 | 气流幅度显著下降但未完全停止的一段呼吸 |
| 觉醒 | 睡眠中出现的一过性清醒或睡眠变浅,常与呼吸事件同时发生 |
| 呼吸暂停指数 | 每小时睡眠中呼吸暂停与低通气的次数,严重程度的核心指标 |
| R&K 分期 | Rechtschaffen 与 Kales 于 1968 年提出的五期分期体系 |
| AASM 分期 | 美国睡眠医学会于 2007 年提出的分期体系,深睡合并为 N3 |
| 慢波睡眠 | 以高幅低频脑电为主的深睡阶段,老体系分为 3 与 4 两期 |
| 快速眼动期 | 眼球快速运动、肌张力极低的一段睡眠,常伴做梦 |
| K 复合波 | 二期睡眠中出现的双相高幅慢波,是分期的标志之一 |
| 睡眠纺锤 | 二期睡眠中出现的短促节律波,与 K 复合波同为分期依据 |
| 有创血压 | 通过动脉内置管直接测得的逐拍血压,与袖带式无创血压相对 |
| 电阻抗心动图 | 通过胸壁阻抗变化推算心搏出量的方法,本库心输出量的来源 |
| 心输出量 | 心脏每分钟泵出的血量,等于每搏量与心率之积 |
| 血氧饱和度 | 血液中与氧结合的血红蛋白占比,以百分比表示 |
| 呼吸带 | 绑在胸部或腹部的弹性带,通过周长变化记录呼吸运动 |
| WFDB | 生理信号库的通用文件格式与配套工具,头、波形、注释三件套 |
| 注释文件 | 存放事件与标签时刻的文件,按固定节拍写入并携带符号 |
| 辅助字段 | 注释中携带文字的部分,本库用它写分期与事件符号 |
| 212 格式 | 每三个字节装两个 12 位采样点的紧凑存储方式 |
| 格 | 分期与事件标注的最小时间单位,本库为三十秒 |
| 受试者泄漏 | 同一受试者的样本同时出现在训练与测试集,导致成绩虚高 |
| 留一受试者 | 每次留一个人做测试、其余人做训练,衡量跨人泛化 |
| ODC-BY | 开放数据共享署名许可,允许商用需署名 |
附录 A:核心数字核对表
| 项 | 值 | 来源 | 来源层级 |
|---|---|---|---|
| 受试者数 | 16 | 官方摘要与论文摘要 | 官方页面 |
| 记录数 | 18 | RECORDS 逐行 | 官方文件 |
| 选样来源 | 60 名男性队列 | 官方摘要 | 官方页面 |
| 平均年龄 | 40 岁 | 官方摘要 | 官方页面 |
| 年龄范围 | 32 至 56 岁 | 官方摘要 | 官方页面 |
| 时长下限 | 2 小时 | 官方摘要 | 官方页面 |
| 时长上限 | 7 小时 | 官方摘要 | 官方页面 |
| 合计时长 | 约 85.6 小时 | 头文件采样点计数除以 250 | 官方文件推算 |
| 采样率 | 250 Hz | 头文件采样率字段 | 官方文件 |
| 量化位数 | 12 位 | 头文件格式码 212 | 官方文件 |
| 通道数 | 4、6、7 | 头文件通道数字段 | 官方文件 |
| 脑电通道 | 1 | 头文件描述串 | 官方文件 |
| 脑电导联 | C4-A1、C3-O1、O2-A1 | 头文件描述串 | 官方文件 |
| 信号种类 | 8 类 | 十八个头文件的描述串并集 | 官方文件推算 |
| 分期符号 | 6 个 | README.st | 官方文件 |
| 事件符号 | 10 个 | README.st | 官方文件 |
| 分期粒度 | 30 秒 | 注释节拍 | 官方文件 |
| 未压缩体积 | 632.3 MB | 页面文件区 | 官方页面 |
| 许可 | ODC-BY 1.0 | 页面许可栏 | 官方页面 |
| 数据 DOI | 10.13026/C23K5S | 页面发现栏 | 官方页面 |
| 首发日期 | 1999-08-03 | 页面版本说明 | 官方页面 |
附录 B:数字的来源分层
第一层,官方页面与官方文件。 受试者数、选样来源、年龄、时长区间、通道数、脑电导联、信号种类、分期与事件符号、分期粒度、体积、许可与 DOI,全部来自项目主页、README.st、RECORDS 与十八个头文件;合计时长由采样点计数除以二百五十赫兹推算。这一层可直接引用,重查可得同样结果。
第二层,论文摘要与题录。 受试者为睡眠呼吸暂停患者、信号构成、光盘含分析程序、三类潜在使用者,来自 Europe PMC 返回的摘要;期刊卷期页码与 DOI 同样来自该库。摘要能支撑「作者主张了什么」,不能支撑「结论有多强」。
第三层,未核实。 每段记录中各分期的实际占比、事件的实际次数、血压标定的真实值、slp67x 的受试者归属、.st 与 .st- 两版注释的具体差异、心输出量的测量精度。正文凡涉及这些的地方,都只做定性表述或明确标注为推断。
附录 C:完整参考文献
| 编号 | 文献 | 链接 | 用途 |
|---|---|---|---|
| 1 | MIT-BIH Polysomnographic Database v1.0.0 | https://physionet.org/content/slpdb/1.0.0/ | 规模、结构、边界数据 |
| 2 | 该库文件目录 | https://physionet.org/files/slpdb/1.0.0/ | 头文件、RECORDS、注释说明、标定表 |
| 3 | Ichimaru Y, Moody GB. Psychiatry Clin Neurosci 1999;53:175-177 | https://doi.org/10.1046/j.1440-1819.1999.00527.x | 实验动机与信号构成 |
| 4 | 同上的 Europe PMC 摘要与题录 | https://www.ebi.ac.uk/europepmc/webservices/rest/search?query=DOI:10.1046/j.1440-1819.1999.00527.x | 作者、卷期、页码 |
| 5 | PhysioNet 平台综述(2026,Nature Health) | https://doi.org/10.1038/s44360-026-00096-z | 托管模式与引用规范 |
| 6 | ODC-BY 1.0 许可全文 | https://opendatacommons.org/licenses/by/1-0/ | 许可条款 |
| 7 | WFDB 头文件字段规范 | https://physionet.org/physiotools/wag/header-5.htm | 采样率与信号行字段的读法 |
| 8 | WFDB 注释文件规范 | https://physionet.org/physiotools/wag/annot-5.htm | 注释节拍与辅助字段的含义 |
附录 D:任务代码
把一段记录的血压与呼吸画在同一张时间轴上,下面这段够用,不需要训练模型。
#-- 逐段比较呼吸与血压的同步关系
import numpy as np, wfdb
def load(name, want=("Resp", "BP")):
rec = wfdb.rdrecord(name)
out = {}
for i, s in enumerate(rec.sig_name):
for w in want:
if s.startswith(w):
out[w] = rec.p_signal[:, i]
return out, rec.fs
sig, fs = load("slp37")
#-- 十秒滑窗内比较两者的波形起伏方向
win = 10 * fs
n = min(len(v) for v in sig.values())
corr = []
for i in range(0, n - win, win):
a = sig["Resp"][i:i + win]
b = sig["BP"][i:i + win]
if a.std() and b.std():
corr.append(float(np.corrcoef(a, b)[0, 1]))
corr = np.array(corr)
print("窗口数", corr.size, "中位相关", round(float(np.median(corr)), 3))
print("负相关窗口数", int((corr < 0).sum()))
输出是十秒窗口内呼吸与血压的相关系数中位数,以及有多少窗口呈负相关。呼吸暂停期间两者的耦合方式会改变,这个数会随之移动。若通道取不到,先确认选中的记录是否含呼吸带那一路。
附录 E:如果只记五件事
第一,它是单实验室的老式多导睡眠记录,16 名男性、18 段、合计约八十五小时,SLP 指多导睡眠图而不是 sleep。
第二,它最大的价值是那条动脉管路:连续有创血压与部分记录的心输出量,今天几乎无法再采。
第三,它按 Rechtschaffen 与 Kales 五期分期,与 AASM 库不可直接比较,深睡两期必须先合并。
第四,通道随批次变化,四路、六路、七路都有;脑电自始至终只有一路。
第五,现实的用法是呼吸循环耦合与外部验证;按格随机划分得到的成绩几乎都来自同一受试者的泄漏。
编辑说明
核验时间 2026 年 10 月 28 日。核验方式:直接访问 PhysioNet 项目页(含重定向后的版本页),读取 RECORDS、README.st、ANNOTATORS、dbcal 与全部十八个头文件,逐行解析通道数、脑电描述串、采样率、采样点计数与物理单位;文件清单的体积与修改时间一并核对。论文信息仅取 Europe PMC 的题录与摘要。未覆盖:十八个注释文件的逐格内容、各记录的实际分期占比、血压标定的真实值、.st 与 .st- 两版注释的差异。受试者数 16 与记录数 18 按并列呈现;合计时长按二百五十赫兹口径推算,头文件中近似分母导致的七百多小时算法在 §2.2 一并说明。
相关数据集导航
以下为站内 AI-Ready 数据集百科中与本词条共享多个主题标签的相关数据集,按相关度降序排列:
- cpap-data-canterbury — 共享标签:生理信号 / 睡眠信号
- meditation — 共享标签:生理信号 / 睡眠信号
- isruc-sleep — 共享标签:生理信号 / 睡眠信号
- shhs — 共享标签:生理信号 / 睡眠信号
- mros-sleep — 共享标签:生理信号 / 睡眠信号
- nsrr — 共享标签:生理信号 / 睡眠信号
- cinc-2018-sleep-legacy — 共享标签:生理信号 / 睡眠信号
- sleep-edf — 共享标签:生理信号 / 睡眠信号
- mass — 共享标签:生理信号 / 睡眠信号
- dreamt — 共享标签:生理信号 / 睡眠信号
导航说明:本章节由全站统一标签体系自动计算生成(标签重合度算法),双向可达;点击链接可跳转至对应数据集词条。

