deap软件结果分析_使用DEAP基于K-means的情感计算

本文通过DEAP数据集进行情感分析,采用K-means算法将数据分为四类。分析了算法的实现细节,包括距离计算方法和初始化点选择的影响。实验结果显示,虽然准确率为54%,但因数据不平衡,实际效果不理想。提出了改进方案,如考虑降维和优化初始点选择,以提高算法性能。
摘要由CSDN通过智能技术生成

DEAP数据集是一个基于主要基于脑电信号的可用于做情绪分析的数据集。数据集是由data和label两类数据组成的。data的结构是40*40*8064(刺激* 通道*数据),值得说明的是通道中只有前32个通道是脑电信号。label的结构是40*40*4,前两个40分别是刺激源和通道,后一个4是valence,arousal,dominance,liking。

我在data数据中选择了前22个人的全部40种刺激的32个脑电通道数据,label数据中,提取前22个人的全部40种刺激对应的vlaence和arousal的label,并且依据V_A两维高低的两两组合,以4为阀值,将其分成四个类。

下面介绍我使用的K-means算法。

设原始数据为{x1,x2,...,xn},四类的中心位置是{u1,u2,u3,u4},xn和uk都是向量。

迭代公式是:

公式一:求出所有数据和初始化的随机数据的距离,然后找出距离每个初始数据最近的数据。在我的算法中,距离的定义是对应项作差后取绝对值求和。

公式二:求出所有和这个初始数据最近原始数据的距离的均值。

迭代结束是按次数来的

下面是源码

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%                                     %%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%    使用DEAP基于K-means的情感计算    %%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%                                     %%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
clear all;
close all;
clc;

% % % %载入数据
raw(1) = load('s01.mat');
raw(2) = load('s02.mat');
raw(3) = load('s03.mat');
raw(4) = load('s04.mat');
raw(5) = load('s05.mat');
raw(6) = load('s06.mat');
raw(7) = load('s07.mat');
raw(8) = load('s08.mat');
raw(9) = load('s09.mat');
raw(10) = load('s10.mat');
raw(11) = load('s11.mat');
raw(12) = load('s12.mat');
raw(13) = load('s13.mat');
raw(14) = load('s14.mat');
raw(15) = load('s15.mat');
raw(16) = load('s16.mat');
raw(17) = load('s17.mat');
raw(18) = load('s18.mat');
raw(19) = load('s19.mat');
raw(20) = load('s20.mat');
raw(21) = load('s21.mat');
raw(22) = load('s22.mat');


% % %对标签进行处理
lab = [];
for i = 1:22
    for j = 1:40
        if raw(i).labels(j,1) >= 4 && raw(i).labels(j,2) >= 4
            lab = [lab;1];
        elseif raw(i).labels(j,1) >= 4 && raw(i).labels(j,2) < 4
            lab = [lab;2];
        elseif raw(i).labels(j,1) < 4 && raw(i).labels(j,2) < 4
            lab = [lab;3];
        else
            lab = [lab;4];
        end
    end
end

dlmwrite('label.txt',lab,'delimiter','n');

% % %对数据整形进行处理
data = [];
for i = 1:22
    for j = 1:40
        for k = 1:32
            pre(k,:) = raw(i).data(j,k,:);
        end
        [sx sy] = size(pre);
        xy = sx * sy;
        data = [data;reshape(pre,1,xy)];
   end
end

[m n]=size(data);

% % %k-means聚类
[u re]=KMeans(data,4);  
[m n]=size(re);

dlmwrite('KM.txt',re,'delimiter','t');

% % %判断对错
sxy = xy + 1;
right = zeros(1,24);
wrong = zeros(1,24);

ji = 1;

for z = 1:4
    for x = 1:4
        for c = 1:4
            for v = 1:4
                if z == x || z == c || z == v || x == c || x == v || c == v
                    continue;
                else
                    for i = 1:m
                        if (re(i,sxy) == 1 && lab(i) == z) || (re(i,sxy) == 2 && lab(i) == x) || (re(i,sxy) == 3 && lab(i) == c) || (re(i,sxy) == 4 && lab(i) == v)
                            right(ji) = right(ji) + 1;
                        else
                            wrong(ji) = wrong(ji) + 1;
                        end
                    end
                    ji = ji + 1;
                end
            end
        end
    end
end

dlmwrite('right.txt',right,'delimiter','n');
dlmwrite('wrong.txt',wrong,'delimiter','n');

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%                                     %%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%               K-means               %%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%                                     %%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%N是数据一共分多少类
%data是输入的不带分类标号的数据
%u是每一类的中心
%re是返回的带分类标号的数据

function [u re]=KMeans(data,N)

    %%%数据相关信息获取
    [m n]=size(data);   %m是数据个数,n是数据维数
    ma=zeros(n,1);        %每一维最大的数
    mi=zeros(n,1);        %每一维最小的数
    u=zeros(N,n);       %随机初始化,最终迭代到每一类的中心位置
    
    for i = 1:n
        ma(i)=max(data(:,i));   
        mi(i)=min(data(:,i));    
    end
    
    %%%为保证初始随机点不是太糟糕
    count = 0;
    quan = zeros(m,N);
    while sum(quan(:,1)) == 0 || sum(quan(:,2)) == 0 || sum(quan(:,3)) == 0 || sum(quan(:,4)) == 0
        for i=1:n
           for j=1:N
                u(j,i)=ma(i)+(mi(i)-ma(i))*rand();  %随机初始化
           end      
        end

        for i=1:N
            tmp{i}=[];      
            for j=1:m
                tmp{i}=[tmp{i};data(j,:)-u(i,:)];
            end
        end
        
        for i=1:m        
            c=[];
            for j=1:N
                c=[c sum(abs(tmp{j}(i,:)))];
            end
            [junk index]=min(c);
            quan(i,index)=sum(abs(tmp{index}(i,:)));
        end
        
        count
        count = count + 1;
        
        for i = 1:4
            sum(quan(:,i))
        end
        
    end

    
    
    
    loop = 1;
    while 1
        pre_u=u;            
        for i=1:N
            tmp{i}=[];     
            for j=1:m
                tmp{i}=[tmp{i};data(j,:)-u(i,:)];
            end
        end
        
        %%%公式一的实现
        quan = zeros(m,N);
        for i=1:m        
            c=[];
            for j=1:N
                c=[c sum(abs(tmp{j}(i,:)))]; %两种距离定义方式
%                 c=[c norm(tmp{j}(i,:))];
            end
            [junk index]=min(c);
            quan(i,index)=sum(abs(tmp{index}(i,:)));
%             quan(i,index)=norm(tmp{index}(i,:)); 
        end              
        
        %%%公式二的实现
        for i=1:N            
           for j=1:n
                u(i,j)=sum(quan(:,i).*data(:,j))/(sum(quan(:,i) + eps));
           end           
        end
        
        loop
        loop = loop + 1;
        
        for i = 1:4
            u(i)
        end
        
        if loop > 0 
            break;
        end
    end
    
    re=[];
    for i=1:m
        tmp=[];
        for j=1:N
            tmp=[tmp norm(data(i,:)-u(j,:))];
        end
        [junk index]=min(tmp);
        re=[re;data(i,:) index];
    end
    
end

跑完下来总结:

在代码编写技巧方面:

1、在Matlab中,有分母存在时,在分母项加上eps。

2、在代码中要让中间结果,和迭代进度输出,以备及时发现问题,避免浪费时间。

在算法评估方面:

1、如果以准确率作为评价标准,那么这次的准确率在54%,值得高兴。但是如果仔细分析这个结果会发现并不乐观,因为其错分率在46%,原因如下。

原来880个数据样本在4类数据的分布是:464,161,78,171;

而K-means跑下来给出的4类数据的分布是:875,2,1,2;

因为K-means只是按照距离分四类,而不是按照V_A两维高低来分四类,因此如果按照最佳的准确率的配对,则是上述结果。其实也最有可能是是上述结果。原因在于数据源本身不平衡,而现在所有的统计学习方法中对解决数据不平衡问题尚无很好的方法,可能解决这个问题的比较火热的方法是强化学习和对抗生成网络。

2、在本次实验中,所用的距离的定义可以继续考究。在本次实验中我所使用的是最为简单的,可以说是欧式距离的方法,甚至由于一开始发现如果对距离取平方再开放,那么在258048维的数据的背景下,数据量太大了。所以后来改用作差取绝对值求和。在这一点上可以考虑一下降维后再做处理。而在降维的方法中,我觉得可以考虑流型的降维方法。

3、因为这个代码前后跑了五次,前后跑了两个星期,除了由于我自己之前没有让输出中间过程与迭代进度导致我没有及时发现算法有问题而浪费了时间之外,算法本身也存在几个问题值得总结教训,

a.首先是初始点的选取,初始点的选取真的是极其重要,首先是点不能全数域取,而是要在各维的最值范围内取值,其次是要检验初始的四个点是不是都有属于各自的最近点。因为,我发现随机取四点,设为a,b,c,d,很可能发生在880个点中没有1个点距离d点最近,那么在后面的迭代中就会导致分母为零的情况发生(这也是我前面总结分母项要加上eps的原因),如果不及时制止就会导致这次的运算结果无效的后果。

而会导致这个这个原因我推测有两个方面,一个是由于数据集本身不平衡导致的,另一个可能是由于我按V_A高低组合分成四类不是很合理导致,当然这两个方面的原因也有相互交合的地方。

b.我所选取的这个数据体量在我的i5-3470(3.2GHZ),16G内存的配置下跑得并不快,24个小时大体上能迭代30次左右。而后来我发现,其实迭代10次之后,就没有变化不大了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值