U-Time 和 U-Sleep
官方实现:
本仓库可用于训练原始的 U-Time 和较新的 U-Sleep 模型。 然而,本仓库自 [1] 以来已有显著扩展,可能会逐渐偏离 [2] 中描述的版本。早期版本可在以下位置找到:
目录
概述
本文档描述了为创建免费公开的睡眠分期系统 U-Sleep [2] 而开发和使用的官方软件包。 U-Sleep 是一个全卷积深度神经网络,用于自动睡眠分期。单个模型实例可以在广泛的临床人群和多导睡眠图(PSG)采集协议中进行准确且鲁棒的睡眠分期训练。
该软件允许使用即时随机选择的输入通道配置,在任意数量的 PSG 数据集上同时训练 U-Sleep。它提供了命令行界面,用于初始化、训练和评估模型,无需修改底层代码库。
预训练的 U-Sleep
接下来我们将更详细地介绍 U-Sleep 背后的软件。请注意:
- 如果您想重新实现、扩展或自己训练 U-Sleep(例如在其他数据集上),您来对地方了!
- 如果您想使用我们预训练的 U-Sleep 模型进行自动睡眠分期,请参考 https://sleep.ai.ku.dk 并按照显示的指南进行操作。另请参阅此仓库以获取 Web 服务器 API 的 Python 绑定。
- U-Sleep 也可在 youSleep BETA 平台 上获得研究和商业许可。
U-Time 和 U-Sleep - 有什么区别?
本仓库存储了用于训练和评估 U-Sleep 睡眠分期模型的代码。它基于并显著扩展了我们的 U-Time 仓库,该仓库发表于 NeurIPS 2019 [1]。在以下内容中,我们将使用术语 U-Sleep 表示鲁棒的高频睡眠分期模型 [2],使用 U-Time 表示用于训练和评估 U-Sleep 模型的代码仓库。
您仍然可以使用此仓库来训练较早的 U-Time 模型,请参阅下面的 U-Time 示例。
系统要求
最低硬件要求
使用已经训练好的 U-Sleep 模型进行睡眠分期通常可以在任何现代笔记本电脑上完成(取决于下面列出的软件要求)。
然而,要从头开始训练 U-Sleep 模型,我们强烈建议使用至少具有以下硬件规格的基于 Linux 的计算机:
- 4+ CPU 核心
- 8+ GiB RAM
- 大量物理存储空间*
- 1 个支持 CUDA 的 GPU(请参考 https://developer.nvidia.com/cuda-gpus 获取详细列表)。
可以在较小的机器上训练模型,也可以不使用 GPU,但这可能需要相当长的时间。同样,更多资源将加快训练速度。如果考虑的数据集超过系统内存(例如上面建议的 8 GiB RAM),则必须预处理数据并从磁盘流式传输,如下面的演示部分所示。在较大的机器上,可以受益于在内存中维护更大的数据池。例如,我们使用 8 个 CPU 核心、1 个 GPU 和 40 GiB RAM 训练了 U-Sleep [2],请参阅下面的完整复现 U-Sleep部分。
*所需的硬盘空间取决于所考虑的数据集的数量和大小。对于完整复现 U-Sleep,大约需要 4 TiB 的可用存储空间。
软件要求:
- 安装了 Linux 操作系统的计算机。我们已在 Red Hat Enterprise (v7.8) 和 Ubuntu (v18.04) 服务器上开发和测试了该软件,但任何现代发行版都应该可以工作。该软件也在 MacOS Catalina (10.15.6) 上测试过,仅用于基于 CPU 的训练和预测。
- Anaconda 或 Miniconda, v4.5 或更高版本,64 位。
如果您要从头开始自己训练 U-Sleep 模型,我们强烈建议在 GPU 上进行。为了在 GPU 上使用 U-Time
包,需要 tensorflow
(v2.8.0
) 库。为此,您的系统还需要以下额外软件:
- NVIDIA GPU 驱动程序 v450.x 或更高版本。
- CUDA Toolkit v11.2。
- cuDNN SDK v8.1。
请参阅 https://www.tensorflow.org/install/gpu 获取更多详细信息。您不需要自己安装 TensorFlow(请参阅下面的安装指南),但必须在继续之前安装上述软件。
安装指南
在安装了 anaconda
或 miniconda
并至少有 1 个可用的支持 CUDA 的 GPU 的 Linux 机器上,运行以下命令以下载软件,创建名为 u-sleep
的 conda 环境,并设置最新的 U-Time 软件包及其依赖项:
git clone https://github.com/perslev/U-Time.git
conda env create --file U-Time/environment.yaml
conda activate u-sleep
pip install U-Time/
或者,你也可以从PyPi安装该软件包(可能更新较少):
pip install utime
演示
在接下来的内容中,我们将演示如何在[2]中使用的数据集的一个显著受限子集上启动U-Sleep的短训练会话。
要求
- 完成安装指南中概述的步骤。
- 此演示在普通计算机和网络连接上大约需要
30分钟
才能完成。大部分时间用于从公共数据库下载所需数据。根据当前数据库流量,这一步可能需要更长时间。 - 你的计算机上需要约
11 GiB
的可用磁盘空间。
准备项目目录
首先,我们创建一个项目目录,用于存储此演示的所有数据。ut init
命令将创建一个文件夹并填充一组默认超参数值:
ut init --name demo --model usleep_demo
进入新创建的项目目录,我们会发现一个存储超参数的文件夹:
cd demo
ls
> hyperparameters
下载公共PSG数据
我们将使用ut fetch
命令从公共睡眠数据库Sleep-EDF和DCSM下载6项PSG研究。
你需要大约10 GiB
的可用硬盘空间来存储下载的文件。根据你的网速和两个服务器的当前负载,下载可能需要5分钟到几个小时不等:
ut fetch --dataset sedf_sc --out_dir data/sedf_sc --N_first 6
ut fetch --dataset dcsm --out_dir data/dcsm --N_first 6
我们在此演示中将考虑的原始数据现已下载完毕。
我们的demo
项目文件夹现在大致具有以下结构:
└─ demo
├─ hyperparameters
└─ data
├─ dcsm
│ ├─ tp005f7e68_a084_46bb_9f0a_b6a084155a1c
│ │ ├─ hypnogram.ids
│ │ └─ psg.h5
│ ├─ ...
└─ sedf_sc
├─ SC4001E0
│ ├─ SC4001E0-PSG.edf
│ └─ SC4001EC-Hypnogram.edf
├─ ...
数据集拆分
在继续训练U-Sleep模型之前,我们使用ut cv_split
命令将每个数据集分成固定的训练/验证/测试集。
必须调用该命令两次,每次都使用一组独特的参数来指定数据集的命名约定:
# 拆分数据集 SEDF-SC
ut cv_split --data_dir data/sedf_sc/ \
--subject_dir_pattern 'SC*' \
--CV 1 \
--validation_fraction 0.10 \
--test_fraction 0.25 \
--subject_matching_regex 'SC4(\d{2}).*' \
--seed 123
# 拆分数据集 DCSM
ut cv_split --data_dir data/dcsm/ \
--subject_dir_pattern 'tp*' \
--CV 1 \
--validation_fraction 0.10 \
--test_fraction 0.25 \
--seed 123
请注意,SEDF-SC
的拆分是基于每个受试者进行的。同一受试者的所有PSG记录都将被放入相同的数据集拆分中。
对于DCSM
来说,这是不需要的,因为所有记录都来自不同的受试者。
请注意,如果你修改了上述任何命令,例如使用不同的输出目录名称,你需要在继续下一步之前相应地修改存储在hyperparameters/dataset_configurations
下的数据集超参数文件中的路径。
数据预处理
运行以下命令准备训练数据:
ut preprocess --out_path data/processed_data.h5 --dataset_splits train_data val_data
ut preprocess
脚本根据hyperparameters/hparams.yaml
中设置的参数和hyperparameters/dataset_configurations
文件夹中所有特定于数据集的文件中描述的方式加载和处理所有数据集。
具体来说,它加载所需的通道(忽略其余部分),重新采样、缩放和裁剪数据,将睡眠图阶段映射到训练期间内部使用的整数表示,最后将处理后的数据保存到HDF5存档中。
在训练时,可以直接从这个存档流式传输数据,以显著减少所需的系统内存。
也可以完全跳过这一步,选择 1) 提前加载训练所需的所有数据,或 2) 在训练过程中实时流式传输和应用预处理,如下面U-Sleep的完整复现部分所示。
训练模型
现在我们可以通过调用ut train
命令开始训练。默认的一组优化超参数已经预先指定,位于项目目录的hyperparameters/hparams.yaml
文件中。在这个演示中,我们只会进行一个非常短的训练会话,但你可以随意修改hparams.yaml
文件中的任何参数。
运行以下命令:
ut train --num_gpus=1 --preprocessed --seed 123
如果你没有可用的GPU,希望在CPU上训练,可以将上述命令中的--num_gpus=1
参数替换为--num_gpus=0
。在CPU上训练可能需要长达30分钟。
训练结束后,model
文件夹中会有一组候选模型可用。使用观察到的最佳模型(验证平均F1分数最高),
我们可以使用所有通道组合对SEDF-SC
和DCSM
的测试集进行预测,并通过调用以下ut predict
命令计算多数投票:
在测试集上进行预测和评估
ut predict --num_gpus=1 \
--data_split test_data \
--strip_func strip_to_match \
--one_shot \
--save_true \
--majority \
--out_dir predictions
预测的睡眠图现在可以在 predictions/test_data
目录下找到。
最后,让我们打印一个全局混淆矩阵(计算所有受试者的结果)用于数据集 sedf_sc
(将 sedf_sc
替换为 dcsm
以评估 DCSM):
ut cm --true 'predictions/test_data/sedf_sc/*TRUE.npy' \
--pred 'predictions/test_data/sedf_sc/majority/*PRED.npy' \
--ignore 5 \
--round 2 \
--wake_trim_min 30
>>> 正在查找文件...
>>> 正在加载2对数据...
>>> 注意:清醒状态修剪30分钟(周期长度30秒)
>>> 注意:忽略类别:[5]
>>>
>>> 原始混淆矩阵:
>>>
>>> 预测0 预测1 预测2 预测3 预测4
>>> 真实0 0 0 17 234 0
>>> 真实1 0 0 132 146 0
>>> 真实2 0 0 790 157 0
>>> 真实3 0 0 25 189 0
>>> 真实4 0 0 243 99 0
>>>
>>> 原始指标:
>>>
>>> F1 精确度 召回率/敏感度
>>> 类别0 0.00 0.00 0.00
>>> 类别1 0.00 0.00 0.00
>>> 类别2 0.73 0.65 0.83
>>> 类别3 0.36 0.23 0.88
>>> 类别4 0.00 0.00 0.00
>>> 平均 0.22 0.18 0.34
如果你得到了类似上面的输出,恭喜!你已经成功安装、配置、训练并评估了一个U-Sleep模型在两个不同的数据集上。
请注意:
-
如果你在GPU上运行上述代码,即使指定了--seed参数,你可能也无法获得与此处列出的完全相同的数字。这是因为在GPU上评估时,U-Sleep训练过程中使用的一些计算本质上是非确定性的。 然而,使用训练好的U-Sleep模型进行预测将会产生确定性的输出。
-
获得的演示模型性能非常低,不适合实际的睡眠分期。原因是我们在非常有限的数据集上训练了U-Sleep,而且只训练了很少的轮次。 请参考完整复现U-Sleep部分,了解如何准备和训练完整版本的U-Sleep。
完整复现U-Sleep
上面的演示原则上描述了复现U-Sleep所需的所有步骤,如[2]中所报告的。 主要的 - 也是显著的 - 区别在于,为了复现完整模型,你需要1)能够访问 2)下载和 3)预处理所有必需的数据集。你可能还需要一台资源更丰富的计算机,如系统要求中所述。
准备数据集
我们尽最大努力使这个过程尽可能简单。你应该采取以下步骤:
- 仔细阅读(至少)我们论文[2]的方法和补充数据集部分,以熟悉数据集、预处理、训练流程等。
- 从国家睡眠研究资源、PhysioNet或其他睡眠数据库下载所有数据集,如补充材料的数据集部分所描述和引用的。对于某些数据集,你必须申请获取访问权限,而其他数据集则是公开可用的。一些数据集可以使用
ut fetch
命令轻松下载。请调用ut fetch --help
查看最新的可以通过这种方式下载的数据集列表。 - 将所有下载的数据放入单个文件夹
[LOCAL_PATH]
中,每个数据集一个子文件夹。 - 按照本仓库
resources/usleep_dataset_pred
文件夹下(也可在这里找到)为每个数据集单独指定的方式运行ut extract
、ut extract_hypno
和ut cv_split
。这些命令将提取数据并将其放入U-Time接受的文件夹结构和格式中,并将数据分割成子集。 - (可选)
ut extract
命令将选择相关通道,将它们重采样到128 Hz,并将数据存储在HDF5存档中。默认情况下不会删除原始数据。如果你的硬盘空间有限,在处理下一个数据集之前,考虑删除旧文件。 - 初始化U-Sleep项目:
ut init --name u-sleep --model usleep
。 - 对于
u-sleep/hyperparameters/dataset_configurations/
中的每个数据集配置文件,将字符串[LOCAL_PATH]替换为你的数据的[LOCAL_PATH]
。
训练模型
如果你有40+ GiB系统内存可用,使用以下命令训练U-Sleep:
ut train --num_gpus 1 --max_loaded_per_dataset 40 --num_access_before_reload 32 --train_queue_type limitation --val_queue_type lazy --max_train_samples_per_epoch 1000000
在内存较少的系统上,你可以选择1)将--max_loaded_per_dataset
参数从当前的40
降低到更小的值(这将在活动内存池中保留较少的PSG记录,从而减少选择记录时的随机性),或2)预处理数据并在训练期间流式传输数据(如上面的演示所示),方法是调用以下两个命令(替换适用的[LOCAL_PATH]):
ut preprocess --out_path '[LOCAL_PATH]/processed_data.h5' --dataset_splits train_data val_data
ut train --num_gpus 1 --preprocessed --max_train_samples_per_epoch 1000000
这将应用所有预处理,创建一个适合流式传输的数据存档,并使用从磁盘即时加载的样本训练U-Sleep。
由于考虑的数据集规模庞大,使用默认参数训练U-Sleep可能需要很长时间。我们建议增加学习率(从当前的1e-7
提高到如1e-6
),除非您想在[2]中考虑的完全相同条件下重新创建U-Sleep。
U-Time示例
您仍然可以使用此存储库来训练较早的U-Time模型。以下我们展示一个端到端的示例。下面列出的命令准备一个项目文件夹,下载sleep-edf-153数据集,在固定的训练/验证/测试数据集分割设置下拟合和评估U-Time模型。请注意,以下代码并不重现[1]中的sleep-edf-153实验,因为那里使用了10折交叉验证。要运行交叉验证实验,请参考ut cv_split --help
和ut cv_experiment --help
命令。
# 获取公共睡眠分期数据集 ut fetch --dataset sedf_sc --out_dir datasets/sedf_sc # 准备固定分割实验 ut cv_split --data_dir 'datasets/sedf_sc' \ --subject_dir_pattern 'SC*' \ --CV 1 \ --validation_fraction 0.20 \ --test_fraction 0.20 \ --subject_matching_regex 'SC4(\d{2}).*' \ --file_list # 初始化U-Time项目 ut init --name my_utime_project \ --model utime \ --data_dir datasets/sedf_sc/views/fixed_split # 开始训练 cd my_utime_project ut train --num_gpus=1 --channels 'EEG Fpz-Cz' # 预测和评估 ut evaluate --out_dir eval --one_shot # 打印混淆矩阵 ut cm --true 'eval/test_data/dataset_1/files/*/true.npz' \ --pred 'eval/test_data/dataset_1/files/*/pred.npz' # 打印每个受试者的汇总统计信息 ut summary --csv_pattern 'eval/test_data/*/evaluation_dice.csv' \ --print_all # 为128 Hz信号的每3秒输出睡眠阶段 # 这里,'folder_regex'匹配数据集中的2个文件 ut predict --folder_regex '../datasets/sedf_sc/SC400[1-2]E0' \ --out_dir high_res_pred \ --data_per_prediction 384 \ --one_shot
参考文献
[1] U-Time
@incollection{NIPS2019_8692,
title = {U-Time: A Fully Convolutional Network for Time Series Segmentation Applied to Sleep Staging},
author = {Perslev, Mathias and Jensen, Michael and Darkner, Sune and Jennum, Poul J\o rgen and Igel, Christian},
booktitle = {Advances in Neural Information Processing Systems 32},
editor = {H. Wallach and H. Larochelle and A. Beygelzimer and F. d\textquotesingle Alch\'{e}-Buc and E. Fox and R. Garnett},
pages = {4415--4426},
year = {2019},
publisher = {Curran Associates, Inc.},
url = {http://papers.nips.cc/paper/8692-u-time-a-fully-convolutional-network-for-time-series-segmentation-applied-to-sleep-staging.pdf}
}
[2] U-Sleep
U-Sleep: 高频睡眠分期的韧性方法
Mathias Perslev (1), Sune Darkner (1), Lykke Kempfner (2), Miki Nikolic (2), Poul Jørgen Jennum (2) & Christian Igel (1)
npj Digital Medicine, 4, 72 (2021)
https://doi.org/10.1038/s41746-021-00440-5
(1) 丹麦哥本哈根大学计算机科学系
(2) 丹麦格洛斯特鲁普国家医院睡眠医学中心