Как применить бинарную кросс-энтропию поэлементно, а затем просуммировать все эти потери в Keras?

Я хочу написать функцию с двумя аргументами, A и B, тензорами одинаковой формы (например, 13x13 или другой формы), и которая возвращает число, которое представляет собой сумму всех потерь при применении двоичной кросс-энтропии покомпонентно. . Итак, для A[i, j] и B[i, j] мы находим двоичную потерю кросс-энтропии, а затем суммируем по всем i и j. Как это реализовать в Keras и Tensorflow?


person Alem    schedule 28.09.2018    source источник


Ответы (2)


Вы можете легко определить эту функцию с помощью функций внутреннего интерфейса (или напрямую используйте их эквиваленты в Tensorflow):

def func(A, B):
    return K.sum(K.binary_crossentropy(A,B)) 

Обратите внимание, что K.binary_crossentropy() предполагает, что заданные входные значения являются вероятностями; если это не так, то передайте from_logit=True в качестве другого аргумента.

Кроме того, если вы хотите использовать эту функцию в слое Lambda, вам необходимо измените его так, чтобы он принимал на вход список тензоров:

def func(inp):
    return K.sum(K.binary_crossentropy(inp[0], inp[1]), [1,2]) # take the sum for each sample independently

# ...
out = Lambda(func)([A, B])

Как видите, [1,2] был передан K.sum() в качестве аргумента axis, чтобы получить сумму по всем элементам одной выборки (а не по всей партии).

person today    schedule 28.09.2018

Решение, предложенное в этом ответе, на самом деле может быть не тем, что вы (читатель) ищете.

Если A и B равны NxM, где M > 1, то binary_crossentropy(A, B) не будет вычислять двоичную кросс-энтропию поэлементно, но binary_crossentropy(A, B) возвращает массив формы Nx1, где binary_crossentropy(A, B)[i] соответствует средней двоичной кросс-энтропии между A[i] и B[i] (т.е. вычисляет двоичную кросс-энтропию между A[i][j] и B[i][j] для всех j, затем вычисляет среднее значение M двоичных кросс-энтропий).

Если вы хотите вычислить двоичную кросс-энтропию между элементами A(i, j) и B(i, j) для всех i и j, тогда вы можете сначала изменить форму A и B, чтобы они имели форму (N*M)x1.

import numpy as np
import tensorflow as tf

a = np.random.rand(4, 2).reshape((-1, 1))
b = np.random.rand(4, 2).reshape((-1, 1))
print("ce between a[i, j] and b[i, j]) =", tf.losses.binary_crossentropy(a, b))
print("average cross-entropy =", np.mean(tf.losses.binary_crossentropy(a, b)))

Однако, если вы хотите вычислить двоичную кросс-энтропию между A и B поэлементно и взять среднее значение всех двоичных кросс-энтропий, вам не нужно изменять форму A и B. Итак, если A и B являются NxM массивами, то binary_crossentropy(A, B) создает массив Nx1, где каждый элемент соответствует средней двоичной кросс-энтропии между строкой i из A и строкой i из B (для i=1, ..., N). Наконец, чтобы взять среднее значение всех бинарных кросс-энтропий, нам также нужно взять среднее значение binary_crossentropy(A, B), то есть tf.reduce_mean(binary_crossentropy(A, B)).

person nbro    schedule 08.01.2020