• 微信公众号:美女很有趣。 工作之余,放松一下,关注即送10G+美女照片!

Pytorch笔记4:多层感知机实现MNIST数据集分类

互联网 diligentman 2周前 (04-07) 7次浏览

文章目录

  • 前言
  • 一、Torch相关包介绍
  • 二、搭建多层感知机
    • 1.MNIST介绍
    • 2.下载MNIST数据集
    • 3.搭建神经网络层
    • 1.权重和偏置
    • 2.定义前向计算网络
    • 3.定义梯度优化器及损失函数设置
    • 4.完成程序设计
  • 三、完整代码程序
  • 总结

前言

复杂的神经网络也是由许多神经元组成,在深度学习领域,神经元即感知机。深度学习通过许多感知机,尽可能的学习一个任务的复杂数学表示。神经网络在模拟生物神经元时,创造性的引入非线性的函数,通过判断是否达到阈值,来觉得信号是否输出,完成信息传递。因此,在阶跃函数的基础上,进一步优化,拓展,得到sigmoid激活函数、Relu、leak ReLu等,细细品味,你将发现这构思的巧妙性、合理性。
本节主要MNIST的代码实现,关于感知机,激活函数等介绍,大家可以参考入手这本书,通俗易懂,内容详实,极具阅读价值。

pdf 地址如下,仅供学习参考:
链接: https://wwe.lanzous.com/ieOE2noazwj.

Pytorch笔记4:多层感知机实现MNIST数据集分类


一、Torch相关包介绍

torch.nn :完成神经网络一些相关操作,包含了在计算机视觉任务中常用到的卷积,池化等一些列API接口实现。
torch.nn.fubctional : 可以比nn更进一步接触实现底层代码的修改。
torch.nn.optim优化器,提供了学习率设置,及更好的梯度下降方式的选择。
torchvision:计算机视觉任务的工具,提供了常用的数据集,模型,转换函数等。实现视觉类任务如分类、目标检测、分割必不可少的。

导入所需包(示例):

import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from torchvision import datasets,transforms

若提示出错,可使用命令行窗口,进行 conda install 安装。或者在pycharm中进行安装,以pycharm为例:输入要安装的包,点击安装即可。
Pytorch笔记4:多层感知机实现MNIST数据集分类
Pytorch笔记4:多层感知机实现MNIST数据集分类
Pytorch笔记4:多层感知机实现MNIST数据集分类

二、搭建多层感知机

1.MNIST介绍

MNIST简介: 包含0-9 共10个手写数字,每个数字由7000张(高度28*宽度28)的图像,将70k数据,分为了训练集60K,测试集10大小。本节,通过感知机实现对MNIST手写数字的分类。

代码如下(示例):

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import warnings
warnings.filterwarnings('ignore')
import  ssl
ssl._create_default_https_context = ssl._create_unverified_context

2.下载MNIST数据集

如果下载失败,也可使用下载好的数据集,还在目录下:
链接: https://wwe.lanzous.com/b01c9d0sj.
密码:3dii
Pytorch笔记4:多层感知机实现MNIST数据集分类
Pytorch笔记4:多层感知机实现MNIST数据集分类

代码如下:

‘./data’:设置要保存的下载目录。
train=True:设置要下载的是60k的训练数据集。
download=True:如果当前文件夹没有数据集,则从网上下载。
transforms.ToTensor():下载的数据集为numpy格式,需要转换为张量格式。
transforms.Normalize((0.1307,), (0.3081,):(此项非必要设置项)为了更好的训练结果,因为图像的数据值是0-1之间,将数据值正则花在0左右,对模型梯度下降效果更好。
batch_size=batch_size, shuffle=True:设置批次大小,随机打算数据。
测试集设置类似

#MNIST 数据集
#设置训练的批次大小、学习率、及训练代数
batch_size=200
learning_rate=0.001
epochs=20


#下载数据集
train_loader = torch.utils.data.DataLoader(
    datasets.MNIST('./data', train=True, download=True,
                   transform=transforms.Compose([
                       transforms.ToTensor(),
                       transforms.Normalize((0.1307,), (0.3081,))
                   ])),
    batch_size=batch_size, shuffle=True)
test_loader = torch.utils.data.DataLoader(
    datasets.MNIST('./data', train=False, download=True, transform=transforms.Compose([
        transforms.ToTensor(),
        transforms.Normalize((0.1307,), (0.3081,))
    ])),
    batch_size=batch_size, shuffle=True)

3.搭建神经网络层

1.权重和偏置

代码如下:

w1,b1:第一层网络感知机。输入图像大小是28*28=784,因此输入为784,输出设置为100(这个参数随意设置,可以尝试不同的数目查看效果)因为W要转置所以输入放后面,输出放前面。b1为第一层网络对应的偏置项。
w2, b2:与上叙述类似。
==w3, b3 ==:注意输出要与分类的10个数字类别数一致,其他与上述类似。
requires_grad=True:此项设置为True,表示要对w,b求梯度。

#生成 三个神经网络成,对应感知节分别为第一层100,第二成200,第三层10,即要分类的数目
w1, b1 = torch.randn(100, 784, requires_grad=True),
         torch.zeros(100, requires_grad=True)
w2, b2 = torch.randn(200, 100, requires_grad=True),
         torch.zeros(200, requires_grad=True)
w3, b3 = torch.randn(10, 200, requires_grad=True),
         torch.zeros(10, requires_grad=True)

2.定义前向计算网络

代码如下:

relu激活函数:确保网络的非线性,实现更好的分类效果。

#定义前向网络计算,每层神经网络输出后增加relu激活函数,确保网络的非线性,实现更好的分类效果
def forward(x):
    x = x@w1.t() + b1
    x = F.relu(x)
    x = x@w2.t() + b2
    x = F.relu(x)
    x = x@w3.t() + b3
    x = F.relu(x)
    return x

3.定义梯度优化器及损失函数设置

代码如下:

.CrossEntropyLoss():损失采用交叉熵损失函数。
.SGD:采用随机梯度下降,并设置学习率。

#定义优化器,采用SGD随机梯度下降的方式对w1, b1, w2, b2, w3, b3进行优化
optimizer = optim.SGD([w1, b1, w2, b2, w3, b3], lr=learning_rate)
#定义采用交叉熵作为损失函数
criteon = nn.CrossEntropyLoss()

4.完成程序设计

代码如下:

#设置迭代次数
for epoch in range(epochs):

    for batch_idx, (data, target) in enumerate(train_loader):
        #将数据打平为(批次,高度*宽度),-1代表所有
        data = data.view(-1, 28*28)
		
		#将数据输入到网络中
        cal_data = forward(data)
        #将计算的数据与目标数据求误差损失
        loss = criteon(cal_data, target)
		
		#将梯度值初始化为0
        optimizer.zero_grad()
        #pytorch计算梯度值
        loss.backward()
        #更新梯度值
        optimizer.step()
		#每隔25*batcsize(200) = 5000 打印输出结果
        if batch_idx % 25 == 0:
            print('训练代数: {} [{}/{} ({:.0f}%)]tLoss: {:.6f}'.format(
                epoch, batch_idx * len(data), len(train_loader.dataset),
                       100. * batch_idx / len(train_loader), loss.item()))

	#将测试误差及正确率清0
    test_loss = 0
    correct = 0
    #取测试集数据及目标数据
    for data, target in test_loader:
        data = data.view(-1, 28 * 28)
        logits = forward(data)
        #误差累加
        test_loss += criteon(logits, target).item()
		#取出预测最大值的索引编号,即预测值
        pred = logits.data.argmax(dim=1)
        #统计正确预测的个数
        correct += pred.eq(target.data).sum()

    test_loss /= len(test_loader.dataset)
    #打印输出测试误差及准确率
    print('n测试集: Average loss: {:.4f}, Accuracy: {}/{} ({:.0f}%)n'.format(
        test_loss, correct, len(test_loader.dataset),
        100. * correct / len(test_loader.dataset)))

三、完整代码程序

因为我们自己随机生成的初始化 w1,w2,w3,达到的性能并不好。所以我们可以采用大神何凯明的初始化权重对w1,w2,w3 进行初始化赋值,准确率可以达到90%。小伙伴们可以尝试下,将初始化赋值代码屏蔽,对比查看效果。

代码如下:

import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from torchvision import datasets,transforms

#MNIST 数据集
#设置训练的批次大小、学习率、及训练代数
batch_size=200
learning_rate=0.001
epochs=20

#下载数据集
train_loader = torch.utils.data.DataLoader(
    datasets.MNIST('./data', train=True, download=True,
                   transform=transforms.Compose([
                       transforms.ToTensor(),
                       transforms.Normalize((0.1307,), (0.3081,))
                   ])),
    batch_size=batch_size, shuffle=True)
test_loader = torch.utils.data.DataLoader(
    datasets.MNIST('./data', train=False, download=True, transform=transforms.Compose([
        transforms.ToTensor(),
        transforms.Normalize((0.1307,), (0.3081,))
    ])),
    batch_size=batch_size, shuffle=True)

#生成三层神经网络成,对应感知机分别为第一层100,第二成200,第三层10,即要分类的数目
w1, b1 = torch.randn(100, 784, requires_grad=True),
         torch.zeros(100, requires_grad=True)
w2, b2 = torch.randn(200, 100, requires_grad=True),
         torch.zeros(200, requires_grad=True)
w3, b3 = torch.randn(10, 200, requires_grad=True),
         torch.zeros(10, requires_grad=True)

#采用何凯明大神的初始化权重,准确率更高,权重的合理初始化很重要
torch.nn.init.kaiming_normal_(w1)
torch.nn.init.kaiming_normal_(w2)
torch.nn.init.kaiming_normal_(w3)

#定义前向网络计算,每层神经网络输出后增加relu激活函数,确保网络的非线性,实现更好的分类效果
def forward(x):
    x = x@w1.t() + b1
    x = F.relu(x)
    x = x@w2.t() + b2
    x = F.relu(x)
    x = x@w3.t() + b3
    x = F.relu(x)
    return x

#定义优化器,采用SGD随机梯度下降的方式对w1, b1, w2, b2, w3, b3进行优化
optimizer = optim.SGD([w1, b1, w2, b2, w3, b3], lr=learning_rate)
#定义采用交叉熵作为损失函数
criteon = nn.CrossEntropyLoss()

# 设置迭代次数
for epoch in range(epochs):

    for batch_idx, (data, target) in enumerate(train_loader):
        # 将数据打平为(批次,高度*宽度),-1代表所有
        data = data.view(-1, 28 * 28)

        # 将数据输入到网络中
        cal_data = forward(data)
        # 将计算的数据与目标数据求误差损失
        loss = criteon(cal_data, target)

        # 将梯度值初始化为0
        optimizer.zero_grad()
        # pytorch计算梯度值
        loss.backward()
        # 更新梯度值
        optimizer.step()
        # 每隔25*batcsize(200) = 5000 打印输出结果
        if batch_idx % 25 == 0:
            print('训练代数: {} [{}/{} ({:.0f}%)]tLoss: {:.6f}'.format(
                epoch, batch_idx * len(data), len(train_loader.dataset),
                       100. * batch_idx / len(train_loader), loss.item()))

    # 将测试误差及正确率清0
    test_loss = 0
    correct = 0
    # 取测试集数据及目标数据
    for data, target in test_loader:
        data = data.view(-1, 28 * 28)
        logits = forward(data)
        # 误差累加
        test_loss += criteon(logits, target).item()
        # 取出预测最大值的索引编号,即预测值
        pred = logits.data.argmax(dim=1)
        # 统计正确预测的个数
        correct += pred.eq(target.data).sum()

    test_loss /= len(test_loader.dataset)
    # 打印输出测试误差及准确率
    print('n测试集: Average loss: {:.4f}, Accuracy: {}/{} ({:.0f}%)n'.format(
        test_loss, correct, len(test_loader.dataset),
        100. * correct / len(test_loader.dataset)))

输出结果:
Pytorch笔记4:多层感知机实现MNIST数据集分类


总结

这一节,我们从底层搭建了一个三层的感知机神经网络,对手写数字数据集MNIST进行训练和测试,达到了92%的正确率。权重的随机初始化,对结果是很重要的,但在torch更高层的API使用中提供了很好的初始化,会在下一节中进行讲解。最后劳烦小伙伴,动手点个赞吧,给予我爆发小宇宙的能量。


程序员灯塔
转载请注明原文链接:Pytorch笔记4:多层感知机实现MNIST数据集分类
喜欢 (0)