6

我有一個網絡可以產生一個4D輸出張量,其中空間維度(〜像素)中每個位置的值將被解釋爲該位置的類別概率。換句話說,輸出是(num_batches, height, width, num_classes)。我有相同大小的標籤,其中真實課程編碼爲一熱。我想用這個來計算categorical-crossentropy的損失。如何在Keras中實現逐點分類交叉熵損失?

問題1:K.softmax函數需要2D(num_batches, num_classes)

問題#2:我不知道從每個位置上的損失,應該如何結合。 reshape的張量是否正確(num_batches * height * width, num_classes),然後調用K.categorical_crossentropy?或者說,請致電K.categorical_crossentropy(num_batches, num_classes)高度*寬度時間和平均結果?

+0

你使用哪個後端? –

+0

@MarcinMożejko我使用TensorFlow - 既可以使用Keras後端api,也可以使用TF自己的功能,要麼就沒關係。謝謝! –

+0

我已經回答了您的問題:-) –

回答

2

只是將輸出平坦化爲尺寸爲(num_batches, height * width * num_classes)的2D張量。您可以使用Flatten圖層執行此操作。確保你的y平鋪方式相同(通常撥打y = y.reshape((num_batches, height * width * num_classes))就足夠了)。

對於第二個問題,在所有width*height預測上使用分類交叉熵基本上與爲每個width*height預測(按照分類交叉熵的定義)平均分類交叉熵相同。

+0

謝謝!雖然我很困惑(num_batches,height * width * num_classes)。是不是基本上計算交叉熵,就好像有num_batches樣本每個都有height * width * num_classes類?我很確定我希望每個點都被視爲一個單獨的樣本,是不是重新變形爲(num_batches * height * width,num_classes)?請讓我知道,如果這兩者在數學上是等價的。 –

+0

對不起,分類交叉熵本質上是數學上相同的。但是,將它與softmax一起使用將不會是數學上相同的,因爲輸出是正常化的,這是我的答案中的一個錯誤。我不認爲有可能改變模型中輸入中點的批量大小。最好的方法可能是制定一個解決方案並實現您自己的softmax激活函數,該函數可對每個「height * width」單元的輸出進行歸一化。 – oscfri

+0

謝謝!我仍然對如何將它翻譯成工作代碼感到困惑,你能否對此有所瞭解?我開始賞金:) –

2

找到this issue確認我的直覺。

總之:softmax將採取二維或三維輸入。如果他們是三維keras將呈現這樣的形狀(樣本,timedimension,numclasses)並將softmax應用於最後一個。出於一些奇怪的原因,它不適用於4D張量。

解決方案:重塑你的輸出像素的序列

reshaped_output = Reshape((height*width, num_classes))(output_tensor) 

然後申請您的SOFTMAX

new_output = Activation('softmax')(reshaped_output) 

,然後要麼你重塑你的目標張量爲2D或者你只是重塑那最後一層進(寬度,高度,num_classes)。

否則,如果我現在不在手機上,我會嘗試的是使用timedistributed(Activation('softmax'))。但是,不知道是否會工作......稍後會嘗試

我希望這有助於:-)

2

你也沒有什麼reshape並定義你自己都softmaxloss。這裏是softmax施加到最後輸入的尺寸(如在tf後端):

def image_softmax(input): 
    label_dim = -1 
    d = K.exp(input - K.max(input, axis=label_dim, keepdims=True)) 
    return d/K.sum(d, axis=label_dim, keepdims=True) 

,並在這裏你有loss(沒有必要重塑任何東西):

__EPS = 1e-5 
def image_categorical_crossentropy(y_true, y_pred): 
    y_pred = K.clip(y_pred, __EPS, 1 - __EPS) 
    return -K.mean(y_true * K.log(y_pred) + (1 - y_true) * K.log(1 - y_pred)) 

沒有進一步的重塑需要。