目录
习题4-2 试设计一个前馈神经网络来解决XOR问题,要求该前馈神经网络具有两个隐藏神经元和一个输出神经元,并使用ReLU作为激活函数.
解:
首先了解一下XOR(异或)问题
表格表示:
x1 | x2 | OR |
---|---|---|
0 | 0 | 0 |
0 | 1 | 1 |
1 | 0 | 1 |
1 | 1 | 0 |
用图像表示:
将上图中不同颜色的点进行分类
很明显,这是线性不可分的
设计网络:
这写上代码
import torch.nn as nn
import torch.nn.functional as F
# 异或门模块由两个全连接层构成
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
import torch
import torch.nn as nn
import torch.optim as optim
# 输入和输出数据
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()
optimizer = torch.optim.Adam(net.parameters(), lr=0.01, betas=(0.9, 0.99))
loss_function = torch.nn.CrossEntropyLoss()
# 进行训练
for epoch in range(10000):
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', input_test.detach().numpy())
print('out_y', out_test.detach().numpy())
运行结果:
w1 = [[ 0.20901406 -0.39346436]
[-0.6683035 -0.7041291 ]]
b1 = [ 0.4484983 -0.61879766]
w2 = [[-0.17339629 0.5743229 ]]
b2 = [0.02311128]
input_x [[0. 0.]
[0. 1.]
[1. 0.]
[1. 1.]]
out_y [[-0.05465666]
[ 0.0135686 ]
[-0.09089892]
[-0.02267366]]
注: w1=[[w1,w2],[w3,w4]],w2=[w5,w6],b1=[b1,b2],b2=[b3]
在进行ReLU的时候,很容易出现死亡ReLU的现象,当数值小于0的时候,就会等于0
习题4-3 试举例说明“死亡ReLU问题”,并提出解决方法.
稀疏性可以提升计算高效性,但同样可能阻碍训练过程。通常,激活函数的输入值有一项偏置项(bias),假设bias变得太小,以至于输入激活函数的值总是负的,那么反向传播过程经过该处的梯度恒为0,对应的权重和偏置参数此次无法得到更新。如果对于所有的样本输入,该激活函数的输入都是负的,那么该神经元再也无法学习,称为神经元”死亡“问题。
解决办法:
- 使用带泄露的ReLU
带参数的 ReLU 引入一个可学习的参数,不 同神经元可以有不同的参数. 对于第 𝑖 个神经元,其 PReLU 的 定义为:
PReLU𝑖 (𝑥) = max(0, 𝑥) + 𝛾𝑖 min(0, 𝑥)- 使用带参数的ReLU
PReLU(Parametric ReLU, PReLU,即带参数的 ReLU)引入一个可学习的参数, 不同神经元可以有不同的参数。 对于第 𝑖 个神经元,ReLU 的定义为:
γi是x ≤ 0时的梯度, 如果 γ i \gamma_i γi= 0, 那么PReLU 就退化为 ReLU. 如果 γ i \gamma_i γi 为一个很小的常数, 则 PReLU 可以看作Leaky ReLU。 PReLU 可以允许不同神经元具有不同的参数, 也可以一组神经元共享一个参数。- 使用正则项约束参数
- 使用其他方式训练网络,例如Adam
这个应该很好理解,这个不好用就换一个嘛
习题4-7 为什么在神经网络模型的结构化风险函数中不对偏置𝒃进行正则化?
首先解释一下正则化
Regularization,中文翻译过来可以称为正则化,或者是规范化。什么是规则?闭卷考试中不能查书,这就是规则,一个限制。同理,在这里,规则化就是说给损失函数加上一些限制,通过这种规则去规范他们再接下来的循环迭代中,不要自我膨胀。
正则化是用来防止模型过拟合而采取的手段
在神经网络模型的结构化风险函数中加入正则化项,可以避免过拟合,对于偏置 b b b进行正则化对于防止过拟合没有什么影响。偏置b对于所有输入样本来说都是一致的,是一个不变量,所以不需要考虑对b进行正则化。
这里就提一下如何正则化模型
我们看一个线性的损失函数(真实值和预测值的误差)
E(w) 是损失函数(又称误差函数),E即Evaluate,有时候写成L即Loss
tn 是测试集的真实输出,又称目标变量
w 是权重(需要训练的部分,未知数)
ϕ()是基函数,例如多项式函数,核函数
测试样本有n个数据
整个函数直观解释就是误差方差和,1/2 只是为了求导后消去方便计算
加正则化项,得到最终的误差函数(Error function)
(2)式被称为目标函数(评价函数)= 误差函数(损失函数) + 正则化项
λ 被称为正则化系数,越大,这个限制越强
习题4-8 为什么在用反向传播算法进行参数学习时要采用随机参数初始化的方式而不是直接令𝑾 = 0, 𝒃 = 0?
反向传播就是要将神经网络的输出误差,一级一级地传播到输入。在计算过程中,计算每一个w对总的损失函数的影响,即损失函数对每个w的偏导。根据w的误差的影响,再乘以步长,就可以更新整个神经网络的权重。当一次反向传播完成之后,网络的参数模型就可以得到更新。更新一轮之后,接着输入下一个样本,算出误差后又可以更新一轮,再输入一个样本,又来更新一轮,通过不断地输入新的样本迭代地更新模型参数,就可以缩小计算值与真实值之间的误差,最终完成神经网络的训练。当直接令w=0,b=0时,会让下一层神经网络中所有神经元进行着相同的计算,具有同样的梯度,同样权重更新。
若将𝑾和𝒃都初始化为0,则在输入层之后的所有隐藏层神经元接收到的输入都是一样的,那么在使用反向传播算法进行梯度的传递时,每一隐藏层的权重梯度值都是相同的,这就导致了权重只能向同一方向下降
习题4-9 梯度消失问题是否可以通过增加学习率来缓解?
先了解一下什么是梯度消失问题
梯度消失问题: 在神经网络的构建过程中,随着网络层数的增加,理论上网络的拟合能力也应该是越来越好的。但是随着网络变深,参数学习更加困难,容易出现梯度消失问题。由于Sigmoid型函数的饱和性,饱和区的导数更接近于0,误差经过每一层传递都会不断衰减。当网络层数很深时,梯度就会不停衰减,甚至消失,使得整个网络很难训练,这就是所谓的梯度消失问题。
在一定程度上可以缓解。适当增大学习率可以使学习率与导数相乘结果变大,缓解梯度消失;过大学习率可能梯度巨大,导致梯度爆炸。
参考
邱锡鹏《神经网络与深度学习》—— 部分习题答案整理
深入理解ReLU、Leaky ReLU、 PReLU、ELU、Softplus
一篇文章完全搞懂正则化(Regularization)
【直观详解】什么是正则化
创作不易,如果对你有帮助,求求你给我个赞!!!
点赞 + 收藏 + 关注!!!
如有错误与建议,望告知!!!(将于下篇文章更正)
请多多关注我!!!谢谢!!!