import torch
from torch import nn
from torch.nn import init
import torchvision
import torchvision.transforms as transforms
import sys
import d2lzh_pytorch as d2l
import time
batch_size=128
trainset = torchvision.datasets.MNIST(root="D:/pythonlearning",train=True, transform=
transforms.ToTensor(),
)
testset = torchvision.datasets.MNIST(root="D:/pythonlearning",train=False, transform=
transforms.ToTensor(),
)
trainloader = torch.utils.data.DataLoader(dataset=trainset,batch_size=batch_size,shuffle=True)
testloader = torch.utils.data.DataLoader(dataset=testset,batch_size=batch_size,shuffle=True)
lr = 0.003
num_epochs = 20
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.conv = nn.Sequential(
#28*28-->28
nn.Conv2d(in_channels=1, out_channels=16, kernel_size=3, stride=1, padding=1),
nn.ReLU(),
#28-->14
nn.MaxPool2d(kernel_size=2, stride=2, padding=0),
#14*14-->14
nn.Conv2d(in_channels=16, out_channels=32, kernel_size=3, stride=1, padding=1),
nn.ReLU(),
#14-->7
nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
)
self.fc = nn.Sequential(
nn.Linear(32*7*7, 84),
nn.ReLU(),
nn.Linear(84, 10)
)
def forward(self, x):
feature = self.conv(x) # x:(batch, 32, 7, 7)
output = self.fc(feature.view(x.shape[0],-1))# x:(batch, 32*7*7)
return output
net = Net()
print(net)
optimizer = torch.optim.Adam(net.parameters(), lr=lr)#Adam算法优化
d2l.train_ch5(net, trainloader, testloader, batch_size, optimizer, device, num_epochs)#训练模型
网络模型:
训练结果:
贴上训练模型函数(d2l包中):
# 该函数已保存在d2lzh_pytorch包中
def evaluate_accuracy(data_iter, net, device=None):
if device is None and isinstance(net, torch.nn.Module):
# 如果没指定device就使用net的device
device = list(net.parameters())[0].device
acc_sum, n = 0.0, 0
with torch.no_grad():
for X, y in data_iter:
if isinstance(net, torch.nn.Module):
net.eval() # 评估模式, 这会关闭dropout
acc_sum += (net(X.to(device)).argmax(dim=1) == y.to(device)).float().sum().cpu().item()
net.train() # 改回训练模式
else: # 自定义的模型, 3.13节之后不会用到, 不考虑GPU
if('is_training' in net.__code__.co_varnames): # 如果有is_training这个参数
# 将is_training设置成False
acc_sum += (net(X, is_training=False).argmax(dim=1) == y).float().sum().item()
else:
acc_sum += (net(X).argmax(dim=1) == y).float().sum().item()
n += y.shape[0]
return acc_sum / n
# 该函数已保存在d2lzh_pytorch包中
def train_ch5(net, train_iter, test_iter, batch_size, optimizer, device, num_epochs):
net = net.to(device)
print("training on ", device)
loss = torch.nn.CrossEntropyLoss()
for epoch in range(num_epochs):
train_l_sum, train_acc_sum, n, batch_count, start = 0.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)
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))