72 lines
2.3 KiB
Python
72 lines
2.3 KiB
Python
# Copyright (c) 2026 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.
|
|
|
|
"""
|
|
CPU unit test for L1NormGradKernel
|
|
(paddle/phi/kernels/cpu/l1_norm_grad_kernel.cc).
|
|
|
|
Kernel formula: dX = dout * sign(X)
|
|
sign(x) = +1 if x > 0, -1 if x < 0, 0 if x == 0
|
|
"""
|
|
|
|
import unittest
|
|
|
|
import numpy as np
|
|
|
|
import paddle
|
|
|
|
|
|
class TestL1NormGradKernel(unittest.TestCase):
|
|
def setUp(self):
|
|
paddle.disable_static()
|
|
paddle.set_device('cpu')
|
|
|
|
def test_basic(self):
|
|
"""dX = dout * sign(X); loss = l1_norm(x), dout = 1."""
|
|
x_np = np.array([-3.0, 1.0, -2.0, 4.0], dtype='float32')
|
|
|
|
x = paddle.to_tensor(x_np, stop_gradient=False)
|
|
loss = paddle.norm(x, p=1) # sum(abs(x))
|
|
loss.backward()
|
|
|
|
# expected: sign(x) * 1.0
|
|
expected = np.sign(x_np).astype('float32')
|
|
np.testing.assert_allclose(x.grad.numpy(), expected, rtol=1e-6)
|
|
|
|
def test_2d_input(self):
|
|
"""2-D input flattened inside the kernel; same formula applies."""
|
|
x_np = np.array([[1.0, -2.0], [-3.0, 4.0]], dtype='float32')
|
|
|
|
x = paddle.to_tensor(x_np, stop_gradient=False)
|
|
loss = paddle.norm(x, p=1)
|
|
loss.backward()
|
|
|
|
expected = np.sign(x_np).astype('float32')
|
|
np.testing.assert_allclose(x.grad.numpy(), expected, rtol=1e-6)
|
|
|
|
def test_scaled_dout(self):
|
|
"""Wrap l1_norm in a chain to get dout != 1: loss = 3 * l1_norm(x)."""
|
|
x_np = np.array([-1.0, 2.0, -3.0], dtype='float32')
|
|
|
|
x = paddle.to_tensor(x_np, stop_gradient=False)
|
|
loss = 3.0 * paddle.norm(x, p=1)
|
|
loss.backward()
|
|
|
|
expected = 3.0 * np.sign(x_np).astype('float32')
|
|
np.testing.assert_allclose(x.grad.numpy(), expected, rtol=1e-6)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
unittest.main()
|