image.png

model.py

  1. import torch.nn as nn
  2. import torch.nn.functional as F
  3. class LeNet(nn.Module):
  4. def __init__(self):
  5. super(LeNet, self).__init__()
  6. self.conv1 = nn.Conv2d(3, 16, 5)
  7. self.pool1 = nn.MaxPool2d(2, 2)
  8. self.conv2 = nn.Conv2d(16, 32, 5)
  9. self.pool2 = nn.MaxPool2d(2, 2)
  10. self.fc1 = nn.Linear(32*5*5, 120)
  11. self.fc2 = nn.Linear(120, 84)
  12. self.fc3 = nn.Linear(84, 10)
  13. def forward(self, x):
  14. x = F.relu(self.conv1(x)) # input(3, 32, 32) output(16, 28, 28)
  15. x = self.pool1(x) # output(16, 14, 14)
  16. x = F.relu(self.conv2(x)) # output(32, 10, 10)
  17. x = self.pool2(x) # output(32, 5, 5)
  18. x = x.view(-1, 32*5*5) # output(32*5*5)
  19. x = F.relu(self.fc1(x)) # output(120)
  20. x = F.relu(self.fc2(x)) # output(84)
  21. x = self.fc3(x) # output(10)
  22. return x

train.py

transforms.ToTensor()
Converts a PIL Image or numpy.ndarray (H x W x C) in the range [0, 255] to a torch.FloatTensor of shape (C x H x W) in the range [0.0, 1.0]
transforms.Normalize()
Normalize a tensor image with mean and standard deviation.Given mean: (M1,...,Mn) and std: (S1,..,Sn) for n channels, this transform will normalize each channel of the input torch.*Tensor i.e. input[channel] = (input[channel] - mean[channel]) / std[channel]
.. note::
This transform acts out of place, i.e., it does not mutates the input tensor.
Args:
mean (sequence): Sequence of means for each channel.
std (sequence): Sequence of standard deviations for each channel.
inplace(bool,optional): Bool to make this operation in-place.

optimizer.zero_grad()来将历史损失清零
如果不清除历史梯度,就会对计算的历史梯度进行累加(通过这个特性,可以实现一个很大batch数值的训练)

https://www.zhihu.com/question/303070254

  1. import torch
  2. import torchvision
  3. import torch.nn as nn
  4. from model import LeNet
  5. import torch.optim as optim
  6. import torchvision.transforms as transforms
  7. def main():
  8. transform = transforms.Compose(
  9. [transforms.ToTensor(),
  10. transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])
  11. # 50000张训练图片
  12. # 第一次使用时要将download设置为True才会自动去下载数据集
  13. train_set = torchvision.datasets.CIFAR10(root='./data', train=True,
  14. download=False, transform=transform)
  15. train_loader = torch.utils.data.DataLoader(train_set, batch_size=36,
  16. shuffle=True, num_workers=0)
  17. # 10000张验证图片
  18. # 第一次使用时要将download设置为True才会自动去下载数据集
  19. val_set = torchvision.datasets.CIFAR10(root='./data', train=False,
  20. download=False, transform=transform)
  21. val_loader = torch.utils.data.DataLoader(val_set, batch_size=5000,
  22. shuffle=False, num_workers=0)
  23. val_data_iter = iter(val_loader)
  24. val_image, val_label = val_data_iter.next()
  25. # classes = ('plane', 'car', 'bird', 'cat',
  26. # 'deer', 'dog', 'frog', 'horse', 'ship', 'truck')
  27. net = LeNet()
  28. loss_function = nn.CrossEntropyLoss()
  29. optimizer = optim.Adam(net.parameters(), lr=0.001)
  30. for epoch in range(5): # loop over the dataset multiple times
  31. running_loss = 0.0
  32. for step, data in enumerate(train_loader, start=0):
  33. # get the inputs; data is a list of [inputs, labels]
  34. inputs, labels = data
  35. # zero the parameter gradients
  36. optimizer.zero_grad()
  37. # forward + backward + optimize
  38. outputs = net(inputs)
  39. loss = loss_function(outputs, labels)
  40. loss.backward()
  41. optimizer.step()
  42. # print statistics
  43. running_loss += loss.item()
  44. if step % 500 == 499: # print every 500 mini-batches
  45. with torch.no_grad():
  46. outputs = net(val_image) # [batch, 10]
  47. predict_y = torch.max(outputs, dim=1)[1]
  48. accuracy = torch.eq(predict_y, val_label).sum().item() / val_label.size(0)
  49. print('[%d, %5d] train_loss: %.3f test_accuracy: %.3f' %
  50. (epoch + 1, step + 1, running_loss / 500, accuracy))
  51. running_loss = 0.0
  52. print('Finished Training')
  53. save_path = './Lenet.pth'
  54. torch.save(net.state_dict(), save_path)
  55. if __name__ == '__main__':
  56. main()