学习网址:https://blog.csdn.net/wjjc1017/article/details/135904420
随机森林(Random Forest)属于集成算法里的Bagging方法,其中Bagging属于多个分类器里的并行方法,Boosting(属于多个分类器里的串行方法)。
核心思想是根据多个分类器的结果,判定为票数多的类别,如果是回归,则是多个回归结果的均值。
Bagging方法主要步骤
给定一个训练集的n个样本,Bagging重复地从训练集中有放回地随机选择样本,并将同一个基本模型(决策树)拟合到样本中。集成中的树的数量和用于训练每个树的样本数量是模型的超参数,通常使用几百到几千棵树,具体取决于训练集的大小和性质。
从Bagging到随机森林
随机森林包含另一种类型的Bagging方案:在决策树的每个节点搜索最佳分割时,它们只考虑一个随机特征子集。这个过程进一步减少了森林中树之间的相关性,从而降低了模型的方差并提高了整体性能。通常,在具有m个特征的数据集中,每次分割只考虑m的平方根个特征。在实践中,这个超参数应该与模型的其他超参数(如树的数量和用于训练它们的样本大小)一起调整。
Scikit-Learn中的随机森林
Scikit-Learn提供了两个实现随机森林模型的类:
分类问题:RandomForestClassifier;回归问题:RandomForestRegressor
参数:
max_samples:从训练集中抽取用于训练每棵树的样本数量。选项是指定一个整数表示样本数量,一个浮点数表示要使用的训练样本的比例,None(默认值)表示使用所有训练样本。
分类示例:
from sklearn.model_selection import train_test_split
from sklearn.datasets import load_iris
iris=load_iris()
X=iris.data[:,:2]#只取前两个特征
y=iris.target#目标变量
X_train,X_test,y_train,y_test=train_test_split(X,y,random_state=42)
from sklearn.ensemble import RandomForestClassifier
clf=RandomForestClassifier(random_state=42,n_jobs=-1)
注:创造一个随机森林分类器对象,默认设置即使用完全生长的树
clf.fit(X_train,y_train)
print(f'Train set accuracy:{clf.score(X_train,y_train):.4f}')
注:打印训练集准确率
print(f'Test set accuracy:{clf.score(X_test,y_test):.4f}')
注:打印测试集准确率
注:第一个'f'不能去掉,否则会直接输出Test set accuracy:{clf.score(X_test,y_test):.4f}
注:':.4f'(冒号不能去,否则会报错)控制浮点数精度,例如:print('{:.4f}'.format(3.1415926))输出结果是3.1416
[out]
Train set accuracy:0.9554
Test set accuracy:0.7895
可以在一些随机森林的超参数上运行随机搜索,已找到更好的模型:
from sklearn.model_selection import RandomizedSearchCV
import numpy as np
params={'n_estimators':[10,50,100,200,500],
'max_depth':np.arange(3,11),
'max_samples':np.arange(0.5,1.0,0.1),
'max_features':['sqrt','log2','None']}
注:参数依次的含义是:决策树的数量、决策树的最大深度范围、每棵决策树的样本比例范围、每棵决策树的特征选择方式。
search=RandomizedSearchCV(RandomForestClassifier(random_state=42),params,n_iter=50,cv=3,n_jobs=-1)
注:n_iter就是具体随机搭配超参数组合的次数(这个次数因此肯定是越大涵盖的组合数越多,效果越好,但也越费时间),模型的训练次数就是n_iter与cv的乘积(因为交叉验证有几折,那么就需要运行几次,而一共有n_iter个参数匹配组合,因此总次数就是二者相乘)。np.arange()是numpy里的方法。
search.fit(X_train,y_train)
print(search.best_params_)
注:打印最佳参数
best_clf=search.best_estimator_
注:将最佳分类器赋值给best_clf变量
print(f'Train accuracy:{best_clf.score(X_train,y_train):.4f}')
print(f'Test accuracy:{best_clf.score(X_test,y_test):.4f}')
[out]
Train accuracy:0.8214
Test accuracy:0.8158
回归示例:
为加利福尼亚住房数据集构建一个随机森林回归器,在这个数据集中,目标是根据该区域(住宅区)的8个不同特征(如中位数收入或每户人口的平均房间数)来预测加利福尼亚某个区域(住宅区)的中位房价。
from sklearn.datasets import fetch_california_housing
data=fetch_california_housing()
注:若报错的话,解决方案参考:https://blog.csdn.net/weixin_40959890/article/details/136716621
X,y=data.data,data.target
feature_names=data.feature_names
注:将数据集中的特征名称赋值给feature_names变量
from sklearn.model_selection import train_test_split
X_train,X_test,y_train,y_test=train_test_split(X,y,test_size=0.2,random_state=0)
from sklearn.ensemble import RandomForestRegressor
reg=RandomForestRegressor(random_state=0)
reg.fit(X_train,y_train)
print(f'R2得分(训练集):{reg.score(X_train,y_train):.4f}')
print(f'R2得分(测试集):{reg.score(X_test,y_test):.4f}')
[out]
R2得分(训练集):0.9727
R2得分(测试集):0.7980
对随机森林的超参数进行随机搜索,看看是否可以得到一个更好的模型:
from sklearn.model_selection import RandomizedSearchCV
import numpy as np
params={'n_estimators':[10,50,100,200,500],
'min_samples_leaf':np.arange(1,6),
'max_samples':np.arange(0.5,1.0,0.1),
'max_features':['sqrt','log2',None]}
search=RandomizedSearchCV(RandomForestRegressor(random_state=0),params,n_iter=50,cv=3,n_jobs=-1)
search.fit(X_train,y_train)
print(search.best_params_)
[out]
{'n_estimators': 500, 'min_samples_leaf': 1, 'max_samples': 0.7999999999999999, 'max_features': 'log2'}
可使用网格搜索GridSearchCV找到最佳参数
注:from sklearn.svm import SVC
from sklearn.model_selection import GridSearchCV
注:param_grid={'C':[0.1,1,10,100],'gamma':[1,0.1,0.01,0.001]}
注:定义支持向量机算法的参数空间范围
注:svm=SVC()
注:定义SVM分类器作为estimator
注:使用网格搜索寻找最佳参数,SVM训练的标签列必须为整型数值,不能为float,上述的是支持向量机相关,主要用于分类情况,与本示例关联不大
regre=RandomForestRegressor()
params={'n_estimators':[10,50,100,200,500],
'min_samples_leaf':np.arange(1,6),
'max_samples':np.arange(0.5,1.0,0.1),
'max_features':['sqrt','log2',None]}
search=GridSearchCV(regre,params,cv=5)
search.fit(X_train,y_train)
注:这一步程序花费的时间巨多,有四个半小时之多。
best_reg=search.best_estimator_
print(f'R2 score(train):{best_reg.fit(X_train,y_train).score(X_train,y_train):.4f}')
print(f'R2 score(test):{best_reg.fit(X_train,y_train).score(X_test,y_test):.4f}')
[out]
R2 score(train):0.9701
R2 score(test):0.8197
特征重要性:
在解释机器学习模型时,一个重要的问题是数据集中最重要的特征是什么,以及它们如何对模型的预测做出贡献?
随机森林是少数可以用来排名数据集中特征重要性的模型之一,例如,可以使用这个排名来执行特征选择。
决策树中特征的预测能力可以基于两个属性来确定:
1、特征在树中的位置,位于树顶部的特征对更大比例的样本的最终预测做出贡献。因此,我们可以使用到达使用该特征的节点的样本比例作为其重要性的估计值;
2、使用该特征分裂节点所实现的不纯度减少量。对于每棵树,按照impurity(gini/entropy/information gain)给特征排序,然后整个森林取平均。最优条件的选择依据是不纯度,不纯度在分类中通常为Gini不纯度或信息增益/信息熵,对于回归问题来说是方差。基于不纯度对模型进行排序有几点需要注意:(1)基于不纯度降低的特征选择将会偏向于选择那些具有较多类别的变量(bias);(2)当存在相关特征时,一个特征被选择后,与其相关的其他特征的重要度则会变得很低,因为它们可以减少的不纯度已经被前面的特征移除了。
注:这两点意思看不大懂啊!!
在Scikit-Learn中,决策树提供了一个名为feature_importances_的属性,它是基于这两个因素的预测能力的归一化估计值。
在随机森林中,我么可以对所有树中的这些估计值进行平均,从而获得更可靠的特征重要性估计值。
例如,让我们绘制加利福尼亚住房数据集中特征的重要性,这是随机森林回归器发现的:
feature_importance=best_reg.feature_importances_
sorted_idx=np.argsort(feature_importance)
pos=np.arange(len(feature_importance))
import matplotlib.pyplot as plt
plt.barh(pos,feature_importance[sorted_idx])
plt.yticks(pos,np.array(feature_names)[sorted_idx])
注:用IDIE Shell 编辑器的话,图未显示。