blob: e9eff0feb50300931da1f47722b7c741d702e44d [file] [log] [blame]
#include "caffe2/operators/logit_op.h"
#include "caffe2/operators/elementwise_op.h"
namespace caffe2 {
struct LogitCPUFunctor {
explicit LogitCPUFunctor(OperatorBase& op)
: eps_(op.GetSingleArgument<float>("eps", 1e-6f)) {
CAFFE_ENFORCE_GT(eps_, 0.0);
CAFFE_ENFORCE_LT(eps_, 0.5);
}
template <typename T>
inline void
operator()(const int n, const T* x, T* y, CPUContext* /* unused */) {
ConstEigenArrayMap<T> X(x, n, 1);
EigenArrayMap<T> Y(y, n, 1);
const T k_one = 1.0;
Y = X.min(k_one - eps_);
Y = Y.max(eps_);
Y = (Y / (k_one - Y)).log();
}
private:
float eps_;
};
template <>
bool LogitGradientOp<float, CPUContext>::RunOnDevice() {
const auto& X = Input(0);
const auto& dY = Input(1);
auto* dX = Output(0);
dX->ResizeLike(X);
int channels = X.dim32(X.ndim() - 1);
ConstEigenArrayMap<float> Xmat(
X.template data<float>(), channels, X.size() / channels);
ConstEigenArrayMap<float> dYmat(
dY.template data<float>(), channels, X.size() / channels);
EigenArrayMap<float> dXmat(
dX->template mutable_data<float>(), channels, X.size() / channels);
dXmat = (Xmat < eps_ || Xmat > 1.0 - eps_)
.select(0, dYmat * ((1 - Xmat) * Xmat).inverse());
return true;
}
REGISTER_CPU_OPERATOR(
Logit,
UnaryElementwiseWithArgsOp<
TensorTypes<float>,
CPUContext,
LogitCPUFunctor>);
REGISTER_CPU_OPERATOR(LogitGradient, LogitGradientOp<float, CPUContext>);
OPERATOR_SCHEMA(Logit)
.NumInputs(1)
.NumOutputs(1)
.AllowInplace({{0, 0}})
.IdenticalTypeAndShape()
.SetDoc(R"DOC(
Elementwise logit transform: logit(x) = log(x / (1 - x)), where x is the
input data clampped in (eps, 1-eps).
)DOC")
.Arg("eps (optional)", "small positive epsilon value, the default is 1e-6.")
.Input(0, "X", "input float tensor")
.Output(0, "Y", "output float tensor");
OPERATOR_SCHEMA(LogitGradient)
.NumInputs(2)
.NumOutputs(1)
.Input(0, "X", "input float tensor")
.Input(1, "dY", "input float tensor")
.Output(0, "dX", "output float tensor")
.Arg("eps", "small positive epsilon value, the default is 1e-6.");
class GetLogitGradient : public GradientMakerBase {
using GradientMakerBase::GradientMakerBase;
vector<OperatorDef> GetGradientDefs() override {
return vector<OperatorDef>{CreateOperatorDef(
"LogitGradient",
"",
std::vector<string>{I(0), GO(0)},
std::vector<string>{GI(0)})};
}
};
REGISTER_GRADIENT(Logit, GetLogitGradient);
} // namespace caffe2