1. 程式人生 > 程式設計 >Keras中的多分類損失函式用法categorical_crossentropy

Keras中的多分類損失函式用法categorical_crossentropy

from keras.utils.np_utils import to_categorical

注意:當使用categorical_crossentropy損失函式時,你的標籤應為多類模式,例如如果你有10個類別,每一個樣本的標籤應該是一個10維的向量,該向量在對應有值的索引位置為1其餘為0。

可以使用這個方法進行轉換:

from keras.utils.np_utils import to_categorical
categorical_labels = to_categorical(int_labels,num_classes=None)

以mnist資料集為例:

from keras.datasets import mnist

(X_train,y_train),(X_test,y_test) = mnist.load_data()
y_train = to_categorical(y_train,10)
y_test = to_categorical(y_test,10)

...
model.compile(loss='categorical_crossentropy',optimizer='adam')
model.fit(X_train,y_train,epochs=100,batch_size=1,verbose=2)

補充知識:Keras中損失函式binary_crossentropy和categorical_crossentropy產生不同結果的分析

問題

在使用keras做對心電訊號分類的專案中發現一個問題,這個問題起源於我的一個使用錯誤:

binary_crossentropy 二進位制交叉熵用於二分類問題中,categorical_crossentropy分類交叉熵適用於多分類問題中,我的心電分類是一個多分類問題,但是我起初使用了二進位制交叉熵,程式碼如下所示:

sgd = SGD(lr=0.003,decay=0,momentum=0.7,nesterov=False)
model.compile(loss='categorical_crossentropy',optimizer='sgd',metrics=['accuracy'])
model.fit(X_train,Y_train,validation_data=(X_test,Y_test),batch_size=16,epochs=20)
score = model.evaluate(X_test,Y_test,batch_size=16)

注意:我的CNN網路模型在最後輸入層正確使用了應該用於多分類問題的softmax啟用函式

後來我在另一個殘差網路模型中對同類資料進行相同的分類問題中,正確使用了分類交叉熵,令人奇怪的是殘差模型的效果遠弱於普通卷積神經網路,這一點是不符合常理的,經過多次修改分析終於發現可能是損失函式的問題,因此我使用二進位制交叉熵在殘差網路中,終於取得了優於普通卷積神經網路的效果。

因此可以斷定問題就出在所使用的損失函式身上

原理

本人也只是個只會使用框架的調參俠,對於一些原理也是一知半解,經過了學習才大致明白,將一些原理記錄如下:

要搞明白分類熵和二進位制交叉熵先要從二者適用的啟用函式說起

啟用函式

sigmoid,softmax主要用於神經網路輸出層的輸出。

softmax函式

Keras中的多分類損失函式用法categorical_crossentropy

softmax可以看作是Sigmoid的一般情況,用於多分類問題。

Softmax函式將K維的實數向量壓縮(對映)成另一個K維的實數向量,其中向量中的每個元素取值都介於 (0,1) 之間。常用於多分類問題。

sigmoid函式

Keras中的多分類損失函式用法categorical_crossentropy

Sigmoid 將一個實數對映到 (0,1) 的區間,可以用來做二分類。Sigmoid 在特徵相差比較複雜或是相差不是特別大時效果比較好。Sigmoid不適合用在神經網路的中間層,因為對於深層網路,sigmoid 函式反向傳播時,很容易就會出現梯度消失的情況(在 sigmoid 接近飽和區時,變換太緩慢,導數趨於 0,這種情況會造成資訊丟失),從而無法完成深層網路的訓練。所以Sigmoid主要用於對神經網路輸出層的啟用。

分析

所以說多分類問題是要softmax啟用函式配合分類交叉熵函式使用,而二分類問題要使用sigmoid啟用函式配合二進位制交叉熵函式適用,但是如果在多分類問題中使用了二進位制交叉熵函式最後的模型分類效果會虛高,即比模型本身真實的分類效果好。

所以就會出現我遇到的情況,這裡引用了論壇一位大佬的樣例:

model.compile(loss='binary_crossentropy',optimizer='adam',metrics=['accuracy']) # WRONG way

model.fit(x_train,batch_size=batch_size,epochs=2,# only 2 epochs,for demonstration purposes
   verbose=1,validation_data=(x_test,y_test))

# Keras reported accuracy:
score = model.evaluate(x_test,y_test,verbose=0) 
score[1]
# 0.9975801164627075

# Actual accuracy calculated manually:
import numpy as np
y_pred = model.predict(x_test)
acc = sum([np.argmax(y_test[i])==np.argmax(y_pred[i]) for i in range(10000)])/10000
acc
# 0.98780000000000001

score[1]==acc
# False 

樣例中模型在評估中得到的準確度高於實際測算得到的準確度,網上給出的原因是Keras沒有定義一個準確的度量,但有幾個不同的,比如binary_accuracy和categorical_accuracy,當你使用binary_crossentropy時keras預設在評估過程中使用了binary_accuracy,但是針對你的分類要求,應當採用的是categorical_accuracy,所以就造成了這個問題(其中的具體原理我也沒去看原始碼詳細瞭解)

解決

所以問題最後的解決方法就是:

對於多分類問題,要麼採用

from keras.metrics import categorical_accuracy
model.compile(loss='binary_crossentropy',metrics=[categorical_accuracy])

要麼採用

model.compile(loss='categorical_crossentropy',
optimizer='adam',metrics=['accuracy'])

以上這篇Keras中的多分類損失函式用法categorical_crossentropy就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支援我們。