信息熵: E n t ( D ) = − ∑ i = 1 n p i l o g p i Ent(D)=-\sum_{i=1}^np_ilogp_i Ent(D)=−∑i=1npilogpi其中n为类别, p i p_i pi为每个类别的概率, D D D为某个特征,越小越确定
信息增益: G a i n ( D , a ) = E n t ( D ) = − ∑ v = 1 v ∣ D v ∣ ∣ D ∣ E n t ( D v ) Gain(D,a)=Ent(D)=-\sum_{v=1}^v\frac{|D^v|}{|D|}Ent(D^v) Gain(D,a)=Ent(D)=−∑v=1v∣D∣∣Dv∣Ent(Dv)越大纯度提升越大,所以分裂 a r g m a x G a i n ( D , a ) argmaxGain(D,a) argmaxGain(D,a)
eg.15个样本,9个1和6个0;有个特征A(取值 A 1 A_1 A1、 A 2 A_2 A2、 A 3 A_3 A3,其中 A 1 A_1 A1(3个1,2个0),其中 A 2 A_2 A2(2个1,3个0)其中 A 3 A_3 A3(4个1,1个0))
E n t ( A ) = − ( 9 15 ∗ l o g 2 9 15 + 6 15 ∗ l o g 2 6 15 ) = 0.971 Ent(A)=-(\frac{9}{15}*log_2\frac{9}{15}+\frac{6}{15}*log_2\frac{6}{15})=0.971 Ent(A)=−(159∗log2159+156∗log2156)=0.971
G a i n ( A , a ) = 0.971 − ( 5 15 E n t ( A 1 ) + 5 15 E n t ( A 2 ) + 5 15 E n t ( A 3 ) ) = 0.083 Gain(A,a)=0.971-(\frac{5}{15}Ent(A1)+\frac{5}{15}Ent(A2)+\frac{5}{15}Ent(A3))=0.083 Gain(A,a)=0.971−(155Ent(A1)+155Ent(A2)+155Ent(A3))=0.083
需要惩罚取值较多的信息增益,引出了信息增益率,即C4.5的算法
I V ( a ) = − ∑ v = 1 v ∣ D v ∣ ∣ D ∣ l o g 2 ∣ D v ∣ ∣ D ∣ IV(a)=-\sum_{v=1}^v\frac{|D^v|}{|D|}log_2\frac{|D^v|}{|D|} IV(a)=−∑v=1v∣D∣∣Dv∣log2∣D∣∣Dv∣ 特征取值越多, I V ( a ) IV(a) IV(a)越大
信息增益率: G a i n _ r a t i o ( D , a ) = G a i n ( D , a ) I V ( a ) Gain\_ratio(D,a)=\frac{Gain(D,a)}{IV(a)} Gain_ratio(D,a)=IV(a)Gain(D,a) argmax G a i n _ r a t i o ( D , a ) Gain\_ratio(D,a) Gain_ratio(D,a)
引出了分类+回归的决策树
G i n i ( D ) = 1 − ∑ i = 1 n p i 2 Gini(D)=1-\sum_{i=1}^np_i^2 Gini(D)=1−∑i=1npi2 反映随机抽2个样本,不一致的概率,越小越好(越纯)
G i n i s p l i t ( D ) = 1 − ∑ v = 1 v ∣ D v ∣ ∣ D ∣ G i n i ( D v ) Gini_{split}(D)=1-\sum_{v=1}^v\frac{|D^v|}{|D|}Gini(D^v) Ginisplit(D)=1−∑v=1v∣D∣∣Dv∣Gini(Dv)
eg.Age(youth(5)、middle(5)、senior(4)),以youth(5)和middle+senior(9)分割为例:
G i n i s p l i t ( A g e ) = 5 14 [ 1 − [ ( 3 5 ) 2 + ( 2 5 ) 2 ] ] + 9 14 [ 1 − [ ( 2 9 ) 2 + ( 7 9 ) 2 ] ] = 0.39 Gini_{split}(Age)=\frac{5}{14}[1-[(\frac{3}{5})^2+(\frac{2}{5})^2]]+\frac{9}{14}[1-[(\frac{2}{9})^2+(\frac{7}{9})^2]]=0.39 Ginisplit(Age)=145[1−[(53)2+(52)2]]+149[1−[(92)2+(97)2]]=0.39
如果为连续性变量处理方式与C4.5相同
回归mse:
注:实践证明 G i n i Gini Gini和 G a i n Gain Gain效果差不多
处理方式 | 信息增益(ID3) | 信息增益率(C4.5) | Gini(Cart) |
---|---|---|---|
连续值处理 | × \times × | √ \surd √ | √ \surd √ |
缺失值处理 | × \times × | √ \surd √ | √ \surd √ |
剪枝 | × \times × | √ \surd √ | √ \surd √ |
一、优点:
一、缺点:
决策树的构建过程中出现过拟合的原因及解决方法
原因:
解决方法: 剪枝、限制深度、RF、正则化等
决策树如何处理缺失值
1、使用权重方法重构。(可认为以前1 ∗ G a i n *Gain ∗Gain,现在无缺失比率 ∗ G a i n *Gain ∗Gain)训练时特征出现缺失怎么处理(划分)即不考虑缺失,然后重赋权重
2、将缺失(划分变量)的样本中分别放到不同分支再进行分支。缺失变量样本的归属分支问题
3、同时探查所有分支,然后算每个类别的概率,取概率最大的类别赋值该样本。测试集中缺失处理
决策树递归终止的条件
1、所有子集被正确分类;2、没有合适的特征选择或信息增益(信息增益率/Gini)很小
决策树的变量重要性
如样本分裂占比 ∗ * ∗Gini/信息增益比
import numpy as np
import pandas as pd
from sklearn.preprocessing import LabelEncoder #分类变量编码包
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier
import variable_iv as vi
import Logistic_model as lm
import os
os.chdir('E:/wyz/Desktop/cart/')
os.environ["PATH"] += os.pathsep + 'D:/Program Files (x86)/Graphviz2.38/bin/'#决策树可视化的包
data = pd.read_excel('ceshi.xlsx',sheet_name = 'Sheet2')
#分类变量编码
from sklearn.preprocessing import LabelEncoder
le = LabelEncoder()
str_variable = list(data.dtypes[data.dtypes.values == object].index)
for col in str_variable:
data[col] = le.fit_transform(data[col].astype(str))
#在单变量分析的基础上填充缺失值(看哪一组的1的比率最接近于缺失值的那一组)
data['var1'] = data['var1'].fillna(0.42089)
data['var2'] = data['var2'].fillna(125.854)
#划分数据集
y = data_model['target']
x = data_model.drop('target', axis=1)
x_train, x_test, y_train, y_test = train_test_split(x, y,random_state=0,train_size=0.7)
#建立模型(min_samples_leaf和min_samples_split需要慎重选择)(和传统决策树有很大区别)
model_tree = DecisionTreeClassifier(
criterion='gini',#划分标准
splitter='best',#特征划分标准
max_depth=3,#树的最大深度
min_samples_split=20,#划分所需要的最小样本数
min_samples_leaf=10,#分到每个叶子最小样本数
max_features=None,#用于参与划分的变量个数
max_leaf_nodes=None,#最大叶子节点数
min_impurity_decrease=0.0,#节点划分最小不纯度
min_weight_fraction_leaf=0.0,#叶子节点最小的样本权重和
presort=False,#进行拟合前是否预分数据来加快树的构建
random_state=None,
)#建模要class_weight='balanced'
model_tree.fit(x_train, y_train)
test_proba = pd.DataFrame(model_tree.predict_proba(x_test))[1].values#预测为0的概率
print('测试集AUC: %.4f'%roc_auc_score(y_test,test_proba))#AUC,预测为概率
#变量重要性(是由该节点样本占总体样本*gini的减少量)
importances = list(model_tree.feature_importances_)
print(importances)
#输出变量重要的前几个变量(求最大的三个索引nsmallest与nlargest相反求最小)
import heapq
imp_index = list(map(importances.index, heapq.nlargest(3,importances)))
var_imp = []
for i in imp_index:
var_imp.append(list1[i])
print(var_imp)
#解决中文乱码问题(含中文的输出方式)
from sklearn.externals.six import StringIO
import pydotplus
from IPython.display import Image
dot_data = StringIO()
#决策树图
list1 = ['var1','var2','var3','var4','var5','var6']
tree.export_graphviz(model_tree, out_file=dot_data,
feature_names=list1,
filled=True, rounded=True,
special_characters=True)
graph = pydotplus.graph_from_dot_data(dot_data.getvalue().replace( 'helvetica' ,' "Microsoft YaHei" '))
graph.write_png("result1.png")#将图画出来
#https://blog.csdn.net/qq_39386012/article/details/83857609#commentBox
Image(graph.create_png())#在jupter中可视化出来
from sklearn import tree
import pydotplus
#决策树图(不含含中文的输出方式)
list1 = ['var1','var2','var3','var4','var5','var6']
dot_data = tree.export_graphviz(model_tree, out_file=None,
feature_names=list1,
filled=True, rounded=True,
special_characters=True)
graph = pydotplus.graph_from_dot_data(dot_data)
graph.write_png("result2.png")#将图画出来
决策树参数详解
参数 | 默认值及输入类型 | 介绍 |
---|---|---|
criterion | 默认值:gini,即CART算法 输入:entropy, gini |
特征选择标准 |
splitter | 默认值:best 输入:best, random |
best在特征的所有划分点中找出最优的划分点,random随机的在部分划分点中找 局部最优的划分点。默认的‘best’适合样本量不大的时候,而如果样本数据量非常大,此时决策树构建推荐‘random’ |
max_depth | 默认值:None 输入:int, None |
决策树最大深度。一般数据比较少或者特征少的时候可以不用管这个值,如果模型样本数量多,特征也多时,推荐限制这个最大深度,具体取值取决于数据的分布。常用的可以取值10-100之间,常用来解决过拟合 |
min_samples_split | 默认值:2 输入:int, float |
内部节点(即判断条件)再划分所需最小样本数。如果是int,则取传入值本身作为最小样本数;如果是float,则取ceil(min_samples_split*样本数量)作为最小样本数。(向上取整) |
min_samples_leaf | 输入:int, float | 叶子节点(即分类)最少样本数。如果是int,则取传入值本身作为最小样本数;如果是float,则取ceil(min_samples_leaf*样本数量)的值作为最小样本数。这个值限制了叶子节点最少的样本数,如果某叶子节点数目小于样本数,则会和兄弟节点一起被剪枝 |
min_weight_fraction_leaf | 默认值:0 输入:float |
叶子节点(即分类)最小的样本权重和,【float】。这个值限制了叶子节点所有样本权重和的最小值,如果小于这个值,则会和兄弟节点一起被剪枝。默认是0,就是不考虑权重问题,所有样本的权重相同。 注:一般来说如果我们有较多样本有缺失值或者分类树样本的分布类别偏差很大,就会引入样本权重,这时就要注意此值 |
max_features | 输入:int,float | 在划分数据集时考虑的最多的特征值数量,【int值】。在每次split时最大特征数;【float值】表示百分数,即(max_features*n_features) |
random_state | 默认值:None 输入:int, randomSate instance, None |
|
max_leaf_nodes | 默认值:None 输入:int, None |
最大叶子节点数。通过设置最大叶子节点数,可以防止过拟合。默认值None,默认情况下不设置最大叶子节点数。如果加了限制,算法会建立在最大叶子节点数内最优的决策树。如果特征不多,可以不考虑这个值,但是如果特征多,可以加限制,具体的值可以通过交叉验证得到 |
min_impurity_decrease | 默认值:0 输入:float |
节点划分最小不纯度,默认值为‘0’。限制决策树的增长,节点的不纯度(基尼系数,信息增益,均方差,绝对差)必须大于这个阈值,否则该节点不再生成子节点 |
class_weight | 默认值:None 输入:dict, list of dicts, balanced |
类别权重(不适用于回归树,sklearn.tree.DecisionTreeRegressor) 指定样本各类别的权重,主要是为了防止训练集某些类别的样本过多,导致训练的决策树过于偏向这些类别。balanced,算法自己计算权重,样本量少的类别所对应的样本权重会更高。如果样本类别分布没有明显的偏倚,则可以不管这个参数 |
presort | 默认值:False 输入:bool |
表示在进行拟合之前,是否预分数据来加快树的构建 注:对于数据集非常庞大的分类,presort=true将导致整个分类变得缓慢;当数据集较小,且树的深度有限制,presort=true才会加速分类 |
决策树调参注意事项