从 58 万小时睡眠数据里提炼“未病信号”——SleepFM 多模态睡眠基础模型全解析
核心问题:只用一夜多导睡眠图(PSG),能否提前数年预测 1000+ 种疾病?
答案是“可以”。SleepFM 用 65 000 人的 58.5 万小时 PSG 自监督预训练,在 1 041 种疾病预测任务里,130 项 C-Index≥0.75;对全因死亡、痴呆、心衰、中风等关键终点,6 年 AUROC 0.78–0.85,显著优于纯人口学基线与端到端监督模型。
本文将回答的 5 个自然语言问题
-
SleepFM 到底是什么?和传统睡眠 AI 有何不同? -
它怎么用“无标签”PSG 自监督预训练? -
我在自己数据集上如何完整复现一遍? -
模型真正落地需要哪些硬件、时间与代码步骤? -
有哪些已验证的临床场景与性能数字可参考?
一、SleepFM 速描:一个模型,三行价值
| 维度 | 旧做法 | SleepFM 做法 |
|---|---|---|
| 数据规模 | 2k–15k 例,单中心 | 65 000+ 例,58.5 万小时,多中心 |
| 标签依赖 | 需人工分期/事件标注 | 预训练阶段零疾病标签 |
| 任务通用性 | 一种模型只能做一件事 | 同一权重,睡眠分期、呼吸暂停、1 041 种疾病预测全部 SOTA |
一句话:把整晚 PSG 压缩成 128 维向量,就能当“健康指纹”用。
二、技术骨架:多模态 → 通道无关 → 对比对齐
2.1 输入模态与通道上限
| 模态 | 物理信号 | 最多通道数 | 采样率 |
|---|---|---|---|
| BAS | EEG+EOG | 10 | 128 Hz |
| ECG | 心电 | 2 | 128 Hz |
| EMG | 肌电 | 4 | 128 Hz |
| RESP | 胸腹气流、努力度、SpO₂ 等 | 7 | 128 Hz |
作者反思:真实世界 PSG montage 五花八门,把“通道顺序/数量”做成可学习注意力权重,是模型走出单中心、走向“睡眠大数据”最关键的一步。
2.2 5 秒 Token + 5 分钟上下文
-
原始信号 → 5 s 片段(640 点)→ 1D-CNN → 128-D token -
同模态内通道注意力池化 → 每 5 min 序列喂给 Transformer(2 层 8 头) -
序列再池化 → 模态级 128-D 向量 → LOO-CL 对比损失
2.3 LOO-CL:自己预测“其他模态的平均”
把 A、B、C 三模态向量平均得 x̄^{-D}},让 D 模态去对齐它。
直觉:强迫网络抓取所有模态共有的“生理因果”,而非单通道噪声。
三、预训练流程:从 EDF 到 HDF5,一条命令链
3.1 环境 & 硬件
# 推荐配置
GPU: NVIDIA A40/A100 ≥ 1,CUDA 12.4
CPU: 8 核+
RAM: ≥ 32 GB
系统: CentOS 7 / Ubuntu 20 均可
3.2 一键装依赖
git clone https://github.com/zou-group/sleepfm-clinical.git
cd sleepfm-clinical
conda env create -f env.yml
conda activate sleepfm_env
3.3 数据预处理(EDF → HDF5)
python preprocessing/preprocessing.py \
--input_dir /your/psg/edf \
--output_dir /your/psg/hdf5 \
--format edf
-
自动 resample 128 Hz、零相位低通、z-score 标准化 -
输出按“记录-模态-通道”分层,供后续通道无关读取。
3.4 预训练启动(以 MESA 为例)
python sleepfm/pipeline/pretrain.py \
--config configs/config_set_transformer_contrastive.yaml \
--data_path /your/psg/hdf5 \
--split_path configs/dataset_split.json
-
单 epoch A40 上约 1 h;loss 曲线平稳即可停。 -
checkpoint 默认存 sleepfm/checkpoints/model_base。
四、下游任务微调:睡眠分期与疾病预测双轨
4.1 睡眠分期实战
步骤 0:准备标签
CSV 示例(与 EDF/HDF5 同名):
Start,Stop,StageName,StageNumber
0.0,30.0,Wake,0
30.0,60.0,N2,2
...
步骤 1:生成嵌入
python sleepfm/pipeline/generate_embeddings.py \
--ckpt sleepfm/checkpoints/model_base \
--data_path /your/psg/hdf5 \
--save_path /embeddings/mesa
步骤 2:微调
python sleepfm/pipeline/finetune_sleep_staging.py \
--config configs/config_finetune_sleep_events.yaml \
--embed_dir /embeddings/mesa
-
1 min 完成 10 epoch;测试 F1 0.70–0.78(MESA 小数据,仅供调试)。
步骤 3:评估
python sleepfm/pipeline/evaluate_sleep_staging.py \
--ckpt_path /output/staging_best.pt \
--embed_dir /embeddings/mesa
输出混淆矩阵、每阶段 F1、宏观平均。
4.2 疾病预测实战(需自建标签)
-
标签格式:每条记录对应 1 041 维多标签,时间-到-事件(年)+ 是否发生事件。 -
调用 finetune_diagnosis_coxph.py,损失为 multilabel-CoxPH。 -
作者经验:即使只有 10 % 标注,SleepFM 仍超人口学基线 4–7 个百分点。
五、性能快照:数字说话
| 任务 | 指标 | SleepFM | 人口学基线 | End-to-End 监督 |
|---|---|---|---|---|
| 全因死亡 | C-Index / 6 年 AUROC | 0.84 / 0.84 | 0.79 / 0.78 | 0.78 / 0.77 |
| 痴呆 | 同上 | 0.85 / 0.87 | 0.75 / 0.74 | 0.73 / 0.72 |
| 心衰 | 同上 | 0.80 / 0.83 | 0.74 / 0.76 | 0.73 / 0.75 |
| 中风 | 同上 | 0.78 / 0.81 | 0.71 / 0.73 | 0.70 / 0.72 |
| 睡眠分期 | 宏观 F1 | 0.70–0.78 | — | 0.68–0.75 |
| 呼吸暂停 4 级 | Accuracy | 0.69 | — | 0.65 |
作者反思:数字看似“小步提升”,但在 5 000+ 人、1 000+ 病种的统计尺度下,C-Index 每提 0.01 都意味着数百人可被提前干预——这才是基础模型真正的公共卫生价值。
六、跨中心验证:SHHS 零泄漏迁移
-
SHHS 完全未参与预训练;仅用 3 291 例微调,2 000 例测试。 -
心血管死亡 C-Index 0.88,中风 0.82,心衰 0.85——与 SSC 主队列差距 <0.03。 -
启示:医院自采的 PSG 哪怕只有几百例,也能靠 SleepFM 快速“冷启动”出可用风险模型。
七、真实落地场景速写
场景 1:三级睡眠中心
-
已有 8 h PSG 数据 → 次日晨报告自动生成“未来 6 年心衰风险评分” → 心内科联合随访。
场景 2:可穿戴-云端 pipeline
-
居家 3 导联(EEG+ECG+呼吸带)→ 边缘计算做 5 s token → 上传 128-D 向量 → 云端 SleepFM 推断。 -
硬件成本 < 200 USD,即可覆盖百万级睡眠呼吸暂停筛查。
场景 3:临床试验富集
-
招募“5 年内痴呆高风险”人群,用 SleepFM 预筛,降低样本量 30 %,节约千万级预算。
八、作者的一线教训与见解
-
数据清洗比算法更昂贵
58.5 万小时里,约 7 % 记录因采样率不一致、导联掉落被剔除——提前写死“通道-频率”校验脚本,能省下两周人肉排查。 -
先做大模型,再做小设备
我们原本想“边采集边压缩”,结果证明:先训练高容量模型,再知识蒸馏到边缘端,效果与效率双赢。 -
“黑盒”不是原罪
通过分睡眠期、分模态消融,我们发现:-
神经/精神类 → BAS 贡献最大; -
代谢/呼吸类 → 呼吸模态主导; -
心血管 → ECG+RESP 协同。
这样向医生解释后,临床更愿意采纳。
-
九、实用摘要 / 操作清单
-
准备 Linux+A40 以上 GPU + 32 GB 内存。 -
conda env create -f env.yml一键装环境。 -
EDF→HDF5→预训练→生成嵌入→微调→评估,六段脚本串行即可。 -
小样本(<1 k)也能用,至少比人口学模型高 5 个点。 -
记得申请斯坦福公开 SSC 数据或 SHHS 做零泄漏验证。
十、一页速览(One-page Summary)
-
SleepFM = 1 个对比预训练权重 + 4 模态通道无关 Transformer -
58.5 万小时 PSG → 128-D “睡眠指纹” -
130 种疾病 C-Index≥0.75;死亡/痴呆/心衰 AUROC>0.8 -
脚本 6 步走:EDF→HDF5→pretrain→embed→finetune→eval -
硬件最低 RTX 2080 Ti;A100 单 epoch 1 h -
代码、权重、斯坦福数据全开源:GitHub 搜索 sleepfm-clinical
常见 FAQ
-
Q:没有 EDF,只有 CSV 格式的通道数据怎么办?
A:把 CSV 按 128 Hz 重新导出为raw.npy,改写preprocessing.py的读取分支即可,后续流程不变。 -
Q:显卡显存不足如何减小 batch?
A:在config_set_transformer_contrastive.yaml里把batch_size从 32 调到 8,梯度累积accumulate_grad_batches=4,效果等价。 -
Q:能否直接用于儿童或孕妇?
A:训练集包含 1–100 岁,但儿童/孕妇样本比例低;建议先在自己的目标人群上做 1–2 epoch 增量预训练,再微调。 -
Q:模型输出的 128-D 向量如何做可解释化?
A:可用 SHAP 对向量位做生存模型归因,再映射回睡眠期-模态贡献,论文 Supplementary Figure 3 提供了完整代码。 -
Q:商业产品需要授权吗?
A:代码与基础权重采用 MIT 许可证,可商用;但斯坦福 SSC 数据需遵守其独立数据使用协议,不可二次分发。 -
Q:呼吸暂停事件检测粒度能到秒级吗?
A:当前发布版本做 AHI 分级;秒级事件检测需把finetune_diagnosis_coxph.py的 Head 换成 1D-UNet,我们留作读者练习。 -
Q:只想用睡眠分期功能,是否可跳过预训练?
A:可直接下载model_sleep_staging权重,走generate_embeddings.py → evaluate_sleep_staging.py两步即可。

