如何按元素应用二元交叉熵,然后在 Keras 中对所有这些损失求和?
How do I apply the binary cross-entropy element-wise and then sum all these losses in Keras?
我想写一个带有两个参数的函数,A
和 B
,相同形状的张量(例如,13x13
,或其他形状),并且returns 一个数字,表示按分量应用二元交叉熵时所有损失的总和。因此,对于 A[i, j]
和 B[i, j]
,我们找到二元交叉熵损失,然后对所有 i
和 j
求和。如何在 Keras 和 Tensorflow 中实现?
您可以使用后端函数 sum
and binary_crossentropy
轻松定义此函数(或直接在 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]
已作为其 axis
参数传递给 K.sum()
,以对单个样本的所有元素求和(而不是对整个元素求和)批次)。
中建议的解决方案实际上可能不是您 (reader) 正在寻找的。
如果 A
和 B
是 NxM
,其中 M > 1
,那么 binary_crossentropy(A, B)
将不会按元素计算二进制交叉熵,但是binary_crossentropy(A, B)
returns 形状为 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
数组,其中每个元素对应于行之间的平均二进制交叉熵A
的 i
和 B
的 i
行(对于 i=1, ..., N
)。最后,取所有二元交叉熵的平均值,我们还需要取binary_crossentropy(A, B)
的平均值,即tf.reduce_mean(binary_crossentropy(A, B))
.
我想写一个带有两个参数的函数,A
和 B
,相同形状的张量(例如,13x13
,或其他形状),并且returns 一个数字,表示按分量应用二元交叉熵时所有损失的总和。因此,对于 A[i, j]
和 B[i, j]
,我们找到二元交叉熵损失,然后对所有 i
和 j
求和。如何在 Keras 和 Tensorflow 中实现?
您可以使用后端函数 sum
and binary_crossentropy
轻松定义此函数(或直接在 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]
已作为其 axis
参数传递给 K.sum()
,以对单个样本的所有元素求和(而不是对整个元素求和)批次)。
如果 A
和 B
是 NxM
,其中 M > 1
,那么 binary_crossentropy(A, B)
将不会按元素计算二进制交叉熵,但是binary_crossentropy(A, B)
returns 形状为 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
数组,其中每个元素对应于行之间的平均二进制交叉熵A
的 i
和 B
的 i
行(对于 i=1, ..., N
)。最后,取所有二元交叉熵的平均值,我们还需要取binary_crossentropy(A, B)
的平均值,即tf.reduce_mean(binary_crossentropy(A, B))
.