NNDL 作业4:第四章课后题

XOR输入为2个神经元,输出为一个神经元,此题要求隐藏神经元为2个,故只要两层全连接层即可。

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 torchvision
import torch.nn as nn
from XORModule import XORModule
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()
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)  # 计算损失函数
    # print('啦啦啦')
    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())

relu函数和sigmoid函数相比,虽然能够避免反向传播过程中的梯度消失、屏蔽负值、防止梯度饱和;

但是relu也有自身的缺陷,当学习率过大时会出现某些神经元永久死亡的现象,导致网络后期无法正常更新

原因分析:

w′=w−ηΔw

上式是神经网络权重更新的公式,其中η表示学习吕,Δw表示通过求导得到的当前参数的梯度(一般为正值)当学习率过大时,会导致 ηΔw 这一项很大,当 ηΔw 大于w时,更新后的w’就会变为负值;

当权重参数变为负值时,输入网络的正值会和权重相乘后也会变为负值,负值通过relu后就会输出0;如果w在后期有机会被更新为正值也不会出现大问题,但是当relu函数输出值为0时,relu的导数也为0,因此会导致后边Δw一直为0,进而导致w一直不会被更新,因此会导致这个神经元永久性死亡(一直输出0)

 

首先模型公式为

这里的W对于函数影响是比较大的,这个偏置 b 对于函数来说只是进行一个向左或向右的平移,并且 b 对输入的改变是不敏感的,无论输入变大还是变小, b 对结果的贡献只是一个偏置,因此其对过拟合没有帮助。

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

 

 反向传播就是要将神经网络的输出误差,一级一级地传播到输入。在计算过程中,计算每一个w对总的损失函数的影响,即损失函数对每个w的偏导。根据w的误差的影响,再乘以步长,就可以更新整个神经网络的权重。当一次反向传播完成之后,网络的参数模型就可以得到更新。更新一轮之后,接着输入下一个样本,算出误差后又可以更新一轮,再输入一个样本,又来更新一轮,通过不断地输入新的样本迭代地更新模型参数,就可以缩小计算值与真实值之间的误差,最终完成神经网络的训练。
因为如果参数都设为0,在第一遍前向计算的过程中所有的隐藏层神经元的激活值都相同。在反向传播时,所有权重更新也都相同,这样会导致隐藏层神经元没有区分性。这种现象称为对称权重现象。这就导致神经网络可以更新多权重没意义了,所以需要采用随机参数初始化的方式。
————————————————
版权声明:本文为CSDN博主「五元钱」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_52086410/article/details/127229725

 不行。

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值