机器学习一(决策树和随机森林)

 

前言

本文试图提纲挈领的对决策树和随机森林的原理及应用做以分析

决策树

算法伪代码

def 创建决策树:
    
    if (数据集中所有样本分类一致): #或者其他终止条件
        创建携带类标签的叶子节点
    else:
        寻找划分数据集的最好特征
        根据最好特征划分数据集
        for 每个划分的数据集:
            创建决策子树(递归)

注意算法要采用递归的方法

依据选取划分数据集特征的方法,有三种常用方法:

ID3:信息增益

 

C4.5:信息增益率

 

CART:基尼系数

对于连续特征:

比如m个样本的连续特征A有m个,从小到大排列为a1,a2,...,am,则CART算法取相邻两样本值的中位数,一共取得m-1个划分点,其中第i个划分点TiTi表示为:Ti=(ai+ai+1)/2。对于这m-1个点,分别计算以该点作为二元分类点时的基尼系数。选择基尼系数最小的点作为该连续特征的二元离散分类点,这样我们就做到了连续特征的离散化。要注意的是,与离散属性不同的是,如果当前节点为连续属性,则该属性后面还可以参与子节点的产生选择过程。

过拟合问题-——剪枝

 过多的枝叶会导致算法的过拟合,所以常使用减枝的方法防止过拟合:常用的剪枝方法有前置法和后置法,前置法指的是在要构建决策树时,依据终止条件确定是否提前终止;后置法指构建好决策树后,再依据条件确定是否用单一节点代替子树。

回归问题

一般采用均方误差作为评价特征的标准

随机森林

bootstrap方法:从样本集进行有放回的重采样。

随机森林步骤:

1.  样本的随机:从样本集中用Bootstrap随机选取n个样本

2.  特征的随机:从所有属性中随机选取K个属性,选择最佳分割属性作为节点建立CART决策树

3.  重复以上两步m次,即建立了m棵CART决策树

4.  这m个CART形成随机森林,通过投票表决结果,决定数据属于哪一类(投票机制有一票否决制、少数服从多数、加权多数)

参考:https://www.cnblogs.com/fionacai/p/5894142.html

sklearn.tree.DecisionTreeClassifier

class sklearn.tree.DecisionTreeClassifier(criterion=’gini’splitter=’best’max_depth=Nonemin_samples_split=2min_samples_leaf=1min_weight_fraction_leaf=0.0max_features=Nonerandom_state=Nonemax_leaf_nodes=Nonemin_impurity_decrease=0.0min_impurity_split=Noneclass_weight=Nonepresort=False)

 Parameters: criterion='gini' or 'entropy'

                    max_depth 设置树的最大深度 默认为‘None’

                    min_sample_split 分割的最小样本数 默认为2

                    详细内容的中文说明可以参考  https://www.cnblogs.com/pinard/p/6056319.html

 

sklearn.tree.DecisionTreeRegressor

 Parameters: criterion='mse'  还可以使用‘friedman_mse’或者'mae'

                     max_depth 设置树的最大深度 默认为‘None’

 

sklearn.ensemble.RandomForestClassifier

Parameters: n_estimator=10 生成决策树的个数

                   criterion='gini' or 'entropy'

 

应用举例

使用随机森林进行回归的例子

import numpy as np
import matplotlib.pyplot as plt
from sklearn.tree import DecisionTreeRegressor


N=100
x = np.random.rand(N) * 6 - 3 
x.sort()
y=0.1*x**3+np.exp(-x*x/2)+ np.random.randn(N) * 0.2  #3次函数+高斯函数+噪声
x = x.reshape(-1, 1)
x_bar=np.linspace(-3,3,50).reshape(-1,1)
y_bar=0.1*x_bar**3+np.exp(-x_bar*x_bar/2)
plt.plot(x,y,'r.')
plt.plot(x_bar,y_bar)
plt.show()

plt.plot(x,y,'r.')
x_test=np.linspace(-3,3,50).reshape(-1,1)
dt = DecisionTreeRegressor(criterion='mse')
depth=[3,6,18]
color='rgy'
for d,c in zip(depth,color):
    dt.set_params(max_depth=d)
    dt.fit(x, y)
    y_test = dt.predict(x_test)
    plt.plot(x_test,y_test,'-',color=c, linewidth=2, label='Depth=%d' % d)

plt.legend(loc='upper left')
plt.xlabel(u'X')
plt.ylabel(u'Y')
plt.grid(b=True)
plt.show()

   图1

 

 

  图2

对比图1中的真实曲线和图2中三条拟合折线可以发现,图二中的折现较好的拟合了原始曲线,如果单纯使用一次特征的线性回归肯定是达不到这样的效果的,其次,我们可以看到当树最大深度为3时,折线段较少,细小的弯曲无法体现,而当深度达到18时,折线波折又过多,有过拟合的嫌疑,当深度为6时,相对较好,因此,我们推断树的深度在拟合过程中起到了重要作用

 

数据集 Adult

字段名

含义

类型

age

年龄

Double

workclass

工作类型

string

fnlwgt

序号

string

education

教育程度*

string

education_num

受教育时间

double

maritial_status

婚姻状况*

string

occupation

职业*

string

relationship

关系*

string

race

种族*

string

sex

性别*

string

capital_gain

资本收益

string

capital_loss

资本损失

string

hours_per_week

每周工作小时数

double

native_country

国籍

string

income

收入

string

表1

基于上面特征,预测收入是否大于50K,我们用决策树和随机森林来解决上述问题。

import pandas as pd
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.preprocessing import LabelEncoder

column_names = 'age', 'workclass', 'fnlwgt', 'education', 'education-num', 'marital-status', 'occupation', \
                   'relationship', 'race', 'sex', 'capital-gain', 'capital-loss', 'hours-per-week',\
                   'native-country', 'income'  #不加括号为元组
data = pd.read_csv('adult.data', header=None, names=column_names)                  
data.isnull().any().any() #是否存在null
for name in column_names:
    data[name]=LabelEncoder().fit_transform(data[name])   #自动转换非数字列为数字
x = data[data.columns[:-1]]
y = data[data.columns[-1]]    
x_train, x_valid, y_train, y_valid = train_test_split(x, y, test_size=0.3, random_state=0)
DT = DecisionTreeClassifier(criterion='gini',max_depth=10,min_samples_split=5)
RF = RandomForestClassifier(criterion='gini', max_depth=10, min_samples_split=5,n_estimators=20)
LR= LogisticRegression()
models=[DT,RF,LR]
for model in models:
    model.fit(x_train,y_train)
    y_pre=model.predict(x_valid)
    print('验证集准确率:', accuracy_score(y_pre, y_valid))

运行结果为:

验证集准确率: 0.852287849319
验证集准确率: 0.858429726686
验证集准确率: 0.805507216706

对比结果,在随机森林与决策树选取相似的参数时,随机森林的结果略好于决策树,logistic回归结果最差,但注意这里logistic回归没有调参。

附:Adult数据集 https://pan.baidu.com/s/1vTMN9Yp6VPndezUR1UtYtw

 

致谢:本文基于小象学院邹博老师机器学习课程,部分代码参考该课程,特此感谢。

posted @ 2018-03-08 21:21  最爱我的肉肉  阅读(3181)  评论(0编辑  收藏  举报