sklearn入门&决策树在sklearn中的实现

sklearn入门

scikit-learn官网:http://scikit-learn.org/stable/index.html
中文翻译网址:https://sklearn.apachecn.org/docs/master/2.html
算法原理推荐书籍:《数据挖掘导论》、《机器学习》

决策树

1 概述

非参数的有监督学习方法,决策树算法的本质是一种图结构
通过对记录的特征的提问,对样本进行分类

关于决策树的节点概念:
1、根节点:没有进边,有出边,包含最初的,针对特征的提问
2、中间节点:既有进边也有出边,进边只有一条,出边可以有很多条,都是针对特征的提问
3、叶子节点:有进边,没有出边,每个叶子节点都有一个类别标签
4、子节点和父节点:在两个相连的节点中,更接近根节点的是父节点,另一个是子节点

1.1 决策树是如何工作的

决策树算法的核心要解决两个问题:
1、如何从数据表中找出最佳节点和最佳分支?
2、如何让决策树停止生长,防止过拟合?

1.2 sklearn中的决策树

  • 模块sklearn.tree
    包含决策树相关的所有类(不包含集成算法),总共五个类:
  • tree.DecisionTreeClassifier分类树
  • tree.DecisionTreeRegressor回归树
  • tree.export_graphviz将生成的决策树导出为DOT格式,画图专用
  • tree.ExtraTreeClassifier高随机版本的分类树
  • tree.ExtraTreeRegressor高随机版本的回归树
  • sklearn建模的基本流程
    sklearn入门&决策树在sklearn中的实现_第1张图片
    对应的代码:
from sklearn import tree	#导入需要的模块

clf = tree.DecisionTreeClassifier()		#实例化,需要使用的参数填入()中
clf = clf.fit(x_train,y_train)			#用训练集数据训练模型,使用fit接口
result = clf.score(x_train,y_train)		#导入测试数据集,利用score接口调用需要的信息

2 DecisionTreeClassifier与红酒数据集

sklearn.DecisionTreeClassifier(criterion=‘gini’,splitter=‘best’,max_depth=None,min_samples_split=2,min_samples_leaf=1,min_weight -raction_leaf=0.0,max_features=None,random_state=None,max_leaf_nodes=None,min_impurity=0.0,min_impurity_split=None,class_weight=None,presort=False)

2.1 重要参数

8个重要的参数

2.1.1 criterion

决策树需要找出最佳节点和最佳的分枝方法,衡量“最佳”的指标叫“不纯度”,不纯度越低,决策树对训练集的拟合越好。
不纯度基于节点计算,书中的每个节点都有一个不纯度,并且子节点的不纯度一定是低于父节点的,可以说,在同一颗决策树上,叶子节点的不纯度是最低的。
criterion是用来决定不纯度的计算方法,可选项

  • entropy:信息熵,实际计算的是基于信息熵的信息增益,即父节点的信息熵和子节点信息熵之差
  • gini:基尼系数
    sklearn入门&决策树在sklearn中的实现_第2张图片
    相交于基尼系数,信息熵对不纯度更加敏感,对不纯度的惩罚最强。在使用中,信息熵和基尼系数的效果差不多,只不过信息熵计算速度稍慢。由于信息熵对不纯度敏感,当信息熵作为指标时,决策树生长更精细,对于高维数据或噪声很多的数据,信息熵容易过拟合,使用基尼系数往往会更好。
    选取参数的方法:通常使用基尼系数。数据维度很大、噪音很大的时候使用基尼系数;维度低、数据比较清晰的时候,信息熵和基尼系数没有区别。当决策树的拟合程度不够(欠拟合)的时候,使用信息熵。可以两个都试试,取效果更好的
    在这里插入图片描述
2.1.2 random_state&splitter

random_state用来设置分枝中的随机模式的参数,默认为None,在高维度时随机性会表现更明显,低纬度的数据随机性几乎 不会显现,输入任意整数,会一直长出同一棵树,让模型稳定下来。
splitter也是用来控制决策树中的随机选项的,有两种输入值:输入“best”,决策树在分枝时虽然随机,但会优先选择更重要的特征进行分枝;输入“random”,分枝时会更随机,树会更深,对训练集的拟合将会降低。
当预测到模型会过拟合时,用这两个参数会帮助降低过拟合的可能性。

2.1.3 剪枝参数

过拟合:在训练集上表现很好,在测试集上表现糟糕
为了使决策树局有更好的泛化性,要对其进行剪枝。剪枝策略对决策树影响巨大,正确的剪枝策略是优化决策树算法的核心。
sklearn提供多种剪枝策略:

  • max_depth:限制数的最大深度,超过设定深度的树枝全部剪掉,是使用最广泛的剪枝参数,在高维度低样本量时非常有效。实际使用时,建议从3开始尝试,根据拟合的效果再决定是否增加设定深度。
  • min_samples_leaf & min_samples_split:min_samples_leaf是限定一个节点在分枝后的每个子节点都必须包含至少min_samples_leaf个训练样本,否则,分枝就不会发生,或者分枝会朝着满足每个子节点都包含min_samples_leaf个样本的方向去发生,一般搭配max_depth使用,在回归树中有神奇的效果,可以让模型更加平滑,这个参数的数量设置的过小会引起过拟合,设置得太大会阻止模型学习数据,一般建议从5开始使用,如果叶节点中含有的样本量变化很大,建议输入浮点数作为样本量的百分比使用(当训练集和测试集的样本量区别很大,使用绝对量限制叶节点中样本数量比较不合理,此时使用相对样本数量更合适),这个参数可以保证每个叶子的最小尺寸,可以在回归问题中避免低方差、过拟合的叶子节点的出现,对于类别不多的分类问题,设置为1通常是最佳选择;min_samples_split限定一个节点必须要包含至少 min_samples_split个训练样本,这个节点才被允许被分枝,否则分枝不会发生。
  • max_features & min_impurity_decrease:max_features限制分枝时考虑的特征个数,超过限制个数的特征都会被舍弃,和max_depth异曲同工,max_features是用来限制高维度数据过拟合的剪枝参数,但方法比较暴力,是直接限制可以使用的特征数量,强行消减数据的信息量来使决策树停下,在不知道决策树中的各个特征的重要性的情况下,情形设定这个参数会导致模型学习不足,如果希望通过降维的方式防止过拟合,建议使用PCA、ICA或者特征选择模块中的降维算法;min_impurity_decrease限制信息增益的大小,信息增益小于设定数值的分枝不会发生。
    确认最优的剪枝参数:使用超参数的曲线来进行判断。超参数的学习曲线是一条以超参数的取值为横坐标,模型的度量指标为纵坐标的曲线,它是用来衡量不同超参数取值下模型的表现曲线。
    Q1:剪枝参数一定能够提升模型在测试集上的表现吗?A1:调参没有绝对的答案,一切都是看数据本身。
    Q2:这么多参数,一个个画学习曲线吗?A2:不是
2.1.4 目标权重参数

class_weight & min_weight_fraction_leaf:都是完成样本标签平衡的参数。样本不平衡是指在一组数据集中,标签的一类天生占有很大的比例。要使用class_weight参数对样本标签进行一定的均衡,给少量的标签更多的权重,让模型偏向少数类,向捕获少数类的方向建模,该参数默认为None,表示自动给予数据集中的所有标签相同的权重。有了权重之后,样本量就不再是单纯地记录数目,而是受输入的权重影响了。此时剪枝就需要搭配min_weight_fraction_leaf这个基于权重的剪枝参数来使用。基于权重的剪枝参数(min_weight_fraction_leaf)将比不知道样本权重的标准(min_samples_leaf)更少偏向主导类。如果样本是加权的,则使用基于权重的预修剪标准更容易优化树结构,这确保叶节点至少包含样本权重总和的一小部分。

2.2 重要属性和接口

属性是在模型训练之后,能够调用查看的模型的各种性质。决策树中最重要的属性是feature_importances_,查看各个特征对模型的重要性。
sklearn中许多算法的接口都是相似的,如fit和score。决策树最常用的接口还有apply和predict,apply中输入测试集的特征返回每个测试样本所在叶子结点的索引,predict输入测试集的特征返回每个测试样本的标签(分类/回归结果)。
**所有接口中要求输入X_train和X_test的部分,输入的特征矩阵必须至少是一个二维矩阵,sklearn不接受任何一维矩阵作为特征矩阵被输入。**如果数据的确只有一个特征,那必须使用reshape(-1,1)来给矩阵增维;如果数据只有一个特征和一个样本,使用reshape(1,-1)来给数据增维。

3 DecisionTreeRegressor

sklearn.DecisionTreeRegressor(criterion=‘mse’,splitter=‘best’,max_depth=None,min_samples_split=2,min_samples_leaf=1,min_weight -raction_leaf=0.0,max_features=None,random_state=None,max_leaf_nodes=None,min_impurity=0.0,min_impurity_split=None,presort=False)
几乎所有的参数、属性和接口都和分类树一模一样。注意:在回归树中,没有标签分布是否均衡的问题,因此没有class_weight这一参数。

3.1 重要参数、属性及接口

  • criterion
    回归树衡量分枝质量的指标,支持的标准有三种:
  • 输入‘mse’使用均方误差,父节点和叶子结点之间的均方误差的差额将被用来作为特征选择的标准,这种方法通过使用叶子结点的均值来最小化L2损失
  • 输入‘friedman_mse’使用费尔德曼均方误差,这种指标是针对潜在分枝中的问题改进后的均方误差
  • 输入‘mae’使用绝对平均误差,这种指标使用叶子结点的中值来最小化L1损失
    在回归树中,MSE不只是分枝质量衡量指标,也是最常用的衡量回归树回归质量的指标。当使用交叉验证或者其他方式获取回归树的结果时,往往选择均方误差作为评估标准(在分类树中这个指标时score,代表预测的准确率)。在回归中,追求MSE越小越好。
  • 属性
    属性中最重要的依然是feature_importances_
  • 接口
    接口依然是apply、fit、predict、score最核心。
    回归树的接口score返回的是R平方,并不是MSE。
    R方可以为正可以为负,MSE永远为正。虽然均方误差永远为正,但sklearn中使用均方误差作为评判标准时,计算的是“负均方误差(neg_mean_squared_error)”。因为sklearn在计算模型评价指标时,会考虑指标本身的性质,均方误差本身是一种误差,所以被sklearn划分为模型的一种损失,因此在sklearn中都以负数表示。真正的均方误差MSE的数值,就是neg_mean_squared_error去掉负号的值。
  • 补充:交叉验证
    交叉验证是用来观察模型的稳定性的一种方法,将数据划分为n份,依次使用其中一份作为测试集,其他n-1份作为训练集,多次计算模型的精确性来评估模型的平均准确程度。训练集和测试集的划分会干扰模型的结果,交叉验证使得模型训练结果更稳定。
    sklearn入门&决策树在sklearn中的实现_第3张图片
#交叉验证cross_val_score的用法
from sklearn.datasets import load_boston
from sklearn.model_selection import cross_val_score
from sklearn.tree import DecisionTreeRegressor
boston = load_boston()
regressor = DecisionTreeRegressor(random_state = 0)
cross_val_score(regressor,boston.data,boston.target,cv = 10
               #,scoring = "neg_mean_squared_error"
               #scoring默认返回R方
               )
'''
结果:
array([ 0.48141081,  0.60461936, -1.32633384,  0.54154398,  0.75705408,
        0.33934083,  0.18757206,  0.40679147, -1.9602183 , -0.32967889])
'''

3.2 实例:一维回归的图像绘制

观察决策树是如何拟合一条曲线的,用回归树来拟合正弦曲线,并添加一些噪声来观察回归树的表现。

#导入需要的库
import numpy  as np
from sklearn.tree import DecisionTreeRegressor
import matplotlib.pyplot as plt

#创建一条含有噪声的正弦曲线
#基本思路:创建一组随机的,分布在0-5上的横坐标的取值(x),然后将这组数据放到sin函数中去生成纵坐标的值(y),接着再到y上去添加噪声
rng = np.random.RandomState(1)#设置随机数种子
x=np.sort(5 * rng.rand(80,1),axis = 0)#80行1列,因为fit不支持一维数据
y = np.sin(x).ravel()
plt.figure()
plt.scatter(x,y,s=20,edgecolor = 'black',c='darkorange',label = 'data')
#结果:

sklearn入门&决策树在sklearn中的实现_第4张图片

#np.random.rand(数据结构),生成随机数组的函数
#了解降维函数ravel()的用法
np.random.random((2,1))
np.random.random((2,1)).ravel()
np.random.random((2,1)).ravel().shape
#结果:(2,)
y[::5] += 3 * (0.5-rng.rand(16))#加上噪声
plt.scatter(x,y,s=20,edgecolor = 'black',c='darkorange',label = 'data')
#结果:

sklearn入门&决策树在sklearn中的实现_第5张图片

#实例化&训练模型
regr_1 = DecisionTreeRegressor(max_depth = 2)
regr_2 = DecisionTreeRegressor(max_depth = 5)
regr_1.fit(x,y)
regr_2.fit(x,y)
#结果:DecisionTreeRegressor(max_depth=5)
#测试集导入模型,预测结果
x_test = np.arange(0.0,5.0,0.01)[:,np.newaxis]
y_1 = regr_1.predict(x_test)
y_2 = regr_2.predict(x_test)
#np.arange(开始点,结束点,步长)生成有序数组的函数
#了解增维切片np.newaxis的用法
l = np.array([1,2,3,4])
l
l.shape
l[:,np.newaxis]
l[:,np.newaxis].shape
l[np.newaxis,:].shape
#结果:(1, 4)
#绘制图像
plt.figure()
plt.scatter(x,y,s=20,edgecolor = 'black',c = 'darkorange',label = 'data')
plt.plot(x_test,y_1,color = 'cornflowerblue',label = "max_depth=2",linewidth = 2)
plt.plot(x_test,y_2,color = 'yellowgreen',label = "max_depth=5",linewidth = 2)
plt.xlabel('data')
plt.ylabel("target")
plt.title("Decision Tree Regression")
plt.legend()
plt.show()

sklearn入门&决策树在sklearn中的实现_第6张图片
可以看到,如果树的最大深度(由max_depth参数控制)设置得太高,则决策树学习得太精细,他从训练数据中学了很多细节,包括噪声得呈现,从而使 模型偏离真实的正弦曲线,形成过拟合。

4 实例:泰坦尼克号幸存者的预测

数据集:https://www.kaggle.com/c/titanic,下载不了可私信我吖~~
目标:通过分类树模型来预测哪些人可能成为幸存者

#导入所需要的库
import pandas as pd
from sklearn.tree import DecisionTreeClassifier
import matplotlib.pyplot as plt
from sklearn.model_selection import GridSearchCV

#导入数据集,探索数据
data = pd.read_csv(r"C:\Users\86188\Desktop\coding\kaggle-titanic-master\input\train.csv")
#data = pd.read_csv("C:/Users/86188/Desktop/coding/kaggle-titanic-master/input/train.csv")
data.head(10)

sklearn入门&决策树在sklearn中的实现_第7张图片

data.info()
'''
结果:

RangeIndex: 891 entries, 0 to 890
Data columns (total 12 columns):
 #   Column       Non-Null Count  Dtype  
---  ------       --------------  -----  
 0   PassengerId  891 non-null    int64  
 1   Survived     891 non-null    int64  
 2   Pclass       891 non-null    int64  
 3   Name         891 non-null    object 
 4   Sex          891 non-null    object 
 5   Age          714 non-null    float64
 6   SibSp        891 non-null    int64  
 7   Parch        891 non-null    int64  
 8   Ticket       891 non-null    object 
 9   Fare         891 non-null    float64
 10  Cabin        204 non-null    object 
 11  Embarked     889 non-null    object 
dtypes: float64(2), int64(5), object(5)
memory usage: 83.7+ KB
'''
#筛选特征
data.drop(["Cabin","Name","Ticket"],inplace=True,axis=1)#删除列
#data = data.drop(["Cabin","Name","Ticket"],inplace = False)
data

sklearn入门&决策树在sklearn中的实现_第8张图片

#处理缺失值
data["Age"] = data["Age"].fillna(data["Age"].mean())#填补缺失值
data.info()
'''
结果:

RangeIndex: 891 entries, 0 to 890
Data columns (total 9 columns):
 #   Column       Non-Null Count  Dtype  
---  ------       --------------  -----  
 0   PassengerId  891 non-null    int64  
 1   Survived     891 non-null    int64  
 2   Pclass       891 non-null    int64  
 3   Sex          891 non-null    object 
 4   Age          891 non-null    float64
 5   SibSp        891 non-null    int64  
 6   Parch        891 non-null    int64  
 7   Fare         891 non-null    float64
 8   Embarked     889 non-null    object 
dtypes: float64(2), int64(5), object(2)
memory usage: 62.8+ KB
'''
data = data.dropna(axis=0)#删除缺失值,Embarked只有两个缺失值,可以直接删除
data.info()
'''
结果:

Int64Index: 889 entries, 0 to 890
Data columns (total 9 columns):
 #   Column       Non-Null Count  Dtype  
---  ------       --------------  -----  
 0   PassengerId  889 non-null    int64  
 1   Survived     889 non-null    int64  
 2   Pclass       889 non-null    int64  
 3   Sex          889 non-null    object 
 4   Age          889 non-null    float64
 5   SibSp        889 non-null    int64  
 6   Parch        889 non-null    int64  
 7   Fare         889 non-null    float64
 8   Embarked     889 non-null    object 
dtypes: float64(2), int64(5), object(2)
memory usage: 69.5+ KB
'''
labels = data['Embarked'].unique().tolist()
data["Embarked"] = data["Embarked"].apply(lambda x:labels.index(x))
data["Sex"] = (data["Sex"] == "male").astype("int")
data

sklearn入门&决策树在sklearn中的实现_第9张图片

x = data.iloc[:,data.columns != "Survived"]
#x
y = data.iloc[:,data.columns == "Survived"]
#以上将数据处理完毕,划分训练集和测试集
from sklearn.model_selection import train_test_split
Xtrain, Xtest, Ytrain, Ytest = train_test_split(x,y,test_size = 0.3)
#Ytrain
for i in [Xtrain, Xtest, Ytrain, Ytest]:
    i.index = range(i.shape[0])
#Xtrain#对索引进行重新赋值
clf = DecisionTreeClassifier(random_state = 25)
clf = clf.fit(Xtrain,Ytrain)
score = clf.score(Xtest,Ytest)
score#结果不太好
#结果:0.704119850187266
#使用交叉验证
from sklearn.model_selection import cross_val_score
clf = DecisionTreeClassifier(random_state = 25)
score = cross_val_score(clf,x,y,cv = 10).mean()
score#效果还是不太好
#结果:0.7469611848825333
#调参,绘制学习曲线
import matplotlib.pyplot as plt
tr = []
te = []
for i in range(10):
    clf = DecisionTreeClassifier(random_state = 25
                                 ,max_depth = i+1
                                 ,criterion = 'entropy')
    clf = clf.fit(Xtrain,Ytrain)
    score_tr = clf.score(Xtrain,Ytrain)
    score_te = cross_val_score(clf,x,y,cv = 10).mean()
    tr.append(score_tr)
    te.append(score_te)
print(max(te))
#结果:0.8166624106230849
plt.plot(range(1,11),tr,color = "red",label = "train")
plt.plot(range(1,11),te,color = "blue",label = "train")
plt.xticks(range(1,11))
plt.legend()
plt.show()

sklearn入门&决策树在sklearn中的实现_第10张图片

import numpy as np
gini_threholds = np.linspace(0,0.5,20)#0.5是根据gini的定义确定的范围
#entropy_threholds = np.linspace(0,1,50)
#np.arange(0,1,0.1)
#网格搜索:能够帮助我们同时调整多个参数的技术,枚举技术
#一串参数和这些参数是对应的,希望网格搜索来搜索到参数的取值范围
parameters = {"criterion":("gini","entropy")
             ,"splitter":("best","random")
             ,"max_depth":[*range(1,10)]
             ,"min_samples_leaf":[*range(1,50,5)]
             ,"min_impurity_decrease":[*np.linspace(0,0.5,20)]}
clf = DecisionTreeClassifier(random_state = 25)
GS = GridSearchCV(clf,parameters,cv=10)
GS = GS.fit(Xtrain,Ytrain)
GS.best_params_#从我们输入的参数和参数取值的列表中,返回最佳组合
'''
结果:
{'criterion': 'gini',
 'max_depth': 7,
 'min_impurity_decrease': 0.0,
 'min_samples_leaf': 11,
 'splitter': 'best'}
'''
GS.best_score_#网格搜索后的模型的评判标准
#结果:0.8313108038914491

5 实例:分类树在合成数集上的表现

#导入需要的库
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.colors import ListedColormap
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.datasets import make_moons,make_circles,make_classification
from sklearn.tree import DecisionTreeClassifier

#生成三种数据集
#从sklearn自带的数据库中生成三种类型的数据集:1)月亮型数据,2)环形数据,3)二分型数据
#make_classification库生成随机的二分型数据
X,y = make_classification(n_samples = 100    #生成100个样本
                         ,n_features = 2     #包含2个特征,即生成二维数据
                         ,n_redundant = 0    #添加冗余特征0个
                         ,n_informative = 2  #包含信息的特征是2个
                         ,random_state = 1   #随机模式1
                         ,n_clusters_per_class = 1  #每个簇内包含的标签类别有1个
                         )
#查看一下X和y
#X#是100行带有2个特征的数据
#y#二分类标签
#画出散点图来观察一下X中特征的分布
plt.scatter(X[:,0],X[:,1])
#结果:

sklearn入门&决策树在sklearn中的实现_第11张图片

#上图显示,生成的二分型数据的两个簇离彼此很远,这样不利于测试分类器的效果,因此使用np生成随机数组,通过让已经生成的二分型数据点加减0-1之间的随机数,使数据分布变得更散更稀疏
#注意:这个过程只能运行一次,因为多次哦运行之后X会变得非常稀疏,两个簇的数据会混合在一起,分类器的效应会继续下降
rng = np.random.RandomState(2)#生成一直随机模式
X += 2 * rng.uniform(size = X.shape)#加减0-1之间的随机数
linearly_separable = (X,y)#生成新的X
plt.scatter(X[:,0],X[:,1])#画散点图来观察一下特征的分布
#结果:

sklearn入门&决策树在sklearn中的实现_第12张图片

#用make_moons创建月亮型数据,make_circles创建环型数据,并将三组数据打包起来放在列表datasets中
datasets = [make_moons(noise = 0.3,random_state = 0),
            make_circles(noise = 0.2,factor = 0.5,random_state = 1),
            linearly_separable]
datasets
len(datasets)
#结果:3

#画出三种数据集和三颗决策树的分类效应图像
#创建画布,宽高比为6*9
figure = plt.figure(figsize = (6,9))
#设置用来安排图像显示位置的全局变量i
i=1
#开始迭代数据,对datasets中的数据进行for循环
for ds_index,ds in enumerate(datasets):
    #对X中的数据进行标准化处理,然后分训练集和测试集
    X,y = ds
    X = StandardScaler().fit_transform(X)
    X_train,X_test,y_train,y_test = train_test_split(X,y,test_size = 0.4,random_state = 42)
    #找出数据集中两个特征的最大值和最小值,让最大值+0.5,最小值-0.5,创造一个比两个特征区间本身更大一点的区间
    x1_min,x1_max = X[:,0].min()-0.5,X[:,0].max()+0.5
    x2_min,x2_max = X[:,1].min()-0.5,X[:,1].max()+0.5
    #用特征向量生成网格数据,网格数据其实就相当于坐标轴上无数个点
    #函数np.arange在给定的两个数之间返回均匀间隔的值,0.2为步长
    #函数meshgrid用以生成网格数据,能够将两个一维数组生成两个二维矩阵
    #如果第一个数组是narray,维度是n,第二个参数是marray,维度是m,那么生成的第一个二维数组是以narray为行,m行的矩阵,而第二个二维数组是以marray的转置为列,n列的矩阵
    #生成的网格数据,是用来绘制决策边界的,因为绘制决策边界的函数contourf要求输入的两个特征都必须是二维的
    array1,array2 = np.meshgrid(np.arange(x1_min,x1_max,0.2),
                                np.arange(x2_min,x2_max,0.2))
    #接下来生成彩色画布
    #用ListedColormap为画布创建颜色,#FF0000正红,#0000FF正蓝
    cm = plt.cm.RdBu
    cm_bright = ListedColormap(['#FF0000','#0000FF'])
    #给画布上加上一个子图,数据为len(datasets)行,2列,放在位置i上
    ax = plt.subplot(len(datasets),2,i)
    #到这里为止,已经生成了0-1之间的坐标系3个了,接下来为坐标系放上标题
    #有三个坐标系,但只需要在第一个坐标系上有标题,因此设定if ds_index==0这个条件
    if ds_index==0:
        ax.set_title("Input data")
    #将数据集的分布放到坐标系上
    #先放训练集
    ax.scatter(X_train[:,0],X_train[:,1],c=y_train,cmap = cm_bright,edgecolors = 'k')
    #放测试集
    ax.scatter(X_test[:,0],X_test[:,1],c=y_test,cmap = cm_bright,alpha = 0.6,edgecolors='k')
    #为图设置坐标轴的最大值和最小值,并设定没有坐标轴
    ax.set_xlim(array1.min(),array1.max())
    ax.set_ylim(array2.min(),array2.max())
    ax.set_xticks(())
    ax.set_yticks(())
    #每次循环之后,改变i的取值让图每次位列不同的位置
    i += 1
    #至此将数据集本身的图像布置完毕,运行以上代码可以看见三个已经处理好的数据集
    #####以下为决策树模型######
    #迭代决策树,首先用subplot增加子图,subplot(行,列,索引)这样的结构,并使用索引i定义图的位置
    #在这里,len(datasets)其实就是3,2是两列
    #在函数最开始,定义i=1,并且在上边建立数据集的图像的时候,已经让i+1,所以i在每次循环中的取值是2,4,6
    ax = plt.subplot(len(datasets),2,i)
    #决策树的建模过程:实例化->fit训练->score接口得到预测的准确率
    clf = tree.DecisionTreeClassifier(max_depth = 5)
    clf.fit(X_train,y_train)
    score = clf.score(X_test,y_test)
    #绘制决策树边界,为此,为网格中的每个点指定一种颜色[x1_min,x1_max] * [x2_min,x2_max]
    #分类树的接口,predict_proba,返回每一个输入的数据点所对应的标签类概率
    #类概率是数据点所在的叶节点中相同类的样本数量/叶节点中的样本总数量
    #由于决策树在训练的时候导入的训练集x_train里面包含两个特征,所以在计算类概率的时候,也必须导入结构相同的数组,即是说,必须有两个特征
    #ravel()能够将一个多维数组转换成一维数组
    #np.c_是能够将两个数组组合起来的函数
    #先将两个网格数据降维成一维数组,再将两个数组连接变成含有两个特征的数据,再代入决策树模型,生成的z包含数据的索引和每个样本点对应的类概率,再切片,切出类概率
    Z = clf.predict_proba(np.c_[array1.ravel(),array2.ravel()])[:,1]
    #np.c_[np.array([1,2,3]),np.array([4,5,6])]
    #将返回的类概率作为数据,放到contourf里面绘制轮廓、
    Z = Z.reshape(array1.shape)
    ax.contourf(array1,array2,Z,cmap = cm,alpha = 0.8)
    #将数据集的分布放到坐标系上
    #将训练集放到图中去
    ax.scatter(X_train[:,0],X_train[:,1],c=y_train,cmap = cm_bright,edgecolors = 'k')
    #将测试集放到图中去
    ax.scatter(X_test[:,0],X_test[:,1],c=y_test,cmap = cm_bright,edgecolors = 'k',alpha = 0.6)
    #为图设置坐标轴的最大值和最小值
    ax.set_xlim(array1.min(),array1.max())
    ax.set_ylim(array2.min(),array2.max())
    #设定坐标轴不显示标尺也不显示数字
    ax.set_xticks(())
    ax.set_yticks(())
    #有三个坐标系,但只需要在第一个坐标系上有标题,因此设定if ds_index==0这个条件
    if ds_index==0:
        ax.set_title("Decision Tree")
    #写在右下角的数字
    ax.text(array1.max()-0.3,array2.min()+0.3,("{:.1f}%".format(score*100)),size=15,horizontalalignment = 'right')
    #让i继续加1
    i += 1
plt.tight_layout()
plt.show()

sklearn入门&决策树在sklearn中的实现_第13张图片
图中每一条线都是决策树在二维平面上画出的一条决策边界,每当决策树分枝一次,就有一条线出现,当数据的维度更高的时候,这条决策边界就会由线变成面,甚至变成想象不出的多维图形。
分类树天生不擅长环型数据,每个模型都有自己的决策上限,所以一个怎样调整都无法提升表现的可能也是有的。当一个模型怎么调整都不行的时候,可以选择换其他的模型使用。
最擅长月亮型数据的是最近邻算法、RBF支持向量机和高斯过程;最擅长环型数据的是最近邻算法和高斯过程;最擅长对半分的数据的是朴素贝叶斯、神经网络和随机森林。

参考: https://www.bilibili.com/video/BV1MA411J7wm?p=2&spm_id_from=pageDriver

你可能感兴趣的:(机器学习,决策树,sklearn,机器学习)