个人感觉,相对于基于高斯过程的贝叶斯优化,基于随机森林的贝叶斯优化要好理解的多。
skopt里面实现了基于随机森林的贝叶斯优化,所以这里直接看看源码:
可以看到,其代理模型就是直接使用sklearn中的回归器;
基于随机森林的贝叶斯优化原理上要好理解的多,比如我们对xgboost进行调参,随机初始化了10组超参数,然后交叉验证得到了10个auc,我们直接使用随机森林对其进行拟合,比如我们令随机森林的trees为100颗树,然后我们训练完毕之后会得到100棵独立的tree,每一个tree都针对超参数和auc进行了拟合,那么所有tree的预测结构就构成了一个关于f(x)(也就是超参数组合w到评价指标y的映射关系)的经验近似高斯过程分布,这个分布的均值为所有tree的预测结果的均值,这个分布的方差为所有tree的叶子节点的impurity的方差。skopt中的实现是:
(impurity的概念下文补充)做了一些微小的约束,不过整体思路是一样的。
下面做个小测试看看具体是怎么计算的:
from sklearn.ensemble import RandomForestRegressor as rf
from sklearn.datasets import load_boston
X=load_boston().data
y=load_boston().target
clf=rf(n_estimators = 5)
clf.fit(X,y)
trees=clf.estimators_
trees
tree=trees[0]
var_tree = tree.tree_.impurity[tree.apply(X)]
var_tree
这里我们以第一棵树为例,tree.apply是
tree=trees[0]
var_tree = tree.tree_.impurity[tree.apply(X)]
var_tree
tree.apply返回样本X在tree上的叶子节点的索引值,
impurity直接返回对应的叶子节点上的评价准则——the value of criterion,因为这里用的是回归树,所以返回的是叶子节点上各个标签和其均值的差的平方的求和。不理解的可以自己做一个简单的计算:
这里我们就得到了506个样本对应的叶子节点的impurity,
std = np.zeros(len(X))
for tree in trees:
var_tree = tree.tree_.impurity[tree.apply(X)]
# This rounding off is done in accordance with the
# adjustment done in section 4.3.3
# of http://arxiv.org/pdf/1211.0906v2.pdf to account
# for cases such as leaves with 1 sample in which there
# is zero variance.
var_tree[var_tree < min_variance] = min_variance
mean_tree = tree.predict(X)
std += var_tree + mean_tree ** 2
然后我们的mean_tree是单个tree预测的最终结果
最终:
std /= len(trees)
std -= predictions ** 2.0
std[std < 0.0] = 0.0
std = std ** 0.5
可以看到,还是假设超参数组合w和评价指标y之间服从某种高斯分布,只不过这里不是使用高斯过程来对超参数组合w和评价指标y进行建模,而是使用随机森林来近似的建立一个经验高斯模型,
具体的做法就是这个多元高斯分布的均值向量就是所有trees的预测结果的均值(平均计算在rf内部实现),而这个分布的协方差矩阵上的数值对应的就是每一颗tree对所有样本的impurity的:
std /= len(trees)
std -= predictions ** 2.0
std[std < 0.0] = 0.0 #避免标准差小于0的尴尬局面
std = std ** 0.5
通过这种类似于直接求标准差的形式(这里我也很疑惑为什么不直接计算标准差还要多一个
的步骤)。查阅了论文:
这是个很有意思的思路,原作者通过这种方式定义了回归问题中,rf对每一个样本的预测的期望和方差,方差可以理解为回归问题中样本的预测置信度,越高则样本的预测越不稳定,这其实和前面的高斯过程的思路类似,最终都是得到关于n组超参数的多元高斯分布,然后当一组新的超参数诞生之后,通过高斯分布的边缘概率分布公式直接得到新的超参数组服从的单高斯分布,并且将其均值作为其对应的模型效果的预测。上面公式的意思就是,
以单个样本为例,假设有一个样本A进入rf,假设树有100棵,则我们去计算每一棵tree对A的预测结果,即ub,这里涉及到回归决策树的基本的预测过程,假设某个叶子节点有10个样本,每个样本的真实的回归标签是不同的,而tree的预测则是直接对这10个样本的回归标签取平均,因此,这里的 实际上就是这10个样本的真实标签的标准差,其平方就是方差了。而整个rf对样本A的预测均值就是每个树的预测结果的平均,而方差则是每一棵树的均值和方差之和的平均再减去整体预测均值的平方,通过这种方式来计算出样本A的预测方差(也就是我们上面使用的api tree.impurity的核心实现原理)。
简单来说,仍旧是假设每一个超参数组合和y都服从高斯分布,所有超参数组合和y服从多元高斯分布,用rf去近似建立拟合这个多元高斯分布,从而解决问题,而标准差是作为预测的置信度用于后续的ac函数的计算里的。