


问题是究竟选择哪个特征更好些呢?那么直观上,如果一个特征具有更好的分类能力,是的各个自己在当前的条件下有最好的分类,那么就更应该选择这个特征。信息增益就能很好的表示这一直观的准则。这样得到的一棵决策树只用了两个特征就进行了判断:


还是以贷款的例子,转换成CSV数据,如下图所示:

ID,年龄,有工作,有自己的房子,信贷情况,类别
1,青年,否,否,一般,否
2,青年,否,否,好,否
3,青年,是,否,好,是
4,青年,是,是,一般,是
5,青年,否,否,一般,否
6,中年,否,否,一般,否
7,中年,否,否,好,否
8,中年,是,是,好,是
9,中年,否,是,非常好,是
10,中年,否,是,非常好,是
11,老年,否,是,非常好,是
12,老年,否,是,好,是
13,老年,是,否,好,是
14,老年,是,否,非常好,是
15,老年,否,否,一般,否
代码如下:
from sklearn.model_selection import train_test_split
from sklearn.feature_extraction import DictVectorizer
import pandas as pd
from sklearn.tree import DecisionTreeClassifier, export_graphviz
def decision():
# 获取数据
titan = pd.read_csv("data3.csv")
# 处理数据,找出特征值和目标值
x = titan[['有工作', '有自己的房子','信贷情况']]
y = titan['类别']
# 分割数据集到训练集合测试集
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.25) # x_train, x_test是特征值 y_train, y_test是目标值
# 特征工程处理
dict = DictVectorizer(sparse=False)
x_train_ = dict.fit_transform(x_train.to_dict(orient="records"))
# print(dict.get_feature_names())
x_test_ = dict.transform(x_test.to_dict(orient="records"))
# 用决策树进行预测
dec = DecisionTreeClassifier()
dec.fit(x_train_, y_train)
y_predict = dec.predict(x_test_)
for work,house,debat,rel,pre in zip(x_test["有工作"],x_test["有自己的房子"],x_test["信贷情况"],y_test,y_predict):
if rel == pre:
print("有工作:"+work," 有自己的房子:",house," 信贷情况:",debat," 是否成功:",rel," 预测是否:",pre,"---预测成功")
else:
print("有工作:" + work, " 有自己的房子:", house, " 信贷情况:", debat, " 是否成功:", rel, " 预测是否:", pre, "---预测失败")
# 预测准确率
print("总体预测的准确率:", dec.score(x_test_, y_test))
# 导出决策树的结构
export_graphviz(dec, out_file="./tree.dot", feature_names=['信贷情况=一般', '信贷情况=好', '信贷情况=非常好', '有工作=否', '有工作=是', '有自己的房子=否', '有自己的房子=是'])
if __name__ == '__main__':
decision()

导出决策树:

决策树的一些优点是:
简单的理解和解释。树木可视化。
需要很少的数据准备。其他技术通常需要数据归一化,需要创建虚拟变量,并删除空值。但请注意,此模块不支持缺少值。
使用树的成本(即,预测数据)在用于训练树的数据点的数量上是对数的。
决策树的缺点包括:
决策树学习者可以创建不能很好地推广数据的过于复杂的树。这被称为过拟合。修剪(目前不支持)的机制,设置叶节点所需的最小采样数或设置树的最大深度是避免此问题的必要条件。
决策树可能不稳定,因为数据的小变化可能会导致完全不同的树被生成。通过使用合奏中的决策树来减轻这个问题。
代码如下(还是以贷款为例):
from sklearn.model_selection import train_test_split, GridSearchCV
from sklearn.feature_extraction import DictVectorizer
from sklearn.ensemble import RandomForestClassifier
import pandas as pd
def decision():
# 获取数据
titan = pd.read_csv("data3.csv")
# 处理数据,找出特征值和目标值
x = titan[['有工作', '有自己的房子', '信贷情况']]
y = titan['类别']
# 分割数据集到训练集合测试集
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.25) # x_train, x_test是特征值 y_train, y_test是目标值
# 特征工程处理
dict = DictVectorizer(sparse=False)
x_train_ = dict.fit_transform(x_train.to_dict(orient="records"))
print(dict.get_feature_names())
x_test_ = dict.transform(x_test.to_dict(orient="records"))
# 随机森林进行预测 (超参数调优)
rf = RandomForestClassifier(n_jobs=-1)
param = {"n_estimators": [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)
y_predict = gc.predict(x_test_)
for work, house, debat, rel, pre in zip(x_test["有工作"], x_test["有自己的房子"], x_test["信贷情况"], y_test, y_predict):
if rel == pre:
print("有工作:" + work, " 有自己的房子:", house, " 信贷情况:", debat, " 是否成功:", rel, " 预测是否:", pre, "---预测成功")
else:
print("有工作:" + work, " 有自己的房子:", house, " 信贷情况:", debat, " 是否成功:", rel, " 预测是否:", pre, "---预测失败")
# 预测准确率
print("总体预测的准确率:", gc.score(x_test_, y_test))
print("查看选择的参数模型:", gc.best_params_)
if __name__ == '__main__':
decision()
运行截图:
