|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"""Tests for base_loss.py.""" |
|
|
|
import numpy as np |
|
import tensorflow as tf |
|
|
|
from deeplab2.model.loss import base_loss as loss |
|
|
|
|
|
class BaseLossTest(tf.test.TestCase): |
|
|
|
def test_general_loss(self): |
|
y_true = { |
|
'gt': tf.ones([2, 33, 33]) * 2, |
|
'weight': tf.ones([2, 33, 33]) |
|
} |
|
y_pred = {'pred': tf.zeros([2, 33, 33])} |
|
|
|
with self.subTest('L1'): |
|
loss_layer = loss.TopKGeneralLoss( |
|
loss.mean_absolute_error, |
|
'gt', |
|
'pred', |
|
'weight') |
|
expected_loss = tf.ones([2]) * 2 |
|
with self.subTest('MSE'): |
|
loss_layer = loss.TopKGeneralLoss( |
|
loss.mean_squared_error, |
|
'gt', |
|
'pred', |
|
'weight') |
|
expected_loss = tf.ones([2]) * 4 |
|
loss_result = loss_layer(y_true, y_pred) |
|
np.testing.assert_almost_equal( |
|
loss_result.numpy(), expected_loss.numpy(), decimal=5) |
|
|
|
def test_general_loss_weights(self): |
|
weights = np.zeros((2, 33, 33)) |
|
weights[:, 17:29, 15:23] = 1 |
|
|
|
gt = np.ones([2, 33, 33]) * 1.5 |
|
gt[:, 17:29, 15:23] = 2 |
|
|
|
y_true = { |
|
'gt': tf.convert_to_tensor(gt, dtype=tf.float32), |
|
'weight': tf.convert_to_tensor(weights, dtype=tf.float32) |
|
} |
|
y_pred = {'pred': tf.zeros([2, 33, 33])} |
|
loss_layer = loss.TopKGeneralLoss( |
|
loss.mean_absolute_error, |
|
'gt', |
|
'pred', |
|
'weight') |
|
|
|
expected_loss = tf.ones([2]) * 2 |
|
loss_result = loss_layer(y_true, y_pred) |
|
|
|
np.testing.assert_almost_equal( |
|
loss_result.numpy(), expected_loss.numpy(), decimal=5) |
|
|
|
def test_topk_ce_loss_ignore(self): |
|
num_classes = 19 |
|
ignore_label = 255 |
|
loss_layer = loss.TopKCrossEntropyLoss( |
|
gt_key='gt', |
|
pred_key='pred', |
|
weight_key='weight', |
|
num_classes=num_classes, |
|
ignore_label=ignore_label) |
|
|
|
gt_tensor = np.ones(shape=[2, 33, 33], dtype=np.int32) * ignore_label |
|
gt_tensor[:, 17:29, 15:23] = 1 |
|
logits = tf.random.uniform(shape=[2, 33, 33, num_classes]) |
|
|
|
y_true = { |
|
'gt': tf.convert_to_tensor(gt_tensor), |
|
'weight': tf.ones([2, 33, 33]) |
|
} |
|
y_pred = {'pred': logits} |
|
|
|
expected_result = tf.nn.softmax_cross_entropy_with_logits( |
|
tf.one_hot(np.squeeze(gt_tensor[:, 17:29, 15:23]), num_classes), |
|
logits[:, 17:29, 15:23, :]) |
|
expected_result = tf.reduce_mean(expected_result, axis=[1, 2]) |
|
|
|
per_sample_loss = loss_layer(y_true, y_pred) |
|
|
|
np.testing.assert_almost_equal( |
|
per_sample_loss.numpy(), expected_result.numpy(), decimal=5) |
|
|
|
def test_topk_ce_loss_global_weight(self): |
|
num_classes = 19 |
|
weight = 3.145 |
|
loss_layer = loss.TopKCrossEntropyLoss( |
|
gt_key='gt', |
|
pred_key='pred', |
|
weight_key='weight', |
|
num_classes=num_classes, |
|
ignore_label=255) |
|
logits = tf.random.uniform(shape=[2, 33, 33, num_classes]) |
|
|
|
y_true = { |
|
'gt': tf.ones([2, 33, 33], tf.int32), |
|
'weight': tf.ones([2, 33, 33]) |
|
} |
|
y_pred = {'pred': logits} |
|
|
|
expected_result = tf.nn.softmax_cross_entropy_with_logits( |
|
tf.one_hot(y_true['gt'], num_classes), logits) |
|
expected_result = tf.reduce_mean(expected_result, axis=[1, 2]) |
|
expected_result *= weight |
|
|
|
per_sample_loss = loss_layer(y_true, y_pred, weight) |
|
|
|
np.testing.assert_almost_equal( |
|
per_sample_loss.numpy(), expected_result.numpy(), decimal=5) |
|
|
|
def test_topk_ce_loss_topk(self): |
|
num_classes = 19 |
|
top_k = 0.5 |
|
loss_layer = loss.TopKCrossEntropyLoss( |
|
gt_key='gt', |
|
pred_key='pred', |
|
weight_key='weight', |
|
num_classes=num_classes, |
|
top_k_percent_pixels=top_k, |
|
ignore_label=255) |
|
|
|
logits = tf.random.uniform(shape=[2, 33, 33, num_classes]) |
|
y_true = { |
|
'gt': tf.ones([2, 33, 33], tf.int32), |
|
'weight': tf.ones([2, 33, 33]) |
|
} |
|
y_pred = {'pred': logits} |
|
|
|
expected_result = tf.nn.softmax_cross_entropy_with_logits( |
|
tf.one_hot(y_true['gt'], num_classes), logits) |
|
expected_result, _ = tf.math.top_k( |
|
tf.reshape(expected_result, shape=[2, -1]), |
|
tf.cast((top_k * tf.size(y_true['gt'], tf.float32) / 2), tf.int32)) |
|
expected_result = tf.reduce_mean(expected_result, axis=[1]) |
|
|
|
per_sample_loss = loss_layer(y_true, y_pred) |
|
|
|
np.testing.assert_almost_equal( |
|
per_sample_loss.numpy(), expected_result.numpy(), decimal=5) |
|
|
|
def test_is_one_hot(self): |
|
num_classes = 19 |
|
gt_list = [ |
|
tf.ones([2, 33, 33], tf.int32), |
|
tf.ones([2, 33], tf.int32), |
|
tf.one_hot(tf.ones([2, 33, 33], tf.int32), num_classes), |
|
tf.one_hot(tf.ones([2, 33], tf.int32), num_classes), |
|
] |
|
pred_list = [ |
|
tf.random.uniform(shape=[2, 33, 33, num_classes]), |
|
tf.random.uniform(shape=[2, 33, num_classes]), |
|
tf.random.uniform(shape=[2, 33, 33, num_classes]), |
|
tf.random.uniform(shape=[2, 33, num_classes]), |
|
] |
|
expected_result_list = [False, False, True, True] |
|
output_list = [] |
|
for gt, pred in zip(gt_list, pred_list): |
|
output_list.append(loss.is_one_hot(gt, pred)) |
|
np.testing.assert_equal(output_list, expected_result_list) |
|
|
|
def test_focal_ce_loss_integer_or_one_hot(self): |
|
num_classes = 19 |
|
gamma = 0.5 |
|
alpha = 0.75 |
|
loss_layer = loss.FocalCrossEntropyLoss( |
|
gt_key='gt', |
|
pred_key='pred', |
|
weight_key='weight', |
|
num_classes=num_classes, |
|
focal_loss_alpha=alpha, |
|
focal_loss_gamma=gamma, |
|
ignore_label=255) |
|
|
|
logits = tf.random.uniform(shape=[2, 33 * 33, num_classes]) |
|
gt = tf.ones([2, 33 * 33], tf.int32) |
|
use_one_hot_encode_list = [False, True] |
|
for use_one_hot_encode in use_one_hot_encode_list: |
|
if use_one_hot_encode: |
|
gt = tf.one_hot(gt, num_classes) |
|
y_true = {'gt': gt} |
|
y_pred = {'pred': logits, |
|
'weight': tf.ones([2, 33 * 33])} |
|
predictions = tf.nn.softmax(logits, axis=-1) |
|
if use_one_hot_encode: |
|
pt = tf.reduce_sum(predictions * gt, axis=-1) |
|
expected_result = tf.nn.softmax_cross_entropy_with_logits(gt, logits) |
|
else: |
|
pt = tf.reduce_sum(predictions * tf.one_hot(gt, num_classes), axis=-1) |
|
expected_result = tf.nn.softmax_cross_entropy_with_logits( |
|
tf.one_hot(gt, num_classes), logits) |
|
expected_result = tf.multiply(tf.pow(1.0 - pt, gamma), expected_result) |
|
expected_result = tf.reshape(expected_result, shape=[2, -1]) |
|
|
|
|
|
expected_result = tf.reduce_mean(expected_result, axis=[1]) * alpha |
|
per_sample_loss = loss_layer(y_true, y_pred) |
|
|
|
np.testing.assert_almost_equal( |
|
per_sample_loss.numpy(), expected_result.numpy(), decimal=5) |
|
|
|
def test_mask_dice_loss(self): |
|
gt = [ |
|
[ |
|
[1., 1., 1.], |
|
[0., 0., 0.], |
|
[0., 0., 0.], |
|
], |
|
[ |
|
[0., 0., 0.], |
|
[1., 1., 1.], |
|
[1., 1., 1.], |
|
], |
|
] |
|
gt = tf.constant(gt, dtype=tf.float32) |
|
gt = tf.expand_dims(gt, -1) |
|
gt = tf.transpose(gt, perm=[3, 1, 2, 0]) |
|
|
|
y_true = {'gt': gt} |
|
|
|
pred = [ |
|
[ |
|
[1., 1., 0.], |
|
[1., 1., 0.], |
|
[1., 1., 0.], |
|
], |
|
[ |
|
[0., 0., 1.], |
|
[0., 0., 1.], |
|
[0., 0., 1.], |
|
], |
|
] |
|
|
|
pred = tf.constant(pred, dtype=tf.float32) * 100. |
|
pred = tf.expand_dims(pred, -1) |
|
pred = tf.transpose(pred, perm=[3, 1, 2, 0]) |
|
y_pred = { |
|
'pred': pred, |
|
'weight': tf.ones([1]) * 0.5 |
|
} |
|
|
|
loss_layer = loss.MaskDiceLoss( |
|
gt_key='gt', |
|
pred_key='pred', |
|
weight_key='weight', |
|
prediction_activation='softmax') |
|
dice_loss = loss_layer(y_true, y_pred) |
|
loss_result = dice_loss.numpy() |
|
|
|
|
|
|
|
|
|
|
|
expected_result = np.array([0.5]) |
|
np.testing.assert_almost_equal(loss_result, expected_result) |
|
|
|
|
|
if __name__ == '__main__': |
|
tf.test.main() |
|
|