OpenBCI-机器学习入门:从脑电信号到模式识别

OpenBCI-机器学习入门:从脑电信号到模式识别

文章目录

引言

在前几篇文章中,我们已经学习了脑电信号的采集、预处理和特征提取技术。现在,我们进入BCI系统最核心的环节------机器学习与模式识别。通过机器学习算法,我们可以让计算机"理解"大脑发出的信号,实现意念控制等神奇功能。

本文将从零开始介绍机器学习在脑电信号处理中的应用,包括常用算法、完整的工作流程和实战代码。


机器学习在BCI中的应用概述

什么是机器学习?

机器学习是人工智能的一个分支,它使计算机能够从数据中学习并做出预测,而无需显式编程。在BCI领域,机器学习的目标是:

  1. 模式识别:从脑电信号中识别出特定的思维模式
  2. 分类决策:将脑电信号分类到不同的意图类别
  3. 预测控制:根据识别结果控制外部设备

BCI中的机器学习流程

#mermaid-svg-Hrf6zGabIPutrcnD{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-Hrf6zGabIPutrcnD .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-Hrf6zGabIPutrcnD .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-Hrf6zGabIPutrcnD .error-icon{fill:#552222;}#mermaid-svg-Hrf6zGabIPutrcnD .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Hrf6zGabIPutrcnD .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-Hrf6zGabIPutrcnD .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Hrf6zGabIPutrcnD .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Hrf6zGabIPutrcnD .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-Hrf6zGabIPutrcnD .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Hrf6zGabIPutrcnD .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Hrf6zGabIPutrcnD .marker{fill:#333333;stroke:#333333;}#mermaid-svg-Hrf6zGabIPutrcnD .marker.cross{stroke:#333333;}#mermaid-svg-Hrf6zGabIPutrcnD svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Hrf6zGabIPutrcnD p{margin:0;}#mermaid-svg-Hrf6zGabIPutrcnD .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-Hrf6zGabIPutrcnD .cluster-label text{fill:#333;}#mermaid-svg-Hrf6zGabIPutrcnD .cluster-label span{color:#333;}#mermaid-svg-Hrf6zGabIPutrcnD .cluster-label span p{background-color:transparent;}#mermaid-svg-Hrf6zGabIPutrcnD .label text,#mermaid-svg-Hrf6zGabIPutrcnD span{fill:#333;color:#333;}#mermaid-svg-Hrf6zGabIPutrcnD .node rect,#mermaid-svg-Hrf6zGabIPutrcnD .node circle,#mermaid-svg-Hrf6zGabIPutrcnD .node ellipse,#mermaid-svg-Hrf6zGabIPutrcnD .node polygon,#mermaid-svg-Hrf6zGabIPutrcnD .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-Hrf6zGabIPutrcnD .rough-node .label text,#mermaid-svg-Hrf6zGabIPutrcnD .node .label text,#mermaid-svg-Hrf6zGabIPutrcnD .image-shape .label,#mermaid-svg-Hrf6zGabIPutrcnD .icon-shape .label{text-anchor:middle;}#mermaid-svg-Hrf6zGabIPutrcnD .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-Hrf6zGabIPutrcnD .rough-node .label,#mermaid-svg-Hrf6zGabIPutrcnD .node .label,#mermaid-svg-Hrf6zGabIPutrcnD .image-shape .label,#mermaid-svg-Hrf6zGabIPutrcnD .icon-shape .label{text-align:center;}#mermaid-svg-Hrf6zGabIPutrcnD .node.clickable{cursor:pointer;}#mermaid-svg-Hrf6zGabIPutrcnD .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-Hrf6zGabIPutrcnD .arrowheadPath{fill:#333333;}#mermaid-svg-Hrf6zGabIPutrcnD .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-Hrf6zGabIPutrcnD .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-Hrf6zGabIPutrcnD .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Hrf6zGabIPutrcnD .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-Hrf6zGabIPutrcnD .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Hrf6zGabIPutrcnD .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-Hrf6zGabIPutrcnD .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-Hrf6zGabIPutrcnD .cluster text{fill:#333;}#mermaid-svg-Hrf6zGabIPutrcnD .cluster span{color:#333;}#mermaid-svg-Hrf6zGabIPutrcnD 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-Hrf6zGabIPutrcnD .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-Hrf6zGabIPutrcnD rect.text{fill:none;stroke-width:0;}#mermaid-svg-Hrf6zGabIPutrcnD .icon-shape,#mermaid-svg-Hrf6zGabIPutrcnD .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Hrf6zGabIPutrcnD .icon-shape p,#mermaid-svg-Hrf6zGabIPutrcnD .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-Hrf6zGabIPutrcnD .icon-shape .label rect,#mermaid-svg-Hrf6zGabIPutrcnD .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Hrf6zGabIPutrcnD .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-Hrf6zGabIPutrcnD .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-Hrf6zGabIPutrcnD :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 是

脑电数据采集
数据预处理
特征提取
特征选择
数据集划分
模型训练
模型评估
评估结果满意?
模型部署
调整参数/更换算法

典型BCI机器学习应用场景

应用场景 输入信号 输出目标 典型算法
运动想象 EEG信号 左/右手运动意图 SVM、LDA、CNN
情绪识别 EEG信号 喜/怒/哀/乐 RF、MLP、Transformer
注意力监测 EEG信号 高/低注意力 SVM、随机森林
P300拼写器 EEG信号 字符选择 LDA、SVM
SSVEP识别 EEG信号 频率识别 CCA、LDA

机器学习基础概念

监督学习与无监督学习

在BCI中,我们主要使用监督学习
#mermaid-svg-7I5PxmDP6kFap6p5{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-7I5PxmDP6kFap6p5 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-7I5PxmDP6kFap6p5 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-7I5PxmDP6kFap6p5 .error-icon{fill:#552222;}#mermaid-svg-7I5PxmDP6kFap6p5 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-7I5PxmDP6kFap6p5 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-7I5PxmDP6kFap6p5 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-7I5PxmDP6kFap6p5 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-7I5PxmDP6kFap6p5 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-7I5PxmDP6kFap6p5 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-7I5PxmDP6kFap6p5 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-7I5PxmDP6kFap6p5 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-7I5PxmDP6kFap6p5 .marker.cross{stroke:#333333;}#mermaid-svg-7I5PxmDP6kFap6p5 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-7I5PxmDP6kFap6p5 p{margin:0;}#mermaid-svg-7I5PxmDP6kFap6p5 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-7I5PxmDP6kFap6p5 .cluster-label text{fill:#333;}#mermaid-svg-7I5PxmDP6kFap6p5 .cluster-label span{color:#333;}#mermaid-svg-7I5PxmDP6kFap6p5 .cluster-label span p{background-color:transparent;}#mermaid-svg-7I5PxmDP6kFap6p5 .label text,#mermaid-svg-7I5PxmDP6kFap6p5 span{fill:#333;color:#333;}#mermaid-svg-7I5PxmDP6kFap6p5 .node rect,#mermaid-svg-7I5PxmDP6kFap6p5 .node circle,#mermaid-svg-7I5PxmDP6kFap6p5 .node ellipse,#mermaid-svg-7I5PxmDP6kFap6p5 .node polygon,#mermaid-svg-7I5PxmDP6kFap6p5 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-7I5PxmDP6kFap6p5 .rough-node .label text,#mermaid-svg-7I5PxmDP6kFap6p5 .node .label text,#mermaid-svg-7I5PxmDP6kFap6p5 .image-shape .label,#mermaid-svg-7I5PxmDP6kFap6p5 .icon-shape .label{text-anchor:middle;}#mermaid-svg-7I5PxmDP6kFap6p5 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-7I5PxmDP6kFap6p5 .rough-node .label,#mermaid-svg-7I5PxmDP6kFap6p5 .node .label,#mermaid-svg-7I5PxmDP6kFap6p5 .image-shape .label,#mermaid-svg-7I5PxmDP6kFap6p5 .icon-shape .label{text-align:center;}#mermaid-svg-7I5PxmDP6kFap6p5 .node.clickable{cursor:pointer;}#mermaid-svg-7I5PxmDP6kFap6p5 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-7I5PxmDP6kFap6p5 .arrowheadPath{fill:#333333;}#mermaid-svg-7I5PxmDP6kFap6p5 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-7I5PxmDP6kFap6p5 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-7I5PxmDP6kFap6p5 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-7I5PxmDP6kFap6p5 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-7I5PxmDP6kFap6p5 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-7I5PxmDP6kFap6p5 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-7I5PxmDP6kFap6p5 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-7I5PxmDP6kFap6p5 .cluster text{fill:#333;}#mermaid-svg-7I5PxmDP6kFap6p5 .cluster span{color:#333;}#mermaid-svg-7I5PxmDP6kFap6p5 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-7I5PxmDP6kFap6p5 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-7I5PxmDP6kFap6p5 rect.text{fill:none;stroke-width:0;}#mermaid-svg-7I5PxmDP6kFap6p5 .icon-shape,#mermaid-svg-7I5PxmDP6kFap6p5 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-7I5PxmDP6kFap6p5 .icon-shape p,#mermaid-svg-7I5PxmDP6kFap6p5 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-7I5PxmDP6kFap6p5 .icon-shape .label rect,#mermaid-svg-7I5PxmDP6kFap6p5 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-7I5PxmDP6kFap6p5 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-7I5PxmDP6kFap6p5 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-7I5PxmDP6kFap6p5 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 监督学习
有标签数据
特征X + 标签Y
训练模型 f: X->Y
无监督学习
无标签数据
特征X
发现数据结构

数据集划分

#mermaid-svg-7yWWWbMdvokWX5BI{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-7yWWWbMdvokWX5BI .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-7yWWWbMdvokWX5BI .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-7yWWWbMdvokWX5BI .error-icon{fill:#552222;}#mermaid-svg-7yWWWbMdvokWX5BI .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-7yWWWbMdvokWX5BI .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-7yWWWbMdvokWX5BI .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-7yWWWbMdvokWX5BI .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-7yWWWbMdvokWX5BI .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-7yWWWbMdvokWX5BI .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-7yWWWbMdvokWX5BI .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-7yWWWbMdvokWX5BI .marker{fill:#333333;stroke:#333333;}#mermaid-svg-7yWWWbMdvokWX5BI .marker.cross{stroke:#333333;}#mermaid-svg-7yWWWbMdvokWX5BI svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-7yWWWbMdvokWX5BI p{margin:0;}#mermaid-svg-7yWWWbMdvokWX5BI .pieCircle{stroke:#000000;stroke-width:2px;opacity:0.7;}#mermaid-svg-7yWWWbMdvokWX5BI .pieOuterCircle{stroke:#000000;stroke-width:1px;fill:none;}#mermaid-svg-7yWWWbMdvokWX5BI .pieTitleText{text-anchor:middle;font-size:25px;fill:#000000;font-family:"trebuchet ms",verdana,arial,sans-serif;}#mermaid-svg-7yWWWbMdvokWX5BI .slice{font-family:"trebuchet ms",verdana,arial,sans-serif;fill:#000000;font-size:17px;}#mermaid-svg-7yWWWbMdvokWX5BI .legend text{fill:#000000;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:17px;}#mermaid-svg-7yWWWbMdvokWX5BI :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 70% 15% 15% 数据集划分比例 训练集 70% 验证集 15% 测试集 15%

评估指标

常用的评估指标包括:

指标 计算公式 含义
准确率 (TP+TN)/(TP+TN+FP+FN) 整体预测正确的比例
精确率 TP/(TP+FP) 预测为正例的样本中实际为正例的比例
召回率 TP/(TP+FN) 实际为正例的样本中被正确预测的比例
F1分数 2精确率召回率/(精确率+召回率) 精确率和召回率的调和平均

#mermaid-svg-Hnn8fX7O9Q59gJto{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-Hnn8fX7O9Q59gJto .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-Hnn8fX7O9Q59gJto .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-Hnn8fX7O9Q59gJto .error-icon{fill:#552222;}#mermaid-svg-Hnn8fX7O9Q59gJto .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Hnn8fX7O9Q59gJto .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-Hnn8fX7O9Q59gJto .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Hnn8fX7O9Q59gJto .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Hnn8fX7O9Q59gJto .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-Hnn8fX7O9Q59gJto .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Hnn8fX7O9Q59gJto .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Hnn8fX7O9Q59gJto .marker{fill:#333333;stroke:#333333;}#mermaid-svg-Hnn8fX7O9Q59gJto .marker.cross{stroke:#333333;}#mermaid-svg-Hnn8fX7O9Q59gJto svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Hnn8fX7O9Q59gJto p{margin:0;}#mermaid-svg-Hnn8fX7O9Q59gJto .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-Hnn8fX7O9Q59gJto .cluster-label text{fill:#333;}#mermaid-svg-Hnn8fX7O9Q59gJto .cluster-label span{color:#333;}#mermaid-svg-Hnn8fX7O9Q59gJto .cluster-label span p{background-color:transparent;}#mermaid-svg-Hnn8fX7O9Q59gJto .label text,#mermaid-svg-Hnn8fX7O9Q59gJto span{fill:#333;color:#333;}#mermaid-svg-Hnn8fX7O9Q59gJto .node rect,#mermaid-svg-Hnn8fX7O9Q59gJto .node circle,#mermaid-svg-Hnn8fX7O9Q59gJto .node ellipse,#mermaid-svg-Hnn8fX7O9Q59gJto .node polygon,#mermaid-svg-Hnn8fX7O9Q59gJto .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-Hnn8fX7O9Q59gJto .rough-node .label text,#mermaid-svg-Hnn8fX7O9Q59gJto .node .label text,#mermaid-svg-Hnn8fX7O9Q59gJto .image-shape .label,#mermaid-svg-Hnn8fX7O9Q59gJto .icon-shape .label{text-anchor:middle;}#mermaid-svg-Hnn8fX7O9Q59gJto .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-Hnn8fX7O9Q59gJto .rough-node .label,#mermaid-svg-Hnn8fX7O9Q59gJto .node .label,#mermaid-svg-Hnn8fX7O9Q59gJto .image-shape .label,#mermaid-svg-Hnn8fX7O9Q59gJto .icon-shape .label{text-align:center;}#mermaid-svg-Hnn8fX7O9Q59gJto .node.clickable{cursor:pointer;}#mermaid-svg-Hnn8fX7O9Q59gJto .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-Hnn8fX7O9Q59gJto .arrowheadPath{fill:#333333;}#mermaid-svg-Hnn8fX7O9Q59gJto .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-Hnn8fX7O9Q59gJto .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-Hnn8fX7O9Q59gJto .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Hnn8fX7O9Q59gJto .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-Hnn8fX7O9Q59gJto .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Hnn8fX7O9Q59gJto .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-Hnn8fX7O9Q59gJto .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-Hnn8fX7O9Q59gJto .cluster text{fill:#333;}#mermaid-svg-Hnn8fX7O9Q59gJto .cluster span{color:#333;}#mermaid-svg-Hnn8fX7O9Q59gJto 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-Hnn8fX7O9Q59gJto .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-Hnn8fX7O9Q59gJto rect.text{fill:none;stroke-width:0;}#mermaid-svg-Hnn8fX7O9Q59gJto .icon-shape,#mermaid-svg-Hnn8fX7O9Q59gJto .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Hnn8fX7O9Q59gJto .icon-shape p,#mermaid-svg-Hnn8fX7O9Q59gJto .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-Hnn8fX7O9Q59gJto .icon-shape .label rect,#mermaid-svg-Hnn8fX7O9Q59gJto .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Hnn8fX7O9Q59gJto .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-Hnn8fX7O9Q59gJto .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-Hnn8fX7O9Q59gJto :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 正例
正例
负例
负例
正例
负例
预测结果
实际类别
预测类别
TP: 真正例
FN: 假负例
预测类别
FP: 假正例
TN: 真负例


BCI常用机器学习算法

1. 线性判别分析 (LDA)

原理:寻找一条直线,使不同类别的数据在这条直线上的投影尽可能分开。

特点

  • 简单快速
  • 计算量小
  • 在小样本数据集上表现良好

适用场景:P300、SSVEP识别

python 复制代码
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis

# 创建LDA分类器
lda = LinearDiscriminantAnalysis()

# 训练模型
lda.fit(X_train, y_train)

# 预测
y_pred = lda.predict(X_test)

# 评估
accuracy = lda.score(X_test, y_test)
print(f"LDA准确率: {accuracy:.2f}")

2. 支持向量机 (SVM)

原理:寻找最优超平面,使不同类别的数据点到超平面的距离最大。

特点

  • 在高维空间表现优秀
  • 适合小样本数据集
  • 有多种核函数可选

适用场景:运动想象、情绪识别
#mermaid-svg-0OpROQs9nsrt3bI3{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-0OpROQs9nsrt3bI3 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-0OpROQs9nsrt3bI3 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-0OpROQs9nsrt3bI3 .error-icon{fill:#552222;}#mermaid-svg-0OpROQs9nsrt3bI3 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-0OpROQs9nsrt3bI3 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-0OpROQs9nsrt3bI3 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-0OpROQs9nsrt3bI3 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-0OpROQs9nsrt3bI3 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-0OpROQs9nsrt3bI3 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-0OpROQs9nsrt3bI3 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-0OpROQs9nsrt3bI3 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-0OpROQs9nsrt3bI3 .marker.cross{stroke:#333333;}#mermaid-svg-0OpROQs9nsrt3bI3 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-0OpROQs9nsrt3bI3 p{margin:0;}#mermaid-svg-0OpROQs9nsrt3bI3 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-0OpROQs9nsrt3bI3 .cluster-label text{fill:#333;}#mermaid-svg-0OpROQs9nsrt3bI3 .cluster-label span{color:#333;}#mermaid-svg-0OpROQs9nsrt3bI3 .cluster-label span p{background-color:transparent;}#mermaid-svg-0OpROQs9nsrt3bI3 .label text,#mermaid-svg-0OpROQs9nsrt3bI3 span{fill:#333;color:#333;}#mermaid-svg-0OpROQs9nsrt3bI3 .node rect,#mermaid-svg-0OpROQs9nsrt3bI3 .node circle,#mermaid-svg-0OpROQs9nsrt3bI3 .node ellipse,#mermaid-svg-0OpROQs9nsrt3bI3 .node polygon,#mermaid-svg-0OpROQs9nsrt3bI3 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-0OpROQs9nsrt3bI3 .rough-node .label text,#mermaid-svg-0OpROQs9nsrt3bI3 .node .label text,#mermaid-svg-0OpROQs9nsrt3bI3 .image-shape .label,#mermaid-svg-0OpROQs9nsrt3bI3 .icon-shape .label{text-anchor:middle;}#mermaid-svg-0OpROQs9nsrt3bI3 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-0OpROQs9nsrt3bI3 .rough-node .label,#mermaid-svg-0OpROQs9nsrt3bI3 .node .label,#mermaid-svg-0OpROQs9nsrt3bI3 .image-shape .label,#mermaid-svg-0OpROQs9nsrt3bI3 .icon-shape .label{text-align:center;}#mermaid-svg-0OpROQs9nsrt3bI3 .node.clickable{cursor:pointer;}#mermaid-svg-0OpROQs9nsrt3bI3 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-0OpROQs9nsrt3bI3 .arrowheadPath{fill:#333333;}#mermaid-svg-0OpROQs9nsrt3bI3 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-0OpROQs9nsrt3bI3 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-0OpROQs9nsrt3bI3 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-0OpROQs9nsrt3bI3 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-0OpROQs9nsrt3bI3 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-0OpROQs9nsrt3bI3 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-0OpROQs9nsrt3bI3 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-0OpROQs9nsrt3bI3 .cluster text{fill:#333;}#mermaid-svg-0OpROQs9nsrt3bI3 .cluster span{color:#333;}#mermaid-svg-0OpROQs9nsrt3bI3 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-0OpROQs9nsrt3bI3 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-0OpROQs9nsrt3bI3 rect.text{fill:none;stroke-width:0;}#mermaid-svg-0OpROQs9nsrt3bI3 .icon-shape,#mermaid-svg-0OpROQs9nsrt3bI3 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-0OpROQs9nsrt3bI3 .icon-shape p,#mermaid-svg-0OpROQs9nsrt3bI3 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-0OpROQs9nsrt3bI3 .icon-shape .label rect,#mermaid-svg-0OpROQs9nsrt3bI3 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-0OpROQs9nsrt3bI3 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-0OpROQs9nsrt3bI3 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-0OpROQs9nsrt3bI3 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 投影
数据点
超平面
支持向量

python 复制代码
from sklearn.svm import SVC
from sklearn.preprocessing import StandardScaler

# 数据标准化
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)

# 创建SVM分类器,使用RBF核
svm = SVC(kernel='rbf', C=1.0, gamma='scale')

# 训练
svm.fit(X_train_scaled, y_train)

# 预测
y_pred = svm.predict(X_test_scaled)

# 评估
from sklearn.metrics import accuracy_score
accuracy = accuracy_score(y_test, y_pred)
print(f"SVM准确率: {accuracy:.2f}")

3. 随机森林 (Random Forest)

原理:集成多个决策树,通过投票机制得到最终预测结果。

特点

  • 抗过拟合能力强
  • 可以处理高维数据
  • 可以评估特征重要性

适用场景:情绪识别、注意力监测

python 复制代码
from sklearn.ensemble import RandomForestClassifier

# 创建随机森林分类器
rf = RandomForestClassifier(
    n_estimators=100,    # 决策树数量
    max_depth=10,        # 树最大深度
    random_state=42
)

# 训练
rf.fit(X_train, y_train)

# 预测
y_pred = rf.predict(X_test)

# 特征重要性
importances = rf.feature_importances_
print("特征重要性:", importances)

4. k近邻算法 (k-NN)

原理:根据最近的k个邻居的类别来判断当前样本的类别。

特点

  • 简单直观
  • 无需训练过程
  • 对数据尺度敏感

适用场景:简单的分类任务

python 复制代码
from sklearn.neighbors import KNeighborsClassifier

# 创建k-NN分类器
knn = KNeighborsClassifier(n_neighbors=5)

# 训练(实际上是存储数据)
knn.fit(X_train, y_train)

# 预测
y_pred = knn.predict(X_test)

5. 朴素贝叶斯 (Naive Bayes)

原理:基于贝叶斯定理和特征独立假设进行分类。

特点

  • 计算速度快
  • 适合高维数据
  • 假设特征独立

适用场景:文本分类、简单EEG分类

python 复制代码
from sklearn.naive_bayes import GaussianNB

# 创建朴素贝叶斯分类器
nb = GaussianNB()

# 训练
nb.fit(X_train, y_train)

# 预测
y_pred = nb.predict(X_test)

完整实战:脑电信号分类流程

数据准备

首先,我们需要准备用于训练的脑电数据。这里使用一个模拟的EEG数据集:

python 复制代码
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler

# 生成模拟EEG数据
np.random.seed(42)
n_samples = 1000
n_features = 64  # 64个特征

# 类别0:放松状态(alpha波较多)
class0 = np.random.normal(loc=5, scale=2, size=(n_samples//2, n_features))
# 类别1:专注状态(beta波较多)
class1 = np.random.normal(loc=8, scale=2, size=(n_samples//2, n_features))

# 合并数据
X = np.vstack([class0, class1])
y = np.array([0]* (n_samples//2) + [1]*(n_samples//2))

# 划分数据集
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42, stratify=y
)

# 数据标准化
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)

print(f"训练集形状: {X_train.shape}")
print(f"测试集形状: {X_test.shape}")
print(f"类别分布: 训练集 {np.bincount(y_train)}, 测试集 {np.bincount(y_test)}")

模型训练与比较

python 复制代码
from sklearn.metrics import accuracy_score, f1_score, classification_report

# 定义要测试的模型
models = {
    'LDA': LinearDiscriminantAnalysis(),
    'SVM': SVC(kernel='rbf', C=1.0, gamma='scale'),
    'Random Forest': RandomForestClassifier(n_estimators=100, random_state=42),
    'k-NN': KNeighborsClassifier(n_neighbors=5),
    'Naive Bayes': GaussianNB()
}

# 训练并评估所有模型
results = {}
for name, model in models.items():
    # 训练
    model.fit(X_train_scaled, y_train)
    
    # 预测
    y_pred = model.predict(X_test_scaled)
    
    # 评估
    accuracy = accuracy_score(y_test, y_pred)
    f1 = f1_score(y_test, y_pred)
    
    results[name] = {'accuracy': accuracy, 'f1': f1}
    print(f"=== {name} ===")
    print(classification_report(y_test, y_pred))
    print()

结果可视化

python 复制代码
import matplotlib.pyplot as plt

# 绘制模型对比图
names = list(results.keys())
accuracies = [results[name]['accuracy'] for name in names]
f1_scores = [results[name]['f1'] for name in names]

fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 5))

ax1.bar(names, accuracies, color='skyblue')
ax1.set_title('模型准确率对比')
ax1.set_ylabel('准确率')
ax1.set_ylim(0.8, 1.0)

ax2.bar(names, f1_scores, color='salmon')
ax2.set_title('模型F1分数对比')
ax2.set_ylabel('F1分数')
ax2.set_ylim(0.8, 1.0)

plt.tight_layout()
plt.show()

模型选择流程图

#mermaid-svg-JHI2W5mR4qj2VYvL{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-JHI2W5mR4qj2VYvL .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-JHI2W5mR4qj2VYvL .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-JHI2W5mR4qj2VYvL .error-icon{fill:#552222;}#mermaid-svg-JHI2W5mR4qj2VYvL .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-JHI2W5mR4qj2VYvL .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-JHI2W5mR4qj2VYvL .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-JHI2W5mR4qj2VYvL .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-JHI2W5mR4qj2VYvL .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-JHI2W5mR4qj2VYvL .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-JHI2W5mR4qj2VYvL .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-JHI2W5mR4qj2VYvL .marker{fill:#333333;stroke:#333333;}#mermaid-svg-JHI2W5mR4qj2VYvL .marker.cross{stroke:#333333;}#mermaid-svg-JHI2W5mR4qj2VYvL svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-JHI2W5mR4qj2VYvL p{margin:0;}#mermaid-svg-JHI2W5mR4qj2VYvL .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-JHI2W5mR4qj2VYvL .cluster-label text{fill:#333;}#mermaid-svg-JHI2W5mR4qj2VYvL .cluster-label span{color:#333;}#mermaid-svg-JHI2W5mR4qj2VYvL .cluster-label span p{background-color:transparent;}#mermaid-svg-JHI2W5mR4qj2VYvL .label text,#mermaid-svg-JHI2W5mR4qj2VYvL span{fill:#333;color:#333;}#mermaid-svg-JHI2W5mR4qj2VYvL .node rect,#mermaid-svg-JHI2W5mR4qj2VYvL .node circle,#mermaid-svg-JHI2W5mR4qj2VYvL .node ellipse,#mermaid-svg-JHI2W5mR4qj2VYvL .node polygon,#mermaid-svg-JHI2W5mR4qj2VYvL .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-JHI2W5mR4qj2VYvL .rough-node .label text,#mermaid-svg-JHI2W5mR4qj2VYvL .node .label text,#mermaid-svg-JHI2W5mR4qj2VYvL .image-shape .label,#mermaid-svg-JHI2W5mR4qj2VYvL .icon-shape .label{text-anchor:middle;}#mermaid-svg-JHI2W5mR4qj2VYvL .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-JHI2W5mR4qj2VYvL .rough-node .label,#mermaid-svg-JHI2W5mR4qj2VYvL .node .label,#mermaid-svg-JHI2W5mR4qj2VYvL .image-shape .label,#mermaid-svg-JHI2W5mR4qj2VYvL .icon-shape .label{text-align:center;}#mermaid-svg-JHI2W5mR4qj2VYvL .node.clickable{cursor:pointer;}#mermaid-svg-JHI2W5mR4qj2VYvL .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-JHI2W5mR4qj2VYvL .arrowheadPath{fill:#333333;}#mermaid-svg-JHI2W5mR4qj2VYvL .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-JHI2W5mR4qj2VYvL .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-JHI2W5mR4qj2VYvL .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-JHI2W5mR4qj2VYvL .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-JHI2W5mR4qj2VYvL .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-JHI2W5mR4qj2VYvL .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-JHI2W5mR4qj2VYvL .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-JHI2W5mR4qj2VYvL .cluster text{fill:#333;}#mermaid-svg-JHI2W5mR4qj2VYvL .cluster span{color:#333;}#mermaid-svg-JHI2W5mR4qj2VYvL 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-JHI2W5mR4qj2VYvL .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-JHI2W5mR4qj2VYvL rect.text{fill:none;stroke-width:0;}#mermaid-svg-JHI2W5mR4qj2VYvL .icon-shape,#mermaid-svg-JHI2W5mR4qj2VYvL .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-JHI2W5mR4qj2VYvL .icon-shape p,#mermaid-svg-JHI2W5mR4qj2VYvL .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-JHI2W5mR4qj2VYvL .icon-shape .label rect,#mermaid-svg-JHI2W5mR4qj2VYvL .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-JHI2W5mR4qj2VYvL .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-JHI2W5mR4qj2VYvL .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-JHI2W5mR4qj2VYvL :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 低维 < 50
高维 >= 50
小样本 < 100
大样本 >= 100
有标注
无标注
数据特征
特征维度
样本量
是否有标注
使用LDA或SVM
使用随机森林
使用SVM或深度学习
使用聚类算法
评估模型性能
选择最优模型


交叉验证与超参数调优

k折交叉验证

python 复制代码
from sklearn.model_selection import cross_val_score

# 使用5折交叉验证评估SVM
svm = SVC(kernel='rbf', C=1.0, gamma='scale')
scores = cross_val_score(svm, X_train_scaled, y_train, cv=5, scoring='accuracy')

print(f"5折交叉验证分数: {scores}")
print(f"平均准确率: {np.mean(scores):.2f} (+/- {np.std(scores)*2:.2f})")

网格搜索调优

python 复制代码
from sklearn.model_selection import GridSearchCV

# 定义参数网格
param_grid = {
    'C': [0.1, 1, 10, 100],
    'gamma': ['scale', 'auto', 0.001, 0.01, 0.1],
    'kernel': ['linear', 'rbf', 'poly']
}

# 创建网格搜索对象
grid_search = GridSearchCV(SVC(), param_grid, cv=5, scoring='accuracy', n_jobs=-1)

# 执行搜索
grid_search.fit(X_train_scaled, y_train)

print(f"最佳参数: {grid_search.best_params_}")
print(f"最佳交叉验证准确率: {grid_search.best_score_:.2f}")

# 使用最佳模型
best_model = grid_search.best_estimator_
test_accuracy = best_model.score(X_test_scaled, y_test)
print(f"测试集准确率: {test_accuracy:.2f}")

学习曲线分析

python 复制代码
from sklearn.model_selection import learning_curve

def plot_learning_curve(estimator, title, X, y, cv=5, n_jobs=-1):
    train_sizes, train_scores, test_scores = learning_curve(
        estimator, X, y, cv=cv, n_jobs=n_jobs,
        train_sizes=np.linspace(0.1, 1.0, 10)
    )
    
    train_mean = np.mean(train_scores, axis=1)
    train_std = np.std(train_scores, axis=1)
    test_mean = np.mean(test_scores, axis=1)
    test_std = np.std(test_scores, axis=1)
    
    plt.figure(figsize=(10, 6))
    plt.title(title)
    plt.xlabel("训练样本数")
    plt.ylabel("分数")
    plt.grid()
    
    plt.fill_between(train_sizes, train_mean - train_std,
                     train_mean + train_std, alpha=0.1, color="r")
    plt.fill_between(train_sizes, test_mean - test_std,
                     test_mean + test_std, alpha=0.1, color="g")
    plt.plot(train_sizes, train_mean, 'o-', color="r", label="训练分数")
    plt.plot(train_sizes, test_mean, 'o-', color="g", label="交叉验证分数")
    plt.legend(loc="best")
    return plt

# 绘制学习曲线
plot_learning_curve(SVC(kernel='rbf'), 'SVM学习曲线', X_train_scaled, y_train)
plt.show()

实战案例:基于机器学习的注意力监测系统

系统架构

#mermaid-svg-nJBmre9Kd8IoqKFE{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-nJBmre9Kd8IoqKFE .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-nJBmre9Kd8IoqKFE .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-nJBmre9Kd8IoqKFE .error-icon{fill:#552222;}#mermaid-svg-nJBmre9Kd8IoqKFE .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-nJBmre9Kd8IoqKFE .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-nJBmre9Kd8IoqKFE .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-nJBmre9Kd8IoqKFE .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-nJBmre9Kd8IoqKFE .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-nJBmre9Kd8IoqKFE .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-nJBmre9Kd8IoqKFE .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-nJBmre9Kd8IoqKFE .marker{fill:#333333;stroke:#333333;}#mermaid-svg-nJBmre9Kd8IoqKFE .marker.cross{stroke:#333333;}#mermaid-svg-nJBmre9Kd8IoqKFE svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-nJBmre9Kd8IoqKFE p{margin:0;}#mermaid-svg-nJBmre9Kd8IoqKFE .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-nJBmre9Kd8IoqKFE .cluster-label text{fill:#333;}#mermaid-svg-nJBmre9Kd8IoqKFE .cluster-label span{color:#333;}#mermaid-svg-nJBmre9Kd8IoqKFE .cluster-label span p{background-color:transparent;}#mermaid-svg-nJBmre9Kd8IoqKFE .label text,#mermaid-svg-nJBmre9Kd8IoqKFE span{fill:#333;color:#333;}#mermaid-svg-nJBmre9Kd8IoqKFE .node rect,#mermaid-svg-nJBmre9Kd8IoqKFE .node circle,#mermaid-svg-nJBmre9Kd8IoqKFE .node ellipse,#mermaid-svg-nJBmre9Kd8IoqKFE .node polygon,#mermaid-svg-nJBmre9Kd8IoqKFE .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-nJBmre9Kd8IoqKFE .rough-node .label text,#mermaid-svg-nJBmre9Kd8IoqKFE .node .label text,#mermaid-svg-nJBmre9Kd8IoqKFE .image-shape .label,#mermaid-svg-nJBmre9Kd8IoqKFE .icon-shape .label{text-anchor:middle;}#mermaid-svg-nJBmre9Kd8IoqKFE .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-nJBmre9Kd8IoqKFE .rough-node .label,#mermaid-svg-nJBmre9Kd8IoqKFE .node .label,#mermaid-svg-nJBmre9Kd8IoqKFE .image-shape .label,#mermaid-svg-nJBmre9Kd8IoqKFE .icon-shape .label{text-align:center;}#mermaid-svg-nJBmre9Kd8IoqKFE .node.clickable{cursor:pointer;}#mermaid-svg-nJBmre9Kd8IoqKFE .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-nJBmre9Kd8IoqKFE .arrowheadPath{fill:#333333;}#mermaid-svg-nJBmre9Kd8IoqKFE .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-nJBmre9Kd8IoqKFE .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-nJBmre9Kd8IoqKFE .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-nJBmre9Kd8IoqKFE .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-nJBmre9Kd8IoqKFE .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-nJBmre9Kd8IoqKFE .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-nJBmre9Kd8IoqKFE .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-nJBmre9Kd8IoqKFE .cluster text{fill:#333;}#mermaid-svg-nJBmre9Kd8IoqKFE .cluster span{color:#333;}#mermaid-svg-nJBmre9Kd8IoqKFE 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-nJBmre9Kd8IoqKFE .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-nJBmre9Kd8IoqKFE rect.text{fill:none;stroke-width:0;}#mermaid-svg-nJBmre9Kd8IoqKFE .icon-shape,#mermaid-svg-nJBmre9Kd8IoqKFE .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-nJBmre9Kd8IoqKFE .icon-shape p,#mermaid-svg-nJBmre9Kd8IoqKFE .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-nJBmre9Kd8IoqKFE .icon-shape .label rect,#mermaid-svg-nJBmre9Kd8IoqKFE .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-nJBmre9Kd8IoqKFE .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-nJBmre9Kd8IoqKFE .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-nJBmre9Kd8IoqKFE :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} EEG采集设备
数据预处理
特征提取
特征选择
机器学习模型
注意力预测
反馈输出
可视化界面
历史数据存储

完整代码实现

python 复制代码
import numpy as np
from sklearn.svm import SVC
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import accuracy_score
import joblib

class AttentionMonitor:
    def __init__(self):
        self.scaler = StandardScaler()
        self.model = SVC(kernel='rbf', C=10, gamma='scale')
        self.is_trained = False
    
    def train(self, X, y):
        """训练模型"""
        X_scaled = self.scaler.fit_transform(X)
        self.model.fit(X_scaled, y)
        self.is_trained = True
        print("模型训练完成")
    
    def predict(self, eeg_data):
        """预测注意力水平"""
        if not self.is_trained:
            raise Exception("模型尚未训练")
        
        # 确保输入数据形状正确
        if len(eeg_data.shape) == 1:
            eeg_data = eeg_data.reshape(1, -1)
        
        X_scaled = self.scaler.transform(eeg_data)
        prediction = self.model.predict(X_scaled)
        probability = self.model.predict_proba(X_scaled)
        
        return prediction[0], probability[0]
    
    def save_model(self, filepath):
        """保存模型"""
        joblib.dump({'model': self.model, 'scaler': self.scaler}, filepath)
        print(f"模型已保存到 {filepath}")
    
    def load_model(self, filepath):
        """加载模型"""
        data = joblib.load(filepath)
        self.model = data['model']
        self.scaler = data['scaler']
        self.is_trained = True
        print(f"模型已从 {filepath} 加载")

# 模拟训练数据
np.random.seed(42)
n_samples = 500
n_channels = 8
n_features = n_channels * 10  # 每个通道提取10个特征

# 低注意力数据
low_attention = np.random.normal(loc=4, scale=1.5, size=(n_samples//2, n_features))
# 高注意力数据
high_attention = np.random.normal(loc=7, scale=1.5, size=(n_samples//2, n_features))

X_train = np.vstack([low_attention, high_attention])
y_train = np.array([0]*(n_samples//2) + [1]*(n_samples//2))

# 创建并训练注意力监测器
monitor = AttentionMonitor()
monitor.train(X_train, y_train)

# 测试预测
test_data = np.random.normal(loc=6, scale=1.5, size=(1, n_features))
attention_level, prob = monitor.predict(test_data)
print(f"预测注意力水平: {'高' if attention_level == 1 else '低'}")
print(f"预测概率: 低注意力={prob[0]:.4f}, 高注意力={prob[1]:.4f}")

# 保存模型
monitor.save_model('attention_model.pkl')

常见问题与解决方案

问题1:数据不平衡

现象:某一类样本数量远多于另一类

解决方案

  • 过采样:增加少数类样本
  • 欠采样:减少多数类样本
  • 使用加权损失函数
python 复制代码
from imblearn.over_sampling import SMOTE

# 使用SMOTE进行过采样
smote = SMOTE(random_state=42)
X_resampled, y_resampled = smote.fit_resample(X_train, y_train)
print(f"重采样后类别分布: {np.bincount(y_resampled)}")

问题2:过拟合

现象:训练集表现很好,但测试集表现很差

解决方案

  • 增加训练数据
  • 使用正则化
  • 减少模型复杂度
  • 使用交叉验证
python 复制代码
# 使用带正则化的SVM
svm = SVC(kernel='rbf', C=0.1, gamma='scale')  # 较小的C值表示更强的正则化

问题3:特征选择

现象:特征维度太高,计算量大且容易过拟合

解决方案

  • 使用特征重要性分析
  • 使用PCA降维
  • 使用互信息选择
python 复制代码
from sklearn.decomposition import PCA

# 使用PCA降维到20个特征
pca = PCA(n_components=20)
X_train_pca = pca.fit_transform(X_train_scaled)
X_test_pca = pca.transform(X_test_scaled)
print(f"降维后特征数: {X_train_pca.shape[1]}")

总结与展望

本章重点

  1. 机器学习流程:数据采集→预处理→特征提取→模型训练→评估→部署
  2. 常用算法:LDA、SVM、随机森林、k-NN、朴素贝叶斯
  3. 评估指标:准确率、精确率、召回率、F1分数
  4. 调优方法:交叉验证、网格搜索、学习曲线

下一步学习计划

下一章我们将进入实战环节,学习如何使用脑电信号控制LED灯,这是一个非常有趣的入门项目!


思考与练习

  1. 思考:为什么在BCI中SVM比神经网络更常用?
  2. 练习:使用真实的EEG数据集(如BCI Competition数据集)进行分类实验
  3. 练习:尝试不同的特征组合和模型参数,比较它们的性能差异

系列文章导航


声明:本文仅供学习交流,文中涉及的硬件设备和软件工具请从官方渠道获取。脑机接口技术涉及生物医学领域,实际应用请遵循相关法律法规和伦理规范。


相关推荐
钓了猫的鱼儿1 小时前
基于深度学习+AI的葡萄目标检测与预警系统(Python源码+数据集+UI可视化界面+YOLOv11训练结果)
人工智能·深度学习·目标检测
木雷坞1 小时前
Open WebUI 连不上 Ollama:Docker Compose 排查记录
人工智能·docker·ai编程
Csu__1 小时前
回归任务中损失函数有哪些
机器学习
AndrewHZ1 小时前
【LLM技术全景】Transformer架构深度解析:Encoder-Decoder全理解
人工智能·深度学习·语言模型·大模型·llm·transformer·编解码技术
Stick_ZYZ1 小时前
从项目启动到 Milvus 向量检索,我把 RAG 项目链路又打通了一层
java·人工智能·经验分享·ai·milvus
沫儿笙1 小时前
新能源汽车焊接智能节气装置
人工智能·机器人·汽车
阿昌喜欢吃黄桃1 小时前
大模型常见参数学习笔记
人工智能·ai·llm·prompt·token
程序员cxuan1 小时前
太顶了,ChatGPT 要和 Codex 搞一起了。
人工智能·后端·程序员
weixin_446260851 小时前
ClinEnv:面向Agent的交互式多阶段电子健康记录(EHR)环境
人工智能