首先查了一下XOR问题描述以及XOR运算的网络结构设计 :
1、 XOR问题描述
异或是对两个运算元的一种逻辑分析类型,当两两数值相同时为否,而数值不同时为真。异或的真值表见表1-1所示:表1-1 异或的真值表
2、XOR运算的网络结构设计
为了采用前馈神经网络解决XOR问题,首先我们通过引入其他逻辑运算与XOR问题进行对比分析,从而设计适合解决XOR运算的网络结构模型。如图1-1和图1-2所示,图中的直线是决策边界。在逻辑运算与、或运算中我们总可以找到一条直线对它们进行准确的分类,它们属于线性可分。然而在图1-3所示的XOR问题中,我们无法找到一条直线将其进行准确的分类,XOR属于一种线性不可分。由于单层神经网络只能解决线性问题,无法解决非线性问题,异或问题属于非线性问题,所以感知机无法解决异或问题。要解决XOR运算问题,需要生成非线性的决策边界。因此,我们使用多层感知机进行求解,在单层前馈神经网络的基础上,加入一层隐含层,即二层的前馈神经网络进行XOR的运算网络结构设计如图1-4所示。从图中可以看出我们设计了一个二层的前馈神经网络对XOR运算进行求解。网络结构由一个输入层、一个隐含层和一个输出层构成,其中输入层有两个神经元,隐含层有两个神经元,输出层有一个神经元构成。
图1-1 AND 图1-2 OR 图1-3 XOR
隐含层的表达式见公式1和公式2所示。
h1 = w11x1+w21x2+b11 (1)
h2= w12x1+w22x2+b12 (2)
输出层表达式如公式3所示。
y=w’11x1+w’21x2+b11 (3)
图1-4 XOR运算网络结构图
代码实现:
import torch
from torch.nn.init import constant_, normal_
import numpy as np
# 数据输入
input_x = torch.tensor([[0, 0], [0, 1], [1, 0], [1, 1]])
input_x = input_x.float()
real_y = torch.tensor([[0], [1], [1], [0]])
real_y = real_y.float()
class XOR_module(torch.nn.Module):
def __init__(self, input_size=2, output_size=1, mean_init=0., std_init=1., b_init=0.0):
super(XOR_module, self).__init__()
self.fc1 = torch.nn.Linear(input_size, 2)
normal_(tensor=self.fc1.weight, mean=mean_init, std=std_init)
constant_(tensor=self.fc1.bias, val=b_init)
self.fc2 = torch.nn.Linear(2, output_size)
normal_(tensor=self.fc2.weight, mean=mean_init, std=std_init)
constant_(tensor=self.fc2.bias, val=b_init)
# 使用'torch.nn.ReLU'定义 relu 激活函数
self.act = torch.nn.ReLU()
# 前向计算
def forward(self, inputs):
outputs = self.fc1(inputs)
outputs = self.act(outputs)
outputs = self.fc2(outputs)
outputs = self.act(outputs)
return outputs
net = XOR_module()
learing_rate = 0.1
epochs = 10000
loss_function = torch.nn.MSELoss() # 用交叉熵损失函数会出现维度错误
optimizer = torch.optim.SGD(net.parameters(), lr=learing_rate)
# 进行训练
for epoch in range(epochs):
out_y = net(input_x)
loss = loss_function(out_y, real_y) # 计算损失函数
loss.backward() # 反向传播
optimizer.step() # 参数更新
optimizer.zero_grad() # 对梯度清零,避免造成累加
# 进行测试
input_test = input_x
out_test = net(input_test)
print('输入x', input_test.detach().numpy())
print('预测值y', np.around(out_test.detach().numpy()))
运行结果:
参考文章:https://zhuanlan.zhihu.com/p/390027968
在反向传播过程中,如果学习率比较大,一个很大的梯度经过ReLU神经元,可能会导致ReLU神经元更新后的偏置和权重是负数,进而导致下一轮正向传播过程中ReLU神经元的输入是负数,输出是0。由于ReLU神经元的输出为0,在后续迭代的反向过程中,该处的梯度一直为0,相关参数不再变化,从而导致ReLU神经元的输入始终是负数,输出始终为0。即为“死亡ReLU问题”
解决方法:
1、使用带泄露的ReLU
2、使用带参数的ReLU
3、使用正则项约束参数
4、使用其他方式训练网络,例如Adam
参考文章:https://blog.csdn.net/weixin_37870870/article/details/108877464
答:正则化的作用是为了限制模型的复杂度避免模型过拟合,提高模型的泛化能力。
对于某个神经元的输入来说,input = w(0)x(0) + w(1)x(1) + w(2)x(2) + ······ + b
对于样本特征向量X,其对input的贡献只与权重向量W有关。
若W向量中的值都很大,若特征向量X中的值发生细微的变化会导致input值的突变。
这就导致了模型的不稳定,所有我们希望得到较小的权重值。而偏置b对于所有输入样本来说都是一致的,是一个不变量,所以不需要考虑对B进行正则化。
对于神经网络正则化,一般只对每一层仿射变换的weights进行正则化惩罚,而不对偏置bias进行正则化。
相比于weight,bias训练准确需要的数据要更少。每个weight指定了两个变量之间的关系。weights训练准确需要在很多种情况下的同时观察两个变量。每个bias只控制一个变量。这意味着不对bias正则化,没有引入很多方差(variance)。同时,对bias进行正则化容易引起欠拟合。
——————来自 《DeepLearning》Chapter 7.1。
参考文章:https://blog.csdn.net/qq_36810398/article/details/90756828
反向传播就是要将神经网络的输出误差,一级一级地传播到输入。在计算过程中,计算每一个w 对总的损失函数的影响,即损失函数对每个w的偏导。根据w的误差的影响,再乘以步长,就可以更新整个神经网络的权重。当一次反向传播完成之后,网络的参数模型就可以得到更新。更新一轮之后,接着输入下一个样本,算出误差后又可以更新一轮,再输入一个样本,又来更新一轮,通过不断地输入新的样本迭代地更新模型参数,就可以缩小计算值与真实值之间的误差,最终完成神经网络的训练。当直接令w =0,b=0时,会让下一层神经网络中所有神经元进行着相同的计算,具有同样的梯度,同样权重更新。
梯度消失是传统神经网络训练中非常致命的一个问题,其本质是由于链式法则的乘法特性导致的。比如之前神经网络中最流行的激活函数之一Sigmoid,其表达式如下:
f ( z ) = 1 1 + e − z f(z)=\frac{1}{1+e^{-z}} f(z)=1+e−z1
这个函数的导数:
f ′ ( z ) = f ( z ) ( 1 − f ( z ) ) f{}'(z)=f(z)(1-f(z)) f′(z)=f(z)(1−f(z))
对于Sigmoid,导数的最大值在输入为0处,值为0.25.考虑一个激活函数都是Sigmoid的多层神经网络,则梯度向后传导时,没经过一个Sigmoid就需要乘以一个小于0.25的梯度。而每乘以一个小于0.25的梯度,则梯度的值又变得更小一些。况且在优化的过程中,每个激活层输入都在0附近的概率非常的低。也就是说随着层数的加深,梯度的衰减会非常的大,迅速接近0,这就是梯度消失的现象。
梯度消失问题是由于激活函数为类似于sigmoid与tanh,其值太大或太小时导数都趋于0;并且在深层神经网络中,误差反向传播时,传播到前几层时梯度信息也会很小。
增大学习率带来的缺陷会比梯度消失问题更加严重,学习率变大时,很容易使得参数跳过最优值点,然后梯度方向改变,导致参数优化时无法收敛。其次这样会导致这个较大的学习率与最开始较大的导数相乘结果十分巨大,导致梯度爆炸。
参考文章:https://blog.csdn.net/pursuit_zhangyu/article/details/80830565
本次内容与上次实验内容有着很大关联,例如死亡Relu问题,梯度消失、梯度爆炸问题等,这次作业更侧重于个人理解,偏理论性;而实验更多是注重的操作,通过代码运行的结果可以直观的了解问题。通过本次作业,我对很多知识有了深入了解,例如梯度消失本质是由于链式法则的乘法特性导致的,还有对bias进行正则化容易引起欠拟合。