畢業設計:基於CNN的影像分類演算法

  • 2020 年 2 月 18 日
  • 筆記

近年來人工智慧越來越火,好像本科畢設不搞人工智慧都很丟人似的。但是普通本科生對於這個領域的了解顯然很少,基本也就是做做數據搜集、數據標註、工程實現、調調參的工作。

不過這也不錯,可以為以後碩士深造埋下伏筆,創造興趣,打好基礎。所以如果不讀碩的同學建議不要選這方面的題目。

這次我介紹的畢設題目是:基於卷積神經網路的影像分類演算法的工程實現。先說一下電腦配置和環境依賴版本。

聯想T480  8G記憶體  2G顯示記憶體  MX150顯示卡(支援GPU加速)  torch 1.3.1  cuda 10.2

我們首先選擇LeNet-5這個卷積神經網路的鼻祖來當做baseline。該網路發表於1998年,當年廣泛應用於美國銀行的數字識別。

當我們跑模型的時候,首先要選擇一個簡單並通用的網路來當做baseline,即知道這個問題的下限在哪裡。這樣方便以後我們選擇更複雜更通用的模型來持續優化效果。

數據集是這樣的。近五千張船舶圖片。船舶種類豐富,包括帆船、漁船、木舟、游輪、貨船、工作船、軍艦等。拍攝角度包括航拍、紅外影像、可見光影像、船上拍攝、船舶加海天背景等。其中軍艦影像佔50%,其他影像佔50%。該畢設問題即解決,區分軍艦和其他船舶的問題。

影像大致如下:

others.4.jpg

others.604.jpg

warship.214.jpg

transport.21.jpg

working.23.jpg

small.378.jpg

這是個二分類的問題。

接下來介紹LeNet-5的網路結構,如圖。

LeNet-5

這裡先介紹一個公式:

N = (W - F + 2P)/ S   +  1  W 輸入矩陣大小  F  卷積層、池化層的核大小  P  填充大小  S  移動步長  N  輸出矩陣大小

先貼上該網路的pytorch的程式碼實現。

class LeNet(BasicModule):      def __init__(self, num_classes=2):            super(LeNet, self).__init__()          self.model_name = 'LeNet'            self.conv1 = nn.Conv2d(3, 6, 5)          self.conv2 = nn.Conv2d(6, 16, 5)          self.fc1 = nn.Linear(16 * 53 * 53, 120)          self.fc2 = nn.Linear(120, 84)          self.fc3 = nn.Linear(84, num_classes)        def forward(self, x):          x = F.max_pool2d(F.relu(self.conv1(x)), (2, 2))          x = F.max_pool2d(F.relu(self.conv2(x)), 2)          x = x.view(x.size()[0], -1)          x = F.relu(self.fc1(x))          x = F.relu(self.fc2(x))          x = self.fc3(x)          return x

在原始論文中,網路結構如此。卷積層1 + 池化層2 + 卷積層3 + 池化層4 + 全連接層5、6、7。一共七層網路。原始論文中,圖片大小為33232,即長寬為32的三通道圖片。

而在本實驗中,因為原始圖片本身很大,在這裡我統一設置成了3224224的圖片。因此在網路中,最後一個池化層和全連接成對接的時候,需要注意大小

原始論文為:

self.fc1 = nn.Linear(16 * 5 * 5, 120)

我改為了:

self.fc1 = nn.Linear(16 * 53 * 53, 120)

可根據上面的公式自行計算。

根據不同參數,我進行了九次實驗,在驗證集上的表現如下:

Figure_1.png

有兩條線明顯效果很差,我們把它們排除,再看一下其他七次實現的情況。

Figure_2.png

從這裡可以清楚的看到七次實驗,驗證集上的變化情況。

一般調參,重要的參數無非是batch_size、學習率。從該曲線可以看出,當batch_size為32,學習率為0.001時,正確率最高。

隨後在測試集上表現如下:

image.png