Keras/TensorFlow 中的损失函数
Loss function in Keras/TensorFlow
我的目的是实现自定义损失函数,以在 Keras 中使用 TensorFlow 作为后端来训练模型。
损失函数
W and H represent, respectively, the width and height of the softmax
layer’s output, and N is the batch size. The variable p is the
probability predicted by the FCN for the correct class.
这个损失函数来自这个paper.
在此实现中,N is 4, W is 200 and H is 400
。
最后一层的输出形状是(None, 400, 200, 2)
。单个标签的形状是 (400, 200, 2)
,其中每个通道代表 class.
到目前为止,
Numpy 实现:
尽管这在这种情况下没有用,但这就是我想作为损失函数实现的。
def loss_using_np(y_true, y_pred):
'''
Assuming, `y_true` and `y_pred` shape is (400, 200, 2).
This might change to (None, 400, 200, 2) while training in batch?
'''
dx = 0.0000000000000001 # Very small value to avoid -infinity while taking log
y_pred = y_pred + dx
class_one_pred = y_pred[:, :, 0]
class_two_pred = y_pred[:, :, 1]
class_one_mask = y_true[:, :, 0] == 1.0
class_two_mask = y_true[:, :, 1] == 1.0
class_one_correct_prob_sum = np.sum(np.log(class_one_pred[class_one_mask]))
class_two_correct_prob_sum = np.sum(np.log(class_two_pred[class_two_mask]))
N = 4
H = 400
W = 200
return -1 * ((class_one_correct_prob_sum + class_two_correct_prob_sum) / ( N * H * W))
以上实现给出了预期的输出;可惜不能用
y_true = np.random.randint(2, size=(400, 200, 2))
y_pred = np.random.random((400, 200, 2))
loss_using_np(y_true, y_pred)
尝试 01 失败
import tensorflow as tf # not a good practice to not use keras.backend?
def loss_function(y_true, y_pred):
# Not a working solution as it raises
# ResourceExhaustedError: OOM when allocating tensor with shape[311146,3,400,2] BUT WHY?
N = 4 # batch size
W = 200
H = 400
dx = 0.0000000000000001
y_pred = tf.add(y_pred, dx)
class_one_gt = y_true[:,:,:,0]
class_one_mask = tf.where(tf.equal(class_one_gt, 1.0))
# Bad to use `tf.gather`. Issues warning,
#`Converting sparse IndexedSlices to a dense Tensor of unknown shape.`
class_one_prob_sum = keras.backend.sum(keras.backend.log(tf.gather(y_pred[:,:,:,0], class_one_mask)))
class_two_gt = y_true[:,:,:,1]
class_two_mask = tf.where(tf.equal(class_two_gt, 1.0))
class_two_prob_sum = keras.backend.sum(keras.backend.log(tf.gather(y_pred[:,:,1], class_two_mask)))
print("This will be printed only once; won't be printed everytime loss is callculated. How to log?")
return -1 * ((class_one_prob_sum + class_two_prob_sum)/ (N * W * H))
尝试 02 失败?
def loss_function(y_true, y_pred):
N = 4
H = 400
W = 200
dx = tf.constant(0.0000000000000001, dtype=tf.float32)
correct_probs = tf.boolean_mask(y_pred, tf.equal(y_true, 1.0))
correct_probs = tf.add(correct_probs, dx)
return (-1 * keras.backend.sum(keras.backend.log(correct_probs))) /(N * H * W)
对于此 #02 方法,我收到警告,
UserWarning: Converting sparse IndexedSlices to a dense Tensor of unknown shape. This may consume a large amount of memory.
"Converting sparse IndexedSlices to a dense Tensor of unknown shape. "
问题
你能告诉我如何在没有任何警告的情况下实现这个损失函数吗?我不确定 #02 是正确的实现。我正在寻找优化的解决方案。非常感谢任何帮助或指点。
我试图使用 print
语句了解 loss_function()
内部发生的事情,但是,当我 compile
模型时,它们被打印了一次。有什么办法可以记录这个吗?
As mentioned by @dennis-ec, one can use tf.Print()
for
debugging.
旁注
我将 Keras 2.1.4
与 TensorFlow 1.4.0-rc1
和 Python 3.5.2
一起使用。
对我来说,作者似乎在使用普通的二元交叉熵损失来进行多标签 class化。他们也这样命名,但与您在 Keras 中实现它的方式相比,他们的定义有点奇怪。
基本上,您可以使用 binary_crossentropy
作为损失函数,并将标签作为形状数组 (400, 200, 1)
提供,其中 0 表示第一个 class,1 表示第二个 class。然后,您的网络的输出将具有相同的形状,每个输出节点都有 sigmoid
个激活函数。这就是 Keras 中通常实现语义分割模型的方式。有关示例,请参阅 this repo:
# final layer, sigmoid activations
conv10 = Conv2D(1, 1, activation = 'sigmoid')(conv9)
model = Model(input = inputs, output = conv10)
# binary_crossentropy loss for multi-label classification
model.compile(optimizer = Adam(lr = 1e-4), loss = 'binary_crossentropy', metrics = ['accuracy'])
这应该给出与论文中定义的实现完全相同的结果(他们可能没有使用 Keras)。
我的目的是实现自定义损失函数,以在 Keras 中使用 TensorFlow 作为后端来训练模型。
损失函数
W and H represent, respectively, the width and height of the softmax layer’s output, and N is the batch size. The variable p is the probability predicted by the FCN for the correct class.
这个损失函数来自这个paper.
在此实现中,N is 4, W is 200 and H is 400
。
最后一层的输出形状是(None, 400, 200, 2)
。单个标签的形状是 (400, 200, 2)
,其中每个通道代表 class.
到目前为止,
Numpy 实现:
尽管这在这种情况下没有用,但这就是我想作为损失函数实现的。
def loss_using_np(y_true, y_pred):
'''
Assuming, `y_true` and `y_pred` shape is (400, 200, 2).
This might change to (None, 400, 200, 2) while training in batch?
'''
dx = 0.0000000000000001 # Very small value to avoid -infinity while taking log
y_pred = y_pred + dx
class_one_pred = y_pred[:, :, 0]
class_two_pred = y_pred[:, :, 1]
class_one_mask = y_true[:, :, 0] == 1.0
class_two_mask = y_true[:, :, 1] == 1.0
class_one_correct_prob_sum = np.sum(np.log(class_one_pred[class_one_mask]))
class_two_correct_prob_sum = np.sum(np.log(class_two_pred[class_two_mask]))
N = 4
H = 400
W = 200
return -1 * ((class_one_correct_prob_sum + class_two_correct_prob_sum) / ( N * H * W))
以上实现给出了预期的输出;可惜不能用
y_true = np.random.randint(2, size=(400, 200, 2))
y_pred = np.random.random((400, 200, 2))
loss_using_np(y_true, y_pred)
尝试 01 失败
import tensorflow as tf # not a good practice to not use keras.backend?
def loss_function(y_true, y_pred):
# Not a working solution as it raises
# ResourceExhaustedError: OOM when allocating tensor with shape[311146,3,400,2] BUT WHY?
N = 4 # batch size
W = 200
H = 400
dx = 0.0000000000000001
y_pred = tf.add(y_pred, dx)
class_one_gt = y_true[:,:,:,0]
class_one_mask = tf.where(tf.equal(class_one_gt, 1.0))
# Bad to use `tf.gather`. Issues warning,
#`Converting sparse IndexedSlices to a dense Tensor of unknown shape.`
class_one_prob_sum = keras.backend.sum(keras.backend.log(tf.gather(y_pred[:,:,:,0], class_one_mask)))
class_two_gt = y_true[:,:,:,1]
class_two_mask = tf.where(tf.equal(class_two_gt, 1.0))
class_two_prob_sum = keras.backend.sum(keras.backend.log(tf.gather(y_pred[:,:,1], class_two_mask)))
print("This will be printed only once; won't be printed everytime loss is callculated. How to log?")
return -1 * ((class_one_prob_sum + class_two_prob_sum)/ (N * W * H))
尝试 02 失败?
def loss_function(y_true, y_pred):
N = 4
H = 400
W = 200
dx = tf.constant(0.0000000000000001, dtype=tf.float32)
correct_probs = tf.boolean_mask(y_pred, tf.equal(y_true, 1.0))
correct_probs = tf.add(correct_probs, dx)
return (-1 * keras.backend.sum(keras.backend.log(correct_probs))) /(N * H * W)
对于此 #02 方法,我收到警告,
UserWarning: Converting sparse IndexedSlices to a dense Tensor of unknown shape. This may consume a large amount of memory.
"Converting sparse IndexedSlices to a dense Tensor of unknown shape. "
问题
你能告诉我如何在没有任何警告的情况下实现这个损失函数吗?我不确定 #02 是正确的实现。我正在寻找优化的解决方案。非常感谢任何帮助或指点。
我试图使用
print
语句了解loss_function()
内部发生的事情,但是,当我compile
模型时,它们被打印了一次。有什么办法可以记录这个吗?
As mentioned by @dennis-ec, one can use
tf.Print()
for debugging.
旁注
我将 Keras 2.1.4
与 TensorFlow 1.4.0-rc1
和 Python 3.5.2
一起使用。
对我来说,作者似乎在使用普通的二元交叉熵损失来进行多标签 class化。他们也这样命名,但与您在 Keras 中实现它的方式相比,他们的定义有点奇怪。
基本上,您可以使用 binary_crossentropy
作为损失函数,并将标签作为形状数组 (400, 200, 1)
提供,其中 0 表示第一个 class,1 表示第二个 class。然后,您的网络的输出将具有相同的形状,每个输出节点都有 sigmoid
个激活函数。这就是 Keras 中通常实现语义分割模型的方式。有关示例,请参阅 this repo:
# final layer, sigmoid activations
conv10 = Conv2D(1, 1, activation = 'sigmoid')(conv9)
model = Model(input = inputs, output = conv10)
# binary_crossentropy loss for multi-label classification
model.compile(optimizer = Adam(lr = 1e-4), loss = 'binary_crossentropy', metrics = ['accuracy'])
这应该给出与论文中定义的实现完全相同的结果(他们可能没有使用 Keras)。