OpenBCI-脑电信号深度学习:CNN与RNN应用

OpenBCI-脑电信号深度学习:CNN与RNN应用

文章目录

关键字 : 深度学习, CNN, RNN, LSTM, EEG, 脑电信号, 脑机接口, BCI

概述

深度学习技术的兴起为脑电信号处理带来了革命性的突破。传统的机器学习方法依赖手工设计特征,而深度学习能够自动从原始信号中学习复杂特征表示。本文将深入介绍如何使用卷积神经网络(CNN)和循环神经网络(RNN)处理脑电信号。

一、深度学习在EEG处理中的优势

1.1 传统方法vs深度学习

#mermaid-svg-8xxLKSs521jf2Nsq{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-8xxLKSs521jf2Nsq .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-8xxLKSs521jf2Nsq .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-8xxLKSs521jf2Nsq .error-icon{fill:#552222;}#mermaid-svg-8xxLKSs521jf2Nsq .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-8xxLKSs521jf2Nsq .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-8xxLKSs521jf2Nsq .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-8xxLKSs521jf2Nsq .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-8xxLKSs521jf2Nsq .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-8xxLKSs521jf2Nsq .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-8xxLKSs521jf2Nsq .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-8xxLKSs521jf2Nsq .marker{fill:#333333;stroke:#333333;}#mermaid-svg-8xxLKSs521jf2Nsq .marker.cross{stroke:#333333;}#mermaid-svg-8xxLKSs521jf2Nsq svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-8xxLKSs521jf2Nsq p{margin:0;}#mermaid-svg-8xxLKSs521jf2Nsq .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-8xxLKSs521jf2Nsq .cluster-label text{fill:#333;}#mermaid-svg-8xxLKSs521jf2Nsq .cluster-label span{color:#333;}#mermaid-svg-8xxLKSs521jf2Nsq .cluster-label span p{background-color:transparent;}#mermaid-svg-8xxLKSs521jf2Nsq .label text,#mermaid-svg-8xxLKSs521jf2Nsq span{fill:#333;color:#333;}#mermaid-svg-8xxLKSs521jf2Nsq .node rect,#mermaid-svg-8xxLKSs521jf2Nsq .node circle,#mermaid-svg-8xxLKSs521jf2Nsq .node ellipse,#mermaid-svg-8xxLKSs521jf2Nsq .node polygon,#mermaid-svg-8xxLKSs521jf2Nsq .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-8xxLKSs521jf2Nsq .rough-node .label text,#mermaid-svg-8xxLKSs521jf2Nsq .node .label text,#mermaid-svg-8xxLKSs521jf2Nsq .image-shape .label,#mermaid-svg-8xxLKSs521jf2Nsq .icon-shape .label{text-anchor:middle;}#mermaid-svg-8xxLKSs521jf2Nsq .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-8xxLKSs521jf2Nsq .rough-node .label,#mermaid-svg-8xxLKSs521jf2Nsq .node .label,#mermaid-svg-8xxLKSs521jf2Nsq .image-shape .label,#mermaid-svg-8xxLKSs521jf2Nsq .icon-shape .label{text-align:center;}#mermaid-svg-8xxLKSs521jf2Nsq .node.clickable{cursor:pointer;}#mermaid-svg-8xxLKSs521jf2Nsq .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-8xxLKSs521jf2Nsq .arrowheadPath{fill:#333333;}#mermaid-svg-8xxLKSs521jf2Nsq .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-8xxLKSs521jf2Nsq .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-8xxLKSs521jf2Nsq .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-8xxLKSs521jf2Nsq .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-8xxLKSs521jf2Nsq .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-8xxLKSs521jf2Nsq .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-8xxLKSs521jf2Nsq .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-8xxLKSs521jf2Nsq .cluster text{fill:#333;}#mermaid-svg-8xxLKSs521jf2Nsq .cluster span{color:#333;}#mermaid-svg-8xxLKSs521jf2Nsq div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-8xxLKSs521jf2Nsq .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-8xxLKSs521jf2Nsq rect.text{fill:none;stroke-width:0;}#mermaid-svg-8xxLKSs521jf2Nsq .icon-shape,#mermaid-svg-8xxLKSs521jf2Nsq .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-8xxLKSs521jf2Nsq .icon-shape p,#mermaid-svg-8xxLKSs521jf2Nsq .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-8xxLKSs521jf2Nsq .icon-shape .label rect,#mermaid-svg-8xxLKSs521jf2Nsq .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-8xxLKSs521jf2Nsq .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-8xxLKSs521jf2Nsq .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-8xxLKSs521jf2Nsq :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 深度学习
端到端
原始EEG
自动特征学习
特征提取
分类
输出
传统方法
手工设计
原始EEG
手动特征提取
特征选择
分类器
输出

1.2 深度学习的优势

#mermaid-svg-fgBIVJaamqWMiL2Q{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-fgBIVJaamqWMiL2Q .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-fgBIVJaamqWMiL2Q .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-fgBIVJaamqWMiL2Q .error-icon{fill:#552222;}#mermaid-svg-fgBIVJaamqWMiL2Q .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-fgBIVJaamqWMiL2Q .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-fgBIVJaamqWMiL2Q .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-fgBIVJaamqWMiL2Q .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-fgBIVJaamqWMiL2Q .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-fgBIVJaamqWMiL2Q .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-fgBIVJaamqWMiL2Q .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-fgBIVJaamqWMiL2Q .marker{fill:#333333;stroke:#333333;}#mermaid-svg-fgBIVJaamqWMiL2Q .marker.cross{stroke:#333333;}#mermaid-svg-fgBIVJaamqWMiL2Q svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-fgBIVJaamqWMiL2Q p{margin:0;}#mermaid-svg-fgBIVJaamqWMiL2Q .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-fgBIVJaamqWMiL2Q .cluster-label text{fill:#333;}#mermaid-svg-fgBIVJaamqWMiL2Q .cluster-label span{color:#333;}#mermaid-svg-fgBIVJaamqWMiL2Q .cluster-label span p{background-color:transparent;}#mermaid-svg-fgBIVJaamqWMiL2Q .label text,#mermaid-svg-fgBIVJaamqWMiL2Q span{fill:#333;color:#333;}#mermaid-svg-fgBIVJaamqWMiL2Q .node rect,#mermaid-svg-fgBIVJaamqWMiL2Q .node circle,#mermaid-svg-fgBIVJaamqWMiL2Q .node ellipse,#mermaid-svg-fgBIVJaamqWMiL2Q .node polygon,#mermaid-svg-fgBIVJaamqWMiL2Q .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-fgBIVJaamqWMiL2Q .rough-node .label text,#mermaid-svg-fgBIVJaamqWMiL2Q .node .label text,#mermaid-svg-fgBIVJaamqWMiL2Q .image-shape .label,#mermaid-svg-fgBIVJaamqWMiL2Q .icon-shape .label{text-anchor:middle;}#mermaid-svg-fgBIVJaamqWMiL2Q .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-fgBIVJaamqWMiL2Q .rough-node .label,#mermaid-svg-fgBIVJaamqWMiL2Q .node .label,#mermaid-svg-fgBIVJaamqWMiL2Q .image-shape .label,#mermaid-svg-fgBIVJaamqWMiL2Q .icon-shape .label{text-align:center;}#mermaid-svg-fgBIVJaamqWMiL2Q .node.clickable{cursor:pointer;}#mermaid-svg-fgBIVJaamqWMiL2Q .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-fgBIVJaamqWMiL2Q .arrowheadPath{fill:#333333;}#mermaid-svg-fgBIVJaamqWMiL2Q .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-fgBIVJaamqWMiL2Q .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-fgBIVJaamqWMiL2Q .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-fgBIVJaamqWMiL2Q .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-fgBIVJaamqWMiL2Q .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-fgBIVJaamqWMiL2Q .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-fgBIVJaamqWMiL2Q .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-fgBIVJaamqWMiL2Q .cluster text{fill:#333;}#mermaid-svg-fgBIVJaamqWMiL2Q .cluster span{color:#333;}#mermaid-svg-fgBIVJaamqWMiL2Q div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-fgBIVJaamqWMiL2Q .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-fgBIVJaamqWMiL2Q rect.text{fill:none;stroke-width:0;}#mermaid-svg-fgBIVJaamqWMiL2Q .icon-shape,#mermaid-svg-fgBIVJaamqWMiL2Q .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-fgBIVJaamqWMiL2Q .icon-shape p,#mermaid-svg-fgBIVJaamqWMiL2Q .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-fgBIVJaamqWMiL2Q .icon-shape .label rect,#mermaid-svg-fgBIVJaamqWMiL2Q .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-fgBIVJaamqWMiL2Q .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-fgBIVJaamqWMiL2Q .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-fgBIVJaamqWMiL2Q :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 深度学习优势
自动特征学习
端到端训练
处理复杂模式
泛化能力强
大规模数据处理
无需领域专家
发现隐藏特征
非线性关系
时空模式

1.3 EEG深度学习挑战

挑战 描述 解决方案
数据量小 EEG数据集通常较小 数据增强、迁移学习
噪声大 信号质量受多种因素影响 预处理、正则化
个体差异 不同人EEG差异大 个性化模型、自适应
计算资源 深度学习需要GPU 轻量级模型、量化

二、CNN在EEG中的应用

2.1 CNN原理概述

#mermaid-svg-G56JD02ZzwlPiDkM{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-G56JD02ZzwlPiDkM .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-G56JD02ZzwlPiDkM .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-G56JD02ZzwlPiDkM .error-icon{fill:#552222;}#mermaid-svg-G56JD02ZzwlPiDkM .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-G56JD02ZzwlPiDkM .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-G56JD02ZzwlPiDkM .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-G56JD02ZzwlPiDkM .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-G56JD02ZzwlPiDkM .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-G56JD02ZzwlPiDkM .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-G56JD02ZzwlPiDkM .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-G56JD02ZzwlPiDkM .marker{fill:#333333;stroke:#333333;}#mermaid-svg-G56JD02ZzwlPiDkM .marker.cross{stroke:#333333;}#mermaid-svg-G56JD02ZzwlPiDkM svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-G56JD02ZzwlPiDkM p{margin:0;}#mermaid-svg-G56JD02ZzwlPiDkM .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-G56JD02ZzwlPiDkM .cluster-label text{fill:#333;}#mermaid-svg-G56JD02ZzwlPiDkM .cluster-label span{color:#333;}#mermaid-svg-G56JD02ZzwlPiDkM .cluster-label span p{background-color:transparent;}#mermaid-svg-G56JD02ZzwlPiDkM .label text,#mermaid-svg-G56JD02ZzwlPiDkM span{fill:#333;color:#333;}#mermaid-svg-G56JD02ZzwlPiDkM .node rect,#mermaid-svg-G56JD02ZzwlPiDkM .node circle,#mermaid-svg-G56JD02ZzwlPiDkM .node ellipse,#mermaid-svg-G56JD02ZzwlPiDkM .node polygon,#mermaid-svg-G56JD02ZzwlPiDkM .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-G56JD02ZzwlPiDkM .rough-node .label text,#mermaid-svg-G56JD02ZzwlPiDkM .node .label text,#mermaid-svg-G56JD02ZzwlPiDkM .image-shape .label,#mermaid-svg-G56JD02ZzwlPiDkM .icon-shape .label{text-anchor:middle;}#mermaid-svg-G56JD02ZzwlPiDkM .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-G56JD02ZzwlPiDkM .rough-node .label,#mermaid-svg-G56JD02ZzwlPiDkM .node .label,#mermaid-svg-G56JD02ZzwlPiDkM .image-shape .label,#mermaid-svg-G56JD02ZzwlPiDkM .icon-shape .label{text-align:center;}#mermaid-svg-G56JD02ZzwlPiDkM .node.clickable{cursor:pointer;}#mermaid-svg-G56JD02ZzwlPiDkM .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-G56JD02ZzwlPiDkM .arrowheadPath{fill:#333333;}#mermaid-svg-G56JD02ZzwlPiDkM .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-G56JD02ZzwlPiDkM .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-G56JD02ZzwlPiDkM .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-G56JD02ZzwlPiDkM .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-G56JD02ZzwlPiDkM .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-G56JD02ZzwlPiDkM .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-G56JD02ZzwlPiDkM .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-G56JD02ZzwlPiDkM .cluster text{fill:#333;}#mermaid-svg-G56JD02ZzwlPiDkM .cluster span{color:#333;}#mermaid-svg-G56JD02ZzwlPiDkM div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-G56JD02ZzwlPiDkM .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-G56JD02ZzwlPiDkM rect.text{fill:none;stroke-width:0;}#mermaid-svg-G56JD02ZzwlPiDkM .icon-shape,#mermaid-svg-G56JD02ZzwlPiDkM .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-G56JD02ZzwlPiDkM .icon-shape p,#mermaid-svg-G56JD02ZzwlPiDkM .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-G56JD02ZzwlPiDkM .icon-shape .label rect,#mermaid-svg-G56JD02ZzwlPiDkM .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-G56JD02ZzwlPiDkM .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-G56JD02ZzwlPiDkM .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-G56JD02ZzwlPiDkM :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 输入: EEG时间序列
卷积层1
激活函数ReLU
池化层1
卷积层2
激活函数ReLU
池化层2
全连接层
输出层

2.2 一维CNN处理EEG

python 复制代码
import tensorflow as tf
from tensorflow.keras import layers, models

class EEG_CNN_Model:
    def __init__(self, input_shape=(250, 8), num_classes=4):
        self.input_shape = input_shape
        self.num_classes = num_classes
    
    def build_model(self):
        model = models.Sequential([
            layers.Conv1D(filters=32, kernel_size=5, activation='relu', 
                         input_shape=self.input_shape),
            layers.MaxPooling1D(pool_size=2),
            layers.Conv1D(filters=64, kernel_size=5, activation='relu'),
            layers.MaxPooling1D(pool_size=2),
            layers.Conv1D(filters=128, kernel_size=5, activation='relu'),
            layers.MaxPooling1D(pool_size=2),
            layers.Flatten(),
            layers.Dense(128, activation='relu'),
            layers.Dropout(0.5),
            layers.Dense(self.num_classes, activation='softmax')
        ])
        
        model.compile(optimizer='adam',
                      loss='sparse_categorical_crossentropy',
                      metrics=['accuracy'])
        
        return model

2.3 二维CNN处理EEG

python 复制代码
class EEG_2DCNN_Model:
    def __init__(self, input_shape=(32, 32, 1), num_classes=4):
        self.input_shape = input_shape
        self.num_classes = num_classes
    
    def build_model(self):
        model = models.Sequential([
            layers.Conv2D(32, (3, 3), activation='relu', input_shape=self.input_shape),
            layers.MaxPooling2D((2, 2)),
            layers.Conv2D(64, (3, 3), activation='relu'),
            layers.MaxPooling2D((2, 2)),
            layers.Conv2D(128, (3, 3), activation='relu'),
            layers.Flatten(),
            layers.Dense(128, activation='relu'),
            layers.Dropout(0.5),
            layers.Dense(self.num_classes, activation='softmax')
        ])
        
        model.compile(optimizer='adam',
                      loss='sparse_categorical_crossentropy',
                      metrics=['accuracy'])
        
        return model

2.4 EEG到图像的转换

python 复制代码
def eeg_to_image(eeg_data, time_window=32, freq_bands=32):
    """将EEG数据转换为频谱图"""
    import numpy as np
    from scipy import signal
    
    n_channels = eeg_data.shape[1]
    images = []
    
    for i in range(n_channels):
        f, t, Sxx = signal.spectrogram(eeg_data[:, i], fs=250, 
                                      nperseg=time_window, noverlap=time_window//2)
        Sxx = Sxx[:freq_bands, :time_window]
        images.append(Sxx)
    
    return np.stack(images, axis=-1)

三、RNN在EEG中的应用

3.1 RNN原理概述

输出 RNN单元 输入序列 输出 RNN单元 输入序列 #mermaid-svg-A29QiNc2mRmC9d34{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-A29QiNc2mRmC9d34 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-A29QiNc2mRmC9d34 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-A29QiNc2mRmC9d34 .error-icon{fill:#552222;}#mermaid-svg-A29QiNc2mRmC9d34 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-A29QiNc2mRmC9d34 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-A29QiNc2mRmC9d34 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-A29QiNc2mRmC9d34 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-A29QiNc2mRmC9d34 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-A29QiNc2mRmC9d34 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-A29QiNc2mRmC9d34 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-A29QiNc2mRmC9d34 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-A29QiNc2mRmC9d34 .marker.cross{stroke:#333333;}#mermaid-svg-A29QiNc2mRmC9d34 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-A29QiNc2mRmC9d34 p{margin:0;}#mermaid-svg-A29QiNc2mRmC9d34 .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-A29QiNc2mRmC9d34 text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-A29QiNc2mRmC9d34 .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-A29QiNc2mRmC9d34 .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-A29QiNc2mRmC9d34 .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-A29QiNc2mRmC9d34 .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-A29QiNc2mRmC9d34 #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-A29QiNc2mRmC9d34 .sequenceNumber{fill:white;}#mermaid-svg-A29QiNc2mRmC9d34 #sequencenumber{fill:#333;}#mermaid-svg-A29QiNc2mRmC9d34 #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-A29QiNc2mRmC9d34 .messageText{fill:#333;stroke:none;}#mermaid-svg-A29QiNc2mRmC9d34 .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-A29QiNc2mRmC9d34 .labelText,#mermaid-svg-A29QiNc2mRmC9d34 .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-A29QiNc2mRmC9d34 .loopText,#mermaid-svg-A29QiNc2mRmC9d34 .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-A29QiNc2mRmC9d34 .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-A29QiNc2mRmC9d34 .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-A29QiNc2mRmC9d34 .noteText,#mermaid-svg-A29QiNc2mRmC9d34 .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-A29QiNc2mRmC9d34 .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-A29QiNc2mRmC9d34 .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-A29QiNc2mRmC9d34 .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-A29QiNc2mRmC9d34 .actorPopupMenu{position:absolute;}#mermaid-svg-A29QiNc2mRmC9d34 .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-A29QiNc2mRmC9d34 .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-A29QiNc2mRmC9d34 .actor-man circle,#mermaid-svg-A29QiNc2mRmC9d34 line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-A29QiNc2mRmC9d34 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 记忆机制 x_t h_t = f(W*h_{t-1} + U*x_t) y_t

3.2 LSTM处理EEG

python 复制代码
class EEG_LSTM_Model:
    def __init__(self, input_shape=(250, 8), num_classes=4):
        self.input_shape = input_shape
        self.num_classes = num_classes
    
    def build_model(self):
        model = models.Sequential([
            layers.LSTM(64, return_sequences=True, input_shape=self.input_shape),
            layers.LSTM(128, return_sequences=True),
            layers.LSTM(64),
            layers.Dense(128, activation='relu'),
            layers.Dropout(0.5),
            layers.Dense(self.num_classes, activation='softmax')
        ])
        
        model.compile(optimizer='adam',
                      loss='sparse_categorical_crossentropy',
                      metrics=['accuracy'])
        
        return model

3.3 GRU处理EEG

python 复制代码
class EEG_GRU_Model:
    def __init__(self, input_shape=(250, 8), num_classes=4):
        self.input_shape = input_shape
        self.num_classes = num_classes
    
    def build_model(self):
        model = models.Sequential([
            layers.GRU(64, return_sequences=True, input_shape=self.input_shape),
            layers.GRU(128, return_sequences=True),
            layers.GRU(64),
            layers.Dense(128, activation='relu'),
            layers.Dropout(0.5),
            layers.Dense(self.num_classes, activation='softmax')
        ])
        
        model.compile(optimizer='adam',
                      loss='sparse_categorical_crossentropy',
                      metrics=['accuracy'])
        
        return model

四、混合模型架构

4.1 CNN+LSTM混合模型

#mermaid-svg-shUf7LUpPKewWeJK{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-shUf7LUpPKewWeJK .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-shUf7LUpPKewWeJK .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-shUf7LUpPKewWeJK .error-icon{fill:#552222;}#mermaid-svg-shUf7LUpPKewWeJK .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-shUf7LUpPKewWeJK .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-shUf7LUpPKewWeJK .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-shUf7LUpPKewWeJK .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-shUf7LUpPKewWeJK .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-shUf7LUpPKewWeJK .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-shUf7LUpPKewWeJK .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-shUf7LUpPKewWeJK .marker{fill:#333333;stroke:#333333;}#mermaid-svg-shUf7LUpPKewWeJK .marker.cross{stroke:#333333;}#mermaid-svg-shUf7LUpPKewWeJK svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-shUf7LUpPKewWeJK p{margin:0;}#mermaid-svg-shUf7LUpPKewWeJK .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-shUf7LUpPKewWeJK .cluster-label text{fill:#333;}#mermaid-svg-shUf7LUpPKewWeJK .cluster-label span{color:#333;}#mermaid-svg-shUf7LUpPKewWeJK .cluster-label span p{background-color:transparent;}#mermaid-svg-shUf7LUpPKewWeJK .label text,#mermaid-svg-shUf7LUpPKewWeJK span{fill:#333;color:#333;}#mermaid-svg-shUf7LUpPKewWeJK .node rect,#mermaid-svg-shUf7LUpPKewWeJK .node circle,#mermaid-svg-shUf7LUpPKewWeJK .node ellipse,#mermaid-svg-shUf7LUpPKewWeJK .node polygon,#mermaid-svg-shUf7LUpPKewWeJK .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-shUf7LUpPKewWeJK .rough-node .label text,#mermaid-svg-shUf7LUpPKewWeJK .node .label text,#mermaid-svg-shUf7LUpPKewWeJK .image-shape .label,#mermaid-svg-shUf7LUpPKewWeJK .icon-shape .label{text-anchor:middle;}#mermaid-svg-shUf7LUpPKewWeJK .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-shUf7LUpPKewWeJK .rough-node .label,#mermaid-svg-shUf7LUpPKewWeJK .node .label,#mermaid-svg-shUf7LUpPKewWeJK .image-shape .label,#mermaid-svg-shUf7LUpPKewWeJK .icon-shape .label{text-align:center;}#mermaid-svg-shUf7LUpPKewWeJK .node.clickable{cursor:pointer;}#mermaid-svg-shUf7LUpPKewWeJK .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-shUf7LUpPKewWeJK .arrowheadPath{fill:#333333;}#mermaid-svg-shUf7LUpPKewWeJK .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-shUf7LUpPKewWeJK .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-shUf7LUpPKewWeJK .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-shUf7LUpPKewWeJK .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-shUf7LUpPKewWeJK .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-shUf7LUpPKewWeJK .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-shUf7LUpPKewWeJK .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-shUf7LUpPKewWeJK .cluster text{fill:#333;}#mermaid-svg-shUf7LUpPKewWeJK .cluster span{color:#333;}#mermaid-svg-shUf7LUpPKewWeJK div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-shUf7LUpPKewWeJK .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-shUf7LUpPKewWeJK rect.text{fill:none;stroke-width:0;}#mermaid-svg-shUf7LUpPKewWeJK .icon-shape,#mermaid-svg-shUf7LUpPKewWeJK .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-shUf7LUpPKewWeJK .icon-shape p,#mermaid-svg-shUf7LUpPKewWeJK .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-shUf7LUpPKewWeJK .icon-shape .label rect,#mermaid-svg-shUf7LUpPKewWeJK .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-shUf7LUpPKewWeJK .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-shUf7LUpPKewWeJK .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-shUf7LUpPKewWeJK :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} EEG输入
CNN层
特征图
LSTM层
时序特征
全连接层
输出

python 复制代码
class EEG_CNN_LSTM_Model:
    def __init__(self, input_shape=(250, 8), num_classes=4):
        self.input_shape = input_shape
        self.num_classes = num_classes
    
    def build_model(self):
        inputs = layers.Input(shape=self.input_shape)
        
        x = layers.Conv1D(32, 5, activation='relu')(inputs)
        x = layers.MaxPooling1D(2)(x)
        x = layers.Conv1D(64, 5, activation='relu')(x)
        x = layers.MaxPooling1D(2)(x)
        
        x = layers.LSTM(128, return_sequences=True)(x)
        x = layers.LSTM(64)(x)
        
        x = layers.Dense(128, activation='relu')(x)
        x = layers.Dropout(0.5)(x)
        outputs = layers.Dense(self.num_classes, activation='softmax')(x)
        
        model = models.Model(inputs, outputs)
        model.compile(optimizer='adam',
                      loss='sparse_categorical_crossentropy',
                      metrics=['accuracy'])
        
        return model

4.2 Transformer模型

python 复制代码
class EEG_Transformer_Model:
    def __init__(self, input_shape=(250, 8), num_classes=4, num_heads=4, d_model=64):
        self.input_shape = input_shape
        self.num_classes = num_classes
        self.num_heads = num_heads
        self.d_model = d_model
    
    def build_model(self):
        inputs = layers.Input(shape=self.input_shape)
        
        x = layers.Dense(self.d_model, activation='relu')(inputs)
        
        transformer_block = layers.MultiHeadAttention(
            num_heads=self.num_heads, key_dim=self.d_model
        )
        x = transformer_block(x, x)
        x = layers.LayerNormalization(epsilon=1e-6)(x)
        
        x = layers.GlobalAveragePooling1D()(x)
        x = layers.Dense(128, activation='relu')(x)
        x = layers.Dropout(0.5)(x)
        outputs = layers.Dense(self.num_classes, activation='softmax')(x)
        
        model = models.Model(inputs, outputs)
        model.compile(optimizer='adam',
                      loss='sparse_categorical_crossentropy',
                      metrics=['accuracy'])
        
        return model

五、数据预处理与增强

5.1 预处理流程

#mermaid-svg-dwx3B2AmS5rAVCBi{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-dwx3B2AmS5rAVCBi .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-dwx3B2AmS5rAVCBi .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-dwx3B2AmS5rAVCBi .error-icon{fill:#552222;}#mermaid-svg-dwx3B2AmS5rAVCBi .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-dwx3B2AmS5rAVCBi .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-dwx3B2AmS5rAVCBi .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-dwx3B2AmS5rAVCBi .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-dwx3B2AmS5rAVCBi .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-dwx3B2AmS5rAVCBi .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-dwx3B2AmS5rAVCBi .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-dwx3B2AmS5rAVCBi .marker{fill:#333333;stroke:#333333;}#mermaid-svg-dwx3B2AmS5rAVCBi .marker.cross{stroke:#333333;}#mermaid-svg-dwx3B2AmS5rAVCBi svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-dwx3B2AmS5rAVCBi p{margin:0;}#mermaid-svg-dwx3B2AmS5rAVCBi .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-dwx3B2AmS5rAVCBi .cluster-label text{fill:#333;}#mermaid-svg-dwx3B2AmS5rAVCBi .cluster-label span{color:#333;}#mermaid-svg-dwx3B2AmS5rAVCBi .cluster-label span p{background-color:transparent;}#mermaid-svg-dwx3B2AmS5rAVCBi .label text,#mermaid-svg-dwx3B2AmS5rAVCBi span{fill:#333;color:#333;}#mermaid-svg-dwx3B2AmS5rAVCBi .node rect,#mermaid-svg-dwx3B2AmS5rAVCBi .node circle,#mermaid-svg-dwx3B2AmS5rAVCBi .node ellipse,#mermaid-svg-dwx3B2AmS5rAVCBi .node polygon,#mermaid-svg-dwx3B2AmS5rAVCBi .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-dwx3B2AmS5rAVCBi .rough-node .label text,#mermaid-svg-dwx3B2AmS5rAVCBi .node .label text,#mermaid-svg-dwx3B2AmS5rAVCBi .image-shape .label,#mermaid-svg-dwx3B2AmS5rAVCBi .icon-shape .label{text-anchor:middle;}#mermaid-svg-dwx3B2AmS5rAVCBi .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-dwx3B2AmS5rAVCBi .rough-node .label,#mermaid-svg-dwx3B2AmS5rAVCBi .node .label,#mermaid-svg-dwx3B2AmS5rAVCBi .image-shape .label,#mermaid-svg-dwx3B2AmS5rAVCBi .icon-shape .label{text-align:center;}#mermaid-svg-dwx3B2AmS5rAVCBi .node.clickable{cursor:pointer;}#mermaid-svg-dwx3B2AmS5rAVCBi .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-dwx3B2AmS5rAVCBi .arrowheadPath{fill:#333333;}#mermaid-svg-dwx3B2AmS5rAVCBi .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-dwx3B2AmS5rAVCBi .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-dwx3B2AmS5rAVCBi .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-dwx3B2AmS5rAVCBi .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-dwx3B2AmS5rAVCBi .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-dwx3B2AmS5rAVCBi .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-dwx3B2AmS5rAVCBi .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-dwx3B2AmS5rAVCBi .cluster text{fill:#333;}#mermaid-svg-dwx3B2AmS5rAVCBi .cluster span{color:#333;}#mermaid-svg-dwx3B2AmS5rAVCBi div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-dwx3B2AmS5rAVCBi .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-dwx3B2AmS5rAVCBi rect.text{fill:none;stroke-width:0;}#mermaid-svg-dwx3B2AmS5rAVCBi .icon-shape,#mermaid-svg-dwx3B2AmS5rAVCBi .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-dwx3B2AmS5rAVCBi .icon-shape p,#mermaid-svg-dwx3B2AmS5rAVCBi .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-dwx3B2AmS5rAVCBi .icon-shape .label rect,#mermaid-svg-dwx3B2AmS5rAVCBi .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-dwx3B2AmS5rAVCBi .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-dwx3B2AmS5rAVCBi .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-dwx3B2AmS5rAVCBi :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 原始EEG数据
滤波
去伪迹
分段
标准化
数据增强
模型输入

5.2 数据增强技术

python 复制代码
class EEGDataAugmenter:
    def __init__(self):
        pass
    
    def add_gaussian_noise(self, data, std=0.01):
        noise = np.random.normal(0, std, data.shape)
        return data + noise
    
    def time_shift(self, data, shift_range=50):
        shift = np.random.randint(-shift_range, shift_range)
        return np.roll(data, shift, axis=0)
    
    def amplitude_scale(self, data, scale_range=(0.9, 1.1)):
        scale = np.random.uniform(*scale_range)
        return data * scale
    
    def time_warp(self, data, warp_factor=0.1):
        from scipy.interpolate import interp1d
        
        t = np.arange(len(data))
        warped_t = t + np.random.normal(0, warp_factor, len(t))
        warped_t = np.clip(warped_t, 0, len(data)-1)
        
        interpolated = []
        for i in range(data.shape[1]):
            f = interp1d(t, data[:, i], kind='linear')
            interpolated.append(f(warped_t))
        
        return np.array(interpolated).T
    
    def augment(self, data, augment_prob=0.5):
        if np.random.random() < augment_prob:
            data = self.add_gaussian_noise(data)
        if np.random.random() < augment_prob:
            data = self.time_shift(data)
        if np.random.random() < augment_prob:
            data = self.amplitude_scale(data)
        if np.random.random() < augment_prob:
            data = self.time_warp(data)
        
        return data

5.3 数据集准备

python 复制代码
def prepare_dataset(file_paths, labels, window_size=250, step_size=125):
    import numpy as np
    
    X = []
    y = []
    
    for file_path, label in zip(file_paths, labels):
        data = np.load(file_path)
        
        for i in range(0, len(data) - window_size, step_size):
            window = data[i:i+window_size]
            X.append(window)
            y.append(label)
    
    return np.array(X), np.array(y)

六、模型训练与评估

6.1 训练流程

#mermaid-svg-mklzIszzhigOkFz6{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-mklzIszzhigOkFz6 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-mklzIszzhigOkFz6 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-mklzIszzhigOkFz6 .error-icon{fill:#552222;}#mermaid-svg-mklzIszzhigOkFz6 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-mklzIszzhigOkFz6 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-mklzIszzhigOkFz6 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-mklzIszzhigOkFz6 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-mklzIszzhigOkFz6 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-mklzIszzhigOkFz6 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-mklzIszzhigOkFz6 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-mklzIszzhigOkFz6 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-mklzIszzhigOkFz6 .marker.cross{stroke:#333333;}#mermaid-svg-mklzIszzhigOkFz6 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-mklzIszzhigOkFz6 p{margin:0;}#mermaid-svg-mklzIszzhigOkFz6 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-mklzIszzhigOkFz6 .cluster-label text{fill:#333;}#mermaid-svg-mklzIszzhigOkFz6 .cluster-label span{color:#333;}#mermaid-svg-mklzIszzhigOkFz6 .cluster-label span p{background-color:transparent;}#mermaid-svg-mklzIszzhigOkFz6 .label text,#mermaid-svg-mklzIszzhigOkFz6 span{fill:#333;color:#333;}#mermaid-svg-mklzIszzhigOkFz6 .node rect,#mermaid-svg-mklzIszzhigOkFz6 .node circle,#mermaid-svg-mklzIszzhigOkFz6 .node ellipse,#mermaid-svg-mklzIszzhigOkFz6 .node polygon,#mermaid-svg-mklzIszzhigOkFz6 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-mklzIszzhigOkFz6 .rough-node .label text,#mermaid-svg-mklzIszzhigOkFz6 .node .label text,#mermaid-svg-mklzIszzhigOkFz6 .image-shape .label,#mermaid-svg-mklzIszzhigOkFz6 .icon-shape .label{text-anchor:middle;}#mermaid-svg-mklzIszzhigOkFz6 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-mklzIszzhigOkFz6 .rough-node .label,#mermaid-svg-mklzIszzhigOkFz6 .node .label,#mermaid-svg-mklzIszzhigOkFz6 .image-shape .label,#mermaid-svg-mklzIszzhigOkFz6 .icon-shape .label{text-align:center;}#mermaid-svg-mklzIszzhigOkFz6 .node.clickable{cursor:pointer;}#mermaid-svg-mklzIszzhigOkFz6 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-mklzIszzhigOkFz6 .arrowheadPath{fill:#333333;}#mermaid-svg-mklzIszzhigOkFz6 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-mklzIszzhigOkFz6 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-mklzIszzhigOkFz6 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-mklzIszzhigOkFz6 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-mklzIszzhigOkFz6 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-mklzIszzhigOkFz6 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-mklzIszzhigOkFz6 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-mklzIszzhigOkFz6 .cluster text{fill:#333;}#mermaid-svg-mklzIszzhigOkFz6 .cluster span{color:#333;}#mermaid-svg-mklzIszzhigOkFz6 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-mklzIszzhigOkFz6 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-mklzIszzhigOkFz6 rect.text{fill:none;stroke-width:0;}#mermaid-svg-mklzIszzhigOkFz6 .icon-shape,#mermaid-svg-mklzIszzhigOkFz6 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-mklzIszzhigOkFz6 .icon-shape p,#mermaid-svg-mklzIszzhigOkFz6 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-mklzIszzhigOkFz6 .icon-shape .label rect,#mermaid-svg-mklzIszzhigOkFz6 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-mklzIszzhigOkFz6 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-mklzIszzhigOkFz6 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-mklzIszzhigOkFz6 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 过拟合
良好
加载数据
数据划分
构建模型
训练
验证
调整参数
测试
保存模型

6.2 训练代码

python 复制代码
def train_model(model, X_train, y_train, X_val, y_val, epochs=50, batch_size=32):
    early_stopping = tf.keras.callbacks.EarlyStopping(
        monitor='val_loss', patience=10, restore_best_weights=True
    )
    
    history = model.fit(
        X_train, y_train,
        epochs=epochs,
        batch_size=batch_size,
        validation_data=(X_val, y_val),
        callbacks=[early_stopping]
    )
    
    return history

6.3 评估指标

python 复制代码
def evaluate_model(model, X_test, y_test):
    loss, accuracy = model.evaluate(X_test, y_test)
    
    y_pred = model.predict(X_test)
    y_pred_classes = np.argmax(y_pred, axis=1)
    
    from sklearn.metrics import classification_report
    report = classification_report(y_test, y_pred_classes)
    
    return loss, accuracy, report

七、迁移学习

7.1 迁移学习原理

#mermaid-svg-YOwEmB5B8aI0MWIs{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-YOwEmB5B8aI0MWIs .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-YOwEmB5B8aI0MWIs .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-YOwEmB5B8aI0MWIs .error-icon{fill:#552222;}#mermaid-svg-YOwEmB5B8aI0MWIs .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-YOwEmB5B8aI0MWIs .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-YOwEmB5B8aI0MWIs .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-YOwEmB5B8aI0MWIs .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-YOwEmB5B8aI0MWIs .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-YOwEmB5B8aI0MWIs .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-YOwEmB5B8aI0MWIs .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-YOwEmB5B8aI0MWIs .marker{fill:#333333;stroke:#333333;}#mermaid-svg-YOwEmB5B8aI0MWIs .marker.cross{stroke:#333333;}#mermaid-svg-YOwEmB5B8aI0MWIs svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-YOwEmB5B8aI0MWIs p{margin:0;}#mermaid-svg-YOwEmB5B8aI0MWIs .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-YOwEmB5B8aI0MWIs .cluster-label text{fill:#333;}#mermaid-svg-YOwEmB5B8aI0MWIs .cluster-label span{color:#333;}#mermaid-svg-YOwEmB5B8aI0MWIs .cluster-label span p{background-color:transparent;}#mermaid-svg-YOwEmB5B8aI0MWIs .label text,#mermaid-svg-YOwEmB5B8aI0MWIs span{fill:#333;color:#333;}#mermaid-svg-YOwEmB5B8aI0MWIs .node rect,#mermaid-svg-YOwEmB5B8aI0MWIs .node circle,#mermaid-svg-YOwEmB5B8aI0MWIs .node ellipse,#mermaid-svg-YOwEmB5B8aI0MWIs .node polygon,#mermaid-svg-YOwEmB5B8aI0MWIs .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-YOwEmB5B8aI0MWIs .rough-node .label text,#mermaid-svg-YOwEmB5B8aI0MWIs .node .label text,#mermaid-svg-YOwEmB5B8aI0MWIs .image-shape .label,#mermaid-svg-YOwEmB5B8aI0MWIs .icon-shape .label{text-anchor:middle;}#mermaid-svg-YOwEmB5B8aI0MWIs .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-YOwEmB5B8aI0MWIs .rough-node .label,#mermaid-svg-YOwEmB5B8aI0MWIs .node .label,#mermaid-svg-YOwEmB5B8aI0MWIs .image-shape .label,#mermaid-svg-YOwEmB5B8aI0MWIs .icon-shape .label{text-align:center;}#mermaid-svg-YOwEmB5B8aI0MWIs .node.clickable{cursor:pointer;}#mermaid-svg-YOwEmB5B8aI0MWIs .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-YOwEmB5B8aI0MWIs .arrowheadPath{fill:#333333;}#mermaid-svg-YOwEmB5B8aI0MWIs .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-YOwEmB5B8aI0MWIs .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-YOwEmB5B8aI0MWIs .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-YOwEmB5B8aI0MWIs .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-YOwEmB5B8aI0MWIs .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-YOwEmB5B8aI0MWIs .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-YOwEmB5B8aI0MWIs .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-YOwEmB5B8aI0MWIs .cluster text{fill:#333;}#mermaid-svg-YOwEmB5B8aI0MWIs .cluster span{color:#333;}#mermaid-svg-YOwEmB5B8aI0MWIs div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-YOwEmB5B8aI0MWIs .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-YOwEmB5B8aI0MWIs rect.text{fill:none;stroke-width:0;}#mermaid-svg-YOwEmB5B8aI0MWIs .icon-shape,#mermaid-svg-YOwEmB5B8aI0MWIs .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-YOwEmB5B8aI0MWIs .icon-shape p,#mermaid-svg-YOwEmB5B8aI0MWIs .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-YOwEmB5B8aI0MWIs .icon-shape .label rect,#mermaid-svg-YOwEmB5B8aI0MWIs .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-YOwEmB5B8aI0MWIs .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-YOwEmB5B8aI0MWIs .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-YOwEmB5B8aI0MWIs :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 源数据集
预训练模型
冻结特征提取层
目标数据集
微调分类层
适应新任务

7.2 迁移学习实现

python 复制代码
def transfer_learning(base_model, X_train, y_train, num_classes=4):
    base_model.trainable = False
    
    inputs = layers.Input(shape=X_train.shape[1:])
    x = base_model(inputs, training=False)
    x = layers.Flatten()(x)
    x = layers.Dense(128, activation='relu')(x)
    outputs = layers.Dense(num_classes, activation='softmax')(x)
    
    model = models.Model(inputs, outputs)
    model.compile(optimizer='adam',
                  loss='sparse_categorical_crossentropy',
                  metrics=['accuracy'])
    
    return model

八、实战案例:运动想象分类

8.1 数据集描述

#mermaid-svg-0BcR2JIcKqDM3sLi{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-0BcR2JIcKqDM3sLi .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-0BcR2JIcKqDM3sLi .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-0BcR2JIcKqDM3sLi .error-icon{fill:#552222;}#mermaid-svg-0BcR2JIcKqDM3sLi .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-0BcR2JIcKqDM3sLi .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-0BcR2JIcKqDM3sLi .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-0BcR2JIcKqDM3sLi .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-0BcR2JIcKqDM3sLi .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-0BcR2JIcKqDM3sLi .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-0BcR2JIcKqDM3sLi .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-0BcR2JIcKqDM3sLi .marker{fill:#333333;stroke:#333333;}#mermaid-svg-0BcR2JIcKqDM3sLi .marker.cross{stroke:#333333;}#mermaid-svg-0BcR2JIcKqDM3sLi svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-0BcR2JIcKqDM3sLi p{margin:0;}#mermaid-svg-0BcR2JIcKqDM3sLi .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-0BcR2JIcKqDM3sLi .cluster-label text{fill:#333;}#mermaid-svg-0BcR2JIcKqDM3sLi .cluster-label span{color:#333;}#mermaid-svg-0BcR2JIcKqDM3sLi .cluster-label span p{background-color:transparent;}#mermaid-svg-0BcR2JIcKqDM3sLi .label text,#mermaid-svg-0BcR2JIcKqDM3sLi span{fill:#333;color:#333;}#mermaid-svg-0BcR2JIcKqDM3sLi .node rect,#mermaid-svg-0BcR2JIcKqDM3sLi .node circle,#mermaid-svg-0BcR2JIcKqDM3sLi .node ellipse,#mermaid-svg-0BcR2JIcKqDM3sLi .node polygon,#mermaid-svg-0BcR2JIcKqDM3sLi .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-0BcR2JIcKqDM3sLi .rough-node .label text,#mermaid-svg-0BcR2JIcKqDM3sLi .node .label text,#mermaid-svg-0BcR2JIcKqDM3sLi .image-shape .label,#mermaid-svg-0BcR2JIcKqDM3sLi .icon-shape .label{text-anchor:middle;}#mermaid-svg-0BcR2JIcKqDM3sLi .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-0BcR2JIcKqDM3sLi .rough-node .label,#mermaid-svg-0BcR2JIcKqDM3sLi .node .label,#mermaid-svg-0BcR2JIcKqDM3sLi .image-shape .label,#mermaid-svg-0BcR2JIcKqDM3sLi .icon-shape .label{text-align:center;}#mermaid-svg-0BcR2JIcKqDM3sLi .node.clickable{cursor:pointer;}#mermaid-svg-0BcR2JIcKqDM3sLi .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-0BcR2JIcKqDM3sLi .arrowheadPath{fill:#333333;}#mermaid-svg-0BcR2JIcKqDM3sLi .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-0BcR2JIcKqDM3sLi .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-0BcR2JIcKqDM3sLi .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-0BcR2JIcKqDM3sLi .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-0BcR2JIcKqDM3sLi .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-0BcR2JIcKqDM3sLi .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-0BcR2JIcKqDM3sLi .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-0BcR2JIcKqDM3sLi .cluster text{fill:#333;}#mermaid-svg-0BcR2JIcKqDM3sLi .cluster span{color:#333;}#mermaid-svg-0BcR2JIcKqDM3sLi div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-0BcR2JIcKqDM3sLi .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-0BcR2JIcKqDM3sLi rect.text{fill:none;stroke-width:0;}#mermaid-svg-0BcR2JIcKqDM3sLi .icon-shape,#mermaid-svg-0BcR2JIcKqDM3sLi .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-0BcR2JIcKqDM3sLi .icon-shape p,#mermaid-svg-0BcR2JIcKqDM3sLi .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-0BcR2JIcKqDM3sLi .icon-shape .label rect,#mermaid-svg-0BcR2JIcKqDM3sLi .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-0BcR2JIcKqDM3sLi .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-0BcR2JIcKqDM3sLi .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-0BcR2JIcKqDM3sLi :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} BCI Competition IV Dataset 2a
9个受试者
4类运动想象
250Hz采样率
左手想象
右手想象
脚想象
舌头想象

8.2 完整实现

python 复制代码
import numpy as np
import tensorflow as tf
from sklearn.model_selection import train_test_split

class MI_Classifier:
    def __init__(self):
        self.model = None
        self.augmenter = EEGDataAugmenter()
    
    def load_data(self, path):
        data = np.load(path)
        X = data['X']
        y = data['y']
        return X, y
    
    def preprocess(self, X):
        X = (X - np.mean(X, axis=0)) / np.std(X, axis=0)
        return X
    
    def train(self, X, y):
        X = self.preprocess(X)
        X_train, X_val, y_train, y_val = train_test_split(X, y, test_size=0.2)
        
        self.model = EEG_CNN_LSTM_Model(input_shape=X_train.shape[1:], num_classes=4).build_model()
        
        history = self.model.fit(
            X_train, y_train,
            epochs=50,
            batch_size=32,
            validation_data=(X_val, y_val),
            callbacks=[tf.keras.callbacks.EarlyStopping(patience=10)]
        )
        
        return history
    
    def predict(self, X):
        X = self.preprocess(X)
        return self.model.predict(X)

if __name__ == '__main__':
    classifier = MI_Classifier()
    X, y = classifier.load_data('mi_dataset.npz')
    classifier.train(X, y)

九、模型部署与优化

9.1 模型压缩

python 复制代码
def compress_model(model, save_path='compressed_model.h5'):
    converter = tf.lite.TFLiteConverter.from_keras_model(model)
    converter.optimizations = [tf.lite.Optimize.DEFAULT]
    tflite_model = converter.convert()
    
    with open(save_path, 'wb') as f:
        f.write(tflite_model)
    
    return tflite_model

9.2 实时推理

python 复制代码
class RealTimeEEGClassifier:
    def __init__(self, model_path, window_size=250):
        self.interpreter = tf.lite.Interpreter(model_path=model_path)
        self.interpreter.allocate_tensors()
        self.window_size = window_size
        self.data_buffer = []
        
        self.input_details = self.interpreter.get_input_details()
        self.output_details = self.interpreter.get_output_details()
    
    def add_data(self, sample):
        self.data_buffer.append(sample)
        if len(self.data_buffer) > self.window_size:
            self.data_buffer = self.data_buffer[-self.window_size:]
    
    def predict(self):
        if len(self.data_buffer) < self.window_size:
            return None
        
        input_data = np.array([self.data_buffer], dtype=np.float32)
        self.interpreter.set_tensor(self.input_details[0]['index'], input_data)
        self.interpreter.invoke()
        
        output_data = self.interpreter.get_tensor(self.output_details[0]['index'])
        return np.argmax(output_data)

十、总结

深度学习为脑电信号处理带来了前所未有的机遇:

  1. CNN擅长提取空间特征,适合处理电极间的空间模式
  2. RNN/LSTM擅长捕捉时间序列依赖,适合处理EEG的动态变化
  3. 混合模型结合了两者的优势,在复杂任务上表现出色
  4. 迁移学习解决了数据量不足的问题

未来研究方向:

  • 自监督学习在EEG中的应用
  • 小样本学习方法
  • 可解释性深度学习
  • 边缘计算部署

参考资料:

  • Schirrmeister, R. T., et al. (2017). Deep learning with convolutional neural networks for EEG decoding and visualization.
  • Wang, F., et al. (2020). EEG-based emotion recognition using deep learning: A review.

相关推荐
KIO no way1 小时前
AI最佳发布时间怎么找_CSDN_AI数字营销的数据功能实测
人工智能
花月C1 小时前
AI驱动的竞品分析多Agent协作系统设计理论
人工智能·python·ai·agent·ai编程
风华圆舞1 小时前
鸿蒙 + Flutter 下如何让 HarmonyOS 能力真正服务于 AI 体验
人工智能·flutter·harmonyos
老马啸西风2 小时前
monolith 打造属于你的知识花园
人工智能
YHHLAI2 小时前
前端工程化调用 AI 多模态生图模型:Qwen Image Demo 实战
前端·人工智能
searchforAI2 小时前
B站视频怎么转文字稿?AI自动总结要点+生成思维导图教程
人工智能·笔记·学习·ai·语音识别·知识管理·视频总结
“码”力全开2 小时前
【架构深探】基于Docker与GB28181/RTSP的边缘计算AI视频管理平台:异构算力调度与源码交付实践
人工智能·docker·架构
伶俜662 小时前
鸿蒙实战(二) ArkUI AI 相机:从零实现实时滤镜与人脸贴纸
人工智能·数码相机
老徐聊GEO2 小时前
AI搜索获客:亲测有效的实践案例分享
大数据·人工智能·python