我的第二个pytorch人工智能程序(最简单的方式训练cifar100)

改进了训练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分