TensorFlow SparseCategoricalCrossentropy 如何工作?
How does TensorFlow SparseCategoricalCrossentropy work?
我试图理解 TensorFlow 中的这个损失函数,但我不明白。它是 SparseCategoricalCrossentropy。所有其他损失函数都需要相同形状的输出和标签,这个特定的损失函数不需要。
源代码:
import tensorflow as tf;
scce = tf.keras.losses.SparseCategoricalCrossentropy();
Loss = scce(
tf.constant([ 1, 1, 1, 2 ], tf.float32),
tf.constant([[1,2],[3,4],[5,6],[7,8]], tf.float32)
);
print("Loss:", Loss.numpy());
错误是:
InvalidArgumentError: Received a label value of 2 which is outside the valid range of [0, 2).
Label values: 1 1 1 2 [Op:SparseSoftmaxCrossEntropyWithLogits]
如何为损失函数 SparseCategoricalCrossentropy 提供合适的参数?
SparseCategoricalCrossentropy 和 CategoricalCrossentropy 都计算分类交叉熵。唯一的区别在于 targets/labels 应该如何编码。
使用 SparseCategoricalCrossentropy 时,目标由类别索引(从 0 开始)表示。您的输出形状为 4x2,这意味着您有两个类别。因此,目标应该是一个 4 维向量,其中的条目要么是 0,要么是 1。例如:
scce = tf.keras.losses.SparseCategoricalCrossentropy();
Loss = scce(
tf.constant([ 0, 0, 0, 1 ], tf.float32),
tf.constant([[1,2],[3,4],[5,6],[7,8]], tf.float32))
这与 CategoricalCrossentropy 形成对比,后者的标签应该是单热编码的:
cce = tf.keras.losses.CategoricalCrossentropy();
Loss = cce(
tf.constant([ [1,0] [1,0], [1, 0], [0, 1] ], tf.float32),
tf.constant([[1,2],[3,4],[5,6],[7,8]], tf.float32))
当你有很多类别时,SparseCategoricalCrossentropy 更有效。
我想补充一些可能令人困惑的内容。 SparseCategoricalCrossentropy
有两个非常重要的参数。第一个是from_logits; recall logits 是尚未通过 Softmax(或 Sigmoid)归一化的网络输出。第二个是reduction
。它通常设置为 'auto'
,这会正常计算分类交叉熵,即 label*log(pred)
的平均值。但是将值设置为 'none'
实际上会为您提供形状为 (batch_size)
的分类交叉熵 label*log(pred)
的每个元素。在此列表上计算 reduce_mean
将得到与 reduction='auto'
.
相同的结果
# Assuming TF2.x
import tensorflow as tf
model_predictions = tf.constant([[1,2], [3,4], [5,6], [7,8]], tf.float32)
labels_sparse = tf.constant([1, 0, 0, 1 ], tf.float32)
labels_dense = tf.constant([[1,0], [1,0], [1,0], [0,1]], tf.float32)
loss_obj_scc = tf.keras.losses.SparseCategoricalCrossentropy(
from_logits=True,
reduction='auto'
)
loss_from_scc = loss_obj_scc(
labels_sparse,
model_predictions,
)
loss_obj_cc = tf.keras.losses.CategoricalCrossentropy(
from_logits=True,
reduction='auto'
)
loss_from_cc = loss_obj_cc(
labels_dense,
model_predictions,
)
print(loss_from_scc, loss_from_cc)
>> (<tf.Tensor: shape=(), dtype=float32, numpy=0.8132617>,
<tf.Tensor: shape=(), dtype=float32, numpy=1.0632616>)
# With `reduction='none'`
loss_obj_scc_red = tf.keras.losses.SparseCategoricalCrossentropy(
from_logits=True,
reduction='none')
loss_from_scc_red = loss_obj_scc_red(
labels_sparse,
model_predictions,
)
print(loss_from_scc_red, tf.math.reduce_mean(loss_from_scc_red))
>> (<tf.Tensor: shape=(4,), dtype=float32, numpy=array([0.31326166, 1.3132616 ,
1.3132616 , 0.31326166], dtype=float32)>,
<tf.Tensor: shape=(), dtype=float32, numpy=0.8132617>)
我试图理解 TensorFlow 中的这个损失函数,但我不明白。它是 SparseCategoricalCrossentropy。所有其他损失函数都需要相同形状的输出和标签,这个特定的损失函数不需要。
源代码:
import tensorflow as tf;
scce = tf.keras.losses.SparseCategoricalCrossentropy();
Loss = scce(
tf.constant([ 1, 1, 1, 2 ], tf.float32),
tf.constant([[1,2],[3,4],[5,6],[7,8]], tf.float32)
);
print("Loss:", Loss.numpy());
错误是:
InvalidArgumentError: Received a label value of 2 which is outside the valid range of [0, 2).
Label values: 1 1 1 2 [Op:SparseSoftmaxCrossEntropyWithLogits]
如何为损失函数 SparseCategoricalCrossentropy 提供合适的参数?
SparseCategoricalCrossentropy 和 CategoricalCrossentropy 都计算分类交叉熵。唯一的区别在于 targets/labels 应该如何编码。
使用 SparseCategoricalCrossentropy 时,目标由类别索引(从 0 开始)表示。您的输出形状为 4x2,这意味着您有两个类别。因此,目标应该是一个 4 维向量,其中的条目要么是 0,要么是 1。例如:
scce = tf.keras.losses.SparseCategoricalCrossentropy();
Loss = scce(
tf.constant([ 0, 0, 0, 1 ], tf.float32),
tf.constant([[1,2],[3,4],[5,6],[7,8]], tf.float32))
这与 CategoricalCrossentropy 形成对比,后者的标签应该是单热编码的:
cce = tf.keras.losses.CategoricalCrossentropy();
Loss = cce(
tf.constant([ [1,0] [1,0], [1, 0], [0, 1] ], tf.float32),
tf.constant([[1,2],[3,4],[5,6],[7,8]], tf.float32))
当你有很多类别时,SparseCategoricalCrossentropy 更有效。
我想补充一些可能令人困惑的内容。 SparseCategoricalCrossentropy
有两个非常重要的参数。第一个是from_logits; recall logits 是尚未通过 Softmax(或 Sigmoid)归一化的网络输出。第二个是reduction
。它通常设置为 'auto'
,这会正常计算分类交叉熵,即 label*log(pred)
的平均值。但是将值设置为 'none'
实际上会为您提供形状为 (batch_size)
的分类交叉熵 label*log(pred)
的每个元素。在此列表上计算 reduce_mean
将得到与 reduction='auto'
.
# Assuming TF2.x
import tensorflow as tf
model_predictions = tf.constant([[1,2], [3,4], [5,6], [7,8]], tf.float32)
labels_sparse = tf.constant([1, 0, 0, 1 ], tf.float32)
labels_dense = tf.constant([[1,0], [1,0], [1,0], [0,1]], tf.float32)
loss_obj_scc = tf.keras.losses.SparseCategoricalCrossentropy(
from_logits=True,
reduction='auto'
)
loss_from_scc = loss_obj_scc(
labels_sparse,
model_predictions,
)
loss_obj_cc = tf.keras.losses.CategoricalCrossentropy(
from_logits=True,
reduction='auto'
)
loss_from_cc = loss_obj_cc(
labels_dense,
model_predictions,
)
print(loss_from_scc, loss_from_cc)
>> (<tf.Tensor: shape=(), dtype=float32, numpy=0.8132617>,
<tf.Tensor: shape=(), dtype=float32, numpy=1.0632616>)
# With `reduction='none'`
loss_obj_scc_red = tf.keras.losses.SparseCategoricalCrossentropy(
from_logits=True,
reduction='none')
loss_from_scc_red = loss_obj_scc_red(
labels_sparse,
model_predictions,
)
print(loss_from_scc_red, tf.math.reduce_mean(loss_from_scc_red))
>> (<tf.Tensor: shape=(4,), dtype=float32, numpy=array([0.31326166, 1.3132616 ,
1.3132616 , 0.31326166], dtype=float32)>,
<tf.Tensor: shape=(), dtype=float32, numpy=0.8132617>)