我是深度学习的初学者。我目前正在努力解决反向传播算法。我在网上找到了这段具有S型激活功能的简单神经网络的反向传播代码。#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)) - 1syn1 = 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_error和k2的输入之间的关系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和y靠得更近(最小化绝对误差),我们需要使误差更大/更正。从第一部分我们知道,可以通过向下推k2的输入来实现此目的(当k2的输入减小时,k2_error会增大)。情况2:> k2,表示> 0为了使y和k2靠得更近(最小化绝对误差),我们需要使误差更小/更负。从第一部分我们知道,可以通过向上推k2_error的输入来实现此目的(当y的输入增加时,k2会减小)。总而言之,如果k2为负(情况1),则通过向下推k2_error的输入将绝对误差最小化。如果k2为正(情况2),则通过向上推k2_error的输入将绝对误差最小化。k2的说明现在我们知道,k2_error的梯度下降最小化总是想将k2的输入向上推,但是这只会使k2_delta> k2_error时的绝对误差最小(上述情况2)。在案例1中,向上推k2的输入将增加绝对误差-因此我们在面对案例1时通过翻转其符号来修改y的输入处的梯度(称为k2)。情况1表示k2 k2乘以k2_delta来翻转渐变的符号!使用此翻转意味着当我们看到案例1时,梯度下降想要将k2_error的输入向下而不是向上推(我们迫使梯度下降放弃其默认行为)。总而言之,仅当面对案例1时,使用k2_delta会翻转常规渐变的符号,这可确保我们始终将绝对误差最小化(与最小化k2_error相对)。重要笔记您的算法通过添加负梯度来修改权重。通常,梯度下降通过减去梯度来修改权重。添加负梯度是一回事,但这确实使我的回答复杂化了。例如,在k2输入处的渐变实际上是k2_delta = k2_error*nonlin(k2, deriv=True),而不是k2_error。您可能想知道为什么我们使用k2而不是k2_delta = k2_error*(-1)*nonlin(k2, deriv=True),这是因为随着k2_delta = k2_error*nonlin(k2, deriv=True)变小,我们希望将权重移动较小的量。关于python - 如何为具有S形激活的简单神经网络进行反向传播?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/45195760/
10-11 03:24