diff --git a/paddle/fluid/operators/fill_constant_op.h b/paddle/fluid/operators/fill_constant_op.h index d91f50a1726c5e559664f8e5b6126e4c96ab8650..74939da08b38dc147c156011759757a605db9444 100644 --- a/paddle/fluid/operators/fill_constant_op.h +++ b/paddle/fluid/operators/fill_constant_op.h @@ -20,48 +20,26 @@ limitations under the License. */ #include "paddle/fluid/framework/data_type.h" #include "paddle/fluid/framework/op_registry.h" #include "paddle/fluid/operators/math/math_function.h" +#include "paddle/fluid/operators/utils.h" namespace paddle { namespace operators { using Tensor = framework::Tensor; -inline framework::DDim GetShape(const framework::ExecutionContext &ctx) { +inline framework::DDim GetShape(const framework::ExecutionContext &ctx, + std::string op_type) { // 1. shape is a Tensor if (ctx.HasInput("ShapeTensor")) { auto *shape_tensor = ctx.Input("ShapeTensor"); - auto *shape_data = shape_tensor->data(); - framework::Tensor cpu_shape_tensor; - if (platform::is_gpu_place(shape_tensor->place())) { - TensorCopySync(*shape_tensor, platform::CPUPlace(), &cpu_shape_tensor); - shape_data = cpu_shape_tensor.data(); - } - auto vec_shape = - std::vector(shape_data, shape_data + shape_tensor->numel()); + auto vec_shape = GetDataFromTensor(shape_tensor); return framework::make_ddim(vec_shape); } // 2. shape is a list/tuple containing Tensor auto shape_tensor_list = ctx.MultiInput("ShapeTensorList"); if (shape_tensor_list.size() > 0) { - std::vector vec_shape; - for (size_t i = 0; i < shape_tensor_list.size(); ++i) { - auto tensor = shape_tensor_list[i]; - PADDLE_ENFORCE_EQ( - tensor->dims(), framework::make_ddim({1}), - platform::errors::InvalidArgument( - "If the element type of 'shape'(tensor_list type) in " - "FillConstantOp is Tensor, the shape of this Tensor element must " - "be [1]. But received the Tensor element's shape is [%s]", - tensor->dims())); - if (platform::is_gpu_place(tensor->place())) { - framework::Tensor temp; - TensorCopySync(*tensor, platform::CPUPlace(), &temp); - vec_shape.push_back(*temp.data()); - } else { - vec_shape.push_back(*tensor->data()); - } - } + auto vec_shape = GetDataFromTensorList(shape_tensor_list); return framework::make_ddim(vec_shape); } @@ -115,7 +93,8 @@ class FillConstantKernel : public framework::OpKernel { } value = tensor_data[0]; } - auto shape = GetShape(ctx); + const std::string op_type = "fill_constant"; + auto shape = GetShape(ctx, op_type); if (out_var->IsType()) { tensor = out_var->GetMutable(); diff --git a/paddle/fluid/operators/gaussian_random_op.cc b/paddle/fluid/operators/gaussian_random_op.cc index e99da6e3412ba994570c106694df077e8cd14160..0f1e4de5cbb88f10bc77791a385c73b5e8df24f0 100644 --- a/paddle/fluid/operators/gaussian_random_op.cc +++ b/paddle/fluid/operators/gaussian_random_op.cc @@ -14,7 +14,7 @@ limitations under the License. */ #include #include "paddle/fluid/framework/op_registry.h" - +#include "paddle/fluid/operators/fill_constant_op.h" #ifdef PADDLE_WITH_MKLDNN #include "paddle/fluid/platform/mkldnn_helper.h" #endif @@ -22,8 +22,37 @@ limitations under the License. */ namespace paddle { namespace operators { +using Tensor = framework::Tensor; template class CPUGaussianRandomKernel : public framework::OpKernel { + public: + void Compute(const framework::ExecutionContext& context) const override { + float mean = context.Attr("mean"); + float std = context.Attr("std"); + auto* tensor = context.Output("Out"); + + unsigned int seed = static_cast(context.Attr("seed")); + std::minstd_rand engine; + if (seed == 0) { + seed = std::random_device()(); + } + engine.seed(seed); + std::normal_distribution dist(mean, std); + + const std::string op_type = "gaussian_random"; + auto shape = GetShape(context, op_type); + tensor->Resize(shape); + int64_t size = tensor->numel(); + T* data = tensor->mutable_data(context.GetPlace()); + + for (int64_t i = 0; i < size; ++i) { + data[i] = dist(engine); + } + } +}; + +template +class CPUGaussianRandomBatchSizeLikeKernel : public framework::OpKernel { public: void Compute(const framework::ExecutionContext& context) const override { float mean = context.Attr("mean"); @@ -58,12 +87,26 @@ class GaussianRandomOp : public framework::OperatorWithKernel { for (auto dim : shape) { temp.push_back(static_cast(dim)); } - PADDLE_ENFORCE_GT( - shape.size(), 0UL, - platform::errors::InvalidArgument( - "Attribute(shape) of GaussianRandomOp must be set " - "and shape.size() > 0, but reveived shape.size() is %d", - shape.size())); + if (shape.empty() && ctx->HasInput("ShapeTensor")) { + auto shape_dims = ctx->GetInputDim("ShapeTensor"); + int num_ele = 1; + for (int i = 0; i < shape_dims.size(); ++i) { + num_ele *= shape_dims[i]; + } + auto vec_dims = std::vector(num_ele, -1); + ctx->SetOutputDim("Out", framework::make_ddim(vec_dims)); + + return; + } + if (!(ctx->HasInput("ShapeTensor") && !ctx->HasInputs("ShapeTensorList"))) { + PADDLE_ENFORCE_GT( + shape.size(), 0UL, + platform::errors::InvalidArgument( + "Attribute(shape) of GaussianRandomOp must be set " + "and shape.size() > 0, but reveived shape.size() is %d", + shape.size())); + } + ctx->SetOutputDim("Out", framework::make_ddim(temp)); } @@ -85,6 +128,16 @@ class GaussianRandomOp : public framework::OperatorWithKernel { static_cast(ctx.Attr("dtype")), ctx.device_context(), layout, library); } + + framework::OpKernelType GetKernelTypeForVar( + const std::string& var_name, const Tensor& tensor, + const framework::OpKernelType& expected_kernel_type) const override { + if (var_name == "ShapeTensor" || var_name == "ShapeTensorList") { + return expected_kernel_type; + } + return framework::OpKernelType(expected_kernel_type.data_type_, + tensor.place(), tensor.layout()); + } }; class GaussianRandomOpMaker : public framework::OpProtoAndCheckerMaker { @@ -94,7 +147,18 @@ class GaussianRandomOpMaker : public framework::OpProtoAndCheckerMaker { AddAttr>("shape", "(vector) " - "The dimension of random tensor."); + "The dimension of random tensor.") + .SetDefault({}); + AddInput("ShapeTensor", + "(Tensor), optional). The shape of the output." + "It has a higher priority than Attr(shape).") + .AsDispensable(); + AddInput("ShapeTensorList", + "(vector>, optional). The shape of the output. " + "It has a higher priority than Attr(shape)." + "The shape of the element in vector must be [1].") + .AsDuplicable() + .AsDispensable(); AddAttr("mean", "(float, default 0.0) " "mean of random tensor.") @@ -135,5 +199,5 @@ REGISTER_OP_WITHOUT_GRADIENT(gaussian_random, ops::GaussianRandomOp, REGISTER_OP_CPU_KERNEL(gaussian_random, ops::CPUGaussianRandomKernel, ops::CPUGaussianRandomKernel); REGISTER_OP_CPU_KERNEL(gaussian_random_batch_size_like, - ops::CPUGaussianRandomKernel, - ops::CPUGaussianRandomKernel); + ops::CPUGaussianRandomBatchSizeLikeKernel, + ops::CPUGaussianRandomBatchSizeLikeKernel); diff --git a/paddle/fluid/operators/gaussian_random_op.cu b/paddle/fluid/operators/gaussian_random_op.cu index 7784856417e579fd43f79fa331d46df8af6c36b8..c144481f8dedc9317f7657a22ce82e56022d5b89 100644 --- a/paddle/fluid/operators/gaussian_random_op.cu +++ b/paddle/fluid/operators/gaussian_random_op.cu @@ -15,6 +15,7 @@ limitations under the License. */ #include #include "paddle/fluid/framework/op_registry.h" #include "paddle/fluid/framework/operator.h" +#include "paddle/fluid/operators/fill_constant_op.h" namespace paddle { namespace operators { @@ -41,7 +42,6 @@ class GPUGaussianRandomKernel : public framework::OpKernel { public: void Compute(const framework::ExecutionContext& context) const override { auto* tensor = context.Output("Out"); - T* data = tensor->mutable_data(context.GetPlace()); unsigned int seed = static_cast(context.Attr("seed")); if (seed == 0) { std::random_device rd; @@ -50,6 +50,11 @@ class GPUGaussianRandomKernel : public framework::OpKernel { T mean = static_cast(context.Attr("mean")); T std = static_cast(context.Attr("std")); thrust::counting_iterator index_sequence_begin(0); + const std::string op_type = "gaussian_random"; + auto shape = GetShape(context, op_type); + tensor->Resize(shape); + T* data = tensor->mutable_data(context.GetPlace()); + int64_t size = tensor->numel(); thrust::transform(index_sequence_begin, index_sequence_begin + size, thrust::device_ptr(data), @@ -57,12 +62,33 @@ class GPUGaussianRandomKernel : public framework::OpKernel { } }; +template +class GPUGaussianRandomBatchSizeLikeKernel : public framework::OpKernel { + public: + void Compute(const framework::ExecutionContext& context) const override { + auto* tensor = context.Output("Out"); + T* data = tensor->mutable_data(context.GetPlace()); + unsigned int seed = static_cast(context.Attr("seed")); + if (seed == 0) { + std::random_device rd; + seed = rd(); + } + T mean = static_cast(context.Attr("mean")); + T std = static_cast(context.Attr("std")); + thrust::counting_iterator index_sequence_begin(0); + int64_t size = tensor->numel(); + thrust::transform(index_sequence_begin, index_sequence_begin + size, + thrust::device_ptr(data), + GaussianGenerator(mean, std, seed)); + } +}; } // namespace operators } // namespace paddle REGISTER_OP_CUDA_KERNEL(gaussian_random, paddle::operators::GPUGaussianRandomKernel, paddle::operators::GPUGaussianRandomKernel); -REGISTER_OP_CUDA_KERNEL(gaussian_random_batch_size_like, - paddle::operators::GPUGaussianRandomKernel, - paddle::operators::GPUGaussianRandomKernel); +REGISTER_OP_CUDA_KERNEL( + gaussian_random_batch_size_like, + paddle::operators::GPUGaussianRandomBatchSizeLikeKernel, + paddle::operators::GPUGaussianRandomBatchSizeLikeKernel); diff --git a/paddle/fluid/operators/mkldnn/gaussian_random_mkldnn_op.cc b/paddle/fluid/operators/mkldnn/gaussian_random_mkldnn_op.cc index 7f5337a14a245441d083d842f460d7719b79ec8f..37b6e3bb803a2b68cec54059b266bd7585ff9958 100644 --- a/paddle/fluid/operators/mkldnn/gaussian_random_mkldnn_op.cc +++ b/paddle/fluid/operators/mkldnn/gaussian_random_mkldnn_op.cc @@ -13,6 +13,7 @@ See the License for the specific language governing permissions and limitations under the License. */ #include +#include "paddle/fluid/operators/fill_constant_op.h" #include "paddle/fluid/operators/mean_op.h" namespace paddle { @@ -26,7 +27,6 @@ class GaussianMKLDNNKernel : public paddle::framework::OpKernel { float mean = context.Attr("mean"); float std = context.Attr("std"); auto* tensor = context.Output("Out"); - T* data = tensor->mutable_data(context.GetPlace()); unsigned int seed = static_cast(context.Attr("seed")); std::minstd_rand engine; @@ -35,6 +35,11 @@ class GaussianMKLDNNKernel : public paddle::framework::OpKernel { } engine.seed(seed); std::normal_distribution dist(mean, std); + + const std::string op_type = "gaussian_random"; + auto shape = GetShape(context, op_type); + tensor->Resize(shape); + T* data = tensor->mutable_data(context.GetPlace()); int64_t size = tensor->numel(); for (int64_t i = 0; i < size; ++i) { data[i] = dist(engine); diff --git a/python/paddle/fluid/layers/distributions.py b/python/paddle/fluid/layers/distributions.py index c5cf4c797502b7d6871dc76d94f6e6463645f3bb..81bea3898bed03e679bb06ebc15d1fa529d33ad3 100644 --- a/python/paddle/fluid/layers/distributions.py +++ b/python/paddle/fluid/layers/distributions.py @@ -357,8 +357,9 @@ class Normal(Distribution): output_shape = shape + batch_shape zero_tmp = tensor.fill_constant_batch_size_like( self.loc + self.scale, batch_shape + shape, self.loc.dtype, 0.) - normal_random_tmp = nn.gaussian_random_batch_size_like( - zero_tmp, zero_tmp.shape, mean=0., std=1., seed=seed) + zero_tmp_shape = nn.shape(zero_tmp) + normal_random_tmp = nn.gaussian_random( + zero_tmp_shape, mean=0., std=1., seed=seed) output = normal_random_tmp * (zero_tmp + self.scale) + self.loc return nn.reshape(output, output_shape) else: diff --git a/python/paddle/fluid/layers/nn.py b/python/paddle/fluid/layers/nn.py index 13a9c5f708f76edd27495bb96b39adae5f4845d9..5a71320e5841fb70295e177c3149187efbd19982 100644 --- a/python/paddle/fluid/layers/nn.py +++ b/python/paddle/fluid/layers/nn.py @@ -11421,33 +11421,55 @@ def gaussian_random(shape, mean=0.0, std=1.0, seed=0, dtype='float32'): Generate a random tensor whose data is drawn from a Gaussian distribution. Args: - shape (Tuple[int] | List[int]): Shape of the generated random tensor. - + shape (tuple[int] | list[int] | Variable | list[Variable]): Shape of the generated random tensor. + mean (float): Mean of the random tensor, defaults to 0.0. - + std (float): Standard deviation of the random tensor, defaults to 1.0. - + seed (int): ${seed_comment} - + dtype(np.dtype | core.VarDesc.VarType | str): Output data type, float32 or float64. Returns: Variable: Random tensor whose data is drawn from a Gaussian distribution, dtype: flaot32 or float64 as specified. Examples: + .. code-block:: python - # declarative mode + import paddle.fluid as fluid + + # example 1: + # attr shape is a list which doesn't contain tensor Variable. + result_1 = fluid.layers.gaussian_random(shape=[3, 4]) + + # example 2: + # attr shape is a list which contains tensor Variable. + dim_1 = fluid.layers.fill_constant([1],"int64",3) + dim_2 = fluid.layers.fill_constant([1],"int32",5) + result_2 = fluid.layers.gaussian_random(shape=[dim_1, dim_2]) + + # example 3: + # attr shape is a Variable, the data type must be int64 or int32. + var_shape = fluid.data(name='var_shape', shape=[2], dtype="int64") + result_3 = fluid.layers.gaussian_random(var_shape) + var_shape_int32 = fluid.data(name='var_shape_int32', shape=[2], dtype="int32") + result_4 = fluid.layers.gaussian_random(var_shape_int32) + + .. code-block:: python + + # declarative mode import numpy as np from paddle import fluid - + x = fluid.layers.gaussian_random((2, 3), std=2., seed=10) - + place = fluid.CPUPlace() exe = fluid.Executor(place) start = fluid.default_startup_program() main = fluid.default_main_program() - + exe.run(start) x_np, = exe.run(main, feed={}, fetch_list=[x]) @@ -11461,33 +11483,44 @@ def gaussian_random(shape, mean=0.0, std=1.0, seed=0, dtype='float32'): import numpy as np from paddle import fluid import paddle.fluid.dygraph as dg - + place = fluid.CPUPlace() with dg.guard(place) as g: x = fluid.layers.gaussian_random((2, 4), mean=2., dtype="float32", seed=10) - x_np = x.numpy() + x_np = x.numpy() x_np # array([[2.3060477 , 2.676496 , 3.9911983 , 0.9990833 ], # [2.8675377 , 2.2279181 , 0.79029655, 2.8447366 ]], dtype=float32) """ helper = LayerHelper('gaussian_random', **locals()) - check_type(shape, 'shape', (list, tuple), 'fluid.layers.gaussian_random') - check_dtype(dtype, 'dtype', ['float32', 'float64'], - 'fluid.layers.gaussian_random') out = helper.create_variable_for_type_inference(dtype) + if not isinstance(shape, (list, tuple, Variable)): + raise TypeError( + "The type of 'shape' in fill_constant must be Variable, list or tuple, but " + "received %s." % (type(shape))) c_dtype = convert_np_dtype_to_dtype_(dtype) + attrs = { + 'mean': mean, + 'std': std, + 'seed': seed, + 'dtype': c_dtype, + 'use_mkldnn': False + } + + inputs = {} + utils._get_shape_tensor_inputs( + inputs=inputs, + helper=helper, + attrs=attrs, + shape=shape, + op_type='gaussian_random') + helper.append_op( type='gaussian_random', + inputs=inputs, outputs={'Out': out}, - attrs={ - 'shape': shape, - 'mean': mean, - 'std': std, - 'seed': seed, - 'dtype': c_dtype, - 'use_mkldnn': False - }) + attrs=attrs) return out diff --git a/python/paddle/fluid/tests/unittests/mkldnn/test_gaussian_random_mkldnn_op.py b/python/paddle/fluid/tests/unittests/mkldnn/test_gaussian_random_mkldnn_op.py index 5ecf8cc80f7eb12b7ecd3a2238d92b2e71ceaa6d..a65efa6deb01f8884a0002cf3cc0edf3f053e84a 100644 --- a/python/paddle/fluid/tests/unittests/mkldnn/test_gaussian_random_mkldnn_op.py +++ b/python/paddle/fluid/tests/unittests/mkldnn/test_gaussian_random_mkldnn_op.py @@ -27,17 +27,15 @@ class TestMKLDNNGaussianRandomOpSeed10(TestGaussianRandomOp): class TestMKLDNNGaussianRandomOpSeed0(TestGaussianRandomOp): def setUp(self): TestGaussianRandomOp.setUp(self) + self.use_mkldnn = True self.attrs = { - "shape": [1000, 784], - "mean": .0, - "std": 1., - "seed": 0, + "shape": [123, 92], + "mean": 1.0, + "std": 2.0, + "seed": 10, "use_mkldnn": self.use_mkldnn } - def init_kernel_type(self): - self.use_mkldnn = True - if __name__ == '__main__': unittest.main() diff --git a/python/paddle/fluid/tests/unittests/test_gaussian_random_op.py b/python/paddle/fluid/tests/unittests/test_gaussian_random_op.py index 44df5daab20536a7f244ed465662257a3975d078..751a5fda267f5cf626f35c3764595d1724618849 100644 --- a/python/paddle/fluid/tests/unittests/test_gaussian_random_op.py +++ b/python/paddle/fluid/tests/unittests/test_gaussian_random_op.py @@ -15,98 +15,213 @@ from __future__ import print_function import unittest -import numpy +import numpy as np import paddle.fluid as fluid import paddle.fluid.core as core from paddle.fluid.op import Operator from paddle.fluid.executor import Executor +from op_test import OpTest -class TestGaussianRandomOp(unittest.TestCase): +class TestGaussianRandomOp(OpTest): def setUp(self): self.op_type = "gaussian_random" self.inputs = {} self.use_mkldnn = False - self.init_kernel_type() self.attrs = { - "shape": [1000, 784], - "mean": .0, - "std": 1., + "shape": [123, 92], + "mean": 1.0, + "std": 2., "seed": 10, "use_mkldnn": self.use_mkldnn } - self.outputs = ["Out"] + self.outputs = {'Out': np.zeros((123, 92), dtype='float32')} - def test_cpu(self): - self.gaussian_random_test(place=fluid.CPUPlace()) + def test_check_output(self): + self.check_output_customized(self.verify_output) - def test_gpu(self): - if core.is_compiled_with_cuda(): - self.gaussian_random_test(place=fluid.CUDAPlace(0)) + def verify_output(self, outs): + self.assertEqual(outs[0].shape, (123, 92)) + hist, _ = np.histogram(outs[0], range=(-3, 5)) + hist = hist.astype("float32") + hist /= float(outs[0].size) + data = np.random.normal(size=(123, 92), loc=1, scale=2) + hist2, _ = np.histogram(data, range=(-3, 5)) + hist2 = hist2.astype("float32") + hist2 /= float(outs[0].size) + self.assertTrue( + np.allclose( + hist, hist2, rtol=0, atol=0.01), + "hist: " + str(hist) + " hist2: " + str(hist2)) - def gaussian_random_test(self, place): - program = fluid.Program() - block = program.global_block() - vout = block.create_var(name="Out") - op = block.append_op( - type=self.op_type, outputs={"Out": vout}, attrs=self.attrs) +# Situation 2: Attr(shape) is a list(with tensor) +class TestGaussianRandomOp_ShapeTensorList(TestGaussianRandomOp): + def setUp(self): + '''Test gaussian_random op with specified value + ''' + self.op_type = "gaussian_random" + self.init_data() + shape_tensor_list = [] + for index, ele in enumerate(self.shape): + shape_tensor_list.append(("x" + str(index), np.ones( + (1)).astype('int32') * ele)) - op.desc.infer_var_type(block.desc) - op.desc.infer_shape(block.desc) + self.attrs = { + 'shape': self.infer_shape, + 'mean': self.mean, + 'std': self.std, + 'seed': self.seed, + 'use_mkldnn': self.use_mkldnn + } - fetch_list = [] - for var_name in self.outputs: - fetch_list.append(block.var(var_name)) + self.inputs = {"ShapeTensorList": shape_tensor_list} + self.outputs = {'Out': np.zeros((123, 92), dtype='float32')} - exe = Executor(place) - outs = exe.run(program, fetch_list=fetch_list) - tensor = outs[0] + def init_data(self): + self.shape = [123, 92] + self.infer_shape = [-1, 92] + self.use_mkldnn = False + self.mean = 1.0 + self.std = 2.0 + self.seed = 10 - self.assertAlmostEqual(numpy.mean(tensor), .0, delta=0.1) - self.assertAlmostEqual(numpy.std(tensor), 1., delta=0.1) + def test_check_output(self): + self.check_output_customized(self.verify_output) - def init_kernel_type(self): - pass +class TestGaussianRandomOp2_ShapeTensorList( + TestGaussianRandomOp_ShapeTensorList): + def init_data(self): + self.shape = [123, 92] + self.infer_shape = [-1, -1] + self.use_mkldnn = False + self.mean = 1.0 + self.std = 2.0 + self.seed = 10 + + +class TestGaussianRandomOp3_ShapeTensorList( + TestGaussianRandomOp_ShapeTensorList): + def init_data(self): + self.shape = [123, 92] + self.infer_shape = [123, -1] + self.use_mkldnn = True + self.mean = 1.0 + self.std = 2.0 + self.seed = 10 + + +class TestGaussianRandomOp4_ShapeTensorList( + TestGaussianRandomOp_ShapeTensorList): + def init_data(self): + self.shape = [123, 92] + self.infer_shape = [123, -1] + self.use_mkldnn = False + self.mean = 1.0 + self.std = 2.0 + self.seed = 10 -class TestGaussianRandomOpError(unittest.TestCase): + +# Situation 3: shape is a tensor +class TestGaussianRandomOp1_ShapeTensor(TestGaussianRandomOp): def setUp(self): + '''Test gaussian_random op with specified value + ''' self.op_type = "gaussian_random" - self.inputs = {} + self.init_data() self.use_mkldnn = False + + self.inputs = {"ShapeTensor": np.array(self.shape).astype("int32")} self.attrs = { - "shape": [1000, 784], - "mean": .0, - "std": 1., - "seed": 10, - "use_mkldnn": self.use_mkldnn + 'mean': self.mean, + 'std': self.std, + 'seed': self.seed, + 'use_mkldnn': self.use_mkldnn } + self.outputs = {'Out': np.zeros((123, 92), dtype='float32')} - self.outputs = ["Out"] - - def test_errors(self): - program = fluid.Program() - with fluid.program_guard(fluid.Program(), program): - input_data = numpy.random.random((2, 4)).astype("float32") - block = program.global_block() - vout = block.create_var(name="Out", dtype='int32') - normal_initializer = fluid.initializer.NormalInitializer( - loc=0.0, scale=1.0, seed=0) - - def test_Variable(): - # the input type must be Variable - normal_initializer(input_data) - - self.assertRaises(TypeError, test_Variable) - - def test_type(): - # dtype must be float32 or float64 - normal_initializer(vout) - - self.assertRaises(TypeError, test_type) + def init_data(self): + self.shape = [123, 92] + self.use_mkldnn = False + self.mean = 1.0 + self.std = 2.0 + self.seed = 10 + + +# Test python API +class TestGaussianRandomAPI(unittest.TestCase): + def test_api(self): + positive_2_int32 = fluid.layers.fill_constant([1], "int32", 2000) + + positive_2_int64 = fluid.layers.fill_constant([1], "int64", 500) + shape_tensor_int32 = fluid.data( + name="shape_tensor_int32", shape=[2], dtype="int32") + + shape_tensor_int64 = fluid.data( + name="shape_tensor_int64", shape=[2], dtype="int64") + + out_1 = fluid.layers.gaussian_random( + shape=[2000, 500], dtype="float32", mean=0.0, std=1.0, seed=10) + + out_2 = fluid.layers.gaussian_random( + shape=[2000, positive_2_int32], + dtype="float32", + mean=0., + std=1.0, + seed=10) + + out_3 = fluid.layers.gaussian_random( + shape=[2000, positive_2_int64], + dtype="float32", + mean=0., + std=1.0, + seed=10) + + out_4 = fluid.layers.gaussian_random( + shape=shape_tensor_int32, + dtype="float32", + mean=0., + std=1.0, + seed=10) + + out_5 = fluid.layers.gaussian_random( + shape=shape_tensor_int64, + dtype="float32", + mean=0., + std=1.0, + seed=10) + + out_6 = fluid.layers.gaussian_random( + shape=shape_tensor_int64, + dtype=np.float32, + mean=0., + std=1.0, + seed=10) + + exe = fluid.Executor(place=fluid.CPUPlace()) + res_1, res_2, res_3, res_4, res_5, res_6 = exe.run( + fluid.default_main_program(), + feed={ + "shape_tensor_int32": np.array([2000, 500]).astype("int32"), + "shape_tensor_int64": np.array([2000, 500]).astype("int64"), + }, + fetch_list=[out_1, out_2, out_3, out_4, out_5, out_6]) + + self.assertAlmostEqual(np.mean(res_1), 0.0, delta=0.1) + self.assertAlmostEqual(np.std(res_1), 1., delta=0.1) + self.assertAlmostEqual(np.mean(res_2), 0.0, delta=0.1) + self.assertAlmostEqual(np.std(res_2), 1., delta=0.1) + self.assertAlmostEqual(np.mean(res_3), 0.0, delta=0.1) + self.assertAlmostEqual(np.std(res_3), 1., delta=0.1) + self.assertAlmostEqual(np.mean(res_4), 0.0, delta=0.1) + self.assertAlmostEqual(np.std(res_5), 1., delta=0.1) + self.assertAlmostEqual(np.mean(res_5), 0.0, delta=0.1) + self.assertAlmostEqual(np.std(res_5), 1., delta=0.1) + self.assertAlmostEqual(np.mean(res_6), 0.0, delta=0.1) + self.assertAlmostEqual(np.std(res_6), 1., delta=0.1) if __name__ == "__main__":