基于python的随机森林算法的实现
随机森林是一种基于决策树的算法
它通过从所有特征中随机抽取m组特征进行决策树判断,最终将m个判断结果综合起来得出最终的判断
具体原理自行学习,本文主要着重于python调用sklearn实现random_forest算法进行二分类
首先是对需要用到的函数库的调用
import numpy as np
from sklearn.preprocessing import MinMaxScaler
import pandas as pd
from sklearn.ensemble import RandomForestClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import cross_val_score, GridSearchCV
from sklearn.model_selection import train_test_split
from sklearn.metrics import roc_auc_score, auc, roc_curve
import matplotlib.pyplot as plt
然后读取文件和处理数据
rd = pd.read_csv('RadImmune_177.csv')
Radlmmune_177.csv是所有样本的集合
其中ESTIMATEScore是需要预测的label列
请预先在表格中将label的值设定为0和1,方便后续操作
查看样本中label分布是否均匀
print(rd.ESTIMATEScore.value_counts())
自动划分数据集为测试集和训练集
y = rd.ESTIMATEScore # 将rd中的label列读取至y
x = rd.drop(['ESTIMATEScore', 'ID', 'StromalScore', 'ImmuneScore'], axis=1) # 将rd中不需要的特征列丢掉
seed=0 # 设置一个随机数种子传递给下面的train_test_split函数,否则每次分割出来的训练集和测试集不一样
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.3, random_state=seed)
注意:随机森林做分类预测时对于样本的特征的值的大小不敏感
且由于随机取特征取预测,对缺失值也不敏感
可以不用进行特征缩放或均值归一化
scaler = MinMaxScaler() # 均值归一化
x_train = scaler.fit_transform(x_train)
x_test = scaler.fit_transform(x_test)
下面实例化随机森林分类模型并进行训练和测试
# random_state参数是随机取特征时的随机数,不填此参数每次训练取得的特征不一样会导致结果不同
rdc = RandomForestClassifier(random_state=0)
rdc = rdc.fit(x_train, y_train)
result = rdc.score(x_test, y_test)
绘图
各个特征的重要性排序及前10表格绘制
importances = rdc.feature_importances_
std = np.std([tree.feature_importances_ for tree in rdc.estimators_], axis=0)
indices = np.argsort(importances)[::-1] # 重要性索引排序
print("Feature ranking:")
for f in range(min(10, x_train.shape[1])):
print("%2d) %-*s %f" % (f + 1, 30, x_train.columns[indices[f]], importances[indices[f]]))# Plot the feature importances of the forest
plt.figure()
plt.title("Feature importances")
plt.bar(range(10), importances[indices[:10]], tick_label=indices[:10], color="r", align="center")
plt.show()
总体分布情况绘制
f, ax = plt.subplots(figsize=(7, 5))
ax.bar(range(len(rdc.feature_importances_)), rdc.feature_importances_)
ax.set_title("Feature Importances")
plt.show()
ROC分数可视化
predictions_validation = rdc.predict_proba(x_test)[:, 1]
fpr, tpr, _ = roc_curve(y_test, predictions_validation)
roc_auc = auc(fpr, tpr)
plt.title('ROC Validation')
plt.plot(fpr, tpr, 'b', label='AUC = %0.2f' % roc_auc)
plt.legend(loc='lower right')
plt.plot([0, 1], [0, 1], 'r--')
plt.xlim([0, 1])
plt.ylim([0, 1])
plt.ylabel('True Positive Rate')
plt.xlabel('False Positive Rate')
plt.show()
比较决策树和随机森林scores
clf = DecisionTreeClassifier(max_depth=None, min_samples_split=2, random_state=0)
scores = cross_val_score(clf, x_train, y_train)
print(scores.mean())
clf2 = RandomForestClassifier(n_estimators=10, max_depth=None, min_samples_split=2, random_state=0)
scores = cross_val_score(clf2, x_train, y_train)
print(scores.mean())
调整超参数(网格搜索)
最大叶子节点数
param_test1 = {'max_leaf_nodes': range(2, 10, 1)} # 从2-10进行搜索,可自行调整
gsearch1 = GridSearchCV(estimator=RandomForestClassifier(random_state=0,
class_weight='balanced'), # 使用的分类器参数
param_grid=param_test1,
scoring='roc_auc',
cv=5)
gsearch1.fit(x_train, y_train)
print(gsearch1.best_params_, gsearch1.best_score_)
网格搜索原理就是固定其他的参数,对于选定的参数的范围每一个都算一遍,找出分数最高的
后面可再进行其他参数的搜索,将前面每一次搜索得到的最好参数放入gsearch2,gsearch3等等分类器中
进行其他参数的搜索,最后的到效果最好的一组参数
分类器参数有哪些
Random Forest Classifier和Random Forest Regressor参数绝大部分相同
- n_estimators:
也就是弱学习器的最大迭代次数,或者说最大的决策树个数,默认是10。一般来说n_estimators太小,容易欠拟合,n_estimators太大,
又容易过拟合,一般选择一个适中的数值。
- bootstrap:
默认True,是否有放回的采样。
- oob_score:
默认识False,即是否采用袋外样本来评估模型的好坏。有放回采样中大约会有36.8%的数据没有被采样到,
我们常常称之为袋外数据(Out Of Bag, 简称OOB),这些数据没有参与到训练集模型的拟合,
因此可以用来检测模型的泛化能力。推荐设置为True,因为袋外分数反应了模型拟合后的泛化能力。
对单个模型的参数训练,我们知道可以用cross validation(cv)来进行,但是比较消耗时间,
而且对于随机森林这种情况没有太大的必要,所以就用袋外数据对决策树模型进行验证,
类似一个简单的交叉验证,性能消耗小,但是效果不错。
- criterion:
即CART树做划分时对特征的评价标准,分类模型和回归模型的损失函数是不一样的。
(1)分类RF对应的CART分类树默认是基尼系数gini,另一个可选择的标准是信息增益entropy,是用来选择节点的最优特征和切分点的两个准则。
(2)回归RF对应的CART回归树默认是均方差MSE,另一个可选择的标准是绝对值误差MAE。一般来说选择默认的标准就已经很好的。
- max_features:
随机森林划分时考虑的最大特征数。可以使用很多种类型的值,默认是"None",意味着划分时考虑所有的特征数;
如果是"log2"意味着划分时最多考虑log2N个特征;如果是"sqrt"或者"auto"意味着划分时最多考虑N−−√N个特征。
如果是整数,代表考虑的特征绝对数。如果是浮点数,代表考虑特征百分比,即考虑(百分比xN)取整后的特征数,其中N为样本总特征数。
一般来说,如果样本特征数不多,比如小于50,我们用默认的"None"就可以了,如果特征数非常多,
我们可以灵活使用刚才描述的其他取值来控制划分时考虑的最大特征数,以控制决策树的生成时间。
- max_depth:
决策树最大深度。默认为"None",即不限制子树的深度。这样建树时,会使每一个叶节点只有一个类别,或是达到min_samples_split。
一般来说,数据少或者特征少的时候可以不管这个值。如果模型样本量多,特征也多的情况下,推荐限制这个最大深度,具体的取值取决于数据的分布。
常用的可以取值10-100之间。
- min_samples_split:
内部节点再划分所需的最小样本数,默认2。这个值限制了子树继续划分的条件,如果某节点的样本数小于min_samples_split,则不会继续划分。
如果样本量不大,可以不设置这个值;如果样本量数量级非常大,则推荐增大这个值。
- min_samples_leaf:
叶子节点最少样本数。
这个值限制了叶子节点的最小样本数,如果某个叶子节点的样本数小于min_samples_leaf,则会和兄弟节点一起被剪枝。
默认是1,可以输入最少的样本数的整数,或者最少样本数占样本总数的百分比。
如果样本量不大,不需要管这个值。如果样本量数量级非常大,则推荐增大这个值。
- min_weight_fraction_leaf:
叶子节点最小的样本权重和。这个值限制了叶子节点所有样本权重和的最小值,
如果小于这个值,则会和兄弟节点一起被剪枝。默认是0,就是不考虑权重问题。
一般来说,如果我们有较多样本有缺失值,或者分类树样本的分布类别偏差很大,就会引入样本权重,这时我们就要注意这个值了。
- max_leaf_nodes:
最大叶子节点数。通过限制最大叶子节点数,可以防止过拟合。默认是"None”,即不限制最大的叶子节点数。
如果加了限制,算法会建立在最大叶子节点数内最优的决策树。如果特征不多,可以不考虑这个值,但是如果特征分成多的话,可以加以限制,
具体的值可以通过交叉验证得到。
- min_impurity_split:
节点划分最小不纯度。这个值限制了决策树的增长,如果某节点的不纯度(基于基尼系数,均方差)小于这个阈值,则该节点不再生成子节点,即为叶子节点。
一般不推荐改动默认值1e-7。
- splitter:
随机选择属性"random"还是选择不纯度最大"best"的属性,建议用默认best。
- presort: 是否对数据进行预分类,以加快拟合中最佳分裂点的发现。默认False,适用于大数据集。
小数据集使用True,可以加快训练。是否预排序,预排序可以加速查找最佳分裂点,对于稀疏数据不管用,Bool,auto:非稀疏数据则预排序,若稀疏数据则不预排序。
一些总结:
- 特征不能太多,否侧效果很差
- 数据集的划分和分类器的随机数都要确定,否则每次结果都不相同