决策树注意事项和参数调节

导入库

import numpy as np
from sklearn import tree
from sklearn.datasets import load_wine
from sklearn.model_selection import train_test_split
from sklearn.model_selection import GridSearchCV
from sklearn.model_selection import cross_val_score
import matplotlib.pyplot as plt

构建数据集

wine = load_wine()
Xtrain,Xtest,Ytrain,Ytest = train_test_split(wine.data,wine.target,test_size=0.3,random_state=11)
print(Xtrain.shape,Xtest.shape)

随机种子

1.在trian_test_spilt(X, Y, test_size, random_size,shuffle = True(default))
  因为trian_test_spilt在划分数据时,shuffle默认是true,所以数据时随机打乱,然后进行划分的。这样就会有不同的排列方式。要想复现结果,用随机种子固定住数据,这样就只有 一种排列方式了。
2.sklearn在构建决策树时,不使用全部的特征,而是随机选取一部分特征,从这一部分特征中选择最优的节点,从而每次生成的树是不同,这样决策树训练测试得到的score具有随机性,要用tree.DecisionTreeClassifier(random_state)固定住结果。
如果想同时找到数据集和score的最好结果,用如下代码:

 for i in range (31):
     Xtrain,Xtest,Ytrain,Ytest = train_test_split(wine.data,wine.target,test_size=0.3,random_state=i)
     for a in range(31):
         clf = tree.DecisionTreeClassifier(criterion='entropy'  # criterion = 'gini'
                                           ,random_state=a
                                           ,splitter='best')  # splitter='random'
         clf = clf.fit(Xtrain, Ytrain)
         score1 = clf.score(Xtest, Ytest)
         print(i,a,score1)

建立模型

sklearn建模过程

clf = tree.DecisionTreeClassifier(criterion='entropy')  # 实例化
clf = clf.fit(Xtrain,Ytrain)                            # 用训练集训练模型
score = clf.score(Xtest,Ytest)                          # 导入测试集,从接口中调用需要的信息
print(score)

探索决策树`(看哪个特征信息熵大)

feature_name = ['酒精','苹果酸','灰','灰的碱性','镁','总酚','类黄酮','非黄烷类酚类','花青素','颜色强度','色调','od280/od315稀释葡萄酒','脯氨酸']
print(clf.feature_importances_)
print([*zip(feature_name,clf.feature_importances_)])

构建随机模型

参数

1.criterion:{“gini”, “entropy”}, default=”gini”
   entropy: 信息熵(内部运算是信息增益)
   gini: 基尼系数

  
2.splitter:{“best”, “random”}, default=”best”
  best: 决策树分支时会优先选择重要的特征进行分枝(符合理论)。
  random:分枝时会更加随机,树会因为不重要的的信息而更深更大,并因这些不必要的信息而降低对训练集的拟合。但当预测到模型会过拟合时,用这个参数帮你防止过拟合,当然树建成后,使用剪枝也可以防止过拟合。

3.random_stateint, RandomState instance, default=None 这个参数上面讲过了。

clf = tree.DecisionTreeClassifier(criterion='entropy'    # 信息熵  # ctiterion = 'gini'(default)  基尼指数
                                 ,random_state=10
                                 ,splitter='best')      # 分枝时虽然随机,但是还是会优先选择更重要的特征进行分枝
                           # splitter = 'random'
                           # 决策树在分枝时会更加随机,树会因为含有更多的不必要信息而更深更大,并因这些不必要信息而降低对训练集的拟合。
                           # 这也是防止过拟合的一种方式。
clf = clf.fit(Xtrain,Ytrain)
score1 = clf.score(Xtest,Ytest)
print(score1)

剪枝参数(防止过拟合)

观察构建的树对训练集的拟合程度,与测试集score比较,是否过拟合或欠拟合

score_train = clf.score(Xtrain,Ytrain)
print(score_train)

参数

4.max_depth:int, default=None  限制树的最大深度
  用的最广的参数,在高维度低样本时非常有效。决策树多生长一层,对样本的需求会增加一倍,所以限制层数能够有效限制过拟合。从max_depth = 3 开始试验。

5.min_samples_split:int or float, default=2
一个节点必须包含至少min_samples_split个训练样本,这个节点才允许被分枝。

6.min_samples_leaf:int or float, default=1
一个节点在分枝后必须包含至少min_samples_leaf个训练样本,这个节点才允许被分枝。

7.class_weight:dict, list of dict or “balanced”, default=None
1)balance:n_samples / (n_classes * np.bincount(y))。
当为二分类时,类的个数n_classes = 2,n_sample:全部样本总数, np.bincount(y):每个类别样本数
使用balance算法会自己计算权重,样本少的类别 np.bincount(y)变少,分子变小,权重会变高,同理类别多的样本权重会减少。
2){class_label: weight} 指定样本各类别的权重。
{1:10} {0:1} label为1的权重为10,label为0的权重为1

8.min_weight_fraction_leaf:float, default=0.0  剪枝参数
限制叶子节点所有样本权重和的最小值。如果调用class_weight,这个参数代替min_samples_leaf。

交叉验证

是否使用整个数据集还是分后的训练集这个问题:
使用整个数据集,不是太严谨,但数据量少,用整个数据集。
sklearn.model_selection.cross_val_score(estimator, X,Y,cv=None)
cv 通常是5或10
交叉验证通常使用mean()函数平均结果。

clf = tree.DecisionTreeClassifier(criterion='entropy'
                                  ,random_state=10
                                  ,splitter='best'
                                  ,max_depth=4           # 限制树的最大深度
                                  ,min_samples_leaf=1    # 子节点分完后至少包含这么多,叶节点才分。
                                  ,min_samples_split=2)  # 叶节点有这么多,才分。
clf = clf.fit(Xtrain,Ytrain)
score2 = clf.score(Xtrain,Ytrain)
score3 = clf.score(Xtest,Ytest)
score4 = cross_val_score(clf,wine.data,wine.target,cv=10).mean() # 注意交叉验证数据是原数据集,不是分后的
print(score2,score3,score4)

学习曲线(只有数字多时,使用)

1.想画几条曲线设置几个列表

2.通常比较训练和测试曲线,观察是否过拟合

train = []
test = []
for i in range(10):
    clf =tree.DecisionTreeClassifier(criterion='entropy',
                                     random_state=10,
                                     max_depth=i+1)
    clf= clf.fit(Xtrain,Ytrain)
    score_tr = clf.score(Xtrain,Ytrain)
    score_te = clf.score(Xtest,Ytest)
    train.append(score_tr)
    test.append(score_te)
print(max(test))
plt.plot(range(1,11),train,color='red',label='train')
plt.plot(range(1,11),test,color='blue',label='test')
plt.xticks(range(1,11))  # 坐标细分
plt.legend()
plt.show()

网格搜索(运行很慢)

参数

1)GS = GridSearchCV(clf,param_grid,cv=10)
param_grid:是个字典或字典列表
这个函数同时满足fit,score,交叉验证三种功能。
2)GS.fit(Xtrain,Ytrain) 直接运行,不需要船变量。
3)GS.best_params_ :最佳参数组合。
4)GS.best_score_ :最好的score的值。

gini_thresholds = np.linspace(0,0.5,20)
parameters = {'splitter':('best','random'),
              'criterion':('gini','entropy'),
              'max_depth':[*range(1,10)],
              'min_samples_leaf':[*range(1,24,2)],
              # 'min_impurity_devrease':[*np.linspace(0,0.5,20)]
              }
clf = tree.DecisionTreeClassifier(random_state=10)
GS = GridSearchCV(clf,parameters,cv=10)
GS.fit(Xtrain,Ytrain)
print(GS.best_params_)
print(GS.best_score_)

注意

1.当样本数量少,但特征数目很多时,决策树很容易过拟合,一把来说,样本数比特征数多一些会比较容易建立健壮的模型。
2.当特征多时,优先使用PCA(主成分分析) / ICA(独立成分分析) / 特征选择。
3.不需要做数据预处理的模型:决策树,随机森林,ICA。因为他们不关心变量的值,只关心变量的分布和变量之间的条件概率。
4.需要做数据预处理的模型:SVM, XGboost, adaboost, gbdt,PCA,SVD。因为他们使用梯度下降求解最优的模型。

调节参数步骤:

1.PCA(主成分分析) / ICA(独立成分分析) / 特征选择进行降维(样本数目远小于特征数目)。
2.选择合适的随机种子(有两个种子)
3.设置参数,利用学习曲线和网格搜索进行调节。

猜你喜欢

转载自blog.csdn.net/steve_tom/article/details/105867170
今日推荐