<机器学习笔记-05 >决策树
关键词:机器学习,决策树
摘要:本文主要介绍了笔者对于决策树原理的理解。
-
知识要点总结
掌握决策树、分类器、积极/消极学习方法、集成学习的概念;
掌握构建决策树、随机森林的方法;
掌握熵、信息增益、基尼不纯度的概念和计算方法;
掌握在python中使用基本数学、决策树和随机森林的方法;
-
概念理解:
-
决策树:
是一种分类器;通过训练数据构建决策树,对未知数据进行分类;
构成:一个根结点(样本全集)、若干内部结点(属性测试)、若干叶结点(决策结果);
判定过程:输入一组未知数据,从根结点出发,按照决策树的判定测试序列,运行到叶结点输出决策结果;
决策树学习目的:产生泛化能力强(处理未见示例能力强)的决策树;
积极学习方法(eager learner):先从训练集建立一个与后面需求无关的模型,模型一旦建好后可以很快的预测出结果;消极学习方法(lazy learner):如KNN(k-Nearest Neighbor)有了训练集数据的预测需求,才会开始学习整个数据的特征;不需要花时间训练预测能力,但比积极学习方法预测慢;
-
熵(Entropy)
如何确定决策树应该先测试哪个解释变量?解决思路:较好的测试可以更大程度上降低分类的不确定度性;
-
熵:度量信息的不确定性;以比特(bits)为单位;完全确定的分类,其熵为0比特;其公式为
H(x)=−∑i=1nP(xi)logbP(xi) 其中,
n 是样本的数量,P(xi) 是第i 个样本的概率;b 一般取2或e 或10;前面加符号是为了熵为非负数; -
举例以方便理解:
- ##### 投掷硬币一次,正反面概率各为0.5,则硬币投掷一次的结果变量熵为
H(x)=−(0.5log20.5+0.5log20.5)=1.0 - ##### 投掷硬币一次,正面概率0.8,反面概率0.2,则硬币投掷一次的结果变量熵为0.72;不确定性降低了,向另一种结果更加靠近;
H(x)=−(0.8log20.8+0.2log20.2)=0.72 - ##### 投掷硬币一次,正面概率为1.0,反面概率为0,则硬币投掷一次的结果变量熵为0;结果不确定性度为0;
H(x)=−(1.0log21.0+0.0log20.0)=0.0
-
信息增益(information gain)
如何评估哪一个变量最大程度地降低了分类的不确定性?
-
信息增益:父结点熵
H(T) 与子节点熵加权均值的差;应该选择信息增益最大的解释变量进行结点划分;IG(T,a)=H(T)−∑v∈val(s){x∈T|xa=v}|T|H(x∈T|xa=v) 其中,
xa∈val(s) 表示解释变量a 的样本x ;{x∈T|xa=v} 表示解释变量a 的值等于v 样本数量;H(x∈T|xa=v) 是解释变量a的值等于v 的样本熵;
-
基尼不纯度(gini impurity):
在使用CART方法时,按照集合中子集标签的概率分布对集合中元素指定标签,基尼不纯度用来衡量被错误指定标签的元素被随机抽取的概率;(翻译自wikipedia-decision tree);
-
计算公式:假设集合共有
j 个子集,t 是结点样本的子集,其中P(i|t) 表示从结点子集中选择一个类型i 的概率;Gini(t)=∑i=1jP(i|t)(1−P(i|t))=∑i=1jP(i|t)−∑i=1jP(i|t)2=1−∑i=1jP(i|t)2 -
集合中只有一类,基尼不纯度为0;美国类型概率相同时,基尼不纯度最大,为
Ginimax=1−1n -
举例方便理解:
投掷硬币,正反面各0.5概率,则硬币投掷一次的不纯度为
Gini(t)=2(0.5)(1−0.5)=1−(0.52+0.52)=0.5 投掷硬币,正面概率为0.8,反面概率为0.2,则硬币投掷一次的不纯度为
Gini(t)=2(0.8)(1−0.8)=1−(0.82+0.22)=0.32 投掷硬币,正面概率为1,反面概率为0,则硬币投掷一次的不纯度为
Gini(t)=2(1.0)(1−1.0)=1−(1.02+0.02)=0
-
决策树构建的基本步骤[参考资料4-李伯韬-决策树学习笔记整理]
开始,所有记录看做一个结点;
遍历每个变量的每一种分割方式(如信息增益最大、基尼不纯度差最大),找到最好的分割点;
分割成两个结点
N1 和N2 对
N1 和N2 分别继续执行2-3步,直到每个结点足够纯为止;
-
随机森林(random forest)
集成学习(ensemble learning)方法:将一堆模型组合起来使用,比单个模型可以取得更好地效果;
随机森林(random foreset):一种集成学习方法,用随机选择训练集解释变量的子集进行训练,获取一系列决策树集合的方法;
随机森林通常用决策树集合里每个决策树的预测结果的均值或者众数作为最终预测值;
优势:相比单一决策树,不太会受到拟合过度的影响;每个决策树只训练一部分解释变量数据,不会记忆训练集的全部噪声;
-
-
Python用法
-
基本用法-Math
基本数学运算(加、减、乘、除、取余、绝对值、幂),不需要调用
math
库-
数学运算(三角函数、反三角函数、指数、对数),需要调用
math
库import math
print math.sin(10) # sine
print math.cos(10) # cosine
print math.tan(10) # tangent
print math.asin(10) # arc sine
print math.acos(10) # arc cosine
print math.atan(10) # arc tangent
print math.sinh(10) # hyperbolic sine
print math.cosh(10) # hyperbolic cosine
print math.tanh(10) # hyperbolic tangent
print math.pow(2, 4) # 2 raised to 4
print math.exp(4) # e ^ 4
print math.sqrt(10) # square root
print math.pow(5, 1/3.0) # cubic root of 5
print math.log(3) # ln; natural logarithm
print math.log(100, 10) # base 10
print math.ceil(2.3) # ceiling
print math.floor(2.7) # floor
print math.pi
print math.e -
对一组数给定1或者0
y=[1 if e=='ad.' else 0 for e in response_variable_columns]
-
Pandas库
-
.loc
使用标签选取数据;df.loc
的第一个参数是行标签,第二个参数为列标签(可选参数,默认为所有列标签),两个参数既可以是列表也可以是单个字符,如果两个参数都为列表则返回的是DataFrame,否则,则为Series。[来自参考资料8]df.loc[行标签,列标签]
df.loc['a':'b']#选取ab两行数据
df.loc[:,'one']#选取one列的数据
-
-
-
Python实例代码整理-决策树和随机森林
-
读取数据,并整理数据(将解释变量和响应变量分开,数据替代,划分成测试集和训练集)
import pandas as pd
df=pd.read_csv('Desktop/ad-dataset/ad.data',header=None,low_memory=False)
explanatory_variable_columns=set(df.columns.values)
response_variable_column=df[len(df.columns.values)-1]
explanatory_variable_columns.remove(len(df.columns.values)-1) #得到解释变量所在的列数
y=[1 if e=='ad.' else 0 for e in response_variable_column]
X=df.loc[:,list(explanatory_variable_columns)]
X.replace(to_replace=' *\?',value=-1,regex=True,inplace=True)
from sklearn.cross_validation import train_test_split
X_train,X_test,y_train,y_test=train_test_split(X,y) -
构建
pipeline
和GridSearchCV
-决策树from sklearn.pipeline import Pipeline
from sklearn.tree import DecisionTreeClassifier
from sklearn.grid_search import GridSearchCV
pipeline_Tree=Pipeline([('clf',DecisionTreeClassifier(criterion='entropy'))])
paras_Tree={'clf__max_depth':(150,155,160),'clf__min_samples_split':(1,2,3),'clf__min_samples_leaf':(1,2,3)}
grid_search_Tree=GridSearchCV(pipeline_Tree,paras_Tree,n_jobs=-1,verbose=1,scoring='f1')
grid_search_Tree.fit(X_train,y_train) -
结果输出-决策树
from sklearn.metrics import classification_report
print('best result: %0.3f' % grid_search_Tree.best_score_) #best result: 0.890
best_paras_Tree=grid_search_Tree.best_estimator_.get_params()
for param_name in sorted(paras_Tree.keys()):
print('\t%s: %r' %(param_name,best_paras_Tree[param_name]))
'''
clf__max_depth: 150
clf__min_samples_leaf: 3
clf__min_samples_split: 1
'''
predictions_Tree=grid_search_Tree.predict(X_test)
print(classification_report(y_test,predictions_Tree))
'''
precision recall f1-score support
0 0.97 0.98 0.98 708
1 0.88 0.81 0.85 112
avg / total 0.96 0.96 0.96 820
''' -
构建
pipeline
和GridSearchCV
-随机森林from sklearn.pipeline import Pipeline
from sklearn.ensemble import RandomForestClassifier
from sklearn.grid_search import GridSearchCV
pipeline_Forest=Pipeline([('clf',RandomForestClassifier(criterion='entropy'))])
paras_Forest={'clf__n_estimators':(5,10,20,50),'clf__max_depth':(50,150,250),'clf__min_samples_split':(1,2,3),'clf__min_samples_leaf':(1,2,3)}
grid_search_Forest=GridSearchCV(pipeline_Forest,paras_Forest,n_jobs=-1,verbose=1,scoring='f1')
grid_search_Forest.fit(X_train,y_train) -
结果输出-随机森林
from sklearn.metrics import classification_report
print('best result: %0.3f' % grid_search_Forest.best_score_)
best_paras_Forest=grid_search_Forest.best_estimator_.get_params()
for param_name in sorted(paras_Forest.keys()):
print('\t%s: %r' %(param_name,best_paras_Forest[param_name]))
predictions_Forest=grid_search_Forest.predict(X_test)
print(classification_report(y_test,predictions_Forest))
'''
best result: 0.922
clf__max_depth: 50
clf__min_samples_leaf: 1
clf__min_samples_split: 3
clf__n_estimators: 50
precision recall f1-score support
0 0.98 0.99 0.99 709
1 0.96 0.87 0.92 111
avg / total 0.98 0.98 0.98 820
'''
-
-
参考资料:
“Mastering Machine Learning With scikit-learn”
Wikipedia-Decision tree learning
周志华-《机器学习》
李伯韬- 决策树学习笔记整理
华山大师兄- 决策树算法总结
July-从决策树学习谈到贝叶斯分类算法、EM、HMM
tornadomeet-一些知识点的初步理解_7(随机森林,ing…)
pandas.loc()
用法