5. 决策树
5.1 认识决策树
如何高效的进行决策?
特征的先后顺序
5.2 决策树分类原理详解
已知四个特征,来判断是否贷款给他
情况1:
如果先看房子,都能拿到贷款。
如果没有房子,则不一定能同意贷款,则应加入别的特征。如工作。
因此先看房子,再看工作,一共两个特征就能决定上面样本是否可以进行贷款了
情况2:
但是如果先看年龄,后信贷情况,还是无法决定是否贷款,则需要再加入其他特征,如工作。那么这个顺序需要看三个特征
情况三:有工作作为第一个特征
那么如何判断特征的先后顺序呢?
5.2.1 信息熵
原理:信息熵,信息增益等。
需要引入信息论的知识,问题:通过例子引入信息熵。
- 信息的定义:消除随机不定性的东西
小明 年龄 ‘我今年18岁’——是信息,是我不确定的
小华 年龄 ‘小明明年19岁’——不是信息,根据上面可以进行推断 - 信息的数量-信息量-信息熵 。衡量消除不确定性的多少。
- 信息量的定义:信息量度量的是一个具体事件发生所带来的信息,衡量信息量大小就看这个信息消除不确定性的程度。
信息量的大小和事件发生的概率成反比。
4. 信息熵的定义:
总的不确定性H(D)根据公式计算。然后计算哪种特征对于这种不确定性减少最少。则使用信息增益
5.2.2 信息增益
- 定义与公式
5.2.3 决策树划分依据之一是信息增益
5.3 API
5.4 鸢尾花案例
from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier, export_graphviz
"""
学习要点:信息熵 信息增益
"""
def show_tree(estimator, feature_name):
export_graphviz(estimator, out_file="../tree.dot", feature_names=feature_name) # 生成树文件, 可以用图像识别软件来画树
return None
def decision_tree_test():
iris = datasets.load_iris()
x_train, x_test, y_train, y_test = train_test_split(iris.data, iris.target, random_state=22)
estimator = DecisionTreeClassifier(criterion="entropy")
estimator.fit(x_train, y_train)
show_tree(estimator, iris.feature_names)
y_predict = estimator.predict(x_test)
print("预测值为:", y_predict, "\n真实值为:", y_test, "\n比较结果为:", y_test == y_predict)
score = estimator.score(x_test, y_test)
print("准确率为: ", score)
return None
if __name__ == '__main__':
decision_tree_test()
5.5 决策树可视化
保存树的结构到dot文件中——API如下
得到dot文件之后,还有方法可以进行可视化可视化网址
5.6 决策树总结
优点:简单的理解和解释,可视化——可解释能力强
缺点:决策树学习者可以创建不能很好地推广数据的过于复杂的树,容易产生过拟合
,
5.7 泰坦尼克号案例
1)获取数据集
2)数据处理:
- 缺失值处理。
- 由于数据集中包含较多类别,因此采用one-hot编码,为了方便操作可将特征值->转换成字典类型。
3)准备好特征值和目标值
其中对于row.name name 等特征对于是否生存,不存在关系。而"pclass", “age”, "sex"明显与生存存在联系。
"survived"为目标值
fillna
填充缺省值
4)划分数据集
5)特征工程:字典特征抽取
6)决策树预估流程
7)模型评估
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier, export_graphviz
from sklearn.feature_extraction import DictVectorizer
import numpy as np
def load_data():
data = pd.read_csv("../../resources/titanic/titanic.csv")
titanic = data.copy()
# 方法一: 过滤掉空的值的数据组, 准确率高点
data_used = titanic[["pclass", "age", "sex", "survived"]]
real_data = pd.DataFrame(columns=["pclass", "age", "sex", "survived"])
for row in data_used.values:
if not np.isnan(row[1]):
real_data = real_data.append([{'pclass': row[0], 'age': row[1],
'sex': row[2], 'survived': row[3]}],
ignore_index=True)
x = real_data[["pclass", "age", "sex"]].to_dict(orient="records")
y = real_data["survived"]
# 方法二: 对空数据设置个非0值
# x = titanic[["pclass", "age", "sex"]] # 只提取这一些特征
# y = titanic["survived"] # 目标值
# x["age"].fillna(x["age"].mean(), inplace=True)
# x = x.to_dict(orient="records")
x_train, x_test, y_train, y_test = train_test_split(x, y.astype('int'), random_state=22)
return x_train, x_test, y_train, y_test
def show_tree(estimator, feature_name):
export_graphviz(estimator, out_file="../titanic_tree.dot", feature_names=feature_name)
return None
def titanic_test():
x_train, x_test, y_train, y_test = load_data()
transfer = DictVectorizer()
x_train = transfer.fit_transform(x_train)
x_test = transfer.transform(x_test)
estimator = DecisionTreeClassifier(criterion="entropy", max_depth=12)
estimator.fit(x_train, y_train)
show_tree(estimator, transfer.get_feature_names())
y_predict = estimator.predict(x_test)
print("预测值为:", y_predict, "\n真实值为:", y_test, "\n比较结果为:", y_test == y_predict)
score = estimator.score(x_test, y_test)
print("准确率为: ", score)
return None
if __name__ == '__main__':
titanic_test()