NNDL 作业4:第四章课后题

4.2试设计一个前馈神经网络来解决XOR问题,要求该前馈神经网络具有两个隐藏神经元和一个输出神经元,并使用ReLU作为激活函数.
XOR问题描述:异或是对两个运算元的一种逻辑分析类型,当两两数值相同时为否,而数值不同时为真。
NNDL 作业4:第四章课后题_第1张图片
XOR运算的网络结构图:
NNDL 作业4:第四章课后题_第2张图片
代码:

import torch
import torch.nn as nn
import torch.optim as optim
 
# 异或门模块由两个全连接层构成
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(reduction='mean')  # 用交叉熵损失函数会出现维度错误
optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)  # 用Adam优化参数选不好会出现计算值超出0-1的范围
 
# 进行训练
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.5185386  -0.64158344]
 [ 0.00888623  0.00222858]]
b1 =  [-0.00175235  0.7334537 ]
w2 =  [[0.09213727 0.2758358 ]]
b2 =  [0.29613346]
input_x [[0. 0.]
 [0. 1.]
 [1. 0.]
 [1. 1.]]
out_y [[0.49844626]
 [0.499061  ]
 [0.5008974 ]
 [0.5015121 ]]

4.3 试举例说明“死亡ReLU问题”,并提出解决办法。
在反向传播过程中,如果学习率比较大,一个很大的梯度经过ReLU神经元,可能会导致ReLU神经元更新后的偏置和权重是负数,进而导致下一轮正向传播过程中ReLU神经元的输入是负数,输出是0。由于ReLU神经元的输出为0,在后续迭代的反向过程中,该处的梯度一直为0,相关参数不再变化,从而导致ReLU神经元的输入始终是负数,输出始终为0。即为“死亡ReLU问题”
解决方法:
1.使用带泄露的ReLU
2.使用带参数的ReLU
3.使用正则项约束参数
4.使用其他方式训练网络,例如Adam
4.7为什么神经网络模型的结构化风险函数中不对偏置b进行正则化。
正则化的作用是为了限制模型的复杂度避免模型过拟合,提高模型的泛化能力。
对于某个神经元的输入来说,input = w(0)x(0) + w(1)x(1) + w(2)x(2) + ······ + b
对于样本特征向量X,其对input的贡献只与权重向量W有关。
若W向量中的值都很大,若特征向量X中的值发生细微的变化会导致input值的突变。
这就导致了模型的不稳定,所有我们希望得到较小的权重值。而偏置b对于所有输入样本来说都是一致的,是一个不变量,所以不需要考虑对B进行正则化。
4.8为什么用反向传播算法进行参数学习时要采用随机参数初始化的方法而不是直接令W=0,b=0?
反向传播就是要将神经网络的输出误差,一级一级地传播到输入。在计算过程中,计算每一个w 对总的损失函数的影响,即损失函数对每个w的偏导。根据w的误差的影响,再乘以步长,就可以更新整个神经网络的权重。当一次反向传播完成之后,网络的参数模型就可以得到更新。更新一轮之后,接着输入下一个样本,算出误差后又可以更新一轮,再输入一个样本,又来更新一轮,通过不断地输入新的样本迭代地更新模型参数,就可以缩小计算值与真实值之间的误差,最终完成神经网络的训练。
若将和都初始化为0,则在输入层之后的所有隐藏层神经元接收到的输入都是一样的,那么在使用反向传播算法进行梯度的传递时,每一隐藏层的权重梯度值都是相同的,这就导致了权重只能向同一方向下降。
梯度消失问题是否可以通过增加学习率来缓解?
在一定程度上可以缓解。适当增大学习率可以使学习率与导数相乘结果变大,缓解梯度消失;过大学习率可能梯度巨大,导致梯度爆炸。

你可能感兴趣的:(深度学习)