决策树
信息论基础
信息量
在日常生活中,极少发生的事件一旦发生是容易引起人们关注的,而司空见惯的事不会引起注意,也就是说,极少见的事件所带来的信息量多。如果用统计学的术语来描述,就是出现概率小的事件信息量多。因此,事件出现得概率越小,信息量愈大。即信息量的多少是与事件发生频繁(即概率大小)成反比。
如已知事件X已发生,则表示X所含有或所提供的信息量为:
信息熵
信息熵这个词是香农从热力学中借用来的。热力学中的热熵表示分子状态混乱程度,香农用信息熵的概念来描述信源的不确定度(变量的不确定性越大,熵也就越大,把它搞清楚所需要的信息量也就越大)。
在信源中,考虑的不是某一单个符号发生的不确定性,而是要考虑这个信源所有可能发生情况的平均不确定性。若信源符号有n种取值:U1…Ui…Un,对应概率为:P1…Pi…Pn,且各种符号的出现彼此独立。这时,信源的平均不确定性应当为单个符号不确定性-logPi的统计平均值,可称为信息熵,即,
式中对数一般取2为底,单位为比特。但是,也可以取其它对数底,采用其它相应的单位,它们间可用换底公式换算。
决策树
引出
“有自己的房子”放在第一位(第一个判定标准),能减少更多的不确定性。
信息增益
信息增益是决策树的划分依据之一。通俗的来说,信息增益就是当得知一个特征条件之后,减少的信息熵的大小。
- 信息增益的定义
- 信息增益的计算
例:
常见决策树使用的算法
ID3 : 信息增益最大的原则
C4.5:信息增益比最大的原则
CART:
回归树:平方误差最小
分类树:基尼系数 最小的准则 sklearn中默认原则
sklearn决策树API
sklearn.tree.DecisionTreeClassifier(criterion = “gini”, max_depth = None, random_state = None)
criterion:默认时“gini”系数,也可以选择信息增益的熵“entropy”
max_depth:树的深度大小
random_state:随机数种子
decision_path: 返回决策树的路径
决策树的结构和本地保存
1.== sklearn.tree.export_graphviz==(estimator, out_file = 路径, feature_names = [""])
该函数能够导出DOT格式
2. 安装工具,将dot文件转化为pdf、png
ubuntu:sudo apt-get install graphviz
3. 运行命令
dot-Tpng tree.dot -o tree.png
案例:泰坦尼克号乘客生存分类模型
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.feature_extraction import DictVectorizer
from sklearn.tree import DecisionTreeClassifier
from sklearn.tree import export_graphviz
def titan():
# 获取数据
titan = pd.read_csv("http://biostat.mc.vanderbilt.edu/wiki/pub/Main/DataSets/titanic.txt")
# print(titan)
# 处理数据,找出特征值和目标值
x = titan[["pclass", "age", "sex"]]
y = titan["survived"]
# 缺失值处理
x["age"].fillna(x["age"].mean(), inplace=True)
# 分割数据集为训练集和测试集
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.25)
# 特征工程(特征提取,将数据转化为one-hot编码)
dict = DictVectorizer(sparse=False)
# 将数据按行(orient)转化为字典形式
x_train = dict.fit_transform(x_train.to_dict(orient="records"))
print(dict.get_feature_names())
# print(x_train)
x_test = dict.transform(x_test.to_dict(orient="records"))
# 用决策树进行预测
dec = DecisionTreeClassifier()
dec.fit(x_train, y_train)
# 预测准确率
print("预测结果:", dec.predict(x_test))
print("预测准确率:", dec.score(x_test, y_test))
# 导出决策树的结构
export_graphviz(dec, out_file="./tree.dot", feature_names=['年龄', 'pclass=1st', 'pclass=2nd', 'pclass=3rd', 'sex=female', 'sex=male'])
if __name__ == '__main__':
titan()
决策树优缺点及改进
优点:
- 简单的理解和解释,树木可视化;
- 需要很少的数据准备,其他数据通常需要进行归一化。
缺点:
决策树学习者可以穿件不能很好地推广数据的过于复杂的树,这被称为过拟合。
改进:
4. 减枝cart算法(决策树API当中已经实现,随机森林参数调优有相关介绍)
5. 随机森林
注:企业重要决策,由于决策树很好的分析能力,在决策过程中应用较多。
随机森林
集成学习方法
随机森林是集成学习方法。集成学习通过建立几个模型组合来解决单一预测问题。它的工作原理是生成多个分类器/模型,各自独立地学习和做出预测。这些预测最后结合成单预测,因此优于任何一个单分类器(例如,如果训练了5棵树,输入一个测试样本数据,若有4个数的结果是True,1个树的结果是False,那么最终的结果会是True)。随机森林最后分类取决于多棵树(弱分类器)的投票表决。
随机森林建立多个决策树的过程
假设有N个样本,M个特征。
单个树建立过程:
- 随机在N个样本中选择一个样本,重复N次(随机有放回抽样)–bootstrap抽样;
- 随机在M个特征中选出m个特征(m<M);
- (假设)建立10棵决策树,样本、特征大多不一样。
随机森林API
sklearn.ensemble.RandomForestClassifier(n_estimators = 10, criterion = “gini”, max_depth = None, bootstrap = True, random_state = None)
主要超参数:
n_estimator:森林里的树木数量—120、200、300、500、800、1200
max_depth:树的最大深度—5、8、15、25、30
max_features = “auto”, 每个决策树的最大特征数量(
if “auto”, then “max_features” = sqrt(n_features);
if “sqrt”, then “max_features” = sqrt(n_features);
if “log2”, then “max_features” = log2(n_features);
if None, then “max_features” = n_features )
bootstrap:默认True,是否在构建树时使用有放回抽样。
随机森林的优点
- 在当前所有的算法中,具有极好的准确率;
- 能够有效运行在大数据集熵;
- 能够处理具有高维度特征的输入样本,且不需要降维;
- 能够评估各个特征在分类问题上的重要性。
案例
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.feature_extraction import DictVectorizer
from sklearn.tree import DecisionTreeClassifier
from sklearn.tree import export_graphviz
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import GridSearchCV
def titan():
# 获取数据
titan = pd.read_csv("http://biostat.mc.vanderbilt.edu/wiki/pub/Main/DataSets/titanic.txt")
# print(titan)
# 处理数据,找出特征值和目标值
x = titan[["pclass", "age", "sex"]]
y = titan["survived"]
# 缺失值处理
x["age"].fillna(x["age"].mean(), inplace=True)
# 分割数据集为训练集和测试集
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.25)
# 特征工程(特征提取,将数据转化为one-hot编码)
dict = DictVectorizer(sparse=False)
# 将数据按行(orient)转化为字典形式
x_train = dict.fit_transform(x_train.to_dict(orient="records"))
print(dict.get_feature_names())
# print(x_train)
x_test = dict.transform(x_test.to_dict(orient="records"))
# 用决策树进行预测
# dec = DecisionTreeClassifier()
# dec.fit(x_train, y_train)
#
# # 预测准确率
# print("预测结果:", dec.predict(x_test))
# print("预测准确率:", dec.score(x_test, y_test))
#
# # 导出决策树的结构
# export_graphviz(dec, out_file="./tree.dot", feature_names=['年龄', 'pclass=1st', 'pclass=2nd', 'pclass=3rd', 'sex=female', 'sex=male'])
# 用随机森林进行预测
rf = RandomForestClassifier()
# 网格搜索与交叉验证
param = {"n_neighbors": [120, 200, 300, 500, 800, 1200], "max_depth": [5, 8, 15, 25, 30]}
gc = GridSearchCV(rf, param_grid=param, cv=2)
gc.fit(x_train, y_train)
print("准确率:", gc.score(x_test, y_test))
print("查看选择的参数模型:", gc.best_params_)
if __name__ == '__main__':
titan()