生活随笔
收集整理的這篇文章主要介紹了
【pytorch】pytorch自定义训练vgg16和测试数据集 微调resnet18全连接层
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
自己定義模型
測試:
correct
= 0total
= 0for data
in test_loader
:img
,label
= dataoutputs
= net
(Variable
(img
))_
,predict
= torch
.max(outputs
.data
,1)total
+= label
.size
(0)correct
+= (predict
== label
).sum()print(str(predict
)+','+str(label
))print(100*correct
/total
)
輸出:
預(yù)測錯(cuò)誤還是挺大的,居然全是1
完整代碼:
```python
import torch
.nn
.functional
as F
import torch
import torch
.nn
as nn
from torch
.autograd
import Variable
from torchvision
import transforms
from torch
.utils
.data
.dataset
import Dataset
from torch
.utils
.data
.dataloader
import DataLoader
from PIL
import Image
import torch
.optim
as optim
import os
learning_rate
= 0.0001
root
= os
.getcwd
() + '\\data\\'
def default_loader(path
):return Image
.open(path
).convert
('RGB')class MyDataset(Dataset
):def __init__(self
, txt
, transform
=None, target_transform
=None,test
= False,loader
=default_loader
):super(MyDataset
, self
).__init__
()imgs
= []fh
= open(txt
, 'r')for line
in fh
: line
= line
.strip
('\n')line
= line
.rstrip
('\n')words
= line
.split
()imgs
.append
((words
[0], int(words
[1])))self
.test
= testself
.imgs
= imgsself
.transform
= transformself
.target_transform
= target_transform
def __getitem__(self
, index
): fn
, label
= self
.imgs
[index
]if self
.test
is False:img_path
= os
.path
.join
("C:\\Users\\pic\\train", fn
)else:img_path
= os
.path
.join
("C:\\Users\\pic\\test", fn
)img
= Image
.open(img_path
).convert
('RGB')if self
.transform
is not None:img
= self
.transform
(img
)return img
, label
def __len__(self
):return len(self
.imgs
)class Net(nn
.Module
): def __init__(self
):super(Net
, self
).__init__
()self
.conv1
= nn
.Conv2d
(3, 6, 5) self
.pool
= nn
.MaxPool2d
(2, 2) self
.conv2
= nn
.Conv2d
(6, 16, 5) self
.fc1
= nn
.Linear
(16 * 5 * 5, 120) self
.fc2
= nn
.Linear
(120, 84)self
.fc3
= nn
.Linear
(84, 2) def forward(self
, x
): x
= self
.pool
(F
.relu
(self
.conv1
(x
))) x
= self
.pool
(F
.relu
(self
.conv2
(x
)))x
= x
.view
(-1, 16 * 5 * 5) x
= F
.relu
(self
.fc1
(x
))x
= F
.relu
(self
.fc2
(x
))x
= self
.fc3
(x
)return xIMG_MEAN
= [0.485, 0.456, 0.406]
IMG_STD
= [0.229, 0.224, 0.225]net
= Net
()
train_data
= MyDataset
(txt
=root
+ 'num.txt', transform
=transforms
.Compose
([transforms
.RandomHorizontalFlip
(), transforms
.Resize
((32, 32)),transforms
.CenterCrop
(32),transforms
.ToTensor
()]))
test_data
= MyDataset
(txt
=root
+'test.txt', transform
=transforms
.Compose
([transforms
.Resize
((32, 32)),transforms
.CenterCrop
(32),transforms
.ToTensor
()]),test
=True)
train_loader
= DataLoader
(dataset
=train_data
, batch_size
=227, shuffle
=True,drop_last
=True)
print('num_of_trainData:', len(train_data
))
test_loader
= DataLoader
(dataset
=test_data
, batch_size
=19, shuffle
=False)def trainandsave():print('h')net
= Net
()optimizer
= optim
.SGD
(net
.parameters
(), lr
=0.001, momentum
=0.9) criterion
= nn
.CrossEntropyLoss
() for epoch
in range(10): running_loss
= 0.0 for i
, data
in enumerate(train_loader
, 0): inputs
, labels
= data inputs
, labels
= Variable
(inputs
), Variable
(labels
) optimizer
.zero_grad
() outputs
= net
(inputs
) loss
= criterion
(outputs
, labels
) loss
.backward
() optimizer
.step
() running_loss
+= loss
.item
() if i
% 9 == 1:print('[%d, %5d] loss: %.3f' %(epoch
+ 1, i
+ 1, running_loss
/ 10)) running_loss
= 0.0 print('Finished Training')torch
.save
(net
, 'net.pkl')torch
.save
(net
.state_dict
(), 'net_params.pkl')
嘗試運(yùn)行vgg16:
找了很久,預(yù)測是參數(shù)的問題,輸入圖片是224*224,一開始改的resize但還是報(bào)錯(cuò),于是改
transforms.CenterCrop((224, 224))
然后data[0]要改成item()
然后運(yùn)行成功了(好慢。。)
class VGG16(nn
.Module
):def __init__(self
, nums
=2):super(VGG16
, self
).__init__
()self
.nums
= numsvgg
= []vgg
.append
(nn
.Conv2d
(in_channels
=3, out_channels
=64, kernel_size
=3, stride
=1, padding
=1))vgg
.append
(nn
.ReLU
())vgg
.append
(nn
.Conv2d
(in_channels
=64, out_channels
=64, kernel_size
=3, stride
=1, padding
=1))vgg
.append
(nn
.ReLU
())vgg
.append
(nn
.MaxPool2d
(kernel_size
=2, stride
=2))vgg
.append
(nn
.Conv2d
(in_channels
=64, out_channels
=128, kernel_size
=3, stride
=1, padding
=1))vgg
.append
(nn
.ReLU
())vgg
.append
(nn
.Conv2d
(in_channels
=128, out_channels
=128, kernel_size
=3, stride
=1, padding
=1))vgg
.append
(nn
.ReLU
())vgg
.append
(nn
.MaxPool2d
(kernel_size
=2, stride
=2))vgg
.append
(nn
.Conv2d
(in_channels
=128, out_channels
=256, kernel_size
=3, stride
=1, padding
=1))vgg
.append
(nn
.ReLU
())vgg
.append
(nn
.Conv2d
(in_channels
=256, out_channels
=256, kernel_size
=3, stride
=1, padding
=1))vgg
.append
(nn
.ReLU
())vgg
.append
(nn
.Conv2d
(in_channels
=256, out_channels
=256, kernel_size
=3, stride
=1, padding
=1))vgg
.append
(nn
.ReLU
())vgg
.append
(nn
.MaxPool2d
(kernel_size
=2, stride
=2))vgg
.append
(nn
.Conv2d
(in_channels
=256, out_channels
=512, kernel_size
=3, stride
=1, padding
=1))vgg
.append
(nn
.ReLU
())vgg
.append
(nn
.Conv2d
(in_channels
=512, out_channels
=512, kernel_size
=3, stride
=1, padding
=1))vgg
.append
(nn
.ReLU
())vgg
.append
(nn
.Conv2d
(in_channels
=512, out_channels
=512, kernel_size
=3, stride
=1, padding
=1))vgg
.append
(nn
.ReLU
())vgg
.append
(nn
.MaxPool2d
(kernel_size
=2, stride
=2))vgg
.append
(nn
.Conv2d
(in_channels
=512, out_channels
=512, kernel_size
=3, stride
=1, padding
=1))vgg
.append
(nn
.ReLU
())vgg
.append
(nn
.Conv2d
(in_channels
=512, out_channels
=512, kernel_size
=3, stride
=1, padding
=1))vgg
.append
(nn
.ReLU
())vgg
.append
(nn
.Conv2d
(in_channels
=512, out_channels
=512, kernel_size
=3, stride
=1, padding
=1))vgg
.append
(nn
.ReLU
())vgg
.append
(nn
.MaxPool2d
(kernel_size
=2, stride
=2))self
.main
= nn
.Sequential
(*vgg
)classfication
= []classfication
.append
(nn
.Linear
(in_features
=512 * 7 * 7, out_features
=4096)) classfication
.append
(nn
.ReLU
())classfication
.append
(nn
.Dropout
(p
=0.5))classfication
.append
(nn
.Linear
(in_features
=4096, out_features
=4096))classfication
.append
(nn
.ReLU
())classfication
.append
(nn
.Dropout
(p
=0.5))classfication
.append
(nn
.Linear
(in_features
=4096, out_features
=self
.nums
))self
.classfication
= nn
.Sequential
(*classfication
)def forward(self
, x
):feature
= self
.main
(x
) feature
= feature
.view
(x
.size
(0), -1) result
= self
.classfication
(feature
)return resultnet
= Net
()
train_data
= MyDataset
(txt
=root
+ 'num.txt', transform
=transforms
.Compose
([transforms
.RandomHorizontalFlip
(),
transforms
.Resize
((224, 224)),
transforms
.CenterCrop
((224, 224)),transforms
.ToTensor
()]))
test_data
= MyDataset
(txt
=root
+'test.txt', transform
=transforms
.Compose
([transforms
.Resize
((32, 32)),transforms
.CenterCrop
(32),transforms
.ToTensor
()]),test
=True)
train_loader
= DataLoader
(dataset
=train_data
, batch_size
=16, shuffle
=True,drop_last
=True)
print('num_of_trainData:', len(train_data
))
test_loader
= DataLoader
(dataset
=test_data
, batch_size
=19, shuffle
=False)if __name__
== '__main__':vgg
= VGG16
()optimizer
= optim
.SGD
(vgg
.parameters
(), lr
=0.001, momentum
=0.9) criterion
= nn
.CrossEntropyLoss
() for epoch
in range(10): running_loss
= 0.0 train_loss
= 0.train_acc
= 0.for i
, data
in enumerate(train_loader
, 0): inputs
, labels
= data inputs
, labels
= Variable
(inputs
), Variable
(labels
) optimizer
.zero_grad
() outputs
= vgg
(inputs
) loss
= criterion
(outputs
, labels
) train_loss
+= loss
.item
()pred
= torch
.max(outputs
, 1)[1]train_correct
= (pred
== labels
).sum()train_acc
+= train_correct
.item
()loss
.backward
() optimizer
.step
() running_loss
+= loss
.item
() print('Train Loss: {:.6f}, Acc: {:.6f}'.format(train_loss
/ (len(train_data
)), train_acc
/ (len(train_data
))))print('Finished Training')torch
.save
(net
, 'net.pkl')torch
.save
(net
.state_dict
(), 'net_params.pkl')
嘗試將損失函數(shù)修改:
optimizer = optim.Adam(vgg.parameters(), lr=1e-6) # 學(xué)習(xí)率為0.001
結(jié)果仍然不理想。懷疑是數(shù)據(jù)集有過大誤差。
載入已有模型進(jìn)行參數(shù)優(yōu)化
兩個(gè)主要的遷移學(xué)習(xí)場景:
Finetuning the convnet: 我們使用預(yù)訓(xùn)練網(wǎng)絡(luò)初始化網(wǎng)絡(luò),而不是隨機(jī)初始化,就像在imagenet 1000數(shù)據(jù)集上訓(xùn)練的網(wǎng)絡(luò)一樣。其余訓(xùn)練看起來像往常一樣。(此微調(diào)過程對應(yīng)引用中所說的初始化)
ConvNet as fixed feature extractor: 在這里,我們將凍結(jié)除最終完全連接層之外的所有網(wǎng)絡(luò)的權(quán)重。最后一個(gè)全連接層被替換為具有隨機(jī)權(quán)重的新層,并且僅訓(xùn)練該層。(此步對應(yīng)引
用中的固定特征提取器
用加載預(yù)訓(xùn)練模型并重置最終的全連接層的方法進(jìn)行訓(xùn)練。
每一個(gè)epoch都進(jìn)行訓(xùn)練和測試。我寫的是resnet18(先自己網(wǎng)上下載pkl文件,在pycharm里面下載太慢)
目前的全部代碼:
from __future__
import print_function
, division
import torch
import torch
.nn
as nn
import torch
.optim
as optim
from torch
.optim
import lr_scheduler
import numpy
as np
import torchvision
from torchvision
import datasets
, models
, transforms
import matplotlib
.pyplot
as plt
import time
import os
import copy
import torchvision
.models
as modelsdata_transforms
= {
'train': transforms
.Compose
([transforms
.RandomResizedCrop
(224),transforms
.RandomHorizontalFlip
(),transforms
.ToTensor
(),transforms
.Normalize
([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])]),'val': transforms
.Compose
([transforms
.Resize
(256),transforms
.CenterCrop
(224),transforms
.ToTensor
(),transforms
.Normalize
([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])]),}data_dir
=os
.getcwd
() + '\\data\\'
image_datasets
= {x
: datasets
.ImageFolder
(os
.path
.join
(data_dir
, x
),data_transforms
[x
]) for x
in ['train', 'val']}
dataloaders
= {x
: torch
.utils
.data
.DataLoader
(image_datasets
[x
], batch_size
=4,shuffle
=True) for x
in ['train', 'val']}
dataset_sizes
= {x
: len(image_datasets
[x
]) for x
in ['train', 'val']}
device
= torch
.device
("cuda:0" if torch
.cuda
.is_available
() else "cpu")
def imshow(inp
, title
=None):"""Imshow for Tensor."""inp
= inp
.numpy
().transpose
((1, 2, 0))mean
= np
.array
([0.485, 0.456, 0.406])std
= np
.array
([0.229, 0.224, 0.225])inp
= std
* inp
+ meaninp
= np
.clip
(inp
, 0, 1)plt
.imshow
(inp
)if title
is not None:plt
.title
(title
)plt
.pause
(0.001) def train_model(model
, criterion
, optimizer
, scheduler
, num_epochs
=25):since
= time
.time
()best_model_wts
= copy
.deepcopy
(model
.state_dict
())best_acc
= 0.0for epoch
in range(num_epochs
):print('Epoch {}/{}'.format(epoch
, num_epochs
- 1))print('-' * 10)for phase
in ['train', 'val']:if phase
== 'train':scheduler
.step
()model
.train
() running_loss
= 0.0running_corrects
= 0for inputs
, labels
in dataloaders
[phase
]:optimizer
.zero_grad
()with torch
.set_grad_enabled
(phase
== 'train'):outputs
= model
(inputs
)_
,preds
= torch
.max(outputs
, 1)loss
= criterion
(outputs
, labels
)if phase
== 'train':loss
.backward
()optimizer
.step
()running_loss
+= loss
.item
() * inputs
.size
(0)running_corrects
+= torch
.sum(preds
== labels
.data
)epoch_loss
= running_loss
/ dataset_sizes
[phase
]epoch_acc
= running_corrects
.double
() / dataset_sizes
[phase
]print('{} Loss: {:.4f} Acc: {:.4f}'.format(phase
, epoch_loss
, epoch_acc
))
if phase
== 'val' and epoch_acc
> best_acc
:best_acc
= epoch_accbest_model_wts
= copy
.deepcopy
(model
.state_dict
())print()time_elapsed
= time
.time
() - since
print('Training complete in {:.0f}m {:.0f}s'.format(time_elapsed
// 60, time_elapsed
% 60))print('Best val Acc: {:4f}'.format(best_acc
))model
.load_state_dict
(best_model_wts
)return modelclass_names
= image_datasets
['train'].classes
def visualize_model(model
, num_images
=6):was_training
= model
.trainingmodel
.eval()images_so_far
= 0fig
= plt
.figure
()with torch
.no_grad
():for i
, (inputs
, labels
) in enumerate(dataloaders
['val']):outputs
= model
(inputs
)_
, preds
= torch
.max(outputs
, 1)for j
in range(inputs
.size
()[0]):images_so_far
+= 1ax
= plt
.subplot
(num_images
// 2, 2, images_so_far
)ax
.axis
('off')ax
.set_title
('predicted: {}'.format(class_names
[preds
[j
]]))imshow
(inputs
.cpu
().data
[j
])if images_so_far
== num_images
:model
.train
(mode
=was_training
)returnmodel
.train
(mode
=was_training
)model_ft
= models
.resnet18
(pretrained
=False)
pthfile
= r'C:\Users\14172\PycharmProjects\pythonProject4\resnet18-5c106cde.pth'
model_ft
.load_state_dict
(torch
.load
(pthfile
))
num_ftrs
= model_ft
.fc
.in_features
model_ft
.fc
= nn
.Linear
(num_ftrs
, 2)
criterion
= nn
.CrossEntropyLoss
()
optimizer_ft
= optim
.SGD
(model_ft
.parameters
(), lr
=0.001, momentum
=0.9)
exp_lr_scheduler
= lr_scheduler
.StepLR
(optimizer_ft
, step_size
=7, gamma
=0.1)
model_ft
= train_model
(model_ft
, criterion
, optimizer_ft
, exp_lr_scheduler
,num_epochs
=25)
torch
.save
(model_ft
, 'modefresnet.pkl')
torch
.save
(model_ft
.state_dict
(), 'modelresnet_params.pkl')
visualize_model
(model_ft
)
兩者差距還是比較大,后期再進(jìn)行調(diào)整。先記錄。
與50位技術(shù)專家面對面20年技術(shù)見證,附贈技術(shù)全景圖
總結(jié)
以上是生活随笔為你收集整理的【pytorch】pytorch自定义训练vgg16和测试数据集 微调resnet18全连接层的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。