目录
5)min_samples_split :内部节点最小样本数,即非叶子节点
7)min_weight_fraction_leaf:叶子结点最小样本权重和
9)min_impurity_decrease:控制决策树节点的分裂
10)min_impurity_split:限制了决策树的增长
12)random_state:设置决策树分枝中随机模式的参数
一、决策树剪枝
1、什么是决策树剪枝?
决策树剪枝是指在训练完整的决策树模型后,通过去除一些不必要的分支或叶节点,以减小模型的复杂度,提高泛化能力的一种技术。决策树剪枝方法主要分为预剪枝和后剪枝两种。
决策树剪枝的目的是防止决策树模型过拟合训练数据,提高模型的泛化能力。
2、如何剪枝
预剪枝:在构建决策树的过程中,在每个节点进行划分前,先进行评估,决定是否进行划分。常用的预剪枝方法有限制树的最大深度、限制节点的最小样本数、限制不纯度的最小改善程度等。其策略为限制树的深度、限制叶子结点个数以及叶子结点的样本数、基尼系数。
后剪枝:在构建完整的决策树后,从底部开始逐层向上剪枝。剪枝时移除某个节点的子树,将该节点转换为叶节点,并将该节点的多数类别作为该叶节点的类别。然后根据剪枝后的树在验证集上的性能,判断是否进行剪枝。常用的后剪枝方法有pessimistic error pruning和cost complexity pruning等。
比如当此时有一个决策树,他的原本训练模型如下图所示:
此时有五个叶子结点,如果想要限制叶子结点树,那么对其进行剪枝,如果只要4个叶子结点,那么可能有多种剪枝方法,但是具体剪哪一个呢,看下一点。
3、剪枝剪哪个位置的叶子结点
在预剪枝中,剪枝的位置是在构建决策树时,在每个节点进行划分之前进行评估。在每个节点进行划分时,利用某种评估方法(如信息增益、基尼指数)来计算划分后的性能,并与预设的剪枝条件进行比较。如果划分后性能没有显著提升或达到剪枝条件,则停止划分并将当前节点转换为叶节点。
后剪枝中,剪枝的位置是在构建完整的决策树之后。首先,从决策树的底部开始逐层向上剪枝。将一个节点的子树移除,将该节点转换为叶节点,并将该节点的多数类别作为该叶节点的类别。然后,根据剪枝后的树在验证数据集上的性能进行评估,如果剪枝后的性能没有显著下降或者达到剪枝条件,则保留剪枝后的树。
剪枝的位置是根据评估指标和剪枝条件来确定的,旨在提高决策树模型的泛化能力。预剪枝在构建决策树时,根据预设条件进行剪枝。而后剪枝在构建完整的决策树后,通过逐层向上剪枝,并根据验证集性能进行剪枝。
二、树模型参数及用法
1、参数种类
下列是直接调用一个树模型的类,然后内部是他的用法
class sklearn.tree.DecisionTreeClassifier(criterion=’gini’, splitter=’best’, max_depth=None, min_samples_split=2, min_samples_leaf=1, min_weight_fraction_leaf=0.0, max_features=None, random_state=None, max_leaf_nodes=None, min_impurity_decrease=0.0, min_impurity_split=None, class_weight=None, presort=False)
2、参数解释
1)criterion:gini or entropy
采用基尼系数还是熵值衡量,默认基尼系数
2)splitter:best or random
前者是在所有特征中找最好的切分点 后者是在部分特征中(数据量大的时候)默认是best,无需更改
3)max_feature:最大特征数目
log2,sqrt,N,特征小于50的时候一般使用所有的,默认取所有特征,无需更改
4)max_depth:最大层数
数据少或者特征少的时候可以不管这个值,如果模型样本量多,特征也多的情况下,可以尝试限制下。如果没有设置,那么将会把节点完全展开,直到所有的叶子节点都是纯的,或者达到最小叶子节点的个数阈值设置。
5)min_samples_split :内部节点最小样本数,即非叶子节点
如果某节点的样本数少于min_samples_split,则不会继续再尝试选择最优特征来进行划分,如果样本量不大,不需要管这个值。如果样本量数量级非常大,则推荐增大这个值。控制内部节点分裂的情况;假设<10,那么分裂的数量小于10就不会再次分裂了,默认2个
6)min_samples_leaf:叶子结点最小样本数
如果某叶子节点数目小于样本数,则会和兄弟节点一起被剪枝,如果样本量不大,不需要管这个值,先构成决策树,再剪枝,当小于某个设定值后,删除此节点以及此节点的分支节点
7)min_weight_fraction_leaf:叶子结点最小样本权重和
限制了叶子节点所有样本权重和的最小值,如果小于这个值,则会和兄弟节点一起被剪枝,默认是0,就是不考虑权重问题。一般来说,如果我们有较多样本有缺失值,或者分类树样本的分布类别偏差很大,就会引入样本权重,这时我们就要注意这个值了。
8)max_leaf_nodes:最大叶子节点数
防止过拟合,默认是"None”,即不限制最大的叶子节点数。如果加了限制,算法会建立在最大叶子节点数内最优的决策树。如果特征不多,可以不考虑这个值,但是如果特征分成多的话,可以加以限制具体的值可以通过交叉验证得到。假设限制最大的叶子节点数为10个,那么就不会再次分裂了
9)min_impurity_decrease:控制决策树节点的分裂
用于设置分裂的阈值,指定了一个阈值,当某个节点进行分裂后,分裂后的节点的不纯度减少值(或相对于父节点的不纯度减少值)大于该阈值时才会进行分裂操作,否则不进行分裂,将该节点标记为叶节点。
10)min_impurity_split:限制了决策树的增长
如果某节点的不纯度(基尼系数,信息增益,均方差,绝对差)小于这个阈值则该节点不再生成子节点。即为叶子节点 。
11)class_weight :指定样本各类别的的权重
主要是为了防止训练集某些类别的样本过多导致训练的决策树过于偏向这些类别。这里可以自己指定各个样本的权重如果使用“balanced”,则算法会自己计算权重,样本量少的类别所对应的样本权重会高。
12)random_state:设置决策树分枝中随机模式的参数
当数据集中的特征数量较少时,随机性不会很明显。但是,当特征数量较多时,随机性就会变得明显。random_state参数可以确保每次运行代码时都得到相同的结果
三、案例实现
当前有一个文件为电信客户流失数据.xlsx,其主要目的是为了训练一个模型,用来测试哪些用户有想要离开电信运营商的趋势,如果判定为想要流失的人员,系统自动给这个客户发送一些福利,如流量、话费券等等
文件内特征及类别大致如下:
完整代码实现:
import pandas as pd
def cm_plot(y, yp): # 可视化混淆矩阵,网上都是包装好的,可以直接复制使用
from sklearn.metrics import confusion_matrix
import matplotlib.pyplot as plt
cm = confusion_matrix(y, yp)
plt.matshow(cm, cmap=plt.cm.Blues)
plt.colorbar()
for x in range(len(cm)):
for y in range(len(cm)):
plt.annotate(cm[x, y], xy=(y, x), horizontalalignment='center',verticalalignment='center')
plt.ylabel('True label')
plt.xlabel('Predicted label')
return plt
datas = pd.read_excel("电信客户流失数据.xlsx") # 导入数据
data = datas.iloc[:,:-1] # 取出特征数据以及标签数据
target = datas.iloc[:,-1]
# 数据切分测试集训练集
from sklearn.model_selection import train_test_split
data_train,data_test,target_train,target_test = train_test_split(data,target,test_size=0.2,random_state=42)
# 定义决策树
from sklearn import tree
# 建立决策树模型,并对其进行训练
dtr = tree.DecisionTreeClassifier(criterion='gini' , max_depth=8 , random_state=42) # 设置计算方式为gini系数计算,最大层数为8层,随机种子设置为42
dtr.fit(data_train,target_train) # 对训练集数据进行训练
# 预测数据
train_predicted = dtr.predict(data_train)
# 对测试集 打印分类报告
from sklearn import metrics
print(metrics.classification_report(target_train,train_predicted))
# 对原始数据测试,并打印报告
predict = dtr.predict(data)
print(metrics.classification_report(target, predict))
# 对随机切分的数据打印报告
predict1 = dtr.predict(data_test)
print(metrics.classification_report(target_test,predict1))
运行结果展示:
此时测试集概率不高,需要你继续对源代码进行调参,或者在对其使用k折交叉验证来处理