python机器学习4:决策树与随机森林算法

1.决策树

1.决策树的基本原理:

决策树是一种在分类与回归中都有着非常广泛应用的算法,它的原理是通过一系列问题进行if/else的推导,最终实现决策。
决策树(Decision Tree,简称DT)是最经典的机器学习模型之一,它的预测结果容易理解,易于向业务部门解释,预测速度快,可以处理离散型数据和连续型数据。

2.决策树的构建:

#导入numpy
import numpy as np
#导入画图工具
import matplotlib.pyplot as plt
from matplotlib.colors import ListedColormap
#导入tree模型和和数据集加载工具
from sklearn import tree,datasets
#导入数据集拆分工具
from sklearn.model_selection import train_test_split
wine = datasets.load_wine()
#只选取数据集的前两个特征
X,y = wine.data[:,:2],wine.target
#将数据集拆分成训练集和测试集
X_train,X_test,y_train,y_test = train_test_split(X,y)
#设定决策树分类器最大深度为1
clf = tree.DecisionTreeClassifier(max_depth=1)
#拟合训练数据集
clf.fit(X_train,y_train)
#定义图像中分区的颜色和散点的颜色
cmap_light = ListedColormap(['#FFAAAA','#AAFFAA','#AAAAFF'])
cmap_bold = ListedColormap(['#FF0000','#00FF00','#0000FF'])
#分别用样本的两个特征值创建图像的横轴和纵轴
x_min,x_max = X_train[:,0].min()-1,X_train[:,0].max()+1
y_min,y_max = X_train[:,1].min()-1,X_train[:,1].max()+1
xx,yy = np.meshgrid(np.arange(x_min,x_max,.02),np.arange(y_min,y_max,.02))
Z =clf.predict(np.c_[xx.ravel(),yy.ravel()])
Z = Z.reshape(xx.shape)
plt.figure()
plt.pcolormesh(xx,yy,Z,cmap=cmap_light)
#用散点把样本表示出来
plt.scatter(X[:,0],X[:,1],c=y,cmap=cmap_bold,edgecolor='k',s=20)
plt.xlim(xx.min(),xx.max())
plt.ylim(yy.min(),yy.max())
plt.title("Classifier:(max_depth=1)")
plt.show()

运行代码,得到如图所示的结果:


图片.png

结果分析:很显然,最大深度为1时分类器的表现肯定不会太好,分类器只分了两类,我们需要加大深度试试看结果会有什么变化。

#设定决策树深度为3
clf2 = tree.DecisionTreeClassifier(max_depth=3)
#重新拟合数据
clf2.fit(X_train,y_train)
#这次我们让max_depth=3,进行绘图
#定义图像中分区的颜色和散点的颜色
cmap_light=ListedColormap(['#FFAAAA','#AAFFAA','#AAAAFF'])
cmap_bold = ListedColormap(['#FF0000','#00FF00','#0000FF'])
cmap_light = ListedColormap(['#FFAAAA', '#AAFFAA', '#AAAAFF'])
cmap_bold = ListedColormap(['#FF0000', '#00FF00', '#0000FF'])
#分别用样本的两个特征值创建图像的横轴和纵轴
x_min,x_max = X_train[:,0].min()-1,X_train[:,0].max()+1
y_min,y_max = X_train[:,1].min()-1,X_train[:,1].max()+1
xx,yy = np.meshgrid(np.arange(x_min,x_max,.01),np.arange(y_min,y_max,.01))
Z=clf2.predict(np.c_[xx.ravel(),yy.ravel()])
Z = Z.reshape(xx.shape)
plt.figure()
plt.pcolormesh(xx,yy,Z,cmap=cmap_light)
#用散点把样本表示出来
plt.scatter(X[:,0],X[:,1],c=y,cmap=cmap_bold,edgecolor='k',s=20)
plt.xlim(xx.min(),xx.max())
plt.ylim(yy.min(),yy.max())
plt.title("Classifier:(max_depth=3)")
plt.show()

运行代码,得到如图所示的结果:


图片.png

结果分析:大部分数据点都进入了正确的分类,接下来进一步调整max_depth的值,看会有什么变化?

#设定决策树深度为5
clf3 = tree.DecisionTreeClassifier(max_depth=5)
#重新拟合数据
clf3.fit(X_train,y_train)
#这次我们让max_depth=3,进行绘图
#定义图像中分区的颜色和散点的颜色
cmap_light=ListedColormap(['#FFAAAA','#AAFFAA','#AAAAFF'])
cmap_bold = ListedColormap(['#FF0000','#00FF00','#0000FF'])
#分别用样本的两个特征值创建图像的横轴和纵轴
x_min,x_max = X_train[:,0].min()-1,X_train[:,0].max()+1
y_min,y_max = X_train[:,1].min()-1,X_train[:,1].max()+1
xx,yy = np.meshgrid(np.arange(x_min,x_max,.02),np.arange(y_min,y_max,.02))
Z=clf3.predict(np.c_[xx.ravel(),yy.ravel()])
Z = Z.reshape(xx.shape)
plt.figure()
plt.pcolormesh(xx,yy,Z,cmap=cmap_light)
#用散点把样本表示出来
plt.scatter(X[:,0],X[:,1],c=y,cmap=cmap_bold,edgecolor='k',s=20)
plt.xlim(xx.min(),xx.max())
plt.ylim(yy.min(),yy.max())
plt.title("Classifier:(max_depth=5)")
plt.show()

运行代码,得到如图所示的结果:


图片.png

结果分析:分类器的表现进一步提升了。它在更加努力地把每一个数据点放入正确的分类当中。

3.决策树的工作过程:

图片.png

分析:为了控制图片不要太大,我们选择了用max_depth=3的分类器来绘制图形,可以方便观看。
先从决策树的根部开始看起,第一个条件是酒精含量小于或等于12.745,samples=133指在根节点上,有133个样本。Value=[41,53,39]是指有41个样本属于class_0,53个样本属于class_1,其余39个样本属于class_2.接下来我们跟着树枝一起前进,在酒精度小于或等于12.745这个条件为true的时候,决策树判断分类为class_1,如果是False,则判断为class_0,这样到下一层,判断为class_1的样本共有53个,而判断class_0的样本则有80个,而再下一层则对酒的苹果酸含量进行判断,进一步对样本进行分类。左边class_1的分支的判断条件是苹果酸含量小于或等于2.445,如果为True,则再判断酒精含量是否小于或等于12.49,如果为False则判断酒精含量是否低于12.12,一次类推,直到将样本全部放进3个分类当中。

4.决策树的优势与不足:

优势:
1.可以很容易地将模型进行可视化,看得明白。
2.由于决策树算法对每个样本特征进行单独处理,因此并不需要对数据进行转换,因此不需要对数据进行预处理。
不足:
1.即便我们在建模的时候可以使用类似max_depth或是max_leaf_nodes等参数来对决策树进行预剪枝处理,但它还是不可避免会出现过拟合的问题,也就让模型的泛化性能大打折扣了。为了避免过拟合问题,下面介绍随机森林算法。

2.随机森林基本原理

1.随机森林的概念:随机森林有的时候也被称为随机决策森林,是一种集合学习方法,既可以用于分类,也可以用于回归。而所谓集合学习算法,其实就是把多个机器学习算法综合在一起,制造出一个更大模型的意思。

2.随机森林的构建

from sklearn.model_selection import train_test_split
#导入随机森林
from sklearn.ensemble import RandomForestClassifier
#载入红酒数据集
from sklearn import datasets
wine = datasets.load_wine()
#选择数据集的前两个特征
X = wine.data[:,:2]
y = wine.target
#将数据集拆分为训练集和测试集
X_train,X_test,y_train,y_test = train_test_split(X,y)
#设定随机森林中有6棵树
forest = RandomForestClassifier(n_estimators=6,random_state=3)
#使用模型拟合数据
forest.fit(X_train,y_train)

运行结果如图所示:


图片.png

结果分析:随机森林向我们返回了包含自身全部参数的信息,让我们重点看一下其中几个必要重要的参数:

1.bootstrap参数:

代表的是bootstrap sample,也就是“有放回抽样”的意思,指每次从样本空间中可以重复抽取同一个样本(因为样本在第一次被抽取之后又被放回去了),形象一点来说,如原始样本是['西瓜',‘苹果’,‘香蕉’,‘桃子’],那么经过bootstrap sample重构的样本就可能是[‘西瓜’,‘西瓜’,‘香蕉’,‘桃子’],还可能是[‘苹果’,‘香蕉’,‘桃子’,‘桃子’].Bootstrap sample生成的数据集和原始数据集在数据量上是完全一样的,但由于进行了重复采样,因此其中有一些数据点会丢失。

2.max_features:

max_features参数的设置,还是有些讲究的,假如把max_features设置为样本全部的特征数n_features就意味着模型会在全部特征中进行筛选,这样在特征选择这一步,就没有随机性可言了。而如果把max_features的值设为1,就意味着模型在数据特征上完全没有选择的余地,只能去寻找这一个被随机选出来的特征向量的阈值了。所以说,max_features的取值越高,随机森林里的每一棵决策树就会“长得越像”,它们因为有更多的不同特征可以选择,也就会更容易拟合数据;反之,如果max_features取值越低,就会迫使每棵决策树的样子更加不同,而且因为特征太少,决策树们不得不制造更多节点来拟合数据。

3.n_estimators:

这个参数控制的是随机森林中决策树的数量。在随机森林构建完成之后,每棵决策树都会单独进行预测。如果是用来进行回归分析的话,随机森林会把所有决策树的值取平均数;如果进行分类,在森林内部会进行“投票”,每棵树预测出数据类别的概率,比如其中一棵树说“这瓶酒80%属于class_1”,另外一棵树说,“这瓶酒60%属于class_2”,随机森林会把这些概率取平均值,然后把样本放入概率最高的分类当中。

4.random_state:

因为随机森林生成的每棵决策树的方法是随机的(所以名字叫随机森林嘛),那么不同的random_state参数会导致模型完全不同,所以如果不希望建模的结果太过于不稳定,一定要固化random_state这个参数的数值。
用图像直观地看一下随机森林分类的表现:

import matplotlib.pyplot as plt
import numpy as np
from matplotlib.colors import ListedColormap
#定义图像中分区的颜色和散点的颜色
cmap_light = ListedColormap(['#FFAAAA', '#AAFFAA', '#AAAAFF'])
cmap_bold = ListedColormap(['#FF0000', '#00FF00', '#0000FF'])

#分别用样本的两个特征值创建图像和横轴和纵轴
x_min, x_max = X_train[:, 0].min() - 1, X_train[:, 0].max() + 1
y_min, y_max = X_train[:, 1].min() - 1, X_train[:, 1].max() + 1
xx, yy = np.meshgrid(np.arange(x_min, x_max, .02),
                     np.arange(y_min, y_max, .02))
Z = forest.predict(np.c_[xx.ravel(), yy.ravel()])

#给每个分类中的样本分配不同的颜色
Z = Z.reshape(xx.shape)
plt.figure()
plt.pcolormesh(xx, yy, Z, cmap=cmap_light)

#用散点把样本表示出来
plt.scatter(X[:, 0], X[:, 1], c=y, cmap=cmap_bold, edgecolor='k', s=20)
plt.xlim(xx.min(), xx.max())
plt.ylim(yy.min(), yy.max())
plt.title("Classifier:RandomForest")
plt.show()
图片.png

3.随机森林的优势与不足:

优势:
1.集成了决策树的所有优点,而且能弥补决策树的不足。但从便于展示决策过程的角度来说,决策树依旧表现强悍。
2.随机森林算法支持并行处理,对于超大规模数据集来说,随机森林会比较耗时(毕竟要建立很多决策树),不过我们可以用多进程并行处理的方式来解决这个问题。实现方式是调节随机森林的n_jobs参数,记得把n_jobs参数值设为和CPU内核数一致,比如你的CPU内核数是2,那么n_jobs参数设为3或者更大就没有意义了。当然如果你搞不清楚自己的CPU到底多少内核,可以设置n_jobs=-1,这样随机森林会使用CPU的全部内核,速度就会极大提升了。
缺点:
1.并行处理功能在处理超大数据集时能提供良好的性能表现,但也有不足,例如,对于超高纬度数据集、稀疏数据集来说,随机森林就有点捉襟见肘了,在这种情况下,线性模型要比随机森林的表现更好一些。
2.随机森林相对更消耗内存,速度也比线性模型要慢,所以如果程序希望更节省内存和时间,还是选择线性模型。

3.随机森林实例----要不要和相亲对象进一步发展

1.数据集的准备

网上有一个注明的数据集--成年人数据集,包括了数万条样本数据。其中,样本特征包括年龄、工作单位性质、统计权重、学历、受教育时长、婚姻状况、职业、家庭情况、种族、性别、资产所得、资产损失、每周工作时长、原籍、收入。
这个数据集下载地址:http://archive.ics.uci.edu/ml/machine-learning-databases/adult/
载入数据集:

import numpy as np
#导入pandas库
import pandas as pd
#用pandas打开csv文件
data = pd.read_csv('adult.csv',header=None,index_col=False,names=['年龄','单位性质'
                ,'权重','学历','受教育时长','婚姻状况','职业','家庭情况','种族','性别','资产所得','资产损失','周工作时长','原籍','收入'])
data_lite = data[['年龄','单位性质','学历','性别','周工作时长','职业','收入']]
#数据前五行
data_lite.head()

运行代码,如图所示:


图片.png

2.用get_dummies处理数据

#使用get_dummies将文本数据转化为数值
data_dummies = pd.get_dummies(data_lite)
#对比样本原始特征和虚拟变量特征
print('样本原始特征:\n',list(data_lite.columns),'\n')
print('虚拟变量特征:\n',list(data_dummies.columns))

运行代码,如图所示:


图片.png

结果分析:可以看到get_dummies很聪明,他把字符串类型的特征拆分开,把单位性质分为“单位性质_Federal-gov” “单位性质_Local-gov”等,如果样本人群的工作单位是联邦政府,那么“单位性质_Federal-gov”这个特征的值就是1,而其他的工作单位性质特征值就是0,这样把字符串巧妙地转换成了0和1这两个整型数据
查看前五行:
data_dummies.head()
结果:


图片.png

从图中可以看出,新的数据集已经扩充到了46列,原因就是get_dummies把元数据集的特征拆分了很多列,现在我们把各列分配给特征向量X和分类标签y
#定义数据集的特征值
features = data_dummies.loc[:,'年龄':'职业_ Transport-moving']
X=features.values
y = data_dummies['收入_ >50K'].values
print('特征形态:{} 标签形态:{}'.format(X.shape,y.shape))

在这段代码中,我们让特征为“年龄”这一列到“职业_Transportation-moving”这一列,而标签y是“收入>=50k”这一列,如果大于50K,则y=1,否则y=0.运行代码:
结果:特征形态:(32561, 44) 标签形态:(32561,)

3.用决策树建模

from sklearn import tree
from sklearn.model_selection import train_test_split
X_train,X_test, y_train,y_test= train_test_split(X,y,random_state=0)
go_dating_tree = tree.DecisionTreeClassifier(max_depth=5)
go_dating_tree.fit(X_train,y_train)
print('模型得分:{:.2f}'.format(go_dating_tree.score(X_test,y_test)))

运行代码后,结果:
模型得分:0.80
结果分析:
可以看到,基于训练数据集的模型在测试集中得到了0.8的评分,还是可以接受的。也就是这个模型的预测准确率在80%。

4.新数据测试

我们知道,MR.Z年龄37岁,在省机关工作,学历是硕士,性别男(当然了。。。),每周工作40小时,职业是文员,现在我们把MR.Z的数据进行输入,并用模型对他的收入进行预测:

Mr_Z =[[37, 40,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,1,
       0,0,0,0,0,0,0,0,0,0,0,0,0]]
dating_dec = go_dating_tree.predict(Mr_Z)
print(dating_dec)

运行结果:[0]
结果分析:是的,机器冰冷地告诉小Q这个残酷的事实,MR.Z并不符合她的要求。
注意:本节用到的adult数据集其实是从没过1994年人口普查数据库抽取而来,而且其中的收入指的是年收入,并非月收入。我们只是用这个数据集来演示决策树的用法,其对我们真实生活场景的参考意义不大。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,684评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,143评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,214评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,788评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,796评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,665评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,027评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,679评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,346评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,664评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,766评论 1 331
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,412评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,015评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,974评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,073评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,501评论 2 343