Drupout,前向传播和反向传播?怎么实现?

目录

一:回顾

二:暂退法(dropout)

 三:实践中的暂退法

 四:从零开始实现

定义模型参数定义模型

训练和测试

五:前向传播和后向传播

正向传播: 

正向传播完成:

 反向传播

 继续反向传播w1

 更新w1的值

把所有的w都更新一遍,反向传播的一轮就结束了

六:总结:

所有项目代码+UI界面


一:回顾

        上次提到了L1L2正则化能缓解过拟合的现象,L1正则化体现了稀疏性(即在某些项有值,而其他项为0,如果换成特征的话就是,某些特征起作用,而不是所有的特征起作用,这个去耦合的过程就是减小过拟合的过程),所以并不是只使用L1或者L2,有些时候会把L1和L2合起来用。而L2正则化是把w的绝对值变小了,而且考虑的特征要比L1多。并用代码实现了通过不同的λ来观察对结果的不同的影响,这次继续介绍解决过拟合的另外一种方法:丢弃法,并介绍前向传播和后向传播。

二:暂退法(dropout)

         暂退法在前向传播过程中,计算每一内部层的同时注入噪声,这已经成为训练神经网络的常用技术。 这种方法之所以被称为暂退法,因为我们从表面上看是在训练过程中丢弃(drop out)一些神经元。 在整个训练过程的每一次迭代中,标准暂退法包括在计算下一层之前将当前层中的一些节点置零。

在标准暂退法正则化中,通过按保留(未丢弃)的节点的分数进行规范化来消除每一层的偏差。 换言之,每个中间活性值ℎ以暂退概率p由随机变量ℎ′替换,如下所示:

         丢弃法并没有改变每个神经元的期望输出值,只是随机地屏蔽一些神经元的输出。对于丢弃率为p的情况,我们可以将保留下来的神经元的输出值除以1-p来作为最终的输出。这样可以保证期望不变(期望仍是h),因为保留下来的神经元的输出值都被乘以了一个固定的因子1/(1-p)。因为对于离散型的数学期望,它的表达式是

根据此模型的设计,其期望值保持不变,即E[ℎ′]=ℎ,所以可以计算出期望不变(这里看了b站up主的讲解就理解了)

 三:实践中的暂退法

通常,我们在测试时不用暂退法。 给定一个训练好的模型和一个新的样本,我们不会丢弃任何节点,因此不需要标准化。 然而也有一些例外:一些研究人员在测试时使用暂退法, 用于估计神经网络预测的“不确定性”: 如果通过许多不同的暂退法遮盖后得到的预测结果都是一致的,那么我们可以说网络发挥更稳定。

通常将丢弃法作用在隐藏层全连接层的输出上 

 四:从零开始实现

要实现单层的暂退法函数, 我们从均匀分布U[0,1]中抽取样本,样本数与这层神经网络的维度一致。 然后我们保留那些对应样本大于p的节点,把剩下的丢弃。

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

def dropout_layer(X, dropout):
    assert 0 <= dropout <= 1
    # 在本情况中,所有元素都被丢弃
    # dropout == 1:丢弃的概率是1
    if dropout == 1:
        return torch.zeros_like(X)
    # 在本情况中,所有元素都被保留
    if dropout == 0:
        return X
    #(torch.rand(X.shape) 0-1的均匀分布。将这个张量中每个元素与0.5比较,生成一个布尔型张量,即大于0.5的元素为 True(1),小于等于0.5的元素为 False(0)
    mask = (torch.rand(X.shape) > dropout).float()
    #  mask(x的值) * x/(1-p) 
    return mask * X / (1.0 - dropout) 

num_inputs, num_outputs, num_hiddens1, num_hiddens2 = 784, 10, 256, 256
dropout1, dropout2 = 0.5, 0.5

我们可以通过下面几个例子来测试dropout_layer函数。 我们将输入X通过暂退法操作,暂退概率分别为0、0.5和1。

X= torch.arange(16, dtype = torch.float32).reshape((2, 8))
print(X)
print(dropout_layer(X, 0.))
print(dropout_layer(X, 0.5))
print(dropout_layer(X, 1.))
#tensor([[ 0.,  1.,  2.,  3.,  4.,  5.,  6.,  7.],
#        [ 8.,  9., 10., 11., 12., 13., 14., 15.]])
#tensor([[ 0.,  1.,  2.,  3.,  4.,  5.,  6.,  7.],
#        [ 8.,  9., 10., 11., 12., 13., 14., 15.]])
#tensor([[ 0.,  2.,  4.,  6.,  0.,  0.,  0., 14.],
#        [16., 18., 20., 22.,  0., 26.,  0., 30.]])
#tensor([[0., 0., 0., 0., 0., 0., 0., 0.],
        [0., 0., 0., 0., 0., 0., 0., 0.]])

定义模型参数定义模型

        我们可以将暂退法应用于每个隐藏层的输出(在激活函数之后), 并且可以为每一层分别设置暂退概率: 常见的技巧是在靠近输入层的地方设置较低的暂退概率。 下面的模型将第一个和第二个隐藏层的暂退概率分别设置为0.2和0.5, 并且暂退法只在训练期间有效。

# 引入的Fashion-MNIST数据集。 我们定义具有两个隐藏层的多层感知机,每个隐藏层包含256个单元。
num_inputs, num_outputs, num_hiddens1, num_hiddens2 = 784, 10, 256, 256
dropout1, dropout2 = 0.5, 0.5
class Net(nn.Module):
    def __init__(self, num_inputs, num_outputs, num_hiddens1, num_hiddens2,
                 is_training=True):
        super(Net, self).__init__()
        self.num_inputs = num_inputs
        # 只有在训练模型时才使用dropout
        self.training = is_training
        self.lin1 = nn.Linear(num_inputs, num_hiddens1)
        self.lin2 = nn.Linear(num_hiddens1, num_hiddens2)
        self.lin3 = nn.Linear(num_hiddens2, num_outputs)
        self.relu = nn.ReLU()

    def forward(self, X):
        H1 = self.relu(self.lin1(X.reshape((-1, self.num_inputs))))
        # 只有在训练模型时才使用dropout
        if self.training == True:
            # 在第一个全连接层之后添加一个dropout层
            H1 = dropout_layer(H1, dropout1)
        H2 = self.relu(self.lin2(H1))
        if self.training == True:
            # 在第二个全连接层之后添加一个dropout层
            H2 = dropout_layer(H2, dropout2)
        out = self.lin3(H2)
        return out

训练和测试

这类似于前面描述的多层感知机训练和测试。

# 引入的Fashion-MNIST数据集。 我们定义具有两个隐藏层的多层感知机,每个隐藏层包含256个单元。
num_inputs, num_outputs, num_hiddens1, num_hiddens2 = 784, 10, 256, 256
dropout1, dropout2 = 0.5, 0.5
net = Net(num_inputs, num_outputs, num_hiddens1, num_hiddens2)

num_epochs, lr, batch_size = 10, 0.5, 256
loss = nn.CrossEntropyLoss()
train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size)
trainer = torch.optim.SGD(net.parameters(), lr=lr)
d2l.train_ch3(net, train_iter, test_iter, loss, num_epochs, trainer)
d2l.plt.show()

经过验证后,dropout和L2效果差不多,所以也当成正则化来使用

在dropout中,隐藏层的数据单元决定了你的训练效果好不好,因为要丢弃一些神经单元

 Tips:

        全连接层采用dropout,卷积层不需要dropout。对深度学习来讲,通常可以把模型弄得复杂点 ,然后通过正则化来控制模型复杂度, 就是有dropout的情况下,可以把隐藏层稍微设大一点点,再把dropout率也设大一点点 ,这样可能比不用dropout,而且隐藏层小一点点的效果会更好一点,Dropout是正则项,它的唯一作用是在更新权重的时候让你模型复杂度变低一点点。    

五:前向传播和后向传播

正向传播: 

正向传播完成:

 反向传播

进行链式求导,先求出w5的梯度,更新w2值,再求出w1的梯度

 

 继续反向传播w1

 更新w1的值

把所有的w都更新一遍,反向传播的一轮就结束了

 

 下一轮又是从正向传播开始,损失比第一轮减小了0.15

事实上,正向传播的时候,除了对wx1+wx2...以外,还需要在括号乘以一个激活函数的,反向传播的时候也会对激活函数继续求导。

这个激活函数是relu,求导只有0和1,

相信大家看完这些图片后能对前向后向传播有更深刻的体会~ 

还有一小部分就是梯度消失和梯度爆炸,relu等激活函数可以减轻sigmoid带来的梯度消失和梯度爆炸,

         默认初始化方法通常是将参数随机初始化为小的随机值,例如从均匀分布或高斯分布中采样。这种方法在许多情况下效果很好,但是如果网络较深或输入特征数量较多,则会遇到梯度消失或梯度爆炸的问题。

        Xavier初始化使用从均匀分布或高斯分布中采样的随机数来初始化参数,并将其乘以一个标量,该标量取决于输入和输出的数量。这种方法可以减少梯度消失和梯度爆炸的问题,并提高模型的收敛速度和性能。Xavier初始化可以更好地处理较深的网络和大量的输入特征,但并不总是比默认初始化更好。实际中,这些方法通常会互相比较以获得最佳性能。

六:总结:

        本节介绍了dropout和前向后向传播的概念以及实现,下一篇我将分享一个线性回归模型实战项目——房价预测。

所有项目代码+UI界面

视频,笔记和代码,以及注释都已经上传网盘,放在主页置顶文章

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
同时使用暂退法和权重衰减可以通过以下步骤实现: 1. 定义模型架构:选择适当的神经网络架构,如卷积神经网络(CNN)或循环神经网络(RNN),并确定层的数量和大小。 2. 添加暂退法:在每个隐藏层中添加暂退层。暂退层将在每个训练批次中以一定的概率随机丢弃一部分神经元的输出。这可以通过在每个隐藏层后面添加一个暂退层,并设置相应的丢弃概率来实现。 3. 添加权重衰减:在损失函数中添加权重衰减项。权重衰减将在训练过程中减小权重的大小,以防止模型过度拟合。可以通过将权重衰减项添加到损失函数中,并设置相应的权重衰减系数来实现。 4. 定义损失函数和优化器:选择适当的损失函数,如交叉熵损失或均方误差损失,并选择合适的优化器,如随机梯度下降(SGD)或Adam。 5. 训练模型:使用训练数据对模型进行训练。在每个训练批次中,通过向传播计算损失,并通过反向传播更新模型的权重。同时,暂退法和权重衰减会在训练过程中起作用,减少过拟合的风险。 6. 超参数调优:调整暂退法的丢弃概率和权重衰减的系数,以找到最佳的超参数组合。可以使用交叉验证或其他评估方法来评估模型在验证集上的性能,并选择最佳的超参数。 7. 测试模型:使用测试数据评估模型的性能。通过向传播计算预测结果,并与真实标签进行比较,评估模型的准确率或其他性能指标。 重要的是要注意,暂退法和权重衰减的效果会受到数据集、模型架构和超参数设置的影响。因此,需要进行实验和调优,找到最佳的超参数组合来提高模型的性能和泛化能力。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值