简单记录一下我的随机森林调参经历

用的特征是我脑机接口数据预处理后,特征融合后,降维(分组lda,去除相关性高的特征,随机森林选择重要的特征)后的数据,内容过于复杂,这里就不详细介绍了

由于我对调参不太了解,对调参对效果的影响没有概念,在这里浅浅记录一下



前3组:训练集1186个样本,测试集297个样本,特征45维

后2组:训练集947个样本,测试集240个样本,特征45维

随机种子random_state:34



刚开始,所有参数都用默认值,可以参考官网:

class sklearn.ensemble.RandomForestClassifier(n_estimators=100, ***, criterion=‘gini’, max_depth=None, min_samples_split=2, min_samples_leaf=1, min_weight_fraction_leaf=0.0, max_features=‘sqrt’, max_leaf_nodes=None, min_impurity_decrease=0.0, bootstrap=True, oob_score=False, n_jobs=None, random_state=None, verbose=0, warm_start=False, class_weight=None, ccp_alpha=0.0, max_samples=None)

得出的结果可以作为baseline:

第 1 个被试 accuracy 0.7912457912457912
第 2 个被试 accuracy 0.8243243243243243
第 3 个被试 accuracy 0.7811447811447811
第 4 个被试 accuracy 0.8416666666666667
第 5 个被试 accuracy 0.7291666666666666



每一次调参,都是只改一个参数,其他参数(除了随机种子)都是默认值

在调参的过程中,我也会分别选择参数,最后组合到一起,和baseline比较

改n_estimators

n_estimators是森林中树木的数量

默认的n_estimators是100

改成50:

第 1 个被试 baseline       0.7912457912457912
第 1 个被试 修改后的accuracy 0.797979797979798
第 2 个被试 baseline       0.8243243243243243
第 2 个被试 修改后的accuracy 0.8175675675675675
第 3 个被试 baseline       0.7811447811447811
第 3 个被试 修改后的accuracy 0.7811447811447811
第 4 个被试 baseline       0.8416666666666667
第 4 个被试 修改后的accuracy 0.8291666666666667
第 5 个被试 baseline       0.7291666666666666
第 5 个被试 修改后的accuracy 0.7333333333333333

改成150:

第 1 个被试 baseline       0.7912457912457912
第 1 个被试 修改后的accuracy 0.8114478114478114
第 2 个被试 baseline       0.8243243243243243
第 2 个被试 修改后的accuracy 0.8243243243243243
第 3 个被试 baseline       0.7811447811447811
第 3 个被试 修改后的accuracy 0.7878787878787878
第 4 个被试 baseline       0.8416666666666667
第 4 个被试 修改后的accuracy 0.8458333333333333
第 5 个被试 baseline       0.7291666666666666
第 5 个被试 修改后的accuracy 0.7458333333333333

改成200:

第 1 个被试 baseline       0.7912457912457912
第 1 个被试 修改后的accuracy 0.8114478114478114
第 2 个被试 baseline       0.8243243243243243
第 2 个被试 修改后的accuracy 0.8277027027027027
第 3 个被试 baseline       0.7811447811447811
第 3 个被试 修改后的accuracy 0.8047138047138047
第 4 个被试 baseline       0.8416666666666667
第 4 个被试 修改后的accuracy 0.8666666666666667
第 5 个被试 baseline       0.7291666666666666
第 5 个被试 修改后的accuracy 0.7583333333333333

改成250:

第 1 个被试 baseline       0.7912457912457912
第 1 个被试 修改后的accuracy 0.8215488215488216
第 2 个被试 baseline       0.8243243243243243
第 2 个被试 修改后的accuracy 0.8277027027027027
第 3 个被试 baseline       0.7811447811447811
第 3 个被试 修改后的accuracy 0.8114478114478114
第 4 个被试 baseline       0.8416666666666667
第 4 个被试 修改后的accuracy 0.85
第 5 个被试 baseline       0.7291666666666666
第 5 个被试 修改后的accuracy 0.7583333333333333

改成300:

第 1 个被试 baseline       0.7912457912457912
第 1 个被试 修改后的accuracy 0.8181818181818182
第 2 个被试 baseline       0.8243243243243243
第 2 个被试 修改后的accuracy 0.831081081081081
第 3 个被试 baseline       0.7811447811447811
第 3 个被试 修改后的accuracy 0.8013468013468014
第 4 个被试 baseline       0.8416666666666667
第 4 个被试 修改后的accuracy 0.8541666666666666
第 5 个被试 baseline       0.7291666666666666
第 5 个被试 修改后的accuracy 0.7541666666666667

改成350:

第 1 个被试 baseline       0.7912457912457912
第 1 个被试 修改后的accuracy 0.8148148148148148
第 2 个被试 baseline       0.8243243243243243
第 2 个被试 修改后的accuracy 0.8344594594594594
第 3 个被试 baseline       0.7811447811447811
第 3 个被试 修改后的accuracy 0.8080808080808081
第 4 个被试 baseline       0.8416666666666667
第 4 个被试 修改后的accuracy 0.8625
第 5 个被试 baseline       0.7291666666666666
第 5 个被试 修改后的accuracy 0.75

改成400:

第 1 个被试 baseline       0.7912457912457912
第 1 个被试 修改后的accuracy 0.8047138047138047
第 2 个被试 baseline       0.8243243243243243
第 2 个被试 修改后的accuracy 0.8344594594594594
第 3 个被试 baseline       0.7811447811447811
第 3 个被试 修改后的accuracy 0.7946127946127947
第 4 个被试 baseline       0.8416666666666667
第 4 个被试 修改后的accuracy 0.8583333333333333
第 5 个被试 baseline       0.7291666666666666
第 5 个被试 修改后的accuracy 0.75

感觉,不管改成啥样,都比默认值强

但是总体感觉还是差差不多的

选个250

改criterion

衡量分割质量的函数

默认的criterion是"gini"

这里改成别的试试

(改成log_loss会报错,就不改成那个了)

改成"entropy":

第 1 个被试 baseline       0.7912457912457912
第 1 个被试 修改后的accuracy 0.8080808080808081
第 2 个被试 baseline       0.8243243243243243
第 2 个被试 修改后的accuracy 0.8513513513513513
第 3 个被试 baseline       0.7811447811447811
第 3 个被试 修改后的accuracy 0.8114478114478114
第 4 个被试 baseline       0.8416666666666667
第 4 个被试 修改后的accuracy 0.8541666666666666
第 5 个被试 baseline       0.7291666666666666
第 5 个被试 修改后的accuracy 0.7666666666666667

提升还是比较明显的

那就改成entropy

改max_depth

树的最大深度。如果没有,则扩展节点,直到所有叶子都是纯的或直到所有叶子包含少于 min_samples_split 样本。

默认:max_depth=None

参考了

这里改成:3,5,8,15,25,30试一试

改成3:

第 1 个被试 baseline       0.7912457912457912
第 1 个被试 修改后的accuracy 0.7272727272727273
第 2 个被试 baseline       0.8243243243243243
第 2 个被试 修改后的accuracy 0.7804054054054054
第 3 个被试 baseline       0.7811447811447811
第 3 个被试 修改后的accuracy 0.7272727272727273
第 4 个被试 baseline       0.8416666666666667
第 4 个被试 修改后的accuracy 0.7958333333333333
第 5 个被试 baseline       0.7291666666666666
第 5 个被试 修改后的accuracy 0.7041666666666667

有明显的下降

改成5:

第 1 个被试 baseline       0.7912457912457912
第 1 个被试 修改后的accuracy 0.7845117845117845
第 2 个被试 baseline       0.8243243243243243
第 2 个被试 修改后的accuracy 0.8006756756756757
第 3 个被试 baseline       0.7811447811447811
第 3 个被试 修改后的accuracy 0.7676767676767676
第 4 个被试 baseline       0.8416666666666667
第 4 个被试 修改后的accuracy 0.8333333333333334
第 5 个被试 baseline       0.7291666666666666
第 5 个被试 修改后的accuracy 0.7125

有明显的下降

改成8:

第 1 个被试 baseline       0.7912457912457912
第 1 个被试 修改后的accuracy 0.7912457912457912
第 2 个被试 baseline       0.8243243243243243
第 2 个被试 修改后的accuracy 0.8074324324324325
第 3 个被试 baseline       0.7811447811447811
第 3 个被试 修改后的accuracy 0.7777777777777778
第 4 个被试 baseline       0.8416666666666667
第 4 个被试 修改后的accuracy 0.8458333333333333
第 5 个被试 baseline       0.7291666666666666
第 5 个被试 修改后的accuracy 0.7666666666666667

有的下降了,有的提升了

改成15:

第 1 个被试 baseline       0.7912457912457912
第 1 个被试 修改后的accuracy 0.7912457912457912
第 2 个被试 baseline       0.8243243243243243
第 2 个被试 修改后的accuracy 0.8209459459459459
第 3 个被试 baseline       0.7811447811447811
第 3 个被试 修改后的accuracy 0.7878787878787878
第 4 个被试 baseline       0.8416666666666667
第 4 个被试 修改后的accuracy 0.8416666666666667
第 5 个被试 baseline       0.7291666666666666
第 5 个被试 修改后的accuracy 0.725

总体没有明显变化

改成25:

第 1 个被试 baseline       0.7912457912457912
第 1 个被试 修改后的accuracy 0.7912457912457912
第 2 个被试 baseline       0.8243243243243243
第 2 个被试 修改后的accuracy 0.8243243243243243
第 3 个被试 baseline       0.7811447811447811
第 3 个被试 修改后的accuracy 0.7811447811447811
第 4 个被试 baseline       0.8416666666666667
第 4 个被试 修改后的accuracy 0.8416666666666667
第 5 个被试 baseline       0.7291666666666666
第 5 个被试 修改后的accuracy 0.7291666666666666

完全没变。

改成30:

第 1 个被试 baseline       0.7912457912457912
第 1 个被试 修改后的accuracy 0.7912457912457912
第 2 个被试 baseline       0.8243243243243243
第 2 个被试 修改后的accuracy 0.8243243243243243
第 3 个被试 baseline       0.7811447811447811
第 3 个被试 修改后的accuracy 0.7811447811447811
第 4 个被试 baseline       0.8416666666666667
第 4 个被试 修改后的accuracy 0.8416666666666667
第 5 个被试 baseline       0.7291666666666666
第 5 个被试 修改后的accuracy 0.7291666666666666

完全没变。(因为25就已经完全没变了)

所以,在这一部分,我选择None。

改min_samples_split

分裂一个内部节点所需的最小样本数

如果是 int,则将 min_samples_split 视为最小数字。

如果是float,则 min_samples_split 是分数, ceil(min_samples_split * n_samples) 是每次分割的最小样本数。

默认是2.

根据参考的博客,这里取3,5,10,15,100试试

改成3:

第 1 个被试 baseline       0.7912457912457912
第 1 个被试 修改后的accuracy 0.8181818181818182
第 2 个被试 baseline       0.8243243243243243
第 2 个被试 修改后的accuracy 0.8412162162162162
第 3 个被试 baseline       0.7811447811447811
第 3 个被试 修改后的accuracy 0.7946127946127947
第 4 个被试 baseline       0.8416666666666667
第 4 个被试 修改后的accuracy 0.8583333333333333
第 5 个被试 baseline       0.7291666666666666
第 5 个被试 修改后的accuracy 0.7458333333333333

提升了

改成5:

第 1 个被试 baseline       0.7912457912457912
第 1 个被试 修改后的accuracy 0.797979797979798
第 2 个被试 baseline       0.8243243243243243
第 2 个被试 修改后的accuracy 0.8243243243243243
第 3 个被试 baseline       0.7811447811447811
第 3 个被试 修改后的accuracy 0.7845117845117845
第 4 个被试 baseline       0.8416666666666667
第 4 个被试 修改后的accuracy 0.8375
第 5 个被试 baseline       0.7291666666666666
第 5 个被试 修改后的accuracy 0.7625

有的提升,有的降低,感觉差别不大

改成10:

第 1 个被试 baseline       0.7912457912457912
第 1 个被试 修改后的accuracy 0.8047138047138047
第 2 个被试 baseline       0.8243243243243243
第 2 个被试 修改后的accuracy 0.8108108108108109
第 3 个被试 baseline       0.7811447811447811
第 3 个被试 修改后的accuracy 0.7777777777777778
第 4 个被试 baseline       0.8416666666666667
第 4 个被试 修改后的accuracy 0.85
第 5 个被试 baseline       0.7291666666666666
第 5 个被试 修改后的accuracy 0.7625

有的提升了,有的降低了

改成15:

第 1 个被试 baseline       0.7912457912457912
第 1 个被试 修改后的accuracy 0.8013468013468014
第 2 个被试 baseline       0.8243243243243243
第 2 个被试 修改后的accuracy 0.8243243243243243
第 3 个被试 baseline       0.7811447811447811
第 3 个被试 修改后的accuracy 0.7946127946127947
第 4 个被试 baseline       0.8416666666666667
第 4 个被试 修改后的accuracy 0.8541666666666666
第 5 个被试 baseline       0.7291666666666666
第 5 个被试 修改后的accuracy 0.7458333333333333

有一点点提升

改成100:

第 1 个被试 baseline       0.7912457912457912
第 1 个被试 修改后的accuracy 0.7643097643097643
第 2 个被试 baseline       0.8243243243243243
第 2 个被试 修改后的accuracy 0.7837837837837838
第 3 个被试 baseline       0.7811447811447811
第 3 个被试 修改后的accuracy 0.7474747474747475
第 4 个被试 baseline       0.8416666666666667
第 4 个被试 修改后的accuracy 0.8
第 5 个被试 baseline       0.7291666666666666
第 5 个被试 修改后的accuracy 0.7291666666666666

有明显降低

所以,这一部分,我选择min_samples_split=3

改min_samples_leaf

叶节点所需的最小样本数。只有在左右分支中至少留下 min_samples_leaf 个训练样本时,才会考虑任何深度的分割点。

我觉得改得稍微大一点,有利于减少过拟合。

如果是 int,则将 min_samples_leaf 视为最小数字。

如果是浮点型,则 min_samples_leaf 是分数, ceil(min_samples_leaf * n_samples) 是每个节点的最小样本数。

这里改成:2,5,10

改成2:

第 1 个被试 baseline       0.7912457912457912
第 1 个被试 修改后的accuracy 0.797979797979798
第 2 个被试 baseline       0.8243243243243243
第 2 个被试 修改后的accuracy 0.8277027027027027
第 3 个被试 baseline       0.7811447811447811
第 3 个被试 修改后的accuracy 0.7878787878787878
第 4 个被试 baseline       0.8416666666666667
第 4 个被试 修改后的accuracy 0.8625
第 5 个被试 baseline       0.7291666666666666
第 5 个被试 修改后的accuracy 0.7625

有一点点提升

改成5:

第 1 个被试 baseline       0.7912457912457912
第 1 个被试 修改后的accuracy 0.7845117845117845
第 2 个被试 baseline       0.8243243243243243
第 2 个被试 修改后的accuracy 0.8243243243243243
第 3 个被试 baseline       0.7811447811447811
第 3 个被试 修改后的accuracy 0.7845117845117845
第 4 个被试 baseline       0.8416666666666667
第 4 个被试 修改后的accuracy 0.8625
第 5 个被试 baseline       0.7291666666666666
第 5 个被试 修改后的accuracy 0.7541666666666667

3个往上走,1个往下走

改成10:

第 1 个被试 baseline       0.7912457912457912
第 1 个被试 修改后的accuracy 0.7777777777777778
第 2 个被试 baseline       0.8243243243243243
第 2 个被试 修改后的accuracy 0.8074324324324325
第 3 个被试 baseline       0.7811447811447811
第 3 个被试 修改后的accuracy 0.7744107744107744
第 4 个被试 baseline       0.8416666666666667
第 4 个被试 修改后的accuracy 0.8166666666666667
第 5 个被试 baseline       0.7291666666666666
第 5 个被试 修改后的accuracy 0.7375

4个往下走,1个往上走

这种情况,我觉得是欠拟合了

所以,这一部分,选择min_samples_leaf=2

改max_features:

寻找最佳分割时要考虑的特征数量。

如果是 int,则考虑每次分割的 max_features 个特征。

如果是float,则 max_features 是一个分数,并且在每次分割时都会考虑 max(1, int(max_features * n_features_in_)) 特征。

如果是“sqrt”,则 max_features=sqrt(n_features)

如果是“log2”,则 max_features=log2(n_features)

如果是None,则 max_features=n_features

版本 1.1 中的更改: max_features 的默认值从 "auto" 更改为 "sqrt"

我这里的默认值是auto,我会试一试:sqrt,log2,None

改成"sqrt"

第 1 个被试 baseline       0.7912457912457912
第 1 个被试 修改后的accuracy 0.7912457912457912
第 2 个被试 baseline       0.8243243243243243
第 2 个被试 修改后的accuracy 0.8243243243243243
第 3 个被试 baseline       0.7811447811447811
第 3 个被试 修改后的accuracy 0.7811447811447811
第 4 个被试 baseline       0.8416666666666667
第 4 个被试 修改后的accuracy 0.8416666666666667
第 5 个被试 baseline       0.7291666666666666
第 5 个被试 修改后的accuracy 0.7291666666666666

完全一致。

改成"log2"

第 1 个被试 baseline       0.7912457912457912
第 1 个被试 修改后的accuracy 0.7878787878787878
第 2 个被试 baseline       0.8243243243243243
第 2 个被试 修改后的accuracy 0.8412162162162162
第 3 个被试 baseline       0.7811447811447811
第 3 个被试 修改后的accuracy 0.8215488215488216
第 4 个被试 baseline       0.8416666666666667
第 4 个被试 修改后的accuracy 0.8458333333333333
第 5 个被试 baseline       0.7291666666666666
第 5 个被试 修改后的accuracy 0.7458333333333333

1个往下走,4个往上走。

改成None

第 1 个被试 baseline       0.7912457912457912
第 1 个被试 修改后的accuracy 0.7609427609427609
第 2 个被试 baseline       0.8243243243243243
第 2 个被试 修改后的accuracy 0.8040540540540541
第 3 个被试 baseline       0.7811447811447811
第 3 个被试 修改后的accuracy 0.7878787878787878
第 4 个被试 baseline       0.8416666666666667
第 4 个被试 修改后的accuracy 0.8458333333333333
第 5 个被试 baseline       0.7291666666666666
第 5 个被试 修改后的accuracy 0.7458333333333333

2个往下走,3个往上走。

这个参数,我选择改成log2

综合改一改试试

根据上边的结果,改成:

clf_random_forest =
RandomForestClassifier(n_estimators=250,criterion="entropy",max_depth=None,min_samples_split=3,max_features="log2", random_state=34)

结果如下:

第 1 个被试 baseline       0.7912457912457912
第 1 个被试 修改后的accuracy 0.8181818181818182
第 2 个被试 baseline       0.8243243243243243
第 2 个被试 修改后的accuracy 0.8344594594594594
第 3 个被试 baseline       0.7811447811447811
第 3 个被试 修改后的accuracy 0.8181818181818182
第 4 个被试 baseline       0.8416666666666667
第 4 个被试 修改后的accuracy 0.8458333333333333
第 5 个被试 baseline       0.7291666666666666
第 5 个被试 修改后的accuracy 0.7541666666666667

可以看出,有时只调整一个参数,是比把这些参数组合在一起效果要好的

不过这么一改,至少是超过了baseline一点点

而且这里有一个bug,就是我实际是通过测试集来选择参数的,而不是通过验证集,所以也存在数据泄露的问题

所以,我还是把这些参数组合在一起吧,虽然可能acc比不上只改动一个参数

其实,划分一个验证集,用网格搜索的方式,也可以找出合适的参数,不过我还没有学到那一部分,目前只是想感受一下参数对结果的影响