考虑平局的投票分类器

在基础分类器中,除了最近邻的方法外,投票也是常用的一种方法。投票的原理是:每一个部分拥有一票或多票,根据一定的规则投给某一个类别,获得最多票数的类别是最终得到的类别。

基础算法

很多matlab的实现投票分类器的代码如下:

a=1:c; % c是类别数
for i=1:num
   h(i,:)=hist(index(i,:),a); % index是一个矩阵,每一个位置都有一个数字,在0到c之间
end
[~,ind]=max(h,[],2);

我一开始也是使用这种方法做的分类,但是老师问我,如果是2:2怎么办呢?在我的实验中,我已知的是一个距离矩阵,共有length(X_tst)行,length(X_trn) * num列,即有多少个测试样本就有多少行,而训练样本数 * 分块数就是列数。在这种情况下,当分块数太小时很有可能出现平局的局面,而以上的算法并没有考虑到这个局面,它只是在平局时简单粗暴地选择了较小的序号。

考虑到平局的算法

这个分类算法被我用于单样本人脸识别,因此代码可能不具有通用性,但是思想方法大体差别不大。

输入:距离矩阵D,共有length(X_tst)行,length(X_trn) * num列。前num列存放各个测试样本到训练图片1的num块的距离。
输出:分类得到的结果ind
流程:

  1. 对第$i$块,得到距离矩阵dt,表示测试样本到所有训练样本第$i$块的距离。从每个dt中得到一个最小距离向量和对应的索引向量。
  2. 将所有的距离向量连起来得到矩阵mindis,将所有的索引合起来得到矩阵index。
  3. 对每一块,用hist进行统计,并连起来。
  4. 求出每块中出现的最大次数times和对应的序号ind。
  5. 用sum和bsxfun函数一起判断有没有平局的出现。
  6. 对于出现平局的样本,找到平局中序号对应的最小距离,谁小测试样本就是那一类的。

比起使用for循环,matlab中更提倡矩阵的运算,所以一部分我是直接使用矩阵进行运算的。但是在处理平局时,我没有找到合适的函数。使用了两层for循环,对每一个测试样本,将距离排序,依次使用最小的距离,并判断最小的距离对应的序号是否在平局的序号中,如果不是再取第二小的,依次递推。

matlab代码

c=max(Y_trn); %类别数
num=size(d,2)/c; %每个图像有多少块
a=1:c;
index=[];
mindis=[];
for i=1:num
   dt=[];
   for j=1:c
      dt=[dt,d(:,num*(j-1)+i)];
   end
   [dis,ind]=min(dt,[],2);
   mindis=[mindis,dis];
   index=[index,ind];
end
for i=1:length(Y_tst)
   h(i,:)=hist(index(i,:),a);
end
[times,ind]=max(h,[],2); % times出现的最大次数, ind:出现的最大次数对应的序号
bf=bsxfun(@eq,h,times);
s=sum(bf,2);% 最大次数出现了几次
fd=find(s~=1); % 找到出现平局的情况
[~, id]=sort(mindis,2);
for i=1:length(fd)
   for j=1:num
      if bf(fd(i),index(fd(i),id(fd(i),j)))==1
         ind(fd(i))=index(fd(i),id(fd(i),j));
         break;
      end
   end
end