使用 pytorch 實現手寫數字識別(GPU加速)

Sample Code
import torch
import torchvision
from torch.utils.data import DataLoader
from torch import nn
import torch.nn.functional as F
import matplotlib.pyplot as plt

n_epochs = 5
batch_size_train = 64
batch_size_test = 1000
learning_rate = 0.01
momentum = 0.5
log_interval = 100
torch.backends.cudnn.enabled = False
random_seed = 19260817
torch.manual_seed(random_seed)

train_loader = torch.utils.data.DataLoader(
    torchvision.datasets.MNIST('./data/', train=True, download=True,
                               transform=torchvision.transforms.Compose([   # 歸一化並轉化爲Tensor
                                   torchvision.transforms.ToTensor(),
                                   torchvision.transforms.Normalize(
                                       (0.1307,), (0.3081,))
                               ])),
    batch_size=batch_size_train, shuffle=True)
test_loader = torch.utils.data.DataLoader(
    torchvision.datasets.MNIST('./data/', train=False, download=True,
                               transform=torchvision.transforms.Compose([
                                   torchvision.transforms.ToTensor(),
                                   torchvision.transforms.Normalize(
                                       (0.1307,), (0.3081,))
                               ])),
    batch_size=batch_size_test, shuffle=True)

class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.conv1 = nn.Conv2d(1, 10, kernel_size=5)
        self.conv2 = nn.Conv2d(10, 20, kernel_size=5)
        self.conv2_drop = nn.Dropout2d()
        self.fc1 = nn.Linear(320, 50)
        self.fc2 = nn.Linear(50, 10)

    def forward(self, x):
        x = F.relu(F.max_pool2d(self.conv1(x), 2))
        x = F.relu(F.max_pool2d(self.conv2_drop(self.conv2(x)), 2))
        x = x.view(-1, 320)
        x = F.relu(self.fc1(x))
        x = F.dropout(x, training=self.training)
        x = self.fc2(x)
        return F.log_softmax(x, dim=1)


network = Net()
network = network.cuda()
optimizer = torch.optim.SGD(network.parameters(), lr=learning_rate, momentum=momentum)

train_dataset_size = len(train_loader.dataset)
train_size = len(train_loader)
test_dataset_size = len(test_loader.dataset)
test_size = len(test_loader)

train_losses = []
train_counter = []
test_losses = []
test_counter = [i * train_dataset_size for i in range(n_epochs + 1)]

def train(epoch):
    network.train()     # 訓練時, 調整網絡至訓練狀態,啓用 BN 和 Dropout
    for batch_idx, (data, target) in enumerate(train_loader):
        data = data.cuda()
        target = target.cuda()
        optimizer.zero_grad()      # 梯度歸零,保證每個 batch 互不干擾
        output = network(data)
        loss = F.nll_loss(output, target)
        loss.backward()     # 反向傳播計算梯度值
        optimizer.step()    # 梯度下降實現參數更新
        if batch_idx % log_interval == 0:
            print('Train Epoch: {} [{}/{} ({:.0f}%)]\tLoss: {:.6f}'.format(epoch, batch_idx * len(data),
                    train_dataset_size, 100. * batch_idx / train_size, loss.item()))
            train_losses.append(loss.item())        # 方便後續畫圖
            train_counter.append((batch_idx * batch_size_train) + ((epoch - 1) * train_dataset_size))


def test():
    network.eval()      # 評價時,禁用 BN 和 Dropout
    test_loss = correct = 0
    with torch.no_grad():   # 保證 requires_grad = False
        for data, target in test_loader:
            data = data.cuda()
            target = target.cuda()
            output = network(data)
            test_loss += F.nll_loss(output, target, reduction='sum').item()
            pred = output.data.max(1, keepdim=True)[1]
            pred = pred.cuda()
            correct += pred.eq(target.data.view_as(pred)).sum()     # 計算正確答案數量
    test_loss /= test_dataset_size
    test_losses.append(test_loss)
    print('\nTest set: Avg. loss: {:.4f}, Accuracy: {}/{} ({:.0f}%)\n'.format(
        test_loss, correct, test_dataset_size, 100. * correct / test_dataset_size))
    
test()
for i in range(1, n_epochs + 1):
    train(i)
    test()

fig = plt.figure()
plt.plot(train_counter, train_losses, color='blue')
plt.scatter(test_counter, test_losses, color='red')
plt.legend(['Train Loss', 'Test Loss'], loc='upper right')
plt.xlabel('number of training examples seen')
plt.ylabel('negative log likelihood loss')
plt.show()
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章