我的小程序:

待办计划:卷起来吧,少年!

我们记账:年薪50w够花么?

基础算法

举个栗子:

当一个有经验的老农看一个瓜是不是好瓜时,他可能会先看下瓜的颜色,一看是青绿的,心想有可能是好瓜!接着他又看了下根蒂,发现是蜷缩着的,老农微微点头,寻思着五成以上是好挂瓜!最后他又敲了下瓜,一听发出浑浊的响声,高兴的叫到:这瓜是个好瓜啊!这就是老农做出决策的大致过程。

决策树算法基本就是偷学老农的决策过程,如下图

代码的形式表示:

划分属性选择

上图算法最重要的一行就是第8行:从A中选择最优的划分属性a*。

一般希望决策树层数越少,分支越少,尽快的做出决策,这就要求结点包含的样本尽可能属于同一类,即结点“纯度”尽量高。

这也符合老农挑瓜的经验:

当老农看了下瓜的根蒂,发现根蒂是蜷缩的,老农回想了下过往他看过的成千上万的瓜,记得根蒂只要是蜷缩的瓜都是好瓜(结点“纯度”很高,所有样本属于同一个分类),他不需要再听瓜的声音,就可以直接做出判断:哈哈,这是个好瓜啊!相反,如果老农回想了过往的那些瓜,发现根蒂是蜷缩的瓜既有好瓜也有坏瓜(结点“纯度”较低,样本属于两个分类),那他肯能就需要再敲下瓜,听听瓜的声音再做出的判断。

最优划分的选择一般有“信息增益”和“基尼指数”等指标。

信息增益(C4.5决策树)

信息熵:度量样本集合的纯度。假定样本集合D中第k类样本所占比例为pk(k=1,2,...,|y|),则D的信息熵为:

信息熵越小,则D的纯度越高。

信息增益:假定离散属性a有V个属性值{a1,a2,...,aV},若用a对样本划分,则会产生V个分支结点,其中第v个分支结点包含了D中所有在属性a上取值为aV的样本,记为Dv。则可以计算出Dv的信息熵,并赋予权重|Dv|/|D|,则可计算出用属性a对样本D进行划分的信息增益:

信息增益越大,纯度提升越大。所以这样来选择最优属性:a* = arg max Gain(D,a)(使信息增益最大的属性a)。

增益率:

著名的C4.5决策树算法没有直接使用信息增益,而是使用的增益率。因为信息增益准则对可取数目较多的属性有所偏好,而这种偏好可能带来不利影响。可以想像,在极端情况下,如果一个数据集D有100个样本,在某属性上有100个不同取值,则该属性上全部信息熵之和为0,即信息增益为最大值Ent(D),显然决策树会对该属性有所偏好。

需要注意的是,增益率对属性数目较少的属性有所偏好,所以C4.5算法也没有直接使用增益率,而是先从属性中找到信息增益高于平均水平的属性,再从中选择增益率最高的。

基尼指数(CART决策树)

基尼值:

基尼值越小,数据集D的纯度越高。

基尼指数:

选择基尼指数最小的属性作为最优划分属性,即a* = arg min Gini_index(D,a).

剪枝处理——避免过拟合

剪枝是为了解决决策树“过拟合”的手段,当一颗决策树分支、层数过多,就容易出现”过拟合“,导致决策树泛化性能不好。剪枝分为“预剪枝”和“后剪枝”。

预剪枝:在决策树生成过程中,在每个结点划分前先估计,若当前结点的划分不能带来泛化性能的提升,就停止划分,把当前结点标记为叶结点。

后剪枝:先生成完整的决策树,之后再自底向上对非叶结点考察,若该结点对应的子树替换为叶结点能提升泛化性能,则将其替换为叶结点。

预剪枝处理方式如下图。假如基于信息增益的准则,我们首先选择了“脐部”作为划分准则。在划分前,所有样本都在根结点1。若不进行划分,则将该结点标记为叶结点,类别为训练集中样本最多的类别,假设是“好瓜”。再用验证集去评估这个单结点决策树,假设正确率为42.9%。接着,我们对“脐部”进行划分,得到结点2,3,4,假设分别对应“好瓜”,“好瓜”,“坏瓜”。再用验证集去评估新的决策树,假设得到正确率71.4%>42.9%,则用“脐部”进行划分得以确定。重复以上步骤生成最终的决策树。

预剪枝优缺点:降低“过拟合”风险,减少时间开销。但是,有些分支当前划分虽不能提升泛化性能,但在其基础上进行的后续划分可能导致性能显著提升,所以可能会带来“欠拟合”的风险。(有点像梯度下降,追求每一步的最快下降,只顾眼前,但可能只能达到局部最优)。

后剪枝过程如下面两图所示。首先生成第一幅图完整的决策树,假设根据验证集得到其正确率为42.9%。接着考察最底下的结点6,若将器分支剪除,相当于把6替换为叶结点,假设其类别为“好瓜”,再用验证集评估新的决策树,假设准确率为57.1%,则后剪枝策略决定剪枝。再考察结点5,以此类推,得到最终的决策树。

后剪枝优缺点:一般情况下,“欠拟合”风险很小,泛化性能往往优于预剪枝。但是时间开销比预剪枝大得多。

连续值处理

对于连续属性(如密度,面积,价格等),其属性值数目无限,不能直接根据连续属性的可取值进行划分。

最简单的策略是“二分法”(C4.5采用):假定样本集D和连续属性a,a在D上有n个不同取值,将这些取值从下到大排列,记为{a1,a2,...,an},选择划分点t可将D划分为D-和D+,D-包含取值不大于t的样本,D+包含取值大于t的样本,可以得到n-1个候选划分点:Ta={[a(i)+a(i+1)]/2|1<=i<=n-1},将信息增益改造成如下公式:

选择使Gain(D,a,t)最大化的划分点t。可以得到如下图所示的决策树:

注:与离散属性不同,若当前节点划分属性为连续值,该属性还可作为后代结点的划分属性(如此处使用了密度<=0.381,不会禁止在子结点使用如密度<=0.294)。

缺失值处理

经常会碰到数据集中某些数据的属性值未知,这时候就要解决两个问题:1、怎么选择划分属性?2、划分属性确定后,怎么把该属性未知的数据划分到结点?

假定D'表示D中在属性a上没有缺失值的样本子集。对于第一个问题,我们只能根据D'来判断属性的优劣。假定属性a有V个可取值,D'v表示D'中在属性a上取值为aVd 样本子集,D'k表示D'中第k(k=1,2,...,|y|)类的样本子集,我们为每个样本赋予一个权重wx。定义以下变量:

并且把信息增益公式推广为如下形式:

其中:

对于第二个问题,若样本在划分属性a上取值已知,就把样本划分到对应的子结点,并且权重保持wx不变。若样本在属性a上取值未知,则把它划分到所有的子结点,并且权重在子结点调整为r'v*wx(r'v指的是图中r波浪v下标),同一个样本以不同的概率划入不同的结点。

多变量决策树(斜决策树)

决策树形成的分类边界有一个明星的特点:轴平行。如下面这颗决策树:它形成的分类边界如下图所示:

当分类边界比较复杂时,要有很多段的划分才能得到近似,所形成的决策树就会很复杂。

多变量决策树是为了实现“斜划分”,减少划分段数。它不以单个属性进行划分,而是每个分类结点是一个形如(w1*a1+w2*a2+...+wd*ad)= t的一个线性分类器,wd是属性ad的权重,w和t在该结点所含样本集和属性集学得。所以多变量分类器就变成为每个结点寻找合适的线性分类器。

多变量分类器所形成的决策树如下图:其对应的分类边界:

生成决策树matlab代码(包括连续值的“二分法”处理):

注:代码里的attrs是这样一个事先处理好的一个结构:

color = struct('attr_k',1,'attr_type',0,'values',{[1,0,0],[0,1,0],[0,0,1]});
rootbase = struct('attr_k',2,'attr_type',0,'values',{[1,0,0],[0,1,0],[0,0,1]});
voice = struct('attr_k',3,'attr_type',0,'values',{[1,0,0],[0,1,0],[0,0,1]});
texture = struct('attr_k',4,'attr_type',0,'values',{[1,0,0],[0,1,0],[0,0,1]});
umbilicus = struct('attr_k',5,'attr_type',0,'values',{[1,0,0],[0,1,0],[0,0,1]});
touch = struct('attr_k',6,'attr_type',0,'values',{[1,0],[0,1]});
density = struct('attr_k',7,'attr_type',2,'values','');
sugar = struct('attr_k',8,'attr_type',2,'values','');
attrs = {color,rootbase,voice,texture,umbilicus,touch,density,sugar};

轻微吐槽:matlab的struct结构好怪异,对matlab不熟,写的挺纠结,不知道大神们有什么建议。

代码开始:

function [tree] = maketreeFunc(x,y,attrs)
%生成结点
tree = struct('parent_attr_val',struct('symbol','','value',''),'div_attr',struct('attr_k','','attr_type',0),'cate','no','child',cell(1));
node = tree;
%属于同一分类,生成叶结点
if isequal(y,ones(length(y),1)*y(1)),%叶结点tree.cate = y(1);return;
endif;
%判断所有属性是否都相同
is_attr_same = 1;
if length(attrs)>0,for i=1:length(attrs),for j=2:length(y),if ~isequal(x{1,attrs{i}(1).attr_k},x{j,attrs{i}(1).attr_k}),is_attr_same = 0;break;endif;endfor;if is_attr_same==0,break;endif;endfor;
endif;
%属性集为空或所有属性值都相同,生成叶结点
if length(attrs)==0||is_attr_same,%找到类别比重最多的一类作为叶结点t = tabulate(y+1);max_percent = max(t(:,3));[row,col] = find(t == max_percent,1);most_y = t(row,1)-1;%叶结点tree.cate = most_y;return;
endif;
%信息熵
info_entropy = infoentropyFunc(y);
%不同属性的信息增益矩阵
info_gain = [];
%确定划分属性
for i=1:length(attrs),attr_col = x(:,attrs{i}(1).attr_k);y_cate = {};L = 1;%连续属性二分法处理if attrs{i}(1).attr_type == 2,attr_col_mat = cell2mat(attr_col);%升序attr_col_mat = sort(attr_col_mat,'ascend');%划分点集合bi_part = [];for j=1:(length(attr_col_mat)-1),bi_part(j) = (attr_col_mat(j)+attr_col_mat(j+1))/2;endfor;%不同划分点信息增益矩阵bi_gain = [];for j=1:length(bi_part),left_cate_y = [];right_cate_y = [];for k=1:length(attr_col),if attr_col{k}<=bi_part(j),left_cate_y = [left_cate_y;y(k)];elseright_cate_y = [right_cate_y;y(k)];endif;endfor;attr_entropy = 0;attr_entropy += (length(left_cate_y)/length(y))*infoentropyFunc(left_cate_y);attr_entropy += (length(right_cate_y)/length(y))*infoentropyFunc(right_cate_y);bi_gain(j) = info_entropy - attr_entropy;endfor;%划分点中信息增益最大的划分点作为该属性的最终信息增益max_bi_pos = find(bi_gain==max(bi_gain),1);info_gain(1,i) = max(bi_gain);info_gain(2,i) = bi_part(max_bi_pos);else%非连续属性for j=1:length(attrs{i}),one_cate_y = [];for k=1:length(attr_col),if attrs{i}(j).values==attr_col{k},one_cate_y = [one_cate_y;y(k)];endif;endfor;if length(one_cate_y)>0,y_cate(L) = one_cate_y;L = L+1;endif;endfor;attr_entropy = 0;for m=1:length(y_cate),attr_entropy += (length(y_cate{m})/length(y))*infoentropyFunc(y_cate{m});endfor;info_gain(1,i) = info_entropy - attr_entropy;endif;%info_gain(i) = struct('gain',info_entropy - attr_entropy,'attr',attrs(i));
endfor;
%取最大的信息增益属性
pos = find(info_gain(1,:)==max(info_gain(1,:)),1);
%记录划分属性
tree.div_attr.attr_k = attrs{pos}(1).attr_k;
tree.div_attr.attr_type = attrs{pos}(1).attr_type;
%生成分支
if attrs{pos}(1).attr_type==2,%连续属性%二分法生成的划分点part_num = info_gain(2,pos);%生成大于和小于划分点的两个分支for i=1:2,x_part = {};y_part = [];k = 1;for j=1:length(x(:,attrs{pos}(1).attr_k)),%小于part_num的部分if i==1,if x(:,attrs{pos}(1).attr_k){j}<=part_num,x_part(k,:) = x(j,:);y_part(k,1) = y(j);k = k + 1;endif;else%大于part_num的部分if x(:,attrs{pos}(1).attr_k){j}>part_num,x_part(k,:) = x(j,:);y_part(k,1) = y(j);k = k + 1;endif;endif;endfor;%连续属性子结点可以继续划分,无需清除该属性%child_attrs = attrs;%child_attrs(pos) = [];[child_tree] = maketreeFunc(x_part,y_part,attrs);if i==1,child_tree.parent_attr_val.symbol = '<';elsechild_tree.parent_attr_val.symbol = '>';endif;child_tree.parent_attr_val.value = part_num;len = length(tree.child);tree.child(len+1) = child_tree;endfor;
else%非连续属性%不同属性值生成分支for i=1:length(attrs{pos}),flag = 0;x_part = {};y_part = [];k = 1;%一个分支的x,y数据集for j=1:length(x(:,attrs{pos}(1).attr_k)),if isequal(attrs{pos}(i).values,x(:,attrs{pos}(1).attr_k){j}),flag = 1;x_part(k,:) = x(j,:);y_part(k,1) = y(j);k = k + 1;endif;endfor;%分支数据为空,生成叶结点if flag==0,%找到类别比例最多的类别t = tabulate(y+1);max_percent = max(t(:,3));[row,col] = find(t == max_percent,1);most_y = t(row,1)-1;%生成叶结点node.cate = most_y;node.parent_attr_val.value = attrs{pos}(i).values;len = length(tree.child);tree.child(len+1) = node;return;endif;child_attrs = attrs;%子结点中删除当前用于划分的属性child_attrs(pos) = [];%生成子结点[child_tree] = maketreeFunc(x_part,y_part,child_attrs);child_tree.parent_attr_val.value = attrs{pos}(i).values;len = length(tree.child);tree.child(len+1) = child_tree;endfor;
endif;

待办计划:卷起来吧,少年!

我们记账:年薪50w够花么?

参考资料:周志华《机器学习》

机器学习:决策树-基础算法,剪枝,连续值缺失值处理,多变量决策树(附代码实现)相关推荐

  1. 机器学习 | 决策树原理剪枝连续值缺失值处理

    机器学习 | 决策树 最近学习了西瓜书决策树一章,简单整理了笔记,后续会继续补充给 文章目录 机器学习 | 决策树 一.基本信息论 1. 信息量 2. 信息熵 二.决策树常用算法 1.ID3 2.C4 ...

  2. [Python从零到壹] 十四.机器学习之分类算法五万字总结全网首发(决策树、KNN、SVM、分类对比实验)

    欢迎大家来到"Python从零到壹",在这里我将分享约200篇Python系列文章,带大家一起去学习和玩耍,看看Python这个有趣的世界.所有文章都将结合案例.代码和作者的经验讲 ...

  3. 基于灰狼算法优化概率神经网络PNN的分类预测-附代码

    基于灰狼算法优化概率神经网络PNN的分类预测 - 附代码 文章目录 基于灰狼算法优化概率神经网络PNN的分类预测 - 附代码 1.PNN网络概述 2.变压器故障诊街系统相关背景 2.1 模型建立 3. ...

  4. gwo算法matlab源代码,智能优化算法应用:基于GWO优化BP神经网络 - 附代码

    智能优化算法应用:基于GWO优化BP神经网络 - 附代码 智能优化算法应用:基于GWO优化BP神经网络 - 附代码 智能优化算法应用:基于GWO优化BP神经网络 文章目录智能优化算法应用:基于GWO优 ...

  5. c语言bmp图片拉普拉斯锐化,图像锐化算法(Image sharpening):拉普拉斯增强和Unsharp Masking(附代码)...

    图像锐化算法(Image sharpening):拉普拉斯增强和Unsharp Masking(附代码) (y(m,n)=x(m,n)+lambda*z(m,n)) 其中(x(m,n))是处理前图片, ...

  6. 机器学习——使用ID3算法从原理到实际举例理解决策树

    文章目录 一.什么是决策树 二.介绍建立决策树的算法 三.决策树的一般流程 四.实际举例构建决策树 使用ID3算法的原理实现构建决策树 参考链接 一.什么是决策树 基本概念 决策树是一种树形结构,其组 ...

  7. 干货 | 算法和编程面试题精选TOP50!(附代码+解题思路+答案)

    作者 | javinpaul 编译 | 王天宇.Jane 整理 | Jane [导读]之前我们给同学们推荐了很多关于 Python 的面试资源,大家都表示很有用.这次营长表示要翻 Java 的牌子啦~ ...

  8. 【Simulink】粒子群算法(PSO)整定PID参数(附代码和讲解)

    目录 0.背景 1.粒子群算法 1.1.算法简介 1.2.算法步骤 1.3.算法举例 2.PID自整定 2.1.基于M文件编写的PID参数自整定 *2.2.复杂系统的PID自整定(基于simulink ...

  9. 【含泪提速!】一文全解相似度算法、跟踪算法在各个AI场景的应用(附代码)

    大家好,我是cv君,大家是否为深度学习算法速度感到困扰?本次cv君倾力分享一个优秀的方法,通过相似度+跟踪方案优化速度问题,并提高了检测.分割算法稳定性,附带代码,一起肝起来吧~ 今天给大家全解一下图 ...

最新文章

  1. 《QML除夕烟花,代码全平台可用》
  2. PHP的简单跳转提示的实现
  3. 【干货】2014Q4手游崩溃数据报告,iphone6第1、三星第2
  4. git 撤销文件的修改(checkout/reset )
  5. C 运算符中不能重载的是哪些
  6. 转:Oracle 中union的用法
  7. 部署windows服务
  8. VML编程之------oval圆rect矩型《VML极道教程》原著:沐缘华
  9. python opencv 找到圆点标定板所有点后通过距离找四个角点2
  10. MedPy医学图像评价的python库
  11. 通信总线协议二 :RS232和RS485
  12. smarty 模板php,php的smarty模板发动机
  13. Drools教程(基础篇)——创建项目
  14. 薄板样条插值(Thin Plate Spline)
  15. RuoYi-Vue前后端分离
  16. 计算机系统的位的描述性定义,计算机系统中,“位”的描述性定义是________。
  17. 辞旧迎新:祝您阖家幸福安康,万事如意
  18. 【Spark ML】第 5 章:Recommendations
  19. 位运算——左移和右移
  20. 如何科学检测新型冠状病毒?

热门文章

  1. 维基百科怎么做创建词条?如何创建维基百科?海外营销_一秒推媒体平台
  2. NDK(一):NDK 的集成
  3. css盒模型、布局模型、 flex弹性盒模型及样式设置小技巧
  4. 浏览器全屏和pc显示器全屏
  5. 工控前辈经验之谈 | 编写PLC程序我从做Excel表开始
  6. for example: not eligible for auto-proxying问题解决
  7. ICLR 2022 | 基于对抗自注意力机制的预训练语言模型
  8. Dialer拨号定制功能
  9. 一文解析数据库基础设施的现状与挑战
  10. 机器学习预测世界杯:巴西夺冠