EEG上k-means的一次实验

    xiaoxiao2023-11-20  187

    EEG上k-means的一次实验

    我们尝试在EEG上进行最简单的k_means聚类并分析乐聚类结果和如若要进行下一步的研究所需要的特征提取。使用的是DEAP数据库

    数据读取

    data=np.loadtxt("/Users/rain/Downloads/EEG/DEAP/EEG_feature.txt") #我们读入所有的可能的 label1=np.loadtxt("/Users/rain/Downloads/EEG/DEAP/valence_arousal_label.txt") label2=np.loadtxt("/Users/rain/Downloads/EEG/DEAP/subject_video.txt")

    计算欧式距离

    def distEclud(x,y): return np.sqrt(np.sum((x-y)**2))

    产生随机的聚类中心

    def randCent(dataSet,k): m,n = dataSet.shape #先将中心全置为0 centroids = np.zeros((k,n)) for i in range(k): index = int(np.random.uniform(0,m)) #随机生成中心 centroids[i,:] = dataSet[index,:] return centroids

    进行聚类

    def KMeans(dataSet,k): m = np.shape(dataSet)[0] #行的数目 # 第一列存样本属于哪一簇 # 第二列存样本的到簇的中心点的误差 clusterAssment = np.mat(np.zeros((m,2))) clusterChange = True # 第1步 初始化centroids centroids = randCent(dataSet,k) while clusterChange: clusterChange = False # 遍历所有的样本(行数) for i in range(m): minDist = 100000.0 minIndex = -1 # 遍历所有的聚类中心 #第2步 找出最近的聚类中心 for j in range(k): # 计算该样本到质心的欧式距离 distance = distEclud(centroids[j,:],dataSet[i,:]) if distance < minDist: minDist = distance minIndex = j # 第 3 步:更新每一行样本所属的类 if clusterAssment[i,0] != minIndex: clusterChange = True clusterAssment[i,:] = minIndex,minDist**2 #第 4 步:更新聚类中心 for j in range(k): pointsInCluster = dataSet[np.nonzero(clusterAssment[:,0].A == j)[0]] # 获取类所有的点 centroids[j,:] = np.mean(pointsInCluster,axis=0) # 对矩阵的行求均值 print("Cluster complete!") #返回聚类中心和聚类结果(包括分类和最小距离) return centroids,clusterAssment

    进行k-means分类 对k=2进行聚类

    k=2 centroids,clusterAssment = KMeans(data,k) kind=clusterAssment[:,0:1] kind=np.reshape(kind,-1) kind kind[0,0:100] matrix([[0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0., 0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0., 0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0., 0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,1.,1.,0., 0.,0.,0.,0.,0.,0.,0.,0.,0.,1.,0.,0.,0.,0.,0.,0., 0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,0., 0., 0., 0., 0.]]) np.transpose(label1)[0,0:100] array([1.,2.,1.,1.,2.,1.,2.,2.,2.,1.,2.,2.,1.,2.,2.,2.,2., 1.,2.,2.,2.,1.,1.,2.,2.,1.,1.,2.,1.,1.,2.,2.,1.,1., 1.,1.,2.,1.,2.,2.,2.,2.,2.,2.,1.,1.,2.,1.,1.,2.,2., 2.,1.,1.,1.,1.,1.,1.,1.,1.,2.,1.,1.,2.,1.,1.,2.,1., 1.,1.,1.,1.,1.,2.,2.,1.,1.,1.,2.,2.,1.,1.,2.,2.,2., 1.,1.,2.,2.,2.,1.,1.,1.,1.,1.,2.,1.,2.,1.,2.]) np.transpose(label1)[1,0:100] array([2.,1.,1.,1.,1.,1.,1.,2.,2.,2.,2.,1.,2.,1.,1.,1.,2., 1.,2.,2.,2.,1.,2.,1.,2.,1.,1.,2.,2.,1.,1.,1.,1.,1., 1.,2.,2.,1.,1.,2.,1.,1.,1.,1.,1.,1.,1.,1.,1.,2.,1., 2.,2.,1.,1.,1.,2.,2.,1.,1.,2.,2.,1.,2.,1.,1.,2.,2., 2.,1.,1.,2.,1.,2.,2.,1.,2.,2.,2.,2.,2.,2.,2.,2.,2., 2.,2.,1.,1.,1.,2.,2.,2.,1.,2.,2.,2.,2.,2.,1.])

    可以直观的看出不论用哪种label分类或是两个label结合的准确性均不高 对k=4进行聚类

    matrix([[2.,2.,2.,2.,2.,2.,2.,1.,2.,2.,2.,2.,1.,1.,1.,2., 1.,1.,1.,1.,2.,2.,1.,1.,1.,2.,1.,2.,1.,1.,1.,1., 1.,2.,2.,1.,1.,0.,1.,1.,1.,1.,1.,2.,1.,1.,1.,1., 1.,1.,1.,1.,1.,1.,2.,1.,1.,1.,1.,1.,1.,1.,1.,1., 1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,1.,2.,2.,2.,2., 2.,2.,2.,2.,2.,2.,2.,2.,2.,2.,2.,2.,2.,2.,2.,2., 2.,2.,2.,2.]])

    同样可以看出聚类与label不符合 对k=38(视频数量)进行聚类

    kind matrix([[29., 29., 29., ..., 29., 29., 18.], [37., 37., 37., ..., 37., 37., 37.], [27., 27., 27., ..., 27., 27., 27.], ..., [ 4., 4., 4., ..., 4., 15., 15.], [ 6., 6., 6., ..., 6., 6., 6.], [ 8., 8., 8., ..., 8., 8., 8.]]) np.reshape(np.transpose(label2)[1],[32,38]) array([[ 5., 4., 24., ..., 23., 9., 26.], [27., 35., 31., ..., 34., 10., 16.], [16., 6., 25., ..., 28., 24., 3.], ..., [24., 25., 13., ..., 27., 38., 31.], [19., 13., 34., ..., 15., 12., 14.], [28., 32., 14., ..., 3., 25., 10.]])

    可以看出完全不符合 对k=32(被试者数量)进行聚类

    k=32 centroids,clusterAssment = KMeans(dataSet,k) kind=clusterAssment[:,0:1] kind=np.reshape(kind,[32,38]) #为了比较方便我们对kind做变换 from scipy import stats most=stats.mode(np.transpose(kind))[0] kind2=np.zeros((32,38)) for i in range(32): for j in range(38): kind2[i,j]=kind[i,j]-most[:,i]+i+1 kind2=np.reshape(kind2,[-1]) train_label2=np.reshape(train_label2,[-1]) print(np.mean(label2==kind2))

    我们输出kind得到

    matrix([[12., 12., 12., ..., 12., 12., 20.], [18., 18., 18., ..., 18., 18., 18.], [ 7., 7., 7., ..., 7., 7., 7.], ..., [26., 26., 26., ..., 26., 26., 26.], [24., 24., 24., ..., 24., 24., 24.], [ 2., 2., 2., ..., 2., 2., 2.]])

    可以看到每一行的基本都被分为同一类,由于类与被试者标号没有严格的对应关系。我们对此做不严谨的分析,对kind矩阵将其每行的众数当成分类正确的,其余少数的当成分类错误的

    from scipy import stats most=stats.mode(np.transpose(kind))[0] kind2=np.zeros((32,38)) for i in range(32): for j in range(38): kind2[i,j]=kind[i,j]-most[:,i]+i+1 kind2 kind2=np.reshape(kind2,[-1]) lab=label2[:,0:1] lab=np.reshape(lab,[-1]) print(np.mean(lab==kind2))

    我们运行100次进行分析

    统计量Valuemean0.7677sd0.1142min0.5411max1.0

    虽然这样的值并不是准确率(因为有少数的两个被试者的多数数据会被分到同一个类中),但我们仍然可以从中看出被试者对于该问题的直接聚类有非常大的影响,并且通过适当地选择聚类中心我们能非常好地进行聚类。

    本次实验的结果很好地解释了上次的CNN网络在该数据集上得分较低的原因:被试者的影响过大,虽然上次试验中尝试通过中心化的方法来减少该影响,但效果并不明显。结合图像我们给出了数据预处理或者特征提取应该适应的一些条件(针对对其他label聚类)

    所有的EEG数据图 视频号1和2的EEG图 从图中可以看出不做变换我们难以区分1和2 其中4个被试者的EEG图 我们可以看出不同的人的EEG可能有显著的差别,这也印证了我们的结果,并且可以看出不同的数据中峰值的位置可能也是不同的尤其可以从64左右的数据看出

    我们可以考虑做差分 虽然差分后从图中看被试者的影响被很大地消除,差分后的聚类效果仍不好,且仍与被试者标号高度相关 尝试标准化和中心化 发现仍没有很好地消除被试者的影响

    因此要将五个级分开去除被试者的影响,我们除了差分还尝试了标准化、最大值、最小值、取值范围、方差、均值等,都没有很好地结果。可能需要提取更为复杂的特征,如峰度等来进行其他label的聚类

    最新回复(0)