随机森林分类(Random Forest Classification)

    其实,之前就接触过随机森林,但仅仅是用来做分类和回归。最近,因为要实现一个idea,想到用随机森林做ensemble learning才具体的来看其理论知识。随机森林主要是用到决策树的理论,也就是用决策树来对特征进行选择。而在特征选择的过程中用到的是熵的概念,其主要实现算法有ID3和C4.5.下面我们先来看看决策树。

    下面我们用一个例子具体的来说明


                                                     image

 

 

    我们要选取一个最好的特征来判断是否贷款,上面给出了年龄,工作,房子,信贷四种特征。如果一种特征具有更好的分类能力,或者说,按照这一特征将训练数据集分割成子集,使得各个子集是当前条件下最好的分类,我们就应该选择这个特征。对于这个问题,直观上是否有房子应该是最好的特征。但这也仅仅是从直观上判断,具体上来讲哪个特征最好了,这里我们引入一个概念-信息增益。

    假设X是一个取值无限的离散随机变量,其概率分布为:

image

    则其熵计算如下,这里我们把image定义为经验熵。

image

    由于熵只依赖X的分布,而与X的取值无关。所以,我们又把熵定义为:
                                                                                    image

    假设我们有两个随机变量x,y(generally,X denote the feature vectors,and Y denote labels)。其联合概率分布为:

image

    这里,假如给定一个X,要我们准确的判断其所属类别,也就是要准确的判断Y。很自然的,我们需要求解给定X下的条件熵:

image

    假设,特征A 对训练集D的信息增益为image,定义为集合D 的经验熵H(D)与特征A给定条件下D的经验熵H(D|A)之差,那么我们定义信息增益如下:

image

 

    一般的,我们把熵H(Y)与条件熵H(Y|X)只差定义为互信息,决策树中的信息增益就是训练数据集中的类与特征的互信息。下面给出计算信息增益的方法:

    image

                                                  image

                                                 image

    如果我们以信息增益为划分训练数据集的特征,存在于选择取值较多的特征的问题。这里我们使用信息增益比(information gain ratio),可以对这一问题进行校正。这是特征选择的另一准则。

image

    下面来介绍一下ID3算法,该算法的核心就是不断的利用信息增益准则选择特征,最终达到分类的目的。

image

image

    C4.5算法其实就是在ID3算法上做了一点的改动,把特征选择的方法改为用信息增益比来计算,而不用ID3中的计算信息增益的方法。其算法流程和ID3差不多,这里就不介绍了。下面来简单的谈一下决策树的剪枝问题,由于决策树是严格的按照一定的规则进行计算,过多的考虑了训练样本的正确性,所以这导致其容易过拟合。所以这里引入剪枝的概念,通过优化损失函数,减少模型的复杂性。具体算法过程可以看课本P-66~P-67页。

    下面我给出C4.5的matlab代码,改代码转自http://blog.csdn.net/ice110956/article/details/10049149

   1: function D = C4_5(train_features, train_targets, inc_node,test_features)
   2: %http://blog.csdn.net/ice110956/article/details/10049149
   3: % 1.train_features,为训练集; train_targets,为训练集标签;
   4: % inc_node为防止过拟合参数,表示样本数小于一定阈值结束递归,可设置为5-10;test_features为测试集。
   5: % 2.取消离散变量,上面说了,是因为我不知道如何处理Miss value的问题,至于影响,应该就是连贪心也算不上了吧,应该是一个理论上还过得去的处理方法。
   6: % 3.图怎么画?介绍几个画图软件:http://www.cnblogs.com/damonlan/archive/2012/03/29/2410301.html 
   7: % 决策树扩展篇:http://blog.csdn.net/ice110956/article/details/29175215 
   8:  
   9: [Ni, M]        = size(train_features); %输入向量为NI*M的矩阵,其中M表示训练样本个数,Ni为特征维数维数
  10: inc_node    = inc_node*M/100; 
  11:  
  12: disp('Building tree') 
  13: tree        = make_tree(train_features, train_targets, inc_node); 
  14:  
  15: %Make the decision region according to the tree %根据产生的数产生决策域
  16: disp('Building decision surface using the tree') 
  17: [n,m]=size(test_features);
  18: targets        = use_tree(test_features, 1:m, tree, unique(train_targets)); %target里包含了对应的测试样本分类所得的类别数
  19:  
  20: D           = targets; 
  21: %END 
  22:  
  23: function targets = use_tree(features, indices, tree,  Uc) %target里包含了对应的测试样本分类所得的类别
  24:  
  25:  
  26: targets = zeros(1, size(features,2)); %1*M的向量
  27:  
  28: if (tree.dim == 0) 
  29:    %Reached the end of the tree 
  30:    targets(indices) = tree.child; 
  31:    return %child里面包含了类别信息,indeces包含了测试样本中当前测试的样本索引
  32: end 
  33:          
  34:  
  35: dim = tree.dim; %当前节点的特征参数
  36: dims= 1:size(features,1); %dims为1-特征维数的向量
  37:  
  38:    %Discrete feature 
  39:    in                = indices(find(features(dim, indices) <= tree.split_loc)); %in为左子树在原矩阵的index
  40:    targets        = targets + use_tree(features(dims, :), in, tree.child_1, Uc); 
  41:    
  42:    in                = indices(find(features(dim, indices) >  tree.split_loc)); %in为右子树在原矩阵的index
  43:    targets        = targets + use_tree(features(dims, :), in, tree.child_2, Uc); 
  44: return 
  45:       
  46:  
  47: function tree = make_tree(features, targets, inc_node) 
  48:  
  49: [Ni, L]                        = size(features); 
  50: Uc                             = unique(targets); %UC表示类别数
  51: tree.dim                        = 0; %树的维度为0
  52: %tree.child(1:maxNbin)    = zeros(1,maxNbin); 
  53:  
  54: if isempty(features), %如果特征为空,退出
  55:    return 
  56: end 
  57:  
  58: %When to stop: If the dimension is one or the number of examples is small 
  59: if ((inc_node > L) | (L == 1) | (length(Uc) == 1)), %剩余训练集只剩一个,或太小,小于inc_node,或只剩一类,退出
  60:    H                    = hist(targets, length(Uc)); %返回类别数的直方图
  61:    [m, largest]     = max(H); %更大的一类,m为大的值,即个数,largest为位置,即类别的位置
  62:    tree.child         = Uc(largest); %直接返回其中更大的一类作为其类别
  63:    return
  64: end 
  65:  
  66: %Compute the node's I 
  67: %计算现有的信息量(经验熵)
  68: for i = 1:length(Uc), 
  69:     Pnode(i) = length(find(targets == Uc(i))) / L; 
  70: end 
  71: Inode = -sum(Pnode.*log(Pnode)/log(2)); 
  72:  
  73: %For each dimension, compute the gain ratio impurity 
  74: %This is done separately for discrete and continuous features 
  75: delta_Ib    = zeros(1, Ni); 
  76: S=[];
  77: for i = 1:Ni, 
  78:    data    = features(i,:); 
  79:    temp=unique(data); 
  80:       P    = zeros(length(Uc), 2); 
  81:        
  82:       %Sort the features 
  83:       [sorted_data, indices] = sort(data); 
  84:       sorted_targets = targets(indices); 
  85:        %结果为排序后的特征和类别
  86:       %Calculate the information for each possible split 
  87:       I    = zeros(1, L-1); 
  88:       
  89:       for j = 1:L-1, 
  90:          for k =1:length(Uc), 
  91:             P(k,1) = length(find(sorted_targets(1:j)         == Uc(k))); %p(1,1):小于第j个样本的b的个数,p(1,2):大于第j个样本的b的个数。
  92:             P(k,2) = length(find(sorted_targets(j+1:end) == Uc(k)));    %p(2,1):小于第j个样本的g的个数,p(1,2):大于第j个样本的g的个数。
  93:          end 
  94:          Ps        = sum(P)/L; %两个子树的权重 
  95:          temp1=[P(:,1)]; 
  96:          temp2=[P(:,2)]; 
  97:          fo=[Info(temp1),Info(temp2)];
  98:          %info    = sum(-P.*log(eps+P)/log(2)); %两个子树的I
  99:          I(j)    = Inode - sum(fo.*Ps);%信息增益    
 100:       end 
 101:       [delta_Ib(i), s] = max(I); 
 102:       S=[S,s];
 103:    
 104: end
 105:  
 106: %Find the dimension minimizing delta_Ib  
 107: %找到最大的划分方法
 108: [m, dim] = max(delta_Ib); %第dim维特征最好,最大信息增益为m
 109:  
 110: dims        = 1:Ni; 
 111: tree.dim = dim; 
 112:  
 113: %Split along the 'dim' dimension 
 114: %分裂树 
 115:    %Continuous feature 
 116:    [sorted_data, indices] = sort(features(dim,:)); 
 117:    %tree.split_loc        = split_loc(dim); 
 118:    %disp(tree.split_loc);
 119:    S(dim)
 120:    indices1=indices(1:S(dim))
 121:    indices2=indices(S(dim)+1:end)
 122:    tree.split_loc=sorted_data(S(dim))
 123:    tree.child_1        = make_tree(features(dims, indices1), targets(indices1), inc_node); 
 124:    tree.child_2        = make_tree(features(dims, indices2), targets(indices2), inc_node); 
 125: %D = C4_5_new(train_features, train_targets, inc_node);

    其实代码不难,下面我给出我的理解。

P50724-095915

    Here we split the data into two sets,with 300 training samples and 51 testing samples,each data is a 34-dimensional vector. Here, each dimension can  be regarded as a variable,with respect to a kind of “feature”.

    在这个决策树中,对每个节点我们计算它的信息增益比,如果信息增益比小于某个阈值。或者,节点包含的样本数小于18(自己设定),则结束递归。从上图中可以看出,从根节点出发(这个节点包含300个样本),第5维特征最好,所以用这个特征进行划分。得到左子树(57个样本全为“1”),右子树(包含243个样本)。所以左子树结束递归,接着计算右子树的特征,第27维特征最好。一直循环….

    最后我们得到这样的一个决策树,除了叶节点,中间节点都包含一个最佳分类的特征,和这个特征对应的特征值。每个叶节点包含一定数量的样本,叶节点的类别规定为多数样本对应的类别。得到了这样的一个决策树后,我们就可以对测试样本进行分类了。使用中间节点记录的特征对测试样本进行划分,直到测试样本划分到每个叶节点中。叶节点中样本的类别就是该测试样本的类别了。

posted on 2015-07-19 13:47  Kevin.Tu  阅读(16492)  评论(0编辑  收藏  举报