import torch
import torch.nn as nn
import torch.optim as optim
import torch.nn.functional as F
from torchvision import datasets, transforms
import matplotlib.pyplot as plt
import numpy as np
%matplotlib inline
input_size = 28
num_classes = 10 #標(biāo)簽種類
num_epochs = 3
batch_size = 64
train_dataset = datasets.MNIST(root='./data', train=True, transform=transforms.ToTensor(), download=True)
test_dataset = datasets.MNIST(root='./data', train=False, transform=transforms.ToTensor())
train_loader = torch.utils.data.DataLoader(dataset=train_dataset, batch_size=batch_size, shuffle=True)
test_loader = torch.utils.data.DataLoader(dataset=test_dataset, batch_size=batch_size, shuffle=True)
class CNN(nn.Module):
? ? def __init__(self):
? ? ? ? super(CNN, self).__init__()
? ? ? ? self.conv1 = nn.Sequential(
? ? ? ? ? ? nn.Conv2d(
? ? ? ? ? ? ? ? in_channels=1,
? ? ? ? ? ? ? ? out_channels=16,
? ? ? ? ? ? ? ? kernel_size=5,
? ? ? ? ? ? ? ? stride=1,
? ? ? ? ? ? ? ? padding=2,
? ? ? ? ? ? ),
? ? ? ? ? ? nn.ReLU(),
? ? ? ? ? ? nn.MaxPool2d(kernel_size=2),
? ? ? ? )
? ? ? ? self.conv2 = nn.Sequential(
? ? ? ? ? ? nn.Conv2d(16, 32, 5, 1, 2),
? ? ? ? ? ? nn.ReLU(),
? ? ? ? ? ? nn.Conv2d(32, 32, 5, 1, 2),
? ? ? ? ? ? nn.ReLU(),
? ? ? ? ? ? nn.MaxPool2d(2),
? ? ? ? )
? ? ? ? self.conv3 = nn.Sequential(
? ? ? ? ? ? nn.Conv2d(32, 64, 5, 1, 2),
? ? ? ? ? ? nn.ReLU(),
? ? ? ? )
? ? ? ? self.out = nn.Linear(64*7*7, 10)
? ? def forward(self, x):
? ? ? ? x = self.conv1(x)
? ? ? ? x = self.conv2(x)
? ? ? ? x = self.conv3(x)
? ? ? ? x = x.view(x.size(0), -1) #第一維不變,后面flatten
? ? ? ? output = self.out(x)
? ? ? ? return output
def accuracy(predictions, labels):
? ? pred = torch.max(predictions.data, 1)[1] #兩個(gè)返回值,一個(gè)是value, 一個(gè)是index
? ? rights = pred.eq(labels.data.view_as(pred)).sum()
? ? return rights, len(labels)
# 實(shí)例化
net = CNN()
#損失函數(shù)
criterion = nn.CrossEntropyLoss()
#優(yōu)化器
optimizer = optim.Adam(net.parameters(), lr=0.001) #定義優(yōu)化器,普通的隨機(jī)梯度下降算法
#開始訓(xùn)練循環(huán)
for epoch in range(num_epochs):
? ? #當(dāng)前epoch的結(jié)果保存下來
? ? train_rights = []
? ? for batch_idx, (data, target) in enumerate(train_loader):? #針對(duì)容器中的每一個(gè)批進(jìn)行循環(huán)
? ? ? ? net.train()? ? ? ? ? ? ? ? ? ? ? ? ? ?
? ? ? ? output = net(data)
? ? ? ? loss = criterion(output, target)
? ? ? ? optimizer.zero_grad()
? ? ? ? loss.backward()
? ? ? ? optimizer.step()
? ? ? ? right = accuracy(output, target)
? ? ? ? train_rights.append(right)
? ? ? ? if batch_idx % 100 == 0:
? ? ? ? ? ? net.eval()
? ? ? ? ? ? val_rights = []
? ? ? ? ? ? for (data, target) in test_loader:
? ? ? ? ? ? ? ? output = net(data)
? ? ? ? ? ? ? ? right = accuracy(output, target)
? ? ? ? ? ? ? ? val_rights.append(right)
? ? ? ? ? ? #準(zhǔn)確率計(jì)算
? ? ? ? ? ? train_r = (sum([tup[0] for tup in train_rights]), sum([tup[1] for tup in train_rights]))
? ? ? ? ? ? val_r = (sum([tup[0] for tup in val_rights]), sum([tup[1] for tup in val_rights]))
? ? ? ? ? ? print('當(dāng)前epoch: {} [{}/{} ({:.0f}%)]\t損失: {:.6f}\t訓(xùn)練集準(zhǔn)確率: {:.2f}%\t測(cè)試集正確率: {:.2f}%'.format(
? ? ? ? ? ? ? ? epoch, batch_idx * batch_size, len(train_loader.dataset),
? ? ? ? ? ? ? ? 100. * batch_idx / len(train_loader),
? ? ? ? ? ? ? ? loss.data,
? ? ? ? ? ? ? ? 100. * train_r[0].numpy() / train_r[1],
? ? ? ? ? ? ? ? 100. * val_r[0].numpy() / val_r[1]))