0x0B 菩提决策树,姻缘算法求

作者: i败火 | 来源:发表于2016-01-06 19:35 被阅读930次

摘要:要找到有情人,通常是一个漫长的过程。在scikit-learn中,如何模拟人类的决策过程?决策树的目的是构建一颗最优的二叉分割树,因此从根节点往下,每一个结点的条件选择,都是为了让树结构最简洁。

0x0B.jpg 00 缘起

姻缘天注定,一段婚姻一段缘,是报恩报怨,还是讨债还债,在一开始,谁都不知道。但可以确定一点,今生定会在一起,无论是长相厮守,还是短暂快乐。

佛曰:和有情人,做快乐事,别问是劫还是缘。

要找到有情人,通常是一个漫长的过程,也许会经历很多场相亲活动。时间久了,对相亲也有更多的认识,并且积累和记录一些数据,如下表:

序号 身高 房子 车子 长相 工作 约否
1 1.80 6.5 fact
2 1.62 5.5 IT
3 1.71 8.5 bank
4 1.58 6.3 bank
5 1.68 5.1 IT 不约
6 1.63 5.3 bank 不约
7 1.78 4.5 IT 不约
8 1.64 7.8 fact 不约
9 1.65 6.6 bank 约吗?

前面8条数据为过往的相亲记录,最后字段为是否愿意继续约会的记录。如前4条数据,会愿意继续约会,后面四条,直接pass。将这八条记录作为训练集,第9条是一条新数据,作为预测,决断是否要继续约会呢?

对数据进行一些处理,将其中的离散变量(类别变量)进行替换,保存成csv格式如下表。1表示有,0表示无,目标值的-1表示没有意义,待预测。对于属性“工作”列,使用字典:{'IT': 0, 'bank': 1, 'fact':2}进行映射。

height,house,car,handsome,job,is_date
1.80,1,0,6.5,2,1
1.62,1,0,5.5,0,1
1.71,0,1,8.5,1,1
1.58,1,1,6.3,1,1
1.68,0,1,5.1,0,0
1.63,1,0,5.3,1,0
1.78,0,0,4.5,0,0
1.64,0,0,7.8,2,0
1.65,0,1,6.6,0,-1

01 scikit-learn模拟

知识星球.jpeg
程序员喜欢用代码说话,喜欢用代码模拟,那么在scikit-learn中,如何模拟人类的决策过程呢?
# sklearn_dt.py
import pandas as pd
from sklearn.tree import DecisionTreeClassifier,export_graphviz

df = pd.read_csv('sklearn_data.csv')
train,test = df.query("is_date != -1"), df.query("is_date == -1")
y_train, X_train = train['is_date'],train.drop(['is_date'], axis=1)
X_test = test.drop(['is_date'], axis=1)

model = DecisionTreeClassifier(criterion='gini')
model.fit(X_train, y_train)
print model.predict(X_test)

上面代码,使用pandas加载数据集,然后选择出训练集与测试集,倒数第三行构建了一个决策树模型,全部使用默认参数,最后对测试数据进行预测。

需要注意一个参数,criterion='gini',这是决策树构建的核心算法,参数“gini”指示了程序使用基尼不纯度来进行构建决策树。对于分类问题,scikit-learn还支持使用参数值为"entropy",表示使用熵的信息增益来构建决策树。对于回归问题,scikit-learn使用mse(均方误差)来构建。

多次运行上面的程序,程序会在某些时刻输出0,某些时间输出1。

02 信息增益,基尼不纯度

上面虽然只是用一行代码便构建了一个决策树,但实际上这一行代码后面,做了很多事情,也就是决策树构建的过程。

由前面的图片可以看出,决策树是一颗二叉树,左右两个分支,中间一个条件判断,条件满足走左分支,条件不满足,走右分支。一层层往下,因此可以用递归过程来构建。唯一的问题,在当前的结点,应该选择哪个条件来进行分割。

决策树的目的是构建一颗最优的二叉分割树,因此从根节点往下,每一个结点的条件选择,都是为了让树结构最简洁。换一句简单的说,就是尽量的找出能使当前数据集尽量分开的条件。

专业术语来说,是使得数据集的不纯度越来小,即纯度越来越大,使得数据尽可能的分开;不纯度也可以理解成数据集的混乱程度(熵),数据越混乱,不纯度越高,熵越大,也即不确定性越大。比如数据集里面,约会和不约会的概率都是0.5,那么表示不确定性很多,即不纯度很大,纯度很小。

我们的目的,就是找到一个条件进行分割,使得这种不确定性减小,如长相小于等于5.4的数据,一定不约,其不纯度为0,表示完全纯净了,都是不约,没有不确定性。

决策树常用的算法有ID3,C4.5,C5.0,CART,其中前面三种,都是用的熵的信息增益(率)来表示。最后一个CART(Classification And Regression Tree),即分类回归树,Scikit-learn实现的便是这种算法,从名字知道,既能用于分类,也用于回归问题,其中分类问题可以使用基尼(Gini)不纯度和熵的信息增益,回归问题使用了方差降低(Variance Reduction,同mse的均方误差)的算法。

维基上面有各种算法的数学公式,对分类问题,都是基于各个类别的概率的简单计算。在构建树的时候,算法会尝试在当前数据集的所有特征上进行切分,找到概率计算出来的最优切分,并将当前条件做为切分点。

以上面的数据为例,使用gini不纯度进行分割,最开始数据集的不纯度为0.5(根结点的impurity=0.5),在尝试了所有将数据切分一分为二(比如,切分按是否有房切分,长相大于7划分,长相小于5划分)的条件后,发现handsome<=5.4的划分,是最优的划分。

因此,决策树的构建过程,主要为两个步骤,一是数据二叉划分,不同的实现方法,有不同的数据划分,对离散变量,通常是按集合的方法,将数据集划分成两类,比如{'bank', 'IT', 'fact'}这个集合,通常会划分成{'bank'}, {'IT','fact'};{'IT'},{'bank','fact'};{'bank','IT'},{'fact'}这三个。而对于连续型数据,{3.8, 4.5, 7.8}这样的集体,则会按两个数的平均值进行划分。

数据分割完后,使用一种度量方法,来计算当前结点应该选择哪一个条件进行最优切分,选中的条件,即为当前的决策。

03 决策之树,决策过程

从上面的算法中,可以简单理解为,决策树就是找到当前最优的条件进行将数据一分为二,最优的条件即为当前的决策。

使用图表,来分析具体的决策过程,在scikit-learn程序中,添加如下代码:

export_graphviz(model.tree_,
                out_file='tree.dot',
                feature_names=df.columns,
                max_depth=None,
                # 下面几个参数,需要使用最新的scikit-learn 0.17版本才能用
                class_names=["is_date:no", "is_date:yes"],
                rounded=True,
                filled=True,
            )

对生成的决策树图片的说明:

  • 第一行为决策条件(非叶子结点),比如根节点handsome<=5.4,条件为真走左边,为假走右边。
  • impurity表示当前数据集的基尼不纯度
  • samples表示当前数据集的样本数
  • value表示当前数据集各个类别(按类别顺序从小到大排序,第0类,第1类……)的数量,如果value中的值相等,当前节点没有着色,为白色。
  • class表示当前数据集中的多数类别,如果value中各个值相等,则应该是按顺序取值。

运行上面的代码,会输出一个tree.dot的文件,再使用如下的命令,可以生成一个图片(开篇图片左边部分):

$ sudo apt-get install graphviz   # 需要安装程序
$ dot -Tpng tree.dot -o tree.png

分析图片的数据,总结出决策规则如下:

  • 长相小于等于5.4的,一定不约;
  • 不满足前面条件,但:有房子的,一定约;
  • 不满足前面条件,但:有车,约,没有车的,不约;


    知识星球.jpeg

    对待测数据,使用上面的规则:

  • 长相大于5.4,不满足规则1,继续下一条;
  • 没有房子,不满足规则2,继续下一条规则;
  • 有车,符合第3条规则,约。

04 spark模拟

上面的决策过程,换成简单的程序思维来表达,就是if-else的条件判断,使用spark的实现的决策树,可以打印出来if-else的条件决策过程:

# spark_dt.py
from pprint import pprint
from pyspark import SparkContext
from pyspark.mllib.tree import DecisionTree
from pyspark.mllib.regression import LabeledPoint

sc = SparkContext()
data = sc.textFile('spark_data.csv').map(lambda x: x.split(',')).map(lambda x: (float(x[0]), int(x[1]), int(x[2]), float(x[3]), int(x[4]), int(x[5])))
train = data.filter(lambda x: x[5]!=-1).map(lambda v: LabeledPoint(v[-1], v[:-1]))
test = data.filter(lambda x: x[5]==-1)#.map(lambda v: LabeledPoint(v[-1], v[:-1]))
model = DecisionTree.trainClassifier(train,
                                     numClasses=2,
                                     categoricalFeaturesInfo={1:2, 2:2, 4:3},
                                     impurity='gini',
                                     maxDepth=5,
                                 )

print 'The predict is:', model.predict(test).collect()
print 'The Decision tree is:', model.toDebugString()

通过上面的model.toDebugString(),打印出决策的过程,见开篇图片右边部分。

05 结尾

上面演示了两种不同的决策树实现,scikit-learn和spark,在演示数据上,输出可能会不同,因为各自的实现是有差别的。主要在于对离散变量(工作属性)的处理和数据的分割上面。

决策树还会涉及剪枝的问题,完全生成的决策树会伴随着数据的噪声导致过拟合,实际应用通常使用随机森林来防止过拟合。关于随机森林,请持续关注。

相关文章

  • 0x0B 菩提决策树,姻缘算法求

    摘要:要找到有情人,通常是一个漫长的过程。在scikit-learn中,如何模拟人类的决策过程?决策树的目的是构建...

  • 决策树算法总结

    目录 一、决策树算法思想 二、决策树学习本质 三、总结 一、决策树(decision tree)算法思想: 决策树...

  • 100天搞定机器学习|Day23-25 决策树及Python实现

    算法部分不再细讲,之前发过很多: 【算法系列】决策树 决策树(Decision Tree)ID3算法 决策树(De...

  • 决策树Decision Tree

    决策树是一种解决分类问题的算法 。 常用的 决策树算法有: ID3 算法 ID3 是最早提出的决策树算法,他...

  • Python学习——决策树中纯度算法的实现

    决策树 决策树算法是机器学习中的一个基础算法,该算法有着诸多的优点。在python中实现决策树,现阶段都已经集成中...

  • 决策树算法

    决策树 决策树也是经常使用的数据挖掘算法,其不用了解机器学习的知识,就能搞明白决策树是如何工作的。 决策树算法能够...

  • Machine Learning in Action:Decis

    概述 决策树这个算法比较接地气,就算你根本不懂机器学习算法也可以很好的理解决策树,决策树之前的算法就已经解释过了。...

  • 通俗地说决策树算法(一)基础概念介绍

    决策树算是比较常见的数据挖掘算法了,最近也想写点算法的东西,就先写个决策树吧。 一. 什么是决策树 决策树是什么,...

  • ID3和C4.5决策树算法总结及其ID3Python实现

    ID3和C4.5决策树算法总结及其ID3Python实现 1.决策树的算法流程 决策树的算法流程主要是:1.如果当...

  • 机器学习6-决策树

    一. 决策树概述 1.1 什么是决策树 决策树输入: 测试集决策树输出: 分类规则(决策树) 1.2 决策树算法概...

网友评论

    本文标题:0x0B 菩提决策树,姻缘算法求

    本文链接:https://www.haomeiwen.com/subject/tgwxkttx.html