脑电模型实战系列(三):基于 KNN 的 DEAP 脑电情绪识别 KNN 算法与 Canberra 距离深度剖析(三)

🌟 引言:让机器学会"读心术"

在前两篇中,我们从 DEAP 数据集的脑波海洋起步,通过 FFT 和频带提取,炼出了 160 维的"情绪指纹"(频带标准差特征)。现在,是时候揭开最后一步的神秘面纱了:分类与预测

今天的主角是 K-近邻(K-Nearest Neighbors, KNN) 。在脑电(EEG)研究领域,KNN 因其无需参数假设、对非线性特征敏感而广受欢迎。本篇将深度剖析 knn_predict.py 的核心逻辑,重点探讨为什么在 EEG 识别中 Canberra 距离 比传统的欧氏距离更胜一筹。


1. KNN 算法:邻里智慧的"懒惰"艺术

KNN 是一种典型的**懒惰学习(Lazy Learning)**算法。它并不在训练阶段构建复杂的数学模型,而是将所有训练样本存储在内存中,直到预测时才进行计算。

1.1 核心逻辑

  1. 特征匹配:将当前测试样本的 160 维特征向量,与数据库中已有的 40 个试验特征逐一对比。

  2. 寻找邻居 :计算相似度(距离),找出距离最近的 个样本。

  3. 多数表决 :这 个邻居中哪类标签最多,新样本就属于哪类。

1.2 为什么 KNN 适合 EEG?

  • 非线性分布:EEG 信号受到个体差异、电极阻抗等多种非线性因素影响。KNN 不需要像线性回归那样预设数据分布,能直接捕捉局部的非线性模式。

  • 小样本友好:DEAP 数据集每个被试只有 40 个试验,这对于深度神经网络来说太少了,但对 KNN 却是"黄金规模"。


2. 距离度量:Canberra 距离的独特魅力

距离度量(Distance Metric)是 KNN 的灵魂。虽然欧氏距离(Euclidean Distance)最广为人知,但在处理 EEG 频域特征时,Canberra 距离(兰氏距离) 展现出了惊人的鲁棒性。

2.1 数学公式对比

  • 缺点:容易被数值较大的维度主导,对接近 0 的微小差异不敏感。

  • Canberra 距离:

    优点:它是一个加权的曼哈顿距离。分母的出现起到了归一化的作用。

2.2 为什么 Canberra 更好?

EEG 的标准差(STD)特征通常分布在很小的数值区间(如 0.01 到 0.5 之间)。

  1. 零值敏感性:如果一个频带的功率从 0 变为 0.01(意味着该频带从静默转为激活),欧氏距离认为温差仅为 0.01,微乎其微;而 Canberra 距离会将这一变化视为显著差异(贡献度趋近 1)。

  2. 抗噪能力:它能有效减弱由于个别通道干扰产生的大数值异常值对整体距离的影响。


3. 核心代码实现:EmotionPredictor

为了方便大家直接使用,我将项目中的预测逻辑封装成了一个标准的 Python 类。

Python

复制代码
import numpy as np
import scipy.spatial as ss
import scipy.stats as sst
import csv

class EmotionPredictor:
    def __init__(self, train_data_path, train_label_path):
        self.train_features = self._load_csv(train_data_path)
        self.train_labels = self._load_csv(train_label_path)
        self.k = 3

    def _load_csv(self, path):
        with open(path, 'r') as f:
            reader = csv.reader(f)
            return np.array(list(reader), dtype=np.float64)

    def predict(self, test_feature):
        """
        基于Canberra距离的KNN预测
        """
        # 1. 计算所有训练样本与测试样本的Canberra距离
        distances = [ss.distance.canberra(x, test_feature) for x in self.train_features]
        
        # 2. 获取距离最近的K个邻居的索引
        nearest_indices = np.argsort(distances)[:self.k]
        nearest_distances = np.sort(distances)[:self.k]
        
        # 3. 智能投票逻辑:比率阈值法 (Ratio Trick)
        # 如果最近邻与次近邻的距离差异极大 (ratio <= 0.7),则极度信任最近邻
        ratio = nearest_distances[0] / nearest_distances[1]
        
        if ratio <= 0.7:
            prediction = self.train_labels[0, nearest_indices[0]]
        else:
            # 否则采用众数投票(民主表决)
            prediction = sst.mode(self.train_labels[0, nearest_indices])[0][0]
            
        return prediction

4. 智能投票机制:为什么是 0.7?

项目中引入了一个非常有趣的优化:比率阈值(Ratio Threshold)

在预测时,我们不仅看谁是最近邻,还看它到底有多"近"。

这种策略有效地提升了模型在面对噪声数据时的分类准确率,将单被试准确率稳定在 70% 左右。


5. 情绪映射:回归 Russell 情绪环

KNN 输出的是 Arousal(唤醒度)和 Valence(效价)的离散级别(1-低,2-中,3-高)。最后一步是将其映射回具体的心理学定义:

Python

复制代码
def get_emotion_description(arousal, valence):
    """
    根据Arousal和Valence级别判断情绪类别
    """
    if arousal == 2.0 or valence == 2.0:
        return "Neutral (中性)"
    
    mapping = {
        (3.0, 1.0): "Fear/Stress (恐惧/压力 - 高唤醒低效价)",
        (3.0, 3.0): "Happy/Excited (快乐/兴奋 - 高唤醒高效价)",
        (1.0, 3.0): "Relax/Calm (放松/平静 - 低唤醒高效价)",
        (1.0, 1.0): "Sad/Depressed (悲伤/抑郁 - 低唤醒低效价)"
    }
    
    return mapping.get((arousal, valence), "Unknown")

🚀 结语:从特征到情绪的飞跃

到此为止,我们已经完成了从脑波原始信号到情绪预测结果的全流程。KNN 虽然简单,但通过 Canberra 距离 的加持和 智能投票 的优化,它成为了脑电识别入门的最佳切入点。

下一篇预告:

我们将跑通全链路实战,结合 OpenCV 实现预测结果的实时可视化------当算法识别出你很快乐时,屏幕上会自动弹出一个笑脸。

💡 思考题:

如果我们将 K 值从 3 增加到 10,准确率会发生什么变化?(提示:考虑过拟合与欠拟合的平衡)。欢迎在评论区留下你的见解!


系列回顾:

文章标签: #脑机接口 #机器学习 #KNN #Canberra距离 #情绪识别 #Python实战

相关推荐
创业之路&下一个五年22 分钟前
以教为学:在赋能他人中完成自我跃升
机器学习·自然语言处理·数据挖掘
机 _ 长39 分钟前
YOLO26 改进 | 训练策略 | 知识蒸馏 (Response + Feature + Relation)
python·深度学习·yolo·目标检测·机器学习·计算机视觉
szcsun51 小时前
机器学习(二)-线性回归实战
人工智能·机器学习·线性回归
力学与人工智能2 小时前
“高雷诺数湍流数据库的构建及湍流机器学习集成研究”湍流重大研究计划集成项目顺利结题
数据库·人工智能·机器学习·高雷诺数·湍流·重大研究计划·项目结题
康谋自动驾驶3 小时前
高校自动驾驶研究新基建:“实测 - 仿真” 一体化数据采集与验证平台
人工智能·机器学习·自动驾驶·科研·数据采集·时间同步·仿真平台
砚边数影3 小时前
决策树实战:基于 KingbaseES 的鸢尾花分类 —— 模型可视化输出
java·数据库·决策树·机器学习·分类·金仓数据库
_ziva_4 小时前
Layer Normalization 全解析:LLMs 训练稳定的核心密码
人工智能·机器学习·自然语言处理
轻览月4 小时前
【DL】卷积神经网络
深度学习·机器学习·cnn·卷积神经网络
逄逄不是胖胖4 小时前
《动手学深度学习》-55-1RNN的复杂实现
pytorch·深度学习·机器学习
砚边数影4 小时前
决策树原理(一):信息增益与特征选择 —— Java 实现 ID3 算法
java·数据库·决策树·机器学习·kingbase·数据库平替用金仓·金仓数据库