如何对使用Sigmoid激活函数的简单神经网络进行反向传播?

我是一名深度学习的初学者。目前正在努力理解反向传播算法。我在网上找到了一段关于使用Sigmoid激活函数的简单神经网络的反向传播代码。

#Step 1 Collect Datax = np.array([[0,0,1], [0,1,1], [1,0,1], [1,1,1]])y = np.array([[0], [1], [1], [0]])#Step 2 build modelnum_epochs = 60000#initialize weightssyn0 = 2np.random.random((3,4)) - 1 syn1 = 2np.random.random((4,1)) - 1def nonlin(x,deriv=False):    if(deriv==True): return x*(1-x)        return 1/(1+np.exp(-x))    for j in xrange(num_epochs): #feed forward through layers 0,1, and 2        k0 = x        k1 = nonlin(np.dot(k0, syn0))        k2 = nonlin(np.dot(k1, syn1))        #how much did we miss the target value?        k2_error = y - k2        if (j% 10000) == 0:            print "Error:" + str(np.mean(np.abs(k2_error)))        #in what direction is the target value?        k2_delta = k2_error*nonlin(k2, deriv=True)        #how much did each k1 value contribute to k2 error        k1_error = k2_delta.dot(syn1.T)        k1_delta= k1_error * nonlin(k1,deriv=True)        syn1 += k1.T.dot(k2_delta)        syn0 += k0.T.dot(k1_delta)

我无法理解这行代码:k2_delta = k2_error*nonlin(k2, deriv=True)。在计算局部梯度时,为什么使用k2_error乘以k2的导数。我们应该使用k2_error以外的其他东西吗?因为这个算法中的成本函数是绝对值,所以我应该使用一个[-1,1,1,-1]的向量作为成本函数的局部梯度吗?我假设这里使用的是解析梯度。


回答:

你可以按原样使用k2_error。我测试了你的代码(在进行格式调整后),并确认它最小化了绝对误差,这与k2_error(你算法中梯度下降的表面但非实际目标)不同。使用k2_delta = k2_error*nonlin(k2, deriv=True)是因为算法在最小化绝对误差而不是k2_error。这是如何运作的:

k2_errork2输入之间的关系

k2_error相对于k2的导数是-1。使用链式法则,k2_error相对于k2输入的导数是(-1)*(nonlin(k2, deriv=True))

因此:

  • k2_error相对于k2输入的导数总是负的。这是因为(nonlin(k2, deriv=True))总是正的。
  • 因此,k2_error的常规梯度下降最小化将始终希望将k2的输入向上推(使其更正)以使k2_error更负。

最小化绝对误差

对于k2_error = y-k2,有两种实际可能性,每种可能性都意味着不同的策略来最小化绝对误差(我们的真正目标)。(有一个不太可能的第三种可能性我们可以忽略。)

  • 情况1:y<k2,这意味着k2_error<0

    • 为了使yk2更接近(最小化绝对误差),我们需要使误差更大/更正。我们从第一部分知道,我们可以通过将k2的输入向下推来实现这一点(当k2的输入减少时,k2_error增加)。
  • 情况2:y>k2,这意味着k2_error>0

    • 为了使yk2更接近(最小化绝对误差),我们需要使误差更小/更负。我们从第一部分知道,我们可以通过将k2的输入向上推来实现这一点(当k2的输入增加时,k2_error减少)。

总结来说,如果k2_error为负(情况1),我们通过将k2的输入向下推来最小化绝对误差。如果k2_error为正(情况2),我们通过将k2的输入向上推来最小化绝对误差。

k2_delta的解释

我们现在知道,k2_error的梯度下降最小化将始终希望将k2的输入向上推,但这只有在y > k2(上面的情况2)时才会最小化绝对误差。在情况1中,将k2的输入向上推会增加绝对误差——所以我们通过在面对情况1时翻转其符号来修改k2输入处的梯度,这个梯度被称为k2_delta。情况1意味着k2_error<0,这意味着我们可以通过将k2_delta乘以k2_error来翻转梯度的符号!使用这种翻转意味着当我们看到情况1时,梯度下降希望将k2的输入向下推而不是向上推(我们强迫梯度下降放弃其默认行为)。

总结来说,使用k2_delta = k2_error*nonlin(k2, deriv=True)仅在面对情况1时翻转常规梯度的符号,这确保我们始终在最小化绝对误差(而不是最小化k2_error)。

重要说明

你的算法通过添加负梯度来修改权重。通常,梯度下降通过减去梯度来修改权重。添加负梯度是相同的事情,但这确实使我的回答有些复杂。例如,k2输入处的梯度实际上是k2_delta = k2_error*(-1)*nonlin(k2, deriv=True),而不是k2_delta = k2_error*nonlin(k2, deriv=True)

你可能想知道为什么我们使用k2_error而不是sign(k2_error),那是因为我们希望随着k2_error变小,权重移动的量也变小。

Related Posts

使用LSTM在Python中预测未来值

这段代码可以预测指定股票的当前日期之前的值,但不能预测…

如何在gensim的word2vec模型中查找双词组的相似性

我有一个word2vec模型,假设我使用的是googl…

dask_xgboost.predict 可以工作但无法显示 – 数据必须是一维的

我试图使用 XGBoost 创建模型。 看起来我成功地…

ML Tuning – Cross Validation in Spark

我在https://spark.apache.org/…

如何在React JS中使用fetch从REST API获取预测

我正在开发一个应用程序,其中Flask REST AP…

如何分析ML.NET中多类分类预测得分数组?

我在ML.NET中创建了一个多类分类项目。该项目可以对…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注