本文介绍了结合集成学习思想的随机森林算法。首先介绍了集成学习中两种经典的集成思想Bagging和Boosting。然后介绍了Bagging的两个关键点:1)样本有放回随机采样,2)特征随机选择。最后介绍了Bagging的代表学习算法随机森林,从方差和偏差的角度分析了Bagging为什么能集成以及随机森林为什么能防止过拟合。
作者 | 文杰
编辑 | yuquanle
集成学习通过构建多个学习器采用加权的方式来完成学习任务,类似于”三个臭皮匠顶个诸葛亮”的思想。当然多个学习器之间需要满足一定的条件,一般来讲,多个学习器同属于一种模型,比如决策树,线性模型,而不会交叉用多种模型。
为了保证集成学习的有效性,多个弱分类器之间应该满足两个条件:
目前,集成学习主要分为Bagging和Boosting两种方式,前者通过Booststrap Aggregation的重采样得到多组训练集,并行的训练基学习器。而后者是一种提升的思想,基学习器是串行执行的,下一个学习器会基于上一个学习的经验进行调整,学习器前后有依赖关系,多个学习器最终组合得到强学习器。
随机森林是集成学习中Bagging方式的代表,其相对于决策树而已,有一个很重要的优点:防止过拟合。
随机森林主要通过以下两点来防止过拟合,这与深度学习中的Dropout(随机的丢失一些样本和特征)技术非常相似:
Bootstrap Sampling是一种统计学上的抽样方法,该方法是这样执行的:对于有个样本的数据集,进行次有放回采样得到数据集 ,这样与的大小一致。有放回采样使得中有的样本重复出现,有的样本则没有出现,简单估计一下,某个样本在次采样中始终没被采到的概率为,取极限:
即中的样本大概有%几率出现在中,采样出个Bootstrap 样本集 ,对这个样本集分别训练一个基学习器 ,结合这些基学习器共同作出决策。
决策时,在分类任务中通常采用投票法,若两个类别票数一样,最简单的做法是随机选择一个;而回归任务则一般使用平均法。整个流程如下所示:
早期的Bagging方法是每个基学习器都是一个决策树,完全按照决策树的规则建树。
随机森林则在Bagging的基础继续采用特征随机,每个基学习器只对在个特征构成的子集下进行建树,一般取。这样构建的决策树相对于完整的决策树是一个“浅决策树”,这样就构成了特征的随机性。
到此,随机森林基本介绍完,但是依然存在问题,随机森林为什么能防止过拟合,随机森林适合什么样的场景?
从Bias和Variance的角度分析,Bagging对样本的重采样得到个训练集,对于每个训练集训练一个基学习器,因为基学习器相同,因此各个学习器有近似的Bais和Variance(学习器并不一定独立)。
假设每个学习器的权重相同即。每个学习器的损失用表示,那么随机森林的损失可表示为:
所以Bagging后的Bias和单个基学习器的接近,并不能显著降低bias。若各基学习器独立,因为每个学习器的权重是,所以引入的方差为,那么随机森林的Variance可表示为:
可以看出,Bagging通过降低Variance来防止过拟合,严格来说每个学习器之间不严格独立,所以Variance的降低会小于B倍。
优点:
缺点:
int createBinTree(bitree_R &t,const Data &data, const int &deep, const int &epsilon)
{
if(!(t=(bitnode_R *)malloc(sizeof(bitnode_R)))) exit(-1);
split_R sp=chooseBestSplit(data,deep,epsilon,10);
cout<<"index="<<sp.bestIndex<<endl;
t->feature=sp.bestIndex;
t->meanValue=sp.value;
//t->data=data;
if(t->feature==-1)
{
t->left=NULL;
t->right=NULL;
//t->data=data;
cout<<"feat-1"<<endl;
return 0;
}
else
{
cout<<"feature="<<t->feature<<" value="<<t->meanValue<<endl;
twoSubData_R twosubdata=binSplitDataSet(data,sp.bestIndex,sp.value);
createBinTree((t->left),twosubdata.left,deep,epsilon);
createBinTree((t->right),twosubdata.right,deep,epsilon);
}
return 0;
}
完整代码见【https://github.com/myazi/myLearn】