基于Pytorch的深度神经网络DNN实战(手写数字识别MNIST)

数据集介绍

手写数字识别数据集(MNIST)是机器学习领域的标准数据集,也是很多人在学习机器学习和深度学习常用来练手的数据集,MNIST 内的每个样本都是二维的灰度图像,如下图所示。

在 MNIST 中,模型的输入是一副图像,模型的输出就是一个与图像中对应的数字(0 至 9 之间的一个整数,不是独热编码)。

在这种多分类问题中,神经网络的输出层需要一个 softmax 激活函数, 它可以把输出层的数据归一化到 0~1 范围内,且加起来为 1,这样就可以表示概率。

环境介绍

编辑器为Pycharm,深度学习框架为Pytorch,需要用到的库有torch,torchvision,matplotlib.

自己提前配置好环境那么上面这些就没什么问题,运行过程中缺少什么库就补什么库。

代码实现

1、数据集预处理

MNIST数据集是torchvision内置的库,写完代码直接运行就能下载,速度很快不用担心。

在 torchvision 库中分别下载训练集与测试集, 因此需要从torchvision 库中导入 datasets 以下载数据集,下载前需要借助 torchvision 库中的 transforms 进行图像转换,将数据集变为tensor张量,并调整数据集的统计分布。

import matplotlib.pyplot as plt
import torch
import torch.nn as nn
from torch.utils.data import DataLoader
from torchvision import datasets, transforms

device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

transform = transforms.Compose([
                transforms.ToTensor(),
                transforms.Normalize(mean=0.1307,std=0.3081)])
train_data = datasets.MNIST(root='Dataset',
                            train=True,
                            transform=transform,
                            download=False)
test_data = datasets.MNIST(root='Dataset',
                           train=False,
                           transform=transform,
                           download=False)
train_dataloader = DataLoader(dataset=train_data,
                              batch_size=64,
                              shuffle=True)
test_dataloader = DataLoader(dataset=test_data,
                             batch_size=64,
                             shuffle=False)

在下载数据集之前,要设定转换参数: transform,该参数里解决两个问题:

 ToTensor:将图像数据转为张量,且调整三个维度的顺序为 C*W*H; C表示通道数,二维灰度图像的通道数为 1,三维 RGB 彩图的通道数为 3。

Normalize:将神经网络的输入数据转化为标准正态分布,训练更好;根据统计计算, MNIST 训练集所有像素的均值是 0.1307、标准差是 0.3081。

2、搭建神经网络

每个样本的输入都是形状为28*28 的二维数组,那么对于 DNN 来说,输入层的神经元参数就要有28*28=784 个;

输出层使用独热编码,需要 10 个参数。

class DNN(nn.Module):
    def __init__(self):
        super(DNN,self).__init__()
        self.net = nn.Sequential( # 按顺序搭建各层
        nn.Flatten(), # 把图像铺平成一维
        nn.Linear(784, 512), nn.ReLU(), # 第 1 层:全连接层
        nn.Linear(512, 256), nn.ReLU(), # 第 2 层:全连接层
        nn.Linear(256, 128), nn.ReLU(), # 第 3 层:全连接层
        nn.Linear(128, 64), nn.ReLU(), # 第 4 层:全连接层
        nn.Linear(64, 10) # 第 5 层:全连接层
        )
    def forward(self, x):
        y = self.net(x)
        return y


# 模型实例化
model = DNN()

3、定义损失函数和优化器

# 损失函数的选择
loss_fn = nn.CrossEntropyLoss() # 自带 softmax 激活函数
# 优化算法的选择
learning_rate = 0.01 # 设置学习率
optimizer = torch.optim.SGD(params=model.parameters(),lr=learning_rate,momentum = 0.5)

4、定义训练函数

# 训练
def train(train_dataloader,model,num_epoch):
    model = model.to(device)
    loss_list = []
    for epoch in range(num_epoch):
        for (x,y) in train_dataloader:
            x,y = x.to(device),y.to(device)
            pred = model(x)
            loss = loss_fn(pred,y)
            loss_list.append(loss.item())
            optimizer.zero_grad()
            loss.backward()
            optimizer.step()
    fig1 = plt.figure()
    plt.plot(range(len(loss_list)),loss_list)
    plt.show()

train(train_dataloader=train_dataloader,model=model,num_epoch=10)

5、定义测试函数

# 测试
def test(test_dataloader,model):
    correct = 0
    total = 0
    with torch.no_grad():
        for (x,y) in test_dataloader:
            x, y = x.to(device), y.to(device)
            pred = model(x)
            _,pred = torch.max(pred.data,dim=1)
            correct += torch.sum((pred == y))
            total += y.size(0)
    print(f'测试集精准度: {100 * correct / total} %')

全部代码

import matplotlib.pyplot as plt
import torch
import torch.nn as nn
from torch.utils.data import DataLoader
from torchvision import datasets, transforms

device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

transform = transforms.Compose([
                transforms.ToTensor(),
                transforms.Normalize(mean=0.1307,std=0.3081)])
train_data = datasets.MNIST(root='Dataset',
                            train=True,
                            transform=transform,
                            download=False)
test_data = datasets.MNIST(root='Dataset',
                           train=False,
                           transform=transform,
                           download=False)
train_dataloader = DataLoader(dataset=train_data,
                              batch_size=64,
                              shuffle=True)
test_dataloader = DataLoader(dataset=test_data,
                             batch_size=64,
                             shuffle=False)

class DNN(nn.Module):
    def __init__(self):
        super(DNN,self).__init__()
        self.net = nn.Sequential( # 按顺序搭建各层
        nn.Flatten(), # 把图像铺平成一维
        nn.Linear(784, 512), nn.ReLU(), # 第 1 层:全连接层
        nn.Linear(512, 256), nn.ReLU(), # 第 2 层:全连接层
        nn.Linear(256, 128), nn.ReLU(), # 第 3 层:全连接层
        nn.Linear(128, 64), nn.ReLU(), # 第 4 层:全连接层
        nn.Linear(64, 10) # 第 5 层:全连接层
        )
    def forward(self, x):
        y = self.net(x)
        return y


# 模型实例化
model = DNN()
# 损失函数的选择
loss_fn = nn.CrossEntropyLoss() # 自带 softmax 激活函数
# 优化算法的选择
learning_rate = 0.01 # 设置学习率
optimizer = torch.optim.SGD(params=model.parameters(),lr=learning_rate,momentum = 0.5)

# 训练
def train(train_dataloader,model,num_epoch):
    model = model.to(device)
    loss_list = []
    for epoch in range(num_epoch):
        for (x,y) in train_dataloader:
            x,y = x.to(device),y.to(device)
            pred = model(x)
            loss = loss_fn(pred,y)
            loss_list.append(loss.item())
            optimizer.zero_grad()
            loss.backward()
            optimizer.step()
    fig1 = plt.figure()
    plt.plot(range(len(loss_list)),loss_list)
    plt.show()

train(train_dataloader=train_dataloader,model=model,num_epoch=10)

# 测试
def test(test_dataloader,model):
    correct = 0
    total = 0
    with torch.no_grad():
        for (x,y) in test_dataloader:
            x, y = x.to(device), y.to(device)
            pred = model(x)
            _,pred = torch.max(pred.data,dim=1)
            correct += torch.sum((pred == y))
            total += y.size(0)
    print(f'测试集精准度: {100 * correct / total} %')



总结

DNN(深度神经网络)是学习深度学习的基础,它都是由线性层(全连接层组成的),这种情况下网络的参数很多,训练效率低下,并且容易造成过拟合,因此后面才会出现CNN,RNN,LSTM,TRANSFORMER等等优秀的网络和机制,不过学习好DNN后面学习才会更快上手。

本人能力有限,不足之处请指出,如果对你有帮助请点赞关注!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值