动手实现深度神经网络6 神经网络的优化之权值衰减与Dropout
机器学习的问题中,过拟合是一个很常见的问题。过拟合
指的是只能拟合训练数据,但不能很好地拟合不包含在训练数据中的其他数据的状态
。
发生过拟合的原因,主要有以下两个:
- 模型拥有大量参数、表现力强。
- 训练数据少。
看到这两个原因,你可能会想到通过“减少参数”或“增加训练数据”来抑制过拟合,然而这两个方法要求过于苛刻,难以实现。
我们往往采取的抑制过拟合的方法有:权值衰减
和Dropout
。
权值衰减
权值衰减是一直以来经常被使用的一种抑制过拟合的方法。该方法通过在学习的过程中对大的权重进行惩罚,来抑制过拟合。因为很多过拟合原本就是 因为权重参数取值过大才发生的。
这里要先介绍一下L2范数
:
L2范数相当于各个元素的平方和的开方。用数学式表示的话,假设有权重 W = (w1,w2,…,wn),则L2范数就是(w12,w22,…,wn2)1/2
权值衰减的具体做法是:
- 对于所有权重,权值衰减方法都会为损失函数加上1/2λW(如果将权重记为W,L2范数的权值衰减就是1/2λW,λ是控制正则化强度的超参数)。
- 在求权重梯度的计算中,要为之前的误差反向传播法的结果加上正则化项的导数λW。
在代码中则主要体现在loss()方法和gradient()方法保存梯度时,具体位置我在下面的代码中用!做了标记
class MyTwoLayerNet:
"""全连接的多层神经网络
Parameters
----------
input_size : 输入大小(MNIST的情况下为784)
hidden_size_list : 隐藏层的神经元数量的列表(e.g. [100, 100, 100])
output_size : 输出大小(MNIST的情况下为10)
activation : 'relu' or 'sigmoid'
weight_init_std : 指定权重的标准差(e.g. 0.01)
指定'relu'或'he'的情况下设定“He的初始值”
指定'sigmoid'或'xavier'的情况下设定“Xavier的初始值”
weight_decay_lambda : Weight Decay(L2范数)的强度默认值设为0,也就是说默认情况下不进行权值衰减
"""
def __init__(self, input_size, hidden_size_list, output_size,
activation='relu', weight_init_std='relu', weight_decay_lambda=0):
self.input_size = input_size
self.output_size = output_size
self.hidden_size_list = hidden_size_list
self.hidden_layer_num = len(hidden_size_list)
self.weight_decay_lambda = weight_decay_lambda
self.params = {
}
# 初始化权重
self.__init_weight(weight_init_std)
# 生成层
activation_layer = {
'sigmoid': Sigmoid, 'relu': Relu}
self.layers = OrderedDict()
for idx in range(1, self.hidden_layer_num+1):
self.layers['Affine' + str(idx)] = Affine(self.params['W' + str(idx)],
self.params['b' + str(idx)])