本文进行随机森林的学习,随机森林是一种基分类器为决策树的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()
关于参数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()
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()
从上图可以看出,当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()
属性和方法
属性
base_estimator_ DecisionTreeClassifier
estimators_ 一列决策树的列表
oob_score_ 袋外分数
其余见机器学习笔记——分类决策树的Sklearn实现 - 掘金 (juejin.cn)