改进了训练cifar10的第一个pytorch程序(很简单的那种):
我的第一个pytorch人工智能程序(最简单而高效的方式)-CSDN博客
下面看代码:#50轮,47分,改进后50轮54分
import torch
#import tqdm
from torchvision import datasets
from torchvision import transforms
from torch.utils.data import DataLoader
import torch.optim
import time
batch_size = 64
device = torch.device("cuda" if torch.cuda.is_available() else "cpu") # 注意不要放到 前面
1 数据
transform_train = transforms.Compose([
transforms.RandomCrop(32, padding=4), #先四周填充0,再把图像随机裁剪成32*32
transforms.RandomHorizontalFlip(), #图像一半的概率翻转,一半的概率不翻转
transforms.ToTensor(),
transforms.Normalize((0, 0, 0), (1, 1, 1)), #R,G,B每层的归一化用到的均值和方差
])
transform = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize( (0.1307,), (0.3081,) )
transforms.Normalize((0, 0, 0), (1,1, 1))
])
train_set = datasets.CIFAR100(root = './data',
train=True,
transform = transform_train,
download=True)
test_set =datasets.CIFAR100(root = './data',
train=False,
transform= transform,
download=True)
train_loader = DataLoader( train_set, shuffle=True, batch_size=batch_size)
test_loader = DataLoader( test_set, shuffle=False, batch_size=batch_size)
2 模型
class ResidualBlock( torch.nn.Module ):
def init(self, channels):
super( ResidualBlock, self).init()
self.Conv1 = torch.nn.Conv2d( channels, channels, kernel_size=(3, 3), padding=1)
self.Conv2 = torch.nn.Conv2d( channels, channels, kernel_size=(3, 3), padding=1)
self.relu=torch.nn.LeakyReLU()
def forward(self, x):
y = self.relu((self.Conv1(x) ))
y = (self.Conv2(y))
return self.relu( y+x )
class Model( torch.nn.Module ):
def init(self):
super( Model, self).init()
self.conv1 = torch.nn.Conv2d( 3, 32, kernel_size=(3,3) , padding=1)
self.conv2 = torch.nn.Conv2d( 32, 64,kernel_size=(3,3) , padding=1 )
self.relu=torch.nn.LeakyReLU()
self.resblk1 = ResidualBlock(32)
self.resblk2 = ResidualBlock(64)
self.pool = torch.nn.MaxPool2d(2)
self.out = torch.nn.Linear(4096*4,100)
def forward(self, x):
x = self.relu( (self.conv1(x) ) )
x = self.resblk1(x)
x = self.pool( self.relu( (self.conv2(x) ) ))
x = self.resblk2(x)
x = self.pool(x)
x=x.view(x.size(0),-1)
x=self.out(x)
return x
3 训练
train_loss = \[\]
train_accuracy = \[\]
model = Model()
model.to(device)
criterion = torch.nn.CrossEntropyLoss()
optimizer = torch.optim.SGD( model.parameters(), lr=0.01, momentum=0.5, weight_decay=5e-4)
def train( epoch):
L = 0.0
total = 0
correct = 0
for index, data in enumerate( tqdm.tqdm( train_loader), start=0 ):
for index, data in enumerate(train_loader, start=0):
x, y = data
x = x.to(device) # 记得前面的"x = "否则没转换
y = y.to(device)
y_ = model(x)
, predicted = torch.max(y.data, dim=1)
loss = criterion( y_, y )
optimizer.zero_grad()
loss.backward()
optimizer.step()
L += loss.data.item() # loss是tensor,想让L保持float所以要写成loss.data.item()
total += y.size(0)
correct += (predicted == y).sum().item()
acc = (100 * correct / total)
print('Accuracy on train set: %d %%' % acc)
train_accuracy.append(acc)
L /= batch_size
train_loss.append(L) # L已经是float了,不需要再加.data.item()
print('%d-th loss: %.3f' % (epoch, L) )
if epoch == 20:
for param_group in optimizer.param_groups:
param_group'lr' *= 0.1
if epoch == 40:
for param_group in optimizer.param_groups:
param_group'lr' *= 0.1
def test():
total = 0
correct = 0
with torch.no_grad():
for data in test_loader:
x, y = data
x = x.to(device)
y = y.to(device)
y_head = model(x)
_, predicted = torch.max(y_head.data, dim=1)
total += y.size(0)
correct += (predicted == y).sum().item()
print( 'Accuracy on test set: %d %%' % (100*correct/total))
if name == 'main':
for epoch in range(50):
time_start = time.perf_counter()
train(epoch)
print('%f s' % (time.perf_counter() - time_start))
test()
PATH = './cifar_ResNet_simple100.pth'
torch.save(model.state_dict(), PATH)#50轮,47分,改进后50轮54分