未验证 提交 53bdee64 编写于 作者: W wangchaochaohu 提交者: GitHub

add tensor support for gaussian_random_op test=develop (#24389)

上级 da4a1db7
...@@ -20,48 +20,26 @@ limitations under the License. */ ...@@ -20,48 +20,26 @@ limitations under the License. */
#include "paddle/fluid/framework/data_type.h" #include "paddle/fluid/framework/data_type.h"
#include "paddle/fluid/framework/op_registry.h" #include "paddle/fluid/framework/op_registry.h"
#include "paddle/fluid/operators/math/math_function.h" #include "paddle/fluid/operators/math/math_function.h"
#include "paddle/fluid/operators/utils.h"
namespace paddle { namespace paddle {
namespace operators { namespace operators {
using Tensor = framework::Tensor; 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 // 1. shape is a Tensor
if (ctx.HasInput("ShapeTensor")) { if (ctx.HasInput("ShapeTensor")) {
auto *shape_tensor = ctx.Input<framework::LoDTensor>("ShapeTensor"); auto *shape_tensor = ctx.Input<framework::LoDTensor>("ShapeTensor");
auto *shape_data = shape_tensor->data<int>(); auto vec_shape = GetDataFromTensor<int>(shape_tensor);
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<int>();
}
auto vec_shape =
std::vector<int>(shape_data, shape_data + shape_tensor->numel());
return framework::make_ddim(vec_shape); return framework::make_ddim(vec_shape);
} }
// 2. shape is a list/tuple containing Tensor // 2. shape is a list/tuple containing Tensor
auto shape_tensor_list = ctx.MultiInput<framework::Tensor>("ShapeTensorList"); auto shape_tensor_list = ctx.MultiInput<framework::Tensor>("ShapeTensorList");
if (shape_tensor_list.size() > 0) { if (shape_tensor_list.size() > 0) {
std::vector<int> vec_shape; auto vec_shape = GetDataFromTensorList(shape_tensor_list);
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<int>());
} else {
vec_shape.push_back(*tensor->data<int>());
}
}
return framework::make_ddim(vec_shape); return framework::make_ddim(vec_shape);
} }
...@@ -115,7 +93,8 @@ class FillConstantKernel : public framework::OpKernel<T> { ...@@ -115,7 +93,8 @@ class FillConstantKernel : public framework::OpKernel<T> {
} }
value = tensor_data[0]; 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<framework::LoDTensor>()) { if (out_var->IsType<framework::LoDTensor>()) {
tensor = out_var->GetMutable<framework::LoDTensor>(); tensor = out_var->GetMutable<framework::LoDTensor>();
......
...@@ -14,7 +14,7 @@ limitations under the License. */ ...@@ -14,7 +14,7 @@ limitations under the License. */
#include <random> #include <random>
#include "paddle/fluid/framework/op_registry.h" #include "paddle/fluid/framework/op_registry.h"
#include "paddle/fluid/operators/fill_constant_op.h"
#ifdef PADDLE_WITH_MKLDNN #ifdef PADDLE_WITH_MKLDNN
#include "paddle/fluid/platform/mkldnn_helper.h" #include "paddle/fluid/platform/mkldnn_helper.h"
#endif #endif
...@@ -22,8 +22,37 @@ limitations under the License. */ ...@@ -22,8 +22,37 @@ limitations under the License. */
namespace paddle { namespace paddle {
namespace operators { namespace operators {
using Tensor = framework::Tensor;
template <typename T> template <typename T>
class CPUGaussianRandomKernel : public framework::OpKernel<T> { class CPUGaussianRandomKernel : public framework::OpKernel<T> {
public:
void Compute(const framework::ExecutionContext& context) const override {
float mean = context.Attr<float>("mean");
float std = context.Attr<float>("std");
auto* tensor = context.Output<framework::Tensor>("Out");
unsigned int seed = static_cast<unsigned int>(context.Attr<int>("seed"));
std::minstd_rand engine;
if (seed == 0) {
seed = std::random_device()();
}
engine.seed(seed);
std::normal_distribution<T> 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<T>(context.GetPlace());
for (int64_t i = 0; i < size; ++i) {
data[i] = dist(engine);
}
}
};
template <typename T>
class CPUGaussianRandomBatchSizeLikeKernel : public framework::OpKernel<T> {
public: public:
void Compute(const framework::ExecutionContext& context) const override { void Compute(const framework::ExecutionContext& context) const override {
float mean = context.Attr<float>("mean"); float mean = context.Attr<float>("mean");
...@@ -58,12 +87,26 @@ class GaussianRandomOp : public framework::OperatorWithKernel { ...@@ -58,12 +87,26 @@ class GaussianRandomOp : public framework::OperatorWithKernel {
for (auto dim : shape) { for (auto dim : shape) {
temp.push_back(static_cast<int64_t>(dim)); temp.push_back(static_cast<int64_t>(dim));
} }
PADDLE_ENFORCE_GT( if (shape.empty() && ctx->HasInput("ShapeTensor")) {
shape.size(), 0UL, auto shape_dims = ctx->GetInputDim("ShapeTensor");
platform::errors::InvalidArgument( int num_ele = 1;
"Attribute(shape) of GaussianRandomOp must be set " for (int i = 0; i < shape_dims.size(); ++i) {
"and shape.size() > 0, but reveived shape.size() is %d", num_ele *= shape_dims[i];
shape.size())); }
auto vec_dims = std::vector<int>(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)); ctx->SetOutputDim("Out", framework::make_ddim(temp));
} }
...@@ -85,6 +128,16 @@ class GaussianRandomOp : public framework::OperatorWithKernel { ...@@ -85,6 +128,16 @@ class GaussianRandomOp : public framework::OperatorWithKernel {
static_cast<framework::proto::VarType::Type>(ctx.Attr<int>("dtype")), static_cast<framework::proto::VarType::Type>(ctx.Attr<int>("dtype")),
ctx.device_context(), layout, library); 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 { class GaussianRandomOpMaker : public framework::OpProtoAndCheckerMaker {
...@@ -94,7 +147,18 @@ class GaussianRandomOpMaker : public framework::OpProtoAndCheckerMaker { ...@@ -94,7 +147,18 @@ class GaussianRandomOpMaker : public framework::OpProtoAndCheckerMaker {
AddAttr<std::vector<int64_t>>("shape", AddAttr<std::vector<int64_t>>("shape",
"(vector<int64_t>) " "(vector<int64_t>) "
"The dimension of random tensor."); "The dimension of random tensor.")
.SetDefault({});
AddInput("ShapeTensor",
"(Tensor<int>), optional). The shape of the output."
"It has a higher priority than Attr(shape).")
.AsDispensable();
AddInput("ShapeTensorList",
"(vector<Tensor<int>>, 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<float>("mean", AddAttr<float>("mean",
"(float, default 0.0) " "(float, default 0.0) "
"mean of random tensor.") "mean of random tensor.")
...@@ -135,5 +199,5 @@ REGISTER_OP_WITHOUT_GRADIENT(gaussian_random, ops::GaussianRandomOp, ...@@ -135,5 +199,5 @@ REGISTER_OP_WITHOUT_GRADIENT(gaussian_random, ops::GaussianRandomOp,
REGISTER_OP_CPU_KERNEL(gaussian_random, ops::CPUGaussianRandomKernel<float>, REGISTER_OP_CPU_KERNEL(gaussian_random, ops::CPUGaussianRandomKernel<float>,
ops::CPUGaussianRandomKernel<double>); ops::CPUGaussianRandomKernel<double>);
REGISTER_OP_CPU_KERNEL(gaussian_random_batch_size_like, REGISTER_OP_CPU_KERNEL(gaussian_random_batch_size_like,
ops::CPUGaussianRandomKernel<float>, ops::CPUGaussianRandomBatchSizeLikeKernel<float>,
ops::CPUGaussianRandomKernel<double>); ops::CPUGaussianRandomBatchSizeLikeKernel<double>);
...@@ -15,6 +15,7 @@ limitations under the License. */ ...@@ -15,6 +15,7 @@ limitations under the License. */
#include <thrust/transform.h> #include <thrust/transform.h>
#include "paddle/fluid/framework/op_registry.h" #include "paddle/fluid/framework/op_registry.h"
#include "paddle/fluid/framework/operator.h" #include "paddle/fluid/framework/operator.h"
#include "paddle/fluid/operators/fill_constant_op.h"
namespace paddle { namespace paddle {
namespace operators { namespace operators {
...@@ -41,7 +42,6 @@ class GPUGaussianRandomKernel : public framework::OpKernel<T> { ...@@ -41,7 +42,6 @@ class GPUGaussianRandomKernel : public framework::OpKernel<T> {
public: public:
void Compute(const framework::ExecutionContext& context) const override { void Compute(const framework::ExecutionContext& context) const override {
auto* tensor = context.Output<framework::Tensor>("Out"); auto* tensor = context.Output<framework::Tensor>("Out");
T* data = tensor->mutable_data<T>(context.GetPlace());
unsigned int seed = static_cast<unsigned int>(context.Attr<int>("seed")); unsigned int seed = static_cast<unsigned int>(context.Attr<int>("seed"));
if (seed == 0) { if (seed == 0) {
std::random_device rd; std::random_device rd;
...@@ -50,6 +50,11 @@ class GPUGaussianRandomKernel : public framework::OpKernel<T> { ...@@ -50,6 +50,11 @@ class GPUGaussianRandomKernel : public framework::OpKernel<T> {
T mean = static_cast<T>(context.Attr<float>("mean")); T mean = static_cast<T>(context.Attr<float>("mean"));
T std = static_cast<T>(context.Attr<float>("std")); T std = static_cast<T>(context.Attr<float>("std"));
thrust::counting_iterator<unsigned int> index_sequence_begin(0); thrust::counting_iterator<unsigned int> 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<T>(context.GetPlace());
int64_t size = tensor->numel(); int64_t size = tensor->numel();
thrust::transform(index_sequence_begin, index_sequence_begin + size, thrust::transform(index_sequence_begin, index_sequence_begin + size,
thrust::device_ptr<T>(data), thrust::device_ptr<T>(data),
...@@ -57,12 +62,33 @@ class GPUGaussianRandomKernel : public framework::OpKernel<T> { ...@@ -57,12 +62,33 @@ class GPUGaussianRandomKernel : public framework::OpKernel<T> {
} }
}; };
template <typename T>
class GPUGaussianRandomBatchSizeLikeKernel : public framework::OpKernel<T> {
public:
void Compute(const framework::ExecutionContext& context) const override {
auto* tensor = context.Output<framework::Tensor>("Out");
T* data = tensor->mutable_data<T>(context.GetPlace());
unsigned int seed = static_cast<unsigned int>(context.Attr<int>("seed"));
if (seed == 0) {
std::random_device rd;
seed = rd();
}
T mean = static_cast<T>(context.Attr<float>("mean"));
T std = static_cast<T>(context.Attr<float>("std"));
thrust::counting_iterator<unsigned int> index_sequence_begin(0);
int64_t size = tensor->numel();
thrust::transform(index_sequence_begin, index_sequence_begin + size,
thrust::device_ptr<T>(data),
GaussianGenerator<T>(mean, std, seed));
}
};
} // namespace operators } // namespace operators
} // namespace paddle } // namespace paddle
REGISTER_OP_CUDA_KERNEL(gaussian_random, REGISTER_OP_CUDA_KERNEL(gaussian_random,
paddle::operators::GPUGaussianRandomKernel<float>, paddle::operators::GPUGaussianRandomKernel<float>,
paddle::operators::GPUGaussianRandomKernel<double>); paddle::operators::GPUGaussianRandomKernel<double>);
REGISTER_OP_CUDA_KERNEL(gaussian_random_batch_size_like, REGISTER_OP_CUDA_KERNEL(
paddle::operators::GPUGaussianRandomKernel<float>, gaussian_random_batch_size_like,
paddle::operators::GPUGaussianRandomKernel<double>); paddle::operators::GPUGaussianRandomBatchSizeLikeKernel<float>,
paddle::operators::GPUGaussianRandomBatchSizeLikeKernel<double>);
...@@ -13,6 +13,7 @@ See the License for the specific language governing permissions and ...@@ -13,6 +13,7 @@ See the License for the specific language governing permissions and
limitations under the License. */ limitations under the License. */
#include <string> #include <string>
#include "paddle/fluid/operators/fill_constant_op.h"
#include "paddle/fluid/operators/mean_op.h" #include "paddle/fluid/operators/mean_op.h"
namespace paddle { namespace paddle {
...@@ -26,7 +27,6 @@ class GaussianMKLDNNKernel : public paddle::framework::OpKernel<T> { ...@@ -26,7 +27,6 @@ class GaussianMKLDNNKernel : public paddle::framework::OpKernel<T> {
float mean = context.Attr<float>("mean"); float mean = context.Attr<float>("mean");
float std = context.Attr<float>("std"); float std = context.Attr<float>("std");
auto* tensor = context.Output<framework::Tensor>("Out"); auto* tensor = context.Output<framework::Tensor>("Out");
T* data = tensor->mutable_data<T>(context.GetPlace());
unsigned int seed = static_cast<unsigned int>(context.Attr<int>("seed")); unsigned int seed = static_cast<unsigned int>(context.Attr<int>("seed"));
std::minstd_rand engine; std::minstd_rand engine;
...@@ -35,6 +35,11 @@ class GaussianMKLDNNKernel : public paddle::framework::OpKernel<T> { ...@@ -35,6 +35,11 @@ class GaussianMKLDNNKernel : public paddle::framework::OpKernel<T> {
} }
engine.seed(seed); engine.seed(seed);
std::normal_distribution<T> dist(mean, std); std::normal_distribution<T> dist(mean, std);
const std::string op_type = "gaussian_random";
auto shape = GetShape(context, op_type);
tensor->Resize(shape);
T* data = tensor->mutable_data<T>(context.GetPlace());
int64_t size = tensor->numel(); int64_t size = tensor->numel();
for (int64_t i = 0; i < size; ++i) { for (int64_t i = 0; i < size; ++i) {
data[i] = dist(engine); data[i] = dist(engine);
......
...@@ -357,8 +357,9 @@ class Normal(Distribution): ...@@ -357,8 +357,9 @@ class Normal(Distribution):
output_shape = shape + batch_shape output_shape = shape + batch_shape
zero_tmp = tensor.fill_constant_batch_size_like( zero_tmp = tensor.fill_constant_batch_size_like(
self.loc + self.scale, batch_shape + shape, self.loc.dtype, 0.) self.loc + self.scale, batch_shape + shape, self.loc.dtype, 0.)
normal_random_tmp = nn.gaussian_random_batch_size_like( zero_tmp_shape = nn.shape(zero_tmp)
zero_tmp, zero_tmp.shape, mean=0., std=1., seed=seed) 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 output = normal_random_tmp * (zero_tmp + self.scale) + self.loc
return nn.reshape(output, output_shape) return nn.reshape(output, output_shape)
else: else:
......
...@@ -10169,33 +10169,55 @@ def gaussian_random(shape, mean=0.0, std=1.0, seed=0, dtype='float32'): ...@@ -10169,33 +10169,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. Generate a random tensor whose data is drawn from a Gaussian distribution.
Args: 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. mean (float): Mean of the random tensor, defaults to 0.0.
std (float): Standard deviation of the random tensor, defaults to 1.0. std (float): Standard deviation of the random tensor, defaults to 1.0.
seed (int): ${seed_comment} seed (int): ${seed_comment}
dtype(np.dtype | core.VarDesc.VarType | str): Output data type, float32 or float64. dtype(np.dtype | core.VarDesc.VarType | str): Output data type, float32 or float64.
Returns: Returns:
Variable: Random tensor whose data is drawn from a Gaussian distribution, dtype: flaot32 or float64 as specified. Variable: Random tensor whose data is drawn from a Gaussian distribution, dtype: flaot32 or float64 as specified.
Examples: Examples:
.. code-block:: python .. 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 import numpy as np
from paddle import fluid from paddle import fluid
x = fluid.layers.gaussian_random((2, 3), std=2., seed=10) x = fluid.layers.gaussian_random((2, 3), std=2., seed=10)
place = fluid.CPUPlace() place = fluid.CPUPlace()
exe = fluid.Executor(place) exe = fluid.Executor(place)
start = fluid.default_startup_program() start = fluid.default_startup_program()
main = fluid.default_main_program() main = fluid.default_main_program()
exe.run(start) exe.run(start)
x_np, = exe.run(main, feed={}, fetch_list=[x]) x_np, = exe.run(main, feed={}, fetch_list=[x])
...@@ -10209,33 +10231,44 @@ def gaussian_random(shape, mean=0.0, std=1.0, seed=0, dtype='float32'): ...@@ -10209,33 +10231,44 @@ def gaussian_random(shape, mean=0.0, std=1.0, seed=0, dtype='float32'):
import numpy as np import numpy as np
from paddle import fluid from paddle import fluid
import paddle.fluid.dygraph as dg import paddle.fluid.dygraph as dg
place = fluid.CPUPlace() place = fluid.CPUPlace()
with dg.guard(place) as g: with dg.guard(place) as g:
x = fluid.layers.gaussian_random((2, 4), mean=2., dtype="float32", seed=10) x = fluid.layers.gaussian_random((2, 4), mean=2., dtype="float32", seed=10)
x_np = x.numpy() x_np = x.numpy()
x_np x_np
# array([[2.3060477 , 2.676496 , 3.9911983 , 0.9990833 ], # array([[2.3060477 , 2.676496 , 3.9911983 , 0.9990833 ],
# [2.8675377 , 2.2279181 , 0.79029655, 2.8447366 ]], dtype=float32) # [2.8675377 , 2.2279181 , 0.79029655, 2.8447366 ]], dtype=float32)
""" """
helper = LayerHelper('gaussian_random', **locals()) 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) 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) 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( helper.append_op(
type='gaussian_random', type='gaussian_random',
inputs=inputs,
outputs={'Out': out}, outputs={'Out': out},
attrs={ attrs=attrs)
'shape': shape,
'mean': mean,
'std': std,
'seed': seed,
'dtype': c_dtype,
'use_mkldnn': False
})
return out return out
......
...@@ -27,17 +27,15 @@ class TestMKLDNNGaussianRandomOpSeed10(TestGaussianRandomOp): ...@@ -27,17 +27,15 @@ class TestMKLDNNGaussianRandomOpSeed10(TestGaussianRandomOp):
class TestMKLDNNGaussianRandomOpSeed0(TestGaussianRandomOp): class TestMKLDNNGaussianRandomOpSeed0(TestGaussianRandomOp):
def setUp(self): def setUp(self):
TestGaussianRandomOp.setUp(self) TestGaussianRandomOp.setUp(self)
self.use_mkldnn = True
self.attrs = { self.attrs = {
"shape": [1000, 784], "shape": [123, 92],
"mean": .0, "mean": 1.0,
"std": 1., "std": 2.0,
"seed": 0, "seed": 10,
"use_mkldnn": self.use_mkldnn "use_mkldnn": self.use_mkldnn
} }
def init_kernel_type(self):
self.use_mkldnn = True
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main()
...@@ -15,98 +15,213 @@ ...@@ -15,98 +15,213 @@
from __future__ import print_function from __future__ import print_function
import unittest import unittest
import numpy import numpy as np
import paddle.fluid as fluid import paddle.fluid as fluid
import paddle.fluid.core as core import paddle.fluid.core as core
from paddle.fluid.op import Operator from paddle.fluid.op import Operator
from paddle.fluid.executor import Executor from paddle.fluid.executor import Executor
from op_test import OpTest
class TestGaussianRandomOp(unittest.TestCase): class TestGaussianRandomOp(OpTest):
def setUp(self): def setUp(self):
self.op_type = "gaussian_random" self.op_type = "gaussian_random"
self.inputs = {} self.inputs = {}
self.use_mkldnn = False self.use_mkldnn = False
self.init_kernel_type()
self.attrs = { self.attrs = {
"shape": [1000, 784], "shape": [123, 92],
"mean": .0, "mean": 1.0,
"std": 1., "std": 2.,
"seed": 10, "seed": 10,
"use_mkldnn": self.use_mkldnn "use_mkldnn": self.use_mkldnn
} }
self.outputs = ["Out"] self.outputs = {'Out': np.zeros((123, 92), dtype='float32')}
def test_cpu(self): def test_check_output(self):
self.gaussian_random_test(place=fluid.CPUPlace()) self.check_output_customized(self.verify_output)
def test_gpu(self): def verify_output(self, outs):
if core.is_compiled_with_cuda(): self.assertEqual(outs[0].shape, (123, 92))
self.gaussian_random_test(place=fluid.CUDAPlace(0)) 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() # Situation 2: Attr(shape) is a list(with tensor)
block = program.global_block() class TestGaussianRandomOp_ShapeTensorList(TestGaussianRandomOp):
vout = block.create_var(name="Out") def setUp(self):
op = block.append_op( '''Test gaussian_random op with specified value
type=self.op_type, outputs={"Out": vout}, attrs=self.attrs) '''
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) self.attrs = {
op.desc.infer_shape(block.desc) 'shape': self.infer_shape,
'mean': self.mean,
'std': self.std,
'seed': self.seed,
'use_mkldnn': self.use_mkldnn
}
fetch_list = [] self.inputs = {"ShapeTensorList": shape_tensor_list}
for var_name in self.outputs: self.outputs = {'Out': np.zeros((123, 92), dtype='float32')}
fetch_list.append(block.var(var_name))
exe = Executor(place) def init_data(self):
outs = exe.run(program, fetch_list=fetch_list) self.shape = [123, 92]
tensor = outs[0] 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) def test_check_output(self):
self.assertAlmostEqual(numpy.std(tensor), 1., delta=0.1) 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): def setUp(self):
'''Test gaussian_random op with specified value
'''
self.op_type = "gaussian_random" self.op_type = "gaussian_random"
self.inputs = {} self.init_data()
self.use_mkldnn = False self.use_mkldnn = False
self.inputs = {"ShapeTensor": np.array(self.shape).astype("int32")}
self.attrs = { self.attrs = {
"shape": [1000, 784], 'mean': self.mean,
"mean": .0, 'std': self.std,
"std": 1., 'seed': self.seed,
"seed": 10, 'use_mkldnn': self.use_mkldnn
"use_mkldnn": self.use_mkldnn
} }
self.outputs = {'Out': np.zeros((123, 92), dtype='float32')}
self.outputs = ["Out"] def init_data(self):
self.shape = [123, 92]
def test_errors(self): self.use_mkldnn = False
program = fluid.Program() self.mean = 1.0
with fluid.program_guard(fluid.Program(), program): self.std = 2.0
input_data = numpy.random.random((2, 4)).astype("float32") self.seed = 10
block = program.global_block()
vout = block.create_var(name="Out", dtype='int32')
normal_initializer = fluid.initializer.NormalInitializer( # Test python API
loc=0.0, scale=1.0, seed=0) class TestGaussianRandomAPI(unittest.TestCase):
def test_api(self):
def test_Variable(): positive_2_int32 = fluid.layers.fill_constant([1], "int32", 2000)
# the input type must be Variable
normal_initializer(input_data) positive_2_int64 = fluid.layers.fill_constant([1], "int64", 500)
shape_tensor_int32 = fluid.data(
self.assertRaises(TypeError, test_Variable) name="shape_tensor_int32", shape=[2], dtype="int32")
def test_type(): shape_tensor_int64 = fluid.data(
# dtype must be float32 or float64 name="shape_tensor_int64", shape=[2], dtype="int64")
normal_initializer(vout)
out_1 = fluid.layers.gaussian_random(
self.assertRaises(TypeError, test_type) 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__": if __name__ == "__main__":
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册