91欧美超碰AV自拍|国产成年人性爱视频免费看|亚洲 日韩 欧美一厂二区入|人人看人人爽人人操aV|丝袜美腿视频一区二区在线看|人人操人人爽人人爱|婷婷五月天超碰|97色色欧美亚州A√|另类A√无码精品一级av|欧美特级日韩特级

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

Max Pooling算子的設(shè)計(jì)實(shí)現(xiàn)

jf_pmFSk4VX ? 來(lái)源:GiantPandaCV ? 2023-01-10 09:51 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

Max Pooling算子的定義

池化層在深度學(xué)習(xí)網(wǎng)絡(luò)中的作用一般是用來(lái)緩解卷積層對(duì)位置的過(guò)度敏感性。池化層每次對(duì)輸入數(shù)據(jù)的一個(gè)固定形狀窗口(池化窗口的大小為pooling height, pooling width)中的元素計(jì)算輸出,池化層直接計(jì)算池化窗口內(nèi)元素的最大值或者平均值,因此該運(yùn)算也分別叫做最大池化或平均池化。

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

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

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

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

Max Pooling Operator的實(shí)現(xiàn)

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_;//高度上的步長(zhǎng)
uint32_tstride_w_;//寬度上的步長(zhǎng)
uint32_tpadding_h_;//高度上的填充
uint32_tpadding_w_;//寬度上的填充
};

可以看到如上的Operator中,有6個(gè)類內(nèi)屬性,分別對(duì)應(yīng)著我們第一節(jié)中講過(guò)的步長(zhǎng)(stride), 池化核(pooling)以及在池化前對(duì)邊緣的擴(kuò)充,以下我們?cè)诜謩e講講:

stride: 池化核每次移動(dòng)的步長(zhǎng)

pooling: 池化核的大小

padding: 對(duì)輸入特征圖的邊緣擴(kuò)充

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

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

Max Pooling Layer的實(shí)現(xiàn)

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());
}

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

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

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());

如上的過(guò)程表示對(duì)輸入的特征圖四周進(jìn)行填充,填充的大小由于padding_w和padding_h決定。這兩個(gè)Layer計(jì)算時(shí)候的屬性由op中得到,也就是說(shuō)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);

如上的過(guò)程表示根據(jù)輸入的特征圖大小input_h和input_w來(lái)計(jì)算對(duì)應(yīng)的輸出特征值大小output_h和output_w. 計(jì)算的公式如上文所示。如果輸入的特征數(shù)據(jù)input_data_有填充,則根據(jù)填充數(shù)據(jù)的輸入大小來(lái)計(jì)算對(duì)應(yīng)的輸出大小。

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) 表示對(duì)輸入的特征圖進(jìn)行逐通道的池化操作, 設(shè)當(dāng)前進(jìn)行操作的輸入特征圖通道為input_channel, 池化后的輸出特征圖放置于output_channel中。池化的過(guò)程如下公式所描述:

在上述的代碼中region表示當(dāng)前輸入特征數(shù)據(jù)需要進(jìn)行池化的部分,對(duì)應(yīng)于公式中[r:r+kernel height -1,c:c+kernel width -1]

中的數(shù)據(jù)。輸入特征的數(shù)據(jù)是逐個(gè)通道進(jìn)行處理(池化操作)的,從ic = 0到ic = input_channel - 1, 當(dāng)前池化的數(shù)據(jù)保存在region中。

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

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層的注冊(cè), 具體流程已經(jīng)在第五節(jié)中講過(guò)。MaxPoolingLayer::MaxPoolingLayer初始化部分根據(jù)傳入的op對(duì)this->op_進(jìn)行賦值,this->op_中保存了stride,padding,pooling等計(jì)算時(shí)需要的屬性信息。

單元測(cè)試

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, 每次移動(dòng)的步長(zhǎng)stride =1,所以根據(jù)我們?cè)诘谝还?jié)中的計(jì)算, 最后的輸出特征圖大小應(yīng)該是2乘2大小, 池化得到的值分別為4 5 7 8.

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






審核編輯:劉清

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • ARM處理器
    +關(guān)注

    關(guān)注

    6

    文章

    361

    瀏覽量

    43350

原文標(biāo)題:自制深度學(xué)習(xí)推理框架-第六課-Max Pooling算子的實(shí)現(xiàn)

文章出處:【微信號(hào):GiantPandaCV,微信公眾號(hào):GiantPandaCV】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    MAX774/MAX775/MAX776:高效低功耗反相DC - DC控制器的設(shè)計(jì)與應(yīng)用

    MAX774/MAX775/MAX776:高效低功耗反相DC - DC控制器的設(shè)計(jì)與應(yīng)用 在電子設(shè)計(jì)領(lǐng)域,DC - DC控制器是實(shí)現(xiàn)電源轉(zhuǎn)換的關(guān)鍵組件。今天,我們來(lái)深入探討MAXIM公
    的頭像 發(fā)表于 03-19 12:00 ?176次閱讀

    探索MAX6922/MAX6932/MAX6933/MAX6934:高性能VFD管驅(qū)動(dòng)器

    。而要實(shí)現(xiàn)VFD管與微控制器或VFD控制器的有效連接,就需要性能卓越的驅(qū)動(dòng)器。今天,我們就來(lái)深入了解一下Maxim公司推出的MAX6922/MAX6932/MAX6933/
    的頭像 發(fā)表于 02-12 15:30 ?763次閱讀

    探索MAX20463:實(shí)現(xiàn)USB Type - A到Type - C的完美轉(zhuǎn)換

    探索MAX20463/MAX20463A:實(shí)現(xiàn)USB Type-A到Type-C的完美轉(zhuǎn)換 在當(dāng)今的電子設(shè)備中,USB接口的升級(jí)換代十分迅速,從傳統(tǒng)的USB Type-A到更為先進(jìn)的USB
    的頭像 發(fā)表于 02-08 11:50 ?508次閱讀

    一文掌握瑞芯微RK系列NPU算子支持全景:覆蓋6大平臺(tái),新增硬件加速算子,嵌入式AI開(kāi)發(fā)不踩坑

    Operator List v2.0.0-beta》文檔,不僅更新了 6 大主流平臺(tái)的算子支持細(xì)節(jié),還新增了exSDPAttention、exMatMul 等硬件加速算子,為開(kāi)發(fā)者提供了更清晰的開(kāi)發(fā)指引。
    的頭像 發(fā)表于 02-06 16:33 ?1181次閱讀
    一文掌握瑞芯微RK系列NPU<b class='flag-5'>算子</b>支持全景:覆蓋6大平臺(tái),新增硬件加速<b class='flag-5'>算子</b>,嵌入式AI開(kāi)發(fā)不踩坑

    探索MAX961 - MAX964/MAX997/MAX999高速比較器:性能、特性與應(yīng)用

    探索MAX961 - MAX964/MAX997/MAX999高速比較器:性能、特性與應(yīng)用 在電子設(shè)計(jì)領(lǐng)域,高速比較器是實(shí)現(xiàn)信號(hào)處理和控制的
    的頭像 發(fā)表于 01-08 17:35 ?690次閱讀

    探索MAX976/MAX978/MAX998高速低功耗比較器的奧秘

    976/MAX978/MAX998專為+3V/+5V單電源應(yīng)用進(jìn)行了優(yōu)化。每個(gè)比較器在僅消耗225μA電源電流的情況下,就能實(shí)現(xiàn)20ns的傳播延遲。其中,MAX998還具備低功耗關(guān)斷
    的頭像 發(fā)表于 01-08 17:35 ?678次閱讀

    MAX961–MAX964/MAX997/MAX999:高速比較器的卓越之選

    MAX961–MAX964/MAX997/MAX999:高速比較器的卓越之選 在電子設(shè)計(jì)領(lǐng)域,高速比較器是實(shí)現(xiàn)精確信號(hào)處理和控制的關(guān)鍵組件。
    的頭像 發(fā)表于 01-08 16:50 ?588次閱讀

    MAX961–MAX964/MAX997/MAX999:高速比較器的卓越之選

    MAX961–MAX964/MAX997/MAX999:高速比較器的卓越之選 在電子設(shè)計(jì)領(lǐng)域,高速比較器一直是實(shí)現(xiàn)快速信號(hào)處理和精確閾值檢測(cè)
    的頭像 發(fā)表于 01-08 16:50 ?542次閱讀

    如何在TensorFlow Lite Micro中添加自定義操作符(2)

    上一篇中,小編給大家抽絲剝繭的介紹了在TFLm中實(shí)現(xiàn)一個(gè)算子所涉及的文件,以及每個(gè)文件的具體作用,包括:功能實(shí)現(xiàn)算子解析等。那么本篇就帶著大家一起看下注冊(cè)機(jī)制是怎么
    的頭像 發(fā)表于 12-26 10:53 ?1299次閱讀

    MAX2769ETI是否可以替換MAX2771ETI的問(wèn)題

    MAX2769ETI 是業(yè)界第一款通用的單芯片全球?qū)Ш叫l(wèi)星系統(tǒng)(GNSS)接收機(jī),用于 GPS、GLONASS 以及伽利略導(dǎo)航衛(wèi)星系統(tǒng)。它采用與 MAX2771ETI 相同的先進(jìn)低功率 SiGe
    發(fā)表于 09-29 13:45

    深入解析面向不同市場(chǎng)的多樣化Arm計(jì)算子系統(tǒng)

    如果你曾基于 Arm 技術(shù)開(kāi)發(fā)過(guò)產(chǎn)品,很大機(jī)會(huì)已經(jīng)感受到了 Arm 計(jì)算子系統(tǒng) (Arm Compute Subsystems, Arm CSS) 所帶來(lái)的強(qiáng)勁性能。
    的頭像 發(fā)表于 09-06 14:09 ?1058次閱讀
    深入解析面向不同市場(chǎng)的多樣化Arm計(jì)<b class='flag-5'>算子</b>系統(tǒng)

    GraniStudio:獲取軸信息例程

    導(dǎo)入。 2.功能說(shuō)明 實(shí)現(xiàn)位置3個(gè)軸的狀態(tài)讀取以及將位置存儲(chǔ)反饋到 HMI 上。 2.1通過(guò)初始化 運(yùn)控板卡 算子連接 格拉尼總線 型運(yùn)控卡,導(dǎo)入工程自動(dòng)進(jìn)行連接,此算子為使用運(yùn)控控制板卡的第一項(xiàng)操作,后續(xù)運(yùn)控
    的頭像 發(fā)表于 08-22 16:40 ?689次閱讀
    GraniStudio:獲取軸信息例程

    MAX1969EUI的電流方向從始終從OS1流向OS2?

    1、MAX1969EUI的電流方向從始終從OS1流向OS2? 2、那是否意味著OS1接TEC+,OS2接TEC-來(lái)實(shí)現(xiàn)制冷? 3、同時(shí)CTLI需要給0~1.5V的電壓來(lái)實(shí)現(xiàn)制冷?
    發(fā)表于 08-07 06:05

    進(jìn)迭時(shí)空同構(gòu)融合RISC-V AI CPU的Triton算子編譯器實(shí)踐

    Pytorch已能做到100%替換CUDA,國(guó)內(nèi)也有智源研究院主導(dǎo)的FlagGems通用算子庫(kù)試圖構(gòu)建起不依賴CUDA的AI計(jì)算生態(tài),截至今日,F(xiàn)lagGems已進(jìn)入Pyto
    的頭像 發(fā)表于 07-15 09:04 ?1999次閱讀
    進(jìn)迭時(shí)空同構(gòu)融合RISC-V AI CPU的Triton<b class='flag-5'>算子</b>編譯器實(shí)踐

    零知開(kāi)源——STM32F4驅(qū)動(dòng)MAX31865實(shí)現(xiàn)PT100高精度測(cè)溫

    ? 簡(jiǎn)介本教程基于零知增強(qiáng)板(主控芯片STM32F407VET6),演示如何通過(guò)MAX31865模塊讀取三線制PT100鉑電阻溫度,并通過(guò)I2C OLED實(shí)時(shí)顯示溫度值和電阻值。重點(diǎn)包含硬件接線配置
    發(fā)表于 05-26 18:52