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=10):        super(SimpleNet, self).__init__()self.unit1 = Unit(in_features=784,out_features=1024)        self.unit2 = Unit(in_features=1024, out_features=1024)        self.unit3 = Unit(in_features=1024, out_features=2048)        self.net = nn.Sequential(self.unit1, self.unit2, self.unit3)        self.fc = nn.Linear(in_features=2048,out_features=num_classes)def forward(self, input):        output = self.net(input)        output = self.fc(output)        return output

完成网络结构设计后,通过实例化这个类来初始化训练模型。为了加速训练过程,选择在GPU上进行模型的训练和测试,具体过程如下所示。

#2.Initialize model
cuda_avail = torch.cuda.is_available()
model = SimpleNet(num_classes=10)
cuda_avail = torch.cuda.is_available()
if cuda_avail:        model.cuda()

3.3 定义优化器和损失函数

本次实验选用Adam优化器,它结合AdaGrad和RMSProp两种优化算法的优点。对梯度的一阶矩估计(First Moment Estimation,即梯度的均值)和二阶矩估计(Second Moment Estimation,即梯度的未中心化的方差)进行综合考虑,计算出更新步长。设置初始学习率为0.001,权重衰减值为0.0001。

损失函数选用交叉熵损失函数,它是一种专门用于处理分类问题的损失函数。

#3. Define the optimizer and loss function
optimizer = Adam(model.parameters(), lr=0.001, weight_decay=0.0001)
loss_fn = nn.CrossEntropyLoss()

3.4 训练模型及保存权重参数

定义训练过程,遍历整个训练集100轮。每遍历一轮训练集,根据训练轮次,不断调整学习率的大小,并计算模型在测试集上的准确率,若本轮训练后的测试准确率高于之前轮次,则保存本轮训练得到的权重参数。具体实现如下所示。

#4.Training
num_epochs = 100
best_acc = 0.0
for epoch in range(num_epochs):        train_acc = 0.0        train_loss = 0.0        train_acc,train_loss = train(model,train_acc,train_loss,train_loader,optimizer,loss_fn,cuda_avail)        adjust_learning_rate(optimizer, epoch)        test_acc = test(model,test_loader,cuda_avail)        if test_acc > best_acc:            save_models(model,epoch)            best_acc = test_acc        print("Epoch {}, Train Accuracy: {} , TrainLoss: {} , Test Accuracy: {}".format(           epoch, train_acc, train_loss, test_acc))

训练过程如下所示。每一轮次训练结束均会打印训练精度,训练损失值和测试精度。

4 完整代码

import torch
import torch.nn as nn
import os
from torch.autograd import Variable
from torchvision.datasets import MNIST
from torchvision.transforms import transforms
from torch.utils.data import DataLoader
from torch.optim import Adamimport numpy
#Set GPU id
os.environ["CUDA_VISIBLE_DEVICES"] = "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 outputclass SimpleNet(nn.Module):    def __init__(self, num_classes=10):        super(SimpleNet, self).__init__()self.unit1 = Unit(in_features=784,out_features=1024)        self.unit2 = Unit(in_features=1024, out_features=1024)        self.unit3 = Unit(in_features=1024, out_features=2048)        self.net = nn.Sequential(self.unit1, self.unit2, self.unit3)        self.fc = nn.Linear(in_features=2048,out_features=num_classes)def forward(self, input):        output = self.net(input)        output = self.fc(output)        return output# Create a learning rate adjustment function that divides the learning rate by 10 every 30 epochs
def adjust_learning_rate(optimizer, epoch):    lr = 0.001     if epoch > 180:        lr = lr / 1000000    elif epoch > 150:        lr = lr / 100000    elif epoch > 120:        lr = lr / 10000    elif epoch > 90:        lr = lr / 1000    elif epoch > 60:        lr = lr / 100    elif epoch > 30:        lr = lr / 10     for param_group in optimizer.param_groups:        param_group["lr"] = lr# Training process
def train(model,train_acc,train_loss,train_loader,optimizer,loss_fn,cuda_avail=True):    model.train()    for i, (images, labels) in enumerate(train_loader):        if cuda_avail:            images = Variable(images.cuda())            images = images.reshape(-1,784)            labels = Variable(labels.cuda())        optimizer.zero_grad()        outputs = model(images)        loss = loss_fn(outputs, labels)        loss.backward()        optimizer.step()        train_loss += loss.cpu().data.numpy() * images.size(0)        _, prediction = torch.max(outputs.data, 1)        train_acc += torch.sum(prediction == labels.data)train_acc = train_acc / 60000    train_loss = train_loss / 60000    return train_acc, train_loss# Test the model while training
def test(model,test_loader,cuda_avail=True):    model.eval()    test_acc = 0.0    for i, (images, labels) in enumerate(test_loader):        if cuda_avail:            images = Variable(images.cuda())            images = images.reshape(-1,784)            labels = Variable(labels.cuda())# Predict classes using images from the test set        outputs = model(images)        _, prediction = torch.max(outputs.data, 1)        test_acc += torch.sum(prediction == labels.data)# Compute the average acc and loss over all 10000 test images    test_acc = test_acc / 10000return test_acc# Save the weights
def save_models(model,epoch):    torch.save(model.state_dict(), "MNIST_model_{}.model".format(epoch))      print("Chekcpoint saved")def main():
#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)#2.Initialize model    cuda_avail = torch.cuda.is_available()    model = SimpleNet(num_classes=10)    cuda_avail = torch.cuda.is_available()    if cuda_avail:        model.cuda()#3. Define the optimizer and loss function     optimizer = Adam(model.parameters(), lr=0.001, weight_decay=0.0001)    loss_fn = nn.CrossEntropyLoss()#4.Training    num_epochs = 100    best_acc = 0.0    for epoch in range(num_epochs):        train_acc = 0.0        train_loss = 0.0        train_acc,train_loss = train(model,train_acc,train_loss,train_loader,                optimizer,loss_fn,cuda_avail)        adjust_learning_rate(optimizer, epoch)        test_acc = test(model,test_loader,cuda_avail)        if test_acc > best_acc:            save_models(model,epoch)            best_acc = test_acc        print("Epoch {}, Train Accuracy: {} , TrainLoss: {} , Test Accuracy: {}".format(            epoch, train_acc, train_loss, test_acc))if __name__ == "__main__":    main()

基于BP神经网络的图像分类相关推荐

  1. 《MATLAB 神经网络43个案例分析》:第25章 基于MIV的神经网络变量筛选----基于BP神经网络的变量筛选

    <MATLAB 神经网络43个案例分析>:第25章 基于MIV的神经网络变量筛选----基于BP神经网络的变量筛选 1. 前言 2. MATLAB 仿真示例 3. 小结 1. 前言 < ...

  2. 基于BP神经网络算法的性别识别

    目录 基于 BP 神经网络算法的性别识别 1 目录 1 1.背景介绍 2 2. OpenCV 的介绍 3 3.安装 OpenCV 4 4. BP 神经网络算法介绍和实践 4 4.1 BP 神经网络结构 ...

  3. ​【交通标志识别】基于BP神经网络实现交通标志识别matlab代码

    1 简介 近年来,交通标志识别在车辆视觉导航系统中是一个热门研究课题.为了安全驾驶和高效运输,交通部门在公路道路上设置了各类重要的交通标志,以提醒司机和行人有关道路交通信息,如指示标志.警告标志.禁止 ...

  4. MATLAB实现基于BP神经网络的手写数字识别+GUI界面+mnist数据集测试

    文章目录 MATLAB实现基于BP神经网络的手写数字识别+GUI界面+mnist数据集测试 一.题目要求 二.完整的目录结构说明 三.Mnist数据集及数据格式转换 四.BP神经网络相关知识 4.1 ...

  5. 基于BP神经网络的PID控制,神经网络算法pid控制

    基于BP神经网络的PID控制器设计 参考一下刘金琨的<先进PID控制>这本书. 例子:被控对象yout(k)=a(k)yout(k-1)/(1+yout(k-1)^2)+u(k_1)其中a ...

  6. 基于bp神经网络的pid算法,神经网络pid控制器设计

    基于BP神经网络的PID控制器设计 参考一下刘金琨的<先进PID控制>这本书. 例子:被控对象yout(k)=a(k)yout(k-1)/(1+yout(k-1)^2)+u(k_1)其中a ...

  7. 基于BP神经网络的车牌识别系统的设计

    一.基本原理概述 基于BP神经网络的的汽车牌照识别系统的处理过程分为预处理.边缘提取.车牌定位.字符分割.字符识别五大模块.具体涉及以下几个过程: ① 原始车牌图像:由数码相机或其他扫描装置拍摄到的车 ...

  8. 基于bp神经网络的pid控制,pid神经网络什么原理

    关于基于神经网络的PID液位控制用MATLAB怎么编程啊?求高手指点!!!! . 其实只需要PID参数能够顺利确定就行了,这里有个程序,你试试看closeallclearallclctic%初始化x= ...

  9. 基于bp神经网络的pid算法,基于单神经元的pid控制

    基于BP神经网络的PID控制器设计 参考一下刘金琨的<先进PID控制>这本书. 例子:被控对象yout(k)=a(k)yout(k-1)/(1+yout(k-1)^2)+u(k_1)其中a ...

最新文章

  1. ef mysql 插件_EF Core 插件 —— ToSql
  2. HashMap和LinkedHashMap的区别
  3. iOS网络开发之:NSURLConnection
  4. Nginx-05:Nginx配置实例之反向代理2
  5. webpack 的基本使用—— 创建列表隔行变色项目||在项目中安装和配置 webpack
  6. Spring Security 玩出花!两种方式 DIY 登录
  7. 5.单行函数,多行函数,字符函数,数字函数,日期函数,数据类型转换,数字和字符串转换,通用函数(case和decode)
  8. Finacial professional
  9. 基于RBF简单的matlab手写识别
  10. jsx怎么往js里传参数_在vue中使用jsx语法的使用方法
  11. [转]项目管理有感之一 沟通
  12. 入门 | egg.js 入门之egg-jwt
  13. 圆环和环形是一样的吗_Excel不知道还可以这样做圆环图
  14. STM32 J-LINK、ST-Link、CMSIS-DAP
  15. Eclipse alt+/语法不提示的解决方法
  16. ADO.Net之SqlConnection、 Sqlcommand的应用
  17. 软件需求工程 高校教学平台 项目总体计划
  18. php gd2扩展_PHP如何打开gd2扩展库
  19. 5.android系统裁剪
  20. php自动化营销推广引流源码,PHP自动化售货发卡网源码

热门文章

  1. 关于api.weixin.qq.com 裁撤公告这件事
  2. SQL语句经典面试题
  3. android fragment不执行onResume,onPause
  4. 大数据之flume开发实例
  5. 使用VuePress搭建在线文档网站
  6. ubuntu root账户登录
  7. Linux中完全卸载nginx及安装的详细步骤
  8. Ubuntu下安装Yarm-PM2
  9. docker rm时提示device or resource busy问题解决
  10. IT大厂有两个月的实习生吗?IT毕业怎么找实习单位?