Caltech 256是什麼?
Caltech 256數據集是加利福尼亞理工學院收集整理的數據集,該數據集選自Google Image數據集,並手工去除了不符合其類別的圖片。在該數據集中,圖片被分爲256類,每一個類別的圖片超過80張。網絡
爲何要用Densenet121模型?
本項目使用在PyTorch框架下搭建的神經網絡來完成圖片分類的任務。因爲網絡輸出的類別數量很大,簡單的網絡模型沒法達到很好的分類效果,所以,本項目使用了預訓練的Densenet121模型,並僅訓練全鏈接層的參數。框架
項目流程:1.數據處理
2.Densenet模型解讀
3.加載預訓練網絡模型
4.訓練神經網絡函數
首先從指定路徑讀取圖像,將圖像大小更改成224*224,並將圖片範圍從0-255改成0-1:學習
from PIL import Image image= Image.open(path) image=image.resize((224,224)) x_data= x_data.astype(numpy.float32) x_data= numpy.multiply(x_data, 1.0/255.0) ## scale to [0,1] from [0,255]
因爲此數據集中有少許圖片的色彩是單通道的,而神經網絡的輸入須要爲三個通道,所以,將該通道的數據複製到三個通道上:測試
if len(x_data.shape)!=3: temp=numpy.zeros ((x_data.shape[0],x_data.shape[1],3)) temp[:,:,0] = x_data temp[:,:,1] = x_data temp[:,:,2] = x_data x_data= temp x_data=numpy.transpose(x_data,(2,0,1)) ## reshape
在上述步驟以後,對圖片進行白化,即讓像素點的平均值爲0,方差爲1。這樣作是爲了減少圖片的範圍,使得圖片的特徵更易於學習。白化的過程以下所示:優化
if x_train is not None: x_train[:,0,:,:] = (x_train[:,0,:,:]-0.485)/0.229 x_train[:,1,:,:] = (x_train[:,1,:,:]-0.456)/0.224 x_train[:,2,:,:] = (x_train[:,2,:,:]-0.406)/0.225 if x_test is not None: x_test[:,0,:,:] = (x_test[:,0,:,:] -0.485) /0.229 x_test[:,1,:,:] = (x_test[:,1,:,:] -0.456) /0.224 x_test[:,2,:,:] = (x_test[:,2,:,:] -0.406) /0.225
DenseNet的網絡結構以下圖所示。在傳統的CNN中,每一個卷積層只與其相鄰的卷積層相鏈接,這就形成了位於網絡淺層的參數在反向傳播中獲取的梯度很是小,也就是梯度消失問題。ui
DenseNet設計了名爲Dense Block的特殊的網絡結構,在一個Dense Block中,每一個層的輸入爲前面全部層的輸出,這也正是Dense的含義。經過這種方法,在反向傳播中,網絡淺層的參數能夠從後面全部層中得到梯度,在很大程度上減弱了梯度消失的問題。值得注意的是,每一個層只與同位於一個Dense Block中的多個層有鏈接,而與Dense Block外的層是沒有鏈接的。spa
torchvision是服務於PyTorch框架的,用於進行圖片處理和生成一些主流模型的庫。使用該庫能夠方便的加載PyTorch的預訓練模型。首先使用pip安裝torchvision庫:設計
pip install torchvision
建立densenet121模型實例,並加載預訓練參數:code
cnn = torchvision.models.densenet121 (pretrained = True) #pretrained =True即爲加載預訓練參數,默認不加載。
凍結全部模型參數,使其值在反向傳播中不改變:
for param in cnn.parameters(): param.requires_grad= False
改變模型全鏈接層輸出的個數爲256:
num_features= cnn.classifier.in_features cnn.classifier= nn.Linear(num_features, 256)
此處不須要擔憂新建的全鏈接層參數會被凍結,由於新建的層參數是默認獲取梯度的。
損失函數選擇CrossEntropy,優化器選擇Adam:
optimizer= Adam(cnn.parameters(), lr=0.001, betas=(0.9, 0.999)) # 選用AdamOptimizer loss_fn= nn.CrossEntropyLoss() # 定義損失函數
下面是完整的訓練過程:
# 訓練並評估模型 data= Dataset() model= Model(data) best_accuracy= 0 foriinrange(args.EPOCHS): cnn.train() x_train, y_train, x_test, y_test= data.next_batch(args.BATCH) # 讀取數據 x_train= torch.from_numpy(x_train) y_train= torch.from_numpy(y_train) x_train= x_train.float() x_test= torch.from_numpy(x_test) y_test= torch.from_numpy(y_test) x_test= x_test.float() ifcuda_avail: x_train= Variable(x_train.cuda()) y_train= Variable(y_train.cuda()) x_test= Variable(x_test.cuda()) y_test= Variable(y_test.cuda()) outputs= cnn(x_train) _, prediction= torch.max(outputs.data, 1) optimizer.zero_grad() # calculate the loss according to labels loss= loss_fn(outputs, y_train) # backward transmit loss loss.backward() # adjust parameters using Adam optimizer.step() # 若測試準確率高於當前最高準確率,則保存模型 train_accuracy= eval(model, x_test, y_test) iftrain_accuracy>best_accuracy: best_accuracy= train_accuracy model.save_model(cnn, MODEL_PATH, overwrite=True) print("step %d, best accuracy %g"%(i, best_accuracy)) print(str(i) +"/"+str(args.EPOCHS))
本文主要講解了DenseNet的網絡結構,以及在PyTorch框架下如何加載預訓練模型並進行fine-tuning。爲了在數據集上得到更高的準確率,讀者可嘗試取消凍結參數的設置,使得卷積層也參與訓練。
獲取相關項目代碼 請訪問: https://www.flyai.com/d/Calte...
— END —