Python-EEG工具库MNE中文教程(10)-信号空间投影SSP数学原理

目录

  • projector(投影)和投影背景
  • 案例解释投影原理
    • 导入工具库
    • 什么是projector(投影)?
    • 计算正交平面
    • 使用SVD计算投影矩阵

本分享为脑机学习者Rose整理发表于公众号:脑机接口社区(微信号:Brain_Computer).QQ交流群:903290195

projector(投影)和投影背景

projector(投影)(简称proj),也称为信号空间投影(SSP),定义了应用于空间上的EEG或MEG数据的线性操作。

可以将该操作看做是一个矩阵乘法,通过将数据投影到较低维度的子空间来降低数据的秩。
这种投影算子可以同时应用于数据和正向运算,用于源定位。注意,可以使用这样的投影算子来完成EEG平均参考。
它存储在info[‘projs‘]中的测量信息中。

案例解释投影原理

导入工具库

import os
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D  # noqa
from scipy.linalg import svd
import mne

# 定义绘制3d图像
def setup_3d_axes():
    ax = plt.axes(projection='3d')
    ax.view_init(azim=-105, elev=20)
    ax.set_xlabel('x')
    ax.set_ylabel('y')
    ax.set_zlabel('z')
    ax.set_xlim(-1, 5)
    ax.set_ylim(-1, 5)
    ax.set_zlim(0, 5)
    return ax

什么是projector(投影)?

在最基本的术语中,投影是将一组点转换为另一组点的操作,在这些点上重复投影操作没有效果。
给一个简单的几何示例,请想象三维空间中的点(3,2,5)。
如果太阳在x,y平面正上方,则该点在x,y平面上的投影看起来很像该点投射的阴影:

ax = setup_3d_axes()

# 绘制向量(3, 2, 5)
origin = np.zeros((3, 1))
point = np.array([[3, 2, 5]]).T
vector = np.hstack([origin, point])
ax.plot(*vector, color='k')
ax.plot(*point, color='k', marker='o')

# 将向量投影到x,y平面上并将其绘制
xy_projection_matrix = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 0]])
projected_point = xy_projection_matrix @ point
projected_vector = xy_projection_matrix @ vector
ax.plot(*projected_vector, color='C0')
ax.plot(*projected_point, color='C0', marker='o')

# 添加显示投影的虚线箭头
arrow_coords = np.concatenate([point, projected_point - point]).flatten()
ax.quiver3D(*arrow_coords, length=0.96, arrow_length_ratio=0.1, color='C1',
            linewidth=1, linestyle='dashed')

注意,使用矩阵乘法来计算点(3,2,5)平面的投影:

再次将投影应用于结果,只会再次返回结果:

从信息的角度来看,此投影采用了点x,y,z,并删除了有关该点在z方向上位置的信息。现在我们所知道的只是它在x,y平面上的位置。此外,将投影矩阵应用于x,y,z空间中的任何点,都会将其缩小为x,y平面上的对应点。术语是子空间:投影矩阵将原始空间中的点投影到比原始空间低维的子空间中。我们的子空间是x,y平面(而不是y,z平面)的原因是投影矩阵中特定值的直接结果。

示例:投影作为降噪
描述这种“信息丢失”或“投影到子空间”的另一种方式是,投影将测量的秩(或“自由度”)从三维降低到二维。如果您知道z方向上的测量分量只是由于您的测量方法而产生的噪声,而您所关心的只是x和y分量,那么将三维测量投影到x,y平面中就可以看作是一种降噪的形式。

当然,如果所有测量噪声都集中在z方向上,那确实是非常幸运的。您可以直接舍弃z分量,而不必费心构造投影矩阵或进行矩阵乘法。假设为了进行该测量,您必须在测量设备上触动触发器(pull a trigger on a measurement device),并且触动触发器的动作会使设备移动一点。如果您测量触发器的触动是如何影响测量设备的位置,则可以"校正"实际测量值,以“投射”触动触发器的效果。在这里,我们假设触发器的平均效果是将测量设备移动(3,?1,1):

trigger_effect = np.array([[3, -1, 1]]).T

计算正交平面

知道了这一点,我们可以计算一个与触发器作用正交的平面(利用一个穿过原点的平面在给定法向量(A,B,C)的情况下具有方程Ax+By+Cz=0),并将实际测量投影到该平面上。

# 计算与trigger_effect正交的平面
x, y = np.meshgrid(np.linspace(-1, 5, 61), np.linspace(-1, 5, 61))
A, B, C = trigger_effect
z = (-A * x - B * y) / C
# 切断z=0以下的平面(只是为了使绘图更精细)
mask = np.where(z >= 0)
x = x[mask]
y = y[mask]
z = z[mask]

使用SVD计算投影矩阵

使用奇异值分解(SVD)从trigger_effect向量计算投影矩阵;
放置好投影矩阵后,我们可以投影原始向量(3,2,5)以消除触发器的影响,然后对其进行绘制:

# 计算投影矩阵
U, S, V = svd(trigger_effect, full_matrices=False)
trigger_projection_matrix = np.eye(3) - U @ U.T

# 将向量投影到正交平面上
projected_point = trigger_projection_matrix @ point
projected_vector = trigger_projection_matrix @ vector

# 绘制trigger_effect及其正交平面
ax = setup_3d_axes()
ax.plot_trisurf(x, y, z, color='C2', shade=False, alpha=0.25)
ax.quiver3D(*np.concatenate([origin, trigger_effect]).flatten(),
            arrow_length_ratio=0.1, color='C2', alpha=0.5)

# 绘制原始向量
ax.plot(*vector, color='k')
ax.plot(*point, color='k', marker='o')
offset = np.full((3, 1), 0.1)
ax.text(*(point + offset).flat, '({}, {}, {})'.format(*point.flat), color='k')

# 绘制投影向量
ax.plot(*projected_vector, color='C0')
ax.plot(*projected_point, color='C0', marker='o')
offset = np.full((3, 1), -0.2)
ax.text(*(projected_point + offset).flat,
        '({}, {}, {})'.format(*np.round(projected_point.flat, 2)),
        color='C0', horizontalalignment='right')

# 添加投影的虚线箭头
arrow_coords = np.concatenate([point, projected_point - point]).flatten()
ax.quiver3D(*arrow_coords, length=0.96, arrow_length_ratio=0.1,
            color='C1', linewidth=1, linestyle='dashed')

与以前一样,投影矩阵会将x,y,z空间中的任何点映射到该平面上,并且一旦某个点投影到该平面上,再次应用投影将不会产生任何效果。因此,很明显,尽管投影点在所有三个x、y和z方向上都有所不同,但是投影点集只有两个有效尺寸(即,它们被约束在一个平面上)。

EEG或MEG信号的投影几乎以相同的方式工作:点x,y,z对应于单个时间点上每个传感器的值,并且投影矩阵根据信号的哪些方面(比如,什么样的噪声)。唯一真正的区别是, 在实际案例中,要处理一系列N维“点”的时间序列(每次采样一个点),而不是单个三维点(x,y,z),其中N通常是几十个或几百个(取决于实验中EEG/MEG系统有多少个传感器)。

由于投影是矩阵运算,因此即使在具有数百个维度和数万个时间点的信号上也可以非常快速地完成投影。

参考:
信号空间投影SSP数学原理

脑机学习者Rose笔记分享,QQ交流群:903290195
更多分享,请关注公众号

原文地址:https://www.cnblogs.com/RoseVorchid/p/12057098.html

时间: 2024-07-30 20:20:52

Python-EEG工具库MNE中文教程(10)-信号空间投影SSP数学原理的相关文章

Python-EEG工具库MNE中文教程(9)-参考电极应用

目录 MNE-Python中的参考 引用简介 无需重新引用(No re-referencing) 平均参考(Average reference) 单电极(A single electrode) 多个电极的平均值(The mean of multiple electrodes) Python案例 @(目录) 本分享为脑机学习者Rose整理发表于公众号:脑机接口社区(微信号:Brain_Computer).QQ交流群:903290195 MNE-Python中的参考 MNE-Python中的平均参考

Expression Blend实例中文教程(10) - 缓冲动画快速入门Easing

随着Rich Internet application(RIA)应用技术的发展,各个公司越来越注重于项目的用户体验性,在保证其功能完善,运行稳定的基础上,绚丽的UI和人性化的操作设计会给用户带来舒适的体验效果.前文我们学习了Blend设计简单的动画,可以使用StoryBoard快速创建一个动画效果,但是该动画效果看起来缺乏自然效果,让用户感觉太过机械化,大大的降低了用户体验性.为了是动画更为人性化,看起来更自然化,我们可以通过以下两个方式来解决: 方法1. 使用前文所提及的,帧动画技术,为了是动

python私有工具库小结

1.一些试用py工具清单 https://www.zhihu.com/question/60402355/answer/752917744?utm_source=wechat_session&utm_medium=social&utm_oi=1081669345989529600&from=singlemessage 原文地址:https://www.cnblogs.com/andy9468/p/11865305.html

1001种玩法 | Python Prompt Toolkit:构建强大交互式命令行的 Python 工具库

Python Prompt Toolkit:构建强大交互式命令行的 Python 工具库 prompt_toolkit 是一个用于构建强大交互式命令行的 Python 工具库. 你是不是在找交互式的 Python shell 工具 ptpython 呢?我们把 ptpython 的源码转移到了一个独立的仓库.如此一来,我们确信  prompt_toolkit 库不会被其他 ptpython 东西"污染",并且 ptpython 也可以独立开发.现在必须用下面这个命令安装 ptpytho

Python 标准库 BaseHTTPServer 中文翻译

Python 标准库 BaseHTTPServer 中文翻译. 注意: BaseHTTPServer模块在Python3中已被合并到http.server,当转换你的资源为 Python3 时 2to3 工具将自己主动适配导入. 源代码:Lib/BaseHTTPServer.py 此模块定义了两个类用于实现HTTP服务器(Web servers).通常,此模块不被直接使用.可是它用来作为基类创建功能性的Web servers. 查看 SimpleHTTPServer 和 CGIHTTPServe

Python Kivy 中文教程:安装(Windows)

Kivy 是一套用于跨平台快速应用开发的开源框架,只需编写一套代码,便可运行于各大桌面及移动平台上(包括 Linux, Windows, OS X, Android, iOS, 以及 Raspberry Pi) Kivy 采用 Python 和 Cython  编写,在国外已经十分火爆,受关注程度甚至一度超越了老牌的 Python GUI 工具 PyQt.可惜 Kivy 在国内还鲜为人知,咪博士将会陆续推出一系列 Kivy 中文教程.这一篇先教大家,在 Windows 上 安装 Kivy. 零.

Python教程10

Python教程10 1.模块 说明:前4个文件代码块分别是 error.jun_03_module1 # -*-coding:utf-8-*- # 定义全局变量 title = "模块1" # 函数 def say_hello(): print("我shi %s" % title) # 类 class Dog(object): pass error.jun_03_module2 # 全局变量 title = "模块2" # 函数 def say

Python 必备好库 - 好工具收藏

apscheduler collections collections.OrderDict collections.defaultdict Python 标准库提供了 collections 模块.这个方便的附加组件可以为你提供更多数据类型. from collections import OrderedDict, Counter # Remembers the order the keys are added! x = OrderedDict(a=1, b=2, c=3) # Counts t

程序员用于机器学习编程的Python 数据处理库 pandas 入门教程

入门介绍 pandas适合于许多不同类型的数据,包括: · 具有异构类型列的表格数据,例如SQL表格或Excel数据 · 有序和无序(不一定是固定频率)时间序列数据. · 具有行列标签的任意矩阵数据(均匀类型或不同类型) · 任何其他形式的观测/统计数据集. 由于这是一个Python语言的软件包,因此需要你的机器上首先需要具备Python语言的环境.关于这一点,请自行在网络上搜索获取方法. 关于如何获取pandas请参阅官网上的说明:pandas Installation. 通常情况下,我们可以