基于CNN的貓狗品種識別技術研究

  • 總體方案


    image.png
  • 研究背景
    近年來,深度學習理論和技術都得到了迅速的發(fā)展,并且受到了越來越多的研究者的關注,深度學習技術在圖像識別領域具有廣泛的應用。尤其是在特征提取和建模上有著非常明顯的優(yōu)勢淺層對比模型。現在已經有了非常多的經典成熟模型,如AlexNet、VGG16、VGG19、GoogleLeNet、Inception-v3和ResNet等,但未必適用于所有的試驗數據集。本課題擬運用卷積神經網絡(CNN)對貓狗公開數據集進行分類識別,在較成熟的Resnet模型基礎上通過模型結構調整和參數尋優(yōu)等,設計出適用于本課題數據集的深度學習分類器。本課題的研究結論可充實貓狗數據集的分類模型庫,為后來者提供參考和借鑒。

  • 技術路線


    image.png
  • 實驗環(huán)境
    本實驗是在基于Anaconda的環(huán)境管理工具、PyTorch深度學習框架和Pycharm的編譯器上進行設計實現的。研究環(huán)境如下所示:
    (1) 軟件部分
    操作系統(tǒng):Windows10 64位系統(tǒng);
    開發(fā)工具:Pycharm、Anaconda;
    CUDA:10.2.89_441.22_win10;
    PyTorch:1.1.0;
    Torchvision:0.3.0;
    Pyyaml:0.1.7;
    Pillow:6.0.0;
    TensorboardX:2.0。
    (2) 硬件部分
    內存:16G;
    CPU:Inter i7-4720HQ 2.6GHz;
    GPU:GTX 950m(2G);
    硬盤:固態(tài)硬盤:128G、機械硬盤:1T。

  • 數據集
    本文采用的是Kaggle競賽的公開的貓狗數據集。本數據集可以從Kaggle官方網站中下載Dogs vs. Cats Redux: Kernels Edition。本數據集一共有貓和狗兩種種類的圖片。貓和狗的圖片各12500張。數據集中初始的各個圖片的大小和分辨率都是不一致的。如圖3-1中的cat.0.jpg的分辨率是500×374而圖3-2中的dog.1.jpg的分辨率是327×499。每張圖片的分辨率都是不同的,所以在之后數據集預處理中需要調整圖片的大小來統(tǒng)一圖片的分辨率。因為數據集中的圖片都為彩色RGB圖片,所以圖像的通道數為3通道。數據集中的圖像不一定完整包含完整的貓或狗的身體,有的主體在圖片中非常小,圖片背景也比較復雜,例如圖3-1中的cat.6.jpg中會出現人或者其他物體。


    image.png

    image.png

    通過調整圖片大小,水平翻轉,一定角度旋轉,添加噪聲,圖片歸一化對貓狗數據集進行預處理操作。


    image.png
  • 網絡模型


    image.png

    ResNet-18都是由BasicBlock組成,從圖4-2也可得知50層及以上的ResNet網絡模型由BottleBlock組成。在我們就需要將我們預處理過的數據集放入現有的Resnet-18和ResNet-50模型中去訓練,首先我們通過前面提到的圖像預處理把訓練圖像裁剪成一個96x96的正方形尺寸,然后輸入到我們的模型中,這里就介紹一下ResNet-18的網絡模型的結構,因為ResNet50與第五章的ResNet-34模型結構相仿。

    ResNet-18的模型結構為:首先第一層是一個7×7的卷積核,輸入特征矩陣為[112,112,64],經過卷積核64,stride為2得到出入特征矩陣[56,56,64]。第二層一開始是由一個3×3的池化層組成的,接著是2個殘差結構,一開始的輸入的特征矩陣為[56,56,64],需要輸出的特征矩陣shape為[28,28,128], 然而主分支與shortcut的輸出特征矩陣shape必須相同,所以[56,56,64]這個特征矩陣的高和寬從56通過主分支的stride為2來縮減為原來的一半即為28,再通過128個卷積核來改變特征矩陣的深度。然而這里的shortcut加上了一個1x1的卷積核,stride也為2,通過這個stride,輸入的特征矩陣的寬和高也縮減為原有的一半,同時通過128個卷積核將輸入的特征矩陣的深度也變?yōu)榱?28。第三層,有2個殘差結構,輸入的特征矩陣shape是[28,28,128],輸出特征矩陣shape是[14,14,256], 然而主分支與shortcut的輸出特征矩陣shape必須相同,所以[14,14,256]這個特征矩陣的高和寬從14通過主分支的stride為2來縮減為原來的一半即為7,再通過128個卷積核來改變特征矩陣的深度。然而這里的shortcut加上了一個1×1的卷積核,stride也為2,通過這個stride,輸入的特征矩陣的寬和高也縮減為原有的一半,同時通過256個卷積核將輸入的特征矩陣的深度也變?yōu)榱?56。第四層,有2個殘差結構,經過上述的相同的變化過程得到輸出的特征矩陣為[7,7,512]。第五層,有2個殘差結構, 經過上述的相同的變化過程得到輸出的特征矩陣為[1,1,512]。接著是平均池化和全連接層。
    image.png
    image.png
    image.png
  • 優(yōu)化和損失函數
    本次選擇隨機梯度下降法(SGD)進行優(yōu)化,具體操作階段,主要利用各樣本迭代更新1次,若樣本非常多,或許僅需一些樣本,便可以把theta迭代至最佳解,而批量梯度下降(BGD)迭代1次必然涉及十多萬樣本,也無法做到最優(yōu),若迭代10次,必須遍歷樣本10次,工作量過大。事實上,SGD也不完美,譬如噪音相比BGD更多,導致SGD各次迭代過程中,無法始終朝總體最優(yōu)推進。因此,即便訓練更加高效,但準確率降低,難以保證全局最優(yōu)。不置可否,就算有著相應隨機性,但是從期望上來看,它是等于正確的導數的。但是隨機梯度下降也有缺點:如果隨機梯度下降更新比較頻繁,可能會造成 cost function 有嚴重的震蕩。
    損失函數采用的是交叉熵損失函數(Cross Entropy Loss),交叉熵能夠衡量同一個隨機變量中的兩個不同概率分布的差異程度,在機器學習中就表示為真實概率分布與預測概率分布之間的差異。交叉熵的值越小,模型預測效果就越好。其計算公式為:
    cross_entropy=-∑_(k=1)^N?〖(p_k*log?〖q_k 〗)〗 (4-1)
    其中??表示真實值,在這個公式中是one-hot形式;??是預測值,在這里假設已經是經過softmax后的結果了。
    仔細觀察可以知道,因為??的元素不是0就是1,而且又是乘法,所以很自然地我們如果知道1所對應的index,那么就不用做其他無意義的運算了。所以在PyTorch代碼中target不是以one-hot形式表示的,而是直接用scalar表示。所以交叉熵的公式(m表示真實類別)可變形為:

cross_entropy=-∑_(k=1)^N?〖(p_k*log?〖q_k 〗 )=-log?〖q_m 〗 〗 (4-2)
仔細觀察,其實就是等同于log_softmax和nll_loss兩個步驟。所以PyTorch中的F.cross_entropy會自動調用上面介紹的log_softmax和nll_loss來計算交叉熵,其計算方式如下:

loss(x,class)=-log?〖((exp?(x[class]))/(∑_j?〖exp?(x[j])〗))〗 (4-3)
one-hot表示獨熱編碼,實踐操作階段,主要通過N位條件碼寄存器,面向N個狀態(tài)完成有效編碼,而各自均單獨存在對應寄存器位,無論哪個時候,始終僅是一位有效。Softmax 屬于1個“軟”的最大值函數,它不是直接取輸出的最大值那一類作為分類結果,同時也會考慮到其它相對來說較小的一類的輸出。換言之,Softmax 能夠把全連接層輸出直接映射為1個概率分布,由訓練角度出發(fā),核心宗旨在于使歸屬第k類各樣本得到 Softmax處理,第 k 類概率愈高愈好。如此一來,更有利于人們以統(tǒng)計學手段論證分類問題。
在實驗的過程中,采用基于PyTorch框架的tensorboardX方法來實現了train_loss, test_loss, test_loss_cat, test_loss_dog這些數據在訓練和測試的期間的loss的變化。

  • 結果展示


    image.png

    image.png
    image.png
    image.png
    image.png
    image.png
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內容