首頁 >> 動(dòng)態(tài) 自制深度學(xué)習(xí)推理框架-實(shí)現(xiàn)我們的第一個(gè)算子Relu-第三課 2023-01-02 22:31:58來源: 我們的課程主頁https://github.com/zjhellofss/KuiperInfer 歡迎pr和點(diǎn)贊(資料圖片)手把手教大家去寫一個(gè)深度學(xué)習(xí)推理框架 B站視頻課程Relu算子的介紹Relu是一種非線性激活函數(shù),它的特點(diǎn)有運(yùn)算簡(jiǎn)單,不會(huì)在梯度處出現(xiàn)梯度消失的情況,而且它在一定程度上能夠防止深度學(xué)習(xí)模型在訓(xùn)練中發(fā)生的過擬合現(xiàn)象。Relu的公式表達(dá)如下所示,「如果對(duì)于深度學(xué)習(xí)基本概念不了解的同學(xué),可以將Relu當(dāng)作一個(gè)公式進(jìn)行對(duì)待,可以不用深究其背后的含義。」我們今天的任務(wù)就是來完成這個(gè)公式中的操作,「值得注意的是,在我們的項(xiàng)目中,x和y可以理解為我們?cè)诘诙?、第三?jié)中實(shí)現(xiàn)的張量類(tensor).」Operator類Operator類就是我們?cè)诘谝还?jié)中說過的計(jì)算圖中「節(jié)點(diǎn)」的概念,計(jì)算圖的另外一個(gè)概念是數(shù)據(jù)流圖,如果同學(xué)們忘記了這個(gè)概念,可以重新重新翻看第一節(jié)課程。在我們的代碼中我們先定義一個(gè)「Operator」類,它是一個(gè)父類,其余的Operator,包括我們本節(jié)要實(shí)現(xiàn)的ReluOperator都是其派生類,「Operator中會(huì)存放節(jié)點(diǎn)相關(guān)的參數(shù)?!估缭凇窩onvOperator」中就會(huì)存放初始化卷積算子所需要的stride, padding, kernel_size等信息,本節(jié)的「ReluOperator」就會(huì)帶有「thresh」值信息。我們從下方的代碼中來了解Operator類和ReluOperator類,它們是父子關(guān)系,Operator是基類,OpType記錄Operator的類型。enumclassOpType{kOperatorUnknown=-1,kOperatorRelu=0,};classOperator{public:OpTypekOpType=OpType::kOperatorUnknown;virtual~Operator()=default;explicitOperator(OpTypeop_type);};ReluOperator實(shí)現(xiàn):classReluOperator:publicOperator{public:~ReluOperator()override=default;explicitReluOperator(floatthresh);voidset_thresh(floatthresh);floatget_thresh()const;private:floatthresh_=0.f;};Layer類我們會(huì)在operator類中存放從「計(jì)算圖結(jié)構(gòu)文件」得到的信息,例如在ReluOperator中存放的thresh值作為一個(gè)參數(shù)就是我們從計(jì)算圖結(jié)構(gòu)文件中得到的,計(jì)算圖相關(guān)的概念我們已經(jīng)在第一節(jié)中講過。下一步我們需要根據(jù)ReLuOperator類去完成ReluLayer的初始化,「他們的區(qū)別在于ReluOperator負(fù)責(zé)存放從計(jì)算圖中得到的節(jié)點(diǎn)信息,不負(fù)責(zé)計(jì)算」,而ReluLayer則「負(fù)責(zé)具體的計(jì)算操作」,同樣,所有的Layer類有一個(gè)公共父類Layer. 我們可以從下方的代碼中來了解兩者的關(guān)系。classLayer{public:explicitLayer(conststd::string&layer_name);virtualvoidForwards(conststd::vector>>&inputs,std::vector>>&outputs);virtual~Layer()=default;private:std::stringlayer_name_;};其中Layer的Forwards方法是具體的執(zhí)行函數(shù),負(fù)責(zé)將輸入的inputs中的數(shù)據(jù),進(jìn)行relu運(yùn)算并存放到對(duì)應(yīng)的outputs中。classReluLayer:publicLayer{public:~ReluLayer()override=default;explicitReluLayer(conststd::shared_ptr&op);voidForwards(conststd::vector>>&inputs,std::vector>>&outputs)override;private:std::shared_ptrop_;};這是集成于Layer的ReluLayer類,我們可以看到其中有一個(gè)op成員,是一個(gè)ReluOperator指針,「這個(gè)指針中負(fù)責(zé)存放ReluLayer計(jì)算時(shí)所需要用到的一些參數(shù)」。此處op_存放的參數(shù)比較簡(jiǎn)單,只有ReluOperator中的thresh參數(shù)。我們?cè)倏纯词窃趺词褂肦eluOperator去初始化ReluLayer的,先通過統(tǒng)一接口傳入Operator類,再轉(zhuǎn)換為對(duì)應(yīng)的ReluOperator指針,最后再通過指針中存放的信息去初始化「op_」.ReluLayer::ReluLayer(conststd::shared_ptr&op):Layer("Relu"){CHECK(op->kOpType==OpType::kOperatorRelu);ReluOperator*relu_op=dynamic_cast(op.get());CHECK(relu_op!=nullptr);this->op_=std::make_shared(relu_op->get_thresh());}我們來看一下具體ReluLayer的Forwards過程,它在執(zhí)行具體的計(jì)算,完成Relu函數(shù)描述的功能。voidReluLayer::Forwards(conststd::vector>>&inputs,std::vector>>&outputs){CHECK(this->op_!=nullptr);CHECK(this->op_->kOpType==OpType::kOperatorRelu);constuint32_tbatch_size=inputs.size();for(inti=0;iempty());conststd::shared_ptr>&input_data=inputs.at(i);input_data->data().transform([&](floatvalue){floatthresh=op_->get_thresh();if(value>=thresh){returnvalue;}else{return0.f;}});outputs.push_back(input_data);}}在for循環(huán)中,首先讀取輸入input_data, 再對(duì)input_data使用armadillo自帶的transform按照我們給定的thresh過濾其中的元素,如果「value」的值大于thresh則不變,如果小于thresh就返回0.最后,我們寫一個(gè)測(cè)試函數(shù)來驗(yàn)證我們以上的兩個(gè)類,節(jié)點(diǎn)op類,計(jì)算層layer類的正確性。先判斷Forwards返回的outputs是否已經(jīng)保存了relu層的輸出,輸出大小應(yīng)該assert為1. 隨后再進(jìn)行比對(duì),我們應(yīng)該知道在thresh等于0的情況下,第一個(gè)輸出index(0)和第二個(gè)輸出index(1)應(yīng)該是0,第三個(gè)輸出應(yīng)該是3.f.TEST(test_layer,forward_relu){usingnamespacekuiper_infer;floatthresh=0.f;std::shared_ptrrelu_op=std::make_shared(thresh);std::shared_ptr>input=std::make_shared>(1,1,3);input->index(0)=-1.f;input->index(1)=-2.f;input->index(2)=3.f;std::vector>>inputs;std::vector>>outputs;inputs.push_back(input);ReluLayerlayer(relu_op);layer.Forwards(inputs,outputs);ASSERT_EQ(outputs.size(),1);for(inti=0;iindex(0),0.f);ASSERT_EQ(outputs.at(i)->index(1),0.f);ASSERT_EQ(outputs.at(i)->index(2),3.f);}}本期代碼倉庫位置gitclonehttps://gitee.com/fssssss/KuiperCourse.gitgitcheckoutfouth 關(guān)鍵詞: 是否已經(jīng) 卷積算子 激活函數(shù) 相關(guān)新聞 自制深度學(xué)習(xí)推理框架-實(shí)現(xiàn)我們的第一個(gè)算子Relu-第三課(2023-01-02) 天天熱議:2023犯太歲的生肖有哪幾個(gè)生肖 你上榜了沒有(2023-01-02) 環(huán)球熱議:feel英語怎么讀 單詞feel怎么讀(2023-01-01) 世界觀焦點(diǎn):安徽合肥中歐班列2022年發(fā)運(yùn)768列 較上年凈增100列(2023-01-01) 健康元(600380)12月30日主力資金凈賣出452.69萬元(2022-12-31) 環(huán)球今日訊!首創(chuàng)證券: 股票交易異常波動(dòng)公告(2022-12-30) 環(huán)球通訊!加碼布局95后興趣消費(fèi),廣發(fā)有魚卡潮系列力拓年輕化金融生態(tài)(2022-12-30) 世界快看:黃健翔曬貝利和馬拉多納多年前的青澀合照悼念:兩代球王,天堂重聚(2022-12-30) 國(guó)家統(tǒng)計(jì)局:2021年全國(guó)文化及相關(guān)產(chǎn)業(yè)增加值占GDP比重為4.56%(2022-12-30) 環(huán)球快訊:廣發(fā)e秒貸網(wǎng)貸逾期后會(huì)被催收嗎(2022-12-30) 全年招引投資億元以上產(chǎn)業(yè)項(xiàng)目100個(gè) 廣安2023年將實(shí)施重點(diǎn)項(xiàng)目“雙百工程”(2022-12-29) 天天時(shí)訊:皖新傳媒(601801.SH):董事長(zhǎng)吳文勝辭職(2022-12-29) 觀熱點(diǎn):臻有錢貸款逾期8年延遲還款影響征信嗎(2022-12-29) 世界短訊!海爾生物: 技術(shù)、場(chǎng)景雙軌驅(qū)動(dòng)下 持續(xù)踐行“社會(huì)創(chuàng)新”責(zé)任(2022-12-29) 今日熱訊:南微醫(yī)學(xué)(688029)12月28日主力資金凈買入431.82萬元(2022-12-29) 天天精選!橘子橙子柑的區(qū)別?(2022-12-29) 德爾姚紅鵬:認(rèn)清現(xiàn)實(shí),聚焦價(jià)值,向陽而行(2022-12-28) 世界動(dòng)態(tài):2022曲阜尼山圣境國(guó)慶防疫要求(2022-12-28) 今日起鄭州將發(fā)放2.5億元消費(fèi)券(2022-12-28) 財(cái)達(dá)證券擬定增募資50億元,今年以來多家券商增資“補(bǔ)血”(2022-12-28) 長(zhǎng)鴻高科(605008.SH):A股定增申請(qǐng)獲證監(jiān)會(huì)受理(2022-12-27) 全球快資訊丨百亞股份(003006)12月27日主力資金凈買入427.64萬元(2022-12-27) 環(huán)球速讀:券商觀點(diǎn)|房地產(chǎn)行業(yè)周報(bào):受疫情影響新房、二手房成交同比降幅明顯擴(kuò)大 多部門發(fā)文支持行業(yè)平穩(wěn)發(fā)展(2022-12-27) 外匯天眼:美國(guó)11月核心PCE物價(jià)指數(shù)年率錄得4.7%(2022-12-26) 當(dāng)前簡(jiǎn)訊:報(bào)告:2023年北京辦公樓需求有望重啟(2022-12-26)