数据分析入门系列教程-决策树实战

简介: 数据分析入门系列教程-决策树实战

在学习了上一节决策树的原理之后,你有没有想动手实践下的冲动呢,今天我们就来用决策树进行项目实战。

决策树的应用场景是非常广泛的,在各行各业都有应用,并且有非常良好的表现。金融行业的风险贷款评估,医疗行业的疾病诊断,电商行业的销售预测等等。

sklearn 中的决策树

首先我们先来了解下如何在 sklearn 中使用决策树模型。

在 sklearn 中,可以使用如下方式来构建决策树分类器

from sklearn.tree import DecisionTreeClassifier
clf = DecisionTreeClassifier(criterion='entropy')

其中的 criterion 参数,就是决策树算法,可以选择 entropy,就是基于信息熵;而 gini,就是基于基尼系数。

构建决策树的一些重要参数,整理如下:

参数名 作用
criterion 特征选择标准,可选参数,默认是 gini,可以设置为 entropy。ID3 算法使用的是 entropy,CART 算法使用的则是 gini。
splitter 特征划分点选择标准,可选参数,默认是 best,可以设置为 random。best 参数是根据算法选择最佳的切分特征,例如 gini、entropy。random 随机的在部分划分点中找局部最优的划分点。默认的"best"适合样本量不大的时候,而如果样本数据量非常大,此时决策树构建推荐"random"。
max_features 在划分数据集时考虑的最多的特征值数量,为 int 或 float 类型。一般情况如果特征不是很多,少于50时,使用默认值 None 即可。
max_depth 决策树最大深,可选参数,默认是 None。
min_samples_split 内部节点再划分所需最小样本数,可选参数,默认是2。当节点的样本数少于 min_samples_split 时,不再继续分裂。
min_samples_leaf 叶子节点最少样本数,可选参数,默认是1。如果某叶子节点数目小于这个阈值,就会和兄弟节点一起被裁剪掉。叶结点需要最少的样本数,也就是最后到叶子节点,需要多少个样本才能算一个叶子节点。
min_weight_fraction_leaf 叶子节点最小的样本权重和,可选参数,默认是0。这个值限制了叶子节点所有样本权重和的最小值,如果小于这个值,则会和兄弟节点一起被剪枝。
max_leaf_nodes 最大叶子节点数,默认是 None。可以通过设置最大叶子节点数,防止过拟合。特征不多时,不用考虑该参数。
class_weight 类别权重,可选参数,默认是 None,也可以字典、字典列表、balanced。指定样本各类别的的权重,主要是为了防止训练集某些类别的样本过多,导致训练的决策树过于偏向这些类别。如果使用 balanced,则算法会自己计算权重,样本量少的类别所对应的样本权重会高。
random_state 随机数种子,可选参数,默认是None。如果设置了随机数种子,那么相同随机数种子,不同时刻产生的随机数也是相同的。
min_impurity_split 信息增益的阈值,如果信息增益小于这个值,则决策树不再增长,该节点不再生成节点,即为叶子节点。
presort 数据是否预排序,可选参数,默认为 False。如果样本量少或者限制了一个深度很小的决策树,设置为 True 可以让划分点选择更加快,决策树建立的更加快。

泰坦尼克预测

在了解了 sklearn 中构建决策树的方式和相关参数后,我们就可以进行真正的决策树构建了,并解决实际问题。

首先我们先使用最为经典的泰坦尼克数据集来预测下乘客的生存情况,你应该还记得,我们在数据清洗章节已经讲解过该数据集是如何清洗的,现在我们继续使用清洗之后的数据,用决策树的方式预测结果。

数据清洗

具体的清洗思路,可以回顾下第4节

import numpy as np
import pandas as pddf = pd.read_csv('titanic_data.csv')
data = df.copy()
data['age'].fillna(df['age'].median(skipna=True), inplace=True)
data.drop(columns=['cabin'], inplace=True)
data['embarked'].fillna(df['embarked'].value_counts().idxmax(), inplace=True)
data.dropna(axis=0, how='any', inplace=True)
data.isnull().sum()  # 查看是否还有空值
data['alone']=np.where((data["sibsp"]+data["parch"])>0, 0, 1)
data.drop('sibsp', axis=1, inplace=True)
data.drop('parch', axis=1, inplace=True)
data =pd.get_dummies(data, columns=["embarked","sex"])
data.drop('name', axis=1, inplace=True)
data.drop('ticket', axis=1, inplace=True)

使用决策树做预测

导入需要的库

from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score

特征选择

feature = ["age","fare","alone","pclass","embarked_C","embarked_S", "embarked_Q","sex_male", "sex_female"]

创建特征(X)和类别标签(y)

X = data[feature]
y = data['survived']

划分训练集和测试集

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=2)

构建决策树模型并训练

clf = DecisionTreeClassifier(criterion='entropy')
clf.fit(X_train, y_train)
>>>
DecisionTreeClassifier(class_weight=None, criterion='entropy', max_depth=None,
            max_features=None, max_leaf_nodes=None,
            min_impurity_decrease=0.0, min_impurity_split=None,
            min_samples_leaf=1, min_samples_split=2,
            min_weight_fraction_leaf=0.0, presort=False, random_state=None,
            splitter='best')

此时打印出来的就是我们构建好的决策树及相关参数

决策树预测

pred_labels = clf.predict(X_test)

查看分类器准确率

print("Accuracy:",accuracy_score(y_test, pred_labels))
>>>
Accuracy: 0.7595419847328244

决策树可视化

为了做决策树的可视化,我们需要另外两个库,pydotplus 和 Grsphviz。

可以直接使用 pip 安装 pydotplus

pip install pydotplus

对于 Graphviz,需要下载对应的软件

https://www.graphviz.org/download/

你可以选择对应的操作系统版本,安装好之后,需要添加环境变量,之后就可以使用了。

此处以 windows 为例

下载并安装好软件

设置环境变量

按快捷键 win+r,在出现的运行对话框中输入sysdm.cpl,点击确定,出现如下对话框:

依次选择“高级”,“环境变量”,在系统变量中选择 Path 编辑

选择新建,并把 Graphviz 的安装路径填入

至此,已经可以正常只用 Graphviz 了。

代码实现

from sklearn.tree import export_graphviz
from sklearn.externals.six import StringIO
import pydotplusdot_data = StringIO()
export_graphviz(clf, out_file=dot_data,
filled=True, rounded=True,
special_characters=True,feature_names = feature,class_names=['0','1'])
graph = pydotplus.graph_from_dot_data(dot_data.getvalue())
graph.write_png('diabetes.png')

现在在当前目录下就成功生成了一个叫做 diabetes.png 的图片了,内容如下:

由于树比较大,更加高清的图片可以在这里下载

https://github.com/zhouwei713/DataAnalyse/tree/master/Decision_tree

我们简单看下根节点吧,这棵决策树在根节点选择的是 sex_male 这个特征来做分类的,小于0.5的数据有636个,分到了左边,即 class 为1,大于0.5的数据有410个,分到了右边,即 class 为0。后面的分类都是以此类推的

员工离职率预测

我们再来做一个员工离职率的预测分析实战,相关数据集可以在这里下载

https://github.com/zhouwei713/DataAnalyse/tree/master/Decision_tree

数据预处理

导入数据并查看是否存在缺失值

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import matplotlib as matplot
import seaborn as sns
df = pd.read_csv('HR.csv', index_col=None)
# 检测是否有缺失数据
df.isnull().any()
>>>
satisfaction_level       False
last_evaluation          False
number_project           False
average_montly_hours     False
time_spend_company       False
Work_accident            False
left                     False
promotion_last_5years    False
sales                    False
salary                   False
dtype: bool

数据很完整,没有缺失值

查看数据

df.head()


satisfaction_level:员工对公司满意度

last_evaluation:上一次公司对员工的评价

number_project:该员工同时负责多少项目

average_montly_hours:每个月工作的时长

time_spend_company:在公司工作多久

Work_accident:是否有个工作事故

left:是否离开公司(1表示离职)

promotion_last_5years:过去5年是否又被升职

sales:部门

salary:工资水平

数据分析

查看数据形状

print(df.shape)
>>>
(14999, 10)

共有14999条数据,每条数据10个特征。不过需要把 left 作为标签,实际为9个特征。

查看离职率

turnover_rate = df.left.value_counts() / len(df)
print(turnover_rate)
>>>
0    0.761917
1    0.238083
Name: left, dtype: float64

离职率为0.24

分组统计

turnover_Summary = df.groupby('left')
print(turnover_Summary.mean())


相关性分析

我们可以通过热力图,来了解下哪些特征的影响最大,哪些特征之间的相关性又是最强的。

corr = df.corr()
sns.heatmap(corr, 
            xticklabels=corr.columns.values,
            yticklabels=corr.columns.values)


两个特征的交叉处,颜色越浅,说明相关性越大。

数据集字符串转换成数字

将数据集中的字符串数据转换成数字类型数据

print(df.dtypes)
>>>
satisfaction_level       float64
last_evaluation          float64
number_project             int64
average_montly_hours       int64
time_spend_company         int64
Work_accident              int64
left                       int64
promotion_last_5years      int64
sales                     object
salary                    object
dtype: object

sales 和 salary 两个特征需要转换

这里要介绍一个 Pandas 超级强大的功能,accessor。该方法可以返回属性,让我们知道某个数据有哪些属性可以使用

import pandas as pd
pd.Series._accessors
>>>
{'cat', 'dt', 'sparse', 'str'}

可以看到,对于 series 类型数据,有如下四个属性可用。

cat:用于分类数据(Categorical data)

str:用于字符数据(String Object data)

dt:用于时间数据(datetime-like data)

sparse:用于系数矩阵

test = pd.Series(['str1', 'str2', 'str3'])
print(test.str.upper())
print(dir(test.str))
>>>
0    STR1
1    STR2
2    STR3
dtype: object
[...'_get_series_list', '_inferred_dtype', '_is_categorical', '_make_accessor', '_orig', '_parent', '_validate', '_wrap_result', 'capitalize', 'casefold', 'cat', 'center', 'contains', 'count', 'decode', 'encode', 'endswith', 'extract', 'extractall', 'find', 'findall', 'get', 'get_dummies', 'index'...]

现在我们要做的是把字符串转换成数字,所以可用使用 cat 这个属性,因为对于 sales 和 salary 两个特征,它们都是类别类型的数据,比如 sales 的 support,product_mng 和 salary 的 low,medium 等。

而 cat 属性的使用,是需要和数据类型 Category 相配合的,故我们需要先将上面两列的数据类型做下转换

df["sales"] = df["sales"].astype('category')
df["salary"] = df["salary"].astype('category')

然后再使用 cat.codes 来实现对整数的映射

df["sales"] = df["sales"].cat.codes
df["salary"] = df["salary"].cat.codes


模型训练

划分标签和特征

target_name = 'left'
X = df.drop('left', axis=1)
y = df[target_name]

划分训练集和测试集

X_train, X_test, y_train, y_test = train_test_split(X,y,test_size=0.15, random_state=123, stratify=y)

stratify 参数的作用是在训练集和测试集中,不同标签(离职非离职)所占比例相同,即原数据集中比例是多少,训练集和测试集中比例也为多少。

模型训练和预测

from sklearn.metrics import roc_auc_score
clf = DecisionTreeClassifier(
    criterion='entropy',
    min_weight_fraction_leaf=0.01
    )
clf = clf.fit(X_train,y_train)
clf_roc_auc = roc_auc_score(y_test, clf.predict(X_test))
print ("决策树 AUC = %2.2f" % clf_roc_auc)
>>>
 ---决策树---
决策树 AUC = 0.93

这里使用了 ROC 和 AUC 来检查分类器的准确率,我们来看看它们的含义。

ROC

ROC(Receiver Operating Characteristic)曲线,用来评价二值分类器的优劣。ROC 曲线下的面积,表示模型准确率,用 AUC 来表示。

ROC 曲线有个很好的特性:当测试集中的正负样本的分布变化的时候,ROC 曲线能够保持不变。在实际的数据集中经常会出现类不平衡(class imbalance)现象,即负样本比正样本多很多(或者相反),而且测试数据中的正负样本的分布也可能随着时间变化。

ROC 曲线

from sklearn.metrics import roc_curve
clf_fpr, clf_tpr, clf_thresholds = roc_curve(y_test, clf.predict_proba(X_test)[:,1])plt.figure()# 决策树 ROC
plt.plot(clf_fpr, clf_tpr, label='Decision Tree (area = %0.2f)' % clf_roc_auc)plt.xlim([0.0, 1.0])
plt.ylim([0.0, 1.05])
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('ROC Graph')
plt.legend(loc="lower right")
plt.show()


图中的曲线,越接近左上,说明模型准确率越高,也即是曲线下面的面积越大。

决策树应用

在构建好决策树之后,我们可以通过决策树来分析出不同特征的重要性,进而帮助做出决定。

在当前员工离职率分析的例子中,我们可以分析出哪几个特征是对员工离职起到觉得性作用的,那么公司就可以对想要留下的员工重点提高对应的特征。

importances = clf.feature_importances_
feat_names = df.drop(['left'],axis=1).columnsindices = np.argsort(importances)[::-1]
plt.figure(figsize=(12,6))
plt.title("Feature importances by Decision Tree")
plt.bar(range(len(indices)), importances[indices], color='lightblue',  align="center")
plt.step(range(len(indices)), np.cumsum(importances[indices]), where='mid', label='Cumulative')
plt.xticks(range(len(indices)), feat_names[indices], rotation='vertical',fontsize=14)
plt.xlim([-1, len(indices)])
plt.show()


这图中可以非常直观的看出,satisfaction_level 起到了最大的作用,大概占到了0.5左右,其次就是 time_spend_company 和 last_evaluation。

那么这些影响是正相关还是负相关呢,就可以结合上面的热力图来分析

比如对于 satisfaction_level,从热力图中可以看到他与 left 是负相关的,所以我们就可以得出结论:满意度越高,越不容易离职。实际上,在真实生活中也是这样的,对吧。

最后再来看下那条折线,它的意思是说,每一个拐折的地方,都是前面特征影响度之和,比如图中红框的地方,就是前两个特征加一起对于离职的影响度,大概占到了0.7左右。


而前五个特征,基本已经占到了1,所以其他特征的影响几乎可以忽略不计了。

文中的完整代码,可以在这里下载:

https://github.com/zhouwei713/DataAnalyse/tree/master/Decision_tree

总结

本节讲解了如何构建决策树,决策树的可视化,同时还分享了当特征值是非数值类型时,转换成数值类型的方法。

对于原始的数据集,我们要有足够的分析,找到不同特征之间的相关性。这些信息,无论是前期的特征选择还是后面训练好模型后的分析,都是很关键的。

同时我们还介绍了 ROC 曲线和 AUC 的概念,是二分类中应用广泛的准确率判定方法。

最后,我们还介绍了如何通过决策树来分析特征的重要性,从而解决工作生活中真实的问题。

练习题

对于 Titanic 的例子,你可以通过在创建决策树实例时,增加参数进行剪枝,使得决策树的准确率提高嘛?

相关文章
|
21天前
|
机器学习/深度学习 数据可视化 数据挖掘
使用Python进行数据分析的入门指南
本文将引导读者了解如何使用Python进行数据分析,从安装必要的库到执行基础的数据操作和可视化。通过本文的学习,你将能够开始自己的数据分析之旅,并掌握如何利用Python来揭示数据背后的故事。
|
1月前
|
机器学习/深度学习 数据可视化 数据挖掘
使用Python进行数据分析的入门指南
【10月更文挑战第42天】本文是一篇技术性文章,旨在为初学者提供一份关于如何使用Python进行数据分析的入门指南。我们将从安装必要的工具开始,然后逐步介绍如何导入数据、处理数据、进行数据可视化以及建立预测模型。本文的目标是帮助读者理解数据分析的基本步骤和方法,并通过实际的代码示例来加深理解。
49 3
|
1月前
|
消息中间件 数据挖掘 Kafka
Apache Kafka流处理实战:构建实时数据分析应用
【10月更文挑战第24天】在当今这个数据爆炸的时代,能够快速准确地处理实时数据变得尤为重要。无论是金融交易监控、网络行为分析还是物联网设备的数据收集,实时数据处理技术都是不可或缺的一部分。Apache Kafka作为一款高性能的消息队列系统,不仅支持传统的消息传递模式,还提供了强大的流处理能力,能够帮助开发者构建高效、可扩展的实时数据分析应用。
83 5
|
23天前
|
数据可视化 数据挖掘
R中单细胞RNA-seq数据分析教程 (3)
R中单细胞RNA-seq数据分析教程 (3)
29 3
R中单细胞RNA-seq数据分析教程 (3)
|
1月前
|
SQL 数据挖掘 Python
R中单细胞RNA-seq数据分析教程 (1)
R中单细胞RNA-seq数据分析教程 (1)
37 5
R中单细胞RNA-seq数据分析教程 (1)
|
29天前
|
机器学习/深度学习 数据挖掘
R中单细胞RNA-seq数据分析教程 (2)
R中单细胞RNA-seq数据分析教程 (2)
46 0
R中单细胞RNA-seq数据分析教程 (2)
|
1月前
|
数据采集 数据可视化 数据挖掘
深入浅出:使用Python进行数据分析的基础教程
【10月更文挑战第41天】本文旨在为初学者提供一个关于如何使用Python语言进行数据分析的入门指南。我们将通过实际案例,了解数据处理的基本步骤,包括数据的导入、清洗、处理、分析和可视化。文章将用浅显易懂的语言,带领读者一步步掌握数据分析师的基本功,并在文末附上完整的代码示例供参考和实践。
|
1月前
|
数据采集 数据可视化 数据挖掘
数据驱动决策:BI工具在数据分析和业务洞察中的应用
【10月更文挑战第28天】在信息爆炸的时代,数据成为企业决策的重要依据。本文综述了商业智能(BI)工具在数据分析和业务洞察中的应用,介绍了数据整合、清洗、可视化及报告生成等功能,并结合实际案例探讨了其价值。BI工具如Tableau、Power BI、QlikView等,通过高效的数据处理和分析,助力企业提升竞争力。
62 5
|
1月前
|
数据采集 数据可视化 数据挖掘
掌握Python数据分析,解锁数据驱动的决策能力
掌握Python数据分析,解锁数据驱动的决策能力
|
1月前
|
并行计算 数据挖掘 大数据
Python数据分析实战:利用Pandas处理大数据集
Python数据分析实战:利用Pandas处理大数据集
下一篇
DataWorks