虽然我们能够通过模块化的方式比较好地对神经网络进行组装,但是每个模块的梯度计算过程仍然十分繁琐且容易出错。在深度学习框架中,已经封装了自动梯度计算的功能,我们只需要聚焦模型架构,不再需要耗费精力进行计算梯度。
飞桨提供了paddle.nn.Layer
类,来方便快速的实现自己的层和模型。模型和层都可以基于paddle.nn.Layer
扩充实现,模型只是一种特殊的层。继承了paddle.nn.Layer
类的算子中,可以在内部直接调用其它继承paddle.nn.Layer
类的算子,飞桨框架会自动识别算子中内嵌的paddle.nn.Layer
类算子,并自动计算它们的梯度,并在优化时更新它们的参数。
pytorch中的相应内容是什么?请简要介绍。
使用Paddle的预定义算子来重新实现二分类任务。主要使用到paddle.nn.Linear。
1. 使用pytorch的预定义算子来重新实现二分类任务。(必做)
2. 增加一个3个神经元的隐藏层,再次实现二分类,并与1做对比。(必做)
3. 自定义隐藏层层数和每个隐藏层中的神经元个数,尝试找到最优超参数完成二分类。可以适当修改数据集,便于探索超参数。(选做)
【思考题】
自定义梯度计算和自动梯度计算:
从计算性能、计算结果等多方面比较,谈谈自己的看法。
实现一个神经网络前,需要先初始化模型参数。
如果对每一层的权重和偏置都用0初始化,那么通过第一遍前向计算,所有隐藏层神经元的激活值都相同;在反向传播时,所有权重的更新也都相同,这样会导致隐藏层神经元没有差异性,出现对称权重现象。
在神经网络的构建过程中,随着网络层数的增加,理论上网络的拟合能力也应该是越来越好的。但是随着网络变深,参数学习更加困难,容易出现梯度消失问题。
由于Sigmoid型函数的饱和性,饱和区的导数更接近于0,误差经过每一层传递都会不断衰减。当网络层数很深时,梯度就会不停衰减,甚至消失,使得整个网络很难训练,这就是所谓的梯度消失问题。
在深度神经网络中,减轻梯度消失问题的方法有很多种,一种简单有效的方式就是使用导数比较大的激活函数,如:ReLU。
ReLU激活函数可以一定程度上改善梯度消失问题,但是在某些情况下容易出现死亡ReLU问题,使得网络难以训练。
这是由于当x<0x<0时,ReLU函数的输出恒为0。在训练过程中,如果参数在一次不恰当的更新后,某个ReLU神经元在所有训练数据上都不能被激活(即输出为0),那么这个神经元自身参数的梯度永远都会是0,在以后的训练过程中永远都不能被激活。
一种简单有效的优化方式就是将激活函数更换为Leaky ReLU、ELU等ReLU的变种。
Git是什么?
Git是目前世界上最先进的分布式版本控制系统(没有之一)。
Git有什么特点?简单来说就是:高端大气上档次!
Git教程 - 廖雪峰的官方网站 (liaoxuefeng.com)
使用GitHub - 廖雪峰的官方网站 (liaoxuefeng.com)
使用Gitee - 廖雪峰的官方网站 (liaoxuefeng.com)
GitHub、Gitee 编写 ReadMe.md - HBU_DAVID - 博客园 (cnblogs.com)
Git - Gitee - HBU_DAVID - 博客园 (cnblogs.com)
NNDL 实验4(上) - HBU_DAVID - 博客园 (cnblogs.com)
NNDL 实验4(下) - HBU_DAVID - 博客园 (cnblogs.com)
2.5. 自动微分 — 动手学深度学习 2.0.0-beta1 documentation (d2l.ai)
4.7. 前向传播、反向传播和计算图 — 动手学深度学习 2.0.0-beta1 documentation (d2l.ai)