基于BP神经网络的图像分类

本文介绍了使用BP神经网络对MNIST手写数字数据集进行分类的实验,包括数据集介绍、网络设计、训练过程及完整代码。网络结构包括1个输入层,3个隐藏层和1个输出层,激活函数采用了非线性变换,优化器选用Adam,损失函数为交叉熵。训练过程中,每轮训练后都会评估并保存最佳模型权重。
摘要由CSDN通过智能技术生成

1 数据集

本次BP神经网络分类实验所用数据集为MNIST手写数据集。

MNIST 数据集来自美国国家标准与技术研究所, National Institute of Standards and Technology (NIST)。训练集 (training set) 由来自 250 个不同人的手写的数字构成, 其中 50% 是高中学生, 50% 来自人口普查局 (the Census Bureau) 的工作人员。测试集(test set) 也是同样比例的手写数字数据。

训练数据集包含60000个样本, 测试数据集包含10000样本。在 MNIST 数据集中,每张图片由28×28个像素点构成, 每个像素点用一个灰度值表示。使用时,将28×28的像素展开成一个维度为784的一维的向量, 向量中的值对应图片中的像素值。此外,还有一个标签数组,对应每张图片所属的手写数字类别(整数0-9)。

本次实验基于Pytorch框架,使用Pytorch自带工具包可完成MNIST数据集的下载及预处理。下图所示代码分别完成了训练数据和测试数据的下载,预处理及加载。

#1.Load the train datasets and test datasets    
train_transformations = transforms.Compose([        
    transforms.ToTensor(),        
    transforms.Normalize((0.5,), (0.5,))    
])    
train_set = MNIST(root="./data", train=True, transform=train_transformations, download=True)    
train_loader = DataLoader(train_set,batch_size=128,shuffle=True,num_workers=4)    
test_transformations = transforms.Compose([        
    transforms.ToTensor(),        
    transforms.Normalize((0.5,), (0.5,))    
])    
test_set = MNIST(root="./data", train=False, transform=test_transformations, download=True)    
test_loader = DataLoader(test_set,batch_size=128,shuffle=False,num_workers=0)

观察MNIST单个样本数据时,发现其中的像素值范围在(0,1)之间,说明已经被整除256,后续无需再重复这一操作。先将28×28的二维数据转换成张量Tensor的形式,再进行标准化处理,将数据映射到(-1,1)之间,最后将数据进行批处理,每批包含128(2的倍数,方便GPU处理)个样本,完成数据的加载。加载时设置打乱训练样本的顺序,不打乱测试样本的顺序。

2 分类网络设计

本次分类BP神经网络共有5层,包括1个输入层,3个隐藏层和一个输出层。层与层之间均采用全连接的形式。输入层有784个节点,对应MNIST单个样本的像素值总数;隐藏层的节点数分别为1024,1024,2048;输出层共有10个节点,用于分类,输出结果为(0-9)的预测概率。详细网络结构图如下所示。
在这里插入图片描述

3 训练过程

训练过程主要分为以下四个步骤,分别为:

  1. 加载训练数据集和测试数据集;

  2. 初始化模型;

  3. 定义优化器和损失函数;

  4. 训练模型及保存权重参数;

下面对每个步骤详细展开介绍。

3.1 加载训练数据集和测试数据集

数据集的加载包括训练数据集和测试数据集的加载,训练数据集用于训练模型,测试数据集用于训练过程中对模型的性能进行实时监测。本次所用数据集为MNIST书写数字数据集,包括60000个训练样本和10000个测试样本,具体加载方式在第一章已详细介绍。

3.2 初始化模型

本次分类BP神经网络共有5层,包括1个输入层,3个隐藏层和一个输出层。层与层之间均采用全连接的形式。代码实现时,只需要实现3个隐藏层和1个输出层的设计即可。

每个隐藏层都由一个线性全连接层和一个激活函数构成,为了方便起见,自定义一个隐藏层模块,主要是定义线性全连接层的输入和输出节点数,激活函数的选取,实现过程如下所示。

# Build the neural network
class Unit(nn.Module):    
    def __init__(self, in_features, out_features):        
        super(Unit, self).__init__()
        
        self.fc=nn.Linear(in_features, out_features, True)        
        self.relu = nn.ReLU()
        
    def forward(self, input):        
        output = self.fc(input)        
        output = self.relu(output)        
        return output

接着,调用上面定义好的隐藏层模块实现整个网络的设计。将3个隐藏层根据其输入和输出节点数一一定义出来,再将这3个隐藏层组合成一个小网络。然后根据分类的类别数定义出输出层,也就是最后一个全连接层。最后在前向传播函数中,将这些层的输入输出拼接起来,实现整个网络的结构设计。代码实现如下所示。

class SimpleNet(nn.Module):    
    def __init__(self, num_classes
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值