softmaxwithloss入門及88.3365解決之道

softmax with loss:
softmax從名字上看就是軟最大,其做法其實很簡單:

前提:最後輸出向量長度爲N,與要區分的類別個數一致


1 第一步,取向量的最大值,將每個值減去最大值,這樣就會將所有的數都變成非正數

2 求softmax:


3 經過第二步就會將向量變成全部小於1,大於0,累加爲1的向量,這樣就比較符合我們輸出每個類別的概率的判斷:在那個類別下的值最大,就判別爲哪一類

4 有了類別輸出概率,在訓練的時候還需要求loss,根據loss去更新梯度,優化參數,類別向量長度也爲N,求loss的公式:
loss=−∑kyklog(pk)
5 在實際計算的時候,比第四步要簡單的多,直接取對應類別下的概率輸出,取負對數,就得到了loss,即只管對應類別下的概率,將其進行優化,因爲概率和爲1,對應類別下的概率值變大,其他值自然變小:
loss -= log(std::max(prob_data[i * dim + label_value * inner_num_ + j],
                           Dtype(FLT_MIN)));

這樣取prob_data的值是因爲在loss的公式中,只需要關注k=y^(i)的那一類即可
dim:批大小個數
label_value:標籤
inner_num_:標籤個數

FLT_MIN的值:1.17549435E-38F
這個值的自然對數是:-87.3365,取負號變成87.3365
這個值是在訓練的時候經常會出現的一個值,出現這個值是因爲,求得的值比系統能夠表示的float最小值還小,一般就是0了,即求得的概率值爲0,

而前面已經說過了。經過softmax後,值都在0-1之間,觀察以e爲底的指數函數的曲線的話,你會發現,當取值趨向於無窮小時,其值才趨近於0:


由此可以判斷是前面的計算出現了float溢出導致出現inf,nan等值
因此問題就出現在前面的features值溢出,即超過float能夠表示的範圍成爲inf,inf在和其他數的運算中會將其他數也變成inf,最後在取inf和FLT_MIN較大值後做log運算後就變成了傳說中的87.3365

softmax輸入的feature由兩部分計算得到:一部分是上一層的輸入數據,另部分是各層權重參數,針對性的可以嘗試下面的方法進行解決:

1 學習率太大,嘗試降低學習率

2  增大批處理試試
3 有時未加歸一化時,也會導致loss爲這個值,嘗試着在最後面的fc層添加批處理層試試
4 數據標籤未從0開始,將數據標籤改成從0開始,並將SoftmaxWithLoss層的前一層的fc層的輸出個數改成類別個數,如果類別個數不對,也有可能出現這個問題
5 偏置初始化值太大,最好初始化爲0,或者是權重初始化值太大,嘗試降低權重初始化方差

6 在solver 中加clip_gradients設置,也許能夠解決這個問題

7 還有一個可能的原因就是:當你的批大小不大,而圖像中混有一些灰度圖,注意,雖然有些圖是3通道,但是各個通過值相等,也是灰度圖,在這種情況下,有些網絡結構就會出現這個值,這個值的出現與批大小,網絡結構,灰度圖,這個三都有關係,如果是這種情況,將灰度圖進行排除


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章