深度学习——多层感知机(MLP)一

深度学习——多层感知机(MLP)一


前言

前面介绍了最简单的神经网络——线性神经网络,而接下来将第一次介绍真正的深度神经网络。其中最简单的深度神经网络称为多层感知机


一、隐藏层

1.1. 线性模型可能会不适用

线性意味着单调假设
任何特征的增大都会导致模型输出的增大(如果对应的权重为正),或者导致模型输出的减小(如果对应的权重为负)。

例如: 如何对猫和狗的图像进行分类呢?
增加位置 ( 13 , 17 ) (13, 17) (13,17)处像素的强度是否总是增加(或降低)图像描绘狗的似然?

对线性模型的依赖对应于一个隐含的假设即区分猫和狗的唯一要求是评估单个像素的强度。
在一个倒置图像后依然保留类别的世界里,这种方法注定会失败。

我们难以通过简单的预处理来解决这个问题。这是因为任何像素的重要性都以复杂的方式取决于该像素的上下文(周围像素的值)。
我们的数据可能会有一种表示,这种表示会考虑到我们在特征之间的相关交互作用

在此表示的基础上建立一个线性模型可能会是合适的,但我们不知道如何手动计算这么一种表示。
对于深度神经网络,我们使用观测数据来联合学习隐藏层表示和应用于该表示的线性预测器

1.2. 在网络中加入隐藏层

我们可以通过在网络中加入一个或多个隐藏层来克服线性模型的限制,使其能处理更普遍的函数关系类型。

在这里插入图片描述

这个多层感知机有4个输入,3个输出,其隐藏层包含5个隐藏单元。
输入层不涉及任何计算,因此使用此网络产生输出只需要实现隐藏层和输出层的计算。因此,这个多层感知机中的层数为2,并且这两个层都是全连接层。

1.3. 从线性到非线性

我们通过矩阵 X ∈ R n × d \mathbf{X} \in \mathbb{R}^{n \times d} XRn×d来表示 n n n个样本的小批量,其中每个样本具有 d d d个输入特征。

对于具有 h h h个隐藏单元的单隐藏层多层感知机:

H ∈ R n × h \mathbf{H} \in \mathbb{R}^{n \times h} HRn×h表示隐藏层的输出,称为隐藏表示
在数学或代码中, H \mathbf{H} H也被称为隐藏层变量
因为隐藏层和输出层都是全连接的,
所以我们有隐藏层权重 W ( 1 ) ∈ R d × h \mathbf{W}^{(1)} \in \mathbb{R}^{d \times h} W(1)Rd×h
和隐藏层偏置 b ( 1 ) ∈ R 1 × h \mathbf{b}^{(1)} \in \mathbb{R}^{1 \times h} b(1)R1×h
以及输出层权重 W ( 2 ) ∈ R h × q \mathbf{W}^{(2)} \in \mathbb{R}^{h \times q} W(2)Rh×q
和输出层偏置 b ( 2 ) ∈ R 1 × q \mathbf{b}^{(2)} \in \mathbb{R}^{1 \times q} b(2)R1×q
形式上,我们按如下方式计算单隐藏层多层感知机的输出
O ∈ R n × q \mathbf{O} \in \mathbb{R}^{n \times q} ORn×q

H = X W ( 1 ) + b ( 1 ) , O = H W ( 2 ) + b ( 2 ) . \begin{aligned} \mathbf{H} & = \mathbf{X} \mathbf{W}^{(1)} + \mathbf{b}^{(1)}, \\ \mathbf{O} & = \mathbf{H}\mathbf{W}^{(2)} + \mathbf{b}^{(2)}. \end{aligned} HO=XW(1)+b(1),=HW(2)+b(2).

即对于任意权重值,我们只需合并隐藏层,便可产生具有参数 W = W ( 1 ) W ( 2 ) \mathbf{W} = \mathbf{W}^{(1)}\mathbf{W}^{(2)} W=W(1)W(2) b = b ( 1 ) W ( 2 ) + b ( 2 ) \mathbf{b} = \mathbf{b}^{(1)} \mathbf{W}^{(2)} + \mathbf{b}^{(2)} b=b(1)W(2)+b(2)的等价单层模型:

O = ( X W ( 1 ) + b ( 1 ) ) W ( 2 ) + b ( 2 ) = X W ( 1 ) W ( 2 ) + b ( 1 ) W ( 2 ) + b ( 2 ) = X W + b . \mathbf{O} = (\mathbf{X} \mathbf{W}^{(1)} + \mathbf{b}^{(1)})\mathbf{W}^{(2)} + \mathbf{b}^{(2)} = \mathbf{X} \mathbf{W}^{(1)}\mathbf{W}^{(2)} + \mathbf{b}^{(1)} \mathbf{W}^{(2)} + \mathbf{b}^{(2)} = \mathbf{X} \mathbf{W} + \mathbf{b}. O=(XW(1)+b(1))W(2)+b(2)=XW(1)W(2)+b(1)W(2)+b(2)=XW+b.

为了发挥多层架构的潜力,我们还需要一个额外的关键要素:
在仿射变换之后对每个隐藏单元应用非线性的激活函数 σ \sigma σ
激活函数的输出(例如, σ ( ⋅ ) \sigma(\cdot) σ())被称为激活值。
一般来说,有了激活函数,就不可能再将我们的多层感知机退化成线性模型:

H = σ ( X W ( 1 ) + b ( 1 ) ) , O = H W ( 2 ) + b ( 2 ) . \begin{aligned} \mathbf{H} & = \sigma(\mathbf{X} \mathbf{W}^{(1)} + \mathbf{b}^{(1)}), \\ \mathbf{O} & = \mathbf{H}\mathbf{W}^{(2)} + \mathbf{b}^{(2)}.\\ \end{aligned} HO=σ(XW(1)+b(1)),=HW(2)+b(2).

隐藏层的激活函数通常是按照每个神经元的输入进行计算的,而不是整个隐藏层的输入一起计算。
这意味着在计算每一层的线性部分之后,我们可以计算每个活性值,而不需要查看其他隐藏单元所取的值。对于大多数激活函数都是这样。

为了构建更通用的多层感知机,我们可以继续堆叠这样的隐藏层,例如 H ( 1 ) = σ 1 ( X W ( 1 ) + b ( 1 ) ) \mathbf{H}^{(1)} = \sigma_1(\mathbf{X} \mathbf{W}^{(1)} + \mathbf{b}^{(1)}) H(1)=σ1(XW(1)+b(1)) H ( 2 ) = σ 2 ( H ( 1 ) W ( 2 ) + b ( 2 ) ) \mathbf{H}^{(2)} = \sigma_2(\mathbf{H}^{(1)} \mathbf{W}^{(2)} + \mathbf{b}^{(2)}) H(2)=σ2(H(1)W(2)+b(2))
一层叠一层,从而产生更有表达能力的模型。

1.4. 通用近似定理

多层感知机可以通过隐藏神经元,捕捉到输入之间复杂的相互作用,这些神经元依赖于每个输入的值。

我们可以很容易地设计隐藏节点来执行任意计算。
例如,在一对输入上进行基本逻辑操作,多层感知机是通用近似器。
即使是网络只有一个隐藏层,给定足够的神经元和正确的权重,
我们可以对任意函数建模,尽管实际中学习该函数是很困难的。

二、激活函数

激活函数(activation function)通过计算加权和并加上偏置来确定神经元是否应该被激活,
它们将输入信号转换为输出的可微运算;大多数激活函数都是非线性的

具体来说,激活函数将输入的加权和与一个阈值进行比较,如果加权和大于阈值,则神经元被激活,否则神经元被抑制。如下展示了激活函数的作用流程:

import torch

# 定义输入张量
x = torch.tensor([-2.0, 1.0, 0.5])

# 定义激活函数
def relu(x):
    return torch.max(torch.tensor(0.0), x)

# 计算加权和并加上偏置
weighted_sum = torch.sum(x) + bias

# 判断神经元是否被激活
if relu(weighted_sum) > 0:
    print("神经元被激活")
else:
    print("神经元被抑制")

2.1. ReLU函数

最受欢迎的激活函数是修正线性单元(Rectified linear unit,ReLU),

给定元素 x x xReLU函数被定义为该元素与 0 0 0的最大值

ReLU ⁡ ( x ) = max ⁡ ( x , 0 ) . \operatorname{ReLU}(x) = \max(x, 0). ReLU(x)=max(x,0).

通俗地说,ReLU函数通过将相应的激活值设为0,仅保留正元素并丢弃所有负元素。

import torch
from d2l import torch as d2l

#ReLU函数
x = torch.arange(-8,8,0.1,requires_grad= True)  #设置requires_grad=True以追踪梯度
#print(x.shape)
y = torch.relu(x) #使用ReLU函数计算x的ReLU值,即将小于0的元素置为0,大于等于0的元素保持不变。
d2l.plot(x.detach(),y.detach(),"x","relu(x)",figsize=(5,3))
#x.detach()和y.detach()将张量转换为普通的Python列表
d2l.plt.show()

在这里插入图片描述

当输入为负时,ReLU函数的导数为0,而当输入为正时,ReLU函数的导数为1。 注意,当输入值精确等于0时,ReLU函数不可导,在此时,我们默认使用左侧的导数,即当输入为0时导数为0。

#绘制RelU函数的导数图像
y.backward(torch.ones_like(x),retain_graph= True) #对y进行反向传播计算梯度。retain_graph=True表示保留计算图,以便后续计算。
d2l.plot(x.detach(),x.grad,"x","relu(x)",figsize=(5,3))
d2l.plt.show()

在这里插入图片描述

使用ReLU的原因是,它求导表现得特别好:要么让参数消失,要么让参数通过。 这使得优化表现得更好。

2.2. sigmoid函数

sigmoid通常称为挤压函数(squashing function): 它将范围(-inf, inf)中的任意输入压缩到区间(0,1)中的某个值:

sigmoid ⁡ ( x ) = 1 1 + exp ⁡ ( − x ) . \operatorname{sigmoid}(x) = \frac{1}{1 + \exp(-x)}. sigmoid(x)=1+exp(x)1.

当我们想要将输出视作二元分类问题的概率时,sigmoid仍然被广泛用作输出单元上的激活函数。
然而,sigmoid在隐藏层中已经较少使用,
它在大部分时候被更简单、更容易训练的ReLU所取代。

#绘制sigmoid函数
y = torch.sigmoid(x)
d2l.plot(x.detach(),y.detach(),"x","sigmoid(x)",figsize=(5,4))
d2l.plt.show()

#绘制sigmoid函数的导数
x.grad.data.zero_() #清除以前的梯度
y.backward(torch.ones_like(x),retain_graph=True)
d2l.plot(x.detach(),x.grad,"x","grad of sigmoid",figsize=(5,4))
d2l.plt.show()

在这里插入图片描述

在这里插入图片描述

2.3. tanh函数

与sigmoid函数类似,tanh(双曲正切)函数也能将其输入压缩转换到区间(-1, 1)上

tanh ⁡ ( x ) = 1 − exp ⁡ ( − 2 x ) 1 + exp ⁡ ( − 2 x ) . \operatorname{tanh}(x) = \frac{1 - \exp(-2x)}{1 + \exp(-2x)}. tanh(x)=1+exp(2x)1exp(2x).

注意,当输入在0附近时,tanh函数接近线性变换。函数的形状类似于sigmoid函数,不同的是tanh函数关于坐标系原点中心对称


#绘制tanh函数
y = torch.tanh(x)
d2l.plot(x.detach(),y.detach(),"x","tanh(x)",figsize=(5,4))
d2l.plt.show()


#绘制tanh函数的导数图像
x.grad.data.zero_()
y.backward(torch.ones_like(x),retain_graph= True)
d2l.plot(x.detach(),x.grad,"x"," grad of tanh(x)",figsize=(5,4))
d2l.plt.show()

在这里插入图片描述

在这里插入图片描述


总结

本章主要对多层感知机的定义进行了介绍,并且介绍了几个常见的激活函数。而我们的学习也从之前的线性模型向着非线性模型转变,下一章则主要介绍多层感知机的代码实现

居善地,心善渊,与善仁,言善信,政善治,事善能,动善时。

–2023-9-26 进阶篇

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

星石传说

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值