一 CART算法基本
上篇为 决策树的基本原理篇,本文主要是聊下CART算法,因为在上文提到的决策树算法中,CART算法在三种决策树算法中应用的最多,CART算法优点:
- 分类规则清晰,结果容易理解
- 计算量小,速度快
- 可以处理异常值,缺失值,不同数量级的值。
二 CART算法原理
CART算法采用Gini系数来判断划分集合的纯度,Gini系数是一个0-1之间的数字,值越小表示纯度越高,数据越集中;值越大表示数据越分散。所以我们划分的时候选择基尼系数最小的属性作为划分条件,其实和信息熵类似,都是一种纯度表示方法。
从数据实战四十五讲里面的公式如下:
父节点的基尼系数等于两个子节点的基尼系数归一化之和:
三 决策树算法实践
决策树算法算是比较简单和好理解的算法了,下面还是用以前SVM的代码来实践下决策树算法,同时练习下如何保存模型和加载模型,以及一些数据可视化的。
如果你多运行几次代码,会发现sklearn 决策树算法的每次执行的结果的准确率并不相同,那么这个是怎么回事,找了一个解释:
# -*- coding: utf-8 -*-
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
from sklearn.tree import DecisionTreeClassifier
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.preprocessing import StandardScaler
from sklearn.tree import export_graphviz
import graphviz
import pickle
from sklearn.externals import joblib
import time
# 加载数据集,你需要把数据放到目录中
data = pd.read_csv("./data.csv")
# 数据清洗
# ID列没有用,删除该列
data.drop("id",axis=1,inplace=True)
# 将B良性替换为0,M恶性替换为1
data['diagnosis'] = data['diagnosis'].map({'M':1,'B':0})
#特征选择
all_mean= list(data.columns[0:32])
corr = data[all_mean].corr(method='pearson')
sorted_features = corr['diagnosis'].sort_values(ascending=False)
chose_features = []
#选择相关性最大的top10数据
feture_num = 13
#去除第一个结果集选择属性
for i in sorted_features[1:feture_num].index:
chose_features.append(i)
print(chose_features)
# 抽取30%的数据作为测试集,其余作为训练集
train, test = train_test_split(data, test_size = 0.3)# in this our main data is splitted into train and test
# 抽取特征选择的数值作为训练和测试数据
train_X = train[chose_features]
train_y = train['diagnosis']
test_X = test[chose_features]
test_y = test['diagnosis']
# 采用Z-Score规范化数据,保证每个特征维度的数据均值为0,方差为1
ss = StandardScaler()
train_X = ss.fit_transform(train_X)
test_X = ss.transform(test_X)
# 创建CART分类树
clf = DecisionTreeClassifier(criterion='gini', random_state=1)
# 拟合构造CART分类树
clf = clf.fit(train_X, train_y)
# 用测试集做预测
prediction=clf.predict(test_X)
# 预测结果与测试集结果作比对
score = accuracy_score(test_y, prediction)
print("CART分类树准确率 %.4lf" % score)
# 保存成python支持的文件格式pickle, 在当前目录下可以看到dtree.pickle
pickle_start = time.perf_counter ()
with open('dtree.pickle', 'wb') as fw:
pickle.dump(clf, fw)
# dtree.pickle
with open('dtree.pickle', 'rb') as fr:
new_clf = pickle.load(fr)
prediction_load = new_clf.predict(test_X)
score_load = accuracy_score(test_y, prediction)
print("Pickle CART分类树准确率 %.4lf" % score_load)
pickle_end = time.perf_counter ()
print("Pickle dump and load and run cost:%s" % str(pickle_end-pickle_start))
# 保存成sklearn自带的文件格式
jblib_start = time.perf_counter ()
joblib.dump(clf, 'clf.pkl')
# 加载clf.pkl
new_job_clf = joblib.load('clf.pkl')
prediction_load_sklearn = new_job_clf.predict(test_X)
score_load_sklearn = accuracy_score(test_y, prediction)
print("Sklearn 自己模型的格式 CART分类树准确率 %.4lf" % score_load_sklearn)
jblib_end = time.perf_counter ()
print("JobLib dump and load and run cost:%s" % str(jblib_end-jblib_start))
#画图
dot_data = export_graphviz(clf,out_file=None)
graph = graphviz.Source(dot_data)
graph.render('Boston')
从结果来说,pickle的文件大小和joblib大小类似;sklearn的模型加载运行的速度更快。
代码中生成的图,使用了graphviz 库需要安装。
安装参考:https://www.cnblogs.com/shuodehaoa/p/8667045.html
官网地址:http://www.graphviz.org/about/
再接着安装python的相关库: pip install graphvize
Graphviz布局程序以简单的文本语言描述图形,并以几种有用的格式制作图形,例如用于网页的图像和SVG,用于PDF或其他文档的Postscript。或在交互式图形浏览器中显示。(Graphviz还支持XML方言GXL。)Graphviz具有用于具体图表的许多有用功能,例如颜色,字体,表格节点布局,线型,超链接和自定义形状的选项。
生成的pdf图像是如下:
里面可以清楚的看出CART树是一颗二叉树,最多有两个节点,每个节点都有计算得出的gini系数的值和一些属性信息还是蛮好的。
在sklearn的记录文档里是这么写的,考虑到数值特征的存在,训练一个最优的决策树是NP-complete。因此比较实际的做法是努力去找一个比较优的,而不是最优的。比如用贪婪算法,随机地从一些特征开始建立次优化的决策树,再从这些树中选择最好的,这样的树能达到较优。