针对DEAP数据集的情绪识别分类任务,以下是完整的解决方案步骤:
1. 数据预处理
- 加载数据:使用
scipy.io
加载.mat文件,提取EEG信号(32通道)和标签(效价、唤醒度)。 - 数据分段:将每个试次的EEG信号分割为4秒的窗口(无重叠或50%重叠),每个窗口对应一个样本。
- 标签处理:根据中位数将效价和唤醒度分为高/低两类,生成二分类标签。
2. 特征提取
对每个窗口的每个EEG通道提取以下特征:
- 频域特征:使用Welch方法计算5个频段(delta、theta、alpha、beta、gamma)的功率谱密度。
- 时域特征:均值、方差、Hjorth参数(活动性、移动性、复杂性)。
- 非线性特征:样本熵(复杂度衡量)。
3. 特征处理
- 标准化:使用Z-score标准化所有特征。
- 降维:应用PCA保留95%的方差,减少特征维度。
4. 分类模型
- 模型选择:使用支持向量机(SVM)和随机森林进行对比,采用网格搜索优化超参数。
- 数据划分:按试次划分训练集和测试集,避免同一试次的数据泄漏。
- 交叉验证:分层K折交叉验证(如10折)确保评估的稳健性。
5. 评估指标
计算准确率、F1分数、AUC等指标,对比不同特征组合和模型的性能。
示例代码
import scipy.io
import numpy as np
from sklearn.model_selection import train_test_split, StratifiedKFold
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score, f1_score
from sklearn.decomposition import PCA
from scipy.signal import welch
import antropy as ant # 用于样本熵计算
# 加载数据
mat = scipy.io.loadmat('data/s01.mat')
data = mat['data'][:, :32, :] # EEG通道
labels = mat['labels'][:, :2] # 效价和唤醒度
# 生成二分类标签
valence_labels = (labels[:, 0] > np.median(labels[:, 0])).astype(int)
arousal_labels = (labels[:, 1] > np.median(labels[:, 1])).astype(int)
# 分割窗口
window_size = 4 * 128 # 4秒
n_windows = data.shape[2] // window_size
windows = data[:, :, :n_windows * window_size].reshape(40, 32, n_windows, window_size)
# 特征提取
def extract_features(window):
fs = 128
freq_bands = {'delta': (0.5, 4), 'theta': (4, 8), 'alpha': (8, 12),
'beta': (12, 30), 'gamma': (30, 64)}
features = []
# 频域特征
freqs, psd = welch(window, fs=fs, nperseg=256)
for band in freq_bands.values():
idx = np.where((freqs >= band[0]) & (freqs <= band[1]))[0]
features.append(np.sum(psd[idx]) if len(idx) > 0 else 0)
# 时域特征
features.extend([np.mean(window), np.var(window),
ant.hjorth_params(window)[1], ant.hjorth_params(window)[2]])
# 样本熵
features.append(ant.sample_entropy(window.reshape(-1, 1)))
return features
# 构建特征矩阵和标签
X, y = [], []
for trial in range(40):
for w in range(n_windows):
trial_features = []
for channel in range(32):
window = windows[trial, channel, w]
trial_features.extend(extract_features(window))
X.append(trial_features)
y.append(valence_labels[trial]) # 以效价为例
X = np.array(X)
y = np.array(y)
# 标准化和PCA
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
pca = PCA(n_components=0.95)
X_pca = pca.fit_transform(X_scaled)
# 划分训练集和测试集(按试次划分)
train_trials, test_trials = train_test_split(np.arange(40), test_size=0.2, stratify=valence_labels)
train_indices = [i for i, trial in enumerate(range(40)) for w in range(n_windows) if trial in train_trials]
test_indices = [i for i, trial in enumerate(range(40)) for w in range(n_windows) if trial in test_trials]
X_train, X_test = X_pca[train_indices], X_pca[test_indices]
y_train, y_test = y[train_indices], y[test_indices]
# 训练SVM
svm = SVC(kernel='rbf', C=1.0, gamma='scale')
svm.fit(X_train, y_train)
y_pred = svm.predict(X_test)
print(f"SVM Accuracy: {accuracy_score(y_test, y_pred):.2f}, F1: {f1_score(y_test, y_pred):.2f}")
# 随机森林
rf = RandomForestClassifier(n_estimators=100)
rf.fit(X_train, y_train)
y_pred_rf = rf.predict(X_test)
print(f"RF Accuracy: {accuracy_score(y_test, y_pred_rf):.2f}, F1: {f1_score(y_test, y_pred_rf):.2f}")
关键优化点
- 特征多样性:结合频域、时域和非线性特征,全面捕捉信号特性。
- 数据划分策略:按试次划分避免数据泄漏,确保模型泛化能力。
- 降维处理:PCA保留主要信息,提升计算效率和模型性能。
通过上述步骤,可有效实现DEAP数据集的情绪分类,根据实际需求调整特征组合和模型参数以优化结果。