发布时间:2026/8/24 17:46:56
多导睡眠五大PSG数据集统一格式化处理|SHHS 完整五个数据集处理请见https://blog.csdn.net/m0_70335361/article/details/151406787?fromshareblogdetailsharetypeblogdetailsharerId151406787sharereferPCsharesourcem0_70335361sharefromfrom_linkhttps://blog.csdn.net/m0_70335361/article/details/151406787?fromshareblogdetailsharetypeblogdetailsharerId151406787sharereferPCsharesourcem0_70335361sharefromfrom_link本文代码已公开至GitHub - lijinyang439-arch/PSGPrep: Config-driven, auditable preprocessing for PSG sleep-staging datasets — 22 profiles, deterministic pairing, QC, provenance, and privacy-aware outputs. · GitHub若需要如SHHS、Sleep-EDF、ISRUC、NSRR等数据集的预处理脚本及其他请私信博主。一、背景介绍睡眠医学研究中多导睡眠图PSG数据集的异构性导致跨研究分析困难SHHS数据库作为公开基准数据集的价值统一格式化处理对提高数据复用性和算法泛化能力的作用二、数据集介绍SHHSSleep Heart Health Study是目前世界上规模较大的多中心睡眠监测研究项目之一旨在探索睡眠呼吸障碍如睡眠呼吸暂停综合征与心血管疾病之间的关系。研究时间从 1995 年开始受试者人数超过6,000 名成年人数据类型基于多导睡眠图PSG的夜间监测数据数据规模原始 PSG 数据 临床/人口学信息SHHS 提供了完整的多导睡眠监测信号EEG脑电图主要通道如 C4–M1EOG眼电图左右眼动信号ROC、LOCEMG肌电图下颌肌或腿部肌电ECG心电图呼吸信号气流、胸腹呼吸带血氧饱和度SpO₂打鼾、体位、脉搏等附加指标此外还包括睡眠分期标签Wake、N1、N2、N3、REM呼吸事件标注呼吸暂停、低通气等临床与人口学数据BMI、血压、心血管疾病史等官网提供的文件如下在 SHHS 访问 1 中有 5,793 名受试者获得了原始多导睡眠图数据在 SHHS 访问 2 中有 2,651 名受试者获得了原始多导睡眠图数据。每个记录都有一个信号文件 (.EDF) 和两个版本的事件评分和时期分期注释 (.XML)。EDF——从 Compumedics Profusion 导出的欧洲数据格式的信号文件。XML (Profusion) - 从 Compumedics Profusion 导出的注释文件。XML (NSRR) - 在EDF 编辑器和转换器工具中处理的注释文件。三、数据集预处理step1导入必要的库from mne.io import concatenate_raws, read_raw_edf import matplotlib.pyplot as plt import mne import os import numpy as np from tqdm import tqdm from sklearn.preprocessing import StandardScaler import xml.etree.ElementTree as ETstep2基础路径与配置dir_path_psg /shhs/polysomnography/edfs/shhs1 dir_path_ann /shhs/polysomnography/annotations-events-profusion/shhs1 seq_dir /data/SHHS1/seq label_dir /data/SHHS1/labels signal_name [EEG, EOG(L)] label2id {0: 0, 1: 1, 2: 2, 3: 3, 4: 3, 5: 4, 9: 0} target_sfreq 100 epoch_sec 30 pack_size 20 # 每 20 个 epoch 打包成一个序列step3工具函数def step3_list_and_pair_files(dir_psg, dir_ann): psg_f_names sorted(os.listdir(dir_psg)) label_f_names sorted(os.listdir(dir_ann)) pairs [] for psg_f_name, label_f_name in zip(psg_f_names, label_f_names): if psg_f_name[:12] label_f_name[:12]: pairs.append((psg_f_name, label_f_name)) print(f[Step 2] 共配对到 {len(pairs)} 个文件) # print(pairs) return pairsstep4预处理和读取EDFdef step3_prepare_dirs(seq_dir, label_dir): os.makedirs(seq_dir, exist_okTrue) os.makedirs(label_dir, exist_okTrue) print(f[Step 3] 输出目录已就绪\n seq_dir{seq_dir}\n label_dir{label_dir}) def step4_load_and_preprocess_psg(psg_path): # 读取原始 raw read_raw_edf(psg_path, preloadTrue, verboseERROR) print(f[Step 4] 原始 info\n{raw.info}) # 选通道 raw.pick_channels(signal_name) # 重采样 滤波 raw.resample(sfreqtarget_sfreq) raw.filter(0.3, 35, fir_designfirwin) print(f[Step 4] 预处理后 info\n{raw.info}) # 转 DataFrame 再取值第一列是 time需要去掉 psg_array raw.to_data_frame().values psg_array psg_array[:, 1:] # 去除时间列只保留信号通道形状: (N_samples, 2) # 标准化逐记录 std StandardScaler() psg_array std.fit_transform(psg_array) # 对齐到 30s100Hz * 30s 3000 样本 samples_per_epoch epoch_sec * target_sfreq cut_tail30 psg_array.shape[0] % samples_per_epoch if cut_tail30 0: psg_array psg_array[:-cut_tail30, :] # reshape 成 (N_epoch, 3000, 2) psg_array psg_array.reshape(-1, samples_per_epoch, len(signal_name)) # 对齐到 20 个 epoch 的整包 cut_tail20 psg_array.shape[0] % pack_size if cut_tail20 0: psg_array psg_array[:-cut_tail20, :,:] # 形状变换 (N_epoch, 3000, 2) - (N_pack, 20, 3000, 2) - (N_pack, 20, 2, 3000) psg_array psg_array.reshape(-1, pack_size, samples_per_epoch, len(signal_name)) epochs_seq psg_array.transpose(0, 1, 3, 2) print(f[Step 4] 预处理后数组形状epochs_seq{epochs_seq.shape} (N_pack, {pack_size}, C{len(signal_name)}, T{samples_per_epoch})) return epochs_seqstep5解析xmldef step5_parse_labels(xml_path, label2id, cut_tail20): labels_list [] tree ET.parse(xml_path) root tree.getroot() # 与原脚本一致直接遍历 SleepStage for child in root.iter(SleepStage): labels_list.append(label2id[child.text]) labels_array np.array(labels_list, dtypenp.int64) # 对齐到 20 的整包与 Step4 的切尾数量一致 if cut_tail20 0: labels_array labels_array[:-cut_tail20] labels_seq labels_array.reshape(-1, pack_size) print(f[Step 5] 标签形状labels_seq{labels_seq.shape} (N_pack, {pack_size})) return labels_seqstep6保存文件def step6_save_npys(out_seq_dir, out_label_dir, rec_id, epochs_seq, labels_seq, start_seq_idx0, start_label_idx0): # 建子目录 seq_subdir os.path.join(out_seq_dir, rec_id) label_subdir os.path.join(out_label_dir, rec_id) os.makedirs(seq_subdir, exist_okTrue) os.makedirs(label_subdir, exist_okTrue) # 保存序列 local_num_seqs 0 for i, seq in enumerate(epochs_seq): seq_name os.path.join(seq_subdir, f{rec_id}-{start_seq_idx local_num_seqs}.npy) with open(seq_name, wb) as f: np.save(f, seq) local_num_seqs 1 # 保存标签 local_num_labels 0 for i, label_pack in enumerate(labels_seq): label_name os.path.join(label_subdir, f{rec_id}-{start_label_idx local_num_labels}.npy) with open(label_name, wb) as f: np.save(f, label_pack) local_num_labels 1 print(f[Step 6] 保存完成seq{local_num_seqs}labels{local_num_labels}rec_id{rec_id}) return local_num_seqs, local_num_labelsstep7mainif __name__ __main__: # Step 2: 配对 PSG 与 XML psg_label_f_pairs step2_list_and_pair_files(dir_path_psg, dir_path_ann) print(f[Step 2] 映射表{label2id}) # Step 3: 准备输出目录 step3_prepare_dirs(seq_dir, label_dir) # Step 4~6: 循环处理若干记录与原脚本一致前 150 个 num_seqs 0 num_labels 0 for psg_f_name, label_f_name in tqdm(psg_label_f_pairs[:150], descProcessing SHHS1): rec_id psg_f_name[:12] psg_path os.path.join(dir_path_psg, psg_f_name) xml_path os.path.join(dir_path_ann, label_f_name) # ---- Step 4: 读取与预处理 PSG ---- # 这里需要知道在对齐到 20-epoch 之前被截去的 epoch 数我们按与你原逻辑严格同步 # 先对齐到 30s - 再 reshape - 再对齐到 20 的整包 # 为了获得 cut_tail20我们复用内部逻辑先计算 epoch 数后对齐见下。 raw_tmp read_raw_edf(psg_path, preloadTrue, verboseERROR) raw_tmp.pick_channels(signal_name) raw_tmp.resample(sfreqtarget_sfreq) raw_tmp.filter(0.3, 35, fir_designfirwin) arr_tmp raw_tmp.to_data_frame().values[:, 1:] samples_per_epoch epoch_sec * target_sfreq cut_tail30 arr_tmp.shape[0] % samples_per_epoch if cut_tail30 0: arr_tmp arr_tmp[:-cut_tail30, :] n_epoch arr_tmp.shape[0] // samples_per_epoch cut_tail20 n_epoch % pack_size # 需要在标签侧裁掉同样的 epoch 数 # 正式得到 epochs_seq epochs_seq step4_load_and_preprocess_psg(psg_path) # ---- Step 5: 解析与对齐标签 ---- labels_seq step5_parse_labels(xml_path, label2id, cut_tail20) # ---- Step 6: 保存 ---- add_seqs, add_labels step6_save_npys( seq_dir, label_dir, rec_id, epochs_seq, labels_seq, start_seq_idxnum_seqs, start_label_idxnum_labels ) num_seqs add_seqs num_labels add_labels # Step 7: 汇总打印 print(f[Step 7] 全部完成保存序列 {num_seqs} 个标签 {num_labels} 个。)最后生成结果

相关新闻

2026/8/24 17:41:54

随机信号参数建模:从AR模型到实战应用全解析

1. 项目概述:从“听天由命”到“心中有数” “随机信号”这个词听起来有点玄乎,但说白了,就是那些我们无法用一个确定公式来精确预测的信号。比如,你手机麦克风录下的环境噪音、股票市场的每日涨跌、或者心电图里那些细微的波动&a…

2026/8/24 20:18:13

Czkawka:一款开源工具找出重复文件、相似图片与空文件夹

Czkawka:一款开源工具找出重复文件、相似图片与空文件夹 【免费下载链接】czkawka Multi functional app to find duplicates, empty folders, similar images etc. 项目地址: https://gitcode.com/GitHub_Trending/cz/czkawka Czkawka 是一款用 Rust 编写的…

2026/8/24 20:18:13

把风扇拖成你喜欢的形状:G-Helper 风扇控制全流程

把风扇拖成你喜欢的形状:G-Helper 风扇控制全流程 【免费下载链接】g-helper Lightweight Armoury Crate alternative for Asus laptops with nearly the same functionality. Works with ROG Zephyrus, Flow, TUF, Strix, Scar, ProArt, Vivobook, Zenbook, Expert…

2026/8/24 20:18:13

简单理解StarRocks

链接地址 上面连接中的Short‑Key没有写清楚 是根据排序键后进行1024的,可以看文中最后面的中文文档查看 额外补充: OLTP:关系例如MySQL 高并发、小事务,读写频繁 ​行式存储,范式化设计(3NF&#xff09…

2026/8/24 20:18:13

网文原始素材到可投产短剧分集剧本完整落地流程

我所在是八人内容改编工作室,主攻网文IP短剧、漫剧改编项目,常规项目体量20‑80集,单集1‑2分钟,我的主要工作是把控从原始网文文本,到分集剧本、故事板的中间转化环节,对接编剧、分镜人员以及后期生产链路…

2026/8/24 0:07:22

[光学原理与应用-521]:对光的错误理解与纠偏

首先光是一种能量的载体和形态,宏观上观察到的光是由无数个微观的光量子组成的,每个光子在产生的瞬间,其在真空的空间中以确定不变的速度沿着一个初始的方向一直向前,在微观层面,每个光量子的运动轨迹是以波函数所展现…

2026/8/24 1:12:32

SIP通话转接原理与REFER方法实战解析

1. 通话转接不是“挂断再拨号”,而是SIP会话的动态重定向你有没有遇到过这样的场景:客服坐席A正在和客户通电话,突然需要把这通对话无缝转给专家坐席B,客户完全感知不到中间的断连——既没听到忙音,也没被要求重新拨号…

2026/8/24 8:17:29

Kolla-ansible单节点OpenStack部署实战:从环境准备到排坑指南

1. 为什么选择Kolla-ansible来部署单节点OpenStack?如果你正在寻找一种能把OpenStack从“概念”快速变成“可用的实验环境”的方法,那么Kolla-ansible几乎是当前最主流、最省心的选择。我见过太多人卡在手动编译依赖、配置服务、处理版本冲突的泥潭里&am…

2026/8/24 1:09:25

3条命令跑通LocalAI:无GPU本地AI引擎部署

3条命令跑通LocalAI:无GPU本地AI引擎部署 【免费下载链接】LocalAI LocalAI is the open-source AI engine. Run any model - LLMs, vision, voice, image, video - on any hardware. No GPU required. 项目地址: https://gitcode.com/GitHub_Trending/lo/LocalAI…

2026/8/24 1:09:25

AI推理性能测试怎么做:MLPerf Inference完整上手指南

AI推理性能测试怎么做:MLPerf Inference完整上手指南 【免费下载链接】inference Reference implementations of MLPerf inference benchmarks 项目地址: https://gitcode.com/gh_mirrors/inf/inference 同一个模型换一张卡,速度快多少你知道吗&a…

2026/8/24 13:42:17

实测才敢推 AI论文网站 2026最新测评与推荐

2026年真正好用的AI论文网站,核心看生成的论文质量、低AI味、格式正确、学术适配四大指标。综合实测,千笔AI、ThouPen、豆包、DeepSeek、Grammarly 是当前最值得推荐的梯队,覆盖从免费到付费、从中文到英文、从文科到理工的全场景需求。一、综…

2026/8/24 18:13:48

2026必备!AI论文网站测评:最新推荐与深度对比

2026年真正好用的AI论文网站,核心看生成的论文质量、低AI味、格式正确、学术适配四大指标。综合实测,千笔AI、ThouPen、豆包、DeepSeek、Grammarly 是当前最值得推荐的梯队,覆盖从免费到付费、从中文到英文、从文科到理工的全场景需求。 一、…

2026/8/23 4:22:01

摆脱论文困扰!盘点2026年全网爆红的的AI论文写作工具

一天写完毕业论文在2026年已不再是天方夜谭。2026年最炸裂、实测能大幅提速的AI论文写作工具,覆盖选题构思、文献整理、内容生成、格式排版等核心场景,真正帮你高效搞定论文难题。 一、全流程王者:一站式搞定论文全链路(一天定稿首…