动手学深度学习--多层感知机篇(MLP)

本文详细介绍了多层感知机(MLP)的原理与实现,包括线性模型的局限性、非线性激活函数如ReLU、Sigmoid和Tanh的作用,以及权重衰减(L2正则化)在防止过拟合中的应用。同时,讨论了暂退法(Dropout)作为提升模型泛化能力的策略,以及前向传播、反向传播和计算图的数学原理。此外,还探讨了数值稳定性和模型初始化的重要性,特别是Xavier初始化在打破神经网络对称性方面的贡献。

多层感知机

前言:本章分为8小章

1.多层感知机

  • 线性模型的缺陷:

具有单调性:即W增大 output增大,W减小 output减小,而现实中存在许多违反单调性的例子:

①体温预测死亡率 ②收入变化与还款可能性

  • 隐藏层与多层感知机(multilayer perceptron MLP)

将前 L-1层看作表示,把最后一层看作线性预测器,这种架构 常称为多层感知机 (此处线性存疑)

在这里插入图片描述

缺点: 具有全连接层的多层感知机的参数开销过大

  • 激活函数:从线性到非线性

多层感知机公式在这里插入图片描述

(H:Hidden O:output),经化简可发现 所谓多层感知机仍可蜕变为:O=XW+b ,摆脱不了其单调性

因此:

我们引入激活函数,增强网络的非线性表征能力,公式如下:

在这里插入图片描述

为了构建更通用的多层感知机, 我们可以继续堆叠这样的隐藏层 :例如

在这里插入图片描述

通过不断堆叠,从而产生更有表达能力的模型

  • 激活函数

①ReLU函数(Rectified linear unit) 中文名:修正线性单元

优点:求导表现好,参数只能消失或者通过,便于优化

公式如下:

在这里插入图片描述

示例:

x = torch.arange(-8.0, 8.0, 0.1, requires_grad=True)
y = torch.relu(x)
d2l.plot(x.detach(), y.detach(), 'x', 'relu(x)', figsize=(5, 2.5))

可以由函数曲线图看出,ReLU是分段线性的

在这里插入图片描述

接下来我们观察ReLU函数的导数图

实现代码:

y.backward(torch.ones_like(x), retain_graph=True)
d2l.plot(x.detach(), x.grad, 'x', 'grad of relu', figsize=(5, 2.5))
#此处我们规定当输入值精确为0时,默认使用左侧导数‘0’

在这里插入图片描述

**此外,ReLU函数 有许多变体,包括参数化ReLU(Parameterized ReLU,pReLU) 函数 该变体为ReLU添加了一个线性项,因此即使参数是负的,某些信息仍然可以通过: **

在这里插入图片描述

②sigmoid函数 又称挤压函数(squashing function)

公式如下:

在这里插入图片描述

该激活函数强制将范围**(-∞,+∞)的任意输入压缩为(0,1)**的某一值

示例:

y = torch.sigmoid(x)
d2l.plot(x.detach(), y.detach(), 'x', 'sigmoid(x)', figsize=(5, 2.5))

在这里插入图片描述

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, 2.5))

在这里插入图片描述

③tanh函数 又称挤压函数(squashing function)

公式:

在这里插入图片描述

该激活函数强制将范围**(-∞,+∞)的任意输入压缩为(0,1)**的某一值

示例:

y = torch.tanh(x)
d2l.plot(x.detach(), y.detach(), 'x', 'tanh(x)', figsize=(5, 2.5))

在这里插入图片描述

导数公式:

在这里插入图片描述

# 清除以前的梯度
x.grad.data.zero_()
y.backward(torch.ones_like(x),retain_graph=True)
d2l.plot(x.detach(), x.grad, 'x', 'grad of tanh', figsize=(5, 2.5))

在这里插入图片描述


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

import torch
from torch import nn
from d2l import torch as d2l

batch_size = 256
train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size)
  • 初始化参数模型

1一般选择2的幂作为层宽度。 因为内存在硬件中的分配和寻址方式,这么做使计算上更高效

2.该数据集中每个图像包含784个灰度像素值,所有图像共分为10类

3.构建单隐藏层的多层感知机(具有256个隐藏单元)

#构建单隐藏层的多层感知机
num_inputs, num_outputs, num_hiddens = 784, 10, 256
# 每个图像包含784个特征  所有图像共有10个类别   而MLP包含256个隐藏单元
W1 = nn.Parameter(torch.randn(
    num_inputs, num_hiddens, requires_grad=True) * 0.01)
b1 = nn.Parameter(torch.zeros(num_hiddens, requires_grad=True))
W2 = nn.Parameter(torch.randn(
    num_hiddens, num_outputs, requires_grad=True) * 0.01)
b2 = nn.Parameter(torch.zeros(num_outputs, requires_grad=True))

params = [W1, b1, W2, b2]
  • 激活函数

此处我们手动实现

def relu(X):
    a = torch.zeros_like(X)
    return torch.max(X, a)
#torch,max(X,a) 将两tensor按元素比较,将最大值作为新元素,最终返回每个元素均最大的tensor
  • 模型

#此处构建忽略了图像的空间结构,直接reshape为向量
def net(X):
    X = X.reshape((-1, num_inputs))
    H = relu(X@W1 + b1)  # 这里“@”代表矩阵乘法
    return (H@W2 + b2)
  • 损失函数

loss = nn.CrossEntropyLoss(reduction='none')
  • 训练

num_epochs, lr = 10, 0.1
updater = torch.optim.SGD(params, lr=lr)
d2l.train_ch3(net, train_iter, test_iter, loss, num_epochs, updater)

在这里插入图片描述

  • 在测试集预测

d2l.predict_ch3(net, test_iter)

在这里插入图片描述


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

高级API简化过程

  • 模型

net = nn.Sequential(nn.Flatten(),#将矩阵按需求自动展平为向量
                    nn.Linear(784, 256),
                    nn.ReLU(),
                    nn.Linear(256, 10))

def init_weights(m):
    
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值