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 天前
统信UOS + 天数AI卡部署SGLang服务手册
人工智能·uos·sglang·天数智芯
DevSecOps选型指南1 天前
中国版Mythos,为何是悬镜安全灵脉CodeAI?
人工智能·安全
Shockang1 天前
LangGraph 状态机实战
人工智能
刹那芳华19921 天前
循环神经网络的从零开始实现(RNN)
人工智能·rnn·深度学习
阿童木写作1 天前
跨境图片翻译工具多合一,批量图片视频字幕翻译加智能抠图
人工智能·python·音视频·语音识别
科技之门1 天前
AI3D从建模到贴图、绑骨和动画的完整流程怎么做?V2Fun完整工作流指南
人工智能·3d·贴图
宇宙第一小趴菜1 天前
二、机器学习的应用领域和发展史
人工智能·机器学习
前端开发江鸟1 天前
我写过 MCP Server,却一直以为 MCP 只有 Tool
人工智能
天国梦1 天前
自习室智能化升级避坑指南:天学网AI智习室方案实测与选型建议
大数据·人工智能
阿里云云原生1 天前
可用性从 99.9% 跃升至 99.995%:畅捷通如何用 AI 重塑运维底座?
运维·网络·人工智能