【问题标题】:Confusion about sigmoid derivative's input in backpropagation关于反向传播中 sigmoid 导数输入的困惑
【发布时间】:2020-06-21 22:31:21
【问题描述】:

当使用链式法则计算成本函数相对于L层权重的斜率时,公式变为:

d C0 / d W(L) = ... . d a(L) / d z(L) . ...

与:

z (L) 是诱导局部场:z (L) = w1(L) * a1(L-1) + w2(L) * a2(L-1) * ...

a (L) 输出:a (L) = & (z (L))

& 是用作激活函数的 sigmoid 函数

注意L被视为层指示符而不是索引

现在:
d a(L) / d z(L) = &' ( z(L) )

&' 是 sigmoid 函数的导数

问题:

但是在这个post 中,James Loy 编写了关于使用 python 从头开始​​构建一个简单的神经网络的文章,
在进行反向传播时,他没有将 z (L) 作为 @ 的输入987654333@ 替换链式规则函数中的d a(L) / d z(L)。相反,他给了它output = last activation of the layer (L)作为输入sigmoid导数&'

def feedforward(self):
        self.layer1 = sigmoid(np.dot(self.input, self.weights1))
        self.output = sigmoid(np.dot(self.layer1, self.weights2))

def backprop(self):
        # application of the chain rule to find derivative of the loss function with respect to weights2 and weights1
        d_weights2 = np.dot(self.layer1.T, (2*(self.y - self.output) * sigmoid_derivative(self.output)))

请注意,在L 层上方的代码中,2 层是最后一层或输出层。 而sigmoid_derivative(self.output) 这是将当前层的激活作为输入给用作激活函数的 sigmoid 函数的导数的地方。

问题:

我们不应该使用这个sigmoid_derivative(np.dot(self.layer1, self.weights2)) 而不是这个sigmoid_derivative(self.output)吗?

【问题讨论】:

    标签: python neural-network backpropagation derivative activation-function


    【解决方案1】:

    原来使用&( z(L) )output,只是为了适应sigmoid_derivative的实现方式。

    这是sigmoid_derivative的代码:

    def sigmoid(x):
        return 1.0/(1+ np.exp(-x))
    
    def sigmoid_derivative(x):
        return x * (1.0 - x)
    

    sigmoid_derivative的数学公式可以写成:&' (x) = &(x) * (1-&(x))

    所以要得到上面的公式,&(z) 而不是 z 被传递给 sigmoid_derivative 以便返回:&(z) * (1.0 - &(z))

    【讨论】:

      【解决方案2】:

      您想对输出使用导数。在反向传播期间,我们仅使用权重来确定每个权重有多少误差,通过这样做,我们可以进一步将误差传播回各层。

      在教程中,sigmoid应用于最后一层:

      self.output = sigmoid(np.dot(self.layer1, self.weights2))
      

      根据您的问题:

      我们不应该使用这个 sigmoid_derivative(np.dot(self.layer1, self.weights2)) 代替这个 sigmoid_derivative(self.output) 吗?

      你不能这样做:

      sigmoid_derivative(np.dot(self.layer1, self.weights2))
      

      因为在这里你试图在尚未应用 sigmoid 的情况下对其进行导数。

      这就是你必须使用的原因:

      sigmoid_derivative(self.output)
      

      【讨论】:

      • 但是为什么要打破公式并得到&' (&(z)) 而不是得到&'(z),这将打破链式法则的组成部分之间的比率:d C / d W(L) = d z(L) / d w(L) * d a(L) / d z(L) * d C / d a(L)
      • 链式法则的主要原因是给出每个变量对成本变化的影响C,而& ( z(L))本身对成本有影响。为什么不采用&' (z(L)) 并尊重公式?为什么选择&' (&(z(L)))
      • 同样在任何阶段z (L) 与权重和之前的激活有关。
      • @EEAH 我更新了我的答案。我希望现在更清楚了。
      【解决方案3】:

      你是对的-看起来作者犯了一个错误。我将解释:当网络完成前向传递(所有激活 + 损失)时,您必须使用梯度下降来根据损失函数最小化权重。为此,您需要损失函数对每个权重矩阵的偏导数。

      在我继续之前的一些符号:损失是LA 是激活(又名 sigmoid),Z 表示净输入,换句话说,W . X 的结果。数字是索引,所以A1 表示第一层的激活。

      您可以使用链式法则在网络中向后移动,并将权重表示为损失的函数。要开始反向传递,首先要获取损失相对于最后一层激活的导数。这是dL/dA2,因为第二层是最后一层。要更新第二层的权重,我们需要完成dA2/dZ2dZ/dW2

      在继续之前,请记住第二层的激活是A2 = sigmoid(W2 . A1)Z2 = W2 . A1。为清楚起见,我们将写为A2 = sigmoid(Z2)。将Z2 视为自己的变量。所以如果你计算dA2/dZ2,你会得到sigmoid_derivative(Z2),即sigmoid_derivative(W2 . A1)sigmoid_derivative(np.dot(self.layer1, self.weights2))。所以它不应该是sigmoid_derivative(self.output),因为output是被sigmoid激活的。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-10-24
        • 2016-09-19
        • 2014-11-30
        • 1970-01-01
        • 2021-05-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多