该代码主要用于处理 EEG 数据,并使用卷积神经网络(CNN)进行分类
代码架构总结:
数据预处理、模型构建、模型训练和评估
1. 导入必要的库
numpy:用于数值计算和数组操作
scipy.io:用于加载 .mat 文件
tensorflow 和 tensorflow.keras:用于构建和训练深度学习模型
sklearn.model_selection:用于数据集的划分
sklearn.preprocessing:用于标签编码(如果需要)
matplotlib.pyplot:用于绘制训练过程中的损失和准确度曲线
import numpy as np
import scipy.io as sio
import tensorflow as tf
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Conv1D, MaxPooling1D, Flatten, Dense
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import LabelEncoder
import matplotlib.pyplot as plt
2.数据预处理
load_mat_data 函数部分
def load_mat_data(mat_file_paths):
eeg_data_list = []
labels_list = []
for mat_file in mat_file_paths:
data = sio.loadmat(mat_file)
# 假设 EEG 数据在 'data' 中,标签在 'labels' 中
eeg_data = data['data'] # EEG 数据 (假设形状为 (通道数, 时间点数, 样本数))
labels = data['labels'].flatten() # 标签 (样本数,)
# 获取 EEG 数据的样本数
num_samples = eeg_data.shape[2]
# 根据标签数量筛选数据样本
num_labels = len(labels)
# 如果标签数小于 EEG 数据的样本数,截取前 num_labels 个样本进行训练
if num_labels < num_samples:
eeg_data = eeg_data[:, :, :num_labels]
# 保留有效标签的 EEG 数据
eeg_data_valid = eeg_data
labels_valid = labels[:eeg_data_valid.shape[2]] # 保留有效标签
# 将有效的 EEG 数据和标签添加到列表中
eeg_data_list.append(eeg_data_valid)
labels_list.append(labels_valid)
# 确保至少有一个有效的实验数据
if not eeg_data_list:
raise ValueError("没有有效的 EEG 数据和标签,所有文件都被跳过。")
# 将所有实验数据拼接在一起
eeg_data = np.concatenate(eeg_data_list, axis=2) # 按照样本维度拼接
labels = np.concatenate(labels_list, axis=0) # 标签的拼接
print(f"拼接后的 EEG 数据形状: {eeg_data.shape}")
print(f"拼接后的 标签形状: {labels.shape}")
# 将数据转置为 (样本数, 时间点数, 通道数)
eeg_data = eeg_data.transpose(2, 1, 0)
# 训练集和测试集划分
X_train, X_test, y_train, y_test = train_test_split(eeg_data, labels, test_size=0.2, random_state=42)
# 如果是回归任务,直接使用原始标签,不需要 LabelEncoder
# 对标签进行编码(如果是分类问题,才需要进行编码)
# 输出训练集和测试集形状
print(f"训练集形状: {X_train.shape}")
print(f"测试集形状: {X_test.shape}")
return X_train, X_test, y_train, y_test
1)输入.mat 文件路径列表。用for循环 遍历每个 .mat 文件,加载 EEG 数据和标签。
1. 假设 EEG 数据的形状为 (通道数, 时间点数, 样本数),标签的形状为 (样本数,)。
2. 如果标签数量小于 EEG 数据的样本数,截取前 num_labels 个样本。
3. 将所有实验数据拼接在一起,形成最终的 EEG 数据和标签。
4. 将 EEG 数据转置为 (样本数, 时间点数, 通道数) 的形状,以便输入到 CNN 中。
2) 使用 train_test_split 将数据划分为训练集和测试集。并输出训练集和测试集的 EEG 数据及对应的标签。
load_mat_data(mat_file_paths) 函数用于加载并处理EEG数据,数据和标签的分割、拼接等操作。代码首先加载MATLAB .mat 文件中的EEG数据,假设数据存在于 data 键中,标签在 labels 键中。
数据的形状会根据需要进行调整,并分割为训练集和测试集。
3. 构建 CNN 模型
build_model 函数部分
def build_model(input_shape, num_classes):
# 构建卷积神经网络模型
model = Sequential()
model.add(Conv1D(64, 3, activation='relu', input_shape=input_shape))
model.add(MaxPooling1D(pool_size=2))
model.add(Conv1D(128, 3, activation='relu'))
model.add(MaxPooling1D(pool_size=2))
model.add(Flatten())
model.add(Dense(128, activation='relu'))
model.add(Dense(num_classes, activation='softmax')) # 假设是分类问题
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])
return model
输入形状 (时间点数, 通道数) 和类别数量 num_classes。
1)模型结构
1. 1D 卷积层 (Conv1D):64 个滤波器,卷积核大小为 3,激活函数为 relu。
2. 1D 最大池化层 (MaxPooling1D):池化大小为 2。
3. 第二个 1D 卷积层:128 个滤波器,卷积核大小为 3,激活函数为 relu。
4. 第二个 1D 最大池化层:池化大小为 2。
5. 展平层 (Flatten):将多维输入展平为一维。
6. 全连接层 (Dense):128 个神经元,激活函数为 relu。
7. 输出层 (Dense):num_classes 个神经元,激活函数为 softmax(用于多分类任务)。
2)模型编译
使用 adam 优化器,损失函数为 sparse_categorical_crossentropy,评估指标为 accuracy。
build_model(input_shape, num_classes) 使用 Sequential API 构建了一个带有两层卷积和池化层的模型。这个模型通过 Conv1D 和 MaxPooling1D 层来处理1D时间序列数据,最后通过全连接层(Dense)输出预测结果。
编译模型时使用了 Adam 优化器,并选择了 sparse_categorical_crossentropy 损失函数,这是针对分类任务的常用选择。
4. 训练和评估模型
train_and_evaluate 函数部分
def train_and_evaluate(mat_file_paths):
# 加载数据并分割训练集和测试集
X_train, X_test, y_train, y_test = load_mat_data(mat_file_paths)
# 确定输入形状和类别数量
input_shape = (X_train.shape[1], X_train.shape[2]) # 输入形状是 (时间点数, 通道数)
num_classes = len(np.unique(y_train)) # 分类任务的类别数
# 构建模型
model = build_model(input_shape, num_classes)
# 训练模型
history = model.fit(X_train, y_train, epochs=50, batch_size=32, validation_data=(X_test, y_test))
# 评估模型
loss, accuracy = model.evaluate(X_test, y_test)
print(f"Test Loss: {loss}")
print(f"Test Accuracy: {accuracy}")
1)输入
输入.mat 文件路径列表。
2)训练
1. 调用 load_mat_data 函数加载数据并划分训练集和测试集。
2. 确定输入形状和类别数量。
3. 调用 build_model 函数构建 CNN 模型。
4. 使用训练集数据训练模型,训练 50 个 epoch,批量大小为 32,并在验证集上验证模型。
3)评估
1. 在测试集上评估模型,输出测试损失和准确度。
2. 绘制训练过程中的损失和准确度变化图。
plt.plot(history.history['loss'], label='Training Loss')
plt.plot(history.history['val_loss'], label='Validation Loss')
plt.title('Loss during Training')
plt.xlabel('Epochs')
plt.ylabel('Loss')
plt.legend()
plt.show()
plt.plot(history.history['accuracy'], label='Training Accuracy')
plt.plot(history.history['val_accuracy'], label='Validation Accuracy')
plt.title('Accuracy during Training')
plt.xlabel('Epochs')
plt.ylabel('Accuracy')
plt.legend()
plt.show()
4)输出
输出训练和验证过程中的损失和准确度曲线,以及测试集上的性能评估结果。
train_and_evaluate(mat_file_paths) 负责调用数据加载和模型构建函数,并执行模型训练。训练过程中记录了训练和验证损失及准确率的变化,并通过 matplotlib 可视化了这些变化。
训练结束后,通过 evaluate 方法评估测试集上的表现,并打印出测试损失和准确率。
5. main函数
if __name__ == '__main__':
# 修改为你的 .mat 文件路径列表
mat_file_paths = [f'D:/Class/compete/EEG/data_preprocessed_matlab/s{str(i).zfill(2)}.mat' for i in range(1, 33)]
train_and_evaluate(mat_file_paths)