From ca4197d87f98e02e11d948adcc6a1f6b0232fac7 Mon Sep 17 00:00:00 2001 From: fsx950223 Date: Wed, 4 Sep 2019 19:37:08 +0800 Subject: [PATCH 01/22] Add GIOU loss --- tensorflow_addons/losses/BUILD | 14 +++ tensorflow_addons/losses/__init__.py | 1 + tensorflow_addons/losses/giou_loss.py | 138 +++++++++++++++++++++ tensorflow_addons/losses/giou_loss_test.py | 20 +++ 4 files changed, 173 insertions(+) create mode 100644 tensorflow_addons/losses/giou_loss.py create mode 100644 tensorflow_addons/losses/giou_loss_test.py diff --git a/tensorflow_addons/losses/BUILD b/tensorflow_addons/losses/BUILD index 927f821fe2..c97351f0e4 100644 --- a/tensorflow_addons/losses/BUILD +++ b/tensorflow_addons/losses/BUILD @@ -8,6 +8,7 @@ py_library( "__init__.py", "contrastive.py", "focal_loss.py", + "giou_loss.py", "lifted.py", "metric_learning.py", "npairs.py", @@ -47,6 +48,19 @@ py_test( ], ) +py_test( + name = "giou_loss_test", + size = "small", + srcs = [ + "giou_loss_test.py", + ], + main = "giou_loss_test.py", + srcs_version = "PY2AND3", + deps = [ + ":losses", + ], +) + py_test( name = "npairs_test", size = "small", diff --git a/tensorflow_addons/losses/__init__.py b/tensorflow_addons/losses/__init__.py index ff8e5094fa..efb00ec7a6 100644 --- a/tensorflow_addons/losses/__init__.py +++ b/tensorflow_addons/losses/__init__.py @@ -24,3 +24,4 @@ from tensorflow_addons.losses.npairs import npairs_loss, NpairsLoss, npairs_multilabel_loss, NpairsMultilabelLoss from tensorflow_addons.losses.sparsemax_loss import sparsemax_loss, SparsemaxLoss from tensorflow_addons.losses.triplet import triplet_semihard_loss, TripletSemiHardLoss +from tensorflow_addons.losses.giou_loss import giou_loss, GIOULoss diff --git a/tensorflow_addons/losses/giou_loss.py b/tensorflow_addons/losses/giou_loss.py new file mode 100644 index 0000000000..0abd713771 --- /dev/null +++ b/tensorflow_addons/losses/giou_loss.py @@ -0,0 +1,138 @@ +# Copyright 2019 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Implements GIOU loss.""" + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import tensorflow as tf +from tensorflow_addons.utils import keras_utils + + +@keras_utils.register_keras_custom_object +class GIOULoss(tf.keras.losses.Loss): + """Implements the GIOU loss function. + + GIOU loss was first introduced in the Generalized Intersection over Union paper + (https://giou.stanford.edu/GIoU.pdf). GIOU loss is a patch for model which IOU + is used in object detection. + + Usage: + + ```python + fl = tfa.losses.GIOU() + loss = fl( + [[0.97], [0.91], [0.03]], + [[1], [1], [0]) + print('Loss: ', loss.numpy()) # Loss: [[0.03045921] + [0.09431068] + [0.31471074] + ``` + Usage with tf.keras API: + + ```python + model = tf.keras.Model(inputs, outputs) + model.compile('sgd', loss=tf.keras.losses.GIOULoss()) + ``` + + Args + name: Op name + + Returns: + Weighted loss float `Tensor`. If `reduction` is `NONE`, this has the same + shape as `y_true`; otherwise, it is scalar. + + Raises: + ValueError: If the shape of `sample_weight` is invalid or value of + `gamma` is less than zero + """ + + def __init__(self, + reduction=tf.keras.losses.Reduction.NONE, + name='giou_loss'): + super(GIOULoss, self).__init__(name=name, reduction=reduction) + + def call(self, y_true, y_pred): + return giou_loss(y_true, y_pred) + + def get_config(self): + base_config = super(GIOULoss, self).get_config() + return base_config + + +@keras_utils.register_keras_custom_object +def giou_loss(y_true, y_pred): + """ + Args + y_true: true targets tensor. + y_pred: predictions tensor. + + Returns: + Weighted loss float `Tensor`. + """ + + y_pred = tf.convert_to_tensor(y_pred) + y_true = tf.cast(y_true, y_pred.dtype) + giou = _giou(y_pred, y_true) + + # compute the final loss and return + return 1 - giou + + +@tf.function +def _giou(b1, b2): + b1_ymin = tf.minimum(b1[:, 0], b1[:, 2]) + b1_xmin = tf.minimum(b1[:, 1], b1[:, 3]) + b1_ymax = tf.maximum(b1[:, 0], b1[:, 2]) + b1_xmax = tf.maximum(b1[:, 1], b1[:, 3]) + b2_ymin = tf.minimum(b2[:, 0], b2[:, 2]) + b2_xmin = tf.minimum(b2[:, 1], b2[:, 3]) + b2_ymax = tf.maximum(b2[:, 0], b2[:, 2]) + b2_xmax = tf.maximum(b2[:, 1], b2[:, 3]) + b1_area = (b1_ymax - b1_ymin) * (b1_xmax - b1_xmin) + b2_area = (b2_ymax - b2_ymin) * (b2_xmax - b1_xmin) + illegal_area_indexes = tf.cast( + tf.where(tf.logical_or(b1_area < 0, b2_area < 0)), tf.int32) + valid_area_indexes = tf.cast( + tf.where(tf.logical_and(b1_area >= 0, b2_area >= 0)), tf.int32) + # if b1_area<0 or b2_area<0: + # return 0 + + intersect_ymin = tf.maximum(b1_ymin, b2_ymin) + intersect_xmin = tf.maximum(b1_xmin, b2_xmin) + intersect_ymax = tf.minimum(b1_ymax, b2_ymax) + intersect_xmax = tf.minimum(b1_xmax, b2_xmax) + intersect_area = tf.maximum(0, + intersect_ymax - intersect_ymin) * tf.maximum( + 0, intersect_xmax - intersect_xmin) + + union_area = b1_area + b2_area - intersect_area + iou = intersect_area / union_area + indices = [valid_area_indexes, illegal_area_indexes] + data = [ + tf.gather(iou, valid_area_indexes), + tf.zeros([tf.shape(illegal_area_indexes)[0], 1], tf.float64) + ] + iou = tf.dynamic_stitch(indices, data) + bc_ymin = tf.minimum(b1_ymin, b2_ymin) + bc_xmin = tf.minimum(b1_xmin, b2_xmin) + bc_ymax = tf.maximum(b1_ymax, b2_ymax) + bc_xmax = tf.maximum(b1_xmax, b2_xmax) + + enclose_area = tf.maximum(0, bc_ymax - bc_ymin) * tf.maximum( + 0, bc_xmax - bc_xmin) + giou = iou - (enclose_area - union_area) / enclose_area + return giou diff --git a/tensorflow_addons/losses/giou_loss_test.py b/tensorflow_addons/losses/giou_loss_test.py new file mode 100644 index 0000000000..b53b70162a --- /dev/null +++ b/tensorflow_addons/losses/giou_loss_test.py @@ -0,0 +1,20 @@ +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import tensorflow as tf +from tensorflow_addons.utils import test_utils +from tensorflow_addons.losses import giou_loss, GIOULoss + + +@test_utils.run_all_in_graph_and_eager_modes +class GIOULossTest(tf.test.TestCase): + def test_giou_loss(self): + pred_data = [[0, 0, 1, 1], [0, 0, 2, 2]] + true_data = [[0, 0, 1, 1], [0, 0, 1, 2]] + loss = giou_loss(true_data, pred_data) + self.assertAllClose(loss, tf.constant([0, 0.5], tf.float64)) + + +if __name__ == '__main__': + tf.test.main() From 27ae8ead7f593f36b12f6afe94cbf8c2292462e9 Mon Sep 17 00:00:00 2001 From: fsx950223 Date: Thu, 5 Sep 2019 10:46:07 +0800 Subject: [PATCH 02/22] Refact giou calculate --- tensorflow_addons/losses/giou_loss.py | 46 +++++++++++++++------- tensorflow_addons/losses/giou_loss_test.py | 28 +++++++++++-- 2 files changed, 56 insertions(+), 18 deletions(-) diff --git a/tensorflow_addons/losses/giou_loss.py b/tensorflow_addons/losses/giou_loss.py index 0abd713771..e4990ada48 100644 --- a/tensorflow_addons/losses/giou_loss.py +++ b/tensorflow_addons/losses/giou_loss.py @@ -27,8 +27,8 @@ class GIOULoss(tf.keras.losses.Loss): """Implements the GIOU loss function. GIOU loss was first introduced in the Generalized Intersection over Union paper - (https://giou.stanford.edu/GIoU.pdf). GIOU loss is a patch for model which IOU - is used in object detection. + (https://giou.stanford.edu/GIoU.pdf). GIOU is a enhance for model which use IOU + in object detection. Usage: @@ -52,12 +52,7 @@ class GIOULoss(tf.keras.losses.Loss): name: Op name Returns: - Weighted loss float `Tensor`. If `reduction` is `NONE`, this has the same - shape as `y_true`; otherwise, it is scalar. - - Raises: - ValueError: If the shape of `sample_weight` is invalid or value of - `gamma` is less than zero + GIOU loss float `Tensor`. """ def __init__(self, @@ -81,19 +76,39 @@ def giou_loss(y_true, y_pred): y_pred: predictions tensor. Returns: - Weighted loss float `Tensor`. + GIOU loss float `Tensor`. """ y_pred = tf.convert_to_tensor(y_pred) y_true = tf.cast(y_true, y_pred.dtype) - giou = _giou(y_pred, y_true) + giou = giou_calculate(y_pred, y_true) # compute the final loss and return return 1 - giou -@tf.function -def _giou(b1, b2): +def giou_calculate(b1, b2): + """ + Args + b1: bbox. + b1: the other bbox. + + Returns: + iou float `Tensor`, between [-1, 1]. + """ + return do_iou_calculate(b1, b2, mode='giou') + + +def do_iou_calculate(b1, b2, mode='iou'): + """ + Args + b1: bbox. + b1: the other bbox. + mode: one of ['iou', 'giou'] + + Returns: + iou float `Tensor`. + """ b1_ymin = tf.minimum(b1[:, 0], b1[:, 2]) b1_xmin = tf.minimum(b1[:, 1], b1[:, 3]) b1_ymax = tf.maximum(b1[:, 0], b1[:, 2]) @@ -108,8 +123,6 @@ def _giou(b1, b2): tf.where(tf.logical_or(b1_area < 0, b2_area < 0)), tf.int32) valid_area_indexes = tf.cast( tf.where(tf.logical_and(b1_area >= 0, b2_area >= 0)), tf.int32) - # if b1_area<0 or b2_area<0: - # return 0 intersect_ymin = tf.maximum(b1_ymin, b2_ymin) intersect_xmin = tf.maximum(b1_xmin, b2_xmin) @@ -127,6 +140,8 @@ def _giou(b1, b2): tf.zeros([tf.shape(illegal_area_indexes)[0], 1], tf.float64) ] iou = tf.dynamic_stitch(indices, data) + if mode == 'iou': + return iou bc_ymin = tf.minimum(b1_ymin, b2_ymin) bc_xmin = tf.minimum(b1_xmin, b2_xmin) bc_ymax = tf.maximum(b1_ymax, b2_ymax) @@ -134,5 +149,6 @@ def _giou(b1, b2): enclose_area = tf.maximum(0, bc_ymax - bc_ymin) * tf.maximum( 0, bc_xmax - bc_xmin) - giou = iou - (enclose_area - union_area) / enclose_area + giou = iou - tf.cast(enclose_area - union_area, tf.float64) / ( + tf.cast(enclose_area, tf.float64) + 1e-8) return giou diff --git a/tensorflow_addons/losses/giou_loss_test.py b/tensorflow_addons/losses/giou_loss_test.py index b53b70162a..5e06838bec 100644 --- a/tensorflow_addons/losses/giou_loss_test.py +++ b/tensorflow_addons/losses/giou_loss_test.py @@ -1,3 +1,19 @@ +# Copyright 2019 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================== +"""Tests for GIOU loss.""" + from __future__ import absolute_import from __future__ import division from __future__ import print_function @@ -9,11 +25,17 @@ @test_utils.run_all_in_graph_and_eager_modes class GIOULossTest(tf.test.TestCase): + def test_config(self): + gl_obj = GIOULoss( + reduction=tf.keras.losses.Reduction.NONE, name='giou_loss') + self.assertEqual(gl_obj.name, 'giou_loss') + self.assertEqual(gl_obj.reduction, tf.keras.losses.Reduction.NONE) + def test_giou_loss(self): - pred_data = [[0, 0, 1, 1], [0, 0, 2, 2]] - true_data = [[0, 0, 1, 1], [0, 0, 1, 2]] + pred_data = [[0, 0, 1, 1], [0, 0, 2, 2], [0, 0, 2, 2]] + true_data = [[0, 0, 1, 1], [0, 0, 1, 2], [2, 2, 4, 4]] loss = giou_loss(true_data, pred_data) - self.assertAllClose(loss, tf.constant([0, 0.5], tf.float64)) + self.assertAllClose(loss, tf.constant([0, 0.5, 1.25], tf.float64)) if __name__ == '__main__': From ae1a0201b2ffb024abb4fe26462f3dbe9bdcfa84 Mon Sep 17 00:00:00 2001 From: fsx950223 Date: Thu, 5 Sep 2019 10:53:34 +0800 Subject: [PATCH 03/22] Fix doc --- tensorflow_addons/losses/giou_loss.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/tensorflow_addons/losses/giou_loss.py b/tensorflow_addons/losses/giou_loss.py index e4990ada48..12e2287603 100644 --- a/tensorflow_addons/losses/giou_loss.py +++ b/tensorflow_addons/losses/giou_loss.py @@ -33,13 +33,11 @@ class GIOULoss(tf.keras.losses.Loss): Usage: ```python - fl = tfa.losses.GIOU() - loss = fl( - [[0.97], [0.91], [0.03]], - [[1], [1], [0]) - print('Loss: ', loss.numpy()) # Loss: [[0.03045921] - [0.09431068] - [0.31471074] + gl = tfa.losses.GIOU() + loss = gl( + [[0, 0, 1, 1], [0, 0, 2, 2], [0, 0, 2, 2]], + [[0, 0, 1, 1], [0, 0, 1, 2], [2, 2, 4, 4]]) + print('Loss: ', loss.numpy()) # Loss: [0, 0.5, 1.25] ``` Usage with tf.keras API: @@ -49,6 +47,7 @@ class GIOULoss(tf.keras.losses.Loss): ``` Args + reduction name: Op name Returns: From 16064300e5461138121c6a82cfffdccfc264538a Mon Sep 17 00:00:00 2001 From: fsx950223 Date: Fri, 6 Sep 2019 09:29:14 +0800 Subject: [PATCH 04/22] Update Readme.md --- tensorflow_addons/losses/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) mode change 100644 => 100755 tensorflow_addons/losses/README.md diff --git a/tensorflow_addons/losses/README.md b/tensorflow_addons/losses/README.md old mode 100644 new mode 100755 index ab54fef1bf..6aeb6c1f6c --- a/tensorflow_addons/losses/README.md +++ b/tensorflow_addons/losses/README.md @@ -5,16 +5,17 @@ |:---------- |:----------- |:------------- | | contrastive | @WindQAQ | windqaq@gmail.com | | focal_loss | @SSaishruthi | saishruthi.tn@gmail.com | +| giou_loss | @who who who | fsx950223@gmail.com | | lifted | @rahulunair | rahulunair@gmail.com | | npairs | @WindQAQ | windqaq@gmail.com | | sparsemax_loss | @AndreasMadsen | amwwebdk+github@gmail.com | -| triplet | @rahulunair | rahulunair@gmail.com | ## Components | Submodule | Loss | Reference | |:----------------------- |:---------------------|:--------------------------| | contrastive | ContrastiveLoss | http://yann.lecun.com/exdb/publis/pdf/hadsell-chopra-lecun-06.pdf | | focal_loss | SigmoidFocalCrossEntropy | https://arxiv.org/abs/1708.02002 | +| giou_loss | GIOULoss | https://giou.stanford.edu/GIoU.pdf | | lifted | LiftedStructLoss | https://arxiv.org/abs/1511.06452 | | npairs | NpairsLoss | http://www.nec-labs.com/uploads/images/Department-Images/MediaAnalytics/papers/nips16_npairmetriclearning.pdf | | npairs | NpairsMultilabelLoss | http://www.nec-labs.com/uploads/images/Department-Images/MediaAnalytics/papers/nips16_npairmetriclearning.pdf | From eb7458dfd8b427408ced46a647a6fc5795c7a710 Mon Sep 17 00:00:00 2001 From: fsx950223 Date: Mon, 9 Sep 2019 09:34:52 +0800 Subject: [PATCH 05/22] Format code --- tensorflow_addons/losses/giou_loss.py | 8 ++++---- tensorflow_addons/losses/giou_loss_test.py | 2 ++ 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/tensorflow_addons/losses/giou_loss.py b/tensorflow_addons/losses/giou_loss.py index 12e2287603..add9045eca 100644 --- a/tensorflow_addons/losses/giou_loss.py +++ b/tensorflow_addons/losses/giou_loss.py @@ -26,9 +26,9 @@ class GIOULoss(tf.keras.losses.Loss): """Implements the GIOU loss function. - GIOU loss was first introduced in the Generalized Intersection over Union paper - (https://giou.stanford.edu/GIoU.pdf). GIOU is a enhance for model which use IOU - in object detection. + GIOU loss was first introduced in the Generalized Intersection over Union + paper (https://giou.stanford.edu/GIoU.pdf). GIOU is a enhance for model + which use IOU in object detection. Usage: @@ -73,7 +73,7 @@ def giou_loss(y_true, y_pred): Args y_true: true targets tensor. y_pred: predictions tensor. - + Returns: GIOU loss float `Tensor`. """ diff --git a/tensorflow_addons/losses/giou_loss_test.py b/tensorflow_addons/losses/giou_loss_test.py index 5e06838bec..f5ae519f5e 100644 --- a/tensorflow_addons/losses/giou_loss_test.py +++ b/tensorflow_addons/losses/giou_loss_test.py @@ -25,6 +25,8 @@ @test_utils.run_all_in_graph_and_eager_modes class GIOULossTest(tf.test.TestCase): + """GIOU test class.""" + def test_config(self): gl_obj = GIOULoss( reduction=tf.keras.losses.Reduction.NONE, name='giou_loss') From be8dcf09b6cf8f81eae71f129a55e014c5ce2e37 Mon Sep 17 00:00:00 2001 From: fsx950223 Date: Mon, 4 Nov 2019 04:07:28 +0000 Subject: [PATCH 06/22] refact calculate --- tensorflow_addons/losses/__init__.py | 2 +- tensorflow_addons/losses/giou_loss.py | 115 +++++++++------------ tensorflow_addons/losses/giou_loss_test.py | 55 ++++++++-- 3 files changed, 97 insertions(+), 75 deletions(-) mode change 100644 => 100755 tensorflow_addons/losses/giou_loss.py mode change 100644 => 100755 tensorflow_addons/losses/giou_loss_test.py diff --git a/tensorflow_addons/losses/__init__.py b/tensorflow_addons/losses/__init__.py index efb00ec7a6..3db3aad827 100644 --- a/tensorflow_addons/losses/__init__.py +++ b/tensorflow_addons/losses/__init__.py @@ -24,4 +24,4 @@ from tensorflow_addons.losses.npairs import npairs_loss, NpairsLoss, npairs_multilabel_loss, NpairsMultilabelLoss from tensorflow_addons.losses.sparsemax_loss import sparsemax_loss, SparsemaxLoss from tensorflow_addons.losses.triplet import triplet_semihard_loss, TripletSemiHardLoss -from tensorflow_addons.losses.giou_loss import giou_loss, GIOULoss +from tensorflow_addons.losses.giou_loss import giou_loss, GIoULoss diff --git a/tensorflow_addons/losses/giou_loss.py b/tensorflow_addons/losses/giou_loss.py old mode 100644 new mode 100755 index add9045eca..c79be5c8d5 --- a/tensorflow_addons/losses/giou_loss.py +++ b/tensorflow_addons/losses/giou_loss.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== -"""Implements GIOU loss.""" +"""Implements GIoU loss.""" from __future__ import absolute_import from __future__ import division @@ -23,91 +23,83 @@ @keras_utils.register_keras_custom_object -class GIOULoss(tf.keras.losses.Loss): - """Implements the GIOU loss function. +class GIoULoss(tf.keras.losses.Loss): + """Implements the GIoU loss function. - GIOU loss was first introduced in the Generalized Intersection over Union - paper (https://giou.stanford.edu/GIoU.pdf). GIOU is a enhance for model + GIoU loss was first introduced in the Generalized Intersection over Union + paper (https://giou.stanford.edu/GIoU.pdf). GIoU is a enhance for model which use IOU in object detection. Usage: ```python - gl = tfa.losses.GIOU() - loss = gl( - [[0, 0, 1, 1], [0, 0, 2, 2], [0, 0, 2, 2]], - [[0, 0, 1, 1], [0, 0, 1, 2], [2, 2, 4, 4]]) - print('Loss: ', loss.numpy()) # Loss: [0, 0.5, 1.25] + gl = tfa.losses.GIoU() + boxes1 = tf.constant([[4.0, 3.0, 7.0, 5.0], [5.0, 6.0, 10.0, 7.0]]) + boxes2 = tf.constant([[3.0, 4.0, 6.0, 8.0], [14.0, 14.0, 15.0, 15.0]]) + loss = gl(boxes1,boxes2) + print('Loss: ', loss.numpy()) # Loss: [1.07500000298023224, 1.9333333373069763] ``` Usage with tf.keras API: ```python model = tf.keras.Model(inputs, outputs) - model.compile('sgd', loss=tf.keras.losses.GIOULoss()) + model.compile('sgd', loss=tf.keras.losses.GIoULoss()) ``` Args - reduction - name: Op name + mode: one of ['giou', 'iou'], decided to calculate giou loss or iou loss. Returns: - GIOU loss float `Tensor`. + GIoU loss double `Tensor`. """ def __init__(self, - reduction=tf.keras.losses.Reduction.NONE, + mode='giou', + reduction=tf.keras.losses.Reduction.AUTO, name='giou_loss'): - super(GIOULoss, self).__init__(name=name, reduction=reduction) - - def call(self, y_true, y_pred): - return giou_loss(y_true, y_pred) + super(GIoULoss, self).__init__(name=name, reduction=reduction) + self.mode = mode def get_config(self): - base_config = super(GIOULoss, self).get_config() + base_config = super(GIoULoss, self).get_config() + base_config['mode'] = self.mode return base_config + def call(self, y_true, y_pred): + return giou_loss(y_true, y_pred, mode=self.mode) + @keras_utils.register_keras_custom_object -def giou_loss(y_true, y_pred): +@tf.function +def giou_loss(y_true, y_pred, mode='giou'): """ Args y_true: true targets tensor. y_pred: predictions tensor. Returns: - GIOU loss float `Tensor`. + GIoU loss double `Tensor`. """ y_pred = tf.convert_to_tensor(y_pred) y_true = tf.cast(y_true, y_pred.dtype) - giou = giou_calculate(y_pred, y_true) + giou = do_giou_calculate(y_pred, y_true, mode) # compute the final loss and return return 1 - giou -def giou_calculate(b1, b2): +def do_giou_calculate(b1, b2, mode='giou'): """ Args b1: bbox. - b1: the other bbox. + b2: the other bbox. + mode: one of ['giou', 'iou'] Returns: - iou float `Tensor`, between [-1, 1]. - """ - return do_iou_calculate(b1, b2, mode='giou') - - -def do_iou_calculate(b1, b2, mode='iou'): - """ - Args - b1: bbox. - b1: the other bbox. - mode: one of ['iou', 'giou'] - - Returns: - iou float `Tensor`. + GIoU loss double `Tensor`. """ + zero = tf.convert_to_tensor(0., b1.dtype) b1_ymin = tf.minimum(b1[:, 0], b1[:, 2]) b1_xmin = tf.minimum(b1[:, 1], b1[:, 3]) b1_ymax = tf.maximum(b1[:, 0], b1[:, 2]) @@ -116,38 +108,33 @@ def do_iou_calculate(b1, b2, mode='iou'): b2_xmin = tf.minimum(b2[:, 1], b2[:, 3]) b2_ymax = tf.maximum(b2[:, 0], b2[:, 2]) b2_xmax = tf.maximum(b2[:, 1], b2[:, 3]) - b1_area = (b1_ymax - b1_ymin) * (b1_xmax - b1_xmin) - b2_area = (b2_ymax - b2_ymin) * (b2_xmax - b1_xmin) - illegal_area_indexes = tf.cast( - tf.where(tf.logical_or(b1_area < 0, b2_area < 0)), tf.int32) - valid_area_indexes = tf.cast( - tf.where(tf.logical_and(b1_area >= 0, b2_area >= 0)), tf.int32) + b1_width = tf.maximum(zero, b1_xmax - b1_xmin) + b1_height = tf.maximum(zero, b1_ymax - b1_ymin) + b2_width = tf.maximum(zero, b2_xmax - b2_xmin) + b2_height = tf.maximum(zero, b2_ymax - b2_ymin) + b1_area = b1_width * b1_height + b2_area = b2_width * b2_height intersect_ymin = tf.maximum(b1_ymin, b2_ymin) intersect_xmin = tf.maximum(b1_xmin, b2_xmin) intersect_ymax = tf.minimum(b1_ymax, b2_ymax) intersect_xmax = tf.minimum(b1_xmax, b2_xmax) - intersect_area = tf.maximum(0, - intersect_ymax - intersect_ymin) * tf.maximum( - 0, intersect_xmax - intersect_xmin) + intersect_width = tf.maximum(zero, intersect_xmax - intersect_xmin) + intersect_height = tf.maximum(zero, intersect_ymax - intersect_ymin) + intersect_area = intersect_width * intersect_height union_area = b1_area + b2_area - intersect_area - iou = intersect_area / union_area - indices = [valid_area_indexes, illegal_area_indexes] - data = [ - tf.gather(iou, valid_area_indexes), - tf.zeros([tf.shape(illegal_area_indexes)[0], 1], tf.float64) - ] - iou = tf.dynamic_stitch(indices, data) + iou = tf.math.divide_no_nan(intersect_area, union_area) if mode == 'iou': return iou - bc_ymin = tf.minimum(b1_ymin, b2_ymin) - bc_xmin = tf.minimum(b1_xmin, b2_xmin) - bc_ymax = tf.maximum(b1_ymax, b2_ymax) - bc_xmax = tf.maximum(b1_xmax, b2_xmax) - - enclose_area = tf.maximum(0, bc_ymax - bc_ymin) * tf.maximum( - 0, bc_xmax - bc_xmin) - giou = iou - tf.cast(enclose_area - union_area, tf.float64) / ( - tf.cast(enclose_area, tf.float64) + 1e-8) + + enclose_ymin = tf.minimum(b1_ymin, b2_ymin) + enclose_xmin = tf.minimum(b1_xmin, b2_xmin) + enclose_ymax = tf.maximum(b1_ymax, b2_ymax) + enclose_xmax = tf.maximum(b1_xmax, b2_xmax) + enclose_width = tf.maximum(zero, enclose_xmax - enclose_xmin) + enclose_height = tf.maximum(zero, enclose_ymax - enclose_ymin) + enclose_area = enclose_width * enclose_height + giou = iou - tf.math.divide_no_nan( + (enclose_area - union_area), enclose_area) return giou diff --git a/tensorflow_addons/losses/giou_loss_test.py b/tensorflow_addons/losses/giou_loss_test.py old mode 100644 new mode 100755 index f5ae519f5e..b95fb769bd --- a/tensorflow_addons/losses/giou_loss_test.py +++ b/tensorflow_addons/losses/giou_loss_test.py @@ -12,32 +12,67 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== -"""Tests for GIOU loss.""" +"""Tests for GIoU loss.""" from __future__ import absolute_import from __future__ import division from __future__ import print_function +from absl.testing import parameterized + +import numpy as np import tensorflow as tf from tensorflow_addons.utils import test_utils -from tensorflow_addons.losses import giou_loss, GIOULoss +from tensorflow_addons.losses import giou_loss, GIoULoss @test_utils.run_all_in_graph_and_eager_modes -class GIOULossTest(tf.test.TestCase): - """GIOU test class.""" +class GIoULossTest(tf.test.TestCase, parameterized.TestCase): + """GIoU test class.""" def test_config(self): - gl_obj = GIOULoss( + gl_obj = GIoULoss( reduction=tf.keras.losses.Reduction.NONE, name='giou_loss') self.assertEqual(gl_obj.name, 'giou_loss') self.assertEqual(gl_obj.reduction, tf.keras.losses.Reduction.NONE) - def test_giou_loss(self): - pred_data = [[0, 0, 1, 1], [0, 0, 2, 2], [0, 0, 2, 2]] - true_data = [[0, 0, 1, 1], [0, 0, 1, 2], [2, 2, 4, 4]] - loss = giou_loss(true_data, pred_data) - self.assertAllClose(loss, tf.constant([0, 0.5, 1.25], tf.float64)) + @parameterized.named_parameters(("float16", np.float16), + ("float32", np.float32), + ("float64", np.float64)) + def test_iou(self, dtype): + boxes1 = tf.constant([[4.0, 3.0, 7.0, 5.0], [5.0, 6.0, 10.0, 7.0]], + dtype=dtype) + boxes2 = tf.constant([[3.0, 4.0, 6.0, 8.0], [14.0, 14.0, 15.0, 15.0]], + dtype=dtype) + expected_result = tf.constant([14.0 / 16.0, 1.], dtype=dtype) + loss = giou_loss(boxes1, boxes2, mode='iou') + self.assertAllCloseAccordingToType(loss, expected_result) + + @parameterized.named_parameters(("float16", np.float16), + ("float32", np.float32), + ("float64", np.float64)) + def test_giou_loss(self, dtype): + boxes1 = tf.constant([[4.0, 3.0, 7.0, 5.0], [5.0, 6.0, 10.0, 7.0]], + dtype=dtype) + boxes2 = tf.constant([[3.0, 4.0, 6.0, 8.0], [14.0, 14.0, 15.0, 15.0]], + dtype=dtype) + expected_result = tf.constant( + [1.07500000298023224, 1.9333333373069763], dtype=dtype) + loss = giou_loss(boxes1, boxes2) + self.assertAllCloseAccordingToType(loss, expected_result) + + @parameterized.named_parameters(("float16", np.float16), + ("float32", np.float32), + ("float64", np.float64)) + def test_giou_loss_swapped(self, dtype): + boxes1 = tf.constant([[7.0, 3.0, 4.0, 5.0], [5.0, 6.0, 10.0, 7.0]], + dtype=dtype) + boxes2 = tf.constant([[3.0, 4.0, 6.0, 8.0], [14.0, 14.0, 15.0, 15.0]], + dtype=dtype) + expected_result = tf.constant( + [1.07500000298023224, 1.9333333373069763], dtype=dtype) + loss = giou_loss(boxes1, boxes2) + self.assertAllCloseAccordingToType(loss, expected_result) if __name__ == '__main__': From 7f72cab314062702d62933dfc15c78678d7c05ba Mon Sep 17 00:00:00 2001 From: fsx950223 Date: Mon, 4 Nov 2019 07:25:31 +0000 Subject: [PATCH 07/22] fix document --- tensorflow_addons/losses/README.md | 2 +- tensorflow_addons/losses/giou_loss.py | 22 ++++++++++++---------- tensorflow_addons/losses/giou_loss_test.py | 0 3 files changed, 13 insertions(+), 11 deletions(-) mode change 100755 => 100644 tensorflow_addons/losses/giou_loss.py mode change 100755 => 100644 tensorflow_addons/losses/giou_loss_test.py diff --git a/tensorflow_addons/losses/README.md b/tensorflow_addons/losses/README.md index 6aeb6c1f6c..1d846e1132 100755 --- a/tensorflow_addons/losses/README.md +++ b/tensorflow_addons/losses/README.md @@ -15,7 +15,7 @@ |:----------------------- |:---------------------|:--------------------------| | contrastive | ContrastiveLoss | http://yann.lecun.com/exdb/publis/pdf/hadsell-chopra-lecun-06.pdf | | focal_loss | SigmoidFocalCrossEntropy | https://arxiv.org/abs/1708.02002 | -| giou_loss | GIOULoss | https://giou.stanford.edu/GIoU.pdf | +| giou_loss | GIoULoss | https://giou.stanford.edu/GIoU.pdf | | lifted | LiftedStructLoss | https://arxiv.org/abs/1511.06452 | | npairs | NpairsLoss | http://www.nec-labs.com/uploads/images/Department-Images/MediaAnalytics/papers/nips16_npairmetriclearning.pdf | | npairs | NpairsMultilabelLoss | http://www.nec-labs.com/uploads/images/Department-Images/MediaAnalytics/papers/nips16_npairmetriclearning.pdf | diff --git a/tensorflow_addons/losses/giou_loss.py b/tensorflow_addons/losses/giou_loss.py old mode 100755 new mode 100644 index c79be5c8d5..cf2cd3acb8 --- a/tensorflow_addons/losses/giou_loss.py +++ b/tensorflow_addons/losses/giou_loss.py @@ -46,11 +46,11 @@ class GIoULoss(tf.keras.losses.Loss): model.compile('sgd', loss=tf.keras.losses.GIoULoss()) ``` - Args + Args: mode: one of ['giou', 'iou'], decided to calculate giou loss or iou loss. Returns: - GIoU loss double `Tensor`. + GIoU loss float `Tensor`. """ def __init__(self, @@ -73,14 +73,16 @@ def call(self, y_true, y_pred): @tf.function def giou_loss(y_true, y_pred, mode='giou'): """ - Args + Args: y_true: true targets tensor. y_pred: predictions tensor. + mode: one of ['giou', 'iou'], decided to calculate giou loss or iou loss. Returns: - GIoU loss double `Tensor`. + GIoU loss float `Tensor`. """ - + if mode not in ['giou', 'iou']: + raise ValueError("Value of mode should be 'iou' or 'giou'") y_pred = tf.convert_to_tensor(y_pred) y_true = tf.cast(y_true, y_pred.dtype) giou = do_giou_calculate(y_pred, y_true, mode) @@ -91,13 +93,13 @@ def giou_loss(y_true, y_pred, mode='giou'): def do_giou_calculate(b1, b2, mode='giou'): """ - Args - b1: bbox. - b2: the other bbox. - mode: one of ['giou', 'iou'] + Args: + b1: bounding box. + b2: the other bounding box. + mode: one of ['giou', 'iou'], decided to calculate giou loss or iou loss. Returns: - GIoU loss double `Tensor`. + GIoU loss float `Tensor`. """ zero = tf.convert_to_tensor(0., b1.dtype) b1_ymin = tf.minimum(b1[:, 0], b1[:, 2]) diff --git a/tensorflow_addons/losses/giou_loss_test.py b/tensorflow_addons/losses/giou_loss_test.py old mode 100755 new mode 100644 From 099298c4b8901c5ddf195d2c7e84ac630e6be795 Mon Sep 17 00:00:00 2001 From: fsx950223 Date: Tue, 5 Nov 2019 01:58:43 +0000 Subject: [PATCH 08/22] fix readme --- tensorflow_addons/losses/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/tensorflow_addons/losses/README.md b/tensorflow_addons/losses/README.md index 1d846e1132..ec570a51a8 100755 --- a/tensorflow_addons/losses/README.md +++ b/tensorflow_addons/losses/README.md @@ -9,6 +9,7 @@ | lifted | @rahulunair | rahulunair@gmail.com | | npairs | @WindQAQ | windqaq@gmail.com | | sparsemax_loss | @AndreasMadsen | amwwebdk+github@gmail.com | +| triplet | @rahulunair | rahulunair@gmail.com | ## Components | Submodule | Loss | Reference | From 825c255fe126fbc71a83706e1f8fbf392d122d7f Mon Sep 17 00:00:00 2001 From: fsx950223 Date: Tue, 5 Nov 2019 02:03:30 +0000 Subject: [PATCH 09/22] fix docs --- tensorflow_addons/losses/README.md | 0 tensorflow_addons/losses/giou_loss.py | 6 +++--- 2 files changed, 3 insertions(+), 3 deletions(-) mode change 100755 => 100644 tensorflow_addons/losses/README.md diff --git a/tensorflow_addons/losses/README.md b/tensorflow_addons/losses/README.md old mode 100755 new mode 100644 diff --git a/tensorflow_addons/losses/giou_loss.py b/tensorflow_addons/losses/giou_loss.py index cf2cd3acb8..e242ec2f81 100644 --- a/tensorflow_addons/losses/giou_loss.py +++ b/tensorflow_addons/losses/giou_loss.py @@ -26,9 +26,9 @@ class GIoULoss(tf.keras.losses.Loss): """Implements the GIoU loss function. - GIoU loss was first introduced in the Generalized Intersection over Union - paper (https://giou.stanford.edu/GIoU.pdf). GIoU is a enhance for model - which use IOU in object detection. + GIoU loss was first introduced in the + [Generalized Intersection over Union paper](https://giou.stanford.edu/GIoU.pdf). + GIoU is a enhance for model which use IOU in object detection. Usage: From 9beec61b9016a28463b71a03ce810b08d42294c6 Mon Sep 17 00:00:00 2001 From: fsx950223 Date: Tue, 5 Nov 2019 02:14:25 +0000 Subject: [PATCH 10/22] Change to official api --- tensorflow_addons/losses/giou_loss.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tensorflow_addons/losses/giou_loss.py b/tensorflow_addons/losses/giou_loss.py index e242ec2f81..9625822a16 100644 --- a/tensorflow_addons/losses/giou_loss.py +++ b/tensorflow_addons/losses/giou_loss.py @@ -19,10 +19,9 @@ from __future__ import print_function import tensorflow as tf -from tensorflow_addons.utils import keras_utils -@keras_utils.register_keras_custom_object +@tf.keras.utils.register_keras_serializable(package='Addons') class GIoULoss(tf.keras.losses.Loss): """Implements the GIoU loss function. @@ -69,7 +68,7 @@ def call(self, y_true, y_pred): return giou_loss(y_true, y_pred, mode=self.mode) -@keras_utils.register_keras_custom_object +@tf.keras.utils.register_keras_serializable(package='Addons') @tf.function def giou_loss(y_true, y_pred, mode='giou'): """ From 72fc21a8986380acbc6195ea20f51c80c387a7c1 Mon Sep 17 00:00:00 2001 From: fsx950223 Date: Tue, 5 Nov 2019 04:45:54 +0000 Subject: [PATCH 11/22] format code --- tensorflow_addons/losses/giou_loss.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tensorflow_addons/losses/giou_loss.py b/tensorflow_addons/losses/giou_loss.py index 9625822a16..4cc3ae4f00 100644 --- a/tensorflow_addons/losses/giou_loss.py +++ b/tensorflow_addons/losses/giou_loss.py @@ -75,7 +75,8 @@ def giou_loss(y_true, y_pred, mode='giou'): Args: y_true: true targets tensor. y_pred: predictions tensor. - mode: one of ['giou', 'iou'], decided to calculate giou loss or iou loss. + mode: one of ['giou', 'iou'], + decided to calculate giou loss or iou loss. Returns: GIoU loss float `Tensor`. @@ -95,7 +96,8 @@ def do_giou_calculate(b1, b2, mode='giou'): Args: b1: bounding box. b2: the other bounding box. - mode: one of ['giou', 'iou'], decided to calculate giou loss or iou loss. + mode: one of ['giou', 'iou'], + decided to calculate giou loss or iou loss. Returns: GIoU loss float `Tensor`. From b35dff90d74df79d5c9ecb36516e3feda8e0cf41 Mon Sep 17 00:00:00 2001 From: fsx950223 Date: Wed, 6 Nov 2019 02:04:02 +0000 Subject: [PATCH 12/22] enhance robust --- tensorflow_addons/losses/giou_loss.py | 16 ++++++++-------- tensorflow_addons/losses/giou_loss_test.py | 18 ++++++++++++++++++ 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/tensorflow_addons/losses/giou_loss.py b/tensorflow_addons/losses/giou_loss.py index 4cc3ae4f00..f42069e06e 100644 --- a/tensorflow_addons/losses/giou_loss.py +++ b/tensorflow_addons/losses/giou_loss.py @@ -103,14 +103,14 @@ def do_giou_calculate(b1, b2, mode='giou'): GIoU loss float `Tensor`. """ zero = tf.convert_to_tensor(0., b1.dtype) - b1_ymin = tf.minimum(b1[:, 0], b1[:, 2]) - b1_xmin = tf.minimum(b1[:, 1], b1[:, 3]) - b1_ymax = tf.maximum(b1[:, 0], b1[:, 2]) - b1_xmax = tf.maximum(b1[:, 1], b1[:, 3]) - b2_ymin = tf.minimum(b2[:, 0], b2[:, 2]) - b2_xmin = tf.minimum(b2[:, 1], b2[:, 3]) - b2_ymax = tf.maximum(b2[:, 0], b2[:, 2]) - b2_xmax = tf.maximum(b2[:, 1], b2[:, 3]) + b1_ymin = tf.minimum(b1[..., 0], b1[..., 2]) + b1_xmin = tf.minimum(b1[..., 1], b1[..., 3]) + b1_ymax = tf.maximum(b1[..., 0], b1[..., 2]) + b1_xmax = tf.maximum(b1[..., 1], b1[..., 3]) + b2_ymin = tf.minimum(b2[..., 0], b2[..., 2]) + b2_xmin = tf.minimum(b2[..., 1], b2[..., 3]) + b2_ymax = tf.maximum(b2[..., 0], b2[..., 2]) + b2_xmax = tf.maximum(b2[..., 1], b2[..., 3]) b1_width = tf.maximum(zero, b1_xmax - b1_xmin) b1_height = tf.maximum(zero, b1_ymax - b1_ymin) b2_width = tf.maximum(zero, b2_xmax - b2_xmin) diff --git a/tensorflow_addons/losses/giou_loss_test.py b/tensorflow_addons/losses/giou_loss_test.py index b95fb769bd..5909713822 100644 --- a/tensorflow_addons/losses/giou_loss_test.py +++ b/tensorflow_addons/losses/giou_loss_test.py @@ -74,6 +74,24 @@ def test_giou_loss_swapped(self, dtype): loss = giou_loss(boxes1, boxes2) self.assertAllCloseAccordingToType(loss, expected_result) + @parameterized.named_parameters(("float16", np.float16), + ("float32", np.float32), + ("float64", np.float64)) + def test_giou_loss_with_dims(self, dtype): + boxes1 = tf.constant([[[4.0, 3.0, 7.0, 5.0], [5.0, 6.0, 10.0, 7.0]], + [[4.0, 3.0, 7.0, 5.0], [5.0, 6.0, 10.0, 7.0]]], + dtype=dtype) + boxes2 = tf.constant( + [[[3.0, 4.0, 6.0, 8.0], [14.0, 14.0, 15.0, 15.0]], + [[3.0, 4.0, 6.0, 8.0], [14.0, 14.0, 15.0, 15.0]]], + dtype=dtype) + expected_result = tf.constant( + [[1.07500000298023224, 1.9333333373069763], + [1.07500000298023224, 1.9333333373069763]], + dtype=dtype) + loss = giou_loss(boxes1, boxes2) + self.assertAllCloseAccordingToType(loss, expected_result) + if __name__ == '__main__': tf.test.main() From 310850df438a2813c0f13b9417df538cbfb68f3e Mon Sep 17 00:00:00 2001 From: fsx950223 Date: Sun, 10 Nov 2019 04:19:57 +0000 Subject: [PATCH 13/22] add box format --- tensorflow_addons/losses/giou_loss.py | 22 ++++++++++------------ tensorflow_addons/losses/giou_loss_test.py | 13 ------------- 2 files changed, 10 insertions(+), 25 deletions(-) diff --git a/tensorflow_addons/losses/giou_loss.py b/tensorflow_addons/losses/giou_loss.py index f42069e06e..a584c56871 100644 --- a/tensorflow_addons/losses/giou_loss.py +++ b/tensorflow_addons/losses/giou_loss.py @@ -73,8 +73,10 @@ def call(self, y_true, y_pred): def giou_loss(y_true, y_pred, mode='giou'): """ Args: - y_true: true targets tensor. - y_pred: predictions tensor. + y_true: true targets tensor. The coordinates of the each bounding box in + boxes are encoded as [y_min, x_min, y_max, x_max]. + y_pred: predictions tensor. The coordinates of the each bounding box in + boxes are encoded as [y_min, x_min, y_max, x_max]. mode: one of ['giou', 'iou'], decided to calculate giou loss or iou loss. @@ -94,8 +96,10 @@ def giou_loss(y_true, y_pred, mode='giou'): def do_giou_calculate(b1, b2, mode='giou'): """ Args: - b1: bounding box. - b2: the other bounding box. + b1: bounding box. The coordinates of the each bounding box in boxes are + encoded as [y_min, x_min, y_max, x_max]. + b2: the other bounding box. The coordinates of the each bounding box + in boxes are encoded as [y_min, x_min, y_max, x_max]. mode: one of ['giou', 'iou'], decided to calculate giou loss or iou loss. @@ -103,14 +107,8 @@ def do_giou_calculate(b1, b2, mode='giou'): GIoU loss float `Tensor`. """ zero = tf.convert_to_tensor(0., b1.dtype) - b1_ymin = tf.minimum(b1[..., 0], b1[..., 2]) - b1_xmin = tf.minimum(b1[..., 1], b1[..., 3]) - b1_ymax = tf.maximum(b1[..., 0], b1[..., 2]) - b1_xmax = tf.maximum(b1[..., 1], b1[..., 3]) - b2_ymin = tf.minimum(b2[..., 0], b2[..., 2]) - b2_xmin = tf.minimum(b2[..., 1], b2[..., 3]) - b2_ymax = tf.maximum(b2[..., 0], b2[..., 2]) - b2_xmax = tf.maximum(b2[..., 1], b2[..., 3]) + b1_ymin, b1_xmin, b1_ymax, b1_xmax = tf.unstack(b1, axis=-1) + b2_ymin, b2_xmin, b2_ymax, b2_xmax = tf.unstack(b2, axis=-1) b1_width = tf.maximum(zero, b1_xmax - b1_xmin) b1_height = tf.maximum(zero, b1_ymax - b1_ymin) b2_width = tf.maximum(zero, b2_xmax - b2_xmin) diff --git a/tensorflow_addons/losses/giou_loss_test.py b/tensorflow_addons/losses/giou_loss_test.py index 5909713822..c61345cb32 100644 --- a/tensorflow_addons/losses/giou_loss_test.py +++ b/tensorflow_addons/losses/giou_loss_test.py @@ -61,19 +61,6 @@ def test_giou_loss(self, dtype): loss = giou_loss(boxes1, boxes2) self.assertAllCloseAccordingToType(loss, expected_result) - @parameterized.named_parameters(("float16", np.float16), - ("float32", np.float32), - ("float64", np.float64)) - def test_giou_loss_swapped(self, dtype): - boxes1 = tf.constant([[7.0, 3.0, 4.0, 5.0], [5.0, 6.0, 10.0, 7.0]], - dtype=dtype) - boxes2 = tf.constant([[3.0, 4.0, 6.0, 8.0], [14.0, 14.0, 15.0, 15.0]], - dtype=dtype) - expected_result = tf.constant( - [1.07500000298023224, 1.9333333373069763], dtype=dtype) - loss = giou_loss(boxes1, boxes2) - self.assertAllCloseAccordingToType(loss, expected_result) - @parameterized.named_parameters(("float16", np.float16), ("float32", np.float32), ("float64", np.float64)) From f85f692080843ac34fc53475d362526e18e0adab Mon Sep 17 00:00:00 2001 From: fsx950223 Date: Tue, 12 Nov 2019 07:17:19 +0000 Subject: [PATCH 14/22] add keras test --- tensorflow_addons/losses/__init__.py | 2 +- tensorflow_addons/losses/giou_loss.py | 9 ++++----- tensorflow_addons/losses/giou_loss_test.py | 21 ++++++++++----------- 3 files changed, 15 insertions(+), 17 deletions(-) diff --git a/tensorflow_addons/losses/__init__.py b/tensorflow_addons/losses/__init__.py index 3db3aad827..7aa292527f 100644 --- a/tensorflow_addons/losses/__init__.py +++ b/tensorflow_addons/losses/__init__.py @@ -20,8 +20,8 @@ from tensorflow_addons.losses.contrastive import contrastive_loss, ContrastiveLoss from tensorflow_addons.losses.focal_loss import sigmoid_focal_crossentropy, SigmoidFocalCrossEntropy +from tensorflow_addons.losses.giou_loss import giou_loss, GIoULoss from tensorflow_addons.losses.lifted import lifted_struct_loss, LiftedStructLoss from tensorflow_addons.losses.npairs import npairs_loss, NpairsLoss, npairs_multilabel_loss, NpairsMultilabelLoss from tensorflow_addons.losses.sparsemax_loss import sparsemax_loss, SparsemaxLoss from tensorflow_addons.losses.triplet import triplet_semihard_loss, TripletSemiHardLoss -from tensorflow_addons.losses.giou_loss import giou_loss, GIoULoss diff --git a/tensorflow_addons/losses/giou_loss.py b/tensorflow_addons/losses/giou_loss.py index a584c56871..276156446c 100644 --- a/tensorflow_addons/losses/giou_loss.py +++ b/tensorflow_addons/losses/giou_loss.py @@ -47,15 +47,14 @@ class GIoULoss(tf.keras.losses.Loss): Args: mode: one of ['giou', 'iou'], decided to calculate giou loss or iou loss. - - Returns: - GIoU loss float `Tensor`. """ def __init__(self, mode='giou', reduction=tf.keras.losses.Reduction.AUTO, name='giou_loss'): + if mode not in ['giou', 'iou']: + raise ValueError("Value of mode should be 'iou' or 'giou'") super(GIoULoss, self).__init__(name=name, reduction=reduction) self.mode = mode @@ -107,8 +106,8 @@ def do_giou_calculate(b1, b2, mode='giou'): GIoU loss float `Tensor`. """ zero = tf.convert_to_tensor(0., b1.dtype) - b1_ymin, b1_xmin, b1_ymax, b1_xmax = tf.unstack(b1, axis=-1) - b2_ymin, b2_xmin, b2_ymax, b2_xmax = tf.unstack(b2, axis=-1) + b1_ymin, b1_xmin, b1_ymax, b1_xmax = tf.unstack(b1, 4, axis=-1) + b2_ymin, b2_xmin, b2_ymax, b2_xmax = tf.unstack(b2, 4, axis=-1) b1_width = tf.maximum(zero, b1_xmax - b1_xmin) b1_height = tf.maximum(zero, b1_ymax - b1_ymin) b2_width = tf.maximum(zero, b2_xmax - b2_xmin) diff --git a/tensorflow_addons/losses/giou_loss_test.py b/tensorflow_addons/losses/giou_loss_test.py index c61345cb32..e52c1c2c08 100644 --- a/tensorflow_addons/losses/giou_loss_test.py +++ b/tensorflow_addons/losses/giou_loss_test.py @@ -64,19 +64,18 @@ def test_giou_loss(self, dtype): @parameterized.named_parameters(("float16", np.float16), ("float32", np.float32), ("float64", np.float64)) - def test_giou_loss_with_dims(self, dtype): - boxes1 = tf.constant([[[4.0, 3.0, 7.0, 5.0], [5.0, 6.0, 10.0, 7.0]], - [[4.0, 3.0, 7.0, 5.0], [5.0, 6.0, 10.0, 7.0]]], + def test_keras_model(self, dtype): + boxes1 = tf.constant([[4.0, 3.0, 7.0, 5.0], [5.0, 6.0, 10.0, 7.0]], + dtype=dtype) + boxes2 = tf.constant([[3.0, 4.0, 6.0, 8.0], [14.0, 14.0, 15.0, 15.0]], dtype=dtype) - boxes2 = tf.constant( - [[[3.0, 4.0, 6.0, 8.0], [14.0, 14.0, 15.0, 15.0]], - [[3.0, 4.0, 6.0, 8.0], [14.0, 14.0, 15.0, 15.0]]], - dtype=dtype) expected_result = tf.constant( - [[1.07500000298023224, 1.9333333373069763], - [1.07500000298023224, 1.9333333373069763]], - dtype=dtype) - loss = giou_loss(boxes1, boxes2) + [1.07500000298023224, 1.9333333373069763], dtype=dtype) + model = tf.keras.Sequential() + model.compile( + optimizer='adam', + loss=GIoULoss(reduction=tf.keras.losses.Reduction.NONE)) + loss = model.evaluate(boxes1, boxes2, batch_size=2, steps=1) self.assertAllCloseAccordingToType(loss, expected_result) From ec11713a8bd5365932e565509aca5c079a197284 Mon Sep 17 00:00:00 2001 From: fsx950223 Date: Wed, 13 Nov 2019 02:57:11 +0000 Subject: [PATCH 15/22] add one bbox test --- tensorflow_addons/losses/giou_loss.py | 1 + tensorflow_addons/losses/giou_loss_test.py | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/tensorflow_addons/losses/giou_loss.py b/tensorflow_addons/losses/giou_loss.py index 276156446c..6d413cad33 100644 --- a/tensorflow_addons/losses/giou_loss.py +++ b/tensorflow_addons/losses/giou_loss.py @@ -82,6 +82,7 @@ def giou_loss(y_true, y_pred, mode='giou'): Returns: GIoU loss float `Tensor`. """ + # if y_true or y_pred: if mode not in ['giou', 'iou']: raise ValueError("Value of mode should be 'iou' or 'giou'") y_pred = tf.convert_to_tensor(y_pred) diff --git a/tensorflow_addons/losses/giou_loss_test.py b/tensorflow_addons/losses/giou_loss_test.py index e52c1c2c08..e09e28edbe 100644 --- a/tensorflow_addons/losses/giou_loss_test.py +++ b/tensorflow_addons/losses/giou_loss_test.py @@ -61,6 +61,16 @@ def test_giou_loss(self, dtype): loss = giou_loss(boxes1, boxes2) self.assertAllCloseAccordingToType(loss, expected_result) + @parameterized.named_parameters(("float16", np.float16), + ("float32", np.float32), + ("float64", np.float64)) + def test_one_bbox(self, dtype): + boxes1 = tf.constant([4.0, 3.0, 7.0, 5.0], dtype=dtype) + boxes2 = tf.constant([3.0, 4.0, 6.0, 8.0], dtype=dtype) + expected_result = tf.constant(1.07500000298023224, dtype=dtype) + loss = giou_loss(boxes1, boxes2) + self.assertAllCloseAccordingToType(loss, expected_result) + @parameterized.named_parameters(("float16", np.float16), ("float32", np.float32), ("float64", np.float64)) From 8d4b3dd0b19d0374f238a0bd3996788da06b4eea Mon Sep 17 00:00:00 2001 From: fsx950223 Date: Wed, 13 Nov 2019 05:28:26 +0000 Subject: [PATCH 16/22] add different shapes test case --- tensorflow_addons/losses/giou_loss_test.py | 26 ++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/tensorflow_addons/losses/giou_loss_test.py b/tensorflow_addons/losses/giou_loss_test.py index e09e28edbe..b804e97549 100644 --- a/tensorflow_addons/losses/giou_loss_test.py +++ b/tensorflow_addons/losses/giou_loss_test.py @@ -61,6 +61,32 @@ def test_giou_loss(self, dtype): loss = giou_loss(boxes1, boxes2) self.assertAllCloseAccordingToType(loss, expected_result) + @parameterized.named_parameters(("float16", np.float16), + ("float32", np.float32), + ("float64", np.float64)) + def test_different_shapes(self, dtype): + boxes1 = tf.constant([[4.0, 3.0, 7.0, 5.0], [5.0, 6.0, 10.0, 7.0]], + dtype=dtype) + boxes2 = tf.constant([[3.0, 4.0, 6.0, 8.0]], + dtype=dtype) + tf.expand_dims(boxes1,-2) + tf.expand_dims(boxes2,0) + expected_result = tf.constant( + [1.07500000298023224, 1.366071], dtype=dtype) + loss = giou_loss(boxes1, boxes2) + self.assertAllCloseAccordingToType(loss, expected_result) + + boxes1 = tf.constant([[4.0, 3.0, 7.0, 5.0], [5.0, 6.0, 10.0, 7.0]], + dtype=dtype) + boxes2 = tf.constant([[3.0, 4.0, 6.0, 8.0]], + dtype=dtype) + tf.expand_dims(boxes1,0) + tf.expand_dims(boxes2,-2) + expected_result = tf.constant( + [1.07500000298023224, 1.366071], dtype=dtype) + loss = giou_loss(boxes1, boxes2) + self.assertAllCloseAccordingToType(loss, expected_result) + @parameterized.named_parameters(("float16", np.float16), ("float32", np.float32), ("float64", np.float64)) From 55f4d0b2a1dd0d4375c886f62e110ab68718048c Mon Sep 17 00:00:00 2001 From: fsx950223 Date: Wed, 13 Nov 2019 05:34:52 +0000 Subject: [PATCH 17/22] format code --- tensorflow_addons/losses/giou_loss.py | 10 ++++----- tensorflow_addons/losses/giou_loss_test.py | 26 ++++++++++------------ 2 files changed, 17 insertions(+), 19 deletions(-) diff --git a/tensorflow_addons/losses/giou_loss.py b/tensorflow_addons/losses/giou_loss.py index 6d413cad33..0225d93f09 100644 --- a/tensorflow_addons/losses/giou_loss.py +++ b/tensorflow_addons/losses/giou_loss.py @@ -72,10 +72,10 @@ def call(self, y_true, y_pred): def giou_loss(y_true, y_pred, mode='giou'): """ Args: - y_true: true targets tensor. The coordinates of the each bounding box in - boxes are encoded as [y_min, x_min, y_max, x_max]. - y_pred: predictions tensor. The coordinates of the each bounding box in - boxes are encoded as [y_min, x_min, y_max, x_max]. + y_true: true targets tensor. The coordinates of the each bounding + box in boxes are encoded as [y_min, x_min, y_max, x_max]. + y_pred: predictions tensor. The coordinates of the each bounding + box in boxes are encoded as [y_min, x_min, y_max, x_max]. mode: one of ['giou', 'iou'], decided to calculate giou loss or iou loss. @@ -98,7 +98,7 @@ def do_giou_calculate(b1, b2, mode='giou'): Args: b1: bounding box. The coordinates of the each bounding box in boxes are encoded as [y_min, x_min, y_max, x_max]. - b2: the other bounding box. The coordinates of the each bounding box + b2: the other bounding box. The coordinates of the each bounding box in boxes are encoded as [y_min, x_min, y_max, x_max]. mode: one of ['giou', 'iou'], decided to calculate giou loss or iou loss. diff --git a/tensorflow_addons/losses/giou_loss_test.py b/tensorflow_addons/losses/giou_loss_test.py index b804e97549..e950079fe5 100644 --- a/tensorflow_addons/losses/giou_loss_test.py +++ b/tensorflow_addons/losses/giou_loss_test.py @@ -62,28 +62,26 @@ def test_giou_loss(self, dtype): self.assertAllCloseAccordingToType(loss, expected_result) @parameterized.named_parameters(("float16", np.float16), - ("float32", np.float32), - ("float64", np.float64)) + ("float32", np.float32), + ("float64", np.float64)) def test_different_shapes(self, dtype): boxes1 = tf.constant([[4.0, 3.0, 7.0, 5.0], [5.0, 6.0, 10.0, 7.0]], dtype=dtype) - boxes2 = tf.constant([[3.0, 4.0, 6.0, 8.0]], - dtype=dtype) - tf.expand_dims(boxes1,-2) - tf.expand_dims(boxes2,0) - expected_result = tf.constant( - [1.07500000298023224, 1.366071], dtype=dtype) + boxes2 = tf.constant([[3.0, 4.0, 6.0, 8.0]], dtype=dtype) + tf.expand_dims(boxes1, -2) + tf.expand_dims(boxes2, 0) + expected_result = tf.constant([1.07500000298023224, 1.366071], + dtype=dtype) loss = giou_loss(boxes1, boxes2) self.assertAllCloseAccordingToType(loss, expected_result) boxes1 = tf.constant([[4.0, 3.0, 7.0, 5.0], [5.0, 6.0, 10.0, 7.0]], dtype=dtype) - boxes2 = tf.constant([[3.0, 4.0, 6.0, 8.0]], - dtype=dtype) - tf.expand_dims(boxes1,0) - tf.expand_dims(boxes2,-2) - expected_result = tf.constant( - [1.07500000298023224, 1.366071], dtype=dtype) + boxes2 = tf.constant([[3.0, 4.0, 6.0, 8.0]], dtype=dtype) + tf.expand_dims(boxes1, 0) + tf.expand_dims(boxes2, -2) + expected_result = tf.constant([1.07500000298023224, 1.366071], + dtype=dtype) loss = giou_loss(boxes1, boxes2) self.assertAllCloseAccordingToType(loss, expected_result) From f830058b94431f70f9d430386dc2877485ea31d1 Mon Sep 17 00:00:00 2001 From: fsx950223 Date: Sun, 17 Nov 2019 06:10:49 +0000 Subject: [PATCH 18/22] fix docs --- tensorflow_addons/losses/giou_loss.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/tensorflow_addons/losses/giou_loss.py b/tensorflow_addons/losses/giou_loss.py index 0225d93f09..0de33ea88c 100644 --- a/tensorflow_addons/losses/giou_loss.py +++ b/tensorflow_addons/losses/giou_loss.py @@ -26,8 +26,10 @@ class GIoULoss(tf.keras.losses.Loss): """Implements the GIoU loss function. GIoU loss was first introduced in the - [Generalized Intersection over Union paper](https://giou.stanford.edu/GIoU.pdf). - GIoU is a enhance for model which use IOU in object detection. + [Generalized Intersection over Union: + A Metric and A Loss for Bounding Box Regression] + (https://giou.stanford.edu/GIoU.pdf). + GIoU is a enhance for model which use IoU in object detection. Usage: @@ -35,18 +37,18 @@ class GIoULoss(tf.keras.losses.Loss): gl = tfa.losses.GIoU() boxes1 = tf.constant([[4.0, 3.0, 7.0, 5.0], [5.0, 6.0, 10.0, 7.0]]) boxes2 = tf.constant([[3.0, 4.0, 6.0, 8.0], [14.0, 14.0, 15.0, 15.0]]) - loss = gl(boxes1,boxes2) + loss = gl(boxes1, boxes2) print('Loss: ', loss.numpy()) # Loss: [1.07500000298023224, 1.9333333373069763] ``` Usage with tf.keras API: ```python model = tf.keras.Model(inputs, outputs) - model.compile('sgd', loss=tf.keras.losses.GIoULoss()) + model.compile('sgd', loss=tfa.losses.GIoULoss()) ``` Args: - mode: one of ['giou', 'iou'], decided to calculate giou loss or iou loss. + mode: one of ['giou', 'iou'], decided to calculate GIoU or IoU loss. """ def __init__(self, @@ -76,8 +78,7 @@ def giou_loss(y_true, y_pred, mode='giou'): box in boxes are encoded as [y_min, x_min, y_max, x_max]. y_pred: predictions tensor. The coordinates of the each bounding box in boxes are encoded as [y_min, x_min, y_max, x_max]. - mode: one of ['giou', 'iou'], - decided to calculate giou loss or iou loss. + mode: one of ['giou', 'iou'], decided to calculate GIoU or IoU loss. Returns: GIoU loss float `Tensor`. @@ -100,8 +101,7 @@ def do_giou_calculate(b1, b2, mode='giou'): encoded as [y_min, x_min, y_max, x_max]. b2: the other bounding box. The coordinates of the each bounding box in boxes are encoded as [y_min, x_min, y_max, x_max]. - mode: one of ['giou', 'iou'], - decided to calculate giou loss or iou loss. + mode: one of ['giou', 'iou'], decided to calculate GIoU or IoU loss. Returns: GIoU loss float `Tensor`. From e42ccd54d6331b593a224cbe05350f19ad289eab Mon Sep 17 00:00:00 2001 From: fsx950223 Date: Tue, 19 Nov 2019 11:28:38 +0000 Subject: [PATCH 19/22] make private --- tensorflow_addons/losses/giou_loss.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tensorflow_addons/losses/giou_loss.py b/tensorflow_addons/losses/giou_loss.py index 0de33ea88c..aca70e2268 100644 --- a/tensorflow_addons/losses/giou_loss.py +++ b/tensorflow_addons/losses/giou_loss.py @@ -83,18 +83,17 @@ def giou_loss(y_true, y_pred, mode='giou'): Returns: GIoU loss float `Tensor`. """ - # if y_true or y_pred: if mode not in ['giou', 'iou']: raise ValueError("Value of mode should be 'iou' or 'giou'") y_pred = tf.convert_to_tensor(y_pred) y_true = tf.cast(y_true, y_pred.dtype) - giou = do_giou_calculate(y_pred, y_true, mode) + giou = _calculate_giou(y_pred, y_true, mode) # compute the final loss and return return 1 - giou -def do_giou_calculate(b1, b2, mode='giou'): +def _calculate_giou(b1, b2, mode='giou'): """ Args: b1: bounding box. The coordinates of the each bounding box in boxes are From a03a320a48bb7890e4b77f9da8e4fc3a9caabcd6 Mon Sep 17 00:00:00 2001 From: fsx950223 Date: Wed, 20 Nov 2019 07:16:45 +0000 Subject: [PATCH 20/22] add interger test --- tensorflow_addons/losses/README.md | 2 +- tensorflow_addons/losses/giou_loss.py | 13 +++++++------ tensorflow_addons/losses/giou_loss_test.py | 12 +++++++++++- 3 files changed, 19 insertions(+), 8 deletions(-) diff --git a/tensorflow_addons/losses/README.md b/tensorflow_addons/losses/README.md index ec570a51a8..2b40ad2f5e 100644 --- a/tensorflow_addons/losses/README.md +++ b/tensorflow_addons/losses/README.md @@ -5,7 +5,7 @@ |:---------- |:----------- |:------------- | | contrastive | @WindQAQ | windqaq@gmail.com | | focal_loss | @SSaishruthi | saishruthi.tn@gmail.com | -| giou_loss | @who who who | fsx950223@gmail.com | +| giou_loss | @fsx950223 | fsx950223@gmail.com | | lifted | @rahulunair | rahulunair@gmail.com | | npairs | @WindQAQ | windqaq@gmail.com | | sparsemax_loss | @AndreasMadsen | amwwebdk+github@gmail.com | diff --git a/tensorflow_addons/losses/giou_loss.py b/tensorflow_addons/losses/giou_loss.py index aca70e2268..b7743ac596 100644 --- a/tensorflow_addons/losses/giou_loss.py +++ b/tensorflow_addons/losses/giou_loss.py @@ -29,7 +29,7 @@ class GIoULoss(tf.keras.losses.Loss): [Generalized Intersection over Union: A Metric and A Loss for Bounding Box Regression] (https://giou.stanford.edu/GIoU.pdf). - GIoU is a enhance for model which use IoU in object detection. + GIoU is an enhancement for models which use IoU in object detection. Usage: @@ -75,9 +75,9 @@ def giou_loss(y_true, y_pred, mode='giou'): """ Args: y_true: true targets tensor. The coordinates of the each bounding - box in boxes are encoded as [y_min, x_min, y_max, x_max]. + box in boxes are encoded as [y_min, x_min, y_max, x_max]. y_pred: predictions tensor. The coordinates of the each bounding - box in boxes are encoded as [y_min, x_min, y_max, x_max]. + box in boxes are encoded as [y_min, x_min, y_max, x_max]. mode: one of ['giou', 'iou'], decided to calculate GIoU or IoU loss. Returns: @@ -86,10 +86,11 @@ def giou_loss(y_true, y_pred, mode='giou'): if mode not in ['giou', 'iou']: raise ValueError("Value of mode should be 'iou' or 'giou'") y_pred = tf.convert_to_tensor(y_pred) + if y_pred.dtype.is_floating is not True: + y_pred=tf.cast(y_pred,tf.float32) y_true = tf.cast(y_true, y_pred.dtype) giou = _calculate_giou(y_pred, y_true, mode) - # compute the final loss and return return 1 - giou @@ -97,9 +98,9 @@ def _calculate_giou(b1, b2, mode='giou'): """ Args: b1: bounding box. The coordinates of the each bounding box in boxes are - encoded as [y_min, x_min, y_max, x_max]. + encoded as [y_min, x_min, y_max, x_max]. b2: the other bounding box. The coordinates of the each bounding box - in boxes are encoded as [y_min, x_min, y_max, x_max]. + in boxes are encoded as [y_min, x_min, y_max, x_max]. mode: one of ['giou', 'iou'], decided to calculate GIoU or IoU loss. Returns: diff --git a/tensorflow_addons/losses/giou_loss_test.py b/tensorflow_addons/losses/giou_loss_test.py index e950079fe5..129d6daf97 100644 --- a/tensorflow_addons/losses/giou_loss_test.py +++ b/tensorflow_addons/losses/giou_loss_test.py @@ -44,7 +44,7 @@ def test_iou(self, dtype): dtype=dtype) boxes2 = tf.constant([[3.0, 4.0, 6.0, 8.0], [14.0, 14.0, 15.0, 15.0]], dtype=dtype) - expected_result = tf.constant([14.0 / 16.0, 1.], dtype=dtype) + expected_result = tf.constant([0.875, 1.], dtype=dtype) loss = giou_loss(boxes1, boxes2, mode='iou') self.assertAllCloseAccordingToType(loss, expected_result) @@ -61,6 +61,16 @@ def test_giou_loss(self, dtype): loss = giou_loss(boxes1, boxes2) self.assertAllCloseAccordingToType(loss, expected_result) + def test_with_integer(self): + boxes1 = tf.constant([[4, 3, 7, 5], [5, 6, 10, 7]], + dtype=tf.int32) + boxes2 = tf.constant([[3, 4, 6, 8], [14, 14, 15, 15]], + dtype=tf.int32) + expected_result = tf.constant( + [1.07500000298023224, 1.9333333373069763], dtype=tf.float32) + loss = giou_loss(boxes1, boxes2) + self.assertAllCloseAccordingToType(loss, expected_result) + @parameterized.named_parameters(("float16", np.float16), ("float32", np.float32), ("float64", np.float64)) From 4b915d1b63ba6c7dcffd168bbba87ce5d7744abc Mon Sep 17 00:00:00 2001 From: fsx950223 Date: Wed, 20 Nov 2019 07:17:55 +0000 Subject: [PATCH 21/22] format code --- tensorflow_addons/losses/giou_loss.py | 2 +- tensorflow_addons/losses/giou_loss_test.py | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/tensorflow_addons/losses/giou_loss.py b/tensorflow_addons/losses/giou_loss.py index b7743ac596..d04fc42037 100644 --- a/tensorflow_addons/losses/giou_loss.py +++ b/tensorflow_addons/losses/giou_loss.py @@ -87,7 +87,7 @@ def giou_loss(y_true, y_pred, mode='giou'): raise ValueError("Value of mode should be 'iou' or 'giou'") y_pred = tf.convert_to_tensor(y_pred) if y_pred.dtype.is_floating is not True: - y_pred=tf.cast(y_pred,tf.float32) + y_pred = tf.cast(y_pred, tf.float32) y_true = tf.cast(y_true, y_pred.dtype) giou = _calculate_giou(y_pred, y_true, mode) diff --git a/tensorflow_addons/losses/giou_loss_test.py b/tensorflow_addons/losses/giou_loss_test.py index 129d6daf97..4070d526b0 100644 --- a/tensorflow_addons/losses/giou_loss_test.py +++ b/tensorflow_addons/losses/giou_loss_test.py @@ -62,10 +62,8 @@ def test_giou_loss(self, dtype): self.assertAllCloseAccordingToType(loss, expected_result) def test_with_integer(self): - boxes1 = tf.constant([[4, 3, 7, 5], [5, 6, 10, 7]], - dtype=tf.int32) - boxes2 = tf.constant([[3, 4, 6, 8], [14, 14, 15, 15]], - dtype=tf.int32) + boxes1 = tf.constant([[4, 3, 7, 5], [5, 6, 10, 7]], dtype=tf.int32) + boxes2 = tf.constant([[3, 4, 6, 8], [14, 14, 15, 15]], dtype=tf.int32) expected_result = tf.constant( [1.07500000298023224, 1.9333333373069763], dtype=tf.float32) loss = giou_loss(boxes1, boxes2) From f8ae33c5a1450ea4eca5ed3bbeddf35db76f34ee Mon Sep 17 00:00:00 2001 From: fsx950223 Date: Wed, 20 Nov 2019 09:35:32 +0000 Subject: [PATCH 22/22] change expression --- tensorflow_addons/losses/giou_loss.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tensorflow_addons/losses/giou_loss.py b/tensorflow_addons/losses/giou_loss.py index d04fc42037..e864528ec2 100644 --- a/tensorflow_addons/losses/giou_loss.py +++ b/tensorflow_addons/losses/giou_loss.py @@ -86,7 +86,7 @@ def giou_loss(y_true, y_pred, mode='giou'): if mode not in ['giou', 'iou']: raise ValueError("Value of mode should be 'iou' or 'giou'") y_pred = tf.convert_to_tensor(y_pred) - if y_pred.dtype.is_floating is not True: + if not y_pred.dtype.is_floating: y_pred = tf.cast(y_pred, tf.float32) y_true = tf.cast(y_true, y_pred.dtype) giou = _calculate_giou(y_pred, y_true, mode)