實(shí)踐教程|卷積神經(jīng)網(wǎng)絡(luò) C++ 從零開始實(shí)現(xiàn)

極市導(dǎo)讀
?目前搭建卷積神經(jīng)網(wǎng)絡(luò)(CNN)一般直接用Pytorch、Tensorflow等深度學(xué)習(xí)框架,很簡單。但如果是手寫反向傳播過程,情況就比BP網(wǎng)絡(luò)復(fù)雜多了,因?yàn)椴粌H僅是矩陣相乘。本文詳解了作者從零開始用c++實(shí)現(xiàn)CNN的過程,附詳細(xì)代碼介紹。?>>加入極市CV技術(shù)交流群,走在計(jì)算機(jī)視覺的最前沿
目前搭建卷積神經(jīng)網(wǎng)絡(luò)(CNN)一般直接用 Pytorch、Tensorflow 等深度學(xué)習(xí)框架,很簡單。但如果是手寫反向傳播過程,情況就比 BP 網(wǎng)絡(luò)復(fù)雜多了,因?yàn)椴粌H僅是矩陣相乘。
目標(biāo)是,從零開始實(shí)現(xiàn) CNN。
剛開始,本人搜網(wǎng)上的卷積神經(jīng)網(wǎng)絡(luò)反向推導(dǎo)的相關(guān)博客,發(fā)現(xiàn)了幾個(gè)問題:
公式看的實(shí)在腦袋疼,不好理解,一大堆的 ,變量還特別多,最后自己實(shí)現(xiàn)才發(fā)現(xiàn),卷積的時(shí)間復(fù)雜度還挺高,好幾層 for; 卷積層的反向傳播,從輸出回傳的梯度 ,求輸入的梯度 存在一個(gè)權(quán)重矩陣 rot180 的操作,而且還需要對梯度 填充 padding 的問題,見卷積神經(jīng)網(wǎng)絡(luò)(CNN)反向傳播算法 - 劉建平Pinard - 博客園:https://www.cnblogs.com/pinard/p/6494810.html(劉建平老師的博客強(qiáng)烈推薦),如下

這個(gè)例子沒有錯(cuò),但只是一種特殊情況,如果步長 stride 大于 1,就不僅僅是外圍填充 0 了,還需要對 數(shù) 據(jù)之間也做填充 0,具體過程和轉(zhuǎn)置卷積的前向過程一模一樣。但即使真的可以這樣做,寫對了,做 padding 消耗也是很大的,假設(shè) stride = 2,則大約有 的計(jì)算都是跟 0 做乘法,是無意義的計(jì)算,個(gè)人以為不可取,個(gè)人改用了其他思路。
后續(xù)一步步實(shí)現(xiàn),遇到的也不僅僅這兩個(gè)問題,一一克服,整個(gè)過程的關(guān)鍵就是——硬著頭皮,老老實(shí)實(shí)寫,別看公式。
這也是本人一直以來的夙愿,終于實(shí)現(xiàn)。整個(gè)過程中,又回顧了一些 C++ 的坑與優(yōu)化技巧,對卷積的前向以及后向過程和如何搭建深度學(xué)習(xí)流程有了更清晰的認(rèn)識(shí),收獲頗豐。
提綱
卷積神經(jīng)網(wǎng)絡(luò)(一)tensor 定義:https://zhuanlan.zhihu.com/p/463673933
卷積神經(jīng)網(wǎng)絡(luò)(二)從圖像到 tensor:https://zhuanlan.zhihu.com/p/468161119
卷積神經(jīng)網(wǎng)絡(luò)(三)ReLU 層:https://zhuanlan.zhihu.com/p/468161821
卷積神經(jīng)網(wǎng)絡(luò)(四)池化層:https://zhuanlan.zhihu.com/p/468163843
卷積神經(jīng)網(wǎng)絡(luò)(五)卷積層:https://zhuanlan.zhihu.com/p/468164733
卷積神經(jīng)網(wǎng)絡(luò)(六)Linear 線性層:https://zhuanlan.zhihu.com/p/468165951
卷積神經(jīng)網(wǎng)絡(luò)(七)搭建 CNN 網(wǎng)絡(luò)結(jié)構(gòu):https://zhuanlan.zhihu.com/p/469475509
卷積神經(jīng)網(wǎng)絡(luò)(八)訓(xùn)練 CNN:https://zhuanlan.zhihu.com/p/468177334
代碼
https://github.com/hermosayhl/CNN
環(huán)境
Windows 11 >=C++17(TDM GCC 10.3.0:https://jmeubank.github.io/tdm-gcc/download/) OpenCV 4.5.2 構(gòu)建工具 Cmake
數(shù)據(jù)集
采用的小型圖像分類數(shù)據(jù)集,從 cat-dog-panda:https://www.kaggle.com/ashishsaxena2209/animal-image-datasetdog-cat-and-panda 數(shù)據(jù)集剔除 cat(cat 和 dog 相對比較難),然后又從 CUB-200 bird:http://www.vision.caltech.edu/visipedia/CUB-200.html 數(shù)據(jù)集中隨機(jī)抽出 1000 張鳥類圖像,湊成三分類的小型數(shù)據(jù)集。train : valid : test 比例 8:1:1。
網(wǎng)絡(luò)模型
本人也不知道是什么網(wǎng)絡(luò)結(jié)構(gòu),隨便設(shè)計(jì)的(能跑就行),只有卷積層、最大池化層、ReLU 層、Softmax 層、Linear 全連接層,比 AlexNet 要簡單,接受的輸入大小是 224x224x3,輸出 3 個(gè)值,經(jīng)過 softmax 得到概率,損失函數(shù)是交叉熵,優(yōu)化方法是 SGD 隨機(jī)梯度下降,最終在測試集上大概可以達(dá)到 0.91 的準(zhǔn)確率,不高,但至少跑通了。



后面雖然也寫了 BatchNorm 層、DropOut 層,訓(xùn)練是沒問題的,這倆的前向和反向傳播都對,但 valid 和 test 階段,過擬合了。。。按照網(wǎng)上諸多說法嘗試,但都失敗了,遺留問題。
后面還嘗試了 Grad-CAM 可視化神經(jīng)網(wǎng)絡(luò),實(shí)現(xiàn)跟論文里的細(xì)節(jié)些許不一樣,例子如下,分類為 bird

公眾號(hào)后臺(tái)回復(fù)“數(shù)據(jù)集”獲取30+深度學(xué)習(xí)數(shù)據(jù)集下載~

#?CV技術(shù)社群邀請函?#

備注:姓名-學(xué)校/公司-研究方向-城市(如:小極-北大-目標(biāo)檢測-深圳)
即可申請加入極市目標(biāo)檢測/圖像分割/工業(yè)檢測/人臉/醫(yī)學(xué)影像/3D/SLAM/自動(dòng)駕駛/超分辨率/姿態(tài)估計(jì)/ReID/GAN/圖像增強(qiáng)/OCR/視頻理解等技術(shù)交流群
每月大咖直播分享、真實(shí)項(xiàng)目需求對接、求職內(nèi)推、算法競賽、干貨資訊匯總、與?10000+來自港科大、北大、清華、中科院、CMU、騰訊、百度等名校名企視覺開發(fā)者互動(dòng)交流~

