深度学习--softmax函数推导

  softmax函数在神经网络中使用是比较频繁,我们刚刚学习的时候,只是直到网络的最后一层经过softmax层,得到最后的输出,但不知道它的具体公式推导,因此本篇,以一个简单的网络来说明神经网络的前向传播与反向传播。
  首先,以简单的单层网络为例。
深度学习--softmax函数推导_第1张图片
  隐含层对应的输出为:
     h1=w1i1+w4i2+w7i3 h 1 = w 1 ∗ i 1 + w 4 ∗ i 2 + w 7 ∗ i 3
     h2=w2i1+w5i2+w8i3 h 2 = w 2 ∗ i 1 + w 5 ∗ i 2 + w 8 ∗ i 3
     h3=w3i1+w6i2+w9i3 h 3 = w 3 ∗ i 1 + w 6 ∗ i 2 + w 9 ∗ i 3
  接下来h1、h2、h3经过softmax层,softmax的公式为: softmax(xi)=exi/jexj s o f t m a x ( x i ) = e x i / ∑ j e x j ,将o1,o2,o3带入公式:
     o1=eh1/(eh1+eh2+eh3) o 1 = e h 1 / ( e h 1 + e h 2 + e h 3 )
     o2=eh2/(eh1+eh2+eh3) o 2 = e h 2 / ( e h 1 + e h 2 + e h 3 )
     o3=eh3/(eh1+eh2+eh3) o 3 = e h 3 / ( e h 1 + e h 2 + e h 3 )
  我们假设,输出的正确标签label为 yi y i yi y i 的分布有一个特点,即:label中只有一个为1,其余懂为0,例如,本例中,label的真实标签 yi=[1,0,0] y i = [ 1 , 0 , 0 ] 。这个特点有助于在反向传播中的求导计算。
  整合前向传播的损失函数为:

LOSS=iyilnoi L O S S = − ∑ i y i ∗ l n o i

  根据label的特点,loss可以简化为: LOSS=yilnoi L O S S = − y i ∗ l n o i ,由于该类的变迁 yi=1 y i = 1 ,因此loss可以进一步简化为: LOSS=lnoi L O S S = − ∗ l n o i 。此时,在对损失函数求导是不是很方便了。
  接下来就是进行反向传播,范围传播的目的要更新网络中的参数 wi w i 。因为,我们先以 w1 w 1 为例。
     lossw1= ∂ l o s s ∂ w 1 =
     losso1o1h1h1w1 ∂ l o s s ∂ o 1 ∗ ∂ o 1 ∂ h 1 ∗ ∂ h 1 ∂ w 1
  这里我们将这三部分拆开进行计算:
  首先,我们来看 :
  第一部分:
     losso1=1o1 ∂ l o s s ∂ o 1 = − 1 o 1
  最后一部分 :
     h1w1=i1,(h1=w1i1+w4i2+w7i3) ∂ h 1 ∂ w 1 = i 1 , ( h 1 = w 1 ∗ i 1 + w 4 ∗ i 2 + w 7 ∗ i 3 )
  中间部分,也是最重要的部分:
     o1h1=(eh1/(eh1+eh2+eh3))h1= ∂ o 1 ∂ h 1 = ∂ ( e h 1 / ( e h 1 + e h 2 + e h 3 ) ) ∂ h 1 =
     eh1(eh1+eh2+eh3)eh12(eh1+eh2+eh3)2= e h 1 ∗ ( e h 1 + e h 2 + e h 3 ) − e h 1 2 ( e h 1 + e h 2 + e h 3 ) 2 =
     eh1eh1+eh2+eh3eeh1+eh2+eh3eh1eh1+eh2+eh3= e h 1 e h 1 + e h 2 + e h 3 ∗ e e h 1 + e h 2 + e h 3 − e h 1 e h 1 + e h 2 + e h 3 =
     eh1eh1+eh2+eh3(1o1)= e h 1 e h 1 + e h 2 + e h 3 ∗ ( 1 − o 1 ) =
     o1(1o1) o 1 ∗ ( 1 − o 1 )
  这三部分值都已经求出,因此;
     lossw1=(o11)i1 ∂ l o s s ∂ w 1 = ( o 1 − 1 ) ∗ i 1
  同理,其他参数的偏导数分别为:
     lossw2=(o21)i1 ∂ l o s s ∂ w 2 = ( o 2 − 1 ) ∗ i 1
     lossw3=(o31)i1 ∂ l o s s ∂ w 3 = ( o 3 − 1 ) ∗ i 1
     lossw4=(o11)i2 ∂ l o s s ∂ w 4 = ( o 1 − 1 ) ∗ i 2
     lossw5=(o21)i2 ∂ l o s s ∂ w 5 = ( o 2 − 1 ) ∗ i 2
     lossw6=(o31)i2 ∂ l o s s ∂ w 6 = ( o 3 − 1 ) ∗ i 2
     lossw7=(o11)i3 ∂ l o s s ∂ w 7 = ( o 1 − 1 ) ∗ i 3
     lossw8=(o21)i3 ∂ l o s s ∂ w 8 = ( o 2 − 1 ) ∗ i 3
     lossw9=(o31)i3 ∂ l o s s ∂ w 9 = ( o 3 − 1 ) ∗ i 3
  因此,最后w1的参数更新为:
w1+=w1ηlossw1 w 1 + = w 1 − η ∗ ∂ l o s s ∂ w 1

  其中 η η 为学习速率,同理更新其他的参数。本轮参数更新完毕后,在进行下一轮的前向传播和反向传播,更新参数,直到损失函数收敛。
  上面只是以一层简单的网络来推导公式,网络中不含有激活函数。下面以两层网络,并且含有激活函数的网络来说明,当然,这是参考牛人的博客: https://www.cnblogs.com/charlotte77/p/5629865.html。里面的推导非常详细,博客中的激活函数使用sigmoid,损失函数使用均方差。同时,我也用代码实现博客中的推导:

def sigmoid(input):
    return 1/(1 + np.exp(-input))

def test_nn():
    learing_rate = 0.1
    output = np.array([0.01,0.99],np.float32)
    x = np.array([0.05,0.1],np.float32)
    w1 = np.array([[0.15,0.25],[0.2,0.3]], np.float32)
    w2 = np.array([[0.4, 0.5], [0.45, 0.55]], np.float32)
    b1 = np.array([0.35,0.35],np.float32)
    b2 = np.array([0.6,0.6],np.float32)
    for i in range(100000):
        net1 = x.dot(w1) + b1
        # print(net1)
        # hidden layer1
        out1 = sigmoid(net1)
        # print(h1)
        net2 = out1.dot(w2) + b2
        out2 = sigmoid(net2)
        # print(out2)
        out_err = np.sum(np.square(out2 - output)/2)
        print('output error is:', out_err)

        #back propagation
        #∂Loss/∂w2 = ∂loss/out2* ∂out2/∂net2 * ∂net2/∂w2
        w2_ = (-(output - out2)*out2*(1 - out2)).reshape(2,1)
        w2_1 = w2_*(out1.reshape(1,2))
        # w2 update
        w2_update = w2 - learing_rate * w2_1.T

        w1_ = w2_.T * w2[0]
        err_sum = np.sum(w1_)
        w1_ = (err_sum * net1*(1-net1)).reshape(2,1)
        w1_ = (w1_*x)
        # w1 update
        w1_update = w1 - learing_rate * w1_
        # print(w1_update)
        w2 = w2_update
        w1 = w1_update
        print('result is :',out2,output)

test_nn()

  经过100000轮迭代后的损失已经将为:7.95119e-06,已经非常的低了,而此时的输出结果为[ 0.01280433 0.98716486],与正确结果[ 0.01 0.99000001],已经非常接近。

output error is: 7.95119e-06
result is : [ 0.01280433  0.98716486] [ 0.01        0.99000001]

  通过这两个例子,对深度学习的前向传播与反向传播就会有一个深入的了解,当然这也是深度学习的基础。只有将基础打好,才能学习与理解更深入的东西。

你可能感兴趣的:(深度学习)