机器学习算法(4)—— 决策树算法_题目 假设我们没有看过世界杯,但是想知道哪支球队会是冠军,我们只能猜测某支球队

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

如下图,第一列为天气,第二列为温度,第三列为湿度,第四列为风速,最后一列该活动是否进行。
我们要解决:根据下面表格数据,判断在对应天气下,活动是否会进行?

在这里插入图片描述
在这里插入图片描述
该数据集有四个属性,属性集合A={ 天气,温度,湿度,风速}, 类别标签有两个,类别集合L={进行,取消}。

a.计算类别信息熵

类别信息熵表示的是所有样本中各种类别出现的不确定性之和。根据熵的概念,熵越大,不确定性就越大,把事情搞清楚所需要的信息量就越多。

在这里插入图片描述
b.计算每个属性的信息熵
在这里插入图片描述
c.计算信息增益

信息增益的 = 熵 - 条件熵,在这里就是 类别信息熵 - 属性信息熵,它表示的是信息不确定性减少的程度。如果一个属性的信息增益越大,就表示用这个属性进行样本划分可以更好的减少划分后样本的不确定性,当然,选择该属性就可以更快更好地完成我们的分类目标。

信息增益就是ID3算法的特征选择指标。
在这里插入图片描述

假设我们把上面表格1的数据前面添加一列为"编号",取值(1–14). 若把"编号"也作为一个候选划分属性,则根据前面步骤: 计算每个属性的信息熵过程中,我们发现,该属性的值为0, 也就是其信息增益为0.940. 但是很明显这么分类,最后出现的结果不具有泛化效果.此时根据信息增益就无法选择出有效分类特征。所以,C4.5选择使用信息增益率对ID3进行改进。

d.计算属性分裂信息度量

用分裂信息度量来考虑某种属性进行分裂时分支的数量信息和尺寸信息,我们把这些信息称为属性的内在信息(instrisic information)。信息增益率用信息增益/内在信息,会导致属性的重要性随着内在信息的增大而减小(也就是说,如果这个属性本身不确定性就很大,那我就越不倾向于选取它),这样算是对单纯用信息增益有所补偿。

在这里插入图片描述
e.计算信息增益率
在这里插入图片描述
天气的信息增益率最高,选择天气为分裂属性。发现分裂了之后,天气是“阴”的条件下,类别是”纯“的(天气是“阴”时,活动都会“进行”),所以把它定义为叶子节点,选择不“纯”的结点继续分裂。

信息增益率越大,代表纯度提升越大,表示这个特征越重要

在这里插入图片描述
在子结点当中重复过程1~5,直到所有的叶子结点足够"纯"。
C4.5的算法流程总结:

while(当前节点"不纯"):
    1.计算当前节点的类别熵(以类别取值计算)
    2.计算当前阶段的属性熵(按照属性取值吓得类别取值计算)
    3.计算信息增益
    4.计算各个属性的分裂信息度量
    5.计算各个属性的信息增益率
end while
当前阶段设置为叶子节点

为什么使用C4.5要好?

  1. 用信息增益率来选择属性

克服了用信息增益来选择属性时偏向选择值多的属性的不足。

  1. 采用了一种后剪枝方法

避免树的高度无节制的增长,避免过度拟合数据

  1. 对于缺失值的处理

在某些情况下,可供使用的数据可能缺少某些属性的值。假如〈x,c(x)〉是样本集S中的一个训练实例,但是其属性A的值A(x)未知。

处理缺少属性值的策略:

  • 一种策略是赋给它结点n所对应的训练实例中该属性的最常见值;
  • 另外一种更复杂的策略是为A的每个可能值赋予一个概率。

例如,给定一个布尔属性A,如果结点n包含6个已知A=1和4个A=0的实例,那么A(x)=1的概率是0.6,而A(x)=0的概率是0.4。于是,实例x的60%被分配到A=1的分支,40%被分配到另一个分支。

C4.5就是使用这种方法处理缺少的属性值。

3.3 基尼指数

CART 决策树 [Breiman et al., 1984] 使用"基尼指数" (Gini index)来选择划分属性。

CART 是Classification and Regression Tree的简称,这是一种著名的决策树学习算法,分类和回归任务都可用

(1)概念

在这里插入图片描述
(2)案例

请根据下图列表,按照基尼指数的划分依据,做出决策树。

在这里插入图片描述

对数据集非序列标号属性{是否有房,婚姻状况,年收入}分别计算它们的Gini指数,取Gini指数最小的属性作为决策树的根节点属性。

① 当根据是否有房来进行划分时,Gini指数计算过程为:

在这里插入图片描述

在这里插入图片描述

② 若按婚姻状况属性来划分,属性婚姻状况有三个可能的取值{married,single,divorced},(CART一定是二叉树)分别计算划分后的Gini指数:

在这里插入图片描述
对比计算结果,根据婚姻状况属性来划分根节点时取Gini指数最小的分组作为划分结果,即:{married} | {single,divorced}

③ 年收入Gini指数:

对于年收入属性为 数值型 属性,首先需要对数据按升序排序,然后从小到大依次用相邻值的中间值作为分隔将样本划分为两组。例如:当面对年收入为60和70这两个值时,我们算得其中间值为65。以中间值65作为分割点求出Gini指数
在这里插入图片描述
根据计算知道,三个属性划分根节点的指数最小的有两个:年收入和婚姻状况,他们的指数都为0.3。此时,选取首先出现的属性【婚姻状况】作为第一次划分

接下来,采用同样的方法,分别计算剩下属性

① 对于是否有房属性,可得:
在这里插入图片描述

② 对于年收入属性则有:

在这里插入图片描述
选取属性【是否有房】作为第二次划分

经过如上流程,构建的决策树,如下图:

在这里插入图片描述

3.4 小结

(1) ID3 决策树算法的缺点

  • ID3算法在选择根节点和各内部节点中的分支属性时,采用信息增益作为评价标准。信息增益的缺点是倾向于选择取值较多的属性,在有些情况下这类属性可能不会提供太多有价值的信息.
  • ID3算法只能对描述属性为离散型属性的数据集构造决策树

(2) C4.5 决策树算法

  • 做出的改进(为什么使用C4.5要好)

    • 用信息增益率来选择属性
    • 除了可以处理离散型描述属性,还可以处理连续数值型属性
    • 采用了一种后剪枝方法
    • 对于缺失值的处理
  • ​ 优点:

    • ​产生的分类规则易于理解,准确率较高。
  • ​ 缺点:

    • ​ 在构造树的过程中,需要对数据集进行多次的顺序扫描和排序,因而导致算法的低效。
    • ​ 此外,C4.5只适合于能够驻留于内存的数据集,当训练集大得无法在内存容纳时程序无法运行。

(3)CART 决策树算法

  • CART算法相比C4.5算法的分类方法,采用了简化的二叉树模型,同时特征选择采用了近似的基尼系数来简化计算。
  • C4.5不一定是二叉树,但CART一定是二叉树。

在这里插入图片描述

4. cart 剪枝

4.1 为何要 cart 剪枝

在这里插入图片描述
图形描述:

  • 横轴表示在决策树创建过程中树的结点总数,纵轴表示决策树的预测精度。
  • 实线显示的是决策树在训练集上的精度,虚线显示的则是在一个独立的测试集上测量出来的精度。
  • 随着树的增长,在训练样集上的精度是单调上升的, 然而在独立的测试样例上测出的精度先上升后下降。

出现这种情况的原因:

  • 噪声、样本冲突,即错误的样本数据。
  • 特征即属性不能完全作为分类标准。
  • 巧合的规律性,数据量不够大。

剪枝 (pruning)是决策树学习算法对付"过拟合"的主要手段。

在决策树学习中,为了尽可能正确分类训练样本,结点划分过程将不断重复,有时会造成决策树分支过多,这时就可能因训练样本学得"太好"了,以致于把训练集自身的一些特点当作所有数据都具有的一般性质而导致过拟合。因此,可通过主动去掉一些分支来降低过拟合的风险

4.2 常用的剪枝方法

决策树剪枝的基本策略有"预剪枝" (pre-pruning)和"后剪枝"(post- pruning) 。

(1)预剪枝

预剪枝是指在决策树生成过程中,对每个结点在划分前先进行估计,若当前结点的划分不能带来决策树泛化性能提升,则停止划分并将当前结点标记为叶结点;

(2)后剪枝

后剪枝则是先从训练集生成一棵完整的决策树,然后自底向上地对非叶结点进行考察,若将该结点对应的子树替换为叶结点能带来决策树泛化性能提升,则将该子树替换为叶结点。

对比两种剪枝方法:

  • 后剪枝决策树通常比预剪枝决策树保留了更多的分支。
  • 一般情形下,后剪枝决策树的欠拟合风险很小,泛化性能往往优于预剪枝决策树。
  • 但后剪枝过程是在生成完全决策树之后进行的。 并且要自底向上地对树中的所有非叶结点进行逐一考察,因此其训练时间开销比未剪枝决策树和预剪枝决策树都要大得多。

5. 特征工程—特征提取

将任意数据(如文本或图像)转换为可用于机器学习的数字特征(特征值化是为了计算机更好的去理解数据)

除此之外,我们还可以在数据预处理过程中将离散的特征数据进行OneHot独热编码。

from sklearn.preprocessing import OneHotEncoder
   
enc = OneHotEncoder()  
enc.fit([[0,0,3],[1,1,0],[0,2,1],[1,0,2]])  # 训练。这里共有4个数据,3种特征
   
array = enc.transform([[0,1,3]]).toarray()  # 测试。这里使用1个新数据来测试
print(array)   # [[ 1 0 0 1 0 0 0 0 1]] # 独热编码结果

特征提取分类:

  • 字典特征提取(特征离散化)
  • 文本特征提取
  • 图像特征提取(深度学习将介绍)

特征提取API:sklearn.feature_extraction

5.1 字典特征提取

作用:对字典数据进行特征值化

sklearn.feature_extraction.DictVectorizer(sparse=True,…)

  • DictVectorizer.fit_transform(X)
    • X:字典或者包含字典的迭代器返回值
    • 返回sparse矩阵
  • DictVectorizer.get_feature_names() 返回类别名称

案例:

我们对以下特征进行提取

[{'city': '北京','temperature':100},
{'city': '上海','temperature':60},
{'city': '深圳','temperature':30}]

from sklearn.feature_extraction import DictVectorizer

data = [{'city': '北京', 'temperature': 100},
        {'city': '上海', 'temperature': 60},
        {'city': '深圳', 'temperature': 30}]

# 1. 实例化一个转换器类
transfer = DictVectorizer()  # 默认sparse=True
# 2. 调用fit\_transform方法输入数据并转换(注意返回格式)
data = transfer.fit_transform(data)
print("返回的结果:\n", data)
# 打印每一列特征名字
names = transfer.get_feature_names()
print(names)

在这里插入图片描述

若为transfer = DictVectorizer(sparse=False)的结果(非sparse矩阵)

在这里插入图片描述

sparse=True 的作用

  • 提高读取效率
  • 节省内存空间

注意:对于特征当中存在类别信息的我们都会做 one-hot 编码处理

5.2 文本特征提取

作用:对文本数据进行特征值化

sklearn.feature_extraction.text.CountVectorizer(stop_words=[])

  • 返回词频矩阵
  • 参数 stop_words:停用词
  • CountVectorizer.fit_transform(X)
    • X:文本或者包含文本字符串的可迭代对象
    • 返回值:返回sparse矩阵
  • CountVectorizer.get_feature_names() 返回值:单词列表

sklearn.feature_extraction.text.TfidfVectorizer

(1)英文文本特征提取

我们对以下数据进行特征提取

["life is short,i like python",
"life is too long,i dislike python"]

from sklearn.feature_extraction.text import CountVectorizer

data = ["life is short,i like like python", "life is too long,i dislike python"]

# 1. 实例化类CountVectorizer
transfer = CountVectorizer() # 要注意CountVectorizer()没有sparse这个参数

# 2. 调用fit\_transform方法输入数据并转换 
# (注意返回格式,利用toarray()将sparse矩阵转换array数组)
data = transfer.fit_transform(data)

print(data)
print(data.toarray())
print("特征名称为:\n",transfer.get_feature_names())

在这里插入图片描述

注意:

  • 单个字符的单词以及标点符号不做统计
  • 英文默认是以空格分开的,其实就达到了一个分词的效果

(2)中文文本特征提取

我们要对中文进行分词处理,需要利用 jieba 分词处理

jieba库的简单用法见:https://blog.csdn.net/hu_wei123/article/details/127121301

对以下三句话进行特征值化

今天很残酷,明天更残酷,后天很美好,
但绝对大部分是死在明天晚上,所以每个人不要放弃今天。

我们看到的从很远星系来的光是在几百万年之前发出的,
这样当我们看到宇宙时,我们是在看它的过去。

如果只用一种方式了解某样事物,你就不会真正了解它。
了解事物真正含义的秘密取决于如何将其与我们所了解的事物相联系。

from sklearn.feature_extraction.text import CountVectorizer
import jieba

data = ["一种还是一种今天很残酷,明天更残酷,后天很美好,但绝对大部分是死在明天晚上,所以每个人不要放弃今天。",
        "我们看到的从很远星系来的光是在几百万年之前发出的,这样当我们看到宇宙时,我们是在看它的过去。",
        "如果只用一种方式了解某样事物,你就不会真正了解它。了解事物真正含义的秘密取决于如何将其与我们所了解的事物相联系。"]

text_list = []
for sentence in data:
    text = " ".join(jieba.lcut(sentence))
    # print(text)
    text_list.append(text)
print(text_list)

# 1. 实例化一个转化器类
transfer = CountVectorizer()

# 2. 调用fit\_transform
data = transfer.fit_transform(text_list)
print("文本特征抽取的结果:\n", data.toarray())
print("返回特征名字:\n", transfer.get_feature_names())

文本特征抽取的结果:
 [[2 0 1 0 0 0 2 0 0 0 0 0 1 0 1 0 0 0 0 1 1 0 2 0 1 0 2 1 0 0 0 1 1 0 0 1 0]
 [0 0 0 1 0 0 0 1 1 1 0 0 0 0 0 0 0 1 3 0 0 0 0 1 0 0 0 0 2 0 0 0 0 0 1 0 1]
 [1 1 0 0 4 3 0 0 0 0 1 1 0 1 0 1 1 0 1 0 0 1 0 0 0 1 0 0 0 2 1 0 0 1 0 0 0]]
返回特征名字:
 ['一种', '不会', '不要', '之前', '了解', '事物', '今天', '光是在', '几百万年', '发出', '取决于', '只用', '后天', '含义', '大部分', '如何', '如果', '宇宙', '我们', '所以', '放弃', '方式', '明天', '星系', '晚上', '某样', '残酷', '每个', '看到', '真正', '秘密', '绝对', '美好', '联系', '过去', '还是', '这样']

(3)Tf-idf文本特征提取

TF-IDF的主要思想是:如果某个词或短语在一篇文章中出现的概率高,并且在其他文章中很少出现,则认为此词或者短语具有很好的类别区分能力,适合用来分类。

TF-IDF的作用:用以评估一字词对于一个文件集或一个语料库中的其中一份文件的重要程度

TF-IDF的重要性:分类机器学习算法进行 文章分类 中前期数据处理方式

在这里插入图片描述

  • 词频(term frequency,tf):指的是某一个给定的词语在该文件中出现的频率
  • 逆向文档频率(inverse document frequency,idf):是一个词语普遍重要性的度量。某一特定词语的idf,可以由总文件数目除以包含该词语之文件的数目,再将得到的商取以10为底的对数得到

最终得出结果 tfidf 可以理解为重要程度

举例:
假如一篇文章的总词语数是100个,而词语"非常"出现了5次,那么"非常"一词在该文件中的词频就是5/100=0.05。
而计算文件频率(IDF)的方法是以文件集的文件总数,除以出现"非常"一词的文件数。
所以,如果"非常"一词在1,0000份文件出现过,而文件总数是10,000,000份的话,
其逆向文件频率就是lg(10,000,000 / 1,0000)=3。
最后"非常"对于这篇文档的tf-idf的分数为0.05 * 3=0.15

其 api 用法同上述中文特征提取

6. 决策树的使用

6.1 决策树 api 介绍

sklearn.tree.DecisionTreeClassifier(criterion=’gini’,max_depth=None,random_state=None)

参数:

  • criterion:特征选择标准

    • 值为"gini"或者"entropy",前者代表基尼系数,后者代表信息增益。一默认"gini",即CART算法。
  • max_depth:决策树最大深度

    • 默认可以不输入,如果不输入的话,决策树在建立子树的时候不会限制子树的深度。一般来说,数据少或者特征少的时候可以不管这个值。如果模型样本量多,特征也多的情况下,推荐限制这个最大深度,具体的取值取决于数据的分布。常用的可以取值10-100之间
  • random_state:随机数种子

  • min_samples_split:内部节点再划分所需最小样本数

    • 这个值限制了子树继续划分的条件,如果某节点的样本数少于min_samples_split,则不会继续再尝试选择最优特征来进行划分。 默认是2.如果样本量不大,不需要管这个值。如果样本量数量级非常大,则推荐增大这个值。我之前的一个项目例子,有大概10万样本,建立决策树时,我选择了min_samples_split=10。可以作为参考。
  • min_samples_leaf:叶子节点最少样本数

    • 这个值限制了叶子节点最少的样本数,如果某叶子节点数目小于样本数,则会和兄弟节点一起被剪枝。 默认是1,可以输入最少的样本数的整数,或者最少样本数占样本总数的百分比。如果样本量不大,不需要管这个值。如果样本量数量级非常大,则推荐增大这个值。之前的10万样本项目使用min_samples_leaf的值为5,仅供参考。

sklearn.tree.export_graphviz()

  • 该函数能够导出DOT格式
  • tree.export_graphviz(estimator,out_file='tree.dot’,feature_names=[‘’,’’])

6.2 案例:泰坦尼克号乘客生存预测

泰坦尼克号沉没是历史上最臭名昭着的沉船之一。1912年4月15日,在她的处女航中,泰坦尼克号在与冰山相撞后沉没,在2224名乘客和机组人员中造成1502人死亡。这场耸人听闻的悲剧震惊了国际社会,并为船舶制定了更好的安全规定。 造成海难失事的原因之一是乘客和机组人员没有足够的救生艇。尽管幸存下沉有一些运气因素,但有些人比其他人更容易生存,例如 妇女,儿童和上流社会 (也就是与性别 Sex年龄 Age社会阶层 Pclass有关)。 在这个案例中,我们要求您完成对哪些人可能存活的分析。特别是,我们要求您运用机器学习工具来预测哪些乘客幸免于悲剧。

在这里插入图片描述
经过观察数据得到,其中 Age 数据存在缺失。

泰坦尼克号数据集获取:https://pan.baidu.com/s/13L6UxNxd2XzgA0rERsXHrg?pwd=blhx
本数据集是从kaggle平台获取,为了实验方便并将train.csv重命名为titanic.csv,读者也可直接从kaggle平台:https://www.kaggle.com/c/titanic/overview,自行下载实验

import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.feature_extraction import DictVectorizer
from sklearn.tree import DecisionTreeClassifier,export_graphviz
# 1.获取数据
titanic = pd.read_csv("./titanic.csv")

# 2.数据基本处理
# 2.1 确定特征值,目标值
x = titanic[["Sex","Age","Pclass"]]
y = titanic["Survived"]



![img](https://img-blog.csdnimg.cn/img_convert/725c5b8ea15029bb2bb94dd42824b3d2.png)
![img](https://img-blog.csdnimg.cn/img_convert/42c9f0469bdd690a245b50fc024f502e.png)
![img](https://img-blog.csdnimg.cn/img_convert/4f46994f0bddd61cf566967f1f568b72.png)

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上大数据知识点,真正体系化!**

**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**

**[需要这份系统化资料的朋友,可以戳这里获取](https://bbs.csdn.net/topics/618545628)**


from sklearn.model_selection import train_test_split
from sklearn.feature_extraction import DictVectorizer
from sklearn.tree import DecisionTreeClassifier,export_graphviz
# 1.获取数据
titanic = pd.read_csv("./titanic.csv")

# 2.数据基本处理
# 2.1 确定特征值,目标值
x = titanic[["Sex","Age","Pclass"]]
y = titanic["Survived"]



[外链图片转存中...(img-Kd4O7HCL-1715825849938)]
[外链图片转存中...(img-Gb6Po8Du-1715825849938)]
[外链图片转存中...(img-v3za7nAL-1715825849938)]

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上大数据知识点,真正体系化!**

**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**

**[需要这份系统化资料的朋友,可以戳这里获取](https://bbs.csdn.net/topics/618545628)**

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值