使用整流线性单元的反向传播

Posted

技术标签:

【中文标题】使用整流线性单元的反向传播【英文标题】:Backpropagation with Rectified Linear Units 【发布时间】:2015-06-09 15:55:49 【问题描述】:

我已经编写了一些代码来在具有逻辑激活函数和 softmax 输出的深度神经网络中实现反向传播。

def backprop_deep(node_values, targets, weight_matrices):
    delta_nodes = node_values[-1] - targets
    delta_weights = delta_nodes.T.dot(node_values[-2])
    weight_updates = [delta_weights]
    for i in xrange(-2, -len(weight_matrices)- 1, -1):
        delta_nodes = dsigmoid(node_values[i][:,:-1]) * delta_nodes.dot(weight_matrices[i+1])[:,:-1]
        delta_weights = delta_nodes.T.dot(node_values[i-1])
        weight_updates.insert(0, delta_weights)
    return weight_updates

代码运行良好,但是当我切换到 ReLU 作为激活函数时,它停止了工作。在反向传播例程中,我只更改激活函数的导数:

def backprop_relu(node_values, targets, weight_matrices):
    delta_nodes = node_values[-1] - targets
    delta_weights = delta_nodes.T.dot(node_values[-2])
    weight_updates = [delta_weights]
    for i in xrange(-2, -len(weight_matrices)- 1, -1):
        delta_nodes = (node_values[i]>0)[:,:-1] * delta_nodes.dot(weight_matrices[i+1])[:,:-1]
        delta_weights = delta_nodes.T.dot(node_values[i-1])
        weight_updates.insert(0, delta_weights)
    return weight_updates

但是,网络不再学习,权重很快变为零并停留在那里。我完全被难住了。

【问题讨论】:

你确定你有正确的导数表示吗? 我有理由确定我这样做了。输入为负时导数应为 0,输入为正时导数应为 1。 ReLU 在零处不可微,所以在这里我假设导数在零处为零。 如果 weight_matrices 的值小于 1,那么将导数设置为 0 或 1 将意味着您在随后的每个步骤中系统地减少 delta_nodes / delta_weights。也许你应该重新规范化它们? 如果这是问题所在,那么使用逻辑激活的反向传播也将是一个问题,因为导数被限制在 0 和 1 之间。 【参考方案1】:

虽然我已经确定了问题的根源,但我将保留它以防它可能对其他人有益。

问题是我在更改激活函数时没有调整初始权重的比例。当节点输入接近零并且逻辑函数近似线性时,逻辑网络学习得很好,而 ReLU 网络对于节点的中等大输入学习得很好。因此,逻辑网络中使用的小权重初始化是不必要的,实际上是有害的。我看到的行为是 ReLU 网络忽略了特征并试图专门学习训练集的偏差。

我目前在 MNIST 数据集上使用从 -.5 到 .5 均匀分布的初始权重,它的学习速度非常快。

【讨论】:

以上是关于使用整流线性单元的反向传播的主要内容,如果未能解决你的问题,请参考以下文章

正向传播和反向传播

正向传播和反向传播

神经网络梯度下降中的反向传播与线性回归

反向传播算法

反向传播神经网络入门

[ch02-02] 非线性反向传播