机器学习测试笔记(14)——决策树与随机森林(上)

简介: 机器学习测试笔记(14)——决策树与随机森林(上)

1决策树模型


1.1基本概念

决策树类似于我们玩的读心游戏,一个人问问题,另一个人只能回答yes或no。比如:

问:这是个人吗?回答:是

问:是女生吗?回答:不是

问:他戴眼镜吗?回答:是

一直猜出回答者的正确答案。如下图所示。

 

image.png


1.2 信息增益与基尼不纯度

在介绍决策树之前我们先来介绍下信息熵,信息熵是约翰·香农根据热力学第二定律,在 1948《通信的数学原理》一书中提出,主要思想是:一个问题不确定性越大,需要获取的信息就越多,信息熵就越大;一个问题不确定性越小,需要获取的信息就越少,信息熵就越小。比如“小张今天会不会在9:00之前到公司”的信息熵就比“小张今天会不会吃早饭”的信息熵要高,因为小张长久以来没有不吃早饭的习惯。


信息熵是这样定义的:假设集合D中第k类样本的比率为pk,(k=1,2,…|y|)

Ent(D)=

image.png


在决策树中有两个概念:信息增益(Information Gain)和基尼不纯度(Gini impurity)。

信息增益(Information Gain):划分数据前后数据信息熵的差值。

信息增益纯度越高,纯度提升越大;信息增益纯度越低,纯度提升越小。

信息增益使用的是ID3算法(改进后为C4.5算法)。决策树在选取节点的时候,计算每个特征值划分后的信息增益,选取信息增益最大的节点。

基尼不纯度:反映从集合D中随机取两个样本后,其类别不一致性的概率。

 image.png


基尼不纯度使用的是CART算法。决策树在集合中要选取基尼不纯度最小的那个节点。


1.3 Sklearn中的决策树构建

Sklearn中使用sklearn.tree.DecisionTreeClassifier构建决策树分类;from sklearn.tree import DecisionTreeRegressor构建决策树回归。 


import numpy as np
import matplotlib.pyplot as plt
from matplotlib.colors import ListedColormap
from sklearn import tree,datasets
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import train_test_split
def base_of_decision_tree(max_depth):
        wine = datasets.load_wine()
# 仅选前两个特征
        X = wine.data[:,:2]
        y = wine.target
        X_train,X_test,y_train,y_test = train_test_split(X, y)
        clf = DecisionTreeClassifier(max_depth=max_depth)
        clf.fit(X_train,y_train)
#定义图像中分区的颜色和散点的颜色,允许用户使用十六进制颜色码来定义自己所需的颜色库                
        cmap_light = ListedColormap(['#FFAAAA','#AAFFAA','#AAAAFF'])
        cmap_bold = ListedColormap(['#FF0000','#00FF00','#0000FF']
#分别将样本的两个特征值创建图像的横轴和纵轴
        x_min,x_max = X_train[:,0].min()-1,X_train[:,0].max()+1
        y_min,y_max = X_train[:,1].min()-1,X_train[:,1].max()+1
        xx, yy = np.meshgrid(np.arange(x_min, x_max, .02),np.arange(y_min, y_max, .02))
#给每个样本分配不同的颜色, predict:训练后返回预测结果,显示标签值
        Z = clf.predict(np.c_[xx.ravel(),yy.ravel()])
        Z = Z.reshape(xx.shape)
        plt.figure()
# plt.pcolormesh的作用在于能够直观表现出分类边界
        plt.pcolormesh(xx,yy,Z,cmap=cmap_light,shading='auto')
#用散点把样本表示出来
        plt.scatter(X[:,0],X[:,1],c=y,cmap=cmap_bold,s=20,edgecolors='k')
        plt.xlim(xx.min(),xx.max()) 
        plt.ylim(yy.min(),yy.max())
        plt.title("Classifier:(max_depth="+str(max_depth)+")")
        print("红酒数据训练集(max_depth="+str(max_depth)+"):{:.2f}".format(clf.score(X_train,y_train)))
        print("红酒数据测试集(max_depth="+str(max_depth)+"):{:.2f}".format(clf.score(X_test,y_test)))
        plt.show()


 输出

红酒数据训练集(max_depth=1):0.68
红酒数据测试集(max_depth=1):0.69
红酒数据训练集(max_depth=3):0.88
红酒数据测试集(max_depth=3):0.76
红酒数据训练集(max_depth=5):0.90
红酒数据测试集(max_depth=5):0.84


 当为max_depth(即树的深度)为1、3、5的时候,划分如下图: 

image.png


通过图和输出结果,都可以看出,随着max_depth增加,划分越精确( max_depth=1的时候完全是不正确的)。但是我们会发现所有的数据测试集都低于训练集的值,这就是决策树最致命的一点:容易过拟合。


1.4剪枝

解决过拟合的方法是剪枝,预剪枝(Pre-pruning)和后剪枝(post-pruning)。预剪枝及早停止树的增长;后剪枝先形成树,然后再剪枝。Sklearn仅采用预剪枝的策略,预剪枝可以分以下三种方法中的任意一种来解决。


限制最大深度

限制叶节点数最大数目

规定一个节点数据点的最小数目

我们以Sklearn乳腺癌数据采取限制最大深度来看一下防止过拟合的效果。 


from sklearn.datasets import load_breast_cancer
from sklearn.tree import DecisionTreeClassifier
def decision_tree():
    cancer = load_breast_cancer()
    x_train,x_test,y_train,y_test = train_test_split(cancer.data,cancer.target,stratify=cancer.target,random_state=42)
    tree = DecisionTreeClassifier(random_state=0) # 构件树,不剪枝
    tree.fit(x_train,y_train)
    print("不剪枝,训练数据集上的精度:{:.3f}".format(tree.score(x_train,y_train)))
    print("不剪枝,测试数据集上的精度:{:.3f}".format(tree.score(x_test,y_test)))
    print("不剪枝,树的深度:{}".format(tree.get_depth()))
    tree = DecisionTreeClassifier(max_depth=4,random_state=0) # 构件树,剪枝
    tree.fit(x_train,y_train)
    print("剪枝,训练数据集上的精度:{:.3f}".format(tree.score(x_train,y_train)))
    print("剪枝,测试数据集上的精度:{:.3f}".format(tree.score(x_test,y_test)))
    print("剪枝,树的深度:{}".format(tree.get_depth()))


 输出 


不剪枝,训练数据集上的精度:1.000
不剪枝,测试数据集上的精度:0.937
不剪枝,树的深度:7
剪枝,训练数据集上的精度:0.988
剪枝,测试数据集上的精度:0.951
剪枝,树的深度:4


 可见树的深度为7的时候,测试数据集的得分<训练数据集的得分。但是当树的深度为4的时候,测试数据集的得分几乎等于训练数据集的得分。


1.5 决策树的可视化

为了看到可视化的决策树,首先需要下载并且安装一个软件Graphviz的软件,Graphviz 是一款由AT&T Research和Lucent Bell实验室开源的可视化图形工具。然后打开命令行,输入pip3 install graphviz。接下来运行下面代码。


from sklearn.tree import export_graphviz
import graphviz
def show_tree():
    wine = datasets.load_wine()
# 仅选前两个特征
    X = wine.data[:,:2]
    y = wine.target
    X_train,X_test,y_train,y_test = train_test_split(X, y)
    clf = DecisionTreeClassifier(max_depth=3)#为了图片不太大选择max_depth=3
    clf.fit(X_train,y_train) export_graphviz(clf,out_file="wine.dot",class_names=wine.target_names,feature_names=wine.feature_names[:2],impurity=False,filled=True)
#打开dot文件
with open("wine.dot") as f:
        dot_graph = f.read()
    graphviz.Source(dot_graph)


 在本地目录下生成wine.dot文件,用Graphviz软件打开,得到如图图片。

 

image.png

总结一下,决策树的优点是:容易可视化和无需对数据进行预处理;缺点是即使采取剪枝也会造成过拟合。解决这个问题最有利的方法是采用随机森林模型。


2 随机森林模型


2.1基本概念

2001年Breiman把分类树组合成随机森林(Breiman 2001a),即在变量(列)的使用和数据(行)的使用上进行随机化,生成很多分类树,再汇总分类树的结果。随机森林在运算量没有显著提高的前提下提高了预测精度。


算法流程:

构建决策树的个数t,单颗决策树的特征个数f,m个样本,n个特征数据集

1 单颗决策树训练

1.1 采用有放回抽样,从原数据集经过m次抽样,获得有m个样本的数据集(可能有重复样本)

1.2 从n个特征里,采用无放回抽样原则,去除f个特征作为输入特征

1.3 在新的数据集(m个样本, f个特征数据集上)构建决策树

1.4 重复上述过程t次,构建t棵决策树

2 随机森林的预测结果

生成t棵决策树,对于每个新的测试样例,综合多棵决策树预测的结果作为随机森林的预测结果。

  回归问题:取t棵决策树预测值的平均值作为随机森林预测结果

  分类问题:少数服从多数的原则,取单棵的分类结果作为类别随机森林预测结果

在Sklearn中RandomForestClassifier和RandomForestRegressor分类和回归树算法。


2.2 Sklearn中的构建随机森林

from sklearn.ensemble import RandomForestClassifier
def base_of_decision_tree_forest(n_estimator,random_state):
    wine = datasets.load_wine()
# 仅选前两个特征
    X = wine.data[:,:2]
    y = wine.target
    X_train, X_test, y_train, y_test = train_test_split(X, y)
    forest = RandomForestClassifier(n_estimators=n_estimator, random_state=random_state, n_jobs=2) 
#n_jobs:设置为CPU个数
# 在训练数据集上进行学习
    forest.fit(X_train, y_train)
    cmap_light = ListedColormap(['#FFAAAA','#AAFFAA','#AAAAFF’])
    cmap_bold =  ListedColormap(['#FF0000','#00FF00','#0000FF’])
#分别将样本的两个特征值创建图像的横轴和纵轴
    x_min,x_max = X_train[:,0].min()-1,X_train[:,0].max()+1
    y_min,y_max = X_train[:,1].min()-1,X_train[:,1].max()+1
xx, yy = np.meshgrid(np.arange(x_min, x_max, .02),np.arange(y_min, y_max, .02))
#给每个样本分配不同的颜色
  Z = forest.predict(np.c_[xx.ravel(),yy.ravel()])
  Z = Z.reshape(xx.shape)
  plt.pcolormesh(xx,yy,Z,cmap=cmap_light,shading='auto’)
  #用散点把样本表示出来
  plt.scatter(X[:,0],X[:,1],c=y,cmap=cmap_bold,s=20,edgecolors='k’)
  plt.xlim(xx.min(),xx.max()) 
  plt.ylim(yy.min(),yy.max())
  print("红酒数据随机森林训练集得分(n_estimators:"+str(n_estimator)+",random_state:"+str(random_state)+"):{:.2f}".format(forest.score(X_train,y_train)))
  print("红酒数据随机森林测试集得分(n_estimators:"+str(n_estimator)+",random_state:"+str(random_state)+"):{:.2f}".format(forest.score(X_test,y_test)))
def tree_forest():
#定义图像中分区的颜色和散点的颜色
    figure,axes = plt.subplots(4,4,figsize =(100,10))
  plt.subplots_adjust(hspace=0.95)
    i = 0
for n_estimator in range(4,8):
for random_state in range(2,6):
            plt.subplot(4,4,i+1)
            plt.title("n_estimator:"+str(n_estimator)+"random_state:"+str(random_state))
            plt.suptitle("Classifier:RandomForest")
            base_of_decision_tree_forest(n_estimator,random_state)
            i = i + 1
    plt.show()


 得到的结果总结如下表。

image.png

image.png


2.3 随机森林避免过拟合

我们以2个月亮数据进行分析。 


import mglearn
def my_RandomForet():
# 生成一个用于模拟的二维数据集
  X, y = datasets.make_moons(n_samples=100, noise=0.25, random_state=3)
# 训练集和测试集的划分
  X_train, X_test, y_train, y_test = train_test_split(X, y, stratify=y,random_state=42)
# 初始化一个包含 5 棵决策树的随机森林分类器
  forest = RandomForestClassifier(n_estimators=5, random_state=2)
# 在训练数据集上进行学习
  forest.fit(X_train, y_train)
# 可视化每棵决策树的决策边界
  fig, axes = plt.subplots(2, 3, figsize=(20, 10))
for i, (ax, tree) in enumerate(zip(axes.ravel(), forest.estimators_)):
    ax.set_title('Tree {}'.format(i))
    mglearn.plots.plot_tree_partition(X_train, y_train, tree, ax=ax)
    print("决策树"+str(i)+"训练集得分:{:.2%}".format(tree.score(X_train,y_train)))
    print("决策树"+str(i)+"测试集得分:{:.2%}".format(tree.score(X_test,y_test)))
# 可视化集成分类器的决策边界
  print("随机森林训练集得分:{:.2%}".format(forest.score(X_train,y_train)))
  print("随机森林测试集得分:{:.2%}".format(forest.score(X_test,y_test)))
  mglearn.plots.plot_2d_separator(forest, X_train, fill=True, ax=axes[-1, -1],alpha=0.4)
  axes[-1, -1].set_title('Random Forest')
  mglearn.discrete_scatter(X_train[:, 0], X_train[:, 1], y_train)
  plt.show()


 输出

image.png

image.png


虽然决策树3不存在过拟合,决策树4的差值与随机森林得分一致,但是随机森林得分比他们都要高。

目录
相关文章
|
7月前
|
存储 数据可视化 测试技术
一个测试工程师的实战笔记:我是如何在Postman和Apipost之间做出选择的?
优秀的API测试工具应该具备: 分层设计:既有可视化操作,也开放代码层深度定制 场景感知:自动识别加密需求推荐处理方案 协议包容:不强迫开发者为了不同协议切换工具 数据主权:允许自主选择数据存储位置
184 7
|
10月前
|
机器学习/深度学习 算法 UED
在数据驱动时代,A/B 测试成为评估机器学习项目不同方案效果的重要方法
在数据驱动时代,A/B 测试成为评估机器学习项目不同方案效果的重要方法。本文介绍 A/B 测试的基本概念、步骤及其在模型评估、算法改进、特征选择和用户体验优化中的应用,同时提供 Python 实现示例,强调其在确保项目性能和用户体验方面的关键作用。
313 6
|
11月前
|
机器学习/深度学习 JSON 算法
实例分割笔记(一): 使用YOLOv5-Seg对图像进行分割检测完整版(从自定义数据集到测试验证的完整流程)
本文详细介绍了使用YOLOv5-Seg模型进行图像分割的完整流程,包括图像分割的基础知识、YOLOv5-Seg模型的特点、环境搭建、数据集准备、模型训练、验证、测试以及评价指标。通过实例代码,指导读者从自定义数据集开始,直至模型的测试验证,适合深度学习领域的研究者和开发者参考。
3679 3
实例分割笔记(一): 使用YOLOv5-Seg对图像进行分割检测完整版(从自定义数据集到测试验证的完整流程)
|
11月前
|
测试技术
自动化测试项目实战笔记(三):测试用户注册(验证码错误,成功,出现弹框时处理)
本文是关于自动化测试项目实战笔记,主要介绍了如何测试用户注册功能,包括验证码错误、注册成功以及弹框处理的测试步骤和代码实现。
364 2
自动化测试项目实战笔记(三):测试用户注册(验证码错误,成功,出现弹框时处理)
|
10月前
|
机器学习/深度学习 算法 UED
在数据驱动时代,A/B 测试成为评估机器学习项目效果的重要手段
在数据驱动时代,A/B 测试成为评估机器学习项目效果的重要手段。本文介绍了 A/B 测试的基本概念、步骤及其在模型评估、算法改进、特征选择和用户体验优化中的应用,强调了样本量、随机性和时间因素的重要性,并展示了 Python 在 A/B 测试中的具体应用实例。
231 1
|
11月前
|
Java 关系型数据库 MySQL
自动化测试项目实战笔记(一):JDK、Tomcat、MySQL、Jpress环境安装和搭建
这篇文章是关于自动化测试项目实战笔记,涵盖了JDK、Tomcat、MySQL、Jpress环境的安装和搭建过程,以及测试用例和常见问题总结。
230 1
自动化测试项目实战笔记(一):JDK、Tomcat、MySQL、Jpress环境安装和搭建
|
11月前
|
安全
红队测试方法论-课程笔记
红队测试方法论-课程笔记
红队测试方法论-课程笔记
|
11月前
|
机器学习/深度学习 弹性计算 自然语言处理
前端大模型应用笔记(二):最新llama3.2小参数版本1B的古董机测试 - 支持128K上下文,表现优异,和移动端更配
llama3.1支持128K上下文,6万字+输入,适用于多种场景。模型能力超出预期,但处理中文时需加中英翻译。测试显示,其英文支持较好,中文则需改进。llama3.2 1B参数量小,适合移动端和资源受限环境,可在阿里云2vCPU和4G ECS上运行。
500 1
|
11月前
|
计算机视觉
目标检测笔记(二):测试YOLOv5各模块的推理速度
这篇文章是关于如何测试YOLOv5中不同模块(如SPP和SPPF)的推理速度,并通过代码示例展示了如何进行性能分析。
451 3
|
11月前
|
人工智能 算法 测试技术
自动化测试项目实战笔记(二):解决验证码识别问题
这篇文章介绍了三种自动化测试中验证码识别的方法:使用Python的pytesseract和PIL模块、利用第三方API如万维易源,以及使用开源的ddddocr库,还提到了一些注意事项,比如如何获取验证码区域的截图。
372 2