# 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. """ 分布式概率分布单元测试 / Probability Distribution Unit Tests 测试目标 / Test Target: paddle.distribution 模块 (覆盖率约84.2%) 覆盖的模块 / Covered Modules: - paddle.distribution.Normal: 正态分布 - paddle.distribution.Uniform: 均匀分布 - paddle.distribution.Categorical: 类别分布 - paddle.distribution.Bernoulli: 伯努利分布 - paddle.distribution.Beta: Beta分布 - paddle.distribution.Dirichlet: Dirichlet分布 - paddle.distribution.Geometric: 几何分布 - paddle.distribution.LogNormal: 对数正态分布 作用 / Purpose: 覆盖各类概率分布的sample、log_prob、entropy、cdf等操作路径, 补充概率分布模块中未被测试覆盖的代码路径。 """ import unittest import numpy as np import paddle import paddle.distribution as dist paddle.disable_static() class TestNormalDistribution(unittest.TestCase): """测试正态分布 / Test Normal distribution""" def test_normal_sample(self): """测试正态分布采样 / Test Normal distribution sampling""" normal = dist.Normal(loc=0.0, scale=1.0) samples = normal.sample([100]) self.assertEqual(samples.shape, [100]) def test_normal_log_prob(self): """测试正态分布对数概率 / Test Normal log probability""" normal = dist.Normal(loc=0.0, scale=1.0) x = paddle.to_tensor([0.0, 1.0, -1.0]) log_prob = normal.log_prob(x) self.assertEqual(log_prob.shape, [3]) def test_normal_entropy(self): """测试正态分布熵 / Test Normal entropy""" normal = dist.Normal(loc=0.0, scale=1.0) entropy = normal.entropy() self.assertIsNotNone(entropy) self.assertTrue(entropy.item() > 0) def test_normal_mean_variance(self): """测试正态分布均值和方差 / Test Normal mean and variance""" normal = dist.Normal(loc=2.0, scale=3.0) self.assertAlmostEqual(float(normal.mean.numpy()), 2.0, places=5) self.assertAlmostEqual(float(normal.variance.numpy()), 9.0, places=5) def test_normal_kl_divergence(self): """测试正态分布KL散度 / Test Normal KL divergence""" p = dist.Normal(loc=0.0, scale=1.0) q = dist.Normal(loc=1.0, scale=2.0) kl = paddle.distribution.kl_divergence(p, q) self.assertTrue(kl.item() >= 0) def test_normal_batch(self): """测试批量正态分布 / Test batched Normal distribution""" loc = paddle.to_tensor([0.0, 1.0, 2.0]) scale = paddle.to_tensor([1.0, 1.0, 1.0]) normal = dist.Normal(loc=loc, scale=scale) samples = normal.sample([10]) self.assertEqual(samples.shape, [10, 3]) class TestUniformDistribution(unittest.TestCase): """测试均匀分布 / Test Uniform distribution""" def test_uniform_sample(self): """测试均匀分布采样 / Test Uniform sampling""" uniform = dist.Uniform(low=0.0, high=1.0) samples = uniform.sample([100]) self.assertEqual(samples.shape, [100]) self.assertTrue(paddle.all(samples >= 0.0).item()) self.assertTrue(paddle.all(samples <= 1.0).item()) def test_uniform_log_prob(self): """测试均匀分布对数概率 / Test Uniform log probability""" uniform = dist.Uniform(low=0.0, high=1.0) x = paddle.to_tensor([0.5]) log_prob = uniform.log_prob(x) self.assertAlmostEqual(log_prob.numpy()[0], 0.0, places=5) def test_uniform_entropy(self): """测试均匀分布熵 / Test Uniform entropy""" uniform = dist.Uniform(low=0.0, high=2.0) entropy = uniform.entropy() # entropy of Uniform(0,2) = log(2) self.assertAlmostEqual(float(entropy.numpy()), np.log(2.0), places=4) def test_uniform_sample_range(self): """测试均匀分布采样范围 / Test Uniform sample range""" uniform = dist.Uniform(low=0.0, high=4.0) samples = uniform.sample([1000]) # Mean should be close to 2.0 sample_mean = float(samples.mean().numpy()) self.assertAlmostEqual(sample_mean, 2.0, delta=0.2) class TestCategoricalDistribution(unittest.TestCase): """测试类别分布 / Test Categorical distribution""" def test_categorical_sample(self): """测试类别分布采样 / Test Categorical sampling""" logits = paddle.to_tensor([1.0, 2.0, 3.0]) categorical = dist.Categorical(logits=logits) samples = categorical.sample([10]) self.assertEqual(samples.shape, [10]) def test_categorical_log_prob(self): """测试类别分布对数概率 / Test Categorical log probability""" logits = paddle.to_tensor([1.0, 2.0, 3.0]) categorical = dist.Categorical(logits=logits) x = paddle.to_tensor([0, 1, 2]) log_prob = categorical.log_prob(x) self.assertEqual(log_prob.shape, [3]) def test_categorical_entropy(self): """测试类别分布熵 / Test Categorical entropy""" # Uniform logits => maximum entropy logits = paddle.zeros([4]) categorical = dist.Categorical(logits=logits) entropy = categorical.entropy() self.assertAlmostEqual(float(entropy.numpy()), np.log(4.0), places=4) class TestBernoulliDistribution(unittest.TestCase): """测试伯努利分布 / Test Bernoulli distribution""" def test_bernoulli_sample(self): """测试伯努利分布采样 / Test Bernoulli sampling""" bernoulli = dist.Bernoulli(probs=0.5) samples = bernoulli.sample([100]) self.assertEqual(samples.shape, [100]) unique_vals = paddle.unique(samples).numpy() # Only 0 and 1 self.assertTrue(all(v in [0, 1] for v in unique_vals)) def test_bernoulli_log_prob(self): """测试伯努利分布对数概率 / Test Bernoulli log probability""" bernoulli = dist.Bernoulli(probs=0.7) x = paddle.to_tensor([0.0, 1.0]) log_prob = bernoulli.log_prob(x) self.assertEqual(log_prob.shape, [2]) def test_bernoulli_entropy(self): """测试伯努利分布熵 / Test Bernoulli entropy""" bernoulli = dist.Bernoulli(probs=0.5) entropy = bernoulli.entropy() # Binary entropy at p=0.5 is log(2) self.assertAlmostEqual(float(entropy.numpy()), np.log(2.0), places=4) def test_bernoulli_mean_variance(self): """测试伯努利分布均值和方差 / Test Bernoulli mean and variance""" p = 0.3 bernoulli = dist.Bernoulli(probs=p) mean = bernoulli.mean var = bernoulli.variance self.assertAlmostEqual(float(mean.numpy()), p, places=5) self.assertAlmostEqual(float(var.numpy()), p * (1 - p), places=5) class TestBetaDistribution(unittest.TestCase): """测试Beta分布 / Test Beta distribution""" def test_beta_sample(self): """测试Beta分布采样 / Test Beta sampling""" beta = dist.Beta(alpha=2.0, beta=5.0) samples = beta.sample([100]) self.assertEqual(samples.shape, [100]) self.assertTrue(paddle.all(samples > 0).item()) self.assertTrue(paddle.all(samples < 1).item()) def test_beta_log_prob(self): """测试Beta分布对数概率 / Test Beta log probability""" beta = dist.Beta(alpha=2.0, beta=5.0) x = paddle.to_tensor([0.3, 0.5, 0.7]) log_prob = beta.log_prob(x) self.assertEqual(log_prob.shape, [3]) def test_beta_entropy(self): """测试Beta分布熵 / Test Beta entropy""" beta = dist.Beta(alpha=2.0, beta=5.0) entropy = beta.entropy() self.assertIsNotNone(entropy) def test_beta_mean_variance(self): """测试Beta分布均值和方差 / Test Beta mean and variance""" alpha, b = 2.0, 5.0 beta = dist.Beta(alpha=alpha, beta=b) expected_mean = alpha / (alpha + b) self.assertAlmostEqual( float(beta.mean.numpy()), expected_mean, places=4 ) class TestLogNormalDistribution(unittest.TestCase): """测试对数正态分布 / Test LogNormal distribution""" def test_lognormal_sample(self): """测试对数正态分布采样 / Test LogNormal sampling""" lognormal = dist.LogNormal(loc=0.0, scale=1.0) samples = lognormal.sample([100]) self.assertEqual(samples.shape, [100]) self.assertTrue(paddle.all(samples > 0).item()) def test_lognormal_log_prob(self): """测试对数正态分布对数概率 / Test LogNormal log probability""" lognormal = dist.LogNormal(loc=0.0, scale=1.0) x = paddle.to_tensor([1.0, 2.0, 0.5]) log_prob = lognormal.log_prob(x) self.assertEqual(log_prob.shape, [3]) def test_lognormal_entropy(self): """测试对数正态分布熵 / Test LogNormal entropy""" lognormal = dist.LogNormal(loc=0.0, scale=1.0) entropy = lognormal.entropy() self.assertIsNotNone(entropy) class TestTransformedDistribution(unittest.TestCase): """测试变换分布 / Test transformed distributions""" def test_independent_distribution(self): """测试独立分布包装 / Test Independent distribution wrapper""" base = dist.Normal(loc=paddle.zeros([3]), scale=paddle.ones([3])) independent = dist.Independent(base, 1) samples = independent.sample([10]) self.assertEqual(samples.shape, [10, 3]) def test_independent_log_prob(self): """测试独立分布的log_prob / Test Independent log_prob""" base = dist.Normal(loc=paddle.zeros([3]), scale=paddle.ones([3])) independent = dist.Independent(base, 1) x = paddle.zeros([10, 3]) log_prob = independent.log_prob(x) self.assertEqual(log_prob.shape, [10]) if __name__ == '__main__': unittest.main()