import torch
import torchvision
import torch.utils.data as data
import torch.nn as nn
import matplotlib.pyplot as plt
import numpy as np
transform = torchvision.transforms.ToTensor()
train_dataset = torchvision.datasets.MNIST(root='./data', train=True, transform=transform, download=True)
test_dataset = torchvision.datasets.MNIST(root='./data', train=False, transform=transform, download=True)
batch_size = 128
train_loader = data.DataLoader(dataset=train_dataset, batch_size=batch_size, shuffle=True)
test_loader = data.DataLoader(dataset=test_dataset, batch_size=batch_size, shuffle=True)
class LeNet(nn.Module):
def __init__(self):
super(LeNet, self).__init__()
self.conv1 = nn.Sequential(
# 1,28,28
nn.Conv2d(
in_channels=1,
out_channels=32,
kernel_size=5,
padding=2,
stride=1
),
# 16,28,28
nn.ReLU(),
nn.MaxPool2d(kernel_size=2, stride=2)
# 16,14,14
)
self.conv2 = nn.Sequential(
nn.Conv2d(
in_channels=32,
out_channels=16,
kernel_size=5
),
# 16,10,10
nn.ReLU(),
nn.MaxPool2d(kernel_size=2, stride=2)
# 16,5,5
)
self.fc1 = nn.Sequential(
nn.Linear(16 * 5 * 5, 120),
nn.ReLU()
)
self.fc2 = nn.Sequential(
nn.Linear(120, 84),
nn.ReLU()
)
self.fc3 = nn.Linear(84, 10)
def forward(self, x):
x = self.conv1(x)
x = self.conv2(x)
x = x.view(x.size(0), -1) # 拉伸
x = self.fc1(x)
x = self.fc2(x)
x = self.fc3(x)
return x
device = ('cuda' if torch.cuda.is_available() else 'cpu')
net = LeNet().to(device)
# 优化器
optimizer = torch.optim.Adam(net.parameters(), lr=1e-3)
# 损失函数
loss_func = nn.CrossEntropyLoss()
epoches = 1
costs = []
for epoch in range(epoches):
sum_loss = 0
net.train()
for step, (batch_x, batch_y) in enumerate(train_loader):
if torch.cuda.is_available():
batch_x = batch_x.cuda()
batch_y = batch_y.cuda()
# 梯度清零
optimizer.zero_grad()
output = net(batch_x)
loss = loss_func(output, batch_y)
loss.backward()
optimizer.step()
costs.append(loss)
sum_loss += loss
if step % 100 == 0:
print(f'epoch:{epoch + 1},mini_batch:{step + 1},mini_loss:{sum_loss / 100}')
sum_loss = 0.0
# 验证
net.eval()
correct = 0
total = 0
for (test_x, test_y) in test_loader:
if torch.cuda.is_available():
test_x = test_x.cuda()
test_y = test_y.cuda()
test_output = net(test_x)
predicted = torch.max(test_output, 1)[1]
total += test_y.size(0)
correct += (predicted == test_y).sum()
print(f'correct:{correct}')
print(f'total:{total}')
print(f'Test acc:{(correct / total * 100):.2f}%')
# 绘制函数
if torch.cuda.is_available():
costs = [cost.cpu().detach().numpy() for cost in costs]
else:
costs = [cost.numpy for cost in costs]
plt.plot(costs)
plt.xlabel('number of iteration')
plt.ylabel('loss in train')
plt.title('LeNet')
plt.show()
loss 函数: