我已经使用 TF 两年了,在每个项目中,我都会弹出许多无意义的错误来进行屏蔽,这些错误通常没有帮助,并且不能表明实际问题是什么。或者更糟糕的是,结果是错误的,但没有错误。我总是使用虚拟数据在训练循环之外测试代码,这很好。但在训练中(调用 fit),我不明白 TensorFlow 到底期望什么。仅举一个例子,有经验的人可以告诉我为什么这段代码不适用于二进制交叉熵,结果是错误的并且模型不收敛,但在这种情况下没有错误:
class MaskedBXE(tf.keras.losses.Loss):
def __init__(self, **kwargs):
super().__init__(**kwargs)
def call(self, y_true, y_pred):
y_true = tf.squeeze(y_true)
mask = tf.where(y_true!=2)
y_true = tf.gather_nd(y_true, mask)
y_pred = tf.gather_nd(y_pred, mask)
loss = tf.keras.losses.binary_crossentropy(y_true, y_pred)
return tf.reduce_mean(loss)
虽然这可以正常工作:
class MaskedBXE(tf.keras.losses.Loss):
def __init__(self, **kwargs):
super().__init__(**kwargs)
def call(self, y_true, y_pred):
mask = tf.where(y_true!=2, True, False)
y_true = y_true[mask]
y_pred = y_pred[mask]
loss = tf.keras.losses.binary_crossentropy(y_true, y_pred)
return tf.reduce_mean(loss)
对于一个绝对的例子来说,情况恰恰相反。我无法使用掩码作为索引,如 y_pred[mask] 或 y_pred[mask[0]],或使用 tf.squeeze() 等。但使用 tf.gather_nd() 是有效的。我总是尝试所有我认为可能的组合,我只是不明白为什么如此简单的事情会如此困难和痛苦。Pytorch也是这样吗?如果您知道 Pytorch 没有类似的烦人细节,我很乐意切换。
编辑 1:它们在训练循环之外正常工作,或者更准确地说是图形模式。
y_pred = tf.random.uniform(shape=[10,], minval=0, maxval=1, dtype='float32')
y_true = tf.random.uniform(shape=[10,], minval=0, maxval=2, dtype='int32')
# first method
class MaskedBXE(tf.keras.losses.Loss):
def __init__(self, **kwargs):
super().__init__(**kwargs)
def call(self, y_true, y_pred):
y_true = tf.squeeze(y_true)
mask = tf.where(y_true!=2)
y_true = tf.gather_nd(y_true, mask)
y_pred = tf.gather_nd(y_pred, mask)
loss = tf.keras.losses.binary_crossentropy(y_true, y_pred)
return tf.reduce_mean(loss)
def get_config(self):
base_config = super().get_config()
return {**base_config}
# instantiate
mbxe = MaskedBXE()
print(f'first snippet: {mbxe(y_true, y_pred).numpy()}')
万千封印
相关分类