第八课 决策树和随机森林

一、决策树原理概述

  • 决策树通过把样本实例从根节点排列到某个叶子节点来对其进行分类。 树上的每个非叶子节点代表对一个属性取值的测试,其分支就代表测试的每个结果;而树上的每个叶子节点均代表一个分类的类别, 树的最高层节点是根节点。
  • 简单地说, 决策树就是一个类似流程图的树形结构, 采用自顶向下的递归方式, 从树的根节点开始, 在它的内部节点上进行属性值的测试比较, 然后按照给定实例的属性值确定对应的分支, 最后在决策树的叶子节点得到结论。 这个过程在以新的节点为根的子树上重复。

在这里插入图片描述

决策树算法

1、ID3算法
熵定义:类别越多熵越大(越混乱)
在这里插入图片描述
信息熵就是一组数据包含的信息,概率的度量。一组数据越有序信息熵也就越低,极端时如果一组数据中只有一个非0,其它都是0,那么熵等于0,因为只有可能是这个非0的情况发生,它给人们的信息已经确定了,或者说不含有任何信息了,因为信息熵含量为0。一组数据越无序信息熵也就越高,极端时如果一组数据均匀分布,那么它的熵最大,因为我们不知道那种情况发生的概率大些。假如一组数据由{d1,d2,…,dn}构成,其和是sum,那么求信息熵的公式是:在这里插入图片描述
分类预测算法属于有指导学习,方法是通过训练数据,按照参考属性对目标属性的依赖程度对参考属性分级别处理,这种分级别处理体现在创建决策树,目的是通过生成的判别树,产生规则,用来判断以后的数据。以如下数据为例:
在这里插入图片描述
共14条记录,目标属性是,是否买电脑,共有两个情况,yes或者no。参考属性有4种情况,分别是,age,income,student,credit_rating。属性age有3种取值情况,分别是,youth,middle_aged,senior,属性income有3种取值情况,分别是,high,medium,low,属性student有2种取值情况,分别是,no,yes,属性credit_rating有2种取值情况,分别是fair,excellent。
1、我们先求参考属性的信息熵:参考属性=class:buy-computer
在这里插入图片描述
式中的5表示5个no,9表示9个yes,14是总的记录数
2、接下来我们求各个参考属性在取各自的值对应目标属性的信息熵,以属性age为例,有3种取值情况,分别是youth,middle_aged,senior,先考虑youth,youth共出现5次,3次no,2次yes,于是信息熵:
在这里插入图片描述
类似得到middle_aged和senior的信息熵,分别是:0和0.971。整个属性age的信息熵应该是它们的加权平均值
在这里插入图片描述
信息增益:
在这里插入图片描述
下面引入信息增益(information gain)这个概念,用Gain(D)表示,该概念是指信息熵的有效减少量,该量越高,表明目标属性在该参考属性那失去的信息熵越多,那么该属性越应该在决策树的上层(如果不好理解,可以用极限的方法,即假如在age属性上,当为youth时全部是on,当为middle时也全部是no,当为senior时全部是yes,那么Hage(D)=0)。
在这里插入图片描述
类似可以求出Gain(income)=0.029,Gain(stduent)=0.151,Gain(credit_rating)=0.048。**最大值为Gain(age),**所以首先按照参考属性age,将数据分为3类,如下:
在这里插入图片描述
然后分别按照上面的方法递归的分类。递归终止的条件是,1,当分到某类时,目标属性全是一个值,如这里当年龄取middle_aged时,目标属性全是yes。2,当分到某类时,某个值的比例达到了给定的阈值,如这里当年龄取youth时,有60%的是no,当然实际的阈值远远大于60%。

2、C4.5算法
在这里插入图片描述
信息增益选择方法有一个很大的缺陷,它总是会倾向于选择属性值多的属性,如果我们在上面的数据记录中加一个姓名属性,假设14条记录中的每个人姓名不同,那么信息增益就会选择姓名作为最佳属性,因为按姓名分裂后,每个组只包含一条记录,而每个记录只属于一类(要么购买电脑要么不购买),因此纯度最高,以姓名作为测试分裂的结点下面有14个分支。但是这样的分类没有意义,它没有任何泛化能力。增益比率对此进行了改进,它引入一个分裂信息:info=上面的H()
在这里插入图片描述
增益比率定义为信息增益与分裂信息的比率:
在这里插入图片描述
我们找
GainRatio
最大的属性作为最佳分裂属性。如果一个属性的取值很多,那么SplitInfoR(D)会大,从而使GainRatio®变小。不过增益比率也有缺点,SplitInfo(D)可能取0,此时没有计算意义;且当SplitInfo(D)趋向于0时,GainRatio®的值变得不可信,改进的措施就是在分母加一个平滑,这里加一个所有分裂信息的平均值:
在这里插入图片描述

决策树优缺点

优点

  • 决策树易于理解和实现。 人们在通过解释后都有能力去理解决策树所表达的意义。
  • 对于决策树,数据的准备往往是简单或者是不必要的。其他的技术往往要求先把数据归一化,比如去掉多余的或者空白的属性。
  • 能够同时处理数据型和常规型属性。 其他的技术往往要求数据属性的单一。
  • 是一个白盒模型。如果给定一个观察的模型,那么根据所产生的决策树很容易推出相应的逻辑表达式。

缺点

  • 对于各类别样本数量不一致的数据,在决策树当中信息增益的结果偏向于那些具有更多数值的特征。
  • 决策树内部节点的判别具有明确性,这种明确性可能会带来误导。

常见决策树:生活中问几个问题来判断一个事件。

二、随机森林概述

Bootstrap抽样(有放回的抽样)

在这里插入图片描述

Bagging算法介绍

在这里插入图片描述
因为样本有重复,所以训练集生成的决策树有重复,因此输出的测试类型有重复。
在这里插入图片描述

随机森林算法

在这里插入图片描述

案例分析

在这里插入图片描述
一、决策树-乳腺癌诊断
1、使用数据介绍:data.m
1:良性;2:恶性
在这里插入图片描述
2、训练集和测试集划分
因为第一列是样本编号,其实用处不大,将第二列500个作为训练集,69个作为测试集,第三列到最后共30列数据中的500个作为训练集,69个作为测试集。

%% I. 清空环境变量
clear all
clc
warning off  % 警示信息不再显示

%% II. 导入数据
load data.mat

%%
% 1. 随机产生训练集/测试集
a = randperm(569);
Train = data(a(1:500),:);
Test = data(a(501:end),:);

%%
% 2. 训练数据
P_train = Train(:,3:end);
T_train = Train(:,2);

%%
% 3. 测试数据
P_test = Test(:,3:end);
T_test = Test(:,2);

在这里插入图片描述
3、创建并查看决策树


%% III. 创建决策树分类器  行代表样本,列是属性变量,同支持向量机
ctree = ClassificationTree.fit(P_train,T_train);

%%
% 1. 查看决策树视图
view(ctree);
view(ctree,'mode','graph');

x21表示第21个变量,即P_train的第21列
在这里插入图片描述
4、仿真测试
将P_test:6930变成T_sim:691.

%% IV. 仿真测试
T_sim = predict(ctree,P_test);

在这里插入图片描述
5、结果分析

%% V. 结果分析
count_B = length(find(T_train == 1));  %312,500训练集中1类别的个数
count_M = length(find(T_train == 2));  %188
rate_B = count_B / 500;  % 训练集中1类别的比例 0.6240
rate_M = count_M / 500;  %0.3760
total_B = length(find(data(:,2) == 1));  %357,569总样本1类别的个数
total_M = length(find(data(:,2) == 2));   %212
number_B = length(find(T_test == 1));  %45
number_M = length(find(T_test == 2));  %24
number_B_sim = length(find(T_sim == 1 & T_test == 1));  %1类型预测正确个数 40
number_M_sim = length(find(T_sim == 2 & T_test == 2));   %23
disp(['病例总数:' num2str(569)...  
      '  良性:' num2str(total_B)...
      '  恶性:' num2str(total_M)]);
disp(['训练集病例总数:' num2str(500)...
      '  良性:' num2str(count_B)...
      '  恶性:' num2str(count_M)]);
disp(['测试集病例总数:' num2str(69)...
      '  良性:' num2str(number_B)...
      '  恶性:' num2str(number_M)]);
disp(['良性乳腺肿瘤确诊:' num2str(number_B_sim)...
      '  误诊:' num2str(number_B - number_B_sim)...
      '  确诊率p1=' num2str(number_B_sim/number_B*100) '%']);
disp(['恶性乳腺肿瘤确诊:' num2str(number_M_sim)...
      '  误诊:' num2str(number_M - number_M_sim)...
      '  确诊率p2=' num2str(number_M_sim/number_M*100) '%']);

在这里插入图片描述
6、解决过拟合问题来限制生长

知识点补充:1、logspace()函数

logscape函数是用来创建指数等差数列,语法描述如下:
logspace(x1,x2)——在从10^x1 ~ 10^x2 区间内生成含有50个元素的等差数列
logspace(x1,x2,n)——在从10^x1~10^x2区间内生成含有n个元素的等差数列
指数等差数列指的是指数部分是一个等差数列:
在这里插入图片描述
在这里插入图片描述

知识点补充:2、numel()函数
在这里插入图片描述
6.1 最小样本误差

%% VI. 叶子节点含有的最小样本数对决策树性能的影响
leafs = logspace(1,2,10);  % 探索10-100个样本的情况

N = numel(leafs);

err = zeros(N,1);  %10行1列的零向量
for n = 1:N
    t = ClassificationTree.fit(P_train,T_train,'crossval','on','minleaf',leafs(n));
    err(n) = kfoldLoss(t);
end
plot(leafs,err);
xlabel('叶子节点含有的最小样本数');
ylabel('交叉验证误差');
title('叶子节点含有的最小样本数对决策树性能的影响')

在这里插入图片描述
通过放大观看,发现样本数为13的时候,误差最小。
在这里插入图片描述
因此设置最小样本数为13.

%% VII. 设置minleaf为13,产生优化决策树
OptimalTree = ClassificationTree.fit(P_train,T_train,'minleaf',13);
view(OptimalTree,'mode','graph')

在这里插入图片描述
通过优化误差达到限制生长

7、比较性能,是否优化更好

%%
% 1. 计算优化后决策树的重采样误差和交叉验证误差
resubOpt = resubLoss(OptimalTree)
lossOpt = kfoldLoss(crossval(OptimalTree))

%%
% 2. 计算优化前决策树的重采样误差和交叉验证误差
resubDefault = resubLoss(ctree)
lossDefault = kfoldLoss(crossval(ctree))

在这里插入图片描述
虽然重采样增大了,但是交叉验证误差减小了。
在这里插入图片描述
结果也发现,误差相较不大,但是大大减少了运行时间了和复杂度。

6.2、剪枝


%% VIII. 剪枝
[~,~,~,bestlevel] = cvLoss(ctree,'subtrees','all','treesize','min')  %4
cptree = prune(ctree,'Level',bestlevel);
view(cptree,'mode','graph')

%%
% 1. 计算剪枝后决策树的重采样误差和交叉验证误差
resubPrune = resubLoss(cptree)
lossPrune = kfoldLoss(crossval(cptree))

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
综上所述:无论是限制样本数还是裁剪都对性能上的提升不是很明显,但是对树的结构有较大的改变。

二、随机森林-乳腺癌诊断
1—2 同上面决策树,数据一样,划分一样
在这里插入图片描述
3、创建随机森林分类器
注意需要用到第三方的包(随机森林工具箱)randomforest-matlab,方法就是将这个文件夹添加到matlab的路径中间去,然后调用即可。
下载地址
在这里插入图片描述
知识点补充function model = classRF_train(X,Y,ntree,mtry, extra_options)
需要2个参数,其余3个是可选的;
X: data matrix
Y: target values
ntree (optional): number of trees (default is 500). also if set to 0 will default to 500 ntree(可选):树数(默认为500)。 如果设置为0将默认为500
mtry (default is floor(sqrt(size(X,2))) D=number of features in X). also if set to 0 will default to 500 mtry(默认值为floor(sqrt(size(X,2)))D = X中的要素数量)。 同样如果设置为0将默认为500

%% III. 创建随机森林分类器
model = classRF_train(P_train,T_train);

默认生成500个树节点。
在这里插入图片描述
4、仿真预测

%% IV. 仿真测试
[T_sim,votes] = classRF_predict(P_test,model);

因为默认是500,所以类别1+类别2=500,谁占的多就选择谁
在这里插入图片描述
5、结果打印-同决策树

%% V. 结果分析
count_B = length(find(T_train == 1));
count_M = length(find(T_train == 2));
total_B = length(find(data(:,2) == 1));
total_M = length(find(data(:,2) == 2));
number_B = length(find(T_test == 1));
number_M = length(find(T_test == 2));
number_B_sim = length(find(T_sim == 1 & T_test == 1));
number_M_sim = length(find(T_sim == 2 & T_test == 2));
disp(['病例总数:' num2str(569)...
      '  良性:' num2str(total_B)...
      '  恶性:' num2str(total_M)]);
disp(['训练集病例总数:' num2str(500)...
      '  良性:' num2str(count_B)...
      '  恶性:' num2str(count_M)]);
disp(['测试集病例总数:' num2str(69)...
      '  良性:' num2str(number_B)...
      '  恶性:' num2str(number_M)]);
disp(['良性乳腺肿瘤确诊:' num2str(number_B_sim)...
      '  误诊:' num2str(number_B - number_B_sim)...
      '  确诊率p1=' num2str(number_B_sim/number_B*100) '%']);
disp(['恶性乳腺肿瘤确诊:' num2str(number_M_sim)...
      '  误诊:' num2str(number_M - number_M_sim)...
      '  确诊率p2=' num2str(number_M_sim/number_M*100) '%']);

在这里插入图片描述
可观察,结果比决策树好。

6、绘图
将类别1作为x,类别2作为y,x+y=500

%% VI. 绘图
figure

index = find(T_sim ~= T_test);  %求出预测值和真实值不一样的索引 【43;54】
plot(votes(index,1),votes(index,2),'r*')  %(498,2)(169,331)
hold on

index = find(T_sim == T_test);
plot(votes(index,1),votes(index,2),'bo')
hold on

legend('错误分类样本','正确分类样本')

plot(0:500,500:-1:0,'r-.') %所有点在x+y=500上面
hold on

plot(0:500,0:500,'r-.')
hold on

line([100 400 400 100 100],[100 100 400 400 100])  %方框范围内表示投票比较接近,容易犯错,框内越多模型越不好

xlabel('输出为类别1的决策树棵数')
ylabel('输出为类别2的决策树棵数')
title('随机森林分类器性能分析')

在这里插入图片描述7、棵树对结果的影响

Accuracy = zeros(1,20);  %1行20列的零向量
for i = 50:50:1000  %20个区间段
    i
    %每种情况,运行100次,取平均值
    accuracy = zeros(1,100);
    for k = 1:100
        % 创建随机森林
        model = classRF_train(P_train,T_train,i);
        % 仿真测试
        T_sim = classRF_predict(P_test,model);
        accuracy(k) = length(find(T_sim == T_test)) / length(T_test);
    end
     Accuracy(i/50) = mean(accuracy);
end
%%
%  绘图
figure
plot(50:50:1000,Accuracy)
xlabel('随机森林中决策树棵数')
ylabel('分类正确率')
title('随机森林中决策树棵数对性能的影响')

在这里插入图片描述
发现100是精度最高。

model = classRF_train(P_train,T_train,100);

%% IV. 仿真测试
[T_sim,votes] = classRF_predict(P_test,model);

%% V. 结果分析
count_B = length(find(T_train == 1));
count_M = length(find(T_train == 2));
total_B = length(find(data(:,2) == 1));
total_M = length(find(data(:,2) == 2));
number_B = length(find(T_test == 1));
number_M = length(find(T_test == 2));
number_B_sim = length(find(T_sim == 1 & T_test == 1));
number_M_sim = length(find(T_sim == 2 & T_test == 2));
disp(['病例总数:' num2str(569)...
      '  良性:' num2str(total_B)...
      '  恶性:' num2str(total_M)]);
disp(['训练集病例总数:' num2str(500)...
      '  良性:' num2str(count_B)...
      '  恶性:' num2str(count_M)]);
disp(['测试集病例总数:' num2str(69)...
      '  良性:' num2str(number_B)...
      '  恶性:' num2str(number_M)]);
disp(['良性乳腺肿瘤确诊:' num2str(number_B_sim)...
      '  误诊:' num2str(number_B - number_B_sim)...
      '  确诊率p1=' num2str(number_B_sim/number_B*100) '%']);
disp(['恶性乳腺肿瘤确诊:' num2str(number_M_sim)...
      '  误诊:' num2str(number_M - number_M_sim)...
      '  确诊率p2=' num2str(number_M_sim/number_M*100) '%']);

在这里插入图片描述
在良性上明显提高了,但是恶性有点下降。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值