NNDL 作业四:第四章课后习题

NNDL 作业四:第四章课后习题

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

答:
XOR问题:

X1 X2 Output
0 0 0
0 1 1
1 0 1
1 1 0

import torch.nn as nn
import torch
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())

结果:

NNDL 作业四:第四章课后习题_第1张图片

 

习题4-3:试举例说明“死亡ReLU问题”,并提出解决方法.

答:

NNDL 作业四:第四章课后习题_第2张图片在反向传播过程中,如果学习率比较大,一个很大的梯度经过ReLU神经元,可能会导致ReLU神经元更新后的偏置和权重是负数,进而导致下一轮正向传播过程中ReLU神经元的输入是负数,输出是0。由于ReLU神经元的输出为0,在后续迭代的反向过程中,该处的梯度一直为0,相关参数不再变化,从而导致ReLU神经元的输入始终是负数,输出始终为0。即为“死亡ReLU问题”
解决方法:
使用Leaky ReLU/PReLU、ELU函数或者Softplus函数替换。
习题4-7:为什么在神经网络模型的结构化风险函数中不对偏置b进行正则化?

答:在神经网络模型的结构化风险函数中加入正则化项,可以避免过拟合。

对于神经网络正则化,一般只对每一层仿射变换的weights进行正则化惩罚,而不对偏置bias进行正则化。相比于weight,bias训练准确需要的数据要更少。每个weight指定了两个变量之间的关系。weights训练准确需要在很多种情况下的同时观察两个变量。每个bias只控制一个变量。这意味着不对bias正则化,没有引入很多方差(variance)。

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

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

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

同时,对bias进行正则化容易引起欠拟合。因此对于偏置b进行正则化对于防止过拟合没有什么影响。

习题4-8:为什么在用反向传播算法进行参数学习时要采用随机参数初始化的方式而不是直接令w =0,b = 0?

答:反向传播就是要将神经网络的输出误差,一级一级地传播到输入。在计算过程中,计算每一个w对总的损失函数的影响,即损失函数对每个w 的偏导。根据w 的误差的影响,再乘以步长,就可以更新整个神经网络的权重。当一次反向传播完成之后,网络的参数模型就可以得到更新。更新一轮之后,接着输入下一个样本,算出误差后又可以更新一轮,再输入一个样本,又来更新一轮,通过不断地输入新的样本迭代地更新模型参数,就可以缩小计算值与真实值之间的误差,最终完成神经网络的训练。如果将和都初始化为0,则在输入层之后的所有隐藏层神经元接收到的输入都是一样的,那么在使用反向传播算法进行梯度的传递时,每一隐藏层的权重梯度值都是相同的,这就导致了权重只能向同一方向下降,这和问题4-1有一定的相似性,只不过是从权重和偏置方面导致了输入X值的非零均值化(更极端的是所有值相同)。

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

答:梯度消失问题,简单地说,根据链式法则,如果每一层神经元对上一层的输出的偏导乘上权重结果都小于1的话(w_{ij}y_{i}^{'}<1.0 ),那么即使这个结果是0.99,在经过足够多层传播之后,误差对输入层的偏导会趋于0(\lim_{n\rightarrow \infty }0.99^{n}=0 )。它是由于激活函数为类似于sigmoid与tanh,其值太大或太小时导数都趋于0;并且在深层神经网络中,误差反向传播时,传播到前几层时梯度信息也会很小。通过增加学习率在一定程度上可以缓解。适当增大学习率可以使学习率与导数相乘结果变大,缓解梯度消失;过大学习率可能梯度巨大,导致梯度爆炸。

总结:本次内容与上次实验内容有许多共同的知识点,例如死亡Relu问题,梯度消失、梯度爆炸问题等,实验更多是注重的操作,通过代码运行的结果可以直观的了解问题。正是由于完成了上次实验,让我对本次理论的理解更加透彻,解答起来也更加容易,所以理论和实践相结合是非常重要的。

你可能感兴趣的:(深度学习,人工智能)