PyTorch - Mnist



关于 Mnist 数据集

  • MNIST 包含70,000张手写数字图像: 60,000张用于培训,10,000张用于测试。
  • 图像是灰度的,28x28像素的,并且居中的,以减少预处理和加快运行。

代码实现

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



数据准备

data_path = 'data/mnist'

transform = torchvision.transforms.Compose([
                                   torchvision.transforms.ToTensor(),
                                   torchvision.transforms.Normalize(
                                       (0.1307,), (0.3081,))
                               ])
train_dataset = torchvision.datasets.MNIST(data_path, train=True, download=True, transform=transform)
test_dataset = torchvision.datasets.MNIST(data_path, train=False, download=True, transform=transform)


batch_size_train = 64
batch_size_test = 1000

# batch_size: 一次性加载的数据量; num_workers=4 使用4个子进程加载数据 
train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=batch_size_train, shuffle=True, num_workers=4)
test_loader = torch.utils.data.DataLoader(test_dataset, batch_size=batch_size_test, shuffle=True, num_workers=4)

查看数据组成

examples = enumerate(test_loader)
batch_idx, (example_data, example_targets) = next(examples)


batch_idx # 0

example_data.shape 
# torch.Size([1000, 1, 28, 28])


example_data
'''
tensor([[[[-0.4242, -0.4242, -0.4242,  ..., -0.4242, -0.4242, -0.4242],
          [-0.4242, -0.4242, -0.4242,  ..., -0.4242, -0.4242, -0.4242], 
          ...,  
          [-0.4242, -0.4242, -0.4242,  ..., -0.4242, -0.4242, -0.4242]]],
        ...,
 
        [[[-0.4242, -0.4242, -0.4242,  ..., -0.4242, -0.4242, -0.4242], 
          ...,  
          [-0.4242, -0.4242, -0.4242,  ..., -0.4242, -0.4242, -0.4242]]]])
'''

example_targets
'''
tensor([3, 3, 2, 7, 5, 7, 6, 5, 4, 8, 3, 1, 7, 8, 0, 1, 4, 7, 9, 4, 4, 4, 6, 1, 7, 8, 8, 0, 9, 7, 2, 1])
'''

print(example_data.shape) # torch.Size([1000, 1, 28, 28])

显示图片


fig = plt.figure()
for i in range(6):
    plt.subplot(2, 3, i + 1)
    plt.tight_layout()
    plt.imshow(example_data[i][0], cmap='gray', interpolation='none')
    plt.title("Ground Truth: {}".format(example_targets[i]))
    plt.xticks([])
    plt.yticks([])
    
plt.show()

在这里插入图片描述


定义网络


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)

训练


设置超参数

n_epochs = 3
learning_rate = 0.01
momentum = 0.5
log_interval = 10
random_seed = 1
torch.manual_seed(random_seed)

设置模型保存地址等

import os 
model_dir = '/Users/xx/mnist/model/'
model_path = os.path.join(model_dir, 'model.pth')
optimizer_path = os.path.join(model_dir, 'optimizer.pth')
def train(epoch):
    
    network.train()
    
    for batch_idx, (data, target) in enumerate(train_loader):
        optimizer.zero_grad()
        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),
                len(train_loader.dataset), 100. * batch_idx / len(train_loader), loss.item()))
            
            train_losses.append(loss.item())
            train_counter.append((batch_idx * 64) + ((epoch - 1) * len(train_loader.dataset)))

            torch.save(network.state_dict(), model_path)
            torch.save(optimizer.state_dict(), optimizer_path)
            
train(1)
'''
-- Train Epoch: 1 [0/60000 (0%)]	Loss: 2.371851
-- Train Epoch: 1 [6400/60000 (11%)]	Loss: 2.068980
-- Train Epoch: 1 [12800/60000 (21%)]	Loss: 1.208917
-- Train Epoch: 1 [19200/60000 (32%)]	Loss: 0.748824
-- Train Epoch: 1 [25600/60000 (43%)]	Loss: 0.609824
...
-- Train Epoch: 1 [57600/60000 (96%)]	Loss: 0.467529
'''

测试

def test():
    network.eval()
    test_loss = 0
    correct = 0
    
    with torch.no_grad():
        for data, target in test_loader:
            output = network(data)
            test_loss += F.nll_loss(output, target, reduction='sum').item()
            pred = output.data.max(1, keepdim=True)[1]
            correct += pred.eq(target.data.view_as(pred)).sum()
            
    test_loss /= len(test_loader.dataset)
    test_losses.append(test_loss)
    print('\n-- Test set: Avg. loss: {:.4f}, Accuracy: {}/{} ({:.0f}%)\n'.format(
        test_loss, correct, len(test_loader.dataset),
        100. * correct / len(test_loader.dataset)))



test()  
# Test set: Avg. loss: 0.2085, Accuracy: 9396/10000 (94%)

for epoch in range(1, n_epochs + 1):
    train(epoch)
    test()


'''
-- Train Epoch: 1 [0/60000 (0%)]	Loss: 0.365044
-- Train Epoch: 1 [6400/60000 (11%)]	Loss: 0.463751
-- Train Epoch: 1 [12800/60000 (21%)]	Loss: 0.384765
-- Train Epoch: 1 [19200/60000 (32%)]	Loss: 0.439015
-- Train Epoch: 1 [25600/60000 (43%)]	Loss: 0.386983
-- Train Epoch: 1 [32000/60000 (53%)]	Loss: 0.287491
-- Train Epoch: 1 [38400/60000 (64%)]	Loss: 0.313556
-- Train Epoch: 1 [44800/60000 (75%)]	Loss: 0.612881
-- Train Epoch: 1 [51200/60000 (85%)]	Loss: 0.340482
-- Train Epoch: 1 [57600/60000 (96%)]	Loss: 0.290289

Test set: Avg. loss: 0.1251, Accuracy: 9617/10000 (96%)

-- Train Epoch: 2 [0/60000 (0%)]	Loss: 0.449924
-- Train Epoch: 2 [6400/60000 (11%)]	Loss: 0.438897
-- Train Epoch: 2 [12800/60000 (21%)]	Loss: 0.292782
...
-- Train Epoch: 2 [57600/60000 (96%)]	Loss: 0.404231

Test set: Avg. loss: 0.1002, Accuracy: 9688/10000 (97%)

-- Train Epoch: 3 [0/60000 (0%)]	Loss: 0.202292
-- Train Epoch: 3 [6400/60000 (11%)]	Loss: 0.512848
-- Train Epoch: 3 [12800/60000 (21%)]	Loss: 0.255428
...
-- Train Epoch: 3 [57600/60000 (96%)]	Loss: 0.186922

Test set: Avg. loss: 0.0845, Accuracy: 9727/10000 (97%)
'''

examples = enumerate(test_loader)
batch_idx, (example_data, example_targets) = next(examples)

with torch.no_grad():
    output = network(example_data)
    
output

fig = plt.figure()
for i in range(6):
    plt.subplot(2, 3, i + 1)
    plt.tight_layout()
    plt.imshow(example_data[i][0], cmap='gray', interpolation='none')
    plt.title("Prediction: {}".format(output.data.max(1, keepdim=True)[1][i].item()))
    plt.xticks([])
    plt.yticks([])
plt.show()

在这里插入图片描述



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')

# Text(0, 0.5, 'negative log likelihood loss')

在这里插入图片描述


LeNet 网络

定义网络模型

class LeNet(nn.Module):
    def __init__(self):
        super(LeNet, self).__init__()
        
        # 1-输入一张灰度图, 6-输出6张特征图,(5,5)也可简化为5,大小为 5*5 的卷积核过滤器。
        self.c1 = nn.Conv2d(1, 6, (5, 5))
        
        # 输入 6 张特诊图,输出 16 张特征图,过滤器仍为 5*5 
        self.c3 = nn.Conv2d(6, 16, 5)
        
        # 由池化层 S4 中所有的特征点(共 16*4*4 个),全连接到 120 个点。
        self.fc1 = nn.Linear(16*4*4, 120)
        
        # 由 120 个点,全连接到 84 个点
        self.fc2 = nn.Linear(120, 84)
        
        # 由 84 个点,全连接到输出层中的 10 个点
        self.fc3 = nn.Linear(84, 10)
    
    def forward(self, x):
        
        # 池化核大小为 2*2,也可简化为参数 2 
        x = F.max_pool2d(F.relu(self.c1(x)), 2) 
        x = F.max_pool2d(F.relu(self.c3(x)), 2) 
        
        x = x.view(-1, self.num_flat_features(x))
        x = F.relu(self.fc1(x))
        x = F.relu(self.fc2(x))
        x = self.fc3(x)
        return x
    
    def num_flat_features(self, x):
        size = x.size()[1:]
        num_features = 1
        for s in size:
            num_features *= s
        return num_features
        

训练

加载网络

if torch.cuda.is_available():
    lenet = LeNet().cuda()
else:
    lenet = LeNet()

lenet

LeNet(
  (c1): Conv2d(1, 6, kernel_size=(5, 5), stride=(1, 1))
  (c3): Conv2d(6, 16, kernel_size=(5, 5), stride=(1, 1))
  (fc1): Linear(in_features=256, out_features=120, bias=True)
  (fc2): Linear(in_features=120, out_features=84, bias=True)
  (fc3): Linear(in_features=84, out_features=10, bias=True)
)

训练

def train(model, criterion, optimizer, epochs=1):
    
    for epoch in range(epochs):
        running_loss = 0.0
        
        for i, data in enumerate(train_loader, 0):
            inputs, labels = data
            
            if torch.cuda.is_available():
                inputs, labels = inputs.cuda(), labels.cuda()
                
            optimizer.zero_grad()
            outputs = model(inputs)
            
            loss = criterion(outputs, labels)
            loss.backward()
            optimizer.step()
            
            running_loss += loss.item()
            if i%1000==999:
                print(f'-- epoch : {epoch+1}, %%bashatch : {i+1}, loss: {running_loss/1000} ')
                running_loss = 0.0

    print('\n\n-- end trainning')
        


2023-02-08

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AI工程化

请我喝杯伯爵奶茶~!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值