一、激活函数
- 前边我们学到,一个节点的输出会进入激活函数进行处理
- 常见的激活函数有以下
sigmoid激活函数
- sigmoid的公式如图
- 它将数据输入的压缩到[0,1]范围内输出
- 类似于神经元的饱和放电
问题1:饱和神经元将使得梯度消失
- 图中是一个sigmoid门
- 当x=-10时,梯度约为0
- 当x=0时,梯度为0.25,是0~1之间的值
- 当x=10时,梯度约为0
当x的值时很大的正数或很小的负数的时候,它们的值位于sigmoid图像的平滑区,这时候梯度消失,神经网络将无法得到梯度反馈
问题2:sigmoid是一个非零中心函数
- 当输入都为正数时会怎么样
- 梯度更新效率非常低
问题3:用到了指数计算,计算代价高
- 但这不是个大问题
tanh激活函数
- 与sigmoid很类似
- 将数据压缩到[-1,1]到范围
- 是以0为中心的函数
- 还是会使得梯度消失
ReLU激活函数
- ReLU函数方程如下图
- 如果输入为负数,则输出为0;如果输入为正数,则输出它本身。
- 在正向区域不会饱和
- 计算代价也比较低,速度是sigmoid或tanh的6倍
- 比sigmoid更具有生物学上的符合性
- 不是以0为中心的函数
- 在负向区域,梯度会消失:
- 当x=10时,梯度为1,正常
- 当x=0时,没有梯度,可以取0
- 当x=-10时,梯度为0
Leaky ReLU 激活函数
- 是对ReLU的改进
- 函数公式如图
- 没有饱和的情况,即使在负空间
- 不会失效
PReLU激活函数
- 也是对ReLU的改进
- 与Leaky ReLU
类似,但是引入参数,使系数可变 - 函数公式如上图
ELU激活函数
- 函数公式如下图
- 拥有ReLU的所有优点
- 它的输出均值接近为0
- 在负区域相比Leaky ReLU增加了对噪声的健壮性(鲁棒性)
- 计算量较大
Maxout “Neuron” 激活函数
- 可以看到它的形式和其他函数不同
- 它泛化了ReLU和Leaky ReLU
- 线性相关,不会饱和,不会失效
- 会把每个神经元的参数量翻倍
经验总结
- 在实践中,一般最好的经验是使用ReLU
- 使用ReLU时,注意学习率的调整
- 可以尝试类ReLU函数,但表现一般
- 可以尝试 tanh函数,表现也一般
- 一般不要使用sigmoid
二、数据预处理
- 对原始数据进行,0中心化处理
- 对数据进行归一化处理
- 在图像处理领域一般只做0中心化,不做归一化
- 在机器学习中还会遇到更加复杂的情况,像PCA、白化
经验总结
- 在实际的图像处理中,值进行0中心化处理
- 例如 CIFAR-10,图片大小为[32,32,3]:
- 减去均值(大小为[32,32,3])
- 减去单通道均值
三、权重初始化
问题1:当初始权重都为0会怎么样?
- 答:所有的神经元都会做相同的事,相同的输出,相同的梯度,不能从不同的神经元学的不同的知识
方法1:是给所有权重一个小的随机值
- 从标准高斯中抽样
- 再乘以0.01
- 在小型网络中运行良好,但是在更深层的网络中就会有问题
一个例子说明存在的问题
- 这是一个10层的神经网络,每一层500个神经元
- 使用tanh激活函数
- 使用小的随机数来初始化权重
- 下面是激活函数的结果
- 从图1中可以看出,均值总是在0附近(快速的趋于0)
- 从图2中可以看出,标准差总是在0附近(快速的趋于0)
- 从图3可以看出,输出的值全部变成0
- 反向传播的情况呢,梯度是什么样的?
- 梯度是很小的值,趋于0,所以权重得不到更新
- W×X门的反向传播怎么样呢?
- 依然是趋于0
方法2:在1的基础上增大权重的值
- 还是上面的例子
- 我们从高斯分布取样
- 乘以1.0而不是0.01
- 所有的神经元都饱和了,因为权重太大,通过激活函数tanh后,激活值分布在平滑区(趋于-1,或趋于1),梯度都为0
方法3:Xavier(一个好的方法)
- 从高斯分布取样
- 根据输入的个数来决定相乘的数值大小
- 当我们有大量的输入,将会得到较小的权重
- 当我们有少量的输入,将会得到较大的权重
- 当我们使用ReLU激活函数时,它将会使网络崩溃
- 它会消除一半的神经元,把你得到的方差减半
- 使得激活后的值趋近于0
- 有一个方法来解决上面的问题
- 因为有一半神经元被消灭,所以除以2,可以保证数量的一致性
扩展
如果对初始化感兴趣,可以看看下边的论文
四、批量归一化
- 在我们想要的高斯范围内保持激活
- 在训练的时候实现归一化而不是初始化
- 在某一层实现高斯分布,对每一个维度执行这个公式
- 如下图,我没有N个训练样本,每个样本是D维的
- 我们计算每个样本的均值和方差
- 进行归一化
- 归一化通常在全连接层或者卷积层之后
- 在非线性层(激活函数)之前
- 更多详细的内容请参考论文
- 问题:对于tanh激活函数来说,我们是否需要一个高斯分布的输入?
- 答:这可能会导致饱和,但是适度的饱和也是可以的,所以我们可以在归一化之后进行额外的缩放操作来减少饱和。
- 这个缩放的操作可以恢复恒等映射,相当于没有进行过归一化
总结归一化
- 输入:小批量输入的值x:求均值;超参数。
- 输出:归一化,缩放、平移后的值。
- 具体步骤如图:
- 计算小批量的均值
- 计算小批量的方差
- 进行归一化
- 进行额外的缩放和平移
- 归一化的作用:
- 改善网络的梯度流
- 允许更高的学习率,拥有更好的健壮性
- 减少对初始化的依赖
- 可以看作一种正则化
- 注意:在测试阶段批量归一化层是不同的:不需要再计算均值和方差,因为在训练阶段已经计算过了。(??)
五、观察学习过程
- 数据预处理
- 选择网络结构
- 初始化我们的网络
- 检查我们的损失函数是否是应该的样子
- 这是个很好的完整性测试
- 首先,不进行正则化,损失是我们预计的值
- 进行正则化,损失变大
- 开始训练,先从小数据集开始,不进行正则化,看损失是否会减小到0
- 开始真正的训练,使用完整的数据集,加一个小的正则化,找到合适学习率,使得损失下降
- 损失下降缓慢,学习率太低
- 学习率太大,会导致损失值为nans
- 一般学习率设置为 1
e-3 ~ 1e-5
六、超参数优化
- 对任何大超参数,执行交叉验证,找到最佳值
- 首先,选取比较分散的值,使用几个epoch的迭代去学习,这样就可以快速的知道那些超参数的值是好的,得到一个参数区间
- 然后,在这个参数区间中进一步精确搜索
- 如果cost的值是使用其他参数值的3倍以上,那么说明这个参数值是不合适的
- 随机搜索效果更好
- 黄色的线,学习率太高了
- 蓝色的线,收敛太慢,学习率太低了
- 绿色的线,学习率高,局部最优
- 红色的线,是最好的,能够快速持续的收敛
- 如上图这样的情况,应该是初始值没有设好
- 训练精度和验证精度差距太大,意味着过拟合
- 没有差距,说明没有过拟合,可以增加模型容量,来提高训练速度