2020.12.28晚記
寫在前面
今天驗收完圖像處理課程的結(jié)課課題——建筑材料識別課題了。晚上決定趁熱打鐵,記錄一下完成這次課題的全過程,還有一點自己的收獲和感悟吧。自己也想要好好地對自己的這次完成情況做一次梳理。這篇博客算是一個驗收后的回顧與總結(jié),也算是提前為正式寫課題報告擬個提綱,或者說,把做過的事情,總結(jié)的經(jīng)驗都先歸納起來,到時候方便寫報告。當然,如果能對同樣剛剛?cè)腴T目標檢測的朋友能有所幫助的話,那就更好了。
其實這也是我們專業(yè)的一個比賽,應用越新的網(wǎng)絡越能夠在保證高精度的情況下獲得更高速度的檢測能力。比如周圍的同學很多使用的其實都是YOLOv5的目標檢測算法。也許是覺得大家都選擇一樣的網(wǎng)絡,那么所有的競爭點都在調(diào)整參數(shù)上了,還有一點是自己覺得這一次的比賽得不得獎并不是最重要的,學習目標檢測算法(畢竟這學期才接觸機器學習),學習訓練網(wǎng)絡,理解其算法背后的理論和意義才是最重要的。所以最終我們組并沒有選擇YOLOv5,而是選擇了2017年年底提出的擁有經(jīng)典one-stage檢測模型和高檢測精度,但是檢測速度較慢的Retinanet目標檢測算法。Retinanet其實不是我們原來決定的最終拿去驗收的算法,而是我們選定的入門目標檢測的算法。在Retinanet之前其實也有很多目標檢測算法,one-stage的,two-stage的,之后也有很多新的優(yōu)秀的目標檢測算法,為什么選擇Retinanet作為入門學習的算法,將在下面具體論述。那為什么最后還是拿運行速度并不夠快的Retinanet算法去驗收了呢?這其實比較意外。我們在了解并實現(xiàn)Retinanet之后,也發(fā)現(xiàn)了其運行速度慢的問題,于是去尋找提升速度的改進方案。最后看到了一張性能對比圖,發(fā)現(xiàn)Efficiendet的運行速度會快得多而且檢測精度也很高。最重要的是,Efficiendet其實是以Retinanet的結(jié)構(gòu)為baseline對其特征提取部分和特征加強部分進行進一步優(yōu)化的網(wǎng)絡,所以基本結(jié)構(gòu)非常相似。但是當我們具體實現(xiàn)之后,確實發(fā)現(xiàn)這個網(wǎng)絡loss很小,檢測精度很高,可惜的是,在我的電腦上跑的預測速度是Retinanet的幾乎三倍。所以最后還是把訓練得比較好的Retinanet拿去驗收了。
這里有一點需要提一下。作為僅上過幾節(jié)機器學習的介紹課,僅僅用CNN做過手寫數(shù)字識別的入門小白來說,對于復雜的目標檢測網(wǎng)絡的入門,找到一個好的領路人特別重要。幸運的是,當前人工智能算法的研究也是實火,CSDN及很多平臺都有非常好的入門資料以及算法實現(xiàn)的介紹,可以說,對于機器學習的入門小白來說,領路人有千千萬。而對于我,我是跟著一個博主[Bubbliiiing](https://blog.csdn.net/weixin_44791964/article/list/1)來學習的。這個博主會發(fā)詳細的算法實現(xiàn)介紹,并且在B站上傳了對應網(wǎng)絡實現(xiàn)的博客講解視頻(B站也是同名),有博客還有視頻講解,還有算法實現(xiàn)的代碼和預訓練權(quán)重都可以在博主提供的github及百度網(wǎng)盤鏈接下載到。我在此次課題的學習過程中,一共跟著博主學習并實現(xiàn)了Retinanet、Efficiendet、YOLOv4這三個網(wǎng)絡的Keras實現(xiàn)。此外,自己還額外實現(xiàn)了Yolov5(跟著CSDN上面的大神們走的)。上面提到的博主一般會對一個算法提供Keras、TensorFlow以及PyTorch三個實現(xiàn)版本,有助于我們比較學習。而且,這個博主寫的代碼對應工程文件的架構(gòu)都差不多,在實現(xiàn)一個網(wǎng)絡之后,很快也就知道了怎么實現(xiàn)另一個網(wǎng)絡(這里指的是理解代碼,完成訓練及預測的步驟,并不是自己編寫出代碼啦)還有,我這次的學習記錄中也用到了該博主博客中部分的圖片。
提前預警一下,這篇博客不是課題報告而是學習記錄,所以可能會有很多啰嗦的大白話記錄自己的感受和思考。這一過程確實做了很多事情,不管是在具體的代碼上還是理論的理解學習上,所以應該也會分集來寫。此外,自己不是以比賽的思路來做的(直接選擇最新的效能最好的算法來訓練數(shù)據(jù)),而是以學習目標檢測的思路來完成這個課題的,所以會循序漸進來介紹自己學習的網(wǎng)絡。內(nèi)容包括網(wǎng)絡結(jié)構(gòu)理解到具體程序部分(自己同時也在學習Python),并且涉及到很多基礎內(nèi)容。
還有,我也是剛剛?cè)腴T,如果文中有哪里描述不當?shù)模蚕M髀反髠b能多多指教!當然有朋友按照我的步驟走出現(xiàn)問題的,歡迎大家來找我一起交流啊~~
好了,說了這么多,終于可以開始進入正題。
一、課題介紹
1、背景說明
建筑工地使用的建筑材料,如條狀鋼筋、鋼筋圈一般堆放于露天的碼垛,以往需要人工點數(shù)估計庫存情況,并根據(jù)每日用量估計及時補充庫存。人工盤點庫存的方式費工費力、勞動強度大、效率低。基于上述原因,擬采用信息化技術代替人工,實現(xiàn)自動估計建筑材料數(shù)量的目的。
2、任務
主辦方將提供訓練模型的圖片數(shù)據(jù)集,該數(shù)據(jù)集由固定的監(jiān)控攝像頭在建筑工地現(xiàn)場拍攝,數(shù)據(jù)集中主要包含鋼筋圈,鋼筋條及砌體等三種建筑材料,如下圖所示:
參賽團隊需要設計深度學習模型,通過上述數(shù)據(jù)的訓練使模型能夠正確識別鋼筋條,鋼筋圈及砌體三種建筑材料,并對圖片中出現(xiàn)的材料個數(shù)進行計數(shù),其中鋼筋圈和砌體的計數(shù)單位均為個,而鋼筋條的計數(shù)單位為捆。
3、數(shù)據(jù)集說明
訓練圖像集包含鋼筋條、鋼筋圈及砌體等建筑材料,每種提供500幅的經(jīng)過預處理的實拍圖像(場地攝像頭位置沒有變化,建筑材料擺放在不同位置拍攝的代表性圖像),共1500副圖像供各參賽隊研究使用,可以使用OpenCV、MATLAB或其他實驗環(huán)境進行研究,其groundtruth文件為shape groundtruth.txt。測試集包括三種建筑材料各200副圖,比賽期間不提供給參賽隊,只在測試時供各參賽隊測試算法性能時使用。
實際情況:一共提供了884張圖片,分為第一批和第二批。第二批圖片的標簽是我們可以直接輸入網(wǎng)絡訓練的標簽(含目標框的位置信息和類別信息),第一批的標簽只有物體的數(shù)量及對應類別的信息,我們自己使用labelimg進行第一批圖片目標框的標注,得到對應的.xml標簽文件。
課題分析:該課題其實就是目標檢測問題。先對圖片中的存在目標進行定位和分類,然后對圖片中的所有目標框進行計數(shù),就得到了每張圖片中物體的類別和數(shù)量。然后按照格式(我們驗收要的文件格式)將檢測結(jié)果(具體某張圖片的類別及數(shù)量)放入一個txt文件。最后通過檢測這個txt文件獲得目標檢測的AP值和Error rate。一開始第一批數(shù)據(jù)的標簽如何利用,一直沒想明白,在初期,它起到的作用僅僅是對照著檢查自己標記的數(shù)量是否符合官方的認定(去詢問了助教,助教提到了弱監(jiān)督的問題,但是在網(wǎng)上查找了一下,都只有理論介紹,并沒有具體的代碼實現(xiàn)可以參照,于是該思路也就擱置了),而在后期,就有了一點其他的似乎可執(zhí)行的想法,這一點放到后面來說。
2020.12.29下午記
二、環(huán)境配置
要進行深度學習網(wǎng)絡的訓練,不管是使用Tensorflow還是Keras還是Pytorch實現(xiàn),很重要的一個環(huán)節(jié)就是環(huán)境配置,Python的開源庫一直都在更新?lián)Q代,所以很可能會出現(xiàn)版本不兼容的問題。這也就再次體現(xiàn)了跟著上面那個博主進行不同網(wǎng)絡的實現(xiàn)學習的好處了,該博主每個網(wǎng)絡的三個版本需要的庫版本都是固定的,所以不需要在實現(xiàn)不同網(wǎng)絡的時候更換環(huán)境,變動需要的包的版本。
在這次課題的完成過程中,我主要選擇的是用Keras實現(xiàn),而在YOLOv5的實現(xiàn)中,使用的是Pytorch(因為官方的實現(xiàn)版本只有Pytorch的)。為什么選擇Keras呢?理由很簡單,因為它對入門的小白來說真的很友好,代碼可讀性很高,容易理解。在我完整地研究透徹Retinanet的keras代碼之后,再去看Efficiendet的代碼,很快就能看懂了。(一方面也是因為Efficiendet是以Retinanet為baseline進行優(yōu)化和改進的吧,所以整體架構(gòu)差不多,只是多了一些tricks來強化,這個也放后面再具體介紹)。
1、深度學習框架選擇
配置環(huán)境前,首先要選好搭建網(wǎng)絡的工具。用不同的工具,需要配備不同的包。那么,Keras,TensorFlow,Pytorch這三個熱門的深度學習框架要選擇哪個好?
Keras:Keras是一個高層神經(jīng)網(wǎng)絡API,Keras由純Python編寫而成并基TensorFlow、Theano以及CNTK后端。所以我們也可以直接使用TensorFlow調(diào)用Keras。它以其易用性和語法簡單性而受到青睞,有助于快速開發(fā)。
以下是從Keras中文文檔中的摘錄:
Keras的設計原則:
用戶友好:用戶的使用體驗始終是我們考慮的首要和中心內(nèi)容。Keras遵循減少認知困難的最佳實踐:Keras提供一致而簡潔的API, 能夠極大減少一般應用下用戶的工作量,同時,Keras提供清晰和具有實踐意義的bug反饋。
模塊性:模型可理解為一個層的序列或數(shù)據(jù)的運算圖,完全可配置的模塊可以用最少的代價自由組合在一起。具體而言,網(wǎng)絡層、損失函數(shù)、優(yōu)化器、初始化策略、激活函數(shù)、正則化方法都是獨立的模塊,你可以使用它們來構(gòu)建自己的模型。
易擴展性:添加新模塊超級容易,只需要仿照現(xiàn)有的模塊編寫新的類或函數(shù)即可。創(chuàng)建新模塊的便利性使得Keras更適合于先進的研究工作。
與Python協(xié)作:Keras沒有單獨的模型配置文件類型(作為對比,caffe有),模型由python代碼描述,使其更緊湊和更易debug,并提供了擴展的便利性。
Keras中文文檔
TensorFlow:作為Google開發(fā)維護的深度學習工具,TensorFlow應該是目前最為流行和使用率最高的深度學習計算框架了。它是用C ++ / Python編寫的,提供Python,R、Java,Go和Java API。TensorFlow雖然很棒,但對于初學者來說并不友好,初學者用TensorFlow來搭建神經(jīng)網(wǎng)絡需要一個思維轉(zhuǎn)變,總體來說TensorFlow沒那么容易。
Pytorch:PyTorch是一款可以媲美于 TensorFlow 優(yōu)秀的深度學習計算框架,但又相比于 TensorFlow 在語法上更具備靈活性。PyTorch原生于一款小眾語言lua,而后基于python 版本后具備了強大的生命力。作為一款基于 python 的深度學習計算庫,PyTorch提供了高于 numpy 的強大的張量計算能力和兼具靈活度和速度的深度學習研究功能。
基于以上的資料,我最終選擇了Keras,Keras具備搭建神經(jīng)網(wǎng)絡各個零部件高度集成的API,對新手非常友好。也許Pytorch和TensorFlow程序運行的速度確實比Keras更快,但是基于入門學習的循序漸進來看,我最終還是選擇了Keras。當然,等到通過Keras入門深度學習了,還是需要再去學習一下其他的工具的。
參考資料:
[深度學習框架的比較:Keras vs Tensorflow vs Pytorch]
https://my.oschina.net/u/4047540/blog/4481723
https://www.sohu.com/a/297453670_455817
2、相關包的安裝
我們小組是一人在Ubuntu18.04上實驗,一人在Windows進行實驗,但是相關包的配置環(huán)節(jié)都差不多。整體搭配是Anaconda+Pycharm。Anaconda用來幫助進行不同環(huán)境的包管理,這一點我看很多博主說是非常好用的。不同的工程可能需要不同的環(huán)境,當然你也可以把所有需要的包放在同一個環(huán)境下,但這樣就會顯得很雜亂,而且有時候不同的程序需要的同一個包的版本還不同,所以最好還是選擇Anaconda來進行環(huán)境管理,我們可以創(chuàng)建不同的環(huán)境,并根據(jù)需要在不同的環(huán)境中配備不同的包。而Pycharm也是一款非常好用而且友好的編程IDLE。
上面提到的博主的Keras實現(xiàn)需要的包及版本:
keras實現(xiàn)代碼對應的tensorflow版本為1.13.2,keras版本是2.1.5。
如果使用GPU進行訓練的話,需要安裝tensorflow-gpu==1.13.2
注意由于h5py庫的更新,安裝過程中會自動安裝h5py=3.0.0以上的版本,會導致decode(“utf-8”)的錯誤!所以一定要在安裝完tensorflow后利用命令裝h5py=2.10.0!
(剛剛?cè)タ戳诉@個鏈接才發(fā)現(xiàn)博主更新的這個問題,之前沒看博客就去直接安裝對應版本的包了,后來去驗收的機子上配置環(huán)境的時候一直出現(xiàn)這個錯誤,還是查了好久最后在貼吧找到的答案......)
安裝包的話,可以直接在Pycharm中的setting處在指定環(huán)境下安裝,也可以打開cmd執(zhí)行語句:
conda activate +環(huán)境名
pip install +包名稱==對應版本號 或 conda install + 包名稱==對應版本號
(語句后面還可以指定鏡像源進行下載,一般使用鏡像源下載會快一點點吧,但是網(wǎng)絡經(jīng)常斷連,我們?nèi)ソo測試的機子配置環(huán)境的時候整整裝了一個晚上,就是因為網(wǎng)絡太差,一直安裝不上包......)
3、GPU的配置
這里分享一下最開始無知的我做了什么傻事吧......之前就有看到一些博客說訓練神經(jīng)網(wǎng)絡最好使用GPU,速度會比較快。但是!之前做手寫數(shù)字識別的時候用CPU跑的速度還是可以的,所以,我也不想那么麻煩,一開始就沒管。最關鍵的是,同一組的同學在Ubuntu上配置GPU的時候直接黑屏自動關機了,后來再開電腦就一直進不去Ubuntu,只好重裝Ubuntu系統(tǒng)。嚇得我...直接放棄在Ubuntu配置,當然,windows也不敢配置了...于是我就這么興沖沖地在把需要的包配置好后,開始跟著博主的指導進行訓練,但是速度是真的慢,我的電腦開了整整一天才訓練十三輪...當然我一開始并沒有在電腦設置不睡眠,非常期待地跑去睡覺然后非常期待地起床后,發(fā)現(xiàn)我在睡覺后電腦也睡了...而且在路途的運輸過程中電腦合上的時候也沒法進行訓練。就這樣斷斷續(xù)續(xù)地運行了十三輪(超過最開始的凍結(jié)某些參數(shù)的總輪數(shù)了),我終于放棄,停止程序,準備配置GPU。只是沒想到,這個第十三輪的模型我一直都保留著,因為這比起之后我用GPU訓練但是訓練不到參數(shù)解凍后的模型,效果好太多!
那么為什么用GPU來訓練網(wǎng)絡速度會快呢?
在此之前,我只知道CPU,并不了解GPU,GPU是做什么的?
GPU(Graphics processing unit),中文全稱圖形處理器。
GPU(圖形處理器)是圖形系統(tǒng)結(jié)構(gòu)的重要元件,是連接計算機和顯示終端的紐帶。一個光柵顯示系統(tǒng)離不開圖形處理器(GPU)。 應該說有顯示系統(tǒng)就有圖形處理器,但是早期的顯卡只包含簡單的存儲器和幀緩沖區(qū),它們實際上只起了一個圖形的存儲和傳遞作用,一切操作都必須由CPU來控制。這對于文本和一些簡單的圖形來說是足夠的,但是當要處理復雜場景特別是一些真實感的三維場景,單靠這種系統(tǒng)是無法完成任務的。所以后來發(fā)展的顯卡都有圖形處理的功能。它不單單存儲圖形,而且能完成大部分圖形功能,這樣就大大減輕了CPU的負擔,提高了顯示能力和顯示速度。
圖形處理器可單獨與專用電路板以及附屬組件組成顯卡,或單獨一片芯片直接內(nèi)嵌入到主板上,或者內(nèi)置于主板的北橋芯片中,現(xiàn)在也有內(nèi)置于CPU上組成SoC的。個人電腦領域中,在2007年,90%以上的新型臺式機和筆記本電腦擁有嵌入式繪圖芯片,但是在性能上往往低于不少獨立顯卡。
(摘自https://zhuanlan.zhihu.com/p/106669828)
GPU非常適合并行計算,并且神經(jīng)網(wǎng)絡是高度并行的(神經(jīng)網(wǎng)絡又無數(shù)的卷積運算構(gòu)成),而這就是為什么深度學習要使用它們。深度學習和神經(jīng)網(wǎng)絡的每個計算任務都是獨立于其他計算的,任何計算都不依賴于任何其他計算的結(jié)果,可以采用高度并行的方式進行計算。而GPU相比于CPU擁有更多獨立的大吞吐量計算通道,較少的控制單元使其不會受到計算以外的更多任務的干擾,擁有比CPU更純粹的計算環(huán)境,所以深度學習和神經(jīng)網(wǎng)絡模型在GPU的加持下會更高效地完成計算任務。
接下來就是配置GPU環(huán)境的總過程了。
主要參考:https://blog.csdn.net/weixin_44791964/article/details/104702142
博主使用的是tensorflow-gpu=1.13.2,因此會用到cuda10.0,與cuda10.0對應的cudnn是7.4.1.5,這個組合博主也試驗過了,絕對是可以用的。
還有一點注意的是,我查了一些其他的博客,很多博主都說不要用cuda10.1。
當然,要使用GPU,電腦要配備有獨立顯卡,可以通過
此電腦-->屬性-->設備管理器-->顯示適配器 進行查看
還可以通過英偉達控制面板查看獨立顯卡的具體信息
步驟如下:
(1)下載cuda及cudnn
(下載什么東西都最好下載到全英文的路徑下,不是全英文容易出問題)
(2)打開cuda_10的exe文件進行安裝
此處選擇自定義
下面的做法跟博主博客里面講的略有不同,如果全都勾選的話,就包含Visual Studio Integration,而一旦勾選這個,后面就會顯示下載不成功。而且CSDN上很多博主也都說不需要下載Visual Studio Integration這一項。至于后面的Driver components和Other components,我并不了解他們的作用,以防萬一還是下載了。這么做最后都挺順利的。
(3)安裝完后在C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.0可以找到根目錄。
把最開始下載的壓縮包進行解壓
把解壓后的四個文件放到上述C盤的目錄下
這樣就OK了。使用這個方法,不需要像其他的博客里面說到的改變環(huán)境變量什么的,就直接可以運行了。安裝完后,訓練的時候默認會使用GPU進行訓練。以下有幾個方法可以證明GPU驅(qū)動程序安裝完畢。
方法一:新建一個,py文件,運行如下代碼:
import tensorflow as tf
a = tf.constant([1.2, 2.3, 3.6], shape=[3], name='a')
b = tf.constant([1.2, 2.3, 3.6], shape=[3], name='b')
c = a + b
session = tf.Session(config=tf.ConfigProto(log_device_placement=True))
print(session.run(c))
如果出現(xiàn)下面的結(jié)果,就說明上面的安裝沒有問題
方法二:運行train.py文件,在訓練的時候
第一是查看執(zhí)行窗是否出現(xiàn)GPA的相關信息,如下所示可以看到我的電腦顯存是2G
第二還可以打開任務管理器,查看GPU的工作情況,如下圖所示,GPU1一直有在工作中
而平常不訓練的時候,是下面這樣的
最最明顯的是,如果使用GPU進行訓練,會發(fā)現(xiàn)訓練速度大大提升,基本上很快一個epoch就走完了,進度條會一直有變化。
不得不說,當我配置成功運行的時候,看到那快速變化的進度條,真的太激動了!!!
所以說還是要用于嘗試呢!!
這里還得提醒大家,在用GPU進行訓練的時候,電腦一定要插著電,訓練網(wǎng)絡實在是耗費電腦資源,最開始的時候我并不清楚,就沒有插電,沒過多久,電腦突然黑屏了!!之前我的電腦就出過一點小問題,我還以為是使用GPU導致了什么故障了,會不會windows被我跑崩了,我都準備做好最壞的打算再次去找惠普售后預約時間了...當時同一組的趙同學問是不是電腦沒電了,我總覺得沒那么簡單,畢竟我就是看它的電量還很充足所以沒一邊充電一邊運行的!!當時還在助教的辦公室,辦公室里也沒有別的插座,最后我去了一樓的保安室試著接通電源。謝天謝地,還真只是因為沒電了才黑屏,真是嚇死我了!!
對于本機的GPU配置和相關包的安裝其實已經(jīng)梳理完了。但是后來我們在訓練的時候,由于我的輕薄本顯存只有2G,實在是太弱小了,而且訓練的圖片數(shù)量很多,分辨率也都很高,參數(shù)量太大,所以訓練的batch size只能調(diào)個2或者4(對GPU來說,batch size設置為2的次方數(shù)有利于它運行),一到8就內(nèi)存溢出了。我們的epoch分為兩輪,第一輪凍結(jié)了某些參數(shù),第二輪把之前凍結(jié)的參數(shù)解凍了參與訓練,一到第二輪,即使是batch size=2的情況,投入全部的數(shù)據(jù)集(884張),也內(nèi)存溢出了。而如果不參與解凍后的epoch,只取前面訓練時保存的模型,效果還不如之前用CPU訓練的第十三輪的數(shù)據(jù)。
因此,我們決定采用老師分享到群里的解決辦法:薅一把Google的羊毛!羊毛可以免費薅,但是需要爬個好的梯子出去才薅得到。其實就是使用Google的Colabratory鏈接谷歌云盤,使用Google的服務器,享受免費且強大的16G顯存在線進行訓練。聽起來真的很棒啊,我們決定試一試!
小記:
第一次寫這么長的博文,
從下午三點寫到晚上八點多了,
但是發(fā)現(xiàn)越寫越有干勁,也不餓,
真是奇怪。
堅持看到這里的朋友們都是了不起的好漢hhh。