机器学习(四):CART分类树(基础篇)


相关的决策树文章:

  • 机器学习(四)ID3决策树
  • 机器学习(四)C4.5决策树
  • 机器学习(四)CART回归树
  • 机器学习(四)决策树绘图
  • 机器学习(四)剪枝技术
    大家都知道,著名的决策树有三种:ID3,C4.5,CART。前面两棵树只适用于分类,前面两个数的优点我们都知道了,那么问题来了,我们为什么要学习CART树呢?CART树又叫分类,回归树,顾名思义,它既可以做分类又可以做回归。是不是感觉很神奇?我们看看他的实现原理。

CRAT树度量指标

1.回归树

纯度:回归方差

其中,I为i可以取的值, x i x_i xi​表示取i的时候的x的值, m u mu mu表示平均值。
归回方差越大,节点数据越分散(不纯)。故选择划分的依据为回归方差和的大小。我们要保证回归方差最小化:


这一章,我们主要介绍CART决策树的分类作用。上面的知识可以先了解一下。

2.分类树

2.1 Gini(基尼系数)

分类问题中,假设有k个类,样本点属于第k类的概率为 p k p_k pk​,则概率分布的基尼指数定义为:

G i n i ( D ) = ∑ k = 1 ∣ y ∣ ∑ k ′ ! = k p k p k ′ = 1 − ∑ k = 1 ∣ y ∣ p k 2 Gini(D) = \displaystyle\sum_{k=1}^{|y|}\displaystyle\sum_{k'!=k}p_kp_{k'}=1-\displaystyle\sum_{k=1}^{|y|}p_k^2 Gini(D)=k=1∑∣y∣​k′!=k∑​pk​pk′​=1−k=1∑∣y∣​pk2​

ps: p k p_k pk​表示选中的样本属于k类别的概率,则这个样本被分错的概率 p k ′ p_k' pk′​为 ( 1 − p k ) (1-p_k) (1−pk​)。

用法:对于给定的样本集合D,其基尼指数为:
G i n i = 1 − ∑ k = 1 K ( ∣ C k ∣ ∣ D ∣ ) 2 Gini=1-\displaystyle\sum_{k=1}^{K}(\frac{|C_k|}{|D|})^2 Gini=1−k=1∑K​(∣D∣∣Ck​∣​)2
ps:这里 C k C_k Ck​是D中属于第k类的样本自己,K是类的个数。

2.2 属性a的基尼系数

G i n i i n d e x ( D , a ) = ∑ v = 1 v ∣ D v ∣ ∣ D ∣ G i n i ( D v ) Gini_index(D,a)=\displaystyle\sum_{v=1}^{v}\frac{|D^v|}{|D|}Gini(D^v) Ginii​ndex(D,a)=v=1∑v​∣D∣∣Dv∣​Gini(Dv)
于是,我们在候选属性集合A中,选择那个使得划分后基尼系数最小的属性作为最优划分属性。

用法:如果样本集合D根据特征A是否取某一可能值a被分割成D1和D2两部分,则:

则在特征A的条件下,集合D的基尼系数定义为:

基尼系数Gini(D)表示集合D的不确定性,基尼系数Gini(D,A)表示经A=a分割后集合D的不确定性。基尼指数越大,样本集合的不确定性也就越大,这一点跟熵很相似。。

3.算法步骤

输入:训练数据集D,停止计算的条件
输出:CART决策树
根据训练数据集,从根节点开始,递归地对每一个节点进行以下操作,构建二叉树:
Step1:设结点地训练数据集为D,计算现有特征对该数据集地基尼指数。此时,对每一个特征A,对其可能取的每一个值a,根据样本点A=a的测试为“是”或“否”将d分割为D1和D2两部分,利用上式Gini(A)来计算A=a时的基尼系数。
Step2:在所有可能的特征A以及他们所有可能的切分点a中,选择基尼系数最小的特征及其对应可能的切分点作为最优特征与最优切分点。依靠最优特征与最优切分点,从现结点生成两个子节点,将训练数据集依特征分配到两个子节点中去。
Step3:对两个子节点递归地调用Step1,Step2,直至满足条件
Step4:生成CART决策树
算法停止计算地条件:

  • 结点中地样本个数小于预定阈值
  • 样本集地基尼指数小于预定阈值
  • 没有更多地特征

4.代码实现

from math import log
import operator
import sys
import plotTrees
sys.path.append(r'D:\python\QG\machine-learning\decide tree\plotTree')def calcProbabilityEnt(dataSet):"""样本点属于第1个类的概率p,即计算2p(1-p)中的p@param dataSet: 数据集@return probabilityEnt: 数据集的概率"""numEntries = len(dataSet)  # 数据条数feaCounts = 0fea1 = dataSet[0][len(dataSet[0]) - 1]for featVec in dataSet:  # 每行数据if featVec[-1] == fea1:feaCounts += 1probabilityEnt = float(feaCounts) / numEntriesreturn probabilityEntdef splitDataSet(dataSet, index, value):"""划分数据集,提取含有某个特征的某个属性的所有数据@param dataSet: 数据集@param index: 属性值所对应的特征列@param value: 某个属性值@return retDataSet: 含有某个特征的某个属性的数据集"""retDataSet = []for featVec in dataSet:# 如果该样本该特征的属性值等于传入的属性值,则去掉该属性然后放入数据集中if featVec[index] == value:reducedFeatVec = featVec[:index] + featVec[index + 1:]  # 去掉该属性的当前样本retDataSet.append(reducedFeatVec)  # append向末尾追加一个新元素,新元素在元素中格式不变,如数组作为一个值在元素中存在return retDataSetdef chooseBestFeatureToSplit(dataSet):"""选择最优特征@param dataSet: 数据集@return bestFeature: 最优特征所在列"""numFeatures = len(dataSet[0]) - 1  # 特征总数if numFeatures == 1:  # 当只有一个特征时return 0bestGini = 1  # 最佳基尼系数bestFeature = -1  # 最优特征for i in range(numFeatures):uniqueVals = set(example[i] for example in dataSet)  # 去重,每个属性值唯一feaGini = 0  # 定义特征的值的基尼系数# 依次计算每个特征的值的熵for value in uniqueVals:subDataSet = splitDataSet(dataSet, i, value)  # 根据该特征属性值分的类# 参数:原数据、循环次数(当前属性值所在列)、当前属性值prob = len(subDataSet) / float(len(dataSet))probabilityEnt = calcProbabilityEnt(subDataSet)feaGini += prob * (2 * probabilityEnt * (1 - probabilityEnt))if (feaGini < bestGini):  # 基尼系数越小越好bestGini = feaGinibestFeature = ireturn bestFeaturedef majorityCnt(classList):"""对最后一个特征分类,出现次数最多的类即为该属性类别,比如:最后分类为2男1女,则判定为男@param classList: 数据集,也是类别集@return sortedClassCount[0][0]: 该属性的类别"""classCount = {}# 计算每个类别出现次数for vote in classList:try:classCount[vote] += 1except KeyError:classCount[vote] = 1sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)  # 出现次数最多的类别在首位# 对第1个参数,按照参数的第1个域来进行排序(第2个参数),然后反序(第3个参数)return sortedClassCount[0][0]  # 该属性的类别def createTree(dataSet, labels):"""对最后一个特征分类,按分类后类别数量排序,比如:最后分类为2同意1不同意,则判定为同意@param dataSet: 数据集@param labels: 特征集@return myTree: 决策树"""classList = [example[-1] for example in dataSet]  # 获取每行数据的最后一个值,即每行数据的类别# 当数据集只有一个类别if classList.count(classList[0]) == len(classList):return classList[0]# 当数据集只剩一列(即类别),即根据最后一个特征分类if len(dataSet[0]) == 1:return majorityCnt(classList)# 其他情况bestFeat = chooseBestFeatureToSplit(dataSet)  # 选择最优特征(所在列)bestFeatLabel = labels[bestFeat]  # 最优特征del (labels[bestFeat])  # 从特征集中删除当前最优特征uniqueVals = set(example[bestFeat] for example in dataSet)  # 选出最优特征对应属性的唯一值myTree = {bestFeatLabel: {}}  # 分类结果以字典形式保存for value in uniqueVals:subLabels = labels[:]  # 深拷贝,拷贝后的值与原值无关(普通复制为浅拷贝,对原值或拷贝后的值的改变互相影响)myTree[bestFeatLabel][value] = createTree(splitDataSet(dataSet, bestFeat, value), subLabels)  # 递归调用创建决策树return myTreeimport pandas as pd
import numpy as npdef loadDataSet(filename):"""函数说明:从文件中下载数据,并将分离除连续型变量和标签变量:parameter:data - Iris数据集attributes - 鸢尾花的属性type - 鸢尾花的类别sl-花萼长度 , sw-花萼宽度, pl-花瓣长度, pw-花瓣宽度:return:"""iris_data = pd.read_csv(filename)   #打开文件iris_data = pd.DataFrame(data=np.array(iris_data), columns=['sl', 'sw', 'pl', 'pw', 'type'], index=range(149))   #给数据集添加列名,方便后面的操作dataSet = iris_data.values.tolist()return dataSetif __name__ == '__main__':#     # 数据集# dataSet = [('青年', '否', '否', '一般', '不同意'),#            ('青年', '否', '否', '好', '不同意'),#            ('青年', '是', '否', '好', '同意'),#            ('青年', '是', '是', '一般', '同意'),#            ('青年', '否', '否', '一般', '不同意'),#            ('中年', '否', '否', '一般', '不同意'),#            ('中年', '否', '否', '好', '不同意'),#            ('中年', '是', '是', '好', '同意'),#            ('中年', '否', '是', '非常好', '同意'),#            ('中年', '否', '是', '非常好', '同意'),#            ('老年', '否', '是', '非常好', '同意'),#            ('老年', '否', '是', '好', '同意'),#            ('老年', '是', '否', '好', '同意'),#            ('老年', '是', '否', '非常好', '同意'),#            ('老年', '否', '否', '一般', '不同意')]# # 特征集# labels = ['年龄', '有工作', '有房子', '信贷情况']# 创建树dataSet =[['sunny', 'hot', 'high', 'FALSE', '25'],['sunny', 'hot', 'high', 'TRUE', '30'],['vercast', 'hot', 'high', 'FALSE', '46'],['rainy ', 'mild', 'high', 'FALSE', '45'],['rainy', 'cool', 'normal', 'FALSE', '52'],['rainy', 'cool', 'normal', 'TRUE', '23'],['overcast', 'cool', 'normal', 'TRUE', '43'],['sunny', 'mild', 'high', 'FALSE', '35'],['sunny ', 'cool', 'normal', 'FALSE', '38'],['rainy', 'mild', 'normal', 'FALSE', '46'],['sunny', 'mild', 'normal', 'TRUE', '48'],['overcast', 'mild', 'high ', 'TRUE  ', '52'],['overcast', 'hot', 'normal ', 'FALSE ', '44'],['rainy', 'mild', 'high', 'TRUE', '30']]labels= ['weather','temp', 'hight', 'weatherplay']tree = createTree(dataSet, labels)  # 输出决策树模型结果plotTrees.createPlot(tree)

我们看看结果:

很好的生成了一个决策树。在这里CART决策树属于分类树,之后面的文章中,我会继续讲解一下回归树的原理和运用。

机器学习(四):CART分类树(基础篇)相关推荐

  1. Lesson 8.1Lesson 8.2 决策树的核心思想与建模流程CART分类树的建模流程与sklearn评估器参数详解

    Lesson 8.1 决策树的核心思想与建模流程 从本节课开始,我们将介绍经典机器学习领域中最重要的一类有监督学习算法--树模型(决策树). 可此前的聚类算法类似,树模型也同样不是一个模型,而是一类模 ...

  2. 决策树之CART分类树

    目录 一.基尼系数 (1)离散型属性 (2)连续型属性 二.cart算法的步骤 三.举个栗子 四.代码实现过程 总结: 一.基尼系数 基尼系数(Gini)是一种不等性的度量,经济学上用基尼系数度量收入 ...

  3. JAVA红石_【Mc我的世界红石研究日记】第四期:红石基础元件(四)——JAVA版基础篇...

    Hello,大家好,欢迎来到Mc元气工作室!本期给大家带来Mc我的世界红石研究日记·第四期!版本:JAVA1.14.3. 第三期答题互动答案 以下哪一个选项被红石比较器检测出的红石信号与其他三项不同? ...

  4. 从零开始掌握Python机器学习:七步教程 基础篇

    前言 「开始」往往是最难的,尤其是当选择太多的时候,一个人往往很难下定决定做出选择.本教程的目的是帮助几乎没有 Python 机器学习背景的新手成长为知识渊博的实践者,而且这个过程中仅需要使用免费的材 ...

  5. CART分类树原理及示例

    转载:https://blog.csdn.net/acdreamers/article/details/44664481 在之前介绍过决策树的ID3算法实现,今天主要来介绍决策树的另一种实现,即CAR ...

  6. mnist手写数字分类的python实现_TensorFlow的MNIST手写数字分类问题 基础篇

    本章节的阅读对象是对机器学习和 TensorFlow 都不太了解的新手. 就像我们学习编程的第一步往往是学习敲出 "Hello World" 一样,机器学习的入门就要知道 MNIS ...

  7. TensorFlow的MNIST手写数字分类问题 基础篇

    本次笔记是训练一个机器学习模型用于预测图片里面的数字. 目录 数据集 softmax 模型 实现回归模型 训练模型 评估模型 数据集 MNIST 数据集的官网是Yann LeCun's website ...

  8. 机器学习(四):剪枝技术(基础篇)

    机器学习(四):剪枝技术(基础篇) 相关的决策树文章: 机器学习(四)ID3决策树 机器学习(四)C4.5决策树 机器学习(四)CART分类树 机器学习(四)CART回归树 机器学习(四)决策树绘图 ...

  9. 机器学习-有监督学习-分类算法:决策树算法【CART树:分类树(基于信息熵;分类依据:信息增益、信息增益率、基尼系数)、回归树(基于均方误差)】【损失函数:叶节点信息熵和】【对特征具有很好的分析能力】

    一.决策树概述 注:生产实践中,不使用决策树,太简单,而是使用决策树的升级版:集成学习算法. 集成学习算法有: Random Forest(随机森林) Extremely Randomized For ...

最新文章

  1. linux rz 上传文件夹_第二章Linux服务器环境搭建之Tomcat安装
  2. python基础一入门必备知识-Python从入门到精通要掌握哪些基础知识?
  3. Java中console类的简单用法
  4. 接口测试指导方案 转:紫漪
  5. ActiveMQ添加商品接收消息
  6. CDQ 分治算法模板
  7. qt中实现息屏开平mousepress_QT信号槽分析
  8. HDOJ1860 ( 统计字符 ) 【水题】
  9. imread函数 matlab_【MATLAB图像处理学习】1.读取和显示图片
  10. CoreAnimation编程指南(简介)
  11. 【TensorFlow】Win7+Anaconda+python3.6+Tensorflow1.9安装教程
  12. nrm : 无法加载文件 C:\Users\hc\AppData\Roaming\npm\nrm.ps1 ,因为在此系统上禁止运行脚本。
  13. matlab 0到正无穷求和,1/k!k从0到无穷求和是多少
  14. 拓端tecdat|用R语言模拟随机服务排队系统
  15. 移动APP测试用例设计的关注点
  16. 如何改变Android-studio中的APP的名字和图标
  17. 在家如何下载nature中的文献
  18. 如何下载B站(哔哩哔哩)高清视频?
  19. C语言基础:如何判断素数(质数)与合数
  20. 流媒体服务器ZLMediaKit

热门文章

  1. 【obs】发送前丢帧算法及帧优先级设置
  2. c语言浮点数乘法算法,单精度浮点数乘法的实现
  3. 科学计数法 与 普通数字 转换
  4. Python中的循环语句
  5. 图解蓝牙 BR/EDR 和BLE的区别
  6. 什么是java双精度浮点数_什么是浮点型?单精度浮点数(float)和双精度浮点数(double)介绍...
  7. 【每周一库】- teloxide (电报群机器人)
  8. 基于模糊PID的柴油机调速系统
  9. Redis 设计与实现 5:压缩列表 ziplist
  10. ios11非越狱如何安装ipa