1.数据集
热狗数据集
2.使用预训练模型的Python代码
import torch
from torch import nn, optim
from torch.utils.data import Dataset, DataLoader
import torchvision
from torchvision.datasets import ImageFolder
from torchvision import transforms
from torchvision import models
import matplotlib.pyplot as plt
import time
import os
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
data_dir = '/root/autodl-tmp/data'
os.listdir(os.path.join(data_dir,'hotdog'))
train_imgs = ImageFolder(os.path.join(data_dir,'hotdog/train'))
test_imgs = ImageFolder(os.path.join(data_dir,'hotdog/test'))
hotdogs = [train_imgs[i][0] for i in range(8)]
not_hotdogs = [train_imgs[-i-1][0] for i in range(8)][0]
def show_images(imgs, num_rows, num_cols, scale=2):
figsize = (num_cols * scale, num_rows * scale)
_, axes = plt.subplots(num_rows,num_cols,figsize=figsize)
for i in range(num_rows):
for j in range(num_cols):
axes[i][j].imshow(imgs[i * num_cols + j])
axes[i][j].axes.get_xaxis().set_visible(False)
axes[i][j].axes.get_yaxis().set_visible(False)
plt.show()
return axes
#show_images(hotdogs+not_hotdogs,2,8,scale=1.4)
normalize = transforms.Normalize(mean=[0.485, 0.456, 0.406],std=[0.229, 0.224, 0.225])
train_augs = transforms.Compose([
transforms.RandomResizedCrop(size=224),
transforms.RandomHorizontalFlip(),
transforms.ToTensor(),
normalize
])
test_augs = transforms.Compose([
transforms.Resize(size=256),
transforms.CenterCrop(size=224),
transforms.ToTensor(),
normalize
])
pretrained_net = models.resnet18(pretrained=True)
pretrained_net.fc = nn.Linear(512,2)
output_params = list(map(id, pretrained_net.fc.parameters()))
feature_params = filter(lambda p: id(p) not in output_params, pretrained_net.parameters())
lr = 0.01
optimizer = optim.SGD([{'params': feature_params},{'params':pretrained_net.fc.parameters(),'lr':lr*10}],lr=lr,weight_decay=0.001)
def evaluate_accuracy(data_iter,net,device):
acc_sum, n = 0.0, 0
for X, y in data_iter:
X = X.to(device)
y = y.to(device)
acc_sum += (net(X).argmax(dim=1) == y).float().sum().item()
n += y.shape[0]
return acc_sum / n
def train(train_iter, test_iter, net, loss, optimizer, device, num_epochs):
net = net.to(device)
print("training on",device)
batch_count = 0
for epoch in range(num_epochs):
train_l_sum, train_acc_sum, n, start = 0.0, 0.0, 0, time.time()
for X, y in train_iter:
X = X.to(device)
y = y.to(device)
y_hat = net(X)
l = loss(y_hat, y)
optimizer.zero_grad()
l.backward()
optimizer.step()
train_l_sum += l.cpu().item()
train_acc_sum += (y_hat.argmax(dim=1) == y).sum().cpu().item()
n += y.shape[0]
batch_count += 1
test_acc = evaluate_accuracy(test_iter, net,device)
print('epoch %d, loss %.4f, train acc %.3f, test acc %.3f, time %.1f sec' %(epoch + 1, train_l_sum/batch_count, train_acc_sum/n,test_acc,time.time()-start))
def train_fine_tuning(net, optimizer, batch_size = 128, num_epochs=5):
train_iter = DataLoader(ImageFolder(os.path.join(data_dir,'hotdog/train'),transform=train_augs),batch_size, shuffle=True)
test_iter = DataLoader(ImageFolder(os.path.join(data_dir,'hotdog/test'),transform=test_augs),batch_size)
loss = torch.nn.CrossEntropyLoss()
train(train_iter, test_iter, net, loss, optimizer, device, num_epochs)
train_fine_tuning(pretrained_net, optimizer)
3.训练结果
4.不使用预训练模型的Python代码
import torch
from torch import nn, optim
from torch.utils.data import Dataset, DataLoader
import torchvision
from torchvision.datasets import ImageFolder
from torchvision import transforms
from torchvision import models
import matplotlib.pyplot as plt
import time
import os
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
data_dir = '/root/autodl-tmp/data'
os.listdir(os.path.join(data_dir,'hotdog'))
train_imgs = ImageFolder(os.path.join(data_dir,'hotdog/train'))
test_imgs = ImageFolder(os.path.join(data_dir,'hotdog/test'))
hotdogs = [train_imgs[i][0] for i in range(8)]
not_hotdogs = [train_imgs[-i-1][0] for i in range(8)][0]
def show_images(imgs, num_rows, num_cols, scale=2):
figsize = (num_cols * scale, num_rows * scale)
_, axes = plt.subplots(num_rows,num_cols,figsize=figsize)
for i in range(num_rows):
for j in range(num_cols):
axes[i][j].imshow(imgs[i * num_cols + j])
axes[i][j].axes.get_xaxis().set_visible(False)
axes[i][j].axes.get_yaxis().set_visible(False)
plt.show()
return axes
#show_images(hotdogs+not_hotdogs,2,8,scale=1.4)
normalize = transforms.Normalize(mean=[0.485, 0.456, 0.406],std=[0.229, 0.224, 0.225])
train_augs = transforms.Compose([
transforms.RandomResizedCrop(size=224),
transforms.RandomHorizontalFlip(),
transforms.ToTensor(),
normalize
])
test_augs = transforms.Compose([
transforms.Resize(size=256),
transforms.CenterCrop(size=224),
transforms.ToTensor(),
normalize
])
pretrained_net = models.resnet18(pretrained=True)
pretrained_net.fc = nn.Linear(512,2)
output_params = list(map(id, pretrained_net.fc.parameters()))
feature_params = filter(lambda p: id(p) not in output_params, pretrained_net.parameters())
lr = 0.01
optimizer = optim.SGD([{'params': feature_params},{'params':pretrained_net.fc.parameters(),'lr':lr*10}],lr=lr,weight_decay=0.001)
def evaluate_accuracy(data_iter,net,device):
acc_sum, n = 0.0, 0
for X, y in data_iter:
X = X.to(device)
y = y.to(device)
acc_sum += (net(X).argmax(dim=1) == y).float().sum().item()
n += y.shape[0]
return acc_sum / n
def train(train_iter, test_iter, net, loss, optimizer, device, num_epochs):
net = net.to(device)
print("training on",device)
batch_count = 0
for epoch in range(num_epochs):
train_l_sum, train_acc_sum, n, start = 0.0, 0.0, 0, time.time()
for X, y in train_iter:
X = X.to(device)
y = y.to(device)
y_hat = net(X)
l = loss(y_hat, y)
optimizer.zero_grad()
l.backward()
optimizer.step()
train_l_sum += l.cpu().item()
train_acc_sum += (y_hat.argmax(dim=1) == y).sum().cpu().item()
n += y.shape[0]
batch_count += 1
test_acc = evaluate_accuracy(test_iter, net,device)
print('epoch %d, loss %.4f, train acc %.3f, test acc %.3f, time %.1f sec' %(epoch + 1, train_l_sum/batch_count, train_acc_sum/n,test_acc,time.time()-start))
def train_fine_tuning(net, optimizer, batch_size = 128, num_epochs=5):
train_iter = DataLoader(ImageFolder(os.path.join(data_dir,'hotdog/train'),transform=train_augs),batch_size, shuffle=True)
test_iter = DataLoader(ImageFolder(os.path.join(data_dir,'hotdog/test'),transform=test_augs),batch_size)
loss = torch.nn.CrossEntropyLoss()
train(train_iter, test_iter, net, loss, optimizer, device, num_epochs)
scratch_net = models.resnet18(pretrained=False, num_classes=2)
lr = 0.1
optimizer = optim.SGD(scratch_net.parameters(),lr=lr,weight_decay=0.001)
train_fine_tuning(scratch_net,optimizer)
5.训练结果
6.结果分析
可以看出,使用预训练模型参数的网络在经过同样的epoch后,达到的精度更高。