pytorch入门(四)搭建多层的神经网络

本文介绍了如何使用PyTorch搭建多层神经网络,从读取MNIST数据集,数据预处理,构建计算图,选择网络层和激活函数,到选择损失函数与优化器,再到训练模型和模型评估的全过程。通过实例展示了神经网络的构建和训练,特别强调了ReLU激活函数和CrossEntropy损失函数的选择。
摘要由CSDN通过智能技术生成


MNIST是一个非常有名的手写体数字识别数据集,在很多资料中,这个数据集都会被用作深度学习的入门样例,接下来将围绕 MNIST数据集 训练多层的神经网络模型。

读取数据

数据集描述

MNIST数据集由250 个不同人手写的数字构成,其训练数据集包含 60,000 个样本, 测试数据集包含 10,000 样本。在 MNIST 数据集中的每张图片由 28 x 28 个像素点构成, 每个像素点用一个灰度值表示。labels 包含了相应的目标变量, 也就是手写数字的类标签(整数 0-9)

读取数据

## 读取pytorch自带数据集Minist
import torch
import torchvision.datasets as dset

root = 'D:\\pytorch\\mnistData\\'
train_set = dset.MNIST('root', train=True, download=False) # train为true表示读取训练集,false表示读取测试集,
test_set = dset.MNIST('root', train=False, download=False) # download为True表示下载,为false表示从本地读取
## 描述数据集
print("train_data:", train_set.train_data.size())
print("train_labels:", train_set.train_labels.size())
print("test_data:", test_set.test_data.size())

样本数据量大小:
在这里插入图片描述
train_set是一个torchvision.datasets.mnist.MNIST类型, 其包含如下信息:
在这里插入图片描述
对train_set 取样发现train_set包含两类信息:原数据
一个是手写数字的像素信息,由于在读取数据时未transform参数,所以特征信息并未转化为tensor类型,而是图片类型;另一个信息则是label,类型为int。
接下来打印前20组数据图像:

for i in range(24):
    image,label = train_set[i]
    path = 'D:\\pytorch\\mnistData\\MNIST\\figure\\{}-{}.png'.format(i,label)
    image.save(path)

由于image.show()仅显示一个临时图片,故将图片保存后做一个展示。
在这里插入图片描述test 内的数据和训练集数据结构相同,不再赘述。

数据预处理

由于读取数据时未定义Transform参数,故读取数据并非是tensor,参考博客link的处理方法,先定义一个转换,而后在读取数据时将此转换赋值到参数transform中读取。

  • 定义数据转换方式
# transforms.ToTensor()将图片转换成PyTorch中处理的对象Tensor,并且进行标准化(数据在0~1之间)
# transforms.Normalize()做归一化。它进行了减均值,再除以标准差。两个参数分别是均值和标准差
# transforms.Compose()函数则是将各种预处理的操作组合到了一起
data_tf = transforms.Compose(
    [transforms.ToTensor(),
     transforms.Normalize([0.5], [0.5])])

其中,transforms.ToTensor函数将图像类型数据转化为Tensor类型,并且做了一个归一化处理,即将Tensor数值均除以255;而Normalize函数对tensor做标准化处理,即将色彩值映射到[-1,1]闭区间里面,假设原色彩值是0,那么映射后就是-1。因为mnist图片都是灰度图,所以只有一个色彩通道。正常的彩色图片是RGB三通道的,transforms.Normalize([r,g,b],[d,e,f])这样对应每个RGB的均值和方差。

利用dataloader读取train_set及test_set,该函数将读取的dataset根据batch size大小、是否shuffle等封装成一个Batch Size大小的Tensor,用于后面的训练。

from torch.utils.data import dataloader

train_dataset = dset.MNIST('root', train=True, transform=data_tf, download=False)
test_dataset = dset.MNIST('root', train=False, transform=data_tf) # 按data_tf的方式转化数据
train_loader = dataloader.DataLoader(dataset=train_set, batch_size=64, shuffle=True) # 数据加载器。组合了一个数据集和采样器,并提供关于数据的迭代器
test_loader = dataloader.DataLoader(dataset=test_set, batch_size=64)
# 将原数据集做一个shuffle并做批处理,每个mini-batch的数目为64个

dataloader将原数据集做一个shuffle并做批处理,每个mini-batch的数目为64个,共有938个mini-batch。

构建计算图

选择网络层

这里选择一个三层的全连接网络且每层为一个线性函数。

选择激活函数

激活函数是人工神经网络的一个极其重要的特征。它决定一个神经元是否应该被激活,激活代表神经元接收的信息与给定的信息有关。激活函数对输入信息进行非线性变换。 然后将变换后的输出信息作为输入信息传给下一层神经元。

  • 常见分类器的适用场景
    1、用于分类器时,Sigmoid函数及其组合通常效果更好。
    2、由于梯度消失问题,有时要避免使用sigmoid和tanh函数。
    3、ReLU函数是一个通用的激活函数,目前在大多数情况下使用。
    4、ReLU函数只能在隐藏层中使用。
    5、如果神经网络中出现死神经元,那么PReLU函数就是最好的选择。

Tip:可以从ReLU函数开始,如果ReLU函数没有提供最优结果,再尝试其他激活函数。

import torch
import torch.nn.functional as F
import torch.nn as nn

## 定义一个三层的全连接网络
class Model(torch.nn.Module):
    def __init__(self, in_dim, n_hidden_1, n_hidden_2, out_dim):
        super(Model,self).__init__()
        
        self.l1 = torch.nn.Linear(in_dim, n_hidden_1) #Linear中的w,b一定要初始化,若自己不定义初始化,则用默认的初始化方式初始化
        self.l2 = torch.nn.Linear(n_hidden_1, n_hidden_2)
        self.l3 = torch.nn.Linear(n_hidden_2, out_dim)
        
    # 激活函数既可以使用nn,又可以调用nn.functional
    def forward(self,x):
        out = F.relu(self.l1(x)) # # 激活函数,直接调用torch.nn.functional中集成好的Relu
        out = self.l2(out)
        out = self.l3(out)
        return out
model = Model(28 * 28, 300, 100, 10)     

选择损失函数与优化器

常见损失函数

torch.nn内置很多损失函数,下面做一个简要介绍

损失函数 表达式 应用场景
nn.CrossEntropyLoss loss ( x , c l a s s ) = − log ⁡ ( exp ⁡ ( x [ c l a s s ] ) ∑ j exp ⁡ ( x [ j ] ) ) =
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值