飞行员短时多模态生理信号疲劳检测:EEG+ECG 融合 XGBoost 方案(论文解读)

发布时间: 2026-09-05
分类: 论文解读 / 航空座舱 / 生物信号融合
标签: EEG, ECG, pilot fatigue, XGBoost, ANOVA-SVM, multimodal fusion, aviation safety


论文信息

项目 内容
标题 To assure aviation safety: the pilot fatigue detection based on short-term multimodal physiological signals
来源 PMC (PMC12909498)
被试 32 名飞行员
信号 EEG + ECG 融合
时间窗 2 秒短时分段
准确率 88.42%(跨被试验证)/ 98.36%(跨片段验证)
训练时间 39.3 秒

1. 核心创新

1.1 关键突破

突破点 传统方案 本文方案
时间窗 30-60秒 2秒
模态 单EEG或单ECG EEG+ECG融合
特征选择 深度学习端到端 ANOVA-SVM 两阶段
分类器 CNN/LSTM XGBoost
训练时间 数小时 39.3秒
跨被试准确率 60-80% 88.42%

1.2 为什么2秒是突破?

时间窗 优势 劣势
60秒 HRV特征丰富 实时性差,疲劳已发生很久
30秒 较好平衡 仍有15秒延迟
10秒 接近实时 HRV统计不稳定
2秒 真正实时 HRV特征受限(本文通过ECG统计特征补偿)

2. 方法详解

2.1 整体框架

2.2 EEG 特征

频段 频率 疲劳时变化
Delta (δ) 0.5-4 Hz ↑ 显著增加
Theta (θ) 4-8 Hz ↑ 增加
Alpha (α) 8-13 Hz ↑ 增加
Beta (β) 13-30 Hz ↓ 混合变化

2.3 ECG 特征

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
import numpy as np
from scipy.signal import find_peaks
from typing import Tuple

class ECGFeatureExtractor:
"""
ECG/HRV 特征提取器

论文方法:2秒短窗内的 ECG 统计特征 + HRV
"""

def __init__(self, fs: int = 250):
self.fs = fs

def extract(self, ecg_signal: np.ndarray) -> dict:
"""
提取 ECG 特征

Args:
ecg_signal: 2秒 ECG 信号

Returns:
features: ECG 特征字典
"""
# R波检测
r_peaks = find_peaks(ecg_signal, distance=self.fs*0.3,
height=0.5*np.max(ecg_signal))[0]

# RR间期
rr_intervals = np.diff(r_peaks) / self.fs

features = {}

if len(rr_intervals) >= 2:
# 时域 HRV 特征
features['rr_mean'] = np.mean(rr_intervals)
features['rr_std'] = np.std(rr_intervals)
features['rr_min'] = np.min(rr_intervals)
features['rr_max'] = np.max(rr_intervals)
features['hr_mean'] = 60 / np.mean(rr_intervals)

# 统计特征(短窗关键)
features['rmssd'] = np.sqrt(np.mean(np.diff(rr_intervals)**2))
features['pnn50'] = np.sum(np.abs(np.diff(rr_intervals)) > 0.05) / len(rr_intervals)
else:
# 短窗可能无足够RR间期,使用ECG统计特征
features['ecg_mean'] = np.mean(ecg_signal)
features['ecg_std'] = np.std(ecg_signal)
features['ecg_skew'] = float(np.sign(np.mean((ecg_signal - np.mean(ecg_signal))**3)))
features['ecg_kurtosis'] = np.mean((ecg_signal - np.mean(ecg_signal))**4) / (np.var(ecg_signal)**2 + 1e-8)
features['ecg_energy'] = np.sum(ecg_signal**2)

return features


class EEGFeatureExtractor:
"""EEG 频域特征提取"""

def __init__(self, fs: int = 250):
self.fs = fs
self.bands = {
'delta': (0.5, 4),
'theta': (4, 8),
'alpha': (8, 13),
'beta': (13, 30)
}

def extract(self, eeg_signal: np.ndarray) -> dict:
"""提取多通道 EEG 频域特征"""
from scipy.signal import welch

features = {}
n_channels = eeg_signal.shape[0]

for ch in range(n_channels):
freqs, psd = welch(eeg_signal[ch], fs=self.fs, nperseg=self.fs*2)

for band_name, (f_low, f_high) in self.bands.items():
mask = (freqs >= f_low) & (freqs <= f_high)
power = np.sum(psd[mask])

features[f'ch{ch}_{band_name}_power'] = power
features[f'ch{ch}_{band_name}_rel'] = power / (np.sum(psd) + 1e-10)

# 频率比
theta_power = features[f'ch{ch}_theta_power']
alpha_power = features[f'ch{ch}_alpha_power']
beta_power = features[f'ch{ch}_beta_power']

features[f'ch{ch}_theta_alpha'] = theta_power / (alpha_power + 1e-10)
features[f'ch{ch}_alpha_beta'] = alpha_power / (beta_power + 1e-10)

return features


class FatigueDetectionPipeline:
"""
飞行员疲劳检测完整管线

EEG + ECG → 特征提取 → ANOVA-SVM选择 → XGBoost分类
"""

def __init__(self):
self.eeg_extractor = EEGFeatureExtractor(fs=250)
self.ecg_extractor = ECGFeatureExtractor(fs=250)
self.selected_features = None

def extract_features(
self,
eeg: np.ndarray, # (C, T)
ecg: np.ndarray # (T,)
) -> dict:
"""提取全部特征"""
eeg_feat = self.eeg_extractor.extract(eeg)
ecg_feat = self.ecg_extractor.extract(ecg)
return {**eeg_feat, **ecg_feat}

def anova_select(self, features_list: list, labels: np.ndarray, top_k: int = 50) -> list:
"""ANOVA 特征筛选"""
from sklearn.feature_selection import f_classif

feature_names = list(features_list[0].keys())
X = np.array([[f[k] for k in feature_names] for f in features_list])

F, p = f_classif(X, labels)

# 按F值排序
ranked = np.argsort(F)[::-1][:top_k]
selected = [feature_names[i] for i in ranked]

return selected


if __name__ == "__main__":
pipeline = FatigueDetectionPipeline()

# 模拟数据
eeg = np.random.randn(14, 500) # 14通道, 2秒@250Hz
ecg = np.random.randn(500) # 2秒@250Hz

features = pipeline.extract_features(eeg, ecg)
print(f"提取特征数: {len(features)}")

# 批量提取
batch = [pipeline.extract_features(np.random.randn(14, 500), np.random.randn(500))
for _ in range(32)]
labels = np.random.randint(0, 2, 32)
selected = pipeline.anova_select(batch, labels, top_k=20)
print(f"ANOVA选择特征: {selected[:5]}...")

print(f"\n=== 论文报告结果 ===")
print(f"被试数: 32")
print(f"时间窗: 2秒")
print(f"跨被试准确率: 88.42%")
print(f"跨片段准确率: 98.36%")
print(f"训练时间: 39.3秒")
print(f"模型: XGBoost + ANOVA-SVM")

3. 实验结果

3.1 性能对比

方法 准确率(跨被试) 准确率(跨片段) 训练时间
EEG-only CNN 76% 92% 2小时
EEG-only Transformer 82% 95% 6小时
EEG+ECG XGBoost 88.42% 98.36% 39.3秒
EEG+ECG CNN-LSTM 85% 97% 4小时

3.2 关键发现

  1. 2秒短窗可行:通过ECG统计特征补偿HRV短窗不足
  2. XGBoost > 深度学习:在跨被试场景下更鲁棒
  3. ANOVA-SVM两阶段选择有效:降低维度同时保留生理意义
  4. 39.3秒训练:比深度学习快300-500倍

4. 跨域启示

4.1 航空→汽车

维度 航空 汽车 可迁移性
时间窗 2秒 2-5秒 ✅
EEG+ECG 可接受 侵入性强 ⚠️ 需替代
XGBoost 轻量 边缘部署 ✅
ANOVA-SVM 通用 通用 ✅

4.2 对 IMS 的建议

建议 优先级
用 XGBoost 替代部分深度学习 🔴 高
采用2-5秒短窗 🔴 高
预留EEG/ECG接口 🟡 中
ANOVA-SVM特征选择 🔴 高

5. 参考资源


2秒短窗 + 多模态融合 + 轻量分类器 = 实时疲劳检测的实用平衡点。 跨被试88%准确率+39秒训练时间证明:不一定需要深度学习才能做好疲劳检测。