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