手写数字识别使用MNIST数据集(通俗易懂的代码)

标题用torch实现手写数字识别

import os
import torch
import torchvision
from torchvision.transforms import Compose,ToTensor,Normalize
from torch.utils.data import DataLoader
from torch import nn, optim
import torch.nn.functional as F
import numpy as np

TRAIN_BATCH_SIZE = 128
TEST_BATCH_SIZE = 1000

# 获取dataloader
def get_dataloader(train=True,batch_size=TRAIN_BATCH_SIZE):
    # 图片处理
    transform_fn = Compose([
        ToTensor(),  # 转换成tensor,(1X28X28)
        Normalize(   # 归一化处理加入均值和标准差,因为是单通道所依元组里边元素个数为1
            (0.1307,), (0.3081,))
    ])
    dataset = torchvision.datasets.MNIST(root="./data",train=train,download=True,transform=transform_fn)
    return DataLoader(dataset=dataset,batch_size=batch_size,shuffle=True)


# data = get_dataloader()
# for i in enumerate(data):
#     print(i)
#     break
#
# print(len(data))  # 查看数据总批次

class ImageNet(nn.Module):
    def __init__(self):
        super(ImageNet, self).__init__()
        self.fc1 = nn.Linear(1*28*28, 28)  # 构建网络层
        self.fc2 = nn.Linear(28, 10)

    def forward(self, data):  # data的形状:[batch_size,1,28,28]
        features = data.view(data.size(0), 1*28*28)  # 需要变形成 (批次图片数量,特征数)
        features = self.fc1(features)  # (batch_size,28)
        features = F.relu(features)  # (batch_size,28)
        out = self.fc2(features)    # (batch_size,10)
        # return out
        return F.log_softmax(out, dim=-1)


model = ImageNet()  # 模型实例化
optimizer = optim.Adam(model.parameters(), lr=0.001)  # 优化器
# 假设已有训练好的模型或者优化器权值
if os.path.exists('./models/model.pkl'):
    model.load_state_dict(torch.load('./models/model.pkl'))
    optimizer.load_state_dict(torch.load('./models/optimizer.pkl'))

# criterion = nn.NLLLoss()
# criterion = nn.CrossEntropyLoss()  # 交叉熵损失函数


# 模型训练
def train(epoch):
    mode = True
    model.train(mode=mode)
    train_dataloader = get_dataloader(train=mode)
    for idx, (data, target) in enumerate(train_dataloader):
        optimizer.zero_grad()
        output = model(data)  # 调用模型得到预测值
        # loss = criterion(output,target) #对数似然损失
        loss = F.nll_loss(output,target)  # 得到损失
        loss.backward()  # 反向传播
        optimizer.step()  # 权值更新
        if idx % 10 == 0:
            print('第%d轮次,损失值为%f' % (epoch, loss.item()))

        # 模型保存
        if idx % 100 == 0:
            torch.save(model.state_dict(), './models/model.pkl')  # 模型保存
            torch.save(optimizer.state_dict(), './models/optimizer.pkl')  # 权值保存


# 模型评估
def test():
    test_loss = []
    correct = []
    model.eval()
    test_dataloader = get_dataloader(train=False, batch_size=TEST_BATCH_SIZE)
    with torch.no_grad():  # 不对操作进行跟踪记录
        for data, target in test_dataloader:
            output = model(data)
            test_loss.append(F.nll_loss(output, target))  # 损失列表
            pred = output.data.max(dim=1)[1]  # 获取最大值的位置,[batch_size,1]
            correct.append(pred.eq(target).float().mean())  # 每个批次的平均准确率
    print('模型损失%f,平均准确率%f' % (np.mean(test_loss), np.mean(correct)))


if __name__ == '__main__':
	# 训练5轮次
    for i in range(5):
        train(i)
    test()
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小帆芽芽

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值