目录
习题 4-2 试设计一个前馈神经网络来解决 XOR 问题,要求该前馈神经网络具有两个隐藏神经元和一个输出神经元,并使用 ReLU 作为激活函数.
习题 4-3 试举例说明“死亡ReLU问题”,并提出解决方法.
习题4-7 为什么在神经网络模型的结构化风险函数中不对偏置b进行正则化?
习题4-8 为什么用反向传播算法进行参数学习时要采用随机参数初始化的方法而不是直接令W=0,b=0?
习题4-9 梯度消失问题是否可以通过增加学习率来缓解?
参考博客:
心得体会:
习题 4-2 试设计一个前馈神经网络来解决 XOR 问题,要求该前馈神经网络具有两个隐藏神经元和一个输出神经元,并使用 ReLU 作为激活函数.
1.XOR问题描述
异或是对两个运算元的一种逻辑分析类型,当两两数值相同时为否,而数值不同时为真。异或的真值表见表1-1所示:
2.代码如下:
import torch
import torch.nn as nn
from sklearn.metrics import accuracy_score
import numpy as np
# XOR问题由两个全连接层构成
class XORModule(nn.Module):
def __init__(self):
super(XORModule, self).__init__()
self.fc1 = nn.Linear(2, 23)
self.fc2 = nn.Linear(23, 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]]).to(torch.float32)
label = torch.Tensor([[0], [1], [1], [0]]).to(torch.float32)
# 设置损失函数和参数优化函数
module = XORModule()
learing_rate = 0.1
epochs = 10000
loss_function = nn.MSELoss(reduction='mean') # MSE损失函数
optimizer = torch.optim.SGD(module.parameters(), lr=learing_rate) # SGD优化器
# 进行训练
for epoch in range(epochs):
out_y = module(input_x)
loss = loss_function(out_y, label) # 计算损失函数
optimizer.zero_grad() # 梯度清零
loss.backward() # 反向传播
optimizer.step() # 参数更新
out_test = module(input_x)
print('input_x', input_x.detach().numpy())
print('output_y', np.around(out_test.detach().numpy()))
运行结果:
原来的准确率特别低,运行结果不准确,通过提高隐藏层神经元的个数来提高准确率,按理来说,改变学习率也可以提高结果的准确度,但在本题中效果并不明显。
1.死亡ReLu问题
ReLU 的全称是 Rectified Linear Unit,其函数图像如下图所示:
上图是一个典型的神经元。
由于 ReLU 在 x>0x>0 时,导数恒为 1。因此在反向传播的过程中,不会因为导数连乘,而使得梯度特别小,以至于参数无法更新。在这个意义上,ReLU 确实避免了梯度消失问题。
下式是神经网络权重更新的公式,迭代就是不断重复做如图的公式:
其中,:= 表示更新参数,J(ω)为代价函数(成本函数);
α表示学习率,用来控制步长,即向下走一步的长度就是函数J(ω)对求导,在代码中我们会使用dw表示这个结果。当学习率过大时,会导致α*这一项很大,当 它大于ω时,更新后的ω’就会变为负值;当权重参数变为负值时,输入网络的正值会和权重相乘后也会变为负值,负值通过ReLu后就会输出0;如果在后期有机会被更新为正值也不会出现大问题,但是当relu函数输出值为0时,relu的导数也为0,因此会导致后边Δω一直为0,进而导致ω一直不会被更新,因此会导致这个神经元永久性死亡。
2.举例:
3.解决死亡ReLU问题的方法:
1.带泄露的ReLU函数(LeakyReLU)
2.带参数的ReLU函数(PReLU)
3.ELU(指数线性单元)
4.Softplus(Rectifier 函数的平滑版本)
1.结构化风险的描述
结构化风险 = 经验风险 + 置信风险
经验风险 = 分类器在给定样本上的误差
置信风险 = 分类器在未知文本上分类的结果的误差
影响经验风险的因素:
分类函数的复杂度。
影响置信风险因素:
1.样本数量,给定的样本数量越大,学习结果越有可能正确,此时置信风险越小。
2.分类函数的VC维,显然VC维越大,推广能力越差,置信风险会变大。
2.不对偏置b进行正则化的原因
首先正则化主要是为了防止过拟合,而过拟合一般表现为模型对于输入的微小改变产生了输出的较大差异,这主要是由于有些参数w过大的关系,通过对||w||进行惩罚,可以缓解这种问题。
而如果对||b||进行惩罚,其实是没有作用的,因为在对输出结果的贡献中,参数b对于输入的改变是不敏感的,不管输入改变是大还是小,参数b的贡献就只是加个偏置而已。举个例子,如果你在训练集中,w和b都表现得很好,但是在测试集上发生了过拟合,b是不背这个锅的,因为它对于所有的数据都是一视同仁的(都只是给它们加个偏置),要背锅的是w,因为它会对不同的数据产生不一样的加权。
或者说,模型对于输入的微小改变产生了输出的较大差异,这是因为模型的“曲率”太大,而模型的曲率是由w决定的,b不贡献曲率(对输入进行求导,b是直接约掉的)
如果全部参数都设置为0的话,会导致前向传播的结果隐层神经元的激活值都相同,出现对称权重现象,而且在反向传播时,所有的权重更新也会相同,导致没有多样性和区分性,而采用随机初始化的方法可以使得每层神经元参数的梯度不同,从而达到不同的值,得到好的分类结果。
在一定程度上可以缓解。适当增大学习率可以使学习率与导数相乘结果变大,缓解梯度消失;过大学习率可能梯度巨大,导致梯度爆炸。
梯度消失:
如果连乘的因子大部分小于1,最后乘积的结果可能趋于0,也就是梯度消失,后面的网络层的参数不发生变化.
梯度爆炸:
如果连乘的因子大部分大于1,最后乘积可能趋于无穷,这就是梯度爆炸
如何防止梯度消失?
sigmiod容易发生,更换激活函数为 ReLU即可。
权重初始化用高斯初始化
如何防止梯度爆炸?
1 设置梯度剪切阈值,如果超过了该阈值,直接将梯度置为该值。
2 使用ReLU,maxout等替代sigmoid
1. 前馈神经网络求解XOR问题
2. 对ReLU激活函数神经元死亡现象的理解
3. 结构化风险
4.什么是梯度爆炸/梯度消失?
对XOR问题有了更为深入的了解,同时掌握了结构化风险以及梯度消失,梯度爆炸相关问题。对于死亡ReLu问题也有了较为深入的掌握。