RELU的神经网络反向传播

Dan*_*nny 28 backpropagation neural-network

我正在尝试用RELU实现神经网络.

输入层 - > 1隐藏层 - > relu - >输出层 - > softmax层

以上是我的神经网络的架构.我很担心这个relu的反向传播.对于RELU的导数,如果x <= 0,则输出为0.如果x> 0,则输出为1.因此,当您计算梯度时,这是否意味着如果x <= 0,我会消除梯度.

有人可以一步一步地解释我的神经网络架构的反向传播吗?

run*_*run 11

如果x <= 0,则输出为0.如果x> 0,则输出为1

ReLU函数定义为:对于x> 0,输出为x,即f(x)= max(0,x)

因此,对于导数f'(x),它实际上是:

如果x <0,则输出为0.如果x> 0,则输出为1.

导数f'(0)未定义.所以它通常设置为0或者你将激活函数修改为小e的f(x)= max(e,x).

通常:ReLU是使用整流器激活功能的单元.这意味着它的工作原理与任何其他隐藏层完全相同,但除了tanh(x),sigmoid(x)或您使用的任何激活之外,您将使用f(x)= max(0,x).

如果你已经为使用sigmoid激活的工作多层网络编写了代码,那么它实际上只有一行变化.关于前向或后向传播的任何内容都不会在算法上发生变化.如果你还没有更简单的模型工作,那就回过头来开始吧.否则你的问题不是关于ReLUs,而是关于整体实施NN.

  • 你确定这是正确的吗?我有工作反向传播代码,并且我更改了激活函数(在前向传播代码中)和梯度(在反向传播代码中),然后程序无法收敛以进行简单的异或测试。 (2认同)
  • 在我看来这里有一个混乱?OP声明0/1输出"对于RELU的衍生物"(这是正确的),而答案假设RELU本身的输出. (2认同)

IVl*_*lad 8

如果你有一个由单个ReLU构成的层,就像你的架构所暗示的那样,那么是的,你可以杀死渐变0.在训练期间,ReLU将返回0到您的输出层,该输出层将返回0或者0.5如果您使用的是后勤单位,则softmax将会压缩它们.因此,0在当前架构下的值对于前向传播部分也没有多大意义.

例如参见.你可以做的是使用"漏出的ReLU",这是一个很小的值0,例如0.01.

我会重新考虑这个架构,然而,将单个ReLU馈送到一堆其他单元然后应用softmax对我来说没有多大意义.


小智 8

\n

所以当你计算梯度时,这是否意味着如果 x <= 0 我就杀死梯度\n体面?

\n
\n

是的!\xe2\x80\x8c 如果神经元(激活函数输入)的输入和偏置的加权和小于零,并且神经元使用 Relu 激活函数,则反向传播期间导数的值为零,输入权重为该神经元不会改变(未更新)。

\n
\n

有人可以“一步一步”解释我的神经网络架构的反向传播吗?

\n
\n

一个简单的例子可以展示反向传播的一步。这个例子涵盖了一个步骤的完整过程。但您也可以只检查与 Relu 相关的部分。这与所介绍的架构类似,为了简单起见,在每一层中使用一个神经元。架构如下:

\n

在此输入图像描述

\n

f 和 g 分别代表 Relu 和 sigmoid,b 代表偏差。\n第 1 步:\n首先计算输出:

\n

在此输入图像描述

\n

这仅代表输出计算。“z”和“a”分别表示神经元的输入和神经元激活函数的输出值之和。\n因此 h 是估计值。假设实际值为 y。

\n

权重现在通过反向传播进行更新。

\n

新的权重是通过计算误差函数相对于权重的梯度,并从之前的权重中减去这个梯度得到的,即:

\n

瓦 = =

\n

在反向传播中,首先计算最后一层的最后一个神经元的梯度。使用链式导数规则来计算:

\n

在此输入图像描述

\n

上面使用的三个通用术语是:

\n
    \n
  • 实际值与估计值之间的差异

    \n
  • \n
  • 神经元输出平方

    \n
  • \n
  • 以及激活函数的导数,假设最后一层的激活函数是 sigmoid,我们有:

    \n
  • \n
\n

在此输入图像描述

\n

而且上面的说法并不一定会变成零。

\n

现在我们进入第二层。在第二层我们将有:

\n

在此输入图像描述

\n

它由 4 个主要术语组成:

\n
    \n
  • 实际值与估计值之间的差异。

    \n
  • \n
  • 神经元输出平方

    \n
  • \n
  • 下一层连接神经元的损失导数之和

    \n
  • \n
  • 激活器函数的导数,由于激活器函数是 Relu,我们将有:

    \n
  • \n
\n

if z2<=0(z2是Relu函数的输入):

\n

在此输入图像描述

\n

否则,它不一定为零:

\n

在此输入图像描述

\n

因此,如果神经元的输入小于零,则损失导数始终为零,权重不会更新。

\n

*重复一遍,神经元输入的总和必须小于零才能杀死梯度下降。

\n

给出的例子是一个非常简单的例子来说明反向传播过程。

\n


Bel*_*ter 6

这是一个很好的示例,使用ReLU来实现XOR:参考,http//pytorch.org/tutorials/beginner/pytorch_with_examples.html

# -*- coding: utf-8 -*-
import numpy as np
import matplotlib.pyplot as plt

# N is batch size(sample size); D_in is input dimension;
# H is hidden dimension; D_out is output dimension.
N, D_in, H, D_out = 4, 2, 30, 1

# Create random input and output data
x = np.array([[0, 0], [0, 1], [1, 0], [1, 1]])
y = np.array([[0], [1], [1], [0]])

# Randomly initialize weights
w1 = np.random.randn(D_in, H)
w2 = np.random.randn(H, D_out)

learning_rate = 0.002
loss_col = []
for t in range(200):
    # Forward pass: compute predicted y
    h = x.dot(w1)
    h_relu = np.maximum(h, 0)  # using ReLU as activate function
    y_pred = h_relu.dot(w2)

    # Compute and print loss
    loss = np.square(y_pred - y).sum() # loss function
    loss_col.append(loss)
    print(t, loss, y_pred)

    # Backprop to compute gradients of w1 and w2 with respect to loss
    grad_y_pred = 2.0 * (y_pred - y) # the last layer's error
    grad_w2 = h_relu.T.dot(grad_y_pred)
    grad_h_relu = grad_y_pred.dot(w2.T) # the second laye's error 
    grad_h = grad_h_relu.copy()
    grad_h[h < 0] = 0  # the derivate of ReLU
    grad_w1 = x.T.dot(grad_h)

    # Update weights
    w1 -= learning_rate * grad_w1
    w2 -= learning_rate * grad_w2

plt.plot(loss_col)
plt.show()
Run Code Online (Sandbox Code Playgroud)

有关ReLU派生产品的更多信息,请参见此处:http : //kawahara.ca/what-is-the-derivative-of-relu/

  • 关于这一行:`grad_h[h &lt; 0] = 0 # ReLU 的导数`。我明白。但是,我们是否还应该添加另一行:`grad_h[h &gt; 1] = 1`,因为 x&gt;0 时导数为 1? (2认同)