畢業設計:基於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