随机森林在大数据运用中非常的常见,它在预测和回归上相比于SVM,多元线性回归,逻辑回归,多项式回归这些,有着比较好的鲁棒性。
随机森林是一个用随机方式建立的,包含多个决策树的分类器。其输出的类别是由各个树输出的类别的众数而定。
优点:
- 处理高纬度的数据,并且不用做特征选择,当然也可以使用随机森林做特征筛选。
- 模型泛化能力强
- 对不平衡数据集来说,可以平衡误差。
- 对缺失值,异常值不敏感。
缺点:
- 当数据噪声比较大时,会产生过拟合现象。
- 对不同取值的属性的数据,取值划分较多的属性会对随机森林产生更大的影响。
废话不多说,直接上干货
随机森林的代码的基本实现
分类模型
from sklearn.ensemble import RandomForestClassifier
#模型训练
forest = RandomForestClassifier()
forest.fit(x_train.values, y_train.values)#训练集和训练集标签#模型评估
score = forest.score(x_test, y_test)print(score)#这里的score代表的acc,精确率#模型预测
pre = forest.predict(x_test)print(pre)#模型预测--输出概率值
pre_p = forest.predict_proba(x_test)print(pre_p)#计算模型运行的时间import time
start = time.time()
end = time.time()
end-start
同时对于分类问题,我们常常需要用到的指标如混淆矩阵,准确率,精准率,召回率,F1指数等等。
下面为分类模型的评估指标计算方法
#分类模型的评估指标from sklearn import metrics
import seaborn as sns
import matplotlib.pyplot as plt
classClassEval():def__init__(self, pre,y_test):
self.pre = pre
self.y_test = y_test
self.C2 =None'''计算混淆矩阵'''defconfusion_matrix(self):
self.C2 = metrics.confusion_matrix(self.y_test,self.pre, labels=[0,1])return self.C2
'''绘制混淆矩阵热图'''defC2_heatmap(self):
self.confusion_matrix()#绘图
sns.set()
f, ax = plt.subplots(figsize=(8,7))
TX = sns.heatmap(self.C2, annot=True, ax=ax, cmap="Spectral_r", fmt=".20g")# 热力图#标题设置
ax.set_title("Confusion Matrix")
ax.set_xlabel("Predict")
ax.set_ylabel("Answer")print("混淆矩阵")'''计算准确率'''defget_acc(self):
self.confusion_matrix()print(type(self.C2))#计算
acc = np.trace(self.C2)/self.C2.sum()return acc
'''计算精准率'''defget_precision(self):
self.confusion_matrix()
Precision =[]
i =0for row in self.C2:
TP = row[i]
TP_FP =0for col in row:
TP_FP += col
Precision.append(TP/TP_FP)
i+=1return Precision;'''计算召回率'''defget_Recall(self):
self.confusion_matrix()
Recall =[]
i =0
TP_FN = np.sum(self.C2, axis=0)for row in self.C2:
TP = row[i]
Recall.append(TP/TP_FN[i])
i+=1return Recall
'''计算F1指数'''defget_F1(self):
self.confusion_matrix()
Precision = self.get_precision()
Recall = self.get_Recall()
F1 =[]for i inrange(len(Precision)):
F1.append(2*Precision[i]*Recall[i]/(Precision[i]+ Recall[i]))return F1
'''计算kappa系数'''defget_kappa(self):
self.confusion_matrix()
kappa = metrics.cohen_kappa_score(np.array(self.predict_label_list).astype(np.int16),np.array(self.answer_label_list).astype(np.int16))return kappa
RF_data = ClassEval(pre, y_test.values)# RF_data.C2_heatmap()print("精确度",RF_data.get_acc())print("精准率",RF_data.get_precision())print("召回率",RF_data.get_Recall())print("F1值",RF_data.get_F1())
回归模型
from sklearn.ensemble import RandomForestRegressor
#训练模型
forest = RandomForestRegressor()
forest.fit(x_train.values, y_train.values)#训练集和训练集标签#模型评估
score = forest.score(x_test, y_test)print(score)#这里的score代表的R2分数#模型预测
pre = forest.predict(x_test)print(pre)#计算模型运行的时间import time
start = time.time()
end = time.time()
end-start
回归模型的评价指标结果如下
MSE:均方误差,观测值与真值偏差的平方和,反应预测结果的精确度。
RMSE:MSE的算术平方根,用来衡量观测值和真值之间的偏差。(开根号之后,误差的结果就与真值在同一个级别)
MAE:平均绝对误差,能更好地反映预测值误差的实际情况
R2:介于0-1之间,越接近1,回归拟合效果越好
MSE计算简便,但MAE对异常点有更好的鲁棒性。
MSE与MAE各自的优缺点
- MSE对误差取了平方(令e=真实值-预测值),因此若e>1,则MSE会进一步增大误差。如果数据中存在异常点,那么e值就会很大,而e则会远大于|e|。因此,相对于使用MAE计算损失,使用MSE的模型会赋予异常点更大的权重。在第二个例子中,用RMSE计算损失的模型会以牺牲了其他样本的误差为代价,朝着减小异常点误差的方向更新。然而这就会降低模型的整体性能。如果训练数据被异常点所污染,那么MAE损失就更好用(比如,在训练数据中存在大量错误的反例和正例标记,但是在测试集中没有这个问题)。
- 直观上可以这样理解:如果我们最小化MSE来对所有的样本点只给出一个预测值,那么这个值一定是所有目标值的平均值。但如果是最小化MAE,那么这个值,则会是所有样本点目标值的中位数。众所周知,对异常值而言,中位数比均值更加鲁棒,因此MAE对于异常值也比MSE更稳定。
- MAE存在一个严重的问题(特别是对于神经网络):更新的梯度始终相同,也就是说,即使对于很小的损失值,梯度也很大。这样不利于模型的学习。为了解决这个缺陷,我们可以使用变化的学习率,在损失接近最小值时降低学习率。而MSE在这种情况下的表现就很好,即便使用固定的学习率也可以有效收敛。MSE损失的梯度随损失增大而增大,而损失趋于0时则会减小。这使得在训练结束时,使用MSE模型的结果会更精确。
MSE和MAE的选择
如果异常点代表在商业中很重要的异常情况,并且需要被检测出来,则应选用MSE损失函数。相反,如果只把异常值当作受损数据,则应选用MAE损失函数。总的来说,处理异常点时,MAE损失函数更稳定,但它的导数不连续,因此求解效率较低。MSE损失函数对异常点更敏感,但通过令其导数为0,可以得到更稳定的封闭解。
from sklearn.metrics import mean_squared_error #MSEfrom sklearn.metrics import mean_absolute_error #MAEfrom sklearn.metrics import r2_score#R2import numpy as np
R2 = r2_score(y_test,pre)#真实数据和预测数据
MSE = mean_squared_error(y_test,pre)
MAE = mean_absolute_error(y_test,pre)
RMSE = np.sqrt(MSE)
随机森林的随机搜索调优
可以通过
get_params()
函数来得到随机森林的各项参数
- n_esimators:要使用的树的数量
- max_feauters:每个节点拆分时要使用的特性数量
- max_depth:每棵树上的叶子数量
- min_samples_split:分裂内部节点所需的最小样本数
- min_samples_leaf:每个叶子中的最小样本数量
- bootstrap:取样方法,是否替换。
Scikit-learn提供RandomizedSearchCV类实现随机搜索。它需要两个参数来建立:一个估计器和超参数的可能值集,称为参数网格或空间。让我们为我们的随机森林模型定义这个参数网格:
from sklearn.model_selection import RandomizedSearchCV
#设置各类参数的范围
n_estimators = np.arange(100,2000, step=100)#从100,2000,步长为100
max_features =["auto","sqrt","log2"]#max_features的几种选择
max_depth =list(np.arange(10,100, step=10))+[None]#深度计算
min_samples_split = np.arange(2,10, step=2)#最小分割
min_samples_leaf =[1,2,4]#最小叶子
bootstrap =[True,False]
param_grid ={"n_estimators": n_estimators,"max_features": max_features,"max_depth": max_depth,"min_samples_split": min_samples_split,"min_samples_leaf": min_samples_leaf,"bootstrap": bootstrap,}#随机参数调优
forest = RandomForestRegressor()'''
n_iter参数,控制我们在搜索中允许的超参数组合的随机选择的迭代次数。
cv:同时也表示三折交叉验证
scoring:评分标准
n_jobs=-1:表示使用机器上的所有内核
'''
random_cv = RandomizedSearchCV(
forest, param_grid, n_iter=100, cv=3, scoring="r2", n_jobs=-1)
random_cv.fit(X, y)print("Best params:\n")print(random_cv.best_params_)
虽然你用了各种调优方法,但是你同样也需要表达。你需要将你的调优过程可视化
随机森林的网格搜索调优
相比于随机搜索,网格搜索则类似与穷举各种可能。
有13680个可能的超参数组合和3倍CV, GridSearchCV将必须适合随机森林41040次。使用RandomizedGridSearchCV,我们得到了相当好的分数,并且只需要100 * 3 = 300 次训练。
new_params ={"n_estimators":[650,700,750,800,850,900,950,1000],"max_features":['sqrt'],"max_depth":[10,15,20,25,30],"min_samples_split":[2,4,6],"min_samples_leaf":[1,2],"bootstrap":[False],}from sklearn.model_selection import GridSearchCV
forest = RandomForestRegressor()'''
这里我们不需要指定评分和CV,这里采用了默认设置
'''
grid_cv = GridSearchCV(forest, new_params, n_jobs=-1)
grid_cv.fit(X, y)print('Best params:\n')print(grid_cv.best_params_,'\n')
当您在实践中使用需要大量计算的模型时,最好得到随机搜索的结果,并在更小的范围内在网格搜索中验证它们。
随机森林的k折交叉验证
把数据平均分成k等份,每次实验拿一份做测试,其余用做训练。
因此你训练出来的模型也是k个,需要实验k次求平均值。
from sklearn.model_selection import KFold
import pandas as pd
import numpy as np
#数据分割
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2, random_state=0)#转成numpy格式
x_train = np.array(x_train)
y_train = np.array(y_train)#这里的k表示进行几折交叉验证
k =2
kfolder = KFold(n_splits=k, shuffle=True,random_state=0)
kfold = kfolder.split(x_train, y_train)for train_index, val_index in kfold:
k_x_train = x_train[train_index]#训练集
k_y_train = y_train[train_index]#测试集标签
k_x_vali = x_train[val_index]#验证集
k_y_vali = y_train[val_index]#验证集标签
forest = RandomForestRegressor()#回归采用平均值#forest = RandomForestClassifier() #分类采用投票法
forest.fit(k_x_train, k_y_train)#训练集和训练集标签
score = forest.score(x_test, y_test)print(score)#这里的score代表的acc,精确率
这里只是一个简单的实现,最后预测的结果的融合,需要你们自己灵活组合,可以采用平均值,也可以采用堆叠法等
随机森林特征筛选
主要就是可视化特征的重要程度,但是由于随机森林对不同取值的属性的数据,取值划分较多的属性会对随机森林产生更大的影响。
建议采用至少两种机器学习方法进行特征筛选,在通过相关性热图,预测指标去判断最后选择那种模型作为特征筛选模型
# 将训练好的模型提取其特征的重要程度
import_level = model.feature_importances_ #这个方法可以调取关于特征重要程度# 特征程度的显示
x_columns = data.columns[1:]
index = np.argsort(import_level)[::-1]for each inrange(x.shape[1]):print('The important level of '+ x_columns[each]+': '+str(import_level[index[each]]))
如果特征较多,建议绘制折线图,如果特征适量,那肯定是柱状图更加清晰
柱状图
#柱状图可视化
plt.figure(figsize=(10,6))
plt.title('title',fontsize =18)
plt.ylabel('import level',fontsize =15,rotation =90)
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus']=Falsefor i inrange(x_columns.shape[0]):
plt.bar(i,import_level[index[i]],color ='orange',align ='center')
plt.xticks(np.arange(x_columns.shape[0]),x_columns,rotation =90,fontsize =15)
版权归原作者 addict_jun 所有, 如有侵权,请联系我们删除。