Merge branch 'develop' of https://github.com/PaddlePaddle/Paddle into dev_add_FillZerosLikeOp_test
commit
df84e39a00
@ -0,0 +1,229 @@
|
||||
/* Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserve.
|
||||
|
||||
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. */
|
||||
|
||||
#include <Python.h>
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
|
||||
#include "paddle/framework/backward.h"
|
||||
#include "paddle/framework/op_registry.h"
|
||||
#include "paddle/framework/operator.h"
|
||||
#include "paddle/framework/scope.h"
|
||||
#include "paddle/framework/tensor_py.h"
|
||||
#include "paddle/operators/net_op.h"
|
||||
#include "paddle/operators/type_alias.h"
|
||||
#include "paddle/platform/enforce.h"
|
||||
#include "paddle/platform/place.h"
|
||||
#include "pybind11/numpy.h"
|
||||
#include "pybind11/pybind11.h"
|
||||
#include "pybind11/stl.h"
|
||||
|
||||
namespace py = pybind11;
|
||||
|
||||
USE_OP(add_two);
|
||||
USE_OP(onehot_cross_entropy);
|
||||
USE_OP_WITHOUT_KERNEL(fc);
|
||||
USE_OP(sgd);
|
||||
USE_OP(mul);
|
||||
USE_OP(mean);
|
||||
USE_OP(sigmoid);
|
||||
USE_OP(softmax);
|
||||
USE_OP(rowwise_add);
|
||||
USE_OP_WITHOUT_KERNEL(recurrent_op);
|
||||
namespace paddle {
|
||||
namespace framework {
|
||||
template <typename ClassType>
|
||||
void ExposeOperator(ClassType &m) {
|
||||
m.def("infer_shape", &ClassType::type::InferShape)
|
||||
.def("run", &ClassType::type::Run)
|
||||
.def("type",
|
||||
[](const typename ClassType::type &op) -> std::string {
|
||||
return op.type_;
|
||||
})
|
||||
.def("outputs",
|
||||
[](const typename ClassType::type &op) -> std::vector<std::string> {
|
||||
return op.outputs_;
|
||||
})
|
||||
.def("__str__", &ClassType::type::DebugString);
|
||||
}
|
||||
|
||||
static size_t UniqueIntegerGenerator() {
|
||||
static std::atomic<size_t> generator;
|
||||
return generator.fetch_add(1);
|
||||
}
|
||||
|
||||
bool IsCompileGPU() {
|
||||
#ifdef PADDLE_ONLY_CPU
|
||||
return false;
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
PYBIND11_PLUGIN(core) {
|
||||
py::module m("core", "C++ core of PaddlePaddle");
|
||||
|
||||
py::class_<Tensor>(m, "Tensor", py::buffer_protocol())
|
||||
.def_buffer(
|
||||
[](Tensor &self) -> py::buffer_info { return CastToPyBuffer(self); })
|
||||
.def("get_dims",
|
||||
[](const Tensor &self) { return vectorize(self.dims()); })
|
||||
.def("set_dims",
|
||||
[](Tensor &self, const std::vector<int> &dim) {
|
||||
self.Resize(make_ddim(dim));
|
||||
})
|
||||
.def("alloc_float",
|
||||
[](Tensor &self, paddle::platform::GPUPlace &place) {
|
||||
self.mutable_data<float>(place);
|
||||
})
|
||||
.def("alloc_float",
|
||||
[](Tensor &self, paddle::platform::CPUPlace &place) {
|
||||
self.mutable_data<float>(place);
|
||||
})
|
||||
.def("alloc_int",
|
||||
[](Tensor &self, paddle::platform::CPUPlace &place) {
|
||||
self.mutable_data<int>(place);
|
||||
})
|
||||
.def("alloc_int",
|
||||
[](Tensor &self, paddle::platform::GPUPlace &place) {
|
||||
self.mutable_data<int>(place);
|
||||
})
|
||||
.def("set", PyCPUTensorSetFromArray<float>)
|
||||
.def("set", PyCPUTensorSetFromArray<int>)
|
||||
#ifndef PADDLE_ONLY_CPU
|
||||
.def("set", PyCUDATensorSetFromArray<float>)
|
||||
.def("set", PyCUDATensorSetFromArray<int>)
|
||||
#endif
|
||||
.def("shape", [](Tensor &self) { return vectorize(self.dims()); });
|
||||
|
||||
py::class_<Variable>(m, "Variable", R"DOC(Variable Class.
|
||||
|
||||
All parameter, weight, gradient are variables in Paddle.
|
||||
)DOC")
|
||||
.def("is_int", [](const Variable &var) { return var.IsType<int>(); })
|
||||
.def("set_int",
|
||||
[](Variable &var, int val) -> void { *var.GetMutable<int>() = val; })
|
||||
.def("get_int", [](const Variable &var) -> int { return var.Get<int>(); })
|
||||
.def("get_tensor",
|
||||
[](Variable &self) -> Tensor * { return self.GetMutable<Tensor>(); },
|
||||
py::return_value_policy::reference)
|
||||
.def("get_net",
|
||||
[](Variable &self) -> ops::NetOp * {
|
||||
return self.GetMutable<ops::NetOp>();
|
||||
},
|
||||
py::return_value_policy::reference);
|
||||
|
||||
py::class_<Scope>(m, "Scope", "")
|
||||
.def("new_var",
|
||||
[](Scope &self, const std::string &name) -> Variable * {
|
||||
return self.NewVar(name);
|
||||
},
|
||||
py::return_value_policy::reference)
|
||||
.def("find_var", &Scope::FindVar, py::return_value_policy::reference)
|
||||
.def(py::init<>())
|
||||
.def("new_scope", [](Scope &self) -> Scope * { return &self.NewScope(); },
|
||||
py::return_value_policy::reference)
|
||||
.def("drop_kids", &Scope::DropKids);
|
||||
|
||||
//! @note: Be careful! PyBind will return std::string as an unicode, not
|
||||
//! Python str. If you want a str object, you should cast them in Python.
|
||||
m.def("get_all_op_protos", []() -> std::vector<py::bytes> {
|
||||
auto &protos = OpRegistry::protos();
|
||||
std::vector<py::bytes> ret_values;
|
||||
for (auto it = protos.begin(); it != protos.end(); ++it) {
|
||||
PADDLE_ENFORCE(it->second.IsInitialized(),
|
||||
"OpProto must all be initialized");
|
||||
std::string str;
|
||||
PADDLE_ENFORCE(it->second.SerializeToString(&str),
|
||||
"Serialize OpProto Error. This could be a bug of Paddle.");
|
||||
ret_values.push_back(py::bytes(str));
|
||||
}
|
||||
return ret_values;
|
||||
});
|
||||
m.def_submodule(
|
||||
"var_names",
|
||||
"The module will return special predefined variable name in Paddle")
|
||||
.def("empty", OperatorBase::EMPTY_VAR_NAME)
|
||||
.def("temp", OperatorBase::TMP_VAR_NAME);
|
||||
// clang-format off
|
||||
py::class_<paddle::platform::DeviceContext>(m, "DeviceContext")
|
||||
.def_static("create",
|
||||
[](paddle::platform::CPUPlace& place)
|
||||
-> paddle::platform::DeviceContext* {
|
||||
return new paddle::platform::CPUDeviceContext();
|
||||
})
|
||||
.def_static("create",
|
||||
[](paddle::platform::GPUPlace& place)
|
||||
-> paddle::platform::DeviceContext* {
|
||||
#ifdef PADDLE_ONLY_CPU
|
||||
PADDLE_THROW("GPUPlace is not supported in CPU device.");
|
||||
#else
|
||||
return new paddle::platform::CUDADeviceContext(place);
|
||||
#endif
|
||||
});
|
||||
// clang-format on
|
||||
|
||||
py::class_<paddle::platform::GPUPlace>(m, "GPUPlace").def(py::init<int>());
|
||||
|
||||
py::class_<paddle::platform::CPUPlace>(m, "CPUPlace").def(py::init<>());
|
||||
|
||||
py::class_<OperatorBase, std::shared_ptr<OperatorBase>> operator_base(
|
||||
m, "Operator");
|
||||
|
||||
operator_base.def_static("create", [](py::bytes protobin) {
|
||||
OpDesc desc;
|
||||
PADDLE_ENFORCE(desc.ParsePartialFromString(protobin),
|
||||
"Cannot parse user input to OpDesc");
|
||||
PADDLE_ENFORCE(desc.IsInitialized(),
|
||||
"User OpDesc is not initialized, reason %s",
|
||||
desc.InitializationErrorString());
|
||||
return OpRegistry::CreateOp(desc);
|
||||
});
|
||||
|
||||
operator_base.def("backward",
|
||||
[](const OperatorBase &forwardOp,
|
||||
const std::unordered_set<std::string> &no_grad_vars) {
|
||||
return Backward(forwardOp, no_grad_vars);
|
||||
});
|
||||
|
||||
ExposeOperator(operator_base);
|
||||
|
||||
py::class_<ops::NetOp, std::shared_ptr<ops::NetOp>> net(m, "Net");
|
||||
|
||||
net.def_static("create",
|
||||
[]() -> std::shared_ptr<ops::NetOp> {
|
||||
auto retv = std::make_shared<ops::NetOp>();
|
||||
retv->type_ = "plain_net";
|
||||
return retv;
|
||||
})
|
||||
.def("add_op", &ops::NetOp::AddOp)
|
||||
.def(
|
||||
"add_op",
|
||||
[](ops::NetOp &self, const std::shared_ptr<ops::NetOp> &net) -> void {
|
||||
self.AddOp(std::static_pointer_cast<OperatorBase>(net));
|
||||
})
|
||||
.def("complete_add_op", &ops::NetOp::CompleteAddOp)
|
||||
.def("complete_add_op",
|
||||
[](std::shared_ptr<ops::NetOp> &self) { self->CompleteAddOp(); });
|
||||
|
||||
ExposeOperator(net);
|
||||
|
||||
m.def("unique_integer", UniqueIntegerGenerator);
|
||||
|
||||
m.def("is_compile_gpu", IsCompileGPU);
|
||||
|
||||
return m.ptr();
|
||||
}
|
||||
} // namespace framework
|
||||
} // namespace paddle
|
@ -0,0 +1,79 @@
|
||||
/* Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserve.
|
||||
|
||||
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. */
|
||||
|
||||
#include "Layer.h"
|
||||
|
||||
namespace paddle {
|
||||
|
||||
/**
|
||||
* A layer for clipping the input value by the threshold.
|
||||
* \f[
|
||||
* out[i] = \min\left(\max\left(in[i],p_{1}\right),p_{2}\right)
|
||||
* \f]
|
||||
*/
|
||||
|
||||
class ClipLayer : public Layer {
|
||||
protected:
|
||||
double min_;
|
||||
double max_;
|
||||
|
||||
public:
|
||||
explicit ClipLayer(const LayerConfig& config) : Layer(config) {}
|
||||
|
||||
bool init(const LayerMap& layerMap,
|
||||
const ParameterMap& parameterMap) override;
|
||||
|
||||
void forward(PassType passType) override;
|
||||
void backward(const UpdateCallback& callback = nullptr) override;
|
||||
};
|
||||
|
||||
REGISTER_LAYER(clip, ClipLayer);
|
||||
|
||||
bool ClipLayer::init(const LayerMap& layerMap,
|
||||
const ParameterMap& parameterMap) {
|
||||
Layer::init(layerMap, parameterMap);
|
||||
|
||||
CHECK_EQ(inputLayers_.size(), 1U);
|
||||
auto layerConf = config_.inputs(0).clip_conf();
|
||||
min_ = layerConf.min();
|
||||
max_ = layerConf.max();
|
||||
CHECK_LT(min_, max_);
|
||||
return true;
|
||||
}
|
||||
|
||||
void ClipLayer::forward(PassType passType) {
|
||||
Layer::forward(passType);
|
||||
|
||||
MatrixPtr inV = getInputValue(0);
|
||||
resetOutput(inV->getHeight(), inV->getWidth());
|
||||
MatrixPtr outV = getOutputValue();
|
||||
outV->copyFrom(*inV);
|
||||
outV->clip(min_, max_);
|
||||
}
|
||||
|
||||
void ClipLayer::backward(const UpdateCallback& callback) {
|
||||
MatrixPtr inV = getInputValue(0);
|
||||
MatrixPtr inG = getInputGrad(0);
|
||||
if (inG) {
|
||||
MatrixPtr outV = getOutputValue();
|
||||
MatrixPtr outG = getOutputGrad();
|
||||
MatrixPtr tmpMtx;
|
||||
Matrix::resizeOrCreate(
|
||||
tmpMtx, outG->getHeight(), outG->getWidth(), false, useGpu_);
|
||||
tmpMtx->clipDerivative(*inV, min_, max_);
|
||||
inG->addDotMul(*outG, *tmpMtx, 1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace paddle
|
@ -0,0 +1,98 @@
|
||||
/* Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserve.
|
||||
|
||||
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. */
|
||||
|
||||
#include "Layer.h"
|
||||
|
||||
namespace paddle {
|
||||
|
||||
/**
|
||||
* A layer for L2 normalization in each row,
|
||||
* \f[
|
||||
* out[i] = \frac{in[i]}{\sqrt{\sum_{k=1}^N in[k]^{2}}}
|
||||
* \f]
|
||||
* where the size of \f$in\f$ is (batchSize x dataDim),
|
||||
* and the size of \f$out\f$ is (batchSize x dataDim).
|
||||
*/
|
||||
|
||||
class RowL2NormLayer : public Layer {
|
||||
protected:
|
||||
MatrixPtr inSquare_;
|
||||
MatrixPtr l2NormReciprocal_;
|
||||
MatrixPtr dotSum_;
|
||||
|
||||
public:
|
||||
explicit RowL2NormLayer(const LayerConfig& config) : Layer(config) {}
|
||||
|
||||
bool init(const LayerMap& layerMap,
|
||||
const ParameterMap& parameterMap) override;
|
||||
|
||||
void forward(PassType passType) override;
|
||||
void backward(const UpdateCallback& callback = nullptr) override;
|
||||
};
|
||||
|
||||
REGISTER_LAYER(row_l2_norm, RowL2NormLayer);
|
||||
|
||||
bool RowL2NormLayer::init(const LayerMap& layerMap,
|
||||
const ParameterMap& parameterMap) {
|
||||
Layer::init(layerMap, parameterMap);
|
||||
|
||||
CHECK_EQ(inputLayers_.size(), 1U);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void RowL2NormLayer::forward(PassType passType) {
|
||||
Layer::forward(passType);
|
||||
|
||||
MatrixPtr inV = getInputValue(0);
|
||||
|
||||
/* malloc memory for the output_ if necessary */
|
||||
size_t batchSize = inV->getHeight();
|
||||
size_t dataDim = getSize();
|
||||
CHECK_EQ(dataDim, inV->getWidth());
|
||||
resetOutput(batchSize, dataDim);
|
||||
MatrixPtr outV = getOutputValue();
|
||||
|
||||
Matrix::resizeOrCreate(inSquare_, batchSize, dataDim, false, useGpu_);
|
||||
inV->square2(*inSquare_);
|
||||
Matrix::resizeOrCreate(l2NormReciprocal_, batchSize, 1, false, useGpu_);
|
||||
inSquare_->rowSum(*l2NormReciprocal_);
|
||||
l2NormReciprocal_->sqrt2(*l2NormReciprocal_);
|
||||
l2NormReciprocal_->scalarDiv(*l2NormReciprocal_, 1.0);
|
||||
outV->rowScale(0, *inV, *l2NormReciprocal_);
|
||||
}
|
||||
|
||||
void RowL2NormLayer::backward(const UpdateCallback& callback) {
|
||||
MatrixPtr inV = getInputValue(0);
|
||||
MatrixPtr inG = getInputGrad(0);
|
||||
MatrixPtr outV = getOutputValue();
|
||||
MatrixPtr outG = getOutputGrad();
|
||||
size_t batchSize = inV->getHeight();
|
||||
|
||||
// inG[ij] += outG[ij] / l2NormReciprocal
|
||||
// inG[ij] += -inV[ij] * l2NormReciprocal * l2NormReciprocal * DotMul(outG[i],
|
||||
// inV[i])
|
||||
if (inG) {
|
||||
Matrix::resizeOrCreate(dotSum_, batchSize, 1, false, useGpu_);
|
||||
dotSum_->zeroMem();
|
||||
dotSum_->rowDotMul(0, *outG, *outV);
|
||||
dotSum_->dotMul(*dotSum_, *l2NormReciprocal_);
|
||||
dotSum_->dotMul(*dotSum_, *l2NormReciprocal_);
|
||||
inSquare_->rowScale(0, *inV, *dotSum_);
|
||||
inG->sub(*inSquare_);
|
||||
inG->addRowScale(0, *outG, *l2NormReciprocal_);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace paddle
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue