Shark源码分析(十一):随机森林算法

Shark源码分析(十一):随机森林算法

关于这个算法的介绍,可以参看我之前关于集成算法的博客。因为Shark中关于决策树算法只实现了CART算法,所以随机森林算法中也只包含了CART算法。如果你已经看过了我之前写的关于CART算法源码分析的博客,看到后面就会发现它与随机森林算法的代码其实差不多。只是在选择最优划分属性时多了一个随机选取候选集的过程。这也是随机森林算法的一大特点。因为CART算法既可以用于分类任务中也可以用于回归任务中,所以基于CART算法的随机森林也能用于这两个任务。这里我们只介绍其用于分类任务中的代码。

MeanModel类

这个类应该算是集成算法的基类,表示如何将多个基学习器的输出结果综合起来。该类定义在<include/shark/Models/MeanModel.h>中。

template<class ModelType> // ModelType表示基学习器的类型
class MeanModel : public AbstractModel<typename ModelType::InputType, typename ModelType::OutputType>
{
private:
    typedef AbstractModel<typename ModelType::InputType, typename ModelType::OutputType> base_type;
public:

    MeanModel():m_weightSum(0){}

    std::string name() const
    { return "MeanModel"; }

    using base_type::eval;
    // 输出集成学习器的结果,与决策树输出的结果一样,是对于每一个类别的所属概率
    void eval(typename base_type::BatchInputType const& patterns, typename base_type::BatchOutputType& outputs)const{
        m_models[0].eval(patterns,outputs);
        outputs *=m_weight[0];
        for(std::size_t i = 1; i != m_models.size(); i++) 
            noalias(outputs) += m_weight[i] * m_models[i](patterns);
        outputs /= m_weightSum;
    }

    void eval(typename base_type::BatchInputType const& patterns, typename base_type::BatchOutputType& outputs, State& state)const{
        eval(patterns,outputs);
    }

    RealVector parameterVector() const {
        return RealVector();
    }

    void setParameterVector(const RealVector& param) {
        SHARK_ASSERT(param.size() == 0);
    }

    void read(InArchive& archive){
        archive >> m_models;
        archive >> m_weight;
        archive >> m_weightSum;
    }

    void write(OutArchive& archive)const{
        archive << m_models;
        archive << m_weight;
        archive << m_weightSum;
    }

    void clearModels(){
        m_models.clear();
        m_weight.clear();
        m_weightSum = 0.0;
    }

    // 增加一个基学习器
    void addModel(ModelType const& model, double weight = 1.0){
        SHARK_CHECK(weight > 0, "Weights must be positive");
        m_models.push_back(model);
        m_weight.push_back(weight);
        m_weightSum+=weight;
    }

    double const& weight(std::size_t i)const{
        return m_weight[i];
    }

    void setWeight(std::size_t i, double newWeight){
        m_weightSum=newWeight - m_weight[i];
        m_weight[i] = newWeight;
    }

    std::size_t numberOfModels()const{
        return m_models.size();
    }

protected:
    // 表示所有的基学习器,这里要求它们的类型是一致的,但是在实际的应用中,其实是可以不一样的
    std::vector<ModelType> m_models;

    // 表示各个基学习器的权重
    std::vector<double> m_weight;

    // 所有权重之和
    double m_weightSum;
};

RFClassifier类

该类是用来表示一个随机森林,定义在<include/shark/Models/Trees/RFClassifier.h>中。

class RFClassifier : public MeanModel<CARTClassifier<RealVector> >
{
public:
    std::string name() const
    { return "RFClassifier"; }

    // 计算模型的平均OOB误差,将基学习器的OOB误差累加起来,再除以基学习器的个数
    void computeOOBerror(){
        std::size_t n_trees = numberOfModels();
        m_OOBerror = 0;
        for(std::size_t j=0;j!=n_trees;++j){
            m_OOBerror += m_models[j].OOBerror();
        }
        m_OOBerror /= n_trees;
    }

    // 综合基学习器每一维的重要程度,得到集成学习器每一维的重要程度
    void computeFeatureImportances(){
        m_featureImportances.resize(m_inputDimension);
        std::size_t n_trees = numberOfModels();

        for(std::size_t i=0;i!=m_inputDimension;++i){
            m_featureImportances[i] = 0;
            for(std::size_t j=0;j!=n_trees;++j){
                m_featureImportances[i] += m_models[j].featureImportances()[i];
            }
            m_featureImportances[i] /= n_trees;
        }
    }

    double const OOBerror() const {
        return m_OOBerror;
    }

    RealVector const& featureImportances() const {
        return m_featureImportances;
    }

    // 统计对于所有的基学习器,每一个特征在选择最优划分属性时被使用的次数
    UIntVector countAttributes() const {
        std::size_t n = m_models.size();
        if(!n) return UIntVector();
        UIntVector r = m_models[0].countAttributes();
        for(std::size_t i=1; i&l
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值