天天看點

神經網絡Softmax層 Python實作

                                            Softmax Python實作

一 、不使用one-hot編碼

import numpy as np

def data_loss_softmax(scores, labels):
    num_examples = scores.shape[0]
    exp_scores = np.exp(scores)
    exp_scores_sum = np.sum(exp_scores, axis=1)

    correct_probs = exp_scores[range(num_examples), labels] / exp_scores_sum
    correct_probs = -np.log(correct_probs)
    data_loss = np.sum(correct_probs) / num_examples
    return data_loss


data=np.array([[0.6,0.2,0.01],[0,0,1],[0.02,0.9,0.3]])
print(data)
labels=np.array([0,2,1])
print(data_loss_softmax(data,labels))
           

 1 【data】 3*3 每行一個樣本,列代表神經網絡最後一層的分類值大小,次元為3

[[0.6  0.2  0.01]
 [0.   0.   1.  ]
 [0.02 0.9  0.3 ]]
           

 2【label】 代表真實的類别 0 1 2代表分類号,這裡不使用one-hot編碼

   [0,2,1]

3  num_examples = scores.shape[0]

   exp_scores = np.exp(scores)

   對矩陣exp_scores 每一個取指數 exp()

[[1.8221188  1.22140276 1.01005017]
 [1.         1.         2.71828183]
 [1.02020134 2.45960311 1.34985881]]
           

4 exp_scores_sum = np.sum(exp_scores, axis=1)

 對每一行計算和,注意axis=1 代表在第二個軸上計算和這樣第二軸的次元計算完畢後就會變為1

[4.05357173 4.71828183 4.82966326]
           

 5   correct_probs = exp_scores[range(num_examples), labels] / exp_scores_sum

     注意此處取出了每個樣本(每行)對應的真實類别号位置的值,這也是為何沒有使用one-hot編碼

  的原因

注意 exp_scores[range(num_examples), labels]和  exp_scores[:, labels]的差別  exp_scores[range(num_examples), labels]計算獲得是3*1的次元,而  exp_scores[:, labels]獲得的還是3*3 的次元,使用exp_scores[range(num_examples), labels]可以獲得每一行特定列位置的數值

[0.44950945 0.57611688 0.5092701 ]

6計算softmax值 

    由于此處correct_probs取出的輸出是對應真實類别位置的值,值越大 計算-np.log(correct_probs)結果越小,代表輸出的類别正确

      correct_probs = -np.log(correct_probs)

   [0.7995984  0.55144471 0.67477675]

7 計算平均損失

      data_loss = np.sum(correct_probs) / num_examples

      0.67

二、使用onehot編碼

def data_loss_softmax_onehot(scores, labels):
    num_examples = scores.shape[0]
    exp_scores = np.exp(scores)
    #print(exp_scores)
    exp_scores_sum = np.sum(exp_scores, axis=1)
    #print(exp_scores_sum)
    correct_probs = exp_scores[:] / exp_scores_sum
    #print(correct_probs)
    correct_probs2 = -labels*np.log(correct_probs)
    #print(correct_probs2)
    data_loss = np.sum(correct_probs2) / num_examples

    return data_loss


data=np.array([[0.6,0.2,0.01],[0,0,1],[0.02,0.9,0.3]])
# print(data)
labels=np.array([[1,0,0],[0,0,1],[0,1,0]])

print(data_loss_softmax_onehot(data, labels))

輸出
--exp_scores 
[[1.8221188  1.22140276 1.01005017]
 [1.         1.         2.71828183]
 [1.02020134 2.45960311 1.34985881]]

--exp_scores_sum 
[4.05357173 4.71828183 4.82966326]

--correct_probs
[[0.44950945 0.258866   0.2091347 ]
 [0.24669602 0.21194156 0.56283051]
 [0.25167961 0.52129211 0.27949336]]

--correct_probs2 
[[ 0.7995984  -0.         -0.        ]
 [-0.         -0.          0.57477675]
 [-0.          0.65144471 -0.        ]]
--最後整個矩陣求和取平均
0.6752732868378
           

代碼不同的地方是

 correct_probs = exp_scores[:] / exp_scores_sum

 correct_probs = -labels*np.log(correct_probs)

此處使用的是數組*數組  

[1,0,0]*[0.44950945 0.258866   0.2091347 ]=[0.7995984  -0.         -0.        ]

繼續閱讀