Chimerge算法与matlab代码实现(数据离散化)
1、算法分析
(卡方检验)
是统计样本的实际观测值与理论推断值之间的偏离程度,实际观测值与理论推断值之间的偏离程度就决定卡方值的大小,如果卡方值大则偏差大,反之,二者偏差小;若两个值相等,则卡方值为0。
χ
2
=
∑
i
=
1
m
∑
j
=
1
k
(
A
i
j
−
E
i
j
)
2
E
i
j
\chi^2=\sum_{i=1}^m\sum_{j=1}^k{(A_{ij}-E_{ij})^2\over E_{ij}}
χ2=i=1∑mj=1∑kEij(Aij−Eij)2
假设比较iris中第1个属性中两个属性值的卡方:
属性值 | 第一个类 | 第二个类 | 第三个类 |
---|---|---|---|
4.3 | 16 | 0 | 0 |
4.9 | 4 | 1 | 1 |
表中数据 16 16 16表示iris数据集中第一个属性的属性值为4.3且实例标签为1的实例数量
由于是比较相邻的两个区间之间的卡方
m
m
m的值为2
k
k
k为每个数据集的类别数 (iris数据集的类别为3)
A
i
j
A_{ij}
Aij为实际的频数 第i个属性值(4.3或4.9) 标签为第j类的次数
R
i
R_{i}
Ri为第i个属性值出现的次数 ///以iris数据集为例(16+0+0)
C
j
C_j
Cj为第j个类别的总数 /// 以iris数据集为例(16+4)
N
N
N为上面所有的数据量 ///以iris数据集为例(16+0+0+4+1+1 )
E
i
j
E_{ij}
Eij为
A
i
j
A_{ij}
Aij期望值
R
i
∗
C
j
N
{R_i*C_j\over N}
NRi∗Cj
Chimerge算法主要依赖于卡方检验:将具有最小卡方值的相邻区间合并在一起,知道满足停止准则。
算法流程:
1)初始化:根据离散的属性值对实例进行排序 [第一个属性,实例标签]/[第二个属性,实例标签]/…[第i个属性,实例标签]划分出i组矩阵,对这i组矩阵的属性值排序
2)自底向上进行区间合并,当满足条件的时候,停止合并
(此处的满足条件有两类:第一个卡方值都是大于某个阈值;第二个是区间达到一定的数量则停止合并)
.根据上面的卡方公式计算相邻区间的卡方分布
.将卡方值最小的一对区间进行合并
2、Matlab代码
function [new_data,cut_point]=Chimerge(data,data_block);
[m,n]=size(data);
class=length(unique(data(:,1)));
cut_point=zeros(n-1,data_block);
new_data=zeros(m,n);
new_data(:,1)=data(:,1);
att_map=cell(n,1);
for i=2:n %遍历属性
pair_att_lable=[data(:,i),data(:,1)];
pair_att_lable=sortrows(pair_att_lable,1);
tmp_map=zeros(1,class+1);
inner=1;
for j=1:m
num=pair_att_lable(j,1);
loc=find(tmp_map(:,1)==num);
if isempty(loc)
tmp_map(inner,1)=num;
tmp_map(inner,pair_att_lable(j,2)+1)=tmp_map(inner,pair_att_lable(j,2)+1)+1;
inner=inner+1;
else
tmp_map(loc,pair_att_lable(j,2)+1)=tmp_map(loc,pair_att_lable(j,2)+1)+1;
end
clear loc; %清除loc变量
end
att_map{i}=tmp_map;
clear num pair_att_lable tmp_map inner loc
end
clear num pair_att_lable tmp_map inner loc
for i=2:n
temp_data=att_map{i};
corrent_interval=length(temp_data(:,1));
while corrent_interval>data_block
chi2_mat=zeros(corrent_interval-1,1);
for j=1:corrent_interval-1
chi2=chi2test(temp_data(j,2:end),temp_data(j+1,2:end));
chi2_mat(j)=chi2;
end
[minv,index]=min(chi2_mat); %寻找最小的卡方值
merge_loc_1=index;
merge_loc_2=index+1;
temp_data(merge_loc_1,2:end)=temp_data(merge_loc_1,2:end)+temp_data(merge_loc_2,2:end); %数据合并
temp_data(merge_loc_2,:)=[];
corrent_interval=corrent_interval-1;
end
%------------------------------------------获取分割点
cut_point(i-1,:)=temp_data(:,1);
%------------------------------------------
%------------------------------------------
for j=1:m %遍历所有的实例
for k=1:data_block
if k~=data_block
if data(j,i)>=temp_data(k,1) && data(j,i)<temp_data(k+1,1) %temp_data是个一维列矩阵
new_data(j,i)=k;
break;
end
if data(j,i)<temp_data(1,1)
new_data(j,i)=1;
break;
end
else
if data(j,i)>=temp_data(k,1)
new_data(j,i)=k;
end
end
end
end
%-------------------------------------------
end
end
%此处为u v两个行向量求卡方分布
function chi2=chi2test(u,v)
len=length(u); %获取类别数量
N=sum(u)+sum(v); %获取总的实例数量
chi2=0; %将传递的参数进行初始化
box=[u;v]; %构造为一个两行的矩阵
for i=1:2
for j=1:len
Eij=sum(box(i,:))*sum(box(:,j))/N;
if Eij==0
tmp_chi=0;
else
tmp_chi=(box(i,j)-Eij)^2/Eij;
end
chi2=chi2+tmp_chi;
end
end
end
链接:https://download.csdn.net/download/weixin_44912943/19102941
该Chimerge.m下载文件中包含了上述代码的解析
若代码有误欢迎留言指出!
如有问题欢迎留言探讨!