首页 > 其他分享 >动手学深度学习(三) 多层感知机

动手学深度学习(三) 多层感知机

时间:2023-05-17 19:34:06浏览次数:32  
标签:acc num 函数 动手 torch 多层 感知机 train test


多层感知机

  1. 多层感知机的基本知识
  2. 使用多层感知机图像分类的从零开始的实现
  3. 使用pytorch的简洁实现

多层感知机的基本知识

深度学习主要关注多层模型。在这里,我们将以多层感知机(multilayer perceptron,MLP)为例,介绍多层神经网络的概念。

隐藏层

下图展示了一个多层感知机的神经网络图,它含有一个隐藏层,该层中有5个隐藏单元。





动手学深度学习(三) 多层感知机_激活函数


Image Name


表达公式

具体来说,给定一个小批量样本

,其批量大小为

,输入个数为

。假设多层感知机只有一个隐藏层,其中隐藏单元个数为

。记隐藏层的输出(也称为隐藏层变量或隐藏变量)为

,有

。因为隐藏层和输出层均是全连接层,可以设隐藏层的权重参数和偏差参数分别为


,输出层的权重和偏差参数分别为


。我们先来看一种含单隐藏层的多层感知机的设计。其输出

的计算为

也就是将隐藏层的输出直接作为输出层的输入。如果将以上两个式子联立起来,可以得到

从联立后的式子可以看出,虽然神经网络引入了隐藏层,却依然等价于一个单层神经网络:其中输出层权重参数为

,偏差参数为

。不难发现,即便再添加更多的隐藏层,以上设计依然只能与仅含输出层的单层神经网络等价。

激活函数

上述问题的根源在于全连接层只是对数据做仿射变换(affine transformation),而多个仿射变换的叠加仍然是一个仿射变换。解决问题的一个方法是引入非线性变换,例如对隐藏变量使用按元素运算的非线性函数进行变换,然后再作为下一个全连接层的输入。这个非线性函数被称为激活函数(activation function)。

下面我们介绍几个常用的激活函数:

ReLU函数

ReLU(rectified linear unit)函数提供了一个很简单的非线性变换。给定元素

,该函数定义为

可以看出,ReLU函数只保留正数元素,并将负数元素清零。为了直观地观察这一非线性变换,我们先定义一个绘图函数xyplot。

%matplotlib inline
import torch
import numpy as np
import matplotlib.pyplot as plt
import sys
sys.path.append("/home/kesci/input")
import d2lzh1981 as d2l
print(torch.__version__)
1.3.0
def xyplot(x_vals, y_vals, name):
    # d2l.set_figsize(figsize=(5, 2.5))
    plt.plot(x_vals.detach().numpy(), y_vals.detach().numpy())
    plt.xlabel('x')
    plt.ylabel(name + '(x)')
x = torch.arange(-8.0, 8.0, 0.1, requires_grad=True)
y = x.relu()
xyplot(x, y, 'relu')



动手学深度学习(三) 多层感知机_激活函数_02


y.sum().backward()
xyplot(x, x.grad, 'grad of relu')



动手学深度学习(三) 多层感知机_多层感知机_03


Sigmoid函数

sigmoid函数可以将元素的值变换到0和1之间:

y = x.sigmoid()
xyplot(x, y, 'sigmoid')



动手学深度学习(三) 多层感知机_多层感知机_04


依据链式法则,sigmoid函数的导数

下面绘制了sigmoid函数的导数。当输入为0时,sigmoid函数的导数达到最大值0.25;当输入越偏离0时,sigmoid函数的导数越接近0。

x.grad.zero_()
y.sum().backward()
xyplot(x, x.grad, 'grad of sigmoid')



动手学深度学习(三) 多层感知机_多层感知机_05


tanh函数

tanh(双曲正切)函数可以将元素的值变换到-1和1之间:

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

y = x.tanh()
xyplot(x, y, 'tanh')



动手学深度学习(三) 多层感知机_多层感知机_06


依据链式法则,tanh函数的导数

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

x.grad.zero_()
y.sum().backward()
xyplot(x, x.grad, 'grad of tanh')



动手学深度学习(三) 多层感知机_多层感知机_07


关于激活函数的选择

ReLu函数是一个通用的激活函数,目前在大多数情况下使用。但是,ReLU函数只能在隐藏层中使用。

用于分类器时,sigmoid函数及其组合通常效果更好。由于梯度消失问题,有时要避免使用sigmoid和tanh函数。

在神经网络层数较多的时候,最好使用ReLu函数,ReLu函数比较简单计算量少,而sigmoid和tanh函数计算量大很多。

在选择激活函数的时候可以先选用ReLu函数如果效果不理想可以尝试其他激活函数。

多层感知机

多层感知机就是含有至少一个隐藏层的由全连接层组成的神经网络,且每个隐藏层的输出通过激活函数进行变换。多层感知机的层数和各隐藏层中隐藏单元个数都是超参数。以单隐藏层为例并沿用本节之前定义的符号,多层感知机按以下方式计算输出:



动手学深度学习(三) 多层感知机_多层感知机_08


其中

表示激活函数。

多层感知机从零开始的实现

import torch
import numpy as np
import sys
sys.path.append("/home/kesci/input")
import d2lzh1981 as d2l
print(torch.__version__)
1.3.0

获取训练集

batch_size = 256
train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size,root='/home/kesci/input/FashionMNIST2065')

定义模型参数

num_inputs, num_outputs, num_hiddens = 784, 10, 256

W1 = torch.tensor(np.random.normal(0, 0.01, (num_inputs, num_hiddens)), dtype=torch.float)
b1 = torch.zeros(num_hiddens, dtype=torch.float)
W2 = torch.tensor(np.random.normal(0, 0.01, (num_hiddens, num_outputs)), dtype=torch.float)
b2 = torch.zeros(num_outputs, dtype=torch.float)

params = [W1, b1, W2, b2]
for param in params:
    param.requires_grad_(requires_grad=True)

定义激活函数

def relu(X):
    return torch.max(input=X, other=torch.tensor(0.0))

定义网络

def net(X):
    X = X.view((-1, num_inputs))
    H = relu(torch.matmul(X, W1) + b1)
    return torch.matmul(H, W2) + b2

定义损失函数

loss = torch.nn.CrossEntropyLoss()

训练

num_epochs, lr = 5, 100.0
# 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:
#                 d2l.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))

d2l.train_ch3(net, train_iter, test_iter, loss, num_epochs, batch_size, params, lr)
epoch 1, loss 0.0030, train acc 0.712, test acc 0.806
epoch 2, loss 0.0019, train acc 0.821, test acc 0.806
epoch 3, loss 0.0017, train acc 0.847, test acc 0.825
epoch 4, loss 0.0015, train acc 0.856, test acc 0.834
epoch 5, loss 0.0015, train acc 0.863, test acc 0.847

多层感知机pytorch实现

import torch
from torch import nn
from torch.nn import init
import numpy as np
import sys
sys.path.append("/home/kesci/input")
import d2lzh1981 as d2l

print(torch.__version__)
1.3.0

初始化模型和各个参数

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)

训练

batch_size = 256
train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size,root='/home/kesci/input/FashionMNIST2065')
loss = torch.nn.CrossEntropyLoss()

optimizer = torch.optim.SGD(net.parameters(), lr=0.5)

num_epochs = 5
d2l.train_ch3(net, train_iter, test_iter, loss, num_epochs, batch_size, None, None, optimizer)
epoch 1, loss 0.0031, train acc 0.701, test acc 0.774
epoch 2, loss 0.0019, train acc 0.821, test acc 0.806
epoch 3, loss 0.0017, train acc 0.841, test acc 0.805
epoch 4, loss 0.0015, train acc 0.855, test acc 0.834
epoch 5, loss 0.0014, train acc 0.866, test acc 0.840

标签:acc,num,函数,动手,torch,多层,感知机,train,test
From: https://blog.51cto.com/u_16116809/6293333

相关文章

  • 动手学深度学习(十二) NLP循环神经网络进阶
    GRURNN存在的问题:梯度较容易出现衰减或爆炸(BPTT)⻔控循环神经⽹络:捕捉时间序列中时间步距离较⼤的依赖关系RNN:ImageNameGRU:ImageName•重置⻔有助于捕捉时间序列⾥短期的依赖关系;•更新⻔有助于捕捉时间序列⾥⻓期的依赖关系。载入数据集importos......
  • 动手学深度学习(一) 线性回归
    线性回归主要内容包括:线性回归的基本要素线性回归模型从零开始的实现线性回归模型使用pytorch的简洁实现线性回归的基本要素模型为了简单起见,这里我们假设价格只取决于房屋状况的两个因素,即面积(平方米)和房龄(年)。接下来我们希望探索价格与这两个因素的具体关系。线性回归假设输出与......
  • 动手学深度学习(十) NLP 语言模型与数据集
    语言模型一段自然语言文本可以看作是一个离散时间序列,给定一个长度为的词的序列,语言模型的目标就是评估该序列是否合理,即计算该序列的概率:本节我们介绍基于统计的语言模型,主要是元语法(-gram)。在后续内容中,我们将会介绍基于神经网络的语言模型。语言模型假设序列中的每个词是依次生......
  • 统计学习方法笔记-感知机学习方法
    感知机(Perceptron)1.感知机模型1.1感知机定义​ 输入空间$\mathcal{X}\subseteq\mathbb{R}^n$,输出空间\(\mathcal{Y}\)={+1,-1};​ 输入\(x\in\mathcal{X}\)表示的实例的特征向量,对应于输入空间的点,输出\(y\in\mathcal{Y}\)表示的实例的类别;由输入空间到输出空间的......
  • MLP多层感知机时间序列预测(Matlab) 所有程序经过验证,保证可以运行
    MLP多层感知机时间序列预测(Matlab)所有程序经过验证,保证可以运行。1.data为数据集,一维时间序列数据。2.MainMLPTS.m为主程序文件,其他为函数文件,无需运行。3.命令窗口输出R2和MAE。ID:9319682924924115......
  • 免费且神奇的知识学习和动手模拟网站大全 All In One
    免费且神奇的知识学习和动手模拟网站大全AllInOnefreeonlineawesomelearingHTML5webistesPhETPhET:Freeonlinephysics,chemistry,biology,earthscienceandmathsimulationsPhET:免费在线物理、化学、生物学、地球科学和数学模拟https://phet.colorado.edu/......
  • 递归及如何用c#递归生成多层次XML文件
    递归递归做为一种算法在程序设计语言中广泛应用.是指函数/过程/子程序在运行过程中直接或间接调用自身而产生的重入现象.递归是计算机科学的一个重要概念,递归的方法是程序设计中有效的方法,采用递归编写程序能使程序变得简洁和清晰.。一般定义程序调用自身的编程技巧称为递归(re......
  • 自己动手实现Lua(三)lua栈
     Lua栈是宿主语言(对于官方Lua来说是C语言,对于本书来说是Go语言)和Lua语言进行沟通的桥梁。Lua的数据类型和值在lua代码里,变量是不携带类型信息的,变量的值才携带类型信息。换句话说,任何一个lua变量都可以被赋予任意类型的值。 在语言层面,Lua一共支持8种数据类型,分别是nil、布......
  • ios如何集成百度地图---还是自己动手做一下--网上好多博客说的都不甚靠谱。
    1:申请key,在appdelegate中加入相应的代码。比如。appdelegate.h中:#import<UIKit/UIKit.h>#import<FMDB.h>#import<BaiduMapAPI_Base/BMKBaseComponent.h>//引入base相关所有的头文件#import<BaiduMapAPI_Map/BMKMapComponent.h>//引入地图功能所有的头文件......
  • elementUI 多层结构动态生成el-form及校验
    如题,当整个el-form都是通过多层数据结构循环渲染出来的表单,那么每个el-form-item的prop和el-input、el-select等的v-model也是动态变量填充,怎么样才能内嵌rules校验呢?如下数据结构://form通过initData数据结构进行渲染constinitData=[{channel:'sms',title......