我正在尝试对标签可能非常稀疏的数据进行分段。因此,我只想计算至少有一个非零值的列中的梯度。
我已经尝试了一些方法,其中我应用了一个额外的输入,该输入是这些非零列的掩码,但鉴于所有必要的信息都已经包含在y_true
中,一种只查看y_true
来查找掩码的方法肯定是可取的。
如果我使用 numpy 实现它,它可能看起来像这样:
def loss(y_true, y_pred):
indices = np.where(np.sum(y_true, axis=1) > 0)
return binary_crossentropy(y_true[indices], y_pred[indices])
在此示例中,y_true
和y_pred
是矢量化 2D 图像。
这如何"翻译"为可微的Keras损失函数?
通过tf
和keras.backend
使用兼容tf
的操作:
import tensorflow as tf
import keras.backend as K
from keras.losses import binary_crossentropy
def custom_loss(y_true, y_pred):
indices = K.squeeze(tf.where(K.sum(y_true, axis=1) > 0))
y_true_sparse = K.cast(K.gather(y_true, indices), dtype='float32')
y_pred_sparse = K.cast(K.gather(y_pred, indices), dtype='float32')
return binary_crossentropy(y_true_sparse, y_pred_sparse) # returns a tensor
我不确定您问题的确切维度规格,但损失必须评估为单个值 - 上面没有,因为您正在传递多维预测和标签。要减少暗淡,请将上面的回程包裹起来,例如K.mean
.例:
y_true = np.random.randint(0,2,(10,2))
y_pred = np.abs(np.random.randn(10,2))
y_pred /= np.max(y_pred) # scale between 0 and 1
print(K.get_value(custom_loss(y_true, y_pred))) # get_value evaluates returned tensor
print(K.get_value(K.mean(custom_loss(y_true, y_pred))
>> [1.1489482 1.2705883 0.76229745 5.101402 3.1309896] # sparse; 5 / 10 results
>> 2.28284 # single value, as required
(最后,请注意,这种稀疏性将通过从总标签/pred 计数中排除全零列来偏向损失;如果不需要,您可以通过K.sum
和K.shape
或K.size
进行平均(