决策树分类算法伪代码&sklearn实战

一.工作原理

构造决策树会遇到的问题:
1.在每次划分怎么确定用哪个特征?
使用熵来消除数据的不确定性
2.如果划分完所有的特征,还是有不同的类别怎么办?
类别频数最高的当作叶节点的分类

二.伪代码

构建决策数(训练集, 特征名列表):
	停止条件1:训练集中的目标变量只有一种,返回目标变量
	停止条件2:特征变量都用完了,返回频数最高的目标变量
	找出划分训练集能最大降低香浓熵的最优特征
	特征名列表去除最优
	创造key为特征value为空字典的树字典
	for 特征的值 in 特征:
		用指定的特征,特征的值来划分训练集,并得到划分后的训练集
		空字典的key为特征的值,value = 构建决策数(划分后的训练集,特征名列表)
	return 树字典
	
找出最优特征(训练集):
	for 特征 in 训练集:
		for 特征值 in 特征:
			通过特征的值水平方向划分训练集
		求出划分后的所有训练集的信息增益
	找出最大的信息增益,确定特征
	return 特征
		
划分训练集(训练集,特征,目标值)
	通过特征水平方向划分训练集
	选出特征值为目标值得训练集子集
	return 子集

计算香农熵(训练集):
	计算所有分类的频数
	for 分类 in 分类集合:
		香浓熵 = - 分类概率 * log(分类概率,2)
	求和所有分类的香浓熵
	return 总的香农熵

分类器(树字典, 特征名列表, 测试样本): 
	找到树字典的根节点对应的特征
	用测试样本对应的特征值找到分支
	获取对应的字典value
	停止条件:value不为字段,返回value值
	if value为字典:
		叶节点 = 分类器(value, 特征名列表, 测试样本)
	return 叶节点

三. 使用sklearn构造决策树
使用的环境是jupyter notebook

from sklearn import tree  # 树模型
from sklearn.model_selection import train_test_split  # 划分训练集和测试集的函数
from sklearn.datasets import load_wine  # 导入数据
import graphviz  # 画图

wine = load_wine()  # 导入数据
X = wine.data  # 特征集
Y = wine.target  # 类别,保存每行数据为哪个类别 

Xtrain, Xtest, Ytrain, Ytest = train_test_split(wine.data,wine.target,test_size=0.3)  # 划分训练集与测试集, 比例为7:3

clf = tree.DecisionTreeClassifier(criterion="entropy")  # 建立模型,最简的方法,有很多参数没用到
clf = clf.fit(Xtrain, Ytrain)  # 填充训练数据
score = clf.score(Xtest, Ytest) #返回预测的准确度

# 使用grahpviz画出树
feature_name = ['酒精','苹果酸','灰','灰的碱性','镁','总酚','类黄酮','非黄烷类酚类','花青素','颜色强度','色调','od280/od315稀释葡萄酒','脯氨酸']
class_names = ['琴酒', '雪莉', '贝尔摩德']
dot_data = tree.export_graphviz(clf
                                ,feature_names=feature_name
                                ,class_names=class_names
                                ,filled=True
                                ,rounded=True
                                ,out_file=None)
graph = graphviz.Source(dot_data)
graph  # 会输出树的图片

print(clf.feature_importances_)  # 打印出每个特征的相关性,帮助我们分析哪些特征比较有用

# 常用参数解释
# random_state 默认为None,当设定一个整数时,每次运行树模型,树的结构都不会变
# splitter 值有"best"\"random"两个,best会优先选择重要的特征进行分支,random则是随机选择
# max_depth 树的最大深度
# min_samples_leaf 每个节点最少要包含的样本数,如果少于这个值,那么父节点就不会分支,父节点当成一个叶节点,叶节点的分类是数量最多的分类
# min_samples_split 每个被分支的节点最少要包含的样本数
# max_features 分支时使用的特征数
# min_impurity_decrease 信息增益的值小于阈值就不会分支

# 使用max_depth参数来对树模型进行调优(这里只是举例,还可以用不同的参数进行调优), 并且画图展示
import matplotlib.pyplot as plt
%matplotlib inline

test = []
for i in range(10):
    clf = tree.DecisionTreeClassifier(max_depth=i+1
                                      ,criterion="entropy"
                                      ,random_state=30
                                      ,splitter="random"
                                     )
    clf = clf.fit(Xtrain, Ytrain)
    score = clf.score(Xtest, Ytest)
    test.append(score)
plt.plot(range(1,11),test,color="red",label="max_depth")
plt.legend()
plt.show()  # 会输出不同max_depth对应的得分图

四. 当样本中的分类不均衡时解决方案

在银行要判断“一个办了信用卡的人是否会违约”,就是是vs否(1%:99%)的比例。这种分类状况下,即便模型什么也不做,全把结果预测成“否”,正确率也能有99%。因此我们要使用class_weight参数对样本标签进行一定的均衡,给少量的标签更多的权重,让模型更偏向少数类,向捕获少数类的方向建模。

# class_weight 有个参数balanced, 或者想要自定义[{0: 1, 1: 1}, {0: 1, 1: 5}, {0: 1, 1: 1}, {0: 1, 1: 1}] instead of [{1:1}, {2:5}, {3:1}, {4:1}]
# min_weight_fraction_leaf 分支后每个叶子中样本的分类数量要不小于该分数与分类总频数的乘积
clf = DecisionTreeClassifier(criterion="entropy", class_weight='balanced', min_weight_fraction_leaf=0.1)  # min_weight_fraction参数需要自己调
clf = clf.fit(Xtrain, Ytrain)
score = clf.score(Xtest, Ytest) 
  • 0
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值