From ea13abd33e60ba1c2c793905e690b91831efe949 Mon Sep 17 00:00:00 2001 From: yangguohao <1901212980@pku.edu.cn> Date: Sun, 13 Mar 2022 01:03:22 +0800 Subject: [PATCH 01/32] 'triplet_margin_loss' --- .../unittests/test_triplet_margin_loss.py | 193 ++++++++++++++++++ python/paddle/nn/__init__.py | 2 + python/paddle/nn/functional/__init__.py | 2 + python/paddle/nn/functional/loss.py | 99 +++++++++ python/paddle/nn/layer/__init__.py | 1 + python/paddle/nn/layer/loss.py | 79 +++++++ 6 files changed, 376 insertions(+) create mode 100644 python/paddle/fluid/tests/unittests/test_triplet_margin_loss.py diff --git a/python/paddle/fluid/tests/unittests/test_triplet_margin_loss.py b/python/paddle/fluid/tests/unittests/test_triplet_margin_loss.py new file mode 100644 index 0000000000000..6c4b00bf3059d --- /dev/null +++ b/python/paddle/fluid/tests/unittests/test_triplet_margin_loss.py @@ -0,0 +1,193 @@ +# Copyright (c) 2020 PaddlePaddle 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. + +import paddle +import paddle.fluid as fluid +import numpy as np +import unittest + + + +def call_TripletMaginLoss_layer(input, + positive, + negative, + p = 2, + margin=0.3, + swap=False, + eps = 1e-6, + reduction='mean',): + triplet_margin_loss = paddle.nn.TripletMarginLoss(p=p,eps=eps, + margin=margin,swap=swap,reduction=reduction) + res = triplet_margin_loss(input=input,positive=positive,negative=negative,) + return res + + +def call_TripletMaginLoss_functional(input, + positive, + negative, + p = 2, + margin=0.3, + swap=False, + eps = 1e-6, + reduction='mean',): + res = paddle.nn.functional.triplet_margin_loss( + input=input,positive=positive,negative=negative,p=p,eps=eps, + margin=margin,swap=swap,reduction=reduction) + return res + + +def test_static(place, + input_np, + positive_np, + negative_np, + p=2, + margin=0.3, + swap=False, + eps=1e-6, + reduction='mean', + functional=False): + paddle.enable_static() + prog = paddle.static.Program() + startup_prog = paddle.static.Program() + with paddle.static.program_guard(prog, startup_prog): + input = paddle.fluid.data( + name='input', shape=input_np.shape, dtype='float64') + positive = paddle.fluid.data( + name='positive', shape=positive_np.shape, dtype='float64') + negative = paddle.fluid.data( + name='negative', shape=negative_np.shape, dtype='float64') + feed_dict = {"input": input_np, "positive": positive_np, "negative":negative_np} + + + if functional: + res = call_TripletMaginLoss_functional(input=input,positive=positive,negative=negative,p=p,eps=eps, + margin=margin,swap=swap,reduction=reduction) + else: + res = call_TripletMaginLoss_layer(input=input,positive=positive,negative=negative,p=p,eps=eps, + margin=margin,swap=swap,reduction=reduction) + + exe = paddle.static.Executor(place) + static_result = exe.run(prog, feed=feed_dict, fetch_list=[res]) + return static_result + +def test_dygraph(place, + input, + positive, + negative, + p=2, + margin=0.3, + swap=False, + eps=1e-6, + reduction='mean', + functional=False): + paddle.disable_static() + input = paddle.to_tensor(input) + positive = paddle.to_tensor(positive) + negative = paddle.to_tensor(negative) + + if functional: + dy_res = call_TripletMaginLoss_functional(input=input,positive=positive,negative=negative,p=p,eps=eps, + margin=margin,swap=swap,reduction=reduction) + else: + dy_res = call_TripletMaginLoss_layer(input=input,positive=positive,negative=negative,p=p,eps=eps, + margin=margin,swap=swap,reduction=reduction) + dy_result = dy_res.numpy() + paddle.enable_static() + return dy_result + + +def calc_triplet_margin_loss(input, + positive, + negative, + p=2, + margin=0.3, + swap=False, + reduction='mean',): + positive_dist = np.linalg.norm((input - positive), p, axis=1) + negative_dist = np.linalg.norm((input - negative), p, axis=1) + + if swap: + swap_dist = np.linalg.norm((positive - negative), p, axis=1) + negative_dist = np.minimum(negative_dist, swap_dist) + expected = np.maximum(positive_dist - negative_dist + margin, 0) + + if reduction == 'mean': + expected = np.mean(expected) + elif reduction == 'sum': + expected = np.sum(expected) + else: + expected = expected + + return expected + + +class TestTripletMarginLoss(unittest.TestCase): + def test_TripletMarginLoss(self): + input = np.random.uniform(0.1, 0.8, size=(20, 30)).astype(np.float64) + positive = np.random.randint(0, 2, size=(20, 30)).astype(np.float64) + negative = np.random.randint(0, 2, size=(20, 30)).astype(np.float64) + + places = [fluid.CPUPlace()] + if fluid.core.is_compiled_with_cuda(): + places.append(fluid.CUDAPlace(0)) + reductions = ['sum', 'mean', 'none'] + for place in places: + for reduction in reductions: + expected = calc_triplet_margin_loss(input=input, positive=positive, negative=negative, + reduction=reduction) + + dy_result = test_dygraph(place=place, + input=input, positive=positive, negative=negative, + reduction=reduction,) + + static_result = test_static(place=place, + input_np=input, positive_np=positive, negative_np=negative, + reduction=reduction,) + self.assertTrue(np.allclose(static_result, expected)) + self.assertTrue(np.allclose(static_result, dy_result)) + self.assertTrue(np.allclose(dy_result, expected)) + static_functional = test_static(place=place, + input_np=input, positive_np=positive, negative_np=negative, + reduction=reduction, + functional=True) + dy_functional = test_dygraph( + place=place, + input=input, positive=positive, negative=negative, + reduction=reduction, + functional=True) + self.assertTrue(np.allclose(static_functional, expected)) + self.assertTrue(np.allclose(static_functional, dy_functional)) + self.assertTrue(np.allclose(dy_functional, expected)) + + def test_TripletMarginLoss_error(self): + paddle.disable_static() + self.assertRaises( + ValueError, + paddle.nn.TripletMarginLoss, + reduction="unsupport reduction") + input = paddle.to_tensor([[0.1, 0.3]], dtype='float32') + positive = paddle.to_tensor([[0.0, 1.0]], dtype='float32') + negative = paddle.to_tensor([[0.2, 0.1]], dtype='float32') + self.assertRaises( + ValueError, + paddle.nn.functional.triplet_margin_loss, + input=input, + positive=positive, + negative=negative, + reduction="unsupport reduction") + paddle.enable_static() + + +if __name__ == "__main__": + unittest.main() diff --git a/python/paddle/nn/__init__.py b/python/paddle/nn/__init__.py index b83a900059bf4..4bb6514101b04 100644 --- a/python/paddle/nn/__init__.py +++ b/python/paddle/nn/__init__.py @@ -105,6 +105,7 @@ from .layer.loss import CTCLoss # noqa: F401 from .layer.loss import SmoothL1Loss # noqa: F401 from .layer.loss import HingeEmbeddingLoss # noqa: F401 +from .layer.loss import TripletMarginLoss from .layer.norm import BatchNorm # noqa: F401 from .layer.norm import SyncBatchNorm # noqa: F401 from .layer.norm import GroupNorm # noqa: F401 @@ -307,4 +308,5 @@ def weight_norm(*args): 'MaxUnPool3D', 'HingeEmbeddingLoss', 'Identity', + 'TripletMarginLoss', ] diff --git a/python/paddle/nn/functional/__init__.py b/python/paddle/nn/functional/__init__.py index a24afc45a5995..941bdf59bb399 100644 --- a/python/paddle/nn/functional/__init__.py +++ b/python/paddle/nn/functional/__init__.py @@ -89,6 +89,7 @@ from .loss import square_error_cost # noqa: F401 from .loss import ctc_loss # noqa: F401 from .loss import hinge_embedding_loss # noqa: F401 +from .loss import triplet_margin_loss from .norm import batch_norm # noqa: F401 from .norm import instance_norm # noqa: F401 from .norm import layer_norm # noqa: F401 @@ -224,4 +225,5 @@ 'class_center_sample', 'sparse_attention', 'fold', + 'triplet_margin_loss' ] diff --git a/python/paddle/nn/functional/loss.py b/python/paddle/nn/functional/loss.py index e7763853bf7c2..38cb532fbb635 100755 --- a/python/paddle/nn/functional/loss.py +++ b/python/paddle/nn/functional/loss.py @@ -2167,3 +2167,102 @@ def hinge_embedding_loss(input, label, margin=1.0, reduction='mean', name=None): return paddle.sum(loss, name=name) elif reduction == 'none': return loss + + +def triplet_margin_loss(input,positive,negative, + swap=False, p=2, eps=1e-6, + margin=1.0, reduction='mean', + name=None): + """ + Creates a criterion that measures the triplet loss given an input + tensors :math:`x1`, :math:`x2`, :math:`x3` and a margin with a value greater than :math:`0`. + This is used for measuring a relative similarity between samples. A triplet + is composed by `input`, `positive` and `negative` (i.e., `input`, `positive examples` and `negative + examples` respectively). The shapes of all input tensors should be + :math:`(N, D)`. + + The distance swap is described in detail in the paper `Learning shallow + convolutional feature descriptors with triplet losses`_ by + V. Balntas, E. Riba et al. + + The loss function for each sample in the mini-batch is: + + .. math:: + L(input, pos, neg) = \max \{d(input_i, pos_i) - d(input_i, neg_i) + {\rm margin}, 0\} + + + where + + .. math:: + d(x_i, y_i) = \left\lVert {\bf x}_i - {\bf y}_i \right\rVert_p + + :param input:Input tensor, the data type is float32 or float64. + the shape is [N, \*], N is batch size and `\*` means any number of additional dimensions, available dtype is float32, float64. + :param positive:Positive tensor containing 1 or -1, the data type is float32 or float64. + The shape of label is the same as the shape of input. + :param negative:Negative tensor containing 1 or -1, the data type is float32 or float64. + The shape of label is the same as the shape of input. + :param swap:The distance swap is described in detail in the paperT + `Learning shallow convolutional feature descriptors with triplet losses` by + V. Balntas, E. Riba et al. Default: ``False``. + :param p:The norm degree for pairwise distance. Default: :math:`2`. + :param margin:Default: :math:`1`. + :param reduction:Indicate how to average the loss by batch_size. + the candicates are ``'none'`` | ``'mean'`` | ``'sum'``. + If :attr:`reduction` is ``'none'``, the unreduced loss is returned; + If :attr:`reduction` is ``'mean'``, the reduced mean loss is returned; + If :attr:`reduction` is ``'sum'``, the summed loss is returned. + Default: ``'mean'`` + :return:Tensor. The tensor variable storing the triplet_margin_loss of input and positive and negative. + + Examples: + .. code-block:: python + + import paddle + import paddle.nn.functional as F + + input = paddle.to_tensor([[1, 5, 3], [0, 3, 2], [1, 4, 1]], dtype=paddle.float32) + positive= paddle.to_tensor([[5, 1, 2], [3, 2, 1], [3, -1, 1]], dtype=paddle.float32) + negative = paddle.to_tensor([[2, 1, -3], [1, 1, -1], [4, -2, 1]], dtype=paddle.float32) + loss = F.triplet_margin_loss(input, positive, negative, margin=1.0, reduction='none') + print(loss) + # Tensor([0. , 0.57496738, 0. ]) + + + loss = F.triplet_margin_loss(input, positive, negative, margin=1.0, reduction='mean') + print(loss) + # Tensor([0.19165580]) + + """ + if reduction not in ['sum', 'mean', 'none']: + raise ValueError( + "'reduction' in 'triplet_margin_loss' should be 'sum', 'mean' or 'none', " + "but received {}.".format(reduction)) + if margin<0: + raise ValueError( + "margin should not smaller than 0" + ) + if not in_dynamic_mode(): + check_variable_and_dtype(input, 'input', ['float32', 'float64'], + 'triplet_margin_loss') + check_variable_and_dtype(positive, 'positive', ['float32', 'float64'], + 'triplet_margin_loss') + check_variable_and_dtype(negative, 'negative', ['float32', 'float64'], + 'triplet_margin_loss') + + distance_function = paddle.nn.PairwiseDistance(p, epsilon=eps) + positive_dist = distance_function(input, positive) + negative_dist = distance_function(input, negative) + + if swap: + swap_dist = distance_function(positive, negative) + negative_dist = paddle.minimum(negative_dist, swap_dist) + + loss = paddle.clip(positive_dist-negative_dist+margin, min=0.0) + + if reduction == 'mean': + return paddle.mean(loss, name=name) + elif reduction == 'sum': + return paddle.sum(loss, name=name) + elif reduction == 'none': + return loss diff --git a/python/paddle/nn/layer/__init__.py b/python/paddle/nn/layer/__init__.py index 2b50508065605..94887b1b9fc72 100644 --- a/python/paddle/nn/layer/__init__.py +++ b/python/paddle/nn/layer/__init__.py @@ -77,6 +77,7 @@ from .loss import CTCLoss # noqa: F401 from .loss import SmoothL1Loss # noqa: F401 from .loss import HingeEmbeddingLoss # noqa: F401 +from .loss import TripletMarginLoss from .norm import BatchNorm1D # noqa: F401 from .norm import BatchNorm2D # noqa: F401 from .norm import BatchNorm3D # noqa: F401 diff --git a/python/paddle/nn/layer/loss.py b/python/paddle/nn/layer/loss.py index 7e40c029a02ec..8bd14f9f31bf1 100644 --- a/python/paddle/nn/layer/loss.py +++ b/python/paddle/nn/layer/loss.py @@ -1298,3 +1298,82 @@ def forward(self, input, label): reduction=self.reduction, margin=self.margin, name=self.name) + + +class TripletMarginLoss(Layer): + """ + Creates a criterion that measures the triplet loss given an input + tensors :math:`x1`, :math:`x2`, :math:`x3` and a margin with a value greater than :math:`0`. + This is used for measuring a relative similarity between samples. A triplet + is composed by `input`, `positive` and `negative` (i.e., `input`, `positive examples` and `negative + examples` respectively). The shapes of all input tensors should be + :math:`(N, D)`. + + The distance swap is described in detail in the paper `Learning shallow + convolutional feature descriptors with triplet losses`_ by + V. Balntas, E. Riba et al. + + The loss function for each sample in the mini-batch is: + + .. math:: + L(input, pos, neg) = \max \{d(input_i, pos_i) - d(input_i, neg_i) + {\rm margin}, 0\} + + + where + + .. math:: + d(x_i, y_i) = \left\lVert {\bf x}_i - {\bf y}_i \right\rVert_p + + :param input:Input tensor, the data type is float32 or float64. + the shape is [N, \*], N is batch size and `\*` means any number of additional dimensions, available dtype is float32, float64. + :param positive:Positive tensor containing 1 or -1, the data type is float32 or float64. + The shape of label is the same as the shape of input. + :param negative:Negative tensor containing 1 or -1, the data type is float32 or float64. + The shape of label is the same as the shape of input. + :param swap:The distance swap is described in detail in the paperT + `Learning shallow convolutional feature descriptors with triplet losses` by + V. Balntas, E. Riba et al. Default: ``False``. + :param p:The norm degree for pairwise distance. Default: :math:`2`. + :param margin:Default: :math:`1`. + :param reduction:Indicate how to average the loss by batch_size. + the candicates are ``'none'`` | ``'mean'`` | ``'sum'``. + If :attr:`reduction` is ``'none'``, the unreduced loss is returned; + If :attr:`reduction` is ``'mean'``, the reduced mean loss is returned; + If :attr:`reduction` is ``'sum'``, the summed loss is returned. + Default: ``'mean'`` + :return:Tensor. The tensor variable storing the triplet_margin_loss of input and positive and negative. + + Examples: + .. code-block:: python + + import paddle + import paddle.nn.functional as F + + input = paddle.to_tensor([[1, 5, 3], [0, 3, 2], [1, 4, 1]], dtype=paddle.float32) + positive= paddle.to_tensor([[5, 1, 2], [3, 2, 1], [3, -1, 1]], dtype=paddle.float32) + negative = paddle.to_tensor([[2, 1, -3], [1, 1, -1], [4, -2, 1]], dtype=paddle.float32) + loss = F.triplet_margin_loss(input, positive, negative, margin=1.0, reduction='none') + print(loss) + # Tensor([0. , 0.57496738, 0. ]) + + + loss = F.triplet_margin_loss(input, positive, negative, margin=1.0, reduction='mean') + print(loss) + # Tensor([0.19165580]) + + """ + def __init__(self, margin: float = 1.0, p: float = 2., eps: float = 1e-6, swap: bool = False,reduction: str = 'mean'): + super(TripletMarginLoss, self).__init__() + if reduction not in ['sum', 'mean', 'none']: + raise ValueError( + "The value of 'reduction' in bce_loss should be 'sum', 'mean' or 'none', but " + "received %s, which is not allowed." % reduction) + self.margin = margin + self.p = p + self.eps = eps + self.swap = swap + self.reduction = reduction + + def forward(self, input, positive, negative): + return F.triplet_margin_loss(input, positive, negative, margin=self.margin, p=self.p, + eps=self.eps, swap=self.swap, reduction=self.reduction) From 352ec1316f204463f7e9183f1c4cf7cf197c714d Mon Sep 17 00:00:00 2001 From: yangguohao <1901212980@pku.edu.cn> Date: Tue, 15 Mar 2022 23:33:51 +0800 Subject: [PATCH 02/32] 'test_file_corret' --- .../tests/unittests/test_triplet_margin_loss.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/python/paddle/fluid/tests/unittests/test_triplet_margin_loss.py b/python/paddle/fluid/tests/unittests/test_triplet_margin_loss.py index 6c4b00bf3059d..b6287394edb84 100644 --- a/python/paddle/fluid/tests/unittests/test_triplet_margin_loss.py +++ b/python/paddle/fluid/tests/unittests/test_triplet_margin_loss.py @@ -19,7 +19,7 @@ -def call_TripletMaginLoss_layer(input, +def call_TripletMarginLoss_layer(input, positive, negative, p = 2, @@ -33,7 +33,7 @@ def call_TripletMaginLoss_layer(input, return res -def call_TripletMaginLoss_functional(input, +def call_TripletMarginLoss_functional(input, positive, negative, p = 2, @@ -71,10 +71,10 @@ def test_static(place, if functional: - res = call_TripletMaginLoss_functional(input=input,positive=positive,negative=negative,p=p,eps=eps, + res = call_TripletMarginLoss_functional(input=input,positive=positive,negative=negative,p=p,eps=eps, margin=margin,swap=swap,reduction=reduction) else: - res = call_TripletMaginLoss_layer(input=input,positive=positive,negative=negative,p=p,eps=eps, + res = call_TripletMarginLoss_layer(input=input,positive=positive,negative=negative,p=p,eps=eps, margin=margin,swap=swap,reduction=reduction) exe = paddle.static.Executor(place) @@ -97,10 +97,10 @@ def test_dygraph(place, negative = paddle.to_tensor(negative) if functional: - dy_res = call_TripletMaginLoss_functional(input=input,positive=positive,negative=negative,p=p,eps=eps, + dy_res = call_TripletMarginLoss_functional(input=input,positive=positive,negative=negative,p=p,eps=eps, margin=margin,swap=swap,reduction=reduction) else: - dy_res = call_TripletMaginLoss_layer(input=input,positive=positive,negative=negative,p=p,eps=eps, + dy_res = call_TripletMarginLoss_layer(input=input,positive=positive,negative=negative,p=p,eps=eps, margin=margin,swap=swap,reduction=reduction) dy_result = dy_res.numpy() paddle.enable_static() From e2117ab7f1da622c32fe6c92182ec962ccf73b33 Mon Sep 17 00:00:00 2001 From: yangguohao <1901212980@pku.edu.cn> Date: Sun, 27 Mar 2022 01:29:03 +0800 Subject: [PATCH 03/32] '2022_03_27' --- .../unittests/test_triplet_margin_loss.py | 20 +++++++++++++++++++ python/paddle/nn/functional/loss.py | 10 ++++++++++ 2 files changed, 30 insertions(+) diff --git a/python/paddle/fluid/tests/unittests/test_triplet_margin_loss.py b/python/paddle/fluid/tests/unittests/test_triplet_margin_loss.py index b6287394edb84..e285f6a31bfcb 100644 --- a/python/paddle/fluid/tests/unittests/test_triplet_margin_loss.py +++ b/python/paddle/fluid/tests/unittests/test_triplet_margin_loss.py @@ -188,6 +188,26 @@ def test_TripletMarginLoss_error(self): reduction="unsupport reduction") paddle.enable_static() + def test_TripletMarginLoss_dimension(self): + paddle.disable_static() + + input = paddle.to_tensor([[0.1, 0.3],[1, 2]], dtype='float32') + positive = paddle.to_tensor([[0.0, 1.0]], dtype='float32') + negative = paddle.to_tensor([[0.2, 0.1]], dtype='float32') + self.assertRaises( + ValueError, + paddle.nn.functional.triplet_margin_loss, + input=input, + positive=positive, + negative=negative,) + TMLoss = paddle.nn.TripletMarginLoss() + self.assertRaises( + ValueError, + TMLoss, + input=input, + positive=positive, + negative=negative,) + paddle.enable_static() if __name__ == "__main__": unittest.main() diff --git a/python/paddle/nn/functional/loss.py b/python/paddle/nn/functional/loss.py index 38cb532fbb635..914dea7dc7c1e 100755 --- a/python/paddle/nn/functional/loss.py +++ b/python/paddle/nn/functional/loss.py @@ -2250,6 +2250,16 @@ def triplet_margin_loss(input,positive,negative, check_variable_and_dtype(negative, 'negative', ['float32', 'float64'], 'triplet_margin_loss') + # reshape to [batch_size, N] + input = input.flatten(start_axis=1,stop_axis=-1) + positive = positive.flatten(start_axis=1,stop_axis=-1) + negative = negative.flatten(start_axis=1,stop_axis=-1) + if not(input.shape==positive.shape==negative.shape): + raise ValueError( + "input's shape must equal to " + "positive's shape and " + "negative's shape") + distance_function = paddle.nn.PairwiseDistance(p, epsilon=eps) positive_dist = distance_function(input, positive) negative_dist = distance_function(input, negative) From 4a76c1ca38cbcef4751fa74c4ac7218b76df3056 Mon Sep 17 00:00:00 2001 From: yangguohao <1901212980@pku.edu.cn> Date: Tue, 5 Apr 2022 00:12:22 +0800 Subject: [PATCH 04/32] 2022_04_05 --- python/paddle/nn/functional/loss.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/python/paddle/nn/functional/loss.py b/python/paddle/nn/functional/loss.py index 914dea7dc7c1e..b6c1a72f2e323 100755 --- a/python/paddle/nn/functional/loss.py +++ b/python/paddle/nn/functional/loss.py @@ -37,7 +37,7 @@ from paddle import _C_ops from paddle import in_dynamic_mode from paddle.framework import core -from ...fluid.framework import _in_legacy_dygraph, in_dygraph_mode +from ...fluid.framework import _in_legacy_dygraph, in_dygraph_mode,_non_static_mode __all__ = [] @@ -2242,7 +2242,7 @@ def triplet_margin_loss(input,positive,negative, raise ValueError( "margin should not smaller than 0" ) - if not in_dynamic_mode(): + if _non_static_mode(): check_variable_and_dtype(input, 'input', ['float32', 'float64'], 'triplet_margin_loss') check_variable_and_dtype(positive, 'positive', ['float32', 'float64'], From 30c9c74c6751d5519e42232010892216982fd5e4 Mon Sep 17 00:00:00 2001 From: yangguohao <1901212980@pku.edu.cn> Date: Sun, 17 Apr 2022 15:03:40 +0800 Subject: [PATCH 05/32] 2022-04-17_1 --- python/paddle/fluid/tests/unittests/test_triplet_margin_loss.py | 1 + 1 file changed, 1 insertion(+) diff --git a/python/paddle/fluid/tests/unittests/test_triplet_margin_loss.py b/python/paddle/fluid/tests/unittests/test_triplet_margin_loss.py index e285f6a31bfcb..fe23145124e0f 100644 --- a/python/paddle/fluid/tests/unittests/test_triplet_margin_loss.py +++ b/python/paddle/fluid/tests/unittests/test_triplet_margin_loss.py @@ -79,6 +79,7 @@ def test_static(place, exe = paddle.static.Executor(place) static_result = exe.run(prog, feed=feed_dict, fetch_list=[res]) + paddle.disable_static() return static_result def test_dygraph(place, From 0a413119cbf3b05bfc7d34ba1947c5c1fe1c2c5b Mon Sep 17 00:00:00 2001 From: yangguohao <1901212980@pku.edu.cn> Date: Sun, 17 Apr 2022 15:39:46 +0800 Subject: [PATCH 06/32] 2022-04-17 --- python/paddle/fluid/tests/unittests/test_triplet_margin_loss.py | 1 - 1 file changed, 1 deletion(-) diff --git a/python/paddle/fluid/tests/unittests/test_triplet_margin_loss.py b/python/paddle/fluid/tests/unittests/test_triplet_margin_loss.py index fe23145124e0f..e285f6a31bfcb 100644 --- a/python/paddle/fluid/tests/unittests/test_triplet_margin_loss.py +++ b/python/paddle/fluid/tests/unittests/test_triplet_margin_loss.py @@ -79,7 +79,6 @@ def test_static(place, exe = paddle.static.Executor(place) static_result = exe.run(prog, feed=feed_dict, fetch_list=[res]) - paddle.disable_static() return static_result def test_dygraph(place, From cba84700dd943f051a5973cc44fea0df587b0abb Mon Sep 17 00:00:00 2001 From: yangguohao <1901212980@pku.edu.cn> Date: Sun, 17 Apr 2022 16:31:31 +0800 Subject: [PATCH 07/32] 2022-04-17_2 --- .../unittests/test_triplet_margin_loss.py | 75 +++++++++++++------ python/paddle/nn/functional/__init__.py | 2 +- python/paddle/nn/functional/loss.py | 11 ++- python/paddle/nn/layer/loss.py | 23 ++++-- 4 files changed, 79 insertions(+), 32 deletions(-) diff --git a/python/paddle/fluid/tests/unittests/test_triplet_margin_loss.py b/python/paddle/fluid/tests/unittests/test_triplet_margin_loss.py index e285f6a31bfcb..0f01dcc584802 100644 --- a/python/paddle/fluid/tests/unittests/test_triplet_margin_loss.py +++ b/python/paddle/fluid/tests/unittests/test_triplet_margin_loss.py @@ -27,23 +27,33 @@ def call_TripletMarginLoss_layer(input, swap=False, eps = 1e-6, reduction='mean',): - triplet_margin_loss = paddle.nn.TripletMarginLoss(p=p,eps=eps, - margin=margin,swap=swap,reduction=reduction) - res = triplet_margin_loss(input=input,positive=positive,negative=negative,) + triplet_margin_loss = paddle.nn.loss.TripletMarginLoss(p=p, + eps=eps, + margin=margin, + swap=swap, + reduction=reduction) + res = triplet_margin_loss(input=input, + positive=positive, + negative=negative,) return res def call_TripletMarginLoss_functional(input, positive, negative, - p = 2, + p=2, margin=0.3, swap=False, - eps = 1e-6, + eps=1e-6, reduction='mean',): - res = paddle.nn.functional.triplet_margin_loss( - input=input,positive=positive,negative=negative,p=p,eps=eps, - margin=margin,swap=swap,reduction=reduction) + res = paddle.nn.functional.triplet_margin_loss(input=input, + positive=positive, + negative=negative, + p=p, + eps=eps, + margin=margin, + swap=swap, + reduction=reduction) return res @@ -57,7 +67,7 @@ def test_static(place, eps=1e-6, reduction='mean', functional=False): - paddle.enable_static() + prog = paddle.static.Program() startup_prog = paddle.static.Program() with paddle.static.program_guard(prog, startup_prog): @@ -67,15 +77,26 @@ def test_static(place, name='positive', shape=positive_np.shape, dtype='float64') negative = paddle.fluid.data( name='negative', shape=negative_np.shape, dtype='float64') - feed_dict = {"input": input_np, "positive": positive_np, "negative":negative_np} - + feed_dict = {"input": input_np, "positive": positive_np, "negative": negative_np} if functional: - res = call_TripletMarginLoss_functional(input=input,positive=positive,negative=negative,p=p,eps=eps, - margin=margin,swap=swap,reduction=reduction) + res = call_TripletMarginLoss_functional(input=input, + positive=positive, + negative=negative, + p=p, + eps=eps, + margin=margin, + swap=swap, + reduction=reduction) else: - res = call_TripletMarginLoss_layer(input=input,positive=positive,negative=negative,p=p,eps=eps, - margin=margin,swap=swap,reduction=reduction) + res = call_TripletMarginLoss_layer(input=input, + positive=positive, + negative=negative, + p=p, + eps=eps, + margin=margin, + swap=swap, + reduction=reduction) exe = paddle.static.Executor(place) static_result = exe.run(prog, feed=feed_dict, fetch_list=[res]) @@ -97,11 +118,23 @@ def test_dygraph(place, negative = paddle.to_tensor(negative) if functional: - dy_res = call_TripletMarginLoss_functional(input=input,positive=positive,negative=negative,p=p,eps=eps, - margin=margin,swap=swap,reduction=reduction) + dy_res = call_TripletMarginLoss_functional(input=input, + positive=positive, + negative=negative, + p=p, + eps=eps, + margin=margin, + swap=swap, + reduction=reduction) else: - dy_res = call_TripletMarginLoss_layer(input=input,positive=positive,negative=negative,p=p,eps=eps, - margin=margin,swap=swap,reduction=reduction) + dy_res = call_TripletMarginLoss_layer(input=input, + positive=positive, + negative=negative, + p=p, + eps=eps, + margin=margin, + swap=swap, + reduction=reduction) dy_result = dy_res.numpy() paddle.enable_static() return dy_result @@ -174,7 +207,7 @@ def test_TripletMarginLoss_error(self): paddle.disable_static() self.assertRaises( ValueError, - paddle.nn.TripletMarginLoss, + paddle.nn.loss.TripletMarginLoss, reduction="unsupport reduction") input = paddle.to_tensor([[0.1, 0.3]], dtype='float32') positive = paddle.to_tensor([[0.0, 1.0]], dtype='float32') @@ -200,7 +233,7 @@ def test_TripletMarginLoss_dimension(self): input=input, positive=positive, negative=negative,) - TMLoss = paddle.nn.TripletMarginLoss() + TMLoss = paddle.nn.loss.TripletMarginLoss() self.assertRaises( ValueError, TMLoss, diff --git a/python/paddle/nn/functional/__init__.py b/python/paddle/nn/functional/__init__.py index 243b6991ad77a..4e57c462d6005 100644 --- a/python/paddle/nn/functional/__init__.py +++ b/python/paddle/nn/functional/__init__.py @@ -227,5 +227,5 @@ 'class_center_sample', 'sparse_attention', 'fold', - 'triplet_margin_loss' + 'triplet_margin_loss', ] diff --git a/python/paddle/nn/functional/loss.py b/python/paddle/nn/functional/loss.py index 68a94e783aeb9..80ef81b20e3fe 100755 --- a/python/paddle/nn/functional/loss.py +++ b/python/paddle/nn/functional/loss.py @@ -2228,9 +2228,14 @@ def hinge_embedding_loss(input, label, margin=1.0, reduction='mean', name=None): return loss -def triplet_margin_loss(input,positive,negative, - swap=False, p=2, eps=1e-6, - margin=1.0, reduction='mean', +def triplet_margin_loss(input, + positive, + negative, + swap=False, + p=2, + eps=1e-6, + margin=1.0, + reduction='mean', name=None): """ Creates a criterion that measures the triplet loss given an input diff --git a/python/paddle/nn/layer/loss.py b/python/paddle/nn/layer/loss.py index 8c45ce271028d..b472d8e43b88e 100644 --- a/python/paddle/nn/layer/loss.py +++ b/python/paddle/nn/layer/loss.py @@ -1351,33 +1351,42 @@ class TripletMarginLoss(Layer): .. code-block:: python import paddle - import paddle.nn.functional as F + import paddle.nn.TripletMarginLoss input = paddle.to_tensor([[1, 5, 3], [0, 3, 2], [1, 4, 1]], dtype=paddle.float32) positive= paddle.to_tensor([[5, 1, 2], [3, 2, 1], [3, -1, 1]], dtype=paddle.float32) negative = paddle.to_tensor([[2, 1, -3], [1, 1, -1], [4, -2, 1]], dtype=paddle.float32) - loss = F.triplet_margin_loss(input, positive, negative, margin=1.0, reduction='none') + triplet_margin_loss = TripletMarginLoss() + loss = triplet_margin_loss(input, positive, negative, reduction='none') print(loss) # Tensor([0. , 0.57496738, 0. ]) - loss = F.triplet_margin_loss(input, positive, negative, margin=1.0, reduction='mean') + loss = triplet_margin_loss(input, positive, negative, margin=1.0, reduction='mean') print(loss) # Tensor([0.19165580]) """ - def __init__(self, margin: float = 1.0, p: float = 2., eps: float = 1e-6, swap: bool = False,reduction: str = 'mean'): + def __init__(self, margin=1.0, p=2., eps= 1e-6, swap=False, reduction='mean', name=None): super(TripletMarginLoss, self).__init__() if reduction not in ['sum', 'mean', 'none']: raise ValueError( - "The value of 'reduction' in bce_loss should be 'sum', 'mean' or 'none', but " + "The value of 'reduction' in TripletMarginLoss should be 'sum', 'mean' or 'none', but " "received %s, which is not allowed." % reduction) self.margin = margin self.p = p self.eps = eps self.swap = swap self.reduction = reduction + self.name = name def forward(self, input, positive, negative): - return F.triplet_margin_loss(input, positive, negative, margin=self.margin, p=self.p, - eps=self.eps, swap=self.swap, reduction=self.reduction) + return F.triplet_margin_loss(input, + positive, + negative, + margin=self.margin, + p=self.p, + eps=self.eps, + swap=self.swap, + reduction=self.reduction, + name=self.name) From b120a369636554fb02d610f356ab272800bc4cda Mon Sep 17 00:00:00 2001 From: yangguohao <1901212980@pku.edu.cn> Date: Mon, 25 Apr 2022 21:07:21 +0800 Subject: [PATCH 08/32] 2022-04-25 --- .../unittests/test_triplet_margin_loss.py | 89 ++++++++++++++++++- python/paddle/nn/functional/loss.py | 23 ++--- python/paddle/nn/layer/loss.py | 48 +++++----- 3 files changed, 121 insertions(+), 39 deletions(-) diff --git a/python/paddle/fluid/tests/unittests/test_triplet_margin_loss.py b/python/paddle/fluid/tests/unittests/test_triplet_margin_loss.py index 0f01dcc584802..de30b5d911b84 100644 --- a/python/paddle/fluid/tests/unittests/test_triplet_margin_loss.py +++ b/python/paddle/fluid/tests/unittests/test_triplet_margin_loss.py @@ -1,4 +1,4 @@ -# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved. +# Copyright (c) 2022 PaddlePaddle 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. @@ -18,7 +18,6 @@ import unittest - def call_TripletMarginLoss_layer(input, positive, negative, @@ -168,8 +167,8 @@ def calc_triplet_margin_loss(input, class TestTripletMarginLoss(unittest.TestCase): def test_TripletMarginLoss(self): input = np.random.uniform(0.1, 0.8, size=(20, 30)).astype(np.float64) - positive = np.random.randint(0, 2, size=(20, 30)).astype(np.float64) - negative = np.random.randint(0, 2, size=(20, 30)).astype(np.float64) + positive = np.random.uniform(0, 2, size=(20, 30)).astype(np.float64) + negative = np.random.uniform(0, 2, size=(20, 30)).astype(np.float64) places = [fluid.CPUPlace()] if fluid.core.is_compiled_with_cuda(): @@ -242,5 +241,87 @@ def test_TripletMarginLoss_dimension(self): negative=negative,) paddle.enable_static() + def test_TripletMarginLoss_swap(self): + reduction = 'mean' + place = fluid.CPUPlace() + input = np.random.uniform(0.1, 0.8, size=(20, 30)).astype(np.float64) + positive = np.random.uniform(0, 2, size=(20, 30)).astype(np.float64) + negative = np.random.uniform(0, 2, size=(20, 30)).astype(np.float64) + expected = calc_triplet_margin_loss(input=input, swap=True, positive=positive, negative=negative, + reduction=reduction) + + dy_result = test_dygraph(place=place, swap=True, + input=input, positive=positive, negative=negative, + reduction=reduction, ) + + static_result = test_static(place=place, swap=True, + input_np=input, positive_np=positive, negative_np=negative, + reduction=reduction, ) + self.assertTrue(np.allclose(static_result, expected)) + self.assertTrue(np.allclose(static_result, dy_result)) + self.assertTrue(np.allclose(dy_result, expected)) + static_functional = test_static(place=place, swap=True, + input_np=input, positive_np=positive, negative_np=negative, + reduction=reduction, + functional=True) + dy_functional = test_dygraph( + place=place, swap=True, + input=input, positive=positive, negative=negative, + reduction=reduction, + functional=True) + self.assertTrue(np.allclose(static_functional, expected)) + self.assertTrue(np.allclose(static_functional, dy_functional)) + self.assertTrue(np.allclose(dy_functional, expected)) + + def test_TripletMarginLoss_margin(self): + paddle.disable_static() + + input = paddle.to_tensor([[0.1, 0.3]], dtype='float32') + positive = paddle.to_tensor([[0.0, 1.0]], dtype='float32') + negative = paddle.to_tensor([[0.2, 0.1]], dtype='float32') + margin = -0.5 + self.assertRaises( + ValueError, + paddle.nn.functional.triplet_margin_loss, + margin=margin, + input=input, + positive=positive, + negative=negative, ) + paddle.enable_static() + + def test_TripletMarginLoss_p(self): + p = 3 + reduction = 'mean' + place = fluid.CPUPlace() + input = np.random.uniform(0.1, 0.8, size=(20, 30)).astype(np.float64) + positive = np.random.uniform(0, 2, size=(20, 30)).astype(np.float64) + negative = np.random.uniform(0, 2, size=(20, 30)).astype(np.float64) + expected = calc_triplet_margin_loss(input=input, p=p, positive=positive, negative=negative, + reduction=reduction) + + dy_result = test_dygraph(place=place, p=p, + input=input, positive=positive, negative=negative, + reduction=reduction,) + + static_result = test_static(place=place, p=p, + input_np=input, positive_np=positive, negative_np=negative, + reduction=reduction,) + self.assertTrue(np.allclose(static_result, expected)) + self.assertTrue(np.allclose(static_result, dy_result)) + self.assertTrue(np.allclose(dy_result, expected)) + static_functional = test_static(place=place, p=p, + input_np=input, positive_np=positive, negative_np=negative, + reduction=reduction, + functional=True) + dy_functional = test_dygraph( + place=place, p=p, + input=input, positive=positive, negative=negative, + reduction=reduction, + functional=True) + self.assertTrue(np.allclose(static_functional, expected)) + self.assertTrue(np.allclose(static_functional, dy_functional)) + self.assertTrue(np.allclose(dy_functional, expected)) + + if __name__ == "__main__": unittest.main() diff --git a/python/paddle/nn/functional/loss.py b/python/paddle/nn/functional/loss.py index 80ef81b20e3fe..617a36eaf3c3e 100755 --- a/python/paddle/nn/functional/loss.py +++ b/python/paddle/nn/functional/loss.py @@ -2245,10 +2245,6 @@ def triplet_margin_loss(input, examples` respectively). The shapes of all input tensors should be :math:`(N, D)`. - The distance swap is described in detail in the paper `Learning shallow - convolutional feature descriptors with triplet losses`_ by - V. Balntas, E. Riba et al. - The loss function for each sample in the mini-batch is: .. math:: @@ -2262,14 +2258,15 @@ def triplet_margin_loss(input, :param input:Input tensor, the data type is float32 or float64. the shape is [N, \*], N is batch size and `\*` means any number of additional dimensions, available dtype is float32, float64. - :param positive:Positive tensor containing 1 or -1, the data type is float32 or float64. + :param positive:Positive tensor, the data type is float32 or float64. The shape of label is the same as the shape of input. - :param negative:Negative tensor containing 1 or -1, the data type is float32 or float64. + :param negative:Negative tensor, the data type is float32 or float64. The shape of label is the same as the shape of input. - :param swap:The distance swap is described in detail in the paperT - `Learning shallow convolutional feature descriptors with triplet losses` by - V. Balntas, E. Riba et al. Default: ``False``. + :param swap:The distance swap change the negative distance to the distance between + positive sample and negative sample. Default: ``False``. :param p:The norm degree for pairwise distance. Default: :math:`2`. + :param eps:Add small value to avoid division by zero, + default value is 1e-6. :param margin:Default: :math:`1`. :param reduction:Indicate how to average the loss by batch_size. the candicates are ``'none'`` | ``'mean'`` | ``'sum'``. @@ -2277,6 +2274,8 @@ def triplet_margin_loss(input, If :attr:`reduction` is ``'mean'``, the reduced mean loss is returned; If :attr:`reduction` is ``'sum'``, the summed loss is returned. Default: ``'mean'`` + :param name: Name for the operation (optional, default is None). + For more information, please refer to :ref:`api_guide_Name`. :return:Tensor. The tensor variable storing the triplet_margin_loss of input and positive and negative. Examples: @@ -2304,7 +2303,7 @@ def triplet_margin_loss(input, "but received {}.".format(reduction)) if margin<0: raise ValueError( - "margin should not smaller than 0" + "The margin between positive samples and negative samples should be greater than 0." ) if not _non_static_mode(): check_variable_and_dtype(input, 'input', ['float32', 'float64'], @@ -2314,10 +2313,6 @@ def triplet_margin_loss(input, check_variable_and_dtype(negative, 'negative', ['float32', 'float64'], 'triplet_margin_loss') - # reshape to [batch_size, N] - input = input.flatten(start_axis=1,stop_axis=-1) - positive = positive.flatten(start_axis=1,stop_axis=-1) - negative = negative.flatten(start_axis=1,stop_axis=-1) if not(input.shape==positive.shape==negative.shape): raise ValueError( "input's shape must equal to " diff --git a/python/paddle/nn/layer/loss.py b/python/paddle/nn/layer/loss.py index b472d8e43b88e..0d941a2621170 100644 --- a/python/paddle/nn/layer/loss.py +++ b/python/paddle/nn/layer/loss.py @@ -1313,10 +1313,6 @@ class TripletMarginLoss(Layer): examples` respectively). The shapes of all input tensors should be :math:`(N, D)`. - The distance swap is described in detail in the paper `Learning shallow - convolutional feature descriptors with triplet losses`_ by - V. Balntas, E. Riba et al. - The loss function for each sample in the mini-batch is: .. math:: @@ -1328,24 +1324,34 @@ class TripletMarginLoss(Layer): .. math:: d(x_i, y_i) = \left\lVert {\bf x}_i - {\bf y}_i \right\rVert_p - :param input:Input tensor, the data type is float32 or float64. + Parameters: + swap:The distance swap change the negative distance to the distance between + positive sample and negative sample. Default: ``False``. + + eps:Add small value to avoid division by zero, + default value is 1e-6. + + p:The norm degree for pairwise distance. Default: :math:`2`. + + margin:Default: :math:`1`. + + reduction:Indicate how to average the loss by batch_size. + the candicates are ``'none'`` | ``'mean'`` | ``'sum'``. + If :attr:`reduction` is ``'none'``, the unreduced loss is returned; + If :attr:`reduction` is ``'mean'``, the reduced mean loss is returned; + If :attr:`reduction` is ``'sum'``, the summed loss is returned. + Default: ``'mean'`` + name: Name for the operation (optional, default is None). + For more information, please refer to :ref:`api_guide_Name`. + Call Parameters: + input:Input tensor, the data type is float32 or float64. the shape is [N, \*], N is batch size and `\*` means any number of additional dimensions, available dtype is float32, float64. - :param positive:Positive tensor containing 1 or -1, the data type is float32 or float64. - The shape of label is the same as the shape of input. - :param negative:Negative tensor containing 1 or -1, the data type is float32 or float64. - The shape of label is the same as the shape of input. - :param swap:The distance swap is described in detail in the paperT - `Learning shallow convolutional feature descriptors with triplet losses` by - V. Balntas, E. Riba et al. Default: ``False``. - :param p:The norm degree for pairwise distance. Default: :math:`2`. - :param margin:Default: :math:`1`. - :param reduction:Indicate how to average the loss by batch_size. - the candicates are ``'none'`` | ``'mean'`` | ``'sum'``. - If :attr:`reduction` is ``'none'``, the unreduced loss is returned; - If :attr:`reduction` is ``'mean'``, the reduced mean loss is returned; - If :attr:`reduction` is ``'sum'``, the summed loss is returned. - Default: ``'mean'`` - :return:Tensor. The tensor variable storing the triplet_margin_loss of input and positive and negative. + positive:Positive tensor, the data type is float32 or float64. + The shape of label is the same as the shape of input. + negative:Negative tensor, the data type is float32 or float64. + The shape of label is the same as the shape of input. + Returns: + Tensor. The tensor variable storing the triplet_margin_loss of input and positive and negative. Examples: .. code-block:: python From b9817ec3ffabeee2e5026c63b708b12963941872 Mon Sep 17 00:00:00 2001 From: yangguohao <1901212980@pku.edu.cn> Date: Mon, 2 May 2022 18:15:24 +0800 Subject: [PATCH 09/32] 2022-05-02_V1 --- .../unittests/test_triplet_margin_loss.py | 18 ++++++++---------- python/paddle/nn/functional/loss.py | 4 ++-- python/paddle/nn/layer/loss.py | 2 +- 3 files changed, 11 insertions(+), 13 deletions(-) diff --git a/python/paddle/fluid/tests/unittests/test_triplet_margin_loss.py b/python/paddle/fluid/tests/unittests/test_triplet_margin_loss.py index de30b5d911b84..6f00e324947c8 100644 --- a/python/paddle/fluid/tests/unittests/test_triplet_margin_loss.py +++ b/python/paddle/fluid/tests/unittests/test_triplet_margin_loss.py @@ -13,11 +13,9 @@ # limitations under the License. import paddle -import paddle.fluid as fluid import numpy as np import unittest - def call_TripletMarginLoss_layer(input, positive, negative, @@ -70,11 +68,11 @@ def test_static(place, prog = paddle.static.Program() startup_prog = paddle.static.Program() with paddle.static.program_guard(prog, startup_prog): - input = paddle.fluid.data( + input = paddle.static.data( name='input', shape=input_np.shape, dtype='float64') - positive = paddle.fluid.data( + positive = paddle.static.data( name='positive', shape=positive_np.shape, dtype='float64') - negative = paddle.fluid.data( + negative = paddle.static.data( name='negative', shape=negative_np.shape, dtype='float64') feed_dict = {"input": input_np, "positive": positive_np, "negative": negative_np} @@ -170,9 +168,9 @@ def test_TripletMarginLoss(self): positive = np.random.uniform(0, 2, size=(20, 30)).astype(np.float64) negative = np.random.uniform(0, 2, size=(20, 30)).astype(np.float64) - places = [fluid.CPUPlace()] - if fluid.core.is_compiled_with_cuda(): - places.append(fluid.CUDAPlace(0)) + places = [paddle.CPUPlace()] + if paddle.device.is_compiled_with_cuda(): + places.append(paddle.CUDAPlace(0)) reductions = ['sum', 'mean', 'none'] for place in places: for reduction in reductions: @@ -243,7 +241,7 @@ def test_TripletMarginLoss_dimension(self): def test_TripletMarginLoss_swap(self): reduction = 'mean' - place = fluid.CPUPlace() + place = paddle.CPUPlace() input = np.random.uniform(0.1, 0.8, size=(20, 30)).astype(np.float64) positive = np.random.uniform(0, 2, size=(20, 30)).astype(np.float64) negative = np.random.uniform(0, 2, size=(20, 30)).astype(np.float64) @@ -292,7 +290,7 @@ def test_TripletMarginLoss_margin(self): def test_TripletMarginLoss_p(self): p = 3 reduction = 'mean' - place = fluid.CPUPlace() + place = paddle.CPUPlace() input = np.random.uniform(0.1, 0.8, size=(20, 30)).astype(np.float64) positive = np.random.uniform(0, 2, size=(20, 30)).astype(np.float64) negative = np.random.uniform(0, 2, size=(20, 30)).astype(np.float64) diff --git a/python/paddle/nn/functional/loss.py b/python/paddle/nn/functional/loss.py index 617a36eaf3c3e..fe9f6d9319d4e 100755 --- a/python/paddle/nn/functional/loss.py +++ b/python/paddle/nn/functional/loss.py @@ -2238,12 +2238,12 @@ def triplet_margin_loss(input, reduction='mean', name=None): """ - Creates a criterion that measures the triplet loss given an input + Measures the triplet loss given an input tensors :math:`x1`, :math:`x2`, :math:`x3` and a margin with a value greater than :math:`0`. This is used for measuring a relative similarity between samples. A triplet is composed by `input`, `positive` and `negative` (i.e., `input`, `positive examples` and `negative examples` respectively). The shapes of all input tensors should be - :math:`(N, D)`. + :math:`(N, *)`. The loss function for each sample in the mini-batch is: diff --git a/python/paddle/nn/layer/loss.py b/python/paddle/nn/layer/loss.py index 0d941a2621170..e68e3d4ced124 100644 --- a/python/paddle/nn/layer/loss.py +++ b/python/paddle/nn/layer/loss.py @@ -1311,7 +1311,7 @@ class TripletMarginLoss(Layer): This is used for measuring a relative similarity between samples. A triplet is composed by `input`, `positive` and `negative` (i.e., `input`, `positive examples` and `negative examples` respectively). The shapes of all input tensors should be - :math:`(N, D)`. + :math:`(N, *)`. The loss function for each sample in the mini-batch is: From 0054e8fe38c75ca0346c866ed3e20cf1c3c42c93 Mon Sep 17 00:00:00 2001 From: yangguohao <1901212980@pku.edu.cn> Date: Fri, 6 May 2022 22:02:56 +0800 Subject: [PATCH 10/32] 2022-05-06_V1 --- .../unittests/test_triplet_margin_loss.py | 2 +- python/paddle/nn/functional/loss.py | 59 +++++++++++-------- python/paddle/nn/layer/loss.py | 4 +- 3 files changed, 39 insertions(+), 26 deletions(-) diff --git a/python/paddle/fluid/tests/unittests/test_triplet_margin_loss.py b/python/paddle/fluid/tests/unittests/test_triplet_margin_loss.py index 6f00e324947c8..5e307d69104ca 100644 --- a/python/paddle/fluid/tests/unittests/test_triplet_margin_loss.py +++ b/python/paddle/fluid/tests/unittests/test_triplet_margin_loss.py @@ -24,7 +24,7 @@ def call_TripletMarginLoss_layer(input, swap=False, eps = 1e-6, reduction='mean',): - triplet_margin_loss = paddle.nn.loss.TripletMarginLoss(p=p, + triplet_margin_loss = paddle.nn.TripletMarginLoss(p=p, eps=eps, margin=margin, swap=swap, diff --git a/python/paddle/nn/functional/loss.py b/python/paddle/nn/functional/loss.py index fe9f6d9319d4e..043ac01a26b64 100755 --- a/python/paddle/nn/functional/loss.py +++ b/python/paddle/nn/functional/loss.py @@ -2237,48 +2237,59 @@ def triplet_margin_loss(input, margin=1.0, reduction='mean', name=None): - """ - Measures the triplet loss given an input - tensors :math:`x1`, :math:`x2`, :math:`x3` and a margin with a value greater than :math:`0`. - This is used for measuring a relative similarity between samples. A triplet - is composed by `input`, `positive` and `negative` (i.e., `input`, `positive examples` and `negative - examples` respectively). The shapes of all input tensors should be - :math:`(N, *)`. + r""" + Measures the triplet loss given an input + tensors :math:`x1`, :math:`x2`, :math:`x3` and a margin with a value greater than :math:`0`. + This is used for measuring a relative similarity between samples. A triplet + is composed by `input`, `positive` and `negative` (i.e., `input`, `positive examples` and `negative + examples` respectively). The shapes of all input tensors should be + :math:`(N, *)`. - The loss function for each sample in the mini-batch is: + The loss function for each sample in the mini-batch is: - .. math:: - L(input, pos, neg) = \max \{d(input_i, pos_i) - d(input_i, neg_i) + {\rm margin}, 0\} + .. math:: + L(input, pos, neg) = \max \{d(input_i, pos_i) - d(input_i, neg_i) + {\rm margin}, 0\} - where + where - .. math:: - d(x_i, y_i) = \left\lVert {\bf x}_i - {\bf y}_i \right\rVert_p + .. math:: + d(x_i, y_i) = \left\lVert {\bf x}_i - {\bf y}_i \right\rVert_p - :param input:Input tensor, the data type is float32 or float64. + Parameters: + input: Input tensor, the data type is float32 or float64. the shape is [N, \*], N is batch size and `\*` means any number of additional dimensions, available dtype is float32, float64. - :param positive:Positive tensor, the data type is float32 or float64. + + positive: Positive tensor, the data type is float32 or float64. The shape of label is the same as the shape of input. - :param negative:Negative tensor, the data type is float32 or float64. + + negative: Negative tensor, the data type is float32 or float64. The shape of label is the same as the shape of input. - :param swap:The distance swap change the negative distance to the distance between + + swap: The distance swap change the negative distance to the distance between positive sample and negative sample. Default: ``False``. - :param p:The norm degree for pairwise distance. Default: :math:`2`. - :param eps:Add small value to avoid division by zero, + + p: The norm degree for pairwise distance. Default: :math:`2`. + + eps: Add small value to avoid division by zero, default value is 1e-6. - :param margin:Default: :math:`1`. - :param reduction:Indicate how to average the loss by batch_size. + + margin: Default: :math:`1`. + + reduction:Indicate how to average the loss by batch_size. the candicates are ``'none'`` | ``'mean'`` | ``'sum'``. If :attr:`reduction` is ``'none'``, the unreduced loss is returned; If :attr:`reduction` is ``'mean'``, the reduced mean loss is returned; If :attr:`reduction` is ``'sum'``, the summed loss is returned. Default: ``'mean'`` - :param name: Name for the operation (optional, default is None). + + name: Name for the operation (optional, default is None). For more information, please refer to :ref:`api_guide_Name`. - :return:Tensor. The tensor variable storing the triplet_margin_loss of input and positive and negative. - Examples: + Returns: + Output: Tensor. The tensor variable storing the triplet_margin_loss of input and positive and negative. + + Examples: .. code-block:: python import paddle diff --git a/python/paddle/nn/layer/loss.py b/python/paddle/nn/layer/loss.py index e68e3d4ced124..691f9cb7ab639 100644 --- a/python/paddle/nn/layer/loss.py +++ b/python/paddle/nn/layer/loss.py @@ -1305,7 +1305,7 @@ def forward(self, input, label): class TripletMarginLoss(Layer): - """ + r""" Creates a criterion that measures the triplet loss given an input tensors :math:`x1`, :math:`x2`, :math:`x3` and a margin with a value greater than :math:`0`. This is used for measuring a relative similarity between samples. A triplet @@ -1343,6 +1343,7 @@ class TripletMarginLoss(Layer): Default: ``'mean'`` name: Name for the operation (optional, default is None). For more information, please refer to :ref:`api_guide_Name`. + Call Parameters: input:Input tensor, the data type is float32 or float64. the shape is [N, \*], N is batch size and `\*` means any number of additional dimensions, available dtype is float32, float64. @@ -1350,6 +1351,7 @@ class TripletMarginLoss(Layer): The shape of label is the same as the shape of input. negative:Negative tensor, the data type is float32 or float64. The shape of label is the same as the shape of input. + Returns: Tensor. The tensor variable storing the triplet_margin_loss of input and positive and negative. From b9bde0b9d959ad4967f2cf13a39b6e30850dde9b Mon Sep 17 00:00:00 2001 From: yangguohao <1901212980@pku.edu.cn> Date: Sat, 7 May 2022 21:59:12 +0800 Subject: [PATCH 11/32] 2022-05-07_V1 --- python/paddle/nn/layer/loss.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/python/paddle/nn/layer/loss.py b/python/paddle/nn/layer/loss.py index 691f9cb7ab639..59ed85262763e 100644 --- a/python/paddle/nn/layer/loss.py +++ b/python/paddle/nn/layer/loss.py @@ -1346,9 +1346,11 @@ class TripletMarginLoss(Layer): Call Parameters: input:Input tensor, the data type is float32 or float64. - the shape is [N, \*], N is batch size and `\*` means any number of additional dimensions, available dtype is float32, float64. + the shape is [N, \*], N is batch size and `\*` means any number of additional dimensions, available dtype is float32, float64. + positive:Positive tensor, the data type is float32 or float64. The shape of label is the same as the shape of input. + negative:Negative tensor, the data type is float32 or float64. The shape of label is the same as the shape of input. From 30e5ccf33631291545311b1d67b55eed572de4cd Mon Sep 17 00:00:00 2001 From: yangguohao <70266361+yangguohao@users.noreply.github.com> Date: Mon, 9 May 2022 17:10:27 +0800 Subject: [PATCH 12/32] Update loss.py --- python/paddle/nn/layer/loss.py | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/python/paddle/nn/layer/loss.py b/python/paddle/nn/layer/loss.py index 59ed85262763e..a9b06e1d8087c 100644 --- a/python/paddle/nn/layer/loss.py +++ b/python/paddle/nn/layer/loss.py @@ -1325,15 +1325,16 @@ class TripletMarginLoss(Layer): d(x_i, y_i) = \left\lVert {\bf x}_i - {\bf y}_i \right\rVert_p Parameters: - swap:The distance swap change the negative distance to the distance between - positive sample and negative sample. Default: ``False``. - - eps:Add small value to avoid division by zero, + margin (int, Optional):Default: :math:`1`. + + p (int, Optional):The norm degree for pairwise distance. Default: :math:`2`. + + eps (float, Optional):Add small value to avoid division by zero, default value is 1e-6. - - p:The norm degree for pairwise distance. Default: :math:`2`. - - margin:Default: :math:`1`. + + swap (bool, Optional):The distance swap change the negative distance to the distance between + positive sample and negative sample. For more details, see `Learning shallow convolutional feature descriptors with triplet losses`. + Default: ``False``. reduction:Indicate how to average the loss by batch_size. the candicates are ``'none'`` | ``'mean'`` | ``'sum'``. @@ -1341,18 +1342,19 @@ class TripletMarginLoss(Layer): If :attr:`reduction` is ``'mean'``, the reduced mean loss is returned; If :attr:`reduction` is ``'sum'``, the summed loss is returned. Default: ``'mean'`` + name: Name for the operation (optional, default is None). For more information, please refer to :ref:`api_guide_Name`. Call Parameters: - input:Input tensor, the data type is float32 or float64. - the shape is [N, \*], N is batch size and `\*` means any number of additional dimensions, available dtype is float32, float64. + input (Tensor):Input tensor, the data type is float32 or float64. + the shape is [N, \*], N is batch size and `\*` means any number of additional dimensions, available dtype is float32, float64. - positive:Positive tensor, the data type is float32 or float64. - The shape of label is the same as the shape of input. + positive (Tensor):Positive tensor, the data type is float32 or float64. + The shape of label is the same as the shape of input. - negative:Negative tensor, the data type is float32 or float64. - The shape of label is the same as the shape of input. + negative (Tensor):Negative tensor, the data type is float32 or float64. + The shape of label is the same as the shape of input. Returns: Tensor. The tensor variable storing the triplet_margin_loss of input and positive and negative. From c0bcb93e5d72843beb3409f6756048bd5b0b1e41 Mon Sep 17 00:00:00 2001 From: yangguohao <70266361+yangguohao@users.noreply.github.com> Date: Mon, 9 May 2022 17:10:35 +0800 Subject: [PATCH 13/32] Update loss.py --- python/paddle/nn/functional/loss.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/python/paddle/nn/functional/loss.py b/python/paddle/nn/functional/loss.py index 043ac01a26b64..af3a9219760c6 100755 --- a/python/paddle/nn/functional/loss.py +++ b/python/paddle/nn/functional/loss.py @@ -2257,24 +2257,25 @@ def triplet_margin_loss(input, d(x_i, y_i) = \left\lVert {\bf x}_i - {\bf y}_i \right\rVert_p Parameters: - input: Input tensor, the data type is float32 or float64. + input (Tensor): Input tensor, the data type is float32 or float64. the shape is [N, \*], N is batch size and `\*` means any number of additional dimensions, available dtype is float32, float64. - positive: Positive tensor, the data type is float32 or float64. + positive (Tensor): Positive tensor, the data type is float32 or float64. The shape of label is the same as the shape of input. - negative: Negative tensor, the data type is float32 or float64. + negative (Tensor): Negative tensor, the data type is float32 or float64. The shape of label is the same as the shape of input. - swap: The distance swap change the negative distance to the distance between - positive sample and negative sample. Default: ``False``. + swap (bool,Optional): The distance swap change the negative distance to the distance between + positive sample and negative sample. For more details, see `Learning shallow convolutional feature descriptors with triplet losses`. + Default: ``False``. - p: The norm degree for pairwise distance. Default: :math:`2`. + p (int, Optional): The norm degree for pairwise distance. Default: :math:`2`. - eps: Add small value to avoid division by zero, + eps (float, Optional): Add small value to avoid division by zero, default value is 1e-6. - margin: Default: :math:`1`. + margin (int, Optional): Default: :math:`1`. reduction:Indicate how to average the loss by batch_size. the candicates are ``'none'`` | ``'mean'`` | ``'sum'``. From c98c01a02ad863aa2b2e8d8fb34ae23602e5fa4b Mon Sep 17 00:00:00 2001 From: yangguohao <70266361+yangguohao@users.noreply.github.com> Date: Mon, 9 May 2022 21:52:20 +0800 Subject: [PATCH 14/32] Update loss.py --- python/paddle/nn/layer/loss.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/paddle/nn/layer/loss.py b/python/paddle/nn/layer/loss.py index a9b06e1d8087c..59da2e8639975 100644 --- a/python/paddle/nn/layer/loss.py +++ b/python/paddle/nn/layer/loss.py @@ -1325,7 +1325,7 @@ class TripletMarginLoss(Layer): d(x_i, y_i) = \left\lVert {\bf x}_i - {\bf y}_i \right\rVert_p Parameters: - margin (int, Optional):Default: :math:`1`. + margin (float, Optional):Default: :math:`1`. p (int, Optional):The norm degree for pairwise distance. Default: :math:`2`. From ec9e86fc122d963d5ae7ddfc33d3cb848d29e0d9 Mon Sep 17 00:00:00 2001 From: yangguohao <70266361+yangguohao@users.noreply.github.com> Date: Mon, 9 May 2022 21:53:06 +0800 Subject: [PATCH 15/32] Update loss.py --- python/paddle/nn/functional/loss.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/paddle/nn/functional/loss.py b/python/paddle/nn/functional/loss.py index af3a9219760c6..59f3c79edf96a 100755 --- a/python/paddle/nn/functional/loss.py +++ b/python/paddle/nn/functional/loss.py @@ -2275,7 +2275,7 @@ def triplet_margin_loss(input, eps (float, Optional): Add small value to avoid division by zero, default value is 1e-6. - margin (int, Optional): Default: :math:`1`. + margin (float, Optional): Default: :math:`1`. reduction:Indicate how to average the loss by batch_size. the candicates are ``'none'`` | ``'mean'`` | ``'sum'``. From 8c5e69d7c5c89703f8521843574abc9fc1b01da1 Mon Sep 17 00:00:00 2001 From: yangguohao <70266361+yangguohao@users.noreply.github.com> Date: Fri, 13 May 2022 17:37:08 +0800 Subject: [PATCH 16/32] Update loss.py --- python/paddle/nn/functional/loss.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/paddle/nn/functional/loss.py b/python/paddle/nn/functional/loss.py index 59f3c79edf96a..778dcb357934d 100755 --- a/python/paddle/nn/functional/loss.py +++ b/python/paddle/nn/functional/loss.py @@ -36,7 +36,7 @@ from paddle.utils import deprecated from paddle import _C_ops from paddle import in_dynamic_mode -from paddle.framework import core +from paddle.framework import core, _non_static_mode from ...fluid.framework import _in_legacy_dygraph, in_dygraph_mode, _non_static_mode, _current_expected_place __all__ = [] From 6304cc2bfe96d4e51e7c801b15450be953a1c611 Mon Sep 17 00:00:00 2001 From: yangguohao <70266361+yangguohao@users.noreply.github.com> Date: Thu, 19 May 2022 15:12:58 +0800 Subject: [PATCH 17/32] Update loss.py --- python/paddle/nn/layer/loss.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/python/paddle/nn/layer/loss.py b/python/paddle/nn/layer/loss.py index 59da2e8639975..1061ca638adca 100644 --- a/python/paddle/nn/layer/loss.py +++ b/python/paddle/nn/layer/loss.py @@ -1336,14 +1336,14 @@ class TripletMarginLoss(Layer): positive sample and negative sample. For more details, see `Learning shallow convolutional feature descriptors with triplet losses`. Default: ``False``. - reduction:Indicate how to average the loss by batch_size. + reduction (str, Optional):Indicate how to average the loss by batch_size. the candicates are ``'none'`` | ``'mean'`` | ``'sum'``. If :attr:`reduction` is ``'none'``, the unreduced loss is returned; If :attr:`reduction` is ``'mean'``, the reduced mean loss is returned; If :attr:`reduction` is ``'sum'``, the summed loss is returned. Default: ``'mean'`` - name: Name for the operation (optional, default is None). + name (str,Optional): Name for the operation (optional, default is None). For more information, please refer to :ref:`api_guide_Name`. Call Parameters: From 63a1cb161d27f2ea919c58a8303cf74f624a9816 Mon Sep 17 00:00:00 2001 From: yangguohao <70266361+yangguohao@users.noreply.github.com> Date: Thu, 19 May 2022 15:18:39 +0800 Subject: [PATCH 18/32] Update loss.py --- python/paddle/nn/functional/loss.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/python/paddle/nn/functional/loss.py b/python/paddle/nn/functional/loss.py index 778dcb357934d..a67e19bdf07ed 100755 --- a/python/paddle/nn/functional/loss.py +++ b/python/paddle/nn/functional/loss.py @@ -2277,14 +2277,14 @@ def triplet_margin_loss(input, margin (float, Optional): Default: :math:`1`. - reduction:Indicate how to average the loss by batch_size. + reduction (str, Optional):Indicate how to average the loss by batch_size. the candicates are ``'none'`` | ``'mean'`` | ``'sum'``. If :attr:`reduction` is ``'none'``, the unreduced loss is returned; If :attr:`reduction` is ``'mean'``, the reduced mean loss is returned; If :attr:`reduction` is ``'sum'``, the summed loss is returned. Default: ``'mean'`` - name: Name for the operation (optional, default is None). + name (str, Optional): Name for the operation (optional, default is None). For more information, please refer to :ref:`api_guide_Name`. Returns: From 0a18f09f411ea9dfe0f86cd8bae83e2c315f1a46 Mon Sep 17 00:00:00 2001 From: yangguohao <70266361+yangguohao@users.noreply.github.com> Date: Mon, 23 May 2022 11:17:40 +0800 Subject: [PATCH 19/32] Update loss.py --- python/paddle/nn/functional/loss.py | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/python/paddle/nn/functional/loss.py b/python/paddle/nn/functional/loss.py index 039130f7a0809..31185295f834f 100755 --- a/python/paddle/nn/functional/loss.py +++ b/python/paddle/nn/functional/loss.py @@ -2235,10 +2235,10 @@ def hinge_embedding_loss(input, label, margin=1.0, reduction='mean', name=None): def triplet_margin_loss(input, positive, negative, - swap=False, + margin=1.0, p=2, - eps=1e-6, - margin=1.0, + epsilon=1e-6, + swap=False, reduction='mean', name=None): r""" @@ -2269,18 +2269,19 @@ def triplet_margin_loss(input, negative (Tensor): Negative tensor, the data type is float32 or float64. The shape of label is the same as the shape of input. - - swap (bool,Optional): The distance swap change the negative distance to the distance between - positive sample and negative sample. For more details, see `Learning shallow convolutional feature descriptors with triplet losses`. - Default: ``False``. - + + margin (float, Optional): Default: :math:`1`. + p (int, Optional): The norm degree for pairwise distance. Default: :math:`2`. - eps (float, Optional): Add small value to avoid division by zero, + epsilon (float, Optional): Add small value to avoid division by zero, default value is 1e-6. + + swap (bool,Optional): The distance swap change the negative distance to the distance between + positive sample and negative sample. For more details, see `Learning shallow convolutional feature descriptors with triplet losses`. + Default: ``False``. - margin (float, Optional): Default: :math:`1`. - + reduction (str, Optional):Indicate how to average the loss by batch_size. the candicates are ``'none'`` | ``'mean'`` | ``'sum'``. If :attr:`reduction` is ``'none'``, the unreduced loss is returned; @@ -2335,7 +2336,7 @@ def triplet_margin_loss(input, "positive's shape and " "negative's shape") - distance_function = paddle.nn.PairwiseDistance(p, epsilon=eps) + distance_function = paddle.nn.PairwiseDistance(p, epsilon=epsilon) positive_dist = distance_function(input, positive) negative_dist = distance_function(input, negative) From 5ed1cb6d9fb7e0bcadd18d4648c51967fb3bc22e Mon Sep 17 00:00:00 2001 From: yangguohao <70266361+yangguohao@users.noreply.github.com> Date: Mon, 23 May 2022 11:19:40 +0800 Subject: [PATCH 20/32] Update loss.py --- python/paddle/nn/layer/loss.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/python/paddle/nn/layer/loss.py b/python/paddle/nn/layer/loss.py index 8be08a60a52f7..16d147b110716 100644 --- a/python/paddle/nn/layer/loss.py +++ b/python/paddle/nn/layer/loss.py @@ -1333,7 +1333,7 @@ class TripletMarginLoss(Layer): p (int, Optional):The norm degree for pairwise distance. Default: :math:`2`. - eps (float, Optional):Add small value to avoid division by zero, + epsilon (float, Optional):Add small value to avoid division by zero, default value is 1e-6. swap (bool, Optional):The distance swap change the negative distance to the distance between @@ -1383,7 +1383,7 @@ class TripletMarginLoss(Layer): # Tensor([0.19165580]) """ - def __init__(self, margin=1.0, p=2., eps= 1e-6, swap=False, reduction='mean', name=None): + def __init__(self, margin=1.0, p=2., epsilon= 1e-6, swap=False, reduction='mean', name=None): super(TripletMarginLoss, self).__init__() if reduction not in ['sum', 'mean', 'none']: raise ValueError( @@ -1391,7 +1391,7 @@ def __init__(self, margin=1.0, p=2., eps= 1e-6, swap=False, reduction='mean', na "received %s, which is not allowed." % reduction) self.margin = margin self.p = p - self.eps = eps + self.epsilon = epsilon self.swap = swap self.reduction = reduction self.name = name @@ -1402,7 +1402,7 @@ def forward(self, input, positive, negative): negative, margin=self.margin, p=self.p, - eps=self.eps, + eps=self.epsilon, swap=self.swap, reduction=self.reduction, name=self.name) From da0515f0332a2dc9080f7f6a7358f327df85b17c Mon Sep 17 00:00:00 2001 From: yangguohao <70266361+yangguohao@users.noreply.github.com> Date: Mon, 23 May 2022 12:49:55 +0800 Subject: [PATCH 21/32] Update test_triplet_margin_loss.py --- .../unittests/test_triplet_margin_loss.py | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/python/paddle/fluid/tests/unittests/test_triplet_margin_loss.py b/python/paddle/fluid/tests/unittests/test_triplet_margin_loss.py index 5e307d69104ca..c8251c154d914 100644 --- a/python/paddle/fluid/tests/unittests/test_triplet_margin_loss.py +++ b/python/paddle/fluid/tests/unittests/test_triplet_margin_loss.py @@ -25,7 +25,7 @@ def call_TripletMarginLoss_layer(input, eps = 1e-6, reduction='mean',): triplet_margin_loss = paddle.nn.TripletMarginLoss(p=p, - eps=eps, + epsilon=eps, margin=margin, swap=swap, reduction=reduction) @@ -47,7 +47,7 @@ def call_TripletMarginLoss_functional(input, positive=positive, negative=negative, p=p, - eps=eps, + epsilon=eps, margin=margin, swap=swap, reduction=reduction) @@ -164,9 +164,9 @@ def calc_triplet_margin_loss(input, class TestTripletMarginLoss(unittest.TestCase): def test_TripletMarginLoss(self): - input = np.random.uniform(0.1, 0.8, size=(20, 30)).astype(np.float64) - positive = np.random.uniform(0, 2, size=(20, 30)).astype(np.float64) - negative = np.random.uniform(0, 2, size=(20, 30)).astype(np.float64) + input = np.random.uniform(0.1, 0.8, size=(5, 5)).astype(np.float64) + positive = np.random.uniform(0, 2, size=(5, 5)).astype(np.float64) + negative = np.random.uniform(0, 2, size=(5, 5)).astype(np.float64) places = [paddle.CPUPlace()] if paddle.device.is_compiled_with_cuda(): @@ -242,9 +242,9 @@ def test_TripletMarginLoss_dimension(self): def test_TripletMarginLoss_swap(self): reduction = 'mean' place = paddle.CPUPlace() - input = np.random.uniform(0.1, 0.8, size=(20, 30)).astype(np.float64) - positive = np.random.uniform(0, 2, size=(20, 30)).astype(np.float64) - negative = np.random.uniform(0, 2, size=(20, 30)).astype(np.float64) + input = np.random.uniform(0.1, 0.8, size=(5, 5)).astype(np.float64) + positive = np.random.uniform(0, 2, size=(5, 5)).astype(np.float64) + negative = np.random.uniform(0, 2, size=(5, 5)).astype(np.float64) expected = calc_triplet_margin_loss(input=input, swap=True, positive=positive, negative=negative, reduction=reduction) @@ -291,9 +291,9 @@ def test_TripletMarginLoss_p(self): p = 3 reduction = 'mean' place = paddle.CPUPlace() - input = np.random.uniform(0.1, 0.8, size=(20, 30)).astype(np.float64) - positive = np.random.uniform(0, 2, size=(20, 30)).astype(np.float64) - negative = np.random.uniform(0, 2, size=(20, 30)).astype(np.float64) + input = np.random.uniform(0.1, 0.8, size=(5, 5)).astype(np.float64) + positive = np.random.uniform(0, 2, size=(5, 5)).astype(np.float64) + negative = np.random.uniform(0, 2, size=(5, 5)).astype(np.float64) expected = calc_triplet_margin_loss(input=input, p=p, positive=positive, negative=negative, reduction=reduction) From 2be018ef4b3255e04e139f9211b86f13a462a0e7 Mon Sep 17 00:00:00 2001 From: yangguohao <70266361+yangguohao@users.noreply.github.com> Date: Tue, 24 May 2022 09:22:33 +0800 Subject: [PATCH 22/32] Update loss.py --- python/paddle/nn/layer/loss.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/paddle/nn/layer/loss.py b/python/paddle/nn/layer/loss.py index 16d147b110716..2ec51706fd03c 100644 --- a/python/paddle/nn/layer/loss.py +++ b/python/paddle/nn/layer/loss.py @@ -1402,7 +1402,7 @@ def forward(self, input, positive, negative): negative, margin=self.margin, p=self.p, - eps=self.epsilon, + epsilon=self.epsilon, swap=self.swap, reduction=self.reduction, name=self.name) From f06ad6299f6676429278d013564c03e50c9e2e60 Mon Sep 17 00:00:00 2001 From: yangguohao <1901212980@pku.edu.cn> Date: Wed, 1 Jun 2022 22:49:37 +0800 Subject: [PATCH 23/32] 2022-06-01_pre-commit --- python/paddle/nn/functional/loss.py | 21 +++++++++--------- python/paddle/nn/layer/loss.py | 34 ++++++++++++++++++----------- 2 files changed, 31 insertions(+), 24 deletions(-) diff --git a/python/paddle/nn/functional/loss.py b/python/paddle/nn/functional/loss.py index 31185295f834f..4ebf2c472de7d 100755 --- a/python/paddle/nn/functional/loss.py +++ b/python/paddle/nn/functional/loss.py @@ -2235,7 +2235,7 @@ def hinge_embedding_loss(input, label, margin=1.0, reduction='mean', name=None): def triplet_margin_loss(input, positive, negative, - margin=1.0, + margin=1.0, p=2, epsilon=1e-6, swap=False, @@ -2270,16 +2270,16 @@ def triplet_margin_loss(input, negative (Tensor): Negative tensor, the data type is float32 or float64. The shape of label is the same as the shape of input. - margin (float, Optional): Default: :math:`1`. + margin (float, Optional): Default: :math:`1`. p (int, Optional): The norm degree for pairwise distance. Default: :math:`2`. epsilon (float, Optional): Add small value to avoid division by zero, default value is 1e-6. - swap (bool,Optional): The distance swap change the negative distance to the distance between + swap (bool,Optional): The distance swap change the negative distance to the distance between positive sample and negative sample. For more details, see `Learning shallow convolutional feature descriptors with triplet losses`. - Default: ``False``. + Default: ``False``. reduction (str, Optional):Indicate how to average the loss by batch_size. @@ -2318,7 +2318,7 @@ def triplet_margin_loss(input, raise ValueError( "'reduction' in 'triplet_margin_loss' should be 'sum', 'mean' or 'none', " "but received {}.".format(reduction)) - if margin<0: + if margin < 0: raise ValueError( "The margin between positive samples and negative samples should be greater than 0." ) @@ -2330,11 +2330,10 @@ def triplet_margin_loss(input, check_variable_and_dtype(negative, 'negative', ['float32', 'float64'], 'triplet_margin_loss') - if not(input.shape==positive.shape==negative.shape): - raise ValueError( - "input's shape must equal to " - "positive's shape and " - "negative's shape") + if not (input.shape == positive.shape == negative.shape): + raise ValueError("input's shape must equal to " + "positive's shape and " + "negative's shape") distance_function = paddle.nn.PairwiseDistance(p, epsilon=epsilon) positive_dist = distance_function(input, positive) @@ -2344,7 +2343,7 @@ def triplet_margin_loss(input, swap_dist = distance_function(positive, negative) negative_dist = paddle.minimum(negative_dist, swap_dist) - loss = paddle.clip(positive_dist-negative_dist+margin, min=0.0) + loss = paddle.clip(positive_dist - negative_dist + margin, min=0.0) if reduction == 'mean': return paddle.mean(loss, name=name) diff --git a/python/paddle/nn/layer/loss.py b/python/paddle/nn/layer/loss.py index 2ec51706fd03c..3f67639b0ce4e 100644 --- a/python/paddle/nn/layer/loss.py +++ b/python/paddle/nn/layer/loss.py @@ -1352,13 +1352,13 @@ class TripletMarginLoss(Layer): Call Parameters: input (Tensor):Input tensor, the data type is float32 or float64. - the shape is [N, \*], N is batch size and `\*` means any number of additional dimensions, available dtype is float32, float64. + the shape is [N, \*], N is batch size and `\*` means any number of additional dimensions, available dtype is float32, float64. positive (Tensor):Positive tensor, the data type is float32 or float64. - The shape of label is the same as the shape of input. + The shape of label is the same as the shape of input. negative (Tensor):Negative tensor, the data type is float32 or float64. - The shape of label is the same as the shape of input. + The shape of label is the same as the shape of input. Returns: Tensor. The tensor variable storing the triplet_margin_loss of input and positive and negative. @@ -1383,7 +1383,14 @@ class TripletMarginLoss(Layer): # Tensor([0.19165580]) """ - def __init__(self, margin=1.0, p=2., epsilon= 1e-6, swap=False, reduction='mean', name=None): + + def __init__(self, + margin=1.0, + p=2., + epsilon=1e-6, + swap=False, + reduction='mean', + name=None): super(TripletMarginLoss, self).__init__() if reduction not in ['sum', 'mean', 'none']: raise ValueError( @@ -1397,12 +1404,13 @@ def __init__(self, margin=1.0, p=2., epsilon= 1e-6, swap=False, reduction='mean' self.name = name def forward(self, input, positive, negative): - return F.triplet_margin_loss(input, - positive, - negative, - margin=self.margin, - p=self.p, - epsilon=self.epsilon, - swap=self.swap, - reduction=self.reduction, - name=self.name) + return F.triplet_margin_loss( + input, + positive, + negative, + margin=self.margin, + p=self.p, + epsilon=self.epsilon, + swap=self.swap, + reduction=self.reduction, + name=self.name) From 32c0440cba17c625183b731d332a0e0ebfe71315 Mon Sep 17 00:00:00 2001 From: yangguohao <1901212980@pku.edu.cn> Date: Sun, 5 Jun 2022 17:34:12 +0800 Subject: [PATCH 24/32] 2022-06-05 --- .../unittests/test_triplet_margin_loss.py | 301 +++++++++++------- python/paddle/nn/functional/loss.py | 14 +- 2 files changed, 189 insertions(+), 126 deletions(-) diff --git a/python/paddle/fluid/tests/unittests/test_triplet_margin_loss.py b/python/paddle/fluid/tests/unittests/test_triplet_margin_loss.py index c8251c154d914..35449890e1817 100644 --- a/python/paddle/fluid/tests/unittests/test_triplet_margin_loss.py +++ b/python/paddle/fluid/tests/unittests/test_triplet_margin_loss.py @@ -16,41 +16,43 @@ import numpy as np import unittest -def call_TripletMarginLoss_layer(input, - positive, - negative, - p = 2, - margin=0.3, - swap=False, - eps = 1e-6, - reduction='mean',): - triplet_margin_loss = paddle.nn.TripletMarginLoss(p=p, - epsilon=eps, - margin=margin, - swap=swap, - reduction=reduction) - res = triplet_margin_loss(input=input, - positive=positive, - negative=negative,) + +def call_TripletMarginLoss_layer( + input, + positive, + negative, + p=2, + margin=0.3, + swap=False, + eps=1e-6, + reduction='mean', ): + triplet_margin_loss = paddle.nn.TripletMarginLoss( + p=p, epsilon=eps, margin=margin, swap=swap, reduction=reduction) + res = triplet_margin_loss( + input=input, + positive=positive, + negative=negative, ) return res -def call_TripletMarginLoss_functional(input, - positive, - negative, - p=2, - margin=0.3, - swap=False, - eps=1e-6, - reduction='mean',): - res = paddle.nn.functional.triplet_margin_loss(input=input, - positive=positive, - negative=negative, - p=p, - epsilon=eps, - margin=margin, - swap=swap, - reduction=reduction) +def call_TripletMarginLoss_functional( + input, + positive, + negative, + p=2, + margin=0.3, + swap=False, + eps=1e-6, + reduction='mean', ): + res = paddle.nn.functional.triplet_margin_loss( + input=input, + positive=positive, + negative=negative, + p=p, + epsilon=eps, + margin=margin, + swap=swap, + reduction=reduction) return res @@ -64,7 +66,6 @@ def test_static(place, eps=1e-6, reduction='mean', functional=False): - prog = paddle.static.Program() startup_prog = paddle.static.Program() with paddle.static.program_guard(prog, startup_prog): @@ -74,31 +75,38 @@ def test_static(place, name='positive', shape=positive_np.shape, dtype='float64') negative = paddle.static.data( name='negative', shape=negative_np.shape, dtype='float64') - feed_dict = {"input": input_np, "positive": positive_np, "negative": negative_np} + feed_dict = { + "input": input_np, + "positive": positive_np, + "negative": negative_np + } if functional: - res = call_TripletMarginLoss_functional(input=input, - positive=positive, - negative=negative, - p=p, - eps=eps, - margin=margin, - swap=swap, - reduction=reduction) + res = call_TripletMarginLoss_functional( + input=input, + positive=positive, + negative=negative, + p=p, + eps=eps, + margin=margin, + swap=swap, + reduction=reduction) else: - res = call_TripletMarginLoss_layer(input=input, - positive=positive, - negative=negative, - p=p, - eps=eps, - margin=margin, - swap=swap, - reduction=reduction) + res = call_TripletMarginLoss_layer( + input=input, + positive=positive, + negative=negative, + p=p, + eps=eps, + margin=margin, + swap=swap, + reduction=reduction) exe = paddle.static.Executor(place) static_result = exe.run(prog, feed=feed_dict, fetch_list=[res]) return static_result + def test_dygraph(place, input, positive, @@ -115,35 +123,38 @@ def test_dygraph(place, negative = paddle.to_tensor(negative) if functional: - dy_res = call_TripletMarginLoss_functional(input=input, - positive=positive, - negative=negative, - p=p, - eps=eps, - margin=margin, - swap=swap, - reduction=reduction) + dy_res = call_TripletMarginLoss_functional( + input=input, + positive=positive, + negative=negative, + p=p, + eps=eps, + margin=margin, + swap=swap, + reduction=reduction) else: - dy_res = call_TripletMarginLoss_layer(input=input, - positive=positive, - negative=negative, - p=p, - eps=eps, - margin=margin, - swap=swap, - reduction=reduction) + dy_res = call_TripletMarginLoss_layer( + input=input, + positive=positive, + negative=negative, + p=p, + eps=eps, + margin=margin, + swap=swap, + reduction=reduction) dy_result = dy_res.numpy() paddle.enable_static() return dy_result -def calc_triplet_margin_loss(input, - positive, - negative, - p=2, - margin=0.3, - swap=False, - reduction='mean',): +def calc_triplet_margin_loss( + input, + positive, + negative, + p=2, + margin=0.3, + swap=False, + reduction='mean', ): positive_dist = np.linalg.norm((input - positive), p, axis=1) negative_dist = np.linalg.norm((input - negative), p, axis=1) @@ -174,26 +185,40 @@ def test_TripletMarginLoss(self): reductions = ['sum', 'mean', 'none'] for place in places: for reduction in reductions: - expected = calc_triplet_margin_loss(input=input, positive=positive, negative=negative, - reduction=reduction) + expected = calc_triplet_margin_loss( + input=input, + positive=positive, + negative=negative, + reduction=reduction) - dy_result = test_dygraph(place=place, - input=input, positive=positive, negative=negative, - reduction=reduction,) + dy_result = test_dygraph( + place=place, + input=input, + positive=positive, + negative=negative, + reduction=reduction, ) - static_result = test_static(place=place, - input_np=input, positive_np=positive, negative_np=negative, - reduction=reduction,) + static_result = test_static( + place=place, + input_np=input, + positive_np=positive, + negative_np=negative, + reduction=reduction, ) self.assertTrue(np.allclose(static_result, expected)) self.assertTrue(np.allclose(static_result, dy_result)) self.assertTrue(np.allclose(dy_result, expected)) - static_functional = test_static(place=place, - input_np=input, positive_np=positive, negative_np=negative, - reduction=reduction, - functional=True) + static_functional = test_static( + place=place, + input_np=input, + positive_np=positive, + negative_np=negative, + reduction=reduction, + functional=True) dy_functional = test_dygraph( place=place, - input=input, positive=positive, negative=negative, + input=input, + positive=positive, + negative=negative, reduction=reduction, functional=True) self.assertTrue(np.allclose(static_functional, expected)) @@ -221,7 +246,7 @@ def test_TripletMarginLoss_error(self): def test_TripletMarginLoss_dimension(self): paddle.disable_static() - input = paddle.to_tensor([[0.1, 0.3],[1, 2]], dtype='float32') + input = paddle.to_tensor([[0.1, 0.3], [1, 2]], dtype='float32') positive = paddle.to_tensor([[0.0, 1.0]], dtype='float32') negative = paddle.to_tensor([[0.2, 0.1]], dtype='float32') self.assertRaises( @@ -229,14 +254,14 @@ def test_TripletMarginLoss_dimension(self): paddle.nn.functional.triplet_margin_loss, input=input, positive=positive, - negative=negative,) + negative=negative, ) TMLoss = paddle.nn.loss.TripletMarginLoss() self.assertRaises( ValueError, TMLoss, input=input, positive=positive, - negative=negative,) + negative=negative, ) paddle.enable_static() def test_TripletMarginLoss_swap(self): @@ -245,26 +270,45 @@ def test_TripletMarginLoss_swap(self): input = np.random.uniform(0.1, 0.8, size=(5, 5)).astype(np.float64) positive = np.random.uniform(0, 2, size=(5, 5)).astype(np.float64) negative = np.random.uniform(0, 2, size=(5, 5)).astype(np.float64) - expected = calc_triplet_margin_loss(input=input, swap=True, positive=positive, negative=negative, - reduction=reduction) - - dy_result = test_dygraph(place=place, swap=True, - input=input, positive=positive, negative=negative, - reduction=reduction, ) + expected = calc_triplet_margin_loss( + input=input, + swap=True, + positive=positive, + negative=negative, + reduction=reduction) - static_result = test_static(place=place, swap=True, - input_np=input, positive_np=positive, negative_np=negative, - reduction=reduction, ) + dy_result = test_dygraph( + place=place, + swap=True, + input=input, + positive=positive, + negative=negative, + reduction=reduction, ) + + static_result = test_static( + place=place, + swap=True, + input_np=input, + positive_np=positive, + negative_np=negative, + reduction=reduction, ) self.assertTrue(np.allclose(static_result, expected)) self.assertTrue(np.allclose(static_result, dy_result)) self.assertTrue(np.allclose(dy_result, expected)) - static_functional = test_static(place=place, swap=True, - input_np=input, positive_np=positive, negative_np=negative, - reduction=reduction, - functional=True) + static_functional = test_static( + place=place, + swap=True, + input_np=input, + positive_np=positive, + negative_np=negative, + reduction=reduction, + functional=True) dy_functional = test_dygraph( - place=place, swap=True, - input=input, positive=positive, negative=negative, + place=place, + swap=True, + input=input, + positive=positive, + negative=negative, reduction=reduction, functional=True) self.assertTrue(np.allclose(static_functional, expected)) @@ -294,26 +338,45 @@ def test_TripletMarginLoss_p(self): input = np.random.uniform(0.1, 0.8, size=(5, 5)).astype(np.float64) positive = np.random.uniform(0, 2, size=(5, 5)).astype(np.float64) negative = np.random.uniform(0, 2, size=(5, 5)).astype(np.float64) - expected = calc_triplet_margin_loss(input=input, p=p, positive=positive, negative=negative, - reduction=reduction) - - dy_result = test_dygraph(place=place, p=p, - input=input, positive=positive, negative=negative, - reduction=reduction,) + expected = calc_triplet_margin_loss( + input=input, + p=p, + positive=positive, + negative=negative, + reduction=reduction) - static_result = test_static(place=place, p=p, - input_np=input, positive_np=positive, negative_np=negative, - reduction=reduction,) + dy_result = test_dygraph( + place=place, + p=p, + input=input, + positive=positive, + negative=negative, + reduction=reduction, ) + + static_result = test_static( + place=place, + p=p, + input_np=input, + positive_np=positive, + negative_np=negative, + reduction=reduction, ) self.assertTrue(np.allclose(static_result, expected)) self.assertTrue(np.allclose(static_result, dy_result)) self.assertTrue(np.allclose(dy_result, expected)) - static_functional = test_static(place=place, p=p, - input_np=input, positive_np=positive, negative_np=negative, - reduction=reduction, - functional=True) + static_functional = test_static( + place=place, + p=p, + input_np=input, + positive_np=positive, + negative_np=negative, + reduction=reduction, + functional=True) dy_functional = test_dygraph( - place=place, p=p, - input=input, positive=positive, negative=negative, + place=place, + p=p, + input=input, + positive=positive, + negative=negative, reduction=reduction, functional=True) self.assertTrue(np.allclose(static_functional, expected)) diff --git a/python/paddle/nn/functional/loss.py b/python/paddle/nn/functional/loss.py index 4ebf2c472de7d..e312868d12bf4 100755 --- a/python/paddle/nn/functional/loss.py +++ b/python/paddle/nn/functional/loss.py @@ -2269,19 +2269,19 @@ def triplet_margin_loss(input, negative (Tensor): Negative tensor, the data type is float32 or float64. The shape of label is the same as the shape of input. - - margin (float, Optional): Default: :math:`1`. - + + margin (float, Optional): Default: :math:`1`. + p (int, Optional): The norm degree for pairwise distance. Default: :math:`2`. epsilon (float, Optional): Add small value to avoid division by zero, default value is 1e-6. - - swap (bool,Optional): The distance swap change the negative distance to the distance between + + swap (bool,Optional): The distance swap change the negative distance to the distance between positive sample and negative sample. For more details, see `Learning shallow convolutional feature descriptors with triplet losses`. - Default: ``False``. + Default: ``False``. + - reduction (str, Optional):Indicate how to average the loss by batch_size. the candicates are ``'none'`` | ``'mean'`` | ``'sum'``. If :attr:`reduction` is ``'none'``, the unreduced loss is returned; From a7d722f42d2e282a6aa3f14c3885de5ba4d0c997 Mon Sep 17 00:00:00 2001 From: yangguohao <1901212980@pku.edu.cn> Date: Mon, 6 Jun 2022 22:32:21 +0800 Subject: [PATCH 25/32] 2022-06-06 --- .../unittests/test_triplet_margin_loss.py | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/python/paddle/fluid/tests/unittests/test_triplet_margin_loss.py b/python/paddle/fluid/tests/unittests/test_triplet_margin_loss.py index 35449890e1817..86c8e775aaf08 100644 --- a/python/paddle/fluid/tests/unittests/test_triplet_margin_loss.py +++ b/python/paddle/fluid/tests/unittests/test_triplet_margin_loss.py @@ -175,9 +175,10 @@ def calc_triplet_margin_loss( class TestTripletMarginLoss(unittest.TestCase): def test_TripletMarginLoss(self): - input = np.random.uniform(0.1, 0.8, size=(5, 5)).astype(np.float64) - positive = np.random.uniform(0, 2, size=(5, 5)).astype(np.float64) - negative = np.random.uniform(0, 2, size=(5, 5)).astype(np.float64) + shape = (2, 2) + input = np.random.uniform(0.1, 0.8, size=shape).astype(np.float64) + positive = np.random.uniform(0, 2, size=shape).astype(np.float64) + negative = np.random.uniform(0, 2, size=shape).astype(np.float64) places = [paddle.CPUPlace()] if paddle.device.is_compiled_with_cuda(): @@ -267,9 +268,10 @@ def test_TripletMarginLoss_dimension(self): def test_TripletMarginLoss_swap(self): reduction = 'mean' place = paddle.CPUPlace() - input = np.random.uniform(0.1, 0.8, size=(5, 5)).astype(np.float64) - positive = np.random.uniform(0, 2, size=(5, 5)).astype(np.float64) - negative = np.random.uniform(0, 2, size=(5, 5)).astype(np.float64) + shape = (2, 2) + input = np.random.uniform(0.1, 0.8, size=shape).astype(np.float64) + positive = np.random.uniform(0, 2, size=shape).astype(np.float64) + negative = np.random.uniform(0, 2, size=shape).astype(np.float64) expected = calc_triplet_margin_loss( input=input, swap=True, @@ -333,11 +335,12 @@ def test_TripletMarginLoss_margin(self): def test_TripletMarginLoss_p(self): p = 3 + shape = (2, 2) reduction = 'mean' place = paddle.CPUPlace() - input = np.random.uniform(0.1, 0.8, size=(5, 5)).astype(np.float64) - positive = np.random.uniform(0, 2, size=(5, 5)).astype(np.float64) - negative = np.random.uniform(0, 2, size=(5, 5)).astype(np.float64) + input = np.random.uniform(0.1, 0.8, size=shape).astype(np.float64) + positive = np.random.uniform(0, 2, size=shape).astype(np.float64) + negative = np.random.uniform(0, 2, size=shape).astype(np.float64) expected = calc_triplet_margin_loss( input=input, p=p, From 8921f86d2c65508f1cabc752af3d19607a97c2d3 Mon Sep 17 00:00:00 2001 From: yangguohao <1901212980@pku.edu.cn> Date: Mon, 6 Jun 2022 22:32:21 +0800 Subject: [PATCH 26/32] 2022-06-06 --- .../unittests/test_triplet_margin_loss.py | 324 +++++++++--------- 1 file changed, 164 insertions(+), 160 deletions(-) diff --git a/python/paddle/fluid/tests/unittests/test_triplet_margin_loss.py b/python/paddle/fluid/tests/unittests/test_triplet_margin_loss.py index 86c8e775aaf08..745cb6a178032 100644 --- a/python/paddle/fluid/tests/unittests/test_triplet_margin_loss.py +++ b/python/paddle/fluid/tests/unittests/test_triplet_margin_loss.py @@ -18,41 +18,46 @@ def call_TripletMarginLoss_layer( - input, - positive, - negative, - p=2, - margin=0.3, - swap=False, - eps=1e-6, - reduction='mean', ): - triplet_margin_loss = paddle.nn.TripletMarginLoss( - p=p, epsilon=eps, margin=margin, swap=swap, reduction=reduction) + input, + positive, + negative, + p=2, + margin=0.3, + swap=False, + eps=1e-6, + reduction='mean', +): + triplet_margin_loss = paddle.nn.TripletMarginLoss(p=p, + epsilon=eps, + margin=margin, + swap=swap, + reduction=reduction) res = triplet_margin_loss( input=input, positive=positive, - negative=negative, ) + negative=negative, + ) return res def call_TripletMarginLoss_functional( - input, - positive, - negative, - p=2, - margin=0.3, - swap=False, - eps=1e-6, - reduction='mean', ): - res = paddle.nn.functional.triplet_margin_loss( - input=input, - positive=positive, - negative=negative, - p=p, - epsilon=eps, - margin=margin, - swap=swap, - reduction=reduction) + input, + positive, + negative, + p=2, + margin=0.3, + swap=False, + eps=1e-6, + reduction='mean', +): + res = paddle.nn.functional.triplet_margin_loss(input=input, + positive=positive, + negative=negative, + p=p, + epsilon=eps, + margin=margin, + swap=swap, + reduction=reduction) return res @@ -69,12 +74,15 @@ def test_static(place, prog = paddle.static.Program() startup_prog = paddle.static.Program() with paddle.static.program_guard(prog, startup_prog): - input = paddle.static.data( - name='input', shape=input_np.shape, dtype='float64') - positive = paddle.static.data( - name='positive', shape=positive_np.shape, dtype='float64') - negative = paddle.static.data( - name='negative', shape=negative_np.shape, dtype='float64') + input = paddle.static.data(name='input', + shape=input_np.shape, + dtype='float64') + positive = paddle.static.data(name='positive', + shape=positive_np.shape, + dtype='float64') + negative = paddle.static.data(name='negative', + shape=negative_np.shape, + dtype='float64') feed_dict = { "input": input_np, "positive": positive_np, @@ -82,25 +90,23 @@ def test_static(place, } if functional: - res = call_TripletMarginLoss_functional( - input=input, - positive=positive, - negative=negative, - p=p, - eps=eps, - margin=margin, - swap=swap, - reduction=reduction) + res = call_TripletMarginLoss_functional(input=input, + positive=positive, + negative=negative, + p=p, + eps=eps, + margin=margin, + swap=swap, + reduction=reduction) else: - res = call_TripletMarginLoss_layer( - input=input, - positive=positive, - negative=negative, - p=p, - eps=eps, - margin=margin, - swap=swap, - reduction=reduction) + res = call_TripletMarginLoss_layer(input=input, + positive=positive, + negative=negative, + p=p, + eps=eps, + margin=margin, + swap=swap, + reduction=reduction) exe = paddle.static.Executor(place) static_result = exe.run(prog, feed=feed_dict, fetch_list=[res]) @@ -123,38 +129,37 @@ def test_dygraph(place, negative = paddle.to_tensor(negative) if functional: - dy_res = call_TripletMarginLoss_functional( - input=input, - positive=positive, - negative=negative, - p=p, - eps=eps, - margin=margin, - swap=swap, - reduction=reduction) + dy_res = call_TripletMarginLoss_functional(input=input, + positive=positive, + negative=negative, + p=p, + eps=eps, + margin=margin, + swap=swap, + reduction=reduction) else: - dy_res = call_TripletMarginLoss_layer( - input=input, - positive=positive, - negative=negative, - p=p, - eps=eps, - margin=margin, - swap=swap, - reduction=reduction) + dy_res = call_TripletMarginLoss_layer(input=input, + positive=positive, + negative=negative, + p=p, + eps=eps, + margin=margin, + swap=swap, + reduction=reduction) dy_result = dy_res.numpy() paddle.enable_static() return dy_result def calc_triplet_margin_loss( - input, - positive, - negative, - p=2, - margin=0.3, - swap=False, - reduction='mean', ): + input, + positive, + negative, + p=2, + margin=0.3, + swap=False, + reduction='mean', +): positive_dist = np.linalg.norm((input - positive), p, axis=1) negative_dist = np.linalg.norm((input - negative), p, axis=1) @@ -174,6 +179,7 @@ def calc_triplet_margin_loss( class TestTripletMarginLoss(unittest.TestCase): + def test_TripletMarginLoss(self): shape = (2, 2) input = np.random.uniform(0.1, 0.8, size=shape).astype(np.float64) @@ -186,62 +192,59 @@ def test_TripletMarginLoss(self): reductions = ['sum', 'mean', 'none'] for place in places: for reduction in reductions: - expected = calc_triplet_margin_loss( - input=input, - positive=positive, - negative=negative, - reduction=reduction) + expected = calc_triplet_margin_loss(input=input, + positive=positive, + negative=negative, + reduction=reduction) dy_result = test_dygraph( place=place, input=input, positive=positive, negative=negative, - reduction=reduction, ) + reduction=reduction, + ) static_result = test_static( place=place, input_np=input, positive_np=positive, negative_np=negative, - reduction=reduction, ) + reduction=reduction, + ) self.assertTrue(np.allclose(static_result, expected)) self.assertTrue(np.allclose(static_result, dy_result)) self.assertTrue(np.allclose(dy_result, expected)) - static_functional = test_static( - place=place, - input_np=input, - positive_np=positive, - negative_np=negative, - reduction=reduction, - functional=True) - dy_functional = test_dygraph( - place=place, - input=input, - positive=positive, - negative=negative, - reduction=reduction, - functional=True) + static_functional = test_static(place=place, + input_np=input, + positive_np=positive, + negative_np=negative, + reduction=reduction, + functional=True) + dy_functional = test_dygraph(place=place, + input=input, + positive=positive, + negative=negative, + reduction=reduction, + functional=True) self.assertTrue(np.allclose(static_functional, expected)) self.assertTrue(np.allclose(static_functional, dy_functional)) self.assertTrue(np.allclose(dy_functional, expected)) def test_TripletMarginLoss_error(self): paddle.disable_static() - self.assertRaises( - ValueError, - paddle.nn.loss.TripletMarginLoss, - reduction="unsupport reduction") + self.assertRaises(ValueError, + paddle.nn.loss.TripletMarginLoss, + reduction="unsupport reduction") input = paddle.to_tensor([[0.1, 0.3]], dtype='float32') positive = paddle.to_tensor([[0.0, 1.0]], dtype='float32') negative = paddle.to_tensor([[0.2, 0.1]], dtype='float32') - self.assertRaises( - ValueError, - paddle.nn.functional.triplet_margin_loss, - input=input, - positive=positive, - negative=negative, - reduction="unsupport reduction") + self.assertRaises(ValueError, + paddle.nn.functional.triplet_margin_loss, + input=input, + positive=positive, + negative=negative, + reduction="unsupport reduction") paddle.enable_static() def test_TripletMarginLoss_dimension(self): @@ -255,14 +258,16 @@ def test_TripletMarginLoss_dimension(self): paddle.nn.functional.triplet_margin_loss, input=input, positive=positive, - negative=negative, ) + negative=negative, + ) TMLoss = paddle.nn.loss.TripletMarginLoss() self.assertRaises( ValueError, TMLoss, input=input, positive=positive, - negative=negative, ) + negative=negative, + ) paddle.enable_static() def test_TripletMarginLoss_swap(self): @@ -272,12 +277,11 @@ def test_TripletMarginLoss_swap(self): input = np.random.uniform(0.1, 0.8, size=shape).astype(np.float64) positive = np.random.uniform(0, 2, size=shape).astype(np.float64) negative = np.random.uniform(0, 2, size=shape).astype(np.float64) - expected = calc_triplet_margin_loss( - input=input, - swap=True, - positive=positive, - negative=negative, - reduction=reduction) + expected = calc_triplet_margin_loss(input=input, + swap=True, + positive=positive, + negative=negative, + reduction=reduction) dy_result = test_dygraph( place=place, @@ -285,7 +289,8 @@ def test_TripletMarginLoss_swap(self): input=input, positive=positive, negative=negative, - reduction=reduction, ) + reduction=reduction, + ) static_result = test_static( place=place, @@ -293,26 +298,25 @@ def test_TripletMarginLoss_swap(self): input_np=input, positive_np=positive, negative_np=negative, - reduction=reduction, ) + reduction=reduction, + ) self.assertTrue(np.allclose(static_result, expected)) self.assertTrue(np.allclose(static_result, dy_result)) self.assertTrue(np.allclose(dy_result, expected)) - static_functional = test_static( - place=place, - swap=True, - input_np=input, - positive_np=positive, - negative_np=negative, - reduction=reduction, - functional=True) - dy_functional = test_dygraph( - place=place, - swap=True, - input=input, - positive=positive, - negative=negative, - reduction=reduction, - functional=True) + static_functional = test_static(place=place, + swap=True, + input_np=input, + positive_np=positive, + negative_np=negative, + reduction=reduction, + functional=True) + dy_functional = test_dygraph(place=place, + swap=True, + input=input, + positive=positive, + negative=negative, + reduction=reduction, + functional=True) self.assertTrue(np.allclose(static_functional, expected)) self.assertTrue(np.allclose(static_functional, dy_functional)) self.assertTrue(np.allclose(dy_functional, expected)) @@ -330,7 +334,8 @@ def test_TripletMarginLoss_margin(self): margin=margin, input=input, positive=positive, - negative=negative, ) + negative=negative, + ) paddle.enable_static() def test_TripletMarginLoss_p(self): @@ -341,12 +346,11 @@ def test_TripletMarginLoss_p(self): input = np.random.uniform(0.1, 0.8, size=shape).astype(np.float64) positive = np.random.uniform(0, 2, size=shape).astype(np.float64) negative = np.random.uniform(0, 2, size=shape).astype(np.float64) - expected = calc_triplet_margin_loss( - input=input, - p=p, - positive=positive, - negative=negative, - reduction=reduction) + expected = calc_triplet_margin_loss(input=input, + p=p, + positive=positive, + negative=negative, + reduction=reduction) dy_result = test_dygraph( place=place, @@ -354,7 +358,8 @@ def test_TripletMarginLoss_p(self): input=input, positive=positive, negative=negative, - reduction=reduction, ) + reduction=reduction, + ) static_result = test_static( place=place, @@ -362,26 +367,25 @@ def test_TripletMarginLoss_p(self): input_np=input, positive_np=positive, negative_np=negative, - reduction=reduction, ) + reduction=reduction, + ) self.assertTrue(np.allclose(static_result, expected)) self.assertTrue(np.allclose(static_result, dy_result)) self.assertTrue(np.allclose(dy_result, expected)) - static_functional = test_static( - place=place, - p=p, - input_np=input, - positive_np=positive, - negative_np=negative, - reduction=reduction, - functional=True) - dy_functional = test_dygraph( - place=place, - p=p, - input=input, - positive=positive, - negative=negative, - reduction=reduction, - functional=True) + static_functional = test_static(place=place, + p=p, + input_np=input, + positive_np=positive, + negative_np=negative, + reduction=reduction, + functional=True) + dy_functional = test_dygraph(place=place, + p=p, + input=input, + positive=positive, + negative=negative, + reduction=reduction, + functional=True) self.assertTrue(np.allclose(static_functional, expected)) self.assertTrue(np.allclose(static_functional, dy_functional)) self.assertTrue(np.allclose(dy_functional, expected)) From 719341b60967f396eb5209917452bf50938fbe5a Mon Sep 17 00:00:00 2001 From: yangguohao <1901212980@pku.edu.cn> Date: Tue, 7 Jun 2022 14:36:15 +0800 Subject: [PATCH 27/32] code_style_check --- python/paddle/nn/layer/loss.py | 39 +++++++++++++++++----------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/python/paddle/nn/layer/loss.py b/python/paddle/nn/layer/loss.py index 5547f5503bc78..35fcafe4ac5c2 100644 --- a/python/paddle/nn/layer/loss.py +++ b/python/paddle/nn/layer/loss.py @@ -1332,16 +1332,16 @@ class TripletMarginLoss(Layer): d(x_i, y_i) = \left\lVert {\bf x}_i - {\bf y}_i \right\rVert_p Parameters: - margin (float, Optional):Default: :math:`1`. - - p (int, Optional):The norm degree for pairwise distance. Default: :math:`2`. - + margin (float, Optional):Default: :math:`1`. + + p (int, Optional):The norm degree for pairwise distance. Default: :math:`2`. + epsilon (float, Optional):Add small value to avoid division by zero, default value is 1e-6. - + swap (bool, Optional):The distance swap change the negative distance to the distance between positive sample and negative sample. For more details, see `Learning shallow convolutional feature descriptors with triplet losses`. - Default: ``False``. + Default: ``False``. reduction (str, Optional):Indicate how to average the loss by batch_size. the candicates are ``'none'`` | ``'mean'`` | ``'sum'``. @@ -1349,19 +1349,19 @@ class TripletMarginLoss(Layer): If :attr:`reduction` is ``'mean'``, the reduced mean loss is returned; If :attr:`reduction` is ``'sum'``, the summed loss is returned. Default: ``'mean'`` - + name (str,Optional): Name for the operation (optional, default is None). For more information, please refer to :ref:`api_guide_Name`. Call Parameters: input (Tensor):Input tensor, the data type is float32 or float64. - the shape is [N, \*], N is batch size and `\*` means any number of additional dimensions, available dtype is float32, float64. + the shape is [N, \*], N is batch size and `\*` means any number of additional dimensions, available dtype is float32, float64. positive (Tensor):Positive tensor, the data type is float32 or float64. - The shape of label is the same as the shape of input. + The shape of label is the same as the shape of input. negative (Tensor):Negative tensor, the data type is float32 or float64. - The shape of label is the same as the shape of input. + The shape of label is the same as the shape of input. Returns: Tensor. The tensor variable storing the triplet_margin_loss of input and positive and negative. @@ -1407,13 +1407,12 @@ def __init__(self, self.name = name def forward(self, input, positive, negative): - return F.triplet_margin_loss( - input, - positive, - negative, - margin=self.margin, - p=self.p, - epsilon=self.epsilon, - swap=self.swap, - reduction=self.reduction, - name=self.name) + return F.triplet_margin_loss(input, + positive, + negative, + margin=self.margin, + p=self.p, + epsilon=self.epsilon, + swap=self.swap, + reduction=self.reduction, + name=self.name) From 4b7275211c3b10f011baa5d0bb7ed0ec152f0c0c Mon Sep 17 00:00:00 2001 From: yangguohao <1901212980@pku.edu.cn> Date: Tue, 7 Jun 2022 14:36:15 +0800 Subject: [PATCH 28/32] code_style_check --- python/paddle/nn/__init__.py | 5 ++--- python/paddle/nn/functional/__init__.py | 3 +-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/python/paddle/nn/__init__.py b/python/paddle/nn/__init__.py index e5bc22688fce4..b73b7a094a87a 100644 --- a/python/paddle/nn/__init__.py +++ b/python/paddle/nn/__init__.py @@ -154,7 +154,7 @@ from . import initializer # noqa: F401 from . import quant # noqa: F401 -#TODO: remove 'diag_embed', 'remove_weight_norm', 'weight_norm' months later. +# TODO: remove 'diag_embed', 'remove_weight_norm', 'weight_norm' months later. import paddle.utils.deprecated as deprecated @@ -191,8 +191,7 @@ def weight_norm(*args): return utils.weight_norm(*args) - -__all__ = [ #noqa +__all__ = [ # noqa 'BatchNorm', 'CELU', 'GroupNorm', diff --git a/python/paddle/nn/functional/__init__.py b/python/paddle/nn/functional/__init__.py index 7e7344c8ebcf6..72d397a1120b6 100644 --- a/python/paddle/nn/functional/__init__.py +++ b/python/paddle/nn/functional/__init__.py @@ -125,8 +125,7 @@ from .sparse_attention import sparse_attention - -__all__ = [ #noqa +__all__ = [ # noqa 'celu', 'conv1d', 'conv1d_transpose', From 463b42d0099a1fa99b9b0b6f28f15b6e06b9bfb6 Mon Sep 17 00:00:00 2001 From: yangguohao <70266361+yangguohao@users.noreply.github.com> Date: Tue, 7 Jun 2022 18:16:55 +0800 Subject: [PATCH 29/32] Update loss.py --- python/paddle/nn/layer/loss.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/python/paddle/nn/layer/loss.py b/python/paddle/nn/layer/loss.py index 35fcafe4ac5c2..54b1db74c82a6 100644 --- a/python/paddle/nn/layer/loss.py +++ b/python/paddle/nn/layer/loss.py @@ -1370,12 +1370,11 @@ class TripletMarginLoss(Layer): .. code-block:: python import paddle - import paddle.nn.TripletMarginLoss input = paddle.to_tensor([[1, 5, 3], [0, 3, 2], [1, 4, 1]], dtype=paddle.float32) positive= paddle.to_tensor([[5, 1, 2], [3, 2, 1], [3, -1, 1]], dtype=paddle.float32) negative = paddle.to_tensor([[2, 1, -3], [1, 1, -1], [4, -2, 1]], dtype=paddle.float32) - triplet_margin_loss = TripletMarginLoss() + triplet_margin_loss = paddle.nn.TripletMarginLoss() loss = triplet_margin_loss(input, positive, negative, reduction='none') print(loss) # Tensor([0. , 0.57496738, 0. ]) From 234f4697dfb6d30e32e8c516c47be6a3d1100751 Mon Sep 17 00:00:00 2001 From: yangguohao <1901212980@pku.edu.cn> Date: Tue, 7 Jun 2022 21:21:29 +0800 Subject: [PATCH 30/32] 2022-06-07_V2 --- python/paddle/nn/layer/loss.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/python/paddle/nn/layer/loss.py b/python/paddle/nn/layer/loss.py index 54b1db74c82a6..7ce9f88004464 100644 --- a/python/paddle/nn/layer/loss.py +++ b/python/paddle/nn/layer/loss.py @@ -1374,13 +1374,13 @@ class TripletMarginLoss(Layer): input = paddle.to_tensor([[1, 5, 3], [0, 3, 2], [1, 4, 1]], dtype=paddle.float32) positive= paddle.to_tensor([[5, 1, 2], [3, 2, 1], [3, -1, 1]], dtype=paddle.float32) negative = paddle.to_tensor([[2, 1, -3], [1, 1, -1], [4, -2, 1]], dtype=paddle.float32) - triplet_margin_loss = paddle.nn.TripletMarginLoss() - loss = triplet_margin_loss(input, positive, negative, reduction='none') + triplet_margin_loss = paddle.nn.TripletMarginLoss(reduction='none') + loss = triplet_margin_loss(input, positive, negative) print(loss) # Tensor([0. , 0.57496738, 0. ]) - - loss = triplet_margin_loss(input, positive, negative, margin=1.0, reduction='mean') + triplet_margin_loss = paddle.nn.TripletMarginLoss( margin=1.0, swap=True, reduction='mean', ) + loss = triplet_margin_loss(input, positive, negative,) print(loss) # Tensor([0.19165580]) From e6793b95b0829c57ea54224a4bfec950e0a47f7e Mon Sep 17 00:00:00 2001 From: yangguohao <70266361+yangguohao@users.noreply.github.com> Date: Mon, 13 Jun 2022 15:06:56 +0800 Subject: [PATCH 31/32] Update loss.py --- python/paddle/nn/layer/loss.py | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/python/paddle/nn/layer/loss.py b/python/paddle/nn/layer/loss.py index 6ef82ccfc4139..fc0ae39ca4345 100644 --- a/python/paddle/nn/layer/loss.py +++ b/python/paddle/nn/layer/loss.py @@ -1485,7 +1485,7 @@ def __init__(self, distance_function=None, margin=1.0, swap=False, - reduction: str='mean', + reduction: str = 'mean', name=None): super(TripletMarginWithDistanceLoss, self).__init__() if reduction not in ['sum', 'mean', 'none']: @@ -1500,14 +1500,13 @@ def __init__(self, self.name = name def forward(self, input, positive, negative): - return F.triplet_margin_with_distance_loss( - input, - positive, - negative, - margin=self.margin, - swap=self.swap, - reduction=self.reduction, - name=self.name) + return F.triplet_margin_with_distance_loss(input, + positive, + negative, + margin=self.margin, + swap=self.swap, + reduction=self.reduction, + name=self.name) class TripletMarginLoss(Layer): @@ -1569,18 +1568,17 @@ class TripletMarginLoss(Layer): .. code-block:: python import paddle - import paddle.nn.TripletMarginLoss input = paddle.to_tensor([[1, 5, 3], [0, 3, 2], [1, 4, 1]], dtype=paddle.float32) positive= paddle.to_tensor([[5, 1, 2], [3, 2, 1], [3, -1, 1]], dtype=paddle.float32) negative = paddle.to_tensor([[2, 1, -3], [1, 1, -1], [4, -2, 1]], dtype=paddle.float32) - triplet_margin_loss = TripletMarginLoss() - loss = triplet_margin_loss(input, positive, negative, reduction='none') + triplet_margin_loss = paddle.nn.TripletMarginLoss(reduction='none') + loss = triplet_margin_loss(input, positive, negative) print(loss) # Tensor([0. , 0.57496738, 0. ]) - - - loss = triplet_margin_loss(input, positive, negative, margin=1.0, reduction='mean') + + triplet_margin_loss = paddle.nn.TripletMarginLoss(margin=1.0, swap=True, reduction='mean', ) + loss = triplet_margin_loss(input, positive, negative,) print(loss) # Tensor([0.19165580]) From eecb30f3203ada990b28983aa19b2d54eb6fa070 Mon Sep 17 00:00:00 2001 From: yangguohao <70266361+yangguohao@users.noreply.github.com> Date: Mon, 13 Jun 2022 15:08:07 +0800 Subject: [PATCH 32/32] Update loss.py --- python/paddle/nn/layer/loss.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/python/paddle/nn/layer/loss.py b/python/paddle/nn/layer/loss.py index fc0ae39ca4345..1e72548ecc138 100644 --- a/python/paddle/nn/layer/loss.py +++ b/python/paddle/nn/layer/loss.py @@ -1501,12 +1501,12 @@ def __init__(self, def forward(self, input, positive, negative): return F.triplet_margin_with_distance_loss(input, - positive, - negative, - margin=self.margin, - swap=self.swap, - reduction=self.reduction, - name=self.name) + positive, + negative, + margin=self.margin, + swap=self.swap, + reduction=self.reduction, + name=self.name) class TripletMarginLoss(Layer):