blob: 79655b3a3ba10e689fcc19381516b621e7688750 [file] [log] [blame]
/*!
* Copyright (c) 2016 by Contributors
* \file sample_op.h
* \brief Elementary sampling operators
*/
#ifndef MXNET_OPERATOR_RANDOM_SAMPLE_OP_H_
#define MXNET_OPERATOR_RANDOM_SAMPLE_OP_H_
#include <mxnet/operator_util.h>
#include <mshadow/base.h>
#include <string>
#include <vector>
#include "../mshadow_op.h"
#include "../elemwise_op_common.h"
#include "../tensor/init_op.h"
namespace mxnet {
namespace op {
struct SampleUniformParam : public dmlc::Parameter<SampleUniformParam> {
float low;
float high;
TShape shape;
std::string ctx;
int dtype;
DMLC_DECLARE_PARAMETER(SampleUniformParam) {
DMLC_DECLARE_FIELD(low).set_default(0.0f)
.describe("Lower bound of the distribution.");
DMLC_DECLARE_FIELD(high).set_default(1.0f)
.describe("Upper bound of the distribution.");
DMLC_DECLARE_FIELD(shape)
.set_default(TShape())
.describe("Shape of the output.");
DMLC_DECLARE_FIELD(ctx)
.set_default("")
.describe("Context of output, in format [cpu|gpu|cpu_pinned](n)."
" Only used for imperative calls.");
DMLC_DECLARE_FIELD(dtype)
.add_enum("None", -1)
.add_enum("float32", mshadow::kFloat32)
.add_enum("float64", mshadow::kFloat64)
.add_enum("float16", mshadow::kFloat16)
.set_default(-1)
.describe("DType of the output in case this can't be inferred. "
"Defaults to float32 if not defined (dtype=None).");
}
};
struct SampleNormalParam : public dmlc::Parameter<SampleNormalParam> {
float loc;
float scale;
TShape shape;
std::string ctx;
int dtype;
DMLC_DECLARE_PARAMETER(SampleNormalParam) {
DMLC_DECLARE_FIELD(loc).set_default(0.0f)
.describe("Mean of the distribution.");
DMLC_DECLARE_FIELD(scale).set_default(1.0f)
.describe("Standard deviation of the distribution.");
DMLC_DECLARE_FIELD(shape)
.set_default(TShape())
.describe("Shape of the output.");
DMLC_DECLARE_FIELD(ctx)
.set_default("")
.describe("Context of output, in format [cpu|gpu|cpu_pinned](n)."
" Only used for imperative calls.");
DMLC_DECLARE_FIELD(dtype)
.add_enum("None", -1)
.add_enum("float32", mshadow::kFloat32)
.add_enum("float64", mshadow::kFloat64)
.add_enum("float16", mshadow::kFloat16)
.set_default(-1)
.describe("DType of the output in case this can't be inferred. "
"Defaults to float32 if not defined (dtype=None).");
}
};
struct SampleGammaParam : public dmlc::Parameter<SampleGammaParam> {
float alpha;
float beta;
TShape shape;
std::string ctx;
int dtype;
DMLC_DECLARE_PARAMETER(SampleGammaParam) {
DMLC_DECLARE_FIELD(alpha).set_default(1.0f)
.describe("Alpha parameter (shape) of the gamma distribution.");
DMLC_DECLARE_FIELD(beta).set_default(1.0f)
.describe("Beta parameter (scale) of the gamma distribution.");
DMLC_DECLARE_FIELD(shape)
.set_default(TShape())
.describe("Shape of the output.");
DMLC_DECLARE_FIELD(ctx)
.set_default("")
.describe("Context of output, in format [cpu|gpu|cpu_pinned](n)."
" Only used for imperative calls.");
DMLC_DECLARE_FIELD(dtype)
.add_enum("None", -1)
.add_enum("float32", mshadow::kFloat32)
.add_enum("float64", mshadow::kFloat64)
.add_enum("float16", mshadow::kFloat16)
.set_default(-1)
.describe("DType of the output in case this can't be inferred. "
"Defaults to float32 if not defined (dtype=None).");
}
};
struct SampleExponentialParam : public dmlc::Parameter<SampleExponentialParam> {
float lam;
TShape shape;
std::string ctx;
int dtype;
DMLC_DECLARE_PARAMETER(SampleExponentialParam) {
DMLC_DECLARE_FIELD(lam).set_default(1.0f)
.describe("Lambda parameter (rate) of the exponential distribution.");
DMLC_DECLARE_FIELD(shape)
.set_default(TShape())
.describe("Shape of the output.");
DMLC_DECLARE_FIELD(ctx)
.set_default("")
.describe("Context of output, in format [cpu|gpu|cpu_pinned](n)."
" Only used for imperative calls.");
DMLC_DECLARE_FIELD(dtype)
.add_enum("None", -1)
.add_enum("float32", mshadow::kFloat32)
.add_enum("float64", mshadow::kFloat64)
.add_enum("float16", mshadow::kFloat16)
.set_default(-1)
.describe("DType of the output in case this can't be inferred. "
"Defaults to float32 if not defined (dtype=None).");
}
};
struct SamplePoissonParam : public dmlc::Parameter<SamplePoissonParam> {
float lam;
TShape shape;
std::string ctx;
int dtype;
DMLC_DECLARE_PARAMETER(SamplePoissonParam) {
DMLC_DECLARE_FIELD(lam).set_default(1.0f)
.describe("Lambda parameter (rate) of the Poisson distribution.");
DMLC_DECLARE_FIELD(shape)
.set_default(TShape())
.describe("Shape of the output.");
DMLC_DECLARE_FIELD(ctx)
.set_default("")
.describe("Context of output, in format [cpu|gpu|cpu_pinned](n)."
" Only used for imperative calls.");
DMLC_DECLARE_FIELD(dtype)
.add_enum("None", -1)
.add_enum("float32", mshadow::kFloat32)
.add_enum("float64", mshadow::kFloat64)
.add_enum("float16", mshadow::kFloat16)
.set_default(-1)
.describe("DType of the output in case this can't be inferred. "
"Defaults to float32 if not defined (dtype=None).");
}
};
struct SampleNegBinomialParam : public dmlc::Parameter<SampleNegBinomialParam> {
int k;
float p;
TShape shape;
std::string ctx;
int dtype;
DMLC_DECLARE_PARAMETER(SampleNegBinomialParam) {
DMLC_DECLARE_FIELD(k).set_default(1)
.describe("Limit of unsuccessful experiments.");
DMLC_DECLARE_FIELD(p).set_default(1.0f)
.describe("Failure probability in each experiment.");
DMLC_DECLARE_FIELD(shape)
.set_default(TShape())
.describe("Shape of the output.");
DMLC_DECLARE_FIELD(ctx)
.set_default("")
.describe("Context of output, in format [cpu|gpu|cpu_pinned](n)."
" Only used for imperative calls.");
DMLC_DECLARE_FIELD(dtype)
.add_enum("None", -1)
.add_enum("float32", mshadow::kFloat32)
.add_enum("float64", mshadow::kFloat64)
.add_enum("float16", mshadow::kFloat16)
.set_default(-1)
.describe("DType of the output in case this can't be inferred. "
"Defaults to float32 if not defined (dtype=None).");
}
};
struct SampleGenNegBinomialParam : public dmlc::Parameter<SampleGenNegBinomialParam> {
float mu;
float alpha;
TShape shape;
std::string ctx;
int dtype;
DMLC_DECLARE_PARAMETER(SampleGenNegBinomialParam) {
DMLC_DECLARE_FIELD(mu).set_default(1.0f)
.describe("Mean of the negative binomial distribution.");
DMLC_DECLARE_FIELD(alpha).set_default(1.0f)
.describe("Alpha (dispersion) parameter of the negative binomial distribution.");
DMLC_DECLARE_FIELD(shape)
.set_default(TShape())
.describe("Shape of the output.");
DMLC_DECLARE_FIELD(ctx)
.set_default("")
.describe("Context of output, in format [cpu|gpu|cpu_pinned](n)."
" Only used for imperative calls.");
DMLC_DECLARE_FIELD(dtype)
.add_enum("None", -1)
.add_enum("float32", mshadow::kFloat32)
.add_enum("float64", mshadow::kFloat64)
.add_enum("float16", mshadow::kFloat16)
.set_default(-1)
.describe("DType of the output in case this can't be inferred. "
"Defaults to float32 if not defined (dtype=None).");
}
};
template<typename xpu>
void SampleUniform_(const nnvm::NodeAttrs& attrs,
const OpContext& ctx,
const std::vector<TBlob>& inputs,
const std::vector<OpReqType>& req,
const std::vector<TBlob>& outputs) {
using namespace mxnet::op;
using namespace mshadow::expr;
mshadow::Stream<xpu> *s = ctx.get_stream<xpu>();
const SampleUniformParam& param = nnvm::get<SampleUniformParam>(attrs.parsed);
MSHADOW_REAL_TYPE_SWITCH(outputs[0].type_flag_, DType, {
mshadow::Random<xpu, DType> *prnd = ctx.requested[0].get_random<xpu, DType>(s);
mshadow::Tensor<xpu, 2, DType> out = outputs[0].FlatTo2D<xpu, DType>(s);
prnd->SampleUniform(&out, param.low, param.high);
});
}
template<typename xpu>
void SampleNormal_(const nnvm::NodeAttrs& attrs,
const OpContext& ctx,
const std::vector<TBlob>& inputs,
const std::vector<OpReqType>& req,
const std::vector<TBlob>& outputs) {
using namespace mxnet::op;
using namespace mshadow::expr;
mshadow::Stream<xpu> *s = ctx.get_stream<xpu>();
const SampleNormalParam& param = nnvm::get<SampleNormalParam>(attrs.parsed);
CHECK_GT(param.scale, 0) << "scale parameter in gaussian has to be positive";
MSHADOW_REAL_TYPE_SWITCH(outputs[0].type_flag_, DType, {
mshadow::Random<xpu, DType> *prnd = ctx.requested[0].get_random<xpu, DType>(s);
mshadow::Tensor<xpu, 2, DType> out = outputs[0].FlatTo2D<xpu, DType>(s);
prnd->SampleGaussian(&out, param.loc, param.scale); // NOLINT(*)
});
}
template<typename xpu>
void SampleGamma_(const nnvm::NodeAttrs& attrs,
const OpContext& ctx,
const std::vector<TBlob>& inputs,
const std::vector<OpReqType>& req,
const std::vector<TBlob>& outputs) {
using namespace mxnet::op;
using namespace mshadow::expr;
mshadow::Stream<xpu> *s = ctx.get_stream<xpu>();
const SampleGammaParam& param = nnvm::get<SampleGammaParam>(attrs.parsed);
CHECK_GT(param.alpha, 0) << "alpha parameter in gamma distribution has to be positive";
CHECK_GT(param.beta, 0) << "beta parameter in gamma distribution has to be positive";
MSHADOW_REAL_TYPE_SWITCH(outputs[0].type_flag_, DType, {
mshadow::Random<xpu, DType> *prnd = ctx.requested[0].get_random<xpu, DType>(s);
mshadow::Tensor<xpu, 2, DType> out = outputs[0].FlatTo2D<xpu, DType>(s);
prnd->SampleGamma(&out, param.alpha, param.beta); // NOLINT(*)
});
}
template<typename xpu>
void SampleExponential_(const nnvm::NodeAttrs& attrs,
const OpContext& ctx,
const std::vector<TBlob>& inputs,
const std::vector<OpReqType>& req,
const std::vector<TBlob>& outputs) {
using namespace mxnet::op;
using namespace mshadow::expr;
mshadow::Stream<xpu> *s = ctx.get_stream<xpu>();
const SampleExponentialParam& param = nnvm::get<SampleExponentialParam>(attrs.parsed);
CHECK_GT(param.lam, 0) << "lambda parameter in exponential distribution has to be positive";
MSHADOW_REAL_TYPE_SWITCH(outputs[0].type_flag_, DType, {
mshadow::Random<xpu, DType> *prnd = ctx.requested[0].get_random<xpu, DType>(s);
mshadow::Tensor<xpu, 2, DType> out = outputs[0].FlatTo2D<xpu, DType>(s);
prnd->SampleExponential(&out, param.lam); // NOLINT(*)
});
}
template<typename xpu>
void SamplePoisson_(const nnvm::NodeAttrs& attrs,
const OpContext& ctx,
const std::vector<TBlob>& inputs,
const std::vector<OpReqType>& req,
const std::vector<TBlob>& outputs) {
using namespace mxnet::op;
using namespace mshadow::expr;
mshadow::Stream<xpu> *s = ctx.get_stream<xpu>();
const SamplePoissonParam& param = nnvm::get<SamplePoissonParam>(attrs.parsed);
CHECK_GE(param.lam, 0) << "lambda parameter in poisson distribution has to be non-negative";
MSHADOW_REAL_TYPE_SWITCH(outputs[0].type_flag_, DType, {
mshadow::Random<xpu, DType> *prnd = ctx.requested[0].get_random<xpu, DType>(s);
mshadow::Tensor<xpu, 2, DType> out = outputs[0].FlatTo2D<xpu, DType>(s);
prnd->SamplePoisson(&out, param.lam); // NOLINT(*)
});
}
template<typename xpu>
void SampleNegBinomial_(const nnvm::NodeAttrs& attrs,
const OpContext& ctx,
const std::vector<TBlob>& inputs,
const std::vector<OpReqType>& req,
const std::vector<TBlob>& outputs) {
using namespace mxnet::op;
using namespace mshadow::expr;
mshadow::Stream<xpu> *s = ctx.get_stream<xpu>();
const SampleNegBinomialParam& param = nnvm::get<SampleNegBinomialParam>(attrs.parsed);
CHECK_GE(param.k, 0) << "k parameter in negative binomial distribution has to be non-negative";
CHECK_GE(param.p, 0) << "p parameter in negative binomial distribution has to be non-negative";
MSHADOW_REAL_TYPE_SWITCH(outputs[0].type_flag_, DType, {
mshadow::Random<xpu, DType> *prnd = ctx.requested[0].get_random<xpu, DType>(s);
mshadow::Tensor<xpu, 2, DType> out = outputs[0].FlatTo2D<xpu, DType>(s);
prnd->SampleNegativeBinomial(&out, param.k, param.p); // NOLINT(*)
});
}
template<typename xpu>
void SampleGenNegBinomial_(const nnvm::NodeAttrs& attrs,
const OpContext& ctx,
const std::vector<TBlob>& inputs,
const std::vector<OpReqType>& req,
const std::vector<TBlob>& outputs) {
using namespace mxnet::op;
using namespace mshadow::expr;
mshadow::Stream<xpu> *s = ctx.get_stream<xpu>();
const SampleGenNegBinomialParam& param = nnvm::get<SampleGenNegBinomialParam>(attrs.parsed);
CHECK_GE(param.mu, 0)
<< "mu parameter in generalized negative binomial distribution has to be non-negative";
CHECK_GE(param.alpha, 0)
<< "alpha parameter in generalized negative binomial distribution has to be non-negative";
MSHADOW_REAL_TYPE_SWITCH(outputs[0].type_flag_, DType, {
mshadow::Random<xpu, DType> *prnd = ctx.requested[0].get_random<xpu, DType>(s);
mshadow::Tensor<xpu, 2, DType> out = outputs[0].FlatTo2D<xpu, DType>(s);
prnd->SampleGeneralizedNegativeBinomial(&out, param.mu, param.alpha); // NOLINT(*)
});
}
template<typename ParamType>
inline bool SampleOpType(const nnvm::NodeAttrs& attrs,
std::vector<int> *in_type,
std::vector<int> *out_type) {
const ParamType& param = nnvm::get<ParamType>(attrs.parsed);
CHECK_EQ(in_type->size(), 0);
CHECK_EQ(out_type->size(), 1);
int dtype = -1;
int dtype_out = (*out_type)[0];
if (dtype_out != -1) {
// Output type can be inferred, use it and make sure it
dtype = dtype_out;
if (param.dtype != -1) {
// dtype given in args, check that it matches the output type
CHECK_EQ(dtype_out, param.dtype) << "Output type does not match requested type: "
<< dtype_out << " vs " << param.dtype;
}
} else {
// Output type can't be inferred
if (param.dtype != -1) {
// Use dtype given in args
dtype = param.dtype;
} else {
// Use default
dtype = mshadow::kFloat32;
}
}
bool dtype_ok = (dtype == mshadow::kFloat16) || (dtype == mshadow::kFloat32) ||
(dtype == mshadow::kFloat64);
CHECK_EQ(dtype_ok, true) << "Output type must be float16, float32, or float64: dtype is "
<< dtype_out << " vs " << mshadow::kFloat16 << " or " << mshadow::kFloat32 << " or "
<< mshadow::kFloat64;
TYPE_ASSIGN_CHECK(*out_type, 0, dtype);
return true;
}
inline std::vector<ResourceRequest> SampleResource(const NodeAttrs& attrs) {
return { ResourceRequest::kRandom, ResourceRequest::kTempSpace };
}
} // namespace op
} // namespace mxnet
#endif // MXNET_OPERATOR_RANDOM_SAMPLE_OP_H_