Files
paddlepaddle--paddle/test/legacy_test/test_legacy_loss_args.py
T
2026-07-13 12:40:42 +08:00

211 lines
7.5 KiB
Python

# Copyright (c) 2025 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 unittest
import warnings
import paddle
from paddle.nn import (
BCELoss,
BCEWithLogitsLoss,
CosineEmbeddingLoss,
CrossEntropyLoss,
HingeEmbeddingLoss,
KLDivLoss,
L1Loss,
MarginRankingLoss,
MSELoss,
MultiLabelMarginLoss,
MultiLabelSoftMarginLoss,
MultiMarginLoss,
NLLLoss,
PoissonNLLLoss,
SmoothL1Loss,
SoftMarginLoss,
TripletMarginLoss,
)
def _get_reduction(loss):
return getattr(loss, 'reduction', None) or getattr(loss, '_reduction', None)
class TestLegacyLossArgs(unittest.TestCase):
def assertSuggests(self, loss_ctor, expected_reduction, **legacy_kwargs):
# Legacy kwargs are translated (not raised). Verify the resulting
# reduction matches the expected value and a DeprecationWarning fires.
with warnings.catch_warnings(record=True) as caught:
warnings.simplefilter('always')
loss = loss_ctor(**legacy_kwargs)
self.assertEqual(_get_reduction(loss), expected_reduction)
self.assertTrue(
any(issubclass(w.category, DeprecationWarning) for w in caught),
f"Expected DeprecationWarning when using legacy args, got: {caught}",
)
def test_no_legacy_all_constructible(self):
# Ensure all 17 losses still construct with reduction only
ctors = [
L1Loss,
NLLLoss,
PoissonNLLLoss,
KLDivLoss,
MSELoss,
BCELoss,
BCEWithLogitsLoss,
HingeEmbeddingLoss,
MultiLabelMarginLoss,
SmoothL1Loss,
SoftMarginLoss,
CrossEntropyLoss,
MultiLabelSoftMarginLoss,
CosineEmbeddingLoss,
MarginRankingLoss,
MultiMarginLoss,
TripletMarginLoss,
]
for ctor in ctors:
_ = ctor(reduction='mean')
def test_no_args_all_constructible_with_defaults(self):
# Ensure all 17 losses construct with default args (no legacy, no explicit reduction)
ctors = [
L1Loss,
NLLLoss,
PoissonNLLLoss,
KLDivLoss,
MSELoss,
BCELoss,
BCEWithLogitsLoss,
HingeEmbeddingLoss,
MultiLabelMarginLoss,
SmoothL1Loss,
SoftMarginLoss,
CrossEntropyLoss,
MultiLabelSoftMarginLoss,
CosineEmbeddingLoss,
MarginRankingLoss,
MultiMarginLoss,
TripletMarginLoss,
]
for ctor in ctors:
_ = ctor()
# Cover legacy combos across the family (not each loss needs all combos)
def test_cross_entropy_reduce_false(self):
self.assertSuggests(CrossEntropyLoss, 'none', reduce=False)
def test_mse_reduce_true_size_average_false(self):
self.assertSuggests(MSELoss, 'sum', reduce=True, size_average=False)
def test_bcewithlogits_reduce_true_size_average_true(self):
self.assertSuggests(
BCEWithLogitsLoss, 'mean', reduce=True, size_average=True
)
def test_l1_size_average_false_only(self):
self.assertSuggests(L1Loss, 'sum', size_average=False)
def test_kldiv_reduce_true_size_average_none(self):
self.assertSuggests(KLDivLoss, 'mean', reduce=True, size_average=None)
def test_multimargin_reduce_false(self):
self.assertSuggests(MultiMarginLoss, 'none', reduce=False)
def test_multilabel_margin_size_average_false(self):
self.assertSuggests(MultiLabelMarginLoss, 'sum', size_average=False)
def test_cosine_embedding_reduce_true_size_average_true(self):
self.assertSuggests(
CosineEmbeddingLoss, 'mean', reduce=True, size_average=True
)
def test_margin_ranking_reduce_true_size_average_false(self):
self.assertSuggests(
MarginRankingLoss, 'sum', reduce=True, size_average=False
)
def test_soft_margin_reduce_false(self):
self.assertSuggests(SoftMarginLoss, 'none', reduce=False)
def test_smooth_l1_size_average_false(self):
self.assertSuggests(SmoothL1Loss, 'sum', size_average=False)
def test_bce_reduce_true_size_average_true(self):
self.assertSuggests(BCELoss, 'mean', reduce=True, size_average=True)
def test_nll_reduce_true_size_average_none(self):
self.assertSuggests(NLLLoss, 'mean', reduce=True, size_average=None)
def test_poisson_nll_reduce_false(self):
self.assertSuggests(PoissonNLLLoss, 'none', reduce=False)
def test_multilabel_soft_margin_size_average_false(self):
self.assertSuggests(MultiLabelSoftMarginLoss, 'sum', size_average=False)
def test_triplet_margin_reduce_true_size_average_false(self):
self.assertSuggests(
TripletMarginLoss, 'sum', reduce=True, size_average=False
)
def test_ce_positional_soft_label_guard_by_ignore_index(self):
# CrossEntropyLoss(weight=None, ignore_index=int, reduction='mean', soft_label=True)
w = paddle.ones([3], dtype='float32')
_ = CrossEntropyLoss(w, -100, 'mean', True)
def test_ce_positional_legacy_reduce_trigger(self):
# CrossEntropyLoss(weight=None, size_average=True, ignore_index, reduce=True)
# PyTorch positional layout is translated into reduction='mean'.
with warnings.catch_warnings(record=True) as caught:
warnings.simplefilter('always')
w = paddle.ones([3], dtype='float32')
loss = CrossEntropyLoss(w, True, -100, True)
self.assertEqual(_get_reduction(loss), 'mean')
self.assertTrue(
any(issubclass(w.category, DeprecationWarning) for w in caught)
)
def test_kldiv_positional_log_target_guard(self):
# KLDivLoss(reduction='mean', log_target=True)
_ = KLDivLoss('mean', True)
def test_kldiv_positional_legacy_reduce_trigger(self):
# KLDivLoss(log_target=True)(Not provide reduction string, treat as legacy reduce)
with warnings.catch_warnings(record=True) as caught:
warnings.simplefilter('always')
loss = KLDivLoss(True)
self.assertEqual(_get_reduction(loss), 'mean')
self.assertTrue(
any(issubclass(w.category, DeprecationWarning) for w in caught)
)
def test_poisson_positional_eps_float_guard(self):
# PoissonNLLLoss(log_input, full, eps)
_ = PoissonNLLLoss(True, False, 1e-8)
def test_poisson_positional_legacy_reduce_trigger(self):
# PoissonNLLLoss(log_input, full, size_average=True, epsilon, reduce=True)
with warnings.catch_warnings(record=True) as caught:
warnings.simplefilter('always')
loss = PoissonNLLLoss(True, False, True, 1e-8, True)
self.assertEqual(_get_reduction(loss), 'mean')
self.assertTrue(
any(issubclass(w.category, DeprecationWarning) for w in caught)
)
if __name__ == '__main__':
unittest.main()