基于决策树的分类预测
一、决策树概述
(一)、基本介绍
决策树(Decision Tree)算法是一种基本的分类与回归方法,决策树模型呈树形结构,在分类问题中,表示基于特征对实例进行分类的过程。它可以认为是 if-then 规则的集合,也可以认为是定义在特征空间与类空间上的条件概率分布。
结构:一般的,一棵决策树包含一个根结点、若干个内部结点和若干个叶结点;根结点包含样本全集;决策树叶结点对应于决策结果,其他每个结点则对应于一个属性测试;每个结点包含的样本集合根据属性测试的结果被划分到子结点中。从根结点到每个叶结点的路径对应了一个判定测试序列。
目的:决策树学习的目的是为 了产生一棵泛化能力强,即处理未见示例能力强的决策树,其基本流程遵循简单且直观的"分而治之" (divide-and-conquer) 策略。
步骤:决策树学习通常包括 3 个步骤:特征选择、决策树的生成和决策树的修剪。其基本算法流程如下图所示:
显然,决策树的生成是一个递归过程。在决策树基本算法中,有三种情形会导致递归返回:
(1) 当前结点包含的样本全属于同一类别,无需划分;
(2) 当前 属性集为空,或是所有样本在所有属性上取值相同,无法划分;
(3) 当前结点包 含的样本集合为空,不能划分。
(二)、划分选择
决策树的性能如何一般取决于如何选择最优划分属性,建立决策树。一般而言,随着划分过程不断进行,我们希望决策树的分支结点所包含的样 本尽可能属于同一类别,即结点的"纯度" (purity) 越来越高。主要有一下三种准则:
(1) 信息熵:信息熵(information entropy) 是度量样本集合纯度最常用的一种指标,信息熵越大,纯度越高。
(2)信息增益:一般而言,信息增益越大,则意味着使用属性来进行划分所获得的"纯度提升"越大。因此,我们可用信息增益来进行决策树的划分属性选择。
(3) 增益率:实际上,信息增益准则对可取值数目较多的属性有所偏好,为减少这种偏好可能带来的不利影响,有时决策树算法不直接使用信息增益,而是使用增益率"(gain ratio) 来选择最优划分属性。
(4) 基尼指数:CART决策树使用"基尼指数" (Gini index) 来选择划分属性,直观来说, 基尼指数反映了从数据集 中随机抽取两个样本,其类别标记不一致的概率.因此,基尼指数越小,则数据集的纯度越高。于是,我们在候选属性集合中,选择那个使得划分后基尼指数最小的属性作为最优划分属性。
(三)剪枝处理
剪枝(pruning) 是决策树学习算法对付"过拟合"的主要手段.在决策树学习中,为了尽可能正确分类训练样本,结点划分过程将不断重复,有时会造成决 策树分支过多,这时就可能因训练样本学得"太好"了,以致于把训练集自身 的一些特点当作所有数据都具有的一般性质而导致过拟合.因此,可通过主动 去掉一些分支来降低过拟合的风险。主要有两种剪枝方式:
(1) 预剪枝:. 预剪枝是指在决策树生成过程中,对每个结点在划 分前先进行估计,若当前结点的划分不能带来决策树泛化性能提升,则停止划 分并将当前结点标记为叶结点;
预剪枝优缺点:预剪枝使得决策树的很多分支都没有"展 开“,这不仅降低了过拟合的风险,还显著减少了决策树的训练时间开销和测试时间开销。但另一方面,有些分支的当前划分虽不能提升泛化性能、甚至可 能导致泛化性能暂时下降,但在其基础上进行的后续划分却有可能导致性能显 著提高;预剪枝基于"贪心"本质禁止这些分支展开 给预剪枝决策树带来了 欠拟含的风险。
(2) 后剪枝:;后剪枝则是先从训练集生成一棵完整的决策树, 然后自底向上地对非叶结点进行考察,若将该结点对应的子树替换为叶结点能带来决策树泛化性能提升,则将该子树替换为叶结点;
后剪枝优缺点:后剪枝决策树通常比预剪枝决策树保留 了更多的分支 一般情形下,后剪枝决策树的欠拟合风险很小,泛化能往往 剪枝决策树。但后剪枝过程是在生成完全决策树之后进行的 并且要白底向上对树中的所有非叶结点进行逐考察,因此其训练时间开销比未剪枝决策树和预剪枝决策树都要大得多。
二、DEMO实战案例
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.tree import DecisionTreeClassifier
from sklearn import tree
from sklearn.model_selection import train_test_split
from mpl_toolkits.mplot3d import Axes3D
import graphviz
import seaborn as sns
import sys, io, os
sys.stdout = io.TextIOWrapper(sys.stdout.buffer,encoding='utf-8')
def demoTree():
x_fearures = np.array([[-1, -2], [-2, -1], [-3, -2], [1, 3], [2, 1], [3, 2]])
y_label = np.array([0, 1, 0, 1, 0, 1])
tree_clf = DecisionTreeClassifier()
tree_clf = tree_clf.fit(x_fearures, y_label)
plt.figure()
plt.scatter(x_fearures[:,0],x_fearures[:,1], c=y_label, s=50, cmap='viridis')
plt.title('Dataset')
plt.show()
x_fearures_new1 = np.array([[0, -1]])
x_fearures_new2 = np.array([[2, 1]])
## 在训练集和测试集上分布利用训练好的模型进行预测
y_label_new1_predict = tree_clf.predict(x_fearures_new1)
y_label_new2_predict = tree_clf.predict(x_fearures_new2)
print('The New point 1 predict class:\n',y_label_new1_predict)
print('The New point 2 predict class:\n',y_label_new2_predict)
三、基于企鹅数据集的决策树实战案例
选择企鹅数据(palmerpenguins)进行方法的尝试训练,该数据集一共包含8个变量,其中7个特征变量,1个目标分类变量。共有344个样本,目标变量为企鹅的类别,其都属于企鹅类的三个亚属,分别是(Adélie, Chinstrap and Gentoo)。包含的三种种企鹅的七个特征,分别是所在岛屿,嘴巴长度,嘴巴深度,脚蹼长度,身体体积,性别以及年龄。
数据集下载链接:https://tianchi-media.oss-cn-beijing.aliyuncs.com/DSW/6tree/penguins_raw.csv
def palmeDecisionTree(path):
data = pd.read_csv(path)
## 为了方便我们仅选取四个简单的特征,有兴趣的同学可以研究下其他特征的含义以及使用方法
data = data[['Species','Culmen Length (mm)','Culmen Depth (mm)',
'Flipper Length (mm)','Body Mass (g)']]
## 利用.info()查看数据的整体信息
data.info()
## 进行简单的数据查看,我们可以利用 .head() 头部.tail()尾部
data.head()
data = data.fillna(-1) # 用-1填补缺失值
data.tail()
## 其对应的类别标签为'Adelie Penguin', 'Gentoo penguin', 'Chinstrap penguin'三种不同企鹅的类别。
data['Species'].unique()
## 利用value_counts函数查看每个类别数量
pd.Series(data['Species']).value_counts()
## 对于特征进行一些统计描述
data.describe()
## 特征与标签组合的散点可视化
sns.pairplot(data=data, diag_kind='hist', hue= 'Species')
plt.show()
'''为了方便我们将标签转化为数字
'Adelie Penguin (Pygoscelis adeliae)' ------0
'Gentoo penguin (Pygoscelis papua)' ------1
'Chinstrap penguin (Pygoscelis antarctica) ------2 '''
def trans(x):
if x == data['Species'].unique()[0]:
return 0
if x == data['Species'].unique()[1]:
return 1
if x == data['Species'].unique()[2]:
return 2
data['Species'] = data['Species'].apply(trans)
for col in data.columns:
if col != 'Species':
sns.boxplot(x='Species', y=col, saturation=0.5, palette='pastel', data=data)
plt.title(col)
plt.show()
# 选取其前三个特征绘制三维散点图
fig = plt.figure(figsize=(10,8))
ax = fig.add_subplot(111, projection='3d')
data_class0 = data[data['Species']==0].values
data_class1 = data[data['Species']==1].values
data_class2 = data[data['Species']==2].values
# 'setosa'(0), 'versicolor'(1), 'virginica'(2)
ax.scatter(data_class0[:,0], data_class0[:,1], data_class0[:,2],label=data['Species'].unique()[0])
ax.scatter(data_class1[:,0], data_class1[:,1], data_class1[:,2],label=data['Species'].unique()[1])
ax.scatter(data_class2[:,0], data_class2[:,1], data_class2[:,2],label=data['Species'].unique()[2])
plt.legend()
plt.show()
## 为了正确评估模型性能,将数据划分为训练集和测试集,并在训练集上训练模型,在测试集上验证模型性能。
## 选择其类别为0和1的样本 (不包括类别为2的样本)
data_target_part = data[data['Species'].isin([0,1])][['Species']]
data_features_part = data[data['Species'].isin([0,1])][['Culmen Length (mm)','Culmen Depth (mm)',
'Flipper Length (mm)','Body Mass (g)']]
## 测试集大小为20%, 80%/20%分
x_train, x_test, y_train, y_test = train_test_split(data_features_part, data_target_part, test_size = 0.2, random_state = 2020)
## 从sklearn中导入决策树模型
from sklearn.tree import DecisionTreeClassifier
from sklearn import tree
## 定义 决策树模型
clf = DecisionTreeClassifier(criterion='entropy')
# 在训练集上训练决策树模型
clf.fit(x_train, y_train)
## 在训练集和测试集上分布利用训练好的模型进行预测
train_predict = clf.predict(x_train)
test_predict = clf.predict(x_test)
from sklearn import metrics
## 利用accuracy(准确度)【预测正确的样本数目占总预测样本数目的比例】评估模型效果
print('The accuracy of the Logistic Regression is:',metrics.accuracy_score(y_train,train_predict))
print('The accuracy of the Logistic Regression is:',metrics.accuracy_score(y_test,test_predict))
## 查看混淆矩阵 (预测值和真实值的各类情况统计矩阵)
confusion_matrix_result = metrics.confusion_matrix(test_predict,y_test)
print('The confusion matrix result:\n',confusion_matrix_result)
# 利用热力图对于结果进行可视化
plt.figure(figsize=(8, 6))
sns.heatmap(confusion_matrix_result, annot=True, cmap='Blues')
plt.xlabel('Predicted labels')
plt.ylabel('True labels')
plt.show()
## 测试集大小为20%, 80%/20%分
x_train, x_test, y_train, y_test = train_test_split(data[['Culmen Length (mm)','Culmen Depth (mm)',
'Flipper Length (mm)','Body Mass (g)']], data[['Species']], test_size = 0.2, random_state = 2020)
## 定义 决策树模型
clf = DecisionTreeClassifier()
# 在训练集上训练决策树模型
clf.fit(x_train, y_train)
## 在训练集和测试集上分布利用训练好的模型进行预测
train_predict = clf.predict(x_train)
test_predict = clf.predict(x_test)
## 由于决策树模型是概率预测模型(前文介绍的 p = p(y=1|x,\theta)),所有我们可以利用 predict_proba 函数预测其概率
train_predict_proba = clf.predict_proba(x_train)
test_predict_proba = clf.predict_proba(x_test)
print('The test predict Probability of each class:\n',test_predict_proba)
## 其中第一列代表预测为0类的概率,第二列代表预测为1类的概率,第三列代表预测为2类的概率。
## 利用accuracy(准确度)【预测正确的样本数目占总预测样本数目的比例】评估模型效果
print('The accuracy of the Logistic Regression is:',metrics.accuracy_score(y_train,train_predict))
print('The accuracy of the Logistic Regression is:',metrics.accuracy_score(y_test,test_predict))
## 查看混淆矩阵
confusion_matrix_result = metrics.confusion_matrix(test_predict,y_test)
print('The confusion matrix result:\n',confusion_matrix_result)
# 利用热力图对于结果进行可视化
plt.figure(figsize=(8, 6))
sns.heatmap(confusion_matrix_result, annot=True, cmap='Blues')
plt.xlabel('Predicted labels')
plt.ylabel('True labels')
plt.show()
上一篇: 设计模式——适配器模式
下一篇: i386 architecture of input file `D:/MinGW/lib/../lib/crt2.o' is incompatible with i386:x86-64 output
推荐阅读
-
基于决策树的分类预测
-
基于geoserver的eclipse管理插件 博客分类: GIS
-
基于倒排索引的缓存对象索引通用解决方案 博客分类: java java倒排索引
-
基于倒排索引的缓存对象索引通用解决方案 博客分类: java java倒排索引
-
基于tomcat插件的maven多模块工程热部署(附插件源码) 博客分类: java tomcat插件maven多模块热部署
-
基于ruby-protobuf的rpc示例 博客分类: Ruby RubyGoogle
-
基于ruby-protobuf的rpc示例 博客分类: Ruby RubyGoogle
-
基于Solr的空间搜索(1) 博客分类: Solr
-
基于Solr的空间搜索(1) 博客分类: Solr
-
基于信息增益的决策树特征选择算法(ID3算法)及python实现