NNDL 作业4:第四章课后题

目录

习题4-2

习题4-3

习题4-7

习题4-8

习题4-9

总结

参考 


习题4-2

试设计一个前馈神经网络来解决XOR问题,要求该前馈神经网络具有两个隐藏神经元和一个输出神经元,并使用ReLU作为激活函数。

XOR问题就是指我们自从学计算机就一直在接触的异或问题,异或问题有两个输入一个输出,若两个输入相同输出结果为0,如果两个输入不同输出结果为1。

这里根据题目要求我们使用的前馈神经网络输入层两个神经元,隐藏层两个神经元,输出层一个神经元,两个全连接层,并且激活函数使用ReLU函数作为激活函数。

使用Tytorch实现的代码如下:

import torch
from torch.nn.init import constant_, normal_
import torch.nn as nn
import torch.optim as optim
import numpy as np


class XORModule(nn.Module):
    def __init__(self):
        super(XORModule, self).__init__()
        self.fc1 = nn.Linear(2, 2)
        self.fc2 = nn.Linear(2, 1)
        self.relu = nn.ReLU()

    def forward(self, x):
        x = x.view(-1, 2)
        x = self.relu((self.fc1(x)))
        x = self.fc2(x)
        return x


# 输入和输出数据
input_x = torch.Tensor([[0, 0], [0, 1], [1, 0], [1, 1]])
input_x1 = input_x.float()
real_y = torch.Tensor([[0], [1], [1], [0]])
real_y1 = real_y.float()
# 设置损失函数和参数优化函数
net = XORModule()
loss_function = nn.MSELoss()  # 用交叉熵损失函数会出现维度错误
optimizer = optim.SGD(net.parameters(), lr=0.01)  # 用Adam优化参数选不好会出现计算值超出0-1的范围

# 进行训练
for epoch in range(1000):
    out_y = net(input_x1)
    loss = loss_function(out_y, real_y1)  # 计算损失函数
    optimizer.zero_grad()  # 对梯度清零,避免造成累加
    loss.backward()  # 反向传播
    optimizer.step()  # 参数更新

# 输出权值和偏置
print('w1 = ', net.fc1.weight.detach().numpy())
print('b1 = ', net.fc1.bias.detach().numpy())
print('w2 = ', net.fc2.weight.detach().numpy())
print('b2 = ', net.fc2.bias.detach().numpy())
# 测试
input_test = input_x1
out_test = net(input_test)
print('input_x:\n', input_test.detach().numpy())
print('out_y:\n', np.around(out_test.detach().numpy()))

运行结果

 

 

习题4-3

试举例说明“死亡ReLU问题”,并提出解决方法。
       ReLU也是非线性函数,它将低于或等于 0 的神经元输入都计算成 0。使用ReLU的全连接层的前向与后向传递的主要计算如下:

z = np.maximum(0, np.dot(W, x)) # forward pass
dz_dW = np.outer(z > 0, x) # backward pass: local gradient for W

 观察上述代码你会发现,当前向传递中一个神经元的值恒等于 0(即z_{i} =0,表示该神经元未被激活),该神经元对应的权重的梯度将为0,这时权重得不到更新。这就会导致所谓的“死亡” ReLU问题。如果一个ReLU 神经元由于被不恰当地初始化而恒等于 0(这时不是模型参数的问题),或是其对应的参数在训练过程中由于大幅度的更新而接近于 0(这时在下一样本的计算中该神经元的值就会趋于为 0,随着而来的是权重的梯度为 0,权重无法更新,导致该神经元的值恒为 0),那么这个神经元将永远处于死亡状态。这就是“死亡” ReLU。
这里的举例可以参考我前面发布的实验NNDL 实验五 前馈神经网络(2)自动梯度计算 & 优化问题中关于死亡ReLU问题的举例

解决办法

而对于这种问题使用Leaky ReLU、PReLU、ELU、Softplus等激活函数代替ReLU来解决。

习题4-7

为什么在神经网络模型的结构化风险函数中不对偏置𝒃进行正则化?

这个问题简单来说就是因为对b进行正则化是没有作用的因为在对输出结果的贡献中,参数b对于输入的改变是不敏感的,不管输入改变是大还是小,参数b的贡献就只是加个偏置而已。

上面是简单说一下,下面我附上一段我搜索到的认为比较好理解的解释:

首先正则化主要是为了防止过拟合,而过拟合一般表现为模型对于输入的微小改变产生了输出的较大差异,这主要是由于有些参数w过大的关系,通过对||w||进行惩罚,可以缓解这种问题。

而如果对||b||进行惩罚,其实是没有作用的,因为在对输出结果的贡献中,参数b对于输入的改变是不敏感的,不管输入改变是大还是小,参数b的贡献就只是加个偏置而已。举个例子,如果你在训练集中,w和b都表现得很好,但是在测试集上发生了过拟合,b是不背这个锅的,因为它对于所有的数据都是一视同仁的(都只是给它们加个偏置),要背锅的是w,因为它会对不同的数据产生不一样的加权。

或者说,模型对于输入的微小改变产生了输出的较大差异,这是因为模型的“曲率”太大,而模型的曲率是由w决定的,b不贡献曲率(对输入进行求导,b是直接约掉的)。
下面是原博客

为什么一般不对偏置b进行正则化?

习题4-8

为什么在用反向传播算法进行参数学习时要采用随机参数初始化的方式而不是直接令 w = 0 , b = 0?
反向传播就是要将神经网络的输出误差,一级一级地传播到输入。在计算过程中,计算每一个w对总的损失函数的影响,即损失函数对每个w的偏导。根据w的误差的影响,再乘以步长,就可以更新整个神经网络的权重。当一次反向传播完成之后,网络的参数模型就可以得到更新。更新一轮之后,接着输入下一个样本,算出误差后又可以更新一轮,再输入一个样本,又来更新一轮,通过不断地输入新的样本迭代地更新模型参数,就可以缩小计算值与真实值之间的误差,最终完成神经网络的训练。
因为如果参数都设为0,在第一遍前向计算的过程中所有的隐藏层神经元的激活值都相同。在反向传播时,所有权重更新也都相同,这样会导致隐藏层神经元没有区分性。这种现象称为对称权重现象。这就导致神经网络可以更新多权重没意义了,所以需要采用随机参数初始化的方式。

习题4-9

梯度消失问题是否可以通过增加学习率来缓解?

 网络层之间的梯度(值小于 1.0)重复相乘导致的指数级减小会产生梯度消失;  

原因: 主要是因为网络层数太多,太深,导致梯度无法传播。本质应该是激活函数的饱和性。

表现:神经网络的反向传播是逐层对函数偏导相乘,因此当神经网络层数非常深的时候,最后一层产生的偏差就因为乘了很多的小于1的数而越来越小,最终就会变为0,从而导致层数比较浅的权重没有更新,这就是梯度消失。

梯度更新公式:
w=w-\eta \frac{\partial E_{k} }{\partial w_{hj} } 

 而适当增大学习率在一定程度上可以缓解梯度消失,而当学习率过大时,可能又会导致梯度爆炸。

梯度消失解决方法:

1、合理的初始化权重值。初始化权重,使每个神经元尽可能不要取极大或极小值,以躲开梯度消失的区域。

   其中, n 为特征数,初始化合理的权重值,它不会增长过快或下降过快到0,可避免梯度爆炸或消失,也可以加快训练速度;

2、使用relu代替sigmoid和tanh作为激活函数。

3、使用其他结构的RNNs,比如长短时记忆网络(LTSM)和Gated Recurrent Unit(GRU),这是最流行的做法。详情请参阅深度学习-循环神经网络(RNN)

总结 

这次在写的时候老师就说第一个题有些问题是有些同学的运行结果不太对,然后自己就多运行了几次确实有成功的也有不成功的,这个题确实存在问题但是本班老师和本班大佬正在商讨解决,期待把问题找出并解决和课上的解释,另外对死亡ReLU问题再次了解,了解了为什么不对偏置b正则化,同时深度学习了梯度消失和梯度爆炸问题等等。

参考 

为什么一般不对偏置b进行正则化?

 深度学习-梯度爆炸和梯度消失

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值