当前位置:   article > 正文

Pytorch总结四之 多层感知机原理及简洁实现_多层感知机的简洁实现

多层感知机的简洁实现

Pytorch总结四之 多层感知机

前边已经介绍了包括线性回归☞666和softmax回归☞666在内的单层神经⽹络。然⽽深度学习主要关注多层模型。
在本节中,我们将以多层感知机(multilayer perceptron,MLP)为例,介绍多层神经⽹络的概念。

1.隐藏层

  • 多层感知机在单层神经⽹络的基础上引⼊了⼀到多个隐藏层(hidden layer)。隐藏层位于输⼊层和输出层之间。图3.3展示了⼀个多层感知机的神经⽹络图,它含有⼀个隐藏层,该层中有5个隐藏单元。
    在这里插入图片描述
  • 在图3.3所示的多层感知机中,输⼊和输出个数分别为4和3,中间的隐藏层中包含了5个隐藏单元
    (hidden unit)。由于输⼊层不涉及计算,图3.3中的多层感知机的层数为2。由图3.3可⻅,隐藏层中的神经元和输⼊层中各个输⼊完全连接,输出层中的神经元和隐藏层中的各个神经元也完全连接。因此,多层感知机中的隐藏层和输出层都是全连接层
    在这里插入图片描述

2. 激活函数

上述问题的根源在于全连接层只是对数据做仿射变换(affine transformation),⽽多个仿射变换的叠加仍然是⼀个仿射变换。解决问题的⼀个⽅法是引⼊⾮线性变换,例如对隐藏变量使⽤按元素运算的⾮线性函数进⾏变换,然后再作为下⼀个全连接层的输⼊。这个⾮线性函数被称为激活函数(activation function)。下⾯我们介绍⼏个常⽤的激活函数。

2.1 Relu函数

ReLU(rectified linear unit)函数提供了⼀个很简单的⾮线性变换。给定元素 ,该函数定义为:
在这里插入图片描述
可以看出,ReLU函数只保留正数元素,并将负数元素清零。为了直观地观察这⼀⾮线性变换,我们先定义⼀个绘图函数 xyplot 。

%matplotlib inline
import torch
import numpy as np
import matplotlib.pylab as plt
import sys
sys.path.append("..")
import d2lzh_pytorch as d2l
def xyplot(x_vals, y_vals, name):
    d2l.set_figsize(figsize=(5, 2.5))
    d2l.plt.plot(x_vals.detach().numpy(), y_vals.detach().numpy())
    d2l.plt.xlabel('x')
    d2l.plt.ylabel(name + '(x)')

# 定义自变量x范围
x = torch.arange(-8.0, 8.0, 0.1, requires_grad=True) 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

接下来通过 NDArray 提供的 relu 函数来绘制ReLU函数。可以看到,该激活函数是⼀个两段线性
函数。

#1.绘制Relu激活函数
y = x.relu()
xyplot(x, y, 'relu')
  • 1
  • 2
  • 3

在这里插入图片描述
显然,当输⼊为负数时,ReLU函数的导数为0;当输⼊为正数时,ReLU函数的导数为1。尽管输⼊为0 时ReLU函数不可导,但是我们可以取此处的导数为0。下⾯绘制ReLU函数的导数。

#绘制导数
y.sum().backward()
xyplot(x, x.grad, 'grad of relu')
  • 1
  • 2
  • 3

在这里插入图片描述

2.2 sigmoid函数

sigmoid函数可以将元素的值变换到0和1之间:
在这里插入图片描述
sigmoid函数在早期的神经⽹络中较为普遍,但它⽬前逐渐被更简单的ReLU函数取代。在后⾯“循环神经⽹络”⼀章中我们会介绍如何利⽤它值域在0到1之间这⼀特性来控制信息在神经⽹络中的流动。下⾯绘制了sigmoid函数。当输⼊接近0时,sigmoid函数接近线性变换。

#2.绘制sigmid函数
y = x.sigmoid()
xyplot(x, y, 'sigmoid')
  • 1
  • 2
  • 3

在这里插入图片描述
在这里插入图片描述

#x.grad.zero_() #此句无用,加上报错,删掉也可绘制如下结果
y.sum().backward()
xyplot(x, x.grad, 'grad of sigmoid')
  • 1
  • 2
  • 3

在这里插入图片描述

2.3 tanh函数

在这里插入图片描述
我们接着绘制tanh函数。当输⼊接近0时,tanh函数接近线性变换。虽然该函数的形状和sigmoid函数
的形状很像,但tanh函数在坐标系的原点上对称。

#3.绘制tanh函数
y = x.tanh()
xyplot(x, y, 'tanh')
  • 1
  • 2
  • 3

在这里插入图片描述

下⾯绘制了tanh函数的导数。当输⼊为0时,tanh函数的导数达到最⼤值1;当输⼊越偏离0时,tanh
函数的导数越接近0。

#x.grad.zero_()
y.sum().backward()
xyplot(x, x.grad, 'grad of tanh') 
  • 1
  • 2
  • 3

在这里插入图片描述

3. 多层感知机

  • 多层感知机就是含有至少一个隐藏层的由全连接层组成的神经网络,且每个隐藏层的输出通过激活函数进行变换。
  • 多层感知机的层数和各隐藏层中隐藏单元个数都是超参数。以单隐藏层为例,多层感知机按以下方式计算输出:
    在这里插入图片描述

4. 多层感知机的简洁实现

#4.多层感知机的简洁实现
#4.1导入模块
import  torch
from torch import nn
from torch.nn import init
import numpy as np
import sys
sys.path.append("..")
import d2lzh_pytorch as d2l

#4.2 定义模型,同soft回归不同的是,多加了一个全连接层为隐藏层,隐藏单元个数为256,
#并使用Relu函数作为激活函数
num_inputs,num_outputs,num_hiddens=784,10,256
net=nn.Sequential(d2l.FlattenLayer(),
                  nn.Linear(num_inputs,num_hiddens),
                  nn.ReLU(),
                  nn.Linear(num_hiddens,num_outputs))
for params in net.parameters():
    init.normal_(params,mean=0,std=0.01)

#4.2 读取数据并训练模型
#由于这⾥使⽤的是PyTorch的SGD⽽不是d2lzh_pytorch⾥⾯的sgd,所以就不存在那样学习率看起来很⼤的问题了。
batch_size = 256
train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size)
loss = torch.nn.CrossEntropyLoss() #交叉熵损失函数
optimizer = torch.optim.SGD(net.parameters(), lr=0.5) #梯度下降大进行学习率优化
num_epochs = 6  #迭代次数
d2l.train_ch3(net, train_iter, test_iter, loss, num_epochs,
batch_size, None, None, optimizer)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

在这里插入图片描述

为了方便理解,贴出训练和评估准确率的源码 utils.py

def train_ch3(net, train_iter, test_iter, loss, num_epochs, batch_size,
              params=None, lr=None, optimizer=None):
    for epoch in range(num_epochs):
        train_l_sum, train_acc_sum, n = 0.0, 0.0, 0
        for X, y in train_iter:
            y_hat = net(X)
            l = loss(y_hat, y).sum()
            
            # 梯度清零
            if optimizer is not None:
                optimizer.zero_grad()
            elif params is not None and params[0].grad is not None:
                for param in params:
                    param.grad.data.zero_()
            
            l.backward()
            if optimizer is None:
                sgd(params, lr, batch_size)
            else:
                optimizer.step()  # “softmax回归的简洁实现”一节将用到
            
            
            train_l_sum += l.item()
            train_acc_sum += (y_hat.argmax(dim=1) == y).sum().item()
            n += y.shape[0]
        test_acc = evaluate_accuracy(test_iter, net)
        print('epoch %d, loss %.4f, train acc %.3f, test acc %.3f'
              % (epoch + 1, train_l_sum / n, train_acc_sum / n, test_acc))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
# ############################ 5.5 #########################
def evaluate_accuracy(data_iter, net, 
        device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')):
    acc_sum, n = 0.0, 0
    with torch.no_grad():
        for X, y in data_iter:
            if isinstance(net, torch.nn.Module):
                net.eval() # 评估模式, 这会关闭dropout
                acc_sum += (net(X.to(device)).argmax(dim=1) == y.to(device)).float().sum().cpu().item()
                net.train() # 改回训练模式
            else: # 自定义的模型, 3.13节之后不会用到, 不考虑GPU
                if('is_training' in net.__code__.co_varnames): # 如果有is_training这个参数
                    # 将is_training设置成False
                    acc_sum += (net(X, is_training=False).argmax(dim=1) == y).float().sum().item() 
                else:
                    acc_sum += (net(X).argmax(dim=1) == y).float().sum().item() 
            n += y.shape[0]
    return acc_sum / n
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/凡人多烦事01/article/detail/327670
推荐阅读
相关标签
  

闽ICP备14008679号