运动想象中共空间模式算法(CSP)的实现
运动想象中共空间模式算法(CSP)的实现
最近在研究运动想象算法,其中CSP来提取特征⽤的⽐较多,尤其是在⼆分类的问题中,之前写过⼀篇如何在MNE库中实现CSP算法的博客,⽤的是MNE库中已经写好的算法,现在想⾃⼰实现该算法,研究了⼏天发现坑还是⽐较多的。。。先列出⼀些参考的博客⽂章,⾥⾯有对应的算法在matlab中的实现,后⾯主要是解释算法中的⼀些细节以及⾃⼰对该算法的理解。强烈建议下载本博客的资源包对照着看,⾥⾯是整理好的博客中⽤到的资料。
CSP原理:
CSP在Python MNE库中的实现
matlab代码实现:
上⾯既然都有实现好的版本了,本着拿来主义的思想本来不打算⾃⼰开发的,但是考虑到后⾯需要⽀持多种编程语⾔的实现,以及验证算法的准确性,我在python中也实现了⼀遍,并尝试理解每⼀条语句的意义,及其对应的原理。不弄不知道啊,⼀弄发现了很多有趣的细节。
⼀句话总结CSP算法:共空间模式算法的基本原理是利⽤矩阵的对⾓化。到⼀组最优空间滤波器进⾏投影,使两类信号的⽅差差异化最⼤,从⽽得到具有较⾼区分度的特征向量。
上⾯所说的特征向量也就相当于滤波器,输⼊数据经过和特征向量的运算就会得到最⼤差异化⽅差的信号,这个信号我理解为是“原始波形”,测量结果=原始波形 * 电极位置,这⼀点在后⾯会详细解释。
算法的实现原理在前⾯的博客中都有所介绍,希望⼤家能对照着看,公式的推导这⾥就不再赘述,下⾯主要说⼀下对应的代码实现中遇到的问题。
问题1 求协⽅差矩阵
类似教父的电影所有的资料第⼀步都是求对应数据的协⽅差矩阵,其对应的计算公式为
那为什么在这⾥会这么计算呢?对⾏计算这个问题好解释,因为脑波数据⼀般都是按⾏存储的,这就是转置的问题。可是为什么它不⽤减去均值,并且也没有求平均。这个问题困扰了我好久,最后在⼀篇⽂献中到了想要的答案。
《Designing optimal spatial filters for single-trial EEG classification in a movement task》⽂章的796页有如下两段话。
第⼀段话主要的意思是说,EEG数据是滤波后的,均值为零,看到这恍然⼤悟,滤波后的数据没有直频分量,均值那可不就是零么,那也就不⽤减均值了。
第⼆段话主要的意思是说,正则化是为了消除不同实验对值的影响,所以使⽤的是迹。
问题2 特征值排序获取⽩化矩阵
排序是为了到影响⼤的特征向量这个好理解,在⽂章《Multiclass Common Spatial Pattern for EEG based Brain Computer Interface with Adaptive Learning Classifier》中第3页有提到这个步骤。
上⽂提到的matlab代码中有⼀个⼩问题,代码中直接对特征值进⾏了排序,我个⼈的理解是应该对特征值的绝对值排序,因为特征值有可能出现负值的。
问题3 为什么最后提取的特征值是和⽅差有关的⼀个量
提取特征的计算公式如下,可为什么是⽅差呢?
这个问题在《Optimizing spatial filters for robust EEG single-trial analysis》⼀⽂中有所解释,⽂章的第4页有如下⼀段话,⼤致的意思是说带通滤波后的信号⽅差和能量有关,虽然还是不太理解,不过总算到⼀些理论依据了。
在上⾯提到的matlab代码中,在提取特征的时候,还对⽅差求了⼀个log:
我想作者可能是借鉴了《Multiclass Common Spatial Pattern for EEG based Brain Computer Interface with Adaptive Learning Classifier》这篇⽂章,⽂章第3页中有如下公式:
matlab代码的Python实现
⾄此流程上算是理解了,参考matlab中的实现,实现了该算法的python版,为了对⽐计算结果,保留了特征值排序的问题,相当于matlab 代码中⼀⽐⼀的实现。
EEG_Channels = trainData.shape[1]
EEG_Trials = trainData.shape[0]
classLabels = np.unique(trainLabels)
EEG_Classes = len(classLabels)
covMatrix = list(range(EEG_Classes))
trialCov = np.zeros([EEG_Channels, EEG_Channels, EEG_Trials])
for i in range(EEG_Trials):
E = trainData[i]
EE = np.dot(E, E.T)
trialCov[:, :, i] = ace(EE)
for i in range(EEG_Classes):
covMatrix[i] = np.mean(trialCov[:, :, trainLabels == classLabels[i]], 2)
print('a' ,covMatrix[0])
print(covMatrix[1])
covTotal = covMatrix[0] + covMatrix[1]
>####特征值降序
eigenvalues, featurevectors = np.linalg.eig(covTotal)
egIndex = np.argsort(eigenvalues)[::-1]
eigenvalues = np.sort(eigenvalues)[::-1]
Ut = featurevectors[:, egIndex]
# 矩阵⽩化
P = np.dot(np.diag(np.sqrt(1/eigenvalues)), Ut.T)
# 矩阵P作⽤求公共特征向量transformedCov1
transformedCov1 = P.dot(covMatrix[0]).dot(P.T)
# 计算公共特征向量transformedCov1的特征向量和特征矩阵eigenvalues, featurevectors = np.linalg.eig(transformedCov1) egIndex = np.argsort(eigenvalues)[::-1]
eigenvalues = np.sort(eigenvalues)[::-1]
U1 = featurevectors[:, egIndex]
# 计算投影矩阵W
CSPMatrix = U1.T.dot(P)
炖牛肉怎么做好吃
# 计算特征矩阵
FilterPairs = 2
踏的拼音和组词feature_train = np.zeros([EEG_Trials, 2*FilterPairs+1])
feature_test = np.zeros([EEG_Trials, 2*FilterPairs+1])
Filter = np.r_[CSPMatrix[:FilterPairs], CSPMatrix[-FilterPairs:]]
小学教师述职#从每⼀次实验中提取CSP特征
无抵押无担保贷款for t in range(EEG_Trials):
# 将数据投影到CSP空间
projectedTrial_train = Filter.dot(trainData[t])
projectedTrial_test = Filter.dot(trainData[t])
# 投影后信号的⽅差作为特征
variances_train = np.var(projectedTrial_train, 1)
variances_test = np.var(projectedTrial_test, 1)
for f in range(len(variances_train)):
feature_train[t, f] = np.log(variances_train[f])
for f in range(len(variances_test)):
feature_test[t, f] = np.log(variances_test[f])
CSP_Train_faetures = feature_train[:, 0:4]
CSP_Test_features = feature_test[:, 0:4]
与Python中MNE库的对⽐
到⽬前为⽌算法算是已经实现了,可是这么做对不对呢,MNE库中有写好的CSP算法,对⽐⼀下看看结果。不⽐不知道啊,⼀⽐呵呵了,结果完全不⼀样啊,只好查看MNE库的源码看看了。主要的计算流程在csp.py中的fit函数中,这⾥截取其中的部分代码进⾏解释说明。
在MNE库中第⼀步也是求协⽅差矩阵,这⾥有两种计算⽅式“concact”和“epoch”,concact是拼接后再求⽅差。
对应上⾯的程序,相当于使⽤的是epoch⽅法,
可是这个协⽅差的计算看起来也很诡异啊,_regularized_covariance是什么⿁,python中有cov函数啊,可是为什么这⾥使⽤的却是另⼀个函数呢?跳转代码瞅瞅,原来使⽤的不是标准的协⽅差计算公式啊。
继续追踪,跳转到了_compute_covariance_auto函数,在这个函数中有很多协⽅差的计算⽅法,涨知识了协⽅差还有这么多计算的道道,原来这叫经验协⽅差。上⾯的注释中说是使⽤sklearn中的计算⽅式,还真特么有。。。。
好吧,不纠结了怎么说这也算是协⽅差,可以接受,继续往下看,看到这部分多少有些安⼼了,MNE中也提供了利⽤迹进⾏正则化的⽅法,看来总体的思路没错。
下⾯就是求特征值和特征向量了,这⾥使⽤了abs绝对值,也对应了我上⾯说的特征值排序应该取绝对值。这⾥为什么-0.5就不清楚了。特征提取采⽤的矩阵相乘,这点前⾯也解释过,滤波后的数据求协⽅差不需要减去均值,这⾥⽤的也是协⽅差(能量)的均值作为特征。
不知道⼤家发现没有这⾥少了⼀个步骤就是⽩化处理,这⼀点还没有没想明⽩?难道就是因为它⽤的协⽅差计算⽅法⽐较⽜,并且特征值减去了0.5就不⽤⽩化了么?⽜⽪就是任性啊。。。
patterns和filter的理解
参考说⼀下个⼈对这两个参数的理解,测得的数据经过filter滤波后的结果相当于是得到了原始波,⽽patterns就是源分布信息。
如何出国打工
原始波 * 源位置 = 测得的数据
《Optimizing spatial filters for robust EEG single-trial analysis》
《Designing optimal spatial filters for single-trial EEG classification in a movement task》

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。

发表评论