利用神經(jīng)網(wǎng)絡對常見水果進行分類
點擊下面卡片關注“AI算法與圖像處理”,選擇加"星標"或“置頂”
重磅干貨,第一時間送達
一個易于閱讀的神經(jīng)網(wǎng)絡指南,以實現(xiàn)高準確率
目的:為 Fruits360 尋找一個能夠達到最高分類準確率的神經(jīng)網(wǎng)絡模型。
深度前饋網(wǎng)絡
卷積神經(jīng)網(wǎng)絡
殘差神經(jīng)網(wǎng)絡(ResNet9)
準備工作
首先,讓我們來理解我們的數(shù)據(jù)集!
Kaggle Fruits360 數(shù)據(jù)集包含131種不同類型的水果和蔬菜的90483張圖像。首先,我們導入數(shù)據(jù)和所需的庫。
import torchimport osimport jovianimport torchvisionimport numpy as npimport matplotlib.pyplot as pltimport torch.nn as nnimport torchvision.models as modelsimport torch.nn.functional as Ffrom torchvision.datasets import ImageFolderfrom torchvision.transforms import ToTensorfrom torchvision.utils import make_gridfrom torch.utils.data.dataloader import DataLoaderfrom torch.utils.data import random_splitimport torchvision.models as models%matplotlib inline

使用matplotlib庫顯示彩色圖像:
import matplotlib.pyplot as pltdef show_example(img, label):print('Label: ', dataset.classes[label], "("+str(label)+")")plt.imshow(img.permute(1, 2, 0))

當我們使用PyTorch時,我們必須使用ToTensor將上述像素圖像轉換為張量:
dataset = ImageFolder(data_dir + '/Training', transform=ToTensor())img, label = dataset[0]print(img.shape, label)img

有3個通道(紅,綠,藍) ,100 * 100圖像大小。每個值表示顏色強度相對于通道顏色。
訓練和驗證數(shù)據(jù)集
接下來,我們將隨機分割數(shù)據(jù),得到3組數(shù)據(jù):
訓練集:訓練模型
驗證集:評估模型
測試集:測試模型的最終準確性
訓練數(shù)據(jù)集規(guī)模:57692
驗證數(shù)據(jù)集大小: 10,000
測試數(shù)據(jù)集的大小: 22,688
分批訓練
由于我們總共有57,692個訓練圖像,在使用 Dataloader 訓練模型之前,我們應該將圖像分成更小的批量。使用較小的數(shù)據(jù)集會減少內存空間,從而提高訓練速度。
對于我們的數(shù)據(jù)集,我們將設置 batch 為 128。

現(xiàn)在,我們將開始構建我們的模型。
1. 深度前饋網(wǎng)絡
超參數(shù):
結構:“5層(2000,1000,500,250,131)”
學習率:[0.01,0.001]
epoch:[10,10]
優(yōu)化器:隨機梯度下降
使用5層架構來訓練模型:
class FruitsModelFF(ImageClassificationBase):def __init__(self):super().__init__()self.linear1= nn.Linear(input_size, 2000)self.linear2= nn.Linear(2000, 1000)self.linear3= nn.Linear(1000,500)self.linear4= nn.Linear(500,250)self.linear5= nn.Linear(250, output_size)def forward(self, xb):out = xb.view(xb.size(0), -1)out= self.linear1(out)out=F.relu(out)out=self.linear2(out)out=F.relu(out)out=self.linear3(out)out=F.relu(out)out=self.linear4(out)out=F.relu(out)out=self.linear5(out)return out
在訓練前,驗證準確率為: 0.52734%


在以 [0.01,0.001] 學習率進行總共20個 epoch 的訓練之后,驗證準確率在96.84% 左右達到一個平穩(wěn)期。這與最初的0.52734% 相比是一個巨大的跳躍。
最后,讓我們用測試數(shù)據(jù)集來測試我們訓練過的模型
img, label = test[8000]plt.imshow(img.permute(1, 2, 0))print('Label:', dataset.classes[label], ', Predicted:', predict_image(img, model))

img, label = test[1002]plt.imshow(img.permute(1, 2, 0))print('Label:', dataset.classes[label], ', Predicted:', predict_image(img, model))

img, label = test[0]plt.imshow(img.permute(1, 2, 0))print('Label:', dataset.classes[label], ', Predicted:', predict_image(img, model))

我們的訓練模型正確地預測了上述所有水果。
Final test accuracy: 86.209%為了進一步提高我們的測試準確性,我們將使用一個通常比前饋神經(jīng)網(wǎng)絡性能更好的卷積神經(jīng)網(wǎng)絡神經(jīng)網(wǎng)絡。
ConvNet 能夠通過相關的濾波器成功地捕獲圖像中的空間和時間依賴關系。由于減少了參數(shù)的數(shù)量和權值的可重用性,該體系結構能夠更好地適應圖像數(shù)據(jù)集。換句話說,網(wǎng)絡可以通過訓練來更好地理解圖像的復雜性。
簡而言之,CNN 非常適合計算密集型的大尺寸圖像:
需要更少的參數(shù)
形成聯(lián)系的稀疏性
有能力檢測相似的模式,并應用在圖像的不同部分學到的特征
2. 簡單的卷積神經(jīng)網(wǎng)絡
簡要介紹一下 CNN 的特點:

內核上的權重首先隨機初始化為:
[0, 1, 2][2, 2, 0][0, 1, 2]
我們的示例圖片如下所示:
[3, 3, 2, 1, 0][0, 0, 1, 3, 1][3, 1, 2, 2, 3][2, 0, 0, 2, 2][2, 0, 0, 0, 1]
當我們將內核應用于示例圖像時,輸出將是:
[12., 12., 17.][10., 17., 19.][ 9., 6., 14.]
應用:

output= 2*0 + 2*1 + 3*2 + 0*2 + 2*2 + 2*0 + 0*0 + 0*1 + 1*2 = 14
對內核在樣本圖像上的每次移動重復輸出的計算,以獲取新的輸出大小。
def apply_kernel(image, kernel):ri, ci = image.shape # image dimensionsrk, ck = kernel.shape # kernel dimensionsro, co = ri-rk+1, ci-ck+1 # output dimensionsoutput = torch.zeros([ro, co])for i in range(ro):for j in range(co):output[i,j] = torch.sum(image[i:i+rk,j:j+ck] * kernel)return output
此外,通過應用最大池化層,我們逐漸減小了每個卷積層輸出張量的大小。

如前所述,卷積層增加了通道數(shù),而最大池化層減少了圖像大小。

現(xiàn)在,讓我們?yōu)橄嗤?Kaggle Fruit Dataset 建立 CNN 模型。
超參數(shù):
epoch:10
學習率:0.001
優(yōu)化器功能:Adam
class FruitsModel(ImageClassificationBase):def __init__(self):super().__init__()self.network = nn.Sequential(nn.Conv2d(3, 32, kernel_size=3, padding=1), #3 channels to 32 channelsnn.ReLU(),nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1),nn.ReLU(),nn.MaxPool2d(2, 2), # output: 64 channels x 50 x 50 image size - decreasenn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1),nn.ReLU(),nn.Conv2d(128, 128, kernel_size=3, stride=1, padding=1), #can keep the same, increase power of model , go deeper as u add linearity to non-linearitynn.ReLU(),nn.MaxPool2d(2, 2), # output: 128 x 25 x 25nn.Conv2d(128, 256, kernel_size=3, stride=1, padding=1),nn.ReLU(),nn.Conv2d(256, 256, kernel_size=3, stride=1, padding=1),nn.ReLU(),nn.MaxPool2d(5, 5), # output: 256 x 5 x 5nn.Flatten(), #a single vector 256*5*5,nn.Linear(256*5*5, 1024),nn.ReLU(),nn.Linear(1024, 512),nn.ReLU(),nn.Linear(512, 131))def forward(self, xb):return self.network(xb)
除了我們的模型中的一個變化,我們使用 Adam optimiiser 函數(shù),因為它是在分類問題中尋找最小成本函數(shù)的一個更有效的方法。
Final test accuracy rate: 92.571%我們實現(xiàn)了一個非常高的最終測試準確率,比前饋神經(jīng)網(wǎng)絡約高6% 。
3. 殘差神經(jīng)網(wǎng)絡(ResNet9)
超參數(shù):
最大學習率:0.01
epoch:10
優(yōu)化器:Adam
def conv_block(in_channels, out_channels, pool=False):layers = [nn.Conv2d(in_channels, out_channels, kernel_size=3, padding=1),nn.BatchNorm2d(out_channels),nn.ReLU(inplace=True)]if pool: layers.append(nn.MaxPool2d(2))return nn.Sequential(*layers)class ResNet9(ImageClassificationBase):def __init__(self, in_channels, num_classes):super().__init__()self.conv1 = conv_block(in_channels, 64)self.conv2 = conv_block(64, 128, pool=True)self.res1 = nn.Sequential(conv_block(128, 128), conv_block(128, 128))self.conv3 = conv_block(128, 256, pool=True)self.conv4 = conv_block(256, 512, pool=True)self.res2 = nn.Sequential(conv_block(512, 512), conv_block(512, 512))self.classifier = nn.Sequential(nn.MaxPool2d(4),nn.Flatten(),nn.Linear(4608, num_classes))def forward(self, xb):out = self.conv1(xb)out = self.conv2(out)out = self.res1(out) + outout = self.conv3(out)out = self.conv4(out)out = self.res2(out) + outout = self.classifier(out)return out
除此之外,我們也會推出「單周期學習率策略」,逐步提高學習率至使用者設定的最高值,然后逐步降至最低值。這種學習率的變化發(fā)生在每一個 epoch 之后。
相對較高的學習率會導致發(fā)散,而相對較低的學習率又會導致模型的過度擬合,因此很難找到合適的學習率。

然而,“單周期學習率策略”通過為我們的模型找到一個最優(yōu)學習率的范圍,克服了這個問題。

經(jīng)過一些修改,我們的最終測試準確度進一步提高了6% 。
總結:




在這3種模型中,ResNet9的測試準確率最高,達到98.85% 。
未來工作:
數(shù)據(jù)轉換(數(shù)據(jù)增強和歸一化)
遷移學習
數(shù)據(jù)集:https://www.kaggle.com/moltean/fruits
代碼鏈接:https://jovian.ml/limyingying2000/fruitsfinal
個人微信(如果沒有備注不拉群!) 請注明:地區(qū)+學校/企業(yè)+研究方向+昵稱
下載1:何愷明頂會分享
在「AI算法與圖像處理」公眾號后臺回復:何愷明,即可下載。總共有6份PDF,涉及 ResNet、Mask RCNN等經(jīng)典工作的總結分析
下載2:終身受益的編程指南:Google編程風格指南
在「AI算法與圖像處理」公眾號后臺回復:c++,即可下載。歷經(jīng)十年考驗,最權威的編程規(guī)范!
下載3 CVPR2021 在「AI算法與圖像處理」公眾號后臺回復:CVPR,即可下載1467篇CVPR 2020論文 和 CVPR 2021 最新論文
點亮
,告訴大家你也在看
