深度森林(gcforest)原理讲解以及代码实现

GcForest原理

gcforest采用Cascade结构,也就是多层级结构,每层由四个随机森林组成,两个随机森林和两个极端森林,每个极端森林包含1000(超参数)个完全随机树,每个森林都会对的数据进行训练,每个森林都输出结果,我们把这个结果叫做森林生成的类向量,为了避免过拟合,我们喂给每个森林训练的数据都是通过k折交叉验证的,每一层最后生成四个类向量,下一层以上一层的四个类向量以及原有的数据为新的train data进行训练,如此叠加,最后一层将类向量进行平均,作为预测结果

个人认为这种结构非常类似于神经网络,神经网络的每个单位是神经元,而深度森林的单位元却是随机森林,单个随机森林在性能上强于单个神经元的,这就是使得深度森林很多时候尽管层级和基础森林树不多,也能取得好的结果的主要原因

在这里插入图片描述

GcForest代码实现原理图

我们需要做出一个layer的结构,每个layer由二种四个森林组成

在这里插入图片描述

每个layer都输出两个结果:每个森林的预测结果、四个森林的预测的平均结果

为了防止过拟合我们的layer都由k折交叉验证产生

在这里插入图片描述

同时为了保留数据全部的特征我们将得到的小layer叠在一起定义一个Biger Layer

之后我们就可以构建深度森林了

在这里插入图片描述

GcForest代码

layer.py

extraTree(极端树)使用的所有的样本,只是特征是随机选取的,因为分裂是随机的,所以在某种程度上比随机森林得到的结果更加好

from sklearn.ensemble import ExtraTreesRegressor#引入极端森林回归
from sklearn.ensemble import RandomForestRegressor#引入随机森林回归
import numpy as np


class Layer:#定义层类
    def __init__(self, n_estimators, num_forests, max_depth=30, min_samples_leaf=1):
        self.num_forests = num_forests  # 定义森林数
        self.n_estimators = n_estimators  # 每个森林的树个数
        self.max_depth = max_depth#每一颗树的最大深度
        self.min_samples_leaf = min_samples_leaf#树会生长到所有叶子都分到一个类,或者某节点所代表的样本数已小于min_samples_leaf
        self.model = []#最后产生的类向量


    def train(self, train_data, train_label, weight, val_data):#训练函数
        val_prob = np.zeros([self.num_forests, val_data.shape[0]])#定义出该层的类向量,有self.num_forersts行,val_data.shape[0]列,这里我们认为val_data应该就是我们的weight
       
        for forest_index in range(self.num_forests):#对具体的layer内的森林进行构建
            if forest_index % 2 == 0:#如果是第偶数个设为随机森林
                clf = RandomForestRegressor(n_estimators=self.n_estimators#子树的个数,
                                             n_jobs=-1, #cpu并行树,-1表示和cpu的核数相同
                                             max_depth=self.max_depth,#最大深度
                                             min_samples_leaf=self.min_samples_leaf)
                clf.fit(train_data, train_label, weight)#weight是取样比重Sample weights
                val_prob[forest_index, :] = clf.predict(val_data)#记录类向量
            else:#如果是第奇数个就设为极端森林
                clf = ExtraTreesRegressor(n_estimators=self.n_estimators,#森林所含树的个数
                                           n_jobs=-1, #并行数
                                           max_depth=self.max_depth,#最大深度
                                           min_samples_leaf=self.min_samples_leaf
  • 26
    点赞
  • 230
    收藏
    觉得还不错? 一键收藏
  • 21
    评论
深度FIFO,即先进先出队列,是一种重要的数据结构。它可以在存储和读取数据时保证数据的顺序,适用于许多应用场景,如缓存、视频处理等。在FPGA中,深度FIFO可以用Verilog语言实现,下面介绍一下它的原理实现方法。 ## 原理 深度FIFO的原理和普通队列相同,它有两个指针,一个用于指向队列头部,一个用于指向队列尾部。当有新的数据进入队列时,数据被写入队列尾部,并且队列尾指针向后移动一个位置;当数据从队列中被读出时,数据被读出队列头部,并且队列头指针向后移动一个位置。当队列满时,新的数据不能被写入队列,当队列为空时,数据不能被读出。 深度FIFO的实现需要使用一些特定的技术,如寄存器、计数器、比较器等。 ## Verilog实现 下面是一个深度为8的FIFO的Verilog实现,它包含一个输入端口、一个输出端口和一些中间信号。 ``` module fifo8( input clk, input rst, input wr_en, input rd_en, input [7:0] data_in, output [7:0] data_out, output empty, output full ); reg [7:0] fifo[0:7]; reg [2:0] wr_ptr; reg [2:0] rd_ptr; reg [2:0] count; assign empty = (count == 0); assign full = (count == 8); always @(posedge clk) begin if (rst) begin wr_ptr <= 3'b0; rd_ptr <= 3'b0; count <= 3'b0; end else begin if (wr_en && !full) begin fifo[wr_ptr] <= data_in; wr_ptr <= wr_ptr + 1; count <= count + 1; end if (rd_en && !empty) begin data_out <= fifo[rd_ptr]; rd_ptr <= rd_ptr + 1; count <= count - 1; end end end endmodule ``` 在这个Verilog代码中,我们使用了三个寄存器:`wr_ptr`、`rd_ptr`和`count`。`wr_ptr`用于指向队列尾部,`rd_ptr`用于指向队列头部,`count`用于记录队列中的元素数量。我们还使用了一个数组`fifo`来存储队列中的数据。 在时钟上升沿时,我们根据`wr_en`和`rd_en`信号判断是否需要写入或读取数据。如果`wr_en`为高电平且队列未满,则将输入数据写入队列尾部,并将`wr_ptr`指针向后移动一个位置,并将`count`增加1。如果`rd_en`为高电平且队列非空,则从队列头部读取数据,并将`rd_ptr`指针向后移动一个位置,并将`count`减少1。 最后,我们定义了四个输出端口:`data_out`用于输出读取到的数据,`empty`用于表示队列是否为空,`full`用于表示队列是否已满。 以上就是深度为8的FIFO的Verilog实现。需要注意的是,这个FIFO只能存储8个8位的数据,如果需要存储更多的数据,需要修改代码中的参数。
评论 21
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值