机器学习笔记——随机森林分类的sklearn实现

466 阅读6分钟

本文进行随机森林的学习,随机森林是一种基分类器为决策树的bagging算法,可以用于提升分类效果。 本文使用的数据仍然是乳腺癌分类数据集。

参数

森林参数

n_estimators:int, default=100,森林中决策树的数量。理论上越多树越好。

bootstrap:bool, default=True,在建树的时候是否使用boostrap选择特征和样本,如果为False,则默认每次使用整个数据集。

oob_score:bool, default=False,是否使用袋外样本计算分数来体现泛化能力,仅仅在boostrap=True的时候有用。

n_jobs,int, default=None,并行的线程数量,-1表示使用所有线程。

warm_start,bool, default=False,如果是True,则使用上一次的随机森林运算结果,并在上一次基础上增加树的数量。

max_samples:int or float, default=None,如果使用boostrap=True,在训练每个基分类器的时候使用的样本X的数量。

如果是None,那么抽取和所有的训练样本数量相同的样本
如果是int,则抽取的样本数量就是输入的数字。
如果是浮点数,则抽取的样本比例是输入的浮点数。

树参数

参见本专栏决策树的那一篇文章

机器学习笔记——分类决策树的Sklearn实现 - 掘金 (juejin.cn)

随机森林实现与参数学习

基础实现

from sklearn.model_selection import cross_val_score
from sklearn.ensemble import RandomForestClassifier as rfc
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasets
cancer=datasets.load_breast_cancer()
clf0=rfc(bootstrap=True,n_estimators=10,random_state=1).fit(cancer['data'],cancer['target'])
clf0.estimators_
[DecisionTreeClassifier(max_features='auto', random_state=1791095845), DecisionTreeClassifier(max_features='auto', random_state=2135392491), DecisionTreeClassifier(max_features='auto', random_state=946286476), DecisionTreeClassifier(max_features='auto', random_state=1857819720), DecisionTreeClassifier(max_features='auto', random_state=491263), DecisionTreeClassifier(max_features='auto', random_state=550290313), DecisionTreeClassifier(max_features='auto', random_state=1298508491), DecisionTreeClassifier(max_features='auto', random_state=2143362693), DecisionTreeClassifier(max_features='auto', random_state=630311759), DecisionTreeClassifier(max_features='auto', random_state=1013994432)]

森林参数学习

n_estimators分类区数量

我们使用其余参数默认,只改变n_estimators,看随机森林的性能变化。使用袋外分数显示模型的泛化能力

大概有一个上升后趋于平稳的趋势。

ln=[]
for i in range(25,300,5):
    l1=0
    for j in range(10):
        clf1=rfc(n_estimators=i,n_jobs=-1,oob_score=True).fit(cancer['data'],cancer['target'])
        l1+=clf1.oob_score_
    ln.append(l1/10)
plt.figure(figsize=(16,6))
plt.plot([i for i in range(25,300,5)],ln,mfc='red',marker='o')
plt.grid()
plt.show()

output_15_0.png

关于参数boostrap的设置与否

当使用bootstrap=False的时候,默认使用全部数据进行树的构建,使用bootstrap=True的时候,每次建立决策树都使用bootstrap抽取样本,我们可以比较这两个参数方式对于n_estimators的敏感性。因为bootstrap=False时无法计算袋外分数,因此这里使用10次三折交叉验证的分数均值体现两个分类器性能。

当其他参数相同,bootstrap=False的曲线在bootstrap=True的上方,其他的规律可能需要进一步发掘,至于原因,私以为是对于非bootstrap的情况下,样本信息损失较少。

lF=[]
lT=[]
for i in range(10,300,10):
    l1=0
    l2=0
    for j in range(10):
        clf2=rfc(n_estimators=i,bootstrap=False,n_jobs=-1)
        l1+=cross_val_score(clf2, cancer['data'], cancer['target'],cv=3).mean()
        clf3=rfc(n_estimators=i,bootstrap=True,n_jobs=-1)
        l2+=cross_val_score(clf3, cancer['data'], cancer['target'],cv=3).mean()        
    lF.append(l1/10)  
    lT.append(l2/10)
plt.figure(figsize=(16,6))
plt.plot([i for i in range(10,300,10)],lF,mfc='red',marker='o',label='False')
plt.plot([i for i in range(10,300,10)],lT,mfc='green',marker='o',label='True')
plt.legend()
plt.grid()
plt.show()

output_20_0.png

max_samples和oob_score

oob_score指的是袋外分数,当使用bootstrap=True的时候,每次使用放回抽样抽取建树样本,没被抽中的那部分数据就是袋外数据。 可以用于体现分类器性能。

lmax1=[]
lmax2=[]
lmax3=[]
lmax5=[]
lmax7=[]
lmax9=[]
lmax=[]
for i in range(20,150,10):
    lm1=0
    lm2=0
    lm3=0
    lm5=0
    lm7=0
    lm9=0
    lmm=0
    for j in range(10):
        clf4_1=rfc(n_estimators=i,bootstrap=True,n_jobs=-1,oob_score=True,max_samples=0.1).fit(cancer['data'],cancer['target'])
        lm1+=clf4_1.oob_score_
        clf4_2=rfc(n_estimators=i,bootstrap=True,n_jobs=-1,oob_score=True,max_samples=0.2).fit(cancer['data'],cancer['target'])
        lm2+=clf4_2.oob_score_        
        clf4_3=rfc(n_estimators=i,bootstrap=True,n_jobs=-1,oob_score=True,max_samples=0.3).fit(cancer['data'],cancer['target'])
        lm3+=clf4_3.oob_score_        
        clf4_5=rfc(n_estimators=i,bootstrap=True,n_jobs=-1,oob_score=True,max_samples=0.5).fit(cancer['data'],cancer['target'])
        lm5+=clf4_5.oob_score_        
        clf4_7=rfc(n_estimators=i,bootstrap=True,n_jobs=-1,oob_score=True,max_samples=0.7).fit(cancer['data'],cancer['target'])
        lm7+=clf4_7.oob_score_             
        clf4_9=rfc(n_estimators=i,bootstrap=True,n_jobs=-1,oob_score=True,max_samples=0.9).fit(cancer['data'],cancer['target'])
        lm9+=clf4_9.oob_score_        
        clf4_0=rfc(n_estimators=i,bootstrap=True,n_jobs=-1,oob_score=True).fit(cancer['data'],cancer['target'])
        lmm+=clf4_0.oob_score_
    lmax1.append(lm1/10)
    lmax2.append(lm2/10)
    lmax3.append(lm3/10)
    lmax5.append(lm5/10)
    lmax7.append(lm7/10)
    lmax9.append(lm9/10)
    lmax.append(lmm/10)
plt.figure(figsize=(16,6))
plt.plot([i for i in range(20,150,10)],lmax1,mfc='red',marker='o',label='0.1')
plt.plot([i for i in range(20,150,10)],lmax2,mfc='green',marker='8',label='0.2')
plt.plot([i for i in range(20,150,10)],lmax3,mfc='blue',marker='o',label='0.3')
plt.plot([i for i in range(20,150,10)],lmax5,mfc='purple',marker='8',label='0.5')
plt.plot([i for i in range(20,150,10)],lmax7,mfc='pink',marker='o',label='0.7')
plt.plot([i for i in range(20,150,10)],lmax9,mfc='lightgreen',marker='8',label='0.9')
plt.plot([i for i in range(20,150,10)],lmax,mfc='darkred',marker='o',label='1')
plt.legend()
plt.grid()
plt.show()

output_24_0.png 从上图可以看出,当max_samples较少的时候,可以看出,性能较差。但是高到一定程度的时候,分类器性能相差较少。

warm_start

主要用于节省时间,可以用于增加树的数量不能用于减少树的数量。

可以看出,在进行热启动之后,再次构建多于原分类器的树的随机森林时间减少了。但是对于冷启动而言,再次构建随机森林相当于重新构建,时间是重新构建随机森林的时间。

from time import time

热启动:

b1=time()
clf5=rfc(n_estimators=200,warm_start=True).fit(cancer['data'],cancer['target'])
e1=time()
print(e1-b1)
0.30507612228393555
b1=time()
clf5.n_estimators=210
clf5.fit(cancer['data'],cancer['target'])
e1=time()
print(e1-b1)
0.01801896095275879

冷启动:

b1=time()
clf6=rfc(n_estimators=200,warm_start=False).fit(cancer['data'],cancer['target'])
e1=time()
print(e1-b1)
0.30408191680908203
b1=time()
clf6.n_estimators=210
clf6.fit(cancer['data'],cancer['target'])
e1=time()
print(e1-b1)
0.3250863552093506

森林参数和树参数

树参数详见决策树,阅读官网文件,我们知道,随机森林两个重要的参数是max_features和n_estimators,这里对这两个参数的联合效果进行测试。

ln0=[]
ln1=[]
ln2=[]
ln3=[]
for i in range(25,300,5):
    l0=0
    l1=0
    l2=0
    for j in range(10):
        clf7_0=rfc(n_estimators=i,n_jobs=-1,oob_score=True,max_features=None).fit(cancer['data'],cancer['target'])
        l0+=clf7_0.oob_score_        
        clf7_1=rfc(n_estimators=i,n_jobs=-1,oob_score=True,max_features='sqrt').fit(cancer['data'],cancer['target'])
        l1+=clf7_1.oob_score_
        clf7_2=rfc(n_estimators=i,n_jobs=-1,oob_score=True,max_features='log2').fit(cancer['data'],cancer['target'])
        l2+=clf7_2.oob_score_
    ln0.append(l0/10)
    ln1.append(l1/10)
    ln2.append(l2/10)
plt.figure(figsize=(16,6))
plt.plot([i for i in range(25,300,5)],ln0,mfc='red',marker='o',label='None')
plt.plot([i for i in range(25,300,5)],ln1,mfc='blue',marker='o',label='sqrt')
plt.plot([i for i in range(25,300,5)],ln2,mfc='green',marker='o',label='log2')

plt.legend()
plt.grid()
plt.show()

output_35_0.png

属性和方法

属性

base_estimator_ DecisionTreeClassifier

estimators_ 一列决策树的列表

oob_score_ 袋外分数

其余见机器学习笔记——分类决策树的Sklearn实现 - 掘金 (juejin.cn)

方法

见决策树文章机器学习笔记——分类决策树的Sklearn实现 - 掘金 (juejin.cn)