精品国产人成在线_亚洲高清无码在线观看_国产在线视频国产永久2021_国产AV综合第一页一个的一区免费影院黑人_最近中文字幕MV高清在线视频

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

Max Pooling算子的設計實現

jf_pmFSk4VX ? 來源:GiantPandaCV ? 2023-01-10 09:51 ? 次閱讀

Max Pooling算子的定義

池化層在深度學習網絡中的作用一般是用來緩解卷積層對位置的過度敏感性。池化層每次對輸入數據的一個固定形狀窗口(池化窗口的大小為pooling height, pooling width)中的元素計算輸出,池化層直接計算池化窗口內元素的最大值或者平均值,因此該運算也分別叫做最大池化或平均池化。

在我們本節課要講的二維最大池化中,池化窗口從輸入數組的最左上方開始,按從左往右、從上往下的順序,依次在輸入數組上滑動(滑動的幅度被稱為stride)。當池化窗口滑動到某一位置時,窗口中的輸入子數組的最大值即輸出數組中相應位置的元素。

01ff34bc-9034-11ed-bfe3-dac502259ad0.png

圖1展示了池化窗口形狀為 2×2 的最大池化,陰影部分為第一個輸出元素及其計算所使用的輸入元素。

輸出數組的高和寬分別為2,其中的4個元素由取最大值運算 max 得出。 如下公式所示,池化操作的步驟依次為從左到右,從上到下,每次向下移動的步長為stride height, 向右移動的步長為stride width. 進行池化操作元素的數量由pooling height和pooling width所組成的2×2的窗口所決定。

Max Pooling Operator的實現

classMaxPoolingOp:publicOperator{
public:
explicitMaxPoolingOp(uint32_tpooling_h,uint32_tpooling_w,uint32_tstride_h,
uint32_tstride_w,uint32_tpadding_h,uint32_tpadding_w);

voidset_pooling_h(uint32_tpooling_height);
voidset_pooling_w(uint32_tpooling_width);

voidset_stride_w(uint32_tstride_width);
voidset_stride_h(uint32_tstride_height);

voidset_padding_h(uint32_tpadding_height);
voidset_padding_w(uint32_tpadding_width);

uint32_tpadding_height()const;
uint32_tpadding_width()const;

uint32_tstride_width()const;
uint32_tstride_height()const;

uint32_tpooling_height()const;
uint32_tpooling_width()const;
private:
uint32_tpooling_h_;//池化核高度大小
uint32_tpooling_w_;//池化核寬度大小
uint32_tstride_h_;//高度上的步長
uint32_tstride_w_;//寬度上的步長
uint32_tpadding_h_;//高度上的填充
uint32_tpadding_w_;//寬度上的填充
};

可以看到如上的Operator中,有6個類內屬性,分別對應著我們第一節中講過的步長(stride), 池化核(pooling)以及在池化前對邊緣的擴充,以下我們在分別講講:

stride: 池化核每次移動的步長

pooling: 池化核的大小

padding: 對輸入特征圖的邊緣擴充

如下圖2是pad(padding值為1)后輸入特征圖的池化操作(池化核為2):

020e0816-9034-11ed-bfe3-dac502259ad0.png

Max Pooling Layer的實現

MaxPoolingLayer::MaxPoolingLayer(conststd::shared_ptr&op):Layer("maxpooling"){
CHECK(op->op_type_==OpType::kOperatorMaxPooling)<op_type_);
MaxPoolingOp*max_pooling_op=dynamic_cast(op.get());

CHECK(max_pooling_op!=nullptr)<op_=std::make_unique(*max_pooling_op);
}

voidMaxPoolingLayer::Forwards(conststd::vector>>&inputs,
std::vector>>&outputs){
CHECK(this->op_!=nullptr);
CHECK(this->op_->op_type_==OpType::kOperatorMaxPooling);
CHECK(!inputs.empty());
constuint32_tpadding_h=this->op_->padding_height();
constuint32_tpadding_w=this->op_->padding_width();
constuint32_tkernel_h=this->op_->pooling_height();
constuint32_tkernel_w=this->op_->pooling_width();
constuint32_tstride_h=this->op_->stride_height();
constuint32_tstride_w=this->op_->stride_width();

constuint32_tbatch_size=inputs.size();
for(uint32_ti=0;i>&input_data_=inputs.at(i)->Clone();
input_data_->Padding({padding_h,padding_h,padding_w,padding_w},std::numeric_limits::lowest());
constuint32_tinput_h=input_data_->rows();
constuint32_tinput_w=input_data_->cols();
constuint32_tinput_c=input_data_->channels();
constuint32_toutput_c=input_c;

constuint32_toutput_h=uint32_t(std::floor((input_h-kernel_h)/stride_h+1));
constuint32_toutput_w=uint32_t(std::floor((input_w-kernel_w)/stride_w+1));
CHECK(output_w>0&&output_h>0);

std::shared_ptr>output_data=std::make_shared>(output_c,output_h,output_w);
for(uint32_tic=0;icat(ic);
arma::fmat&output_channel=output_data->at(ic);
for(uint32_tr=0;rMaxPoolingLayer::CreateInstance(conststd::shared_ptr&op){
CHECK(op->op_type_==OpType::kOperatorMaxPooling);
std::shared_ptrmax_layer=std::make_sh了ared(op);
returnmax_layer;
}

LayerRegistererWrapperkMaxPoolingLayer(OpType::kOperatorMaxPooling,MaxPoolingLayer::CreateInstance);
voidMaxPoolingLayer::Forwards(conststd::vector>>&inputs,
std::vector>>&outputs){
CHECK(this->op_!=nullptr);
CHECK(this->op_->op_type_==OpType::kOperatorMaxPooling);
CHECK(!inputs.empty());
}

我們重點來看Forwards函數, 首先判斷輸入是否為空并獲得池化操作相關的屬性值(原本存放在op中).

計算池化后的輸出特征圖大小, 公式為:

for(uint32_ti=0;i>&input_data_=inputs.at(i)->Clone();
input_data_->Padding({padding_h,padding_h,padding_w,padding_w},std::numeric_limits::lowest());

如上的過程表示對輸入的特征圖四周進行填充,填充的大小由于padding_w和padding_h決定。這兩個Layer計算時候的屬性由op中得到,也就是說padding_w和padding_h存放在this->op中, this->op_ = std::make_unique(*max_pooling_op);

for(uint32_ti=0;i>&input_data_=inputs.at(i)->Clone();
input_data_->Padding({padding_h,padding_h,padding_w,padding_w},std::numeric_limits::lowest());
constuint32_tinput_h=input_data_->rows();
constuint32_tinput_w=input_data_->cols();
constuint32_tinput_c=input_data_->channels();
constuint32_toutput_c=input_c;

constuint32_toutput_h=uint32_t(std::floor((input_h-kernel_h)/stride_h+1));
constuint32_toutput_w=uint32_t(std::floor((input_w-kernel_w)/stride_w+1));
CHECK(output_w>0&&output_h>0);

如上的過程表示根據輸入的特征圖大小input_h和input_w來計算對應的輸出特征值大小output_h和output_w. 計算的公式如上文所示。如果輸入的特征數據input_data_有填充,則根據填充數據的輸入大小來計算對應的輸出大小。

for(uint32_ti=0;iat(ic);
arma::fmat&output_channel=output_data->at(ic);
for(uint32_tr=0;r

for(uint32_t ic =0; ic < input_c;++ic) 表示對輸入的特征圖進行逐通道的池化操作, 設當前進行操作的輸入特征圖通道為input_channel, 池化后的輸出特征圖放置于output_channel中。池化的過程如下公式所描述:

在上述的代碼中region表示當前輸入特征數據需要進行池化的部分,對應于公式中[r:r+kernel height -1,c:c+kernel width -1]

中的數據。輸入特征的數據是逐個通道進行處理(池化操作)的,從ic = 0到ic = input_channel - 1, 當前池化的數據保存在region中。

input_channel.submat(r, c, r + kernel_h -1, c + kernel_w -1)取得一個池化區域內的所有元素,隨后使用region.max()取得區域內(kernel_h和kernel_w組成的范圍)的最大值, 并且每次區域移動的位置是stride_h和stride_w, 取得最大值后存放在輸出特征圖中對應的位置中,輸出存放的位置為輸出特征圖outut_channel的(int(r/stride_h),int(c/stride_w))的位置中。這部分可能描述地比較晦澀,請結合視頻一起食用。

Max Pooling Layer的其他部分

MaxPoolingLayer::MaxPoolingLayer(conststd::shared_ptr&op):Layer("maxpooling"){
CHECK(op->op_type_==OpType::kOperatorMaxPooling)<op_type_);
MaxPoolingOp*max_pooling_op=dynamic_cast(op.get());

CHECK(max_pooling_op!=nullptr)<op_=std::make_unique(*max_pooling_op);
}

LayerRegistererWrapperkMaxPoolingLayer(OpType::kOperatorMaxPooling,MaxPoolingLayer::CreateInstance);

以上的步驟完成了Max Pooling層的注冊, 具體流程已經在第五節中講過。MaxPoolingLayer::MaxPoolingLayer初始化部分根據傳入的op對this->op_進行賦值,this->op_中保存了stride,padding,pooling等計算時需要的屬性信息

單元測試

TEST(test_layer,forward_maxpooling1){
usingnamespacekuiper_infer;
uint32_tstride_h=1;
uint32_tstride_w=1;
uint32_tpadding_h=0;
uint32_tpadding_w=0;
uint32_tpooling_h=2;
uint32_tpooling_w=2;

std::shared_ptr
max_op=std::make_shared(pooling_h,pooling_w,stride_h,stride_w,padding_h,padding_w);
std::shared_ptrmax_layer=LayerRegisterer::CreateLayer(max_op);
CHECK(max_layer!=nullptr);

arma::fmatinput_data="012;"
"345;"
"678;";
std::shared_ptr>input=std::make_shared>(2,input_data.n_rows,input_data.n_cols);
input->at(0)=input_data;
input->at(1)=input_data;

std::vector>>inputs;
std::vector>>outputs;
inputs.push_back(input);

max_layer->Forwards(inputs,outputs);
ASSERT_EQ(outputs.size(),1);
constauto&output=outputs.at(0);
LOG(INFO)<data();
ASSERT_EQ(output->rows(),2);
ASSERT_EQ(output->cols(),2);

ASSERT_EQ(output->at(0,0,0),4);
ASSERT_EQ(output->at(0,0,1),5);
ASSERT_EQ(output->at(0,1,0),7);
ASSERT_EQ(output->at(0,1,1),8);

ASSERT_EQ(output->at(1,0,0),4);
ASSERT_EQ(output->at(1,0,1),5);
ASSERT_EQ(output->at(1,1,0),7);
ASSERT_EQ(output->at(1,1,1),8);
}

可以看到, 我們的輸入為 arma::fmat input_data ="0 1 2 ; 3 4 5 ;6 7 8; " , 池化核的大小為2, 每次移動的步長stride =1,所以根據我們在第一節中的計算, 最后的輸出特征圖大小應該是2乘2大小, 池化得到的值分別為4 5 7 8.

021f7632-9034-11ed-bfe3-dac502259ad0.png






審核編輯:劉清

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • ARM處理器
    +關注

    關注

    6

    文章

    360

    瀏覽量

    41667

原文標題:自制深度學習推理框架-第六課-Max Pooling算子的實現

文章出處:【微信號:GiantPandaCV,微信公眾號:GiantPandaCV】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    MAX232實現單電源供電下放大3.3Vpp方波?

    請問大佬,可以通過MAX232實現單電源5V供電下,把40KHZ,3.3Vpp的方波放大到多少?怎么實現呢?(老師提示是用H橋和MAX轉換電路)
    發表于 11-04 20:08

    基于 DSP5509 進行數字圖像處理中 Sobel 算子邊緣檢測的硬件連接電路圖

    以下是基于 DSP5509 進行數字圖像處理中 Sobel 算子邊緣檢測的硬件設計方案: 一、總體架構 圖像采集:使用合適的圖像傳感器,如 CMOS 傳感器,通過相應的接口(如 SPI、I2C 等
    發表于 09-25 15:25

    摩爾線程攜手智源研究院完成基于Triton的大模型算子庫適配

    里,即成功完成了近60個算子的功能驗證,精度符合交付標準,并實現對Bert-large模型的全面支持。FlagGems算子庫在摩爾線程MUSA架構上展現出了接近手寫算子的計算性能,且性
    的頭像 發表于 08-02 11:06 ?777次閱讀

    ZN-Z84,能ping通,但是NI MAX不識別,找不到設備

    前提是,安裝原廠的user程序,利用usb驅動和接口,是可以實現程控通信的。 ZN-Z84,開關單元,利用網線連接,結果IP 都用cmd的ping 命令ping通了,死活都無法在NI MAX 和IO
    發表于 08-02 09:08

    ZN-Z84,能ping通,但是NI MAX不識別,找不到設備

    前提是,安裝原廠的user程序,利用usb驅動和接口,是可以實現程控通信的。 ZN-Z84,開關單元,利用網線連接,結果IP 都用cmd的ping 命令ping通了,死活都無法在NI MAX 和IO
    發表于 07-27 10:18

    ClickHouse內幕(3)基于索引的查詢優化

    ClickHouse索引采用唯一聚簇索引的方式,即Part內數據按照order by keys有序,在整個查詢計劃中,如果算子能夠有效利用輸入數據的有序性,對算子的執行性能將有巨大的提升。本文討論
    的頭像 發表于 06-11 10:46 ?937次閱讀
    ClickHouse內幕(3)基于索引的查詢優化

    Arm發布全新終端計算子系統,加速AI體驗與產品上市

    全球領先的半導體知識產權(IP)提供商Arm控股有限公司(納斯達克股票代碼:ARM)今日正式推出全新的Arm終端計算子系統(CSS),以推動人工智能(AI)體驗的前沿發展,并助力芯片合作伙伴在構建基于Arm架構的解決方案時實現更高效、更快速的流程,從而加速產品上市。
    的頭像 發表于 05-30 14:23 ?539次閱讀

    Arm宣布推出終端計算子系統(CSS),提供領先的人工智能體驗

    Arm 控股有限公司(納斯達克股票代碼:ARM,以下簡稱“Arm”)今日宣布推出 Arm? 終端計算子系統 (CSS),以提供領先的人工智能 (AI) 體驗,助力芯片合作伙伴更輕松、快速地構建基于 Arm 架構的解決方案,并加速其產品上市進程。
    的頭像 發表于 05-30 14:11 ?1204次閱讀
    Arm宣布推出終端計<b class='flag-5'>算子</b>系統(CSS),提供領先的人工智能體驗

    MAX13085EESA+與MAX13485EESA+的差異在什么地方?

    MAX13085EESA+與MAX13485EESA+,這兩款同系列的8SO芯片的差異在什么地方,是否可以互相替代
    發表于 05-23 08:10

    MAX17205電量計如何正確配置所有寄存器?

    第一個問題:MAX17205 用EZ配置電池相關參數,但我發現Empty Voltage最低只能設置為3V,我想設置成2.5V或2.4V有辦法實現嗎? 第二個問題:我看MAX17205芯片手冊,有
    發表于 05-22 08:17

    Arm新Arm Neoverse計算子系統(CSS):Arm Neoverse CSS V3和Arm Neoverse CSS N3

    Arm宣布了兩款新的Arm Neoverse計算子系統(CSS),它們基于“迄今為止最好的一代Neoverse技術”。是什么讓這些新產品在擁擠的計算技術領域脫穎而出? Arm的兩個新Arm
    的頭像 發表于 04-24 17:53 ?989次閱讀
    Arm新Arm Neoverse計<b class='flag-5'>算子</b>系統(CSS):Arm Neoverse CSS V3和Arm Neoverse CSS N3

    PSoC4s MAX如何讓距離傳感器進入堅固的地面?

    我們正在考慮在連接到 FG 的金屬框架上實現 PSoC4s MAX 接近傳感器。 圖像示意圖如下: 當我們驗證操作時,PSoC4s MAX的距離傳感器的靈敏度非常差,因為金屬框架變成了堅固
    發表于 01-29 07:01

    OneFlow Softmax算子源碼解讀之WarpSoftmax

    寫在前面:近來筆者偶然間接觸了一個深度學習框架 OneFlow,所以這段時間主要在閱讀 OneFlow 框架的 cuda 源碼。官方源碼基于不同場景分三種方式實現 Softmax,本文主要介紹其中一種的實現過程,即 Warp 級別 Softmax,適用于矩陣寬度不超過 1
    的頭像 發表于 01-08 09:24 ?760次閱讀
    OneFlow Softmax<b class='flag-5'>算子</b>源碼解讀之WarpSoftmax

    請問MAX9291MAX9288上電后,i2c通信不通的原因?

    請問MAX9291MAX9288上電后,通過i2c通信不通的原因?
    發表于 12-28 09:24

    OpenCV邊緣檢測算子Laplace、LoG詳解

    一階導數算子(例如 Sobel 算子)通過對圖像求導來確定圖像的邊緣,數值絕對值較高的點對應了圖像的邊緣。如果繼續求二階導,原先數值絕對值較高的點對應了過零點。因此,也可以通過找到二階導數的過零點來檢測邊緣。在某些情況下,找二階導數的過零點可能更容易。
    的頭像 發表于 12-21 16:34 ?2045次閱讀
    OpenCV邊緣檢測<b class='flag-5'>算子</b>Laplace、LoG詳解