树模型的共线性问题
The following article is from 风控建模 Author Monica
决策树是一种非参数的监督学习算法,既可以用于分类问题,也可以用于回归问题,还经常被用于各种集成学习算法(如随机森林,xgboost,gbdt等)。决策树模型非常简单,它们是一种树状判断的结构,可以用一些简单 if-else-then 来表述。
虽然原理简单,但决策树可以变得很复杂。从下面这个图可以看出,决策树甚至可以用来拟合正弦曲线,树越深,拟合结果越精细。
目前主要有3种决策树算法:ID3 (Iterative Dichotomiser 3) ,C4.5, CART (Classification and Regression Trees)。
其中,ID3 算法通过使用信息增益作为选择分裂属性的准则来构建多叉树,但只支持分类型的属性,并且容易选择取值多的属性分裂。
C4.5算法是ID3算法的改进版,使用信息增益率准则选择分裂属性,属性可以是分类型,也可以是数值型的,同时还支持缺失值和剪枝处理。C4.5之后还有个C5.0,是个商用版,小编不太熟,这里提一下,感兴趣的同学可以研究一下。
CART算法和C4.5也比较类似,但它的结构是二叉树而非多叉树,并且支持回归问题。它使用的是Gini指数作为属性的选择准则,属性也支持分类型,数值型,缺失值,支持剪枝。
python的sklearn库实现的是改进的CART决策树算法(可以使用信息增益和gini做准则),但只接受数值型变量输入。主要有两个类,DecisionTreeClassifier 和 DecisionTreeRegressor。
DecisionTreeClassifier主要用于分类问题,训练完成后可以用 export_graphviz 来可视化。除了二分类,还支持多分类,同学们遇到多分类问题时可以试试。
DecisionTreeRegressor用于回归问题,比如前文中用来解决正弦函数回归的问题。
决策树算法的优缺点
优点:
简单易理解,具有很好的解释性,能够可视化。
无需过多的数据预处理操作。
训练模型的算法复杂度与数据集大小是log的关系。
支持分类型变量和数值型变量,不过sklearn只支持数值型的X。
属于白盒模型,可以通过很简单的布尔逻辑表述。
当对数据源的假设受到破坏时,也有比较好的效果。
缺点:
容易过拟合,可以通过剪枝来减轻,在sklearn里,可以调节最大深度max_depth,叶子节点数max_leaf_nodes,叶节点最小样本数min_samples_leaf等参数。
不稳定,容易受干扰。
不是全局最优,而是启发式算法得到的局部最优。
难以学习复杂概念。
在正负样本不均衡的情况下,决策树偏差会很大。
下面我们来讨论下决策树的共线性问题,当小编听说决策树还需要考虑共线性的问题时,小编是表示怀疑的。
下面我们就用实际代码,做个实验来看看,到底决策树需要不需要考虑共线性。
from sklearn.tree import DecisionTreeClassifier
from sklearn.tree import DecisionTreeRegressor
import numpy as np
from sklearn.model_selection import train_test_split
import pandas as pd
import matplotlib.pyplot as plt
from sklearn import tree
from sklearn.metrics import classification_report
import graphviz
%matplotlib inline
生成数据集
a = np.linspace(-20,20,100)
x1 = a+ np.random.randn()
x2 = a+np.random.randn() + 10
df1 = pd.DataFrame({'x1':a,'x2':x1})
df1['y'] =1
df2 = pd.DataFrame({'x1':a,'x2':x2})
df2['y'] = 0
df = df1.append(df2,ignore_index=True)
df.head()
x1 x2 y
0 -20.000000 -22.139616 1
1 -19.595960 -21.735576 1
2 -19.191919 -21.331536 1
3 -18.787879 -20.927495 1
4 -18.383838 -20.523455 1
看下相关性:
x1和x2的相关性太强了有没有?先看下不管共线性,建出的模型能有多差。
X_train, X_test, y_train, y_test = train_test_split(
df[['x1','x2']],df.y,test_size=0.33)
clf = tree.DecisionTreeClassifier()
clf = clf.fit(X_train, y_train)
print(classification_report(y_test,clf.predict(X_test)))
效果还好。那如果要考虑共线性,保留x1,删除x2建模:
clf2 = tree.DecisionTreeClassifier()
clf2 = clf.fit(X_train[['x1']], y_train)
print(classification_report(y_test,clf.predict(X_test[['x1']])))
模型效果显然很差。再看保留x2,删除x1建模效果:
clf3 = tree.DecisionTreeClassifier()
clf3 = clf.fit(X_train[['x2']], y_train)
print(classification_report(y_test,clf.predict(X_test[['x2']])))
效果同样不行。
小编得出的结论是,决策树这类树模型不同于逻辑回归、线性回归这类线性模型,它是一类无参数的模型,对属性间的独立性或相关性不做什么假设,也就无需考虑什么多重共线性啦。当然,这也是小编的一些个人观点,如果大家有问题,欢迎一起讨论。谢谢大家的支持~~
来源|风控建模
作者| Monica
更多精彩,戳这里
阅读原文,即可报名