提交 877decdc 编写于 作者: X xutianbing

merge Daoyuan's FuncArg, address one of the comments.

上级 47aaac00
...@@ -27,6 +27,7 @@ if(WITH_TESTING) ...@@ -27,6 +27,7 @@ if(WITH_TESTING)
add_simple_unittest(ContextProjectionOpTest) add_simple_unittest(ContextProjectionOpTest)
add_simple_unittest(PadOpTest) add_simple_unittest(PadOpTest)
add_simple_unittest(MulOpTest) add_simple_unittest(MulOpTest)
add_simple_unittest(CosSimOpTest)
endif() endif()
endif() endif()
......
...@@ -27,21 +27,21 @@ namespace paddle { ...@@ -27,21 +27,21 @@ namespace paddle {
* *
*/ */
template <> template <>
void CosSimForward<DEVICE_TYPE_CPU>(CpuMatrix* out_mat, void CosSimForward<DEVICE_TYPE_CPU>(CpuMatrix& out_mat,
const CpuMatrix* in1_mat, const CpuMatrix& in1_mat,
const CpuMatrix* in2_mat, const CpuMatrix& in2_mat,
real scale) { real scale) {
CHECK(out_mat && in1_mat && in2_mat); CHECK(out_mat.getData() && in1_mat.getData() && in2_mat.getData());
size_t num_samples = out_mat->getHeight(); size_t num_samples = out_mat.getHeight();
size_t dim = in1_mat->getWidth(); size_t dim = in1_mat.getWidth();
/// column vector [nSamples, 1] /// column vector [nSamples, 1]
real* out = out_mat->getData(); real* out = out_mat.getData();
const real* x = in1_mat->getData(); const real* x = in1_mat.getData();
const real* y = in2_mat->getData(); const real* y = in2_mat.getData();
/// in2 might only have one row or full rows /// in2 might only have one row or full rows
CHECK(in2_mat->getHeight() == 1LU || in2_mat->getHeight() == num_samples); CHECK(in2_mat.getHeight() == 1LU || in2_mat.getHeight() == num_samples);
size_t inc = (in2_mat->getHeight() == 1LU) ? 0 : dim; size_t inc = (in2_mat.getHeight() == 1LU) ? 0 : dim;
for (size_t i = 0; i < num_samples; ++i, x += dim, y += inc) { for (size_t i = 0; i < num_samples; ++i, x += dim, y += inc) {
real square_sum_x = 0; real square_sum_x = 0;
real square_sum_y = 0; real square_sum_y = 0;
...@@ -75,26 +75,26 @@ class CosSimForwardFunc : public FunctionBase { ...@@ -75,26 +75,26 @@ class CosSimForwardFunc : public FunctionBase {
scale_ = config.get<real>("scale"); scale_ = config.get<real>("scale");
} }
void calc(const Arguments& inputs, void calc(const BufferArgs& inputs, const BufferArgs& outputs) override {
const Arguments& outputs,
const Arguments& inouts) override {
CHECK_EQ(inputs.size(), 2); CHECK_EQ(inputs.size(), 2);
CHECK_EQ(outputs.size(), 1); CHECK_EQ(outputs.size(), 1);
CHECK_EQ(inouts.size(), 0);
CHECK_EQ(inputs[0].dims_[0], outputs[0].dims_[0]); CHECK_EQ(inputs[0].shape().ndims(), (size_t)2);
CHECK_EQ(inputs[0].dims_[1], inputs[1].dims_[1]); CHECK_EQ(inputs[1].shape().ndims(), (size_t)2);
CHECK_EQ(outputs[0].dims_[1], 1UL); CHECK_EQ(outputs[0].shape().ndims(), (size_t)2);
CHECK(outputs[0].getData() && inputs[0].getData() && inputs[1].getData()); CHECK_EQ(inputs[0].shape()[0], outputs[0].shape()[0]);
auto out_mat = std::make_shared<typename MatrixT<Device>::type>( CHECK_EQ(inputs[0].shape()[1], inputs[1].shape()[1]);
outputs[0].getData(), outputs[0].dims_[0], outputs[0].dims_[1]); CHECK_EQ(outputs[0].shape()[1], 1UL);
const auto in1_mat = std::make_shared<typename MatrixT<Device>::type>(
inputs[0].getData(), inputs[0].dims_[0], inputs[0].dims_[1]);
const auto in2_mat = std::make_shared<typename MatrixT<Device>::type>(
inputs[1].getData(), inputs[1].dims_[0], inputs[1].dims_[1]);
CosSimForward<Device>(out_mat.get(), in1_mat.get(), in2_mat.get(), scale_); CHECK(outputs[0].data() && inputs[0].data() && inputs[1].data());
CHECK_EQ(outputs[0].getArgType(), ASSIGN_TO);
auto out_mat = outputs[0].matrix<Device>();
const auto in1_mat = inputs[0].matrix<Device>();
const auto in2_mat = inputs[1].matrix<Device>();
CosSimForward<Device>(out_mat, in1_mat, in2_mat, scale_);
} }
private: private:
...@@ -116,28 +116,29 @@ private: ...@@ -116,28 +116,29 @@ private:
* \param scale, default 1.0 * \param scale, default 1.0
*/ */
template <> template <>
void CosSimBackward<DEVICE_TYPE_CPU>(const CpuMatrix* out_grad, void CosSimBackward<DEVICE_TYPE_CPU>(const CpuMatrix& out_grad,
const CpuMatrix* out_val, const CpuMatrix& out_val,
const CpuMatrix* in1_val, const CpuMatrix& in1_val,
const CpuMatrix* in2_val, const CpuMatrix& in2_val,
CpuMatrix* in1_grad, CpuMatrix& in1_grad,
CpuMatrix* in2_grad, CpuMatrix& in2_grad,
real scale) { real scale) {
CHECK(out_grad && out_val && in1_val && in2_val && in1_grad && in2_grad); CHECK(out_grad.getData() && out_val.getData() && in1_val.getData() &&
CHECK_EQ(out_val->useGpu_, false) << "Matrix type are GPU, CPU required"; in2_val.getData() && in1_grad.getData() && in2_grad.getData());
CHECK_EQ(out_val.useGpu_, false) << "Matrix type are GPU, CPU required";
const real* grad = out_grad->getData();
const real* out = out_val->getData(); const real* grad = out_grad.getData();
const real* prev_out_x = in1_val->getData(); const real* out = out_val.getData();
const real* prev_out_y = in2_val->getData(); const real* prev_out_x = in1_val.getData();
real* prev_grad_x = in1_grad->getData(); const real* prev_out_y = in2_val.getData();
real* prev_grad_y = in2_grad->getData(); real* prev_grad_x = in1_grad.getData();
real* prev_grad_y = in2_grad.getData();
size_t num_samples = out_grad->getHeight();
size_t dim = in1_val->getWidth(); size_t num_samples = out_grad.getHeight();
CHECK_EQ(in2_val->getHeight(), in2_grad->getHeight()); size_t dim = in1_val.getWidth();
CHECK(in2_val->getHeight() == 1LU || in2_val->getHeight() == num_samples); CHECK_EQ(in2_val.getHeight(), in2_grad.getHeight());
size_t inc = (in2_val->getHeight() == 1LU) ? 0 : dim; CHECK(in2_val.getHeight() == 1LU || in2_val.getHeight() == num_samples);
size_t inc = (in2_val.getHeight() == 1LU) ? 0 : dim;
for (size_t i = 0; i < num_samples; ++i, for (size_t i = 0; i < num_samples; ++i,
prev_out_x += dim, prev_out_x += dim,
prev_out_y += inc, prev_out_y += inc,
...@@ -178,8 +179,8 @@ void CosSimBackward<DEVICE_TYPE_CPU>(const CpuMatrix* out_grad, ...@@ -178,8 +179,8 @@ void CosSimBackward<DEVICE_TYPE_CPU>(const CpuMatrix* out_grad,
/** /**
* Cosine Similarity backward Derivative * Cosine Similarity backward Derivative
* *
* \param inouts[0] forward input grad 1, size: nSamples * dim. * \param outputs[0] forward input grad 1, size: nSamples * dim.
* \param inouts[1] forward input grad 2, * \param outputs[1] forward input grad 2,
* size: n2 * dim (n2 == 1 or n2 == nSamples). * size: n2 * dim (n2 == 1 or n2 == nSamples).
* *
* \param inputs[0] backward loss output grad, size : nSamples * 1. * \param inputs[0] backward loss output grad, size : nSamples * 1.
...@@ -194,46 +195,36 @@ class CosSimBackwardFunc : public FunctionBase { ...@@ -194,46 +195,36 @@ class CosSimBackwardFunc : public FunctionBase {
scale_ = config.get<real>("scale"); scale_ = config.get<real>("scale");
} }
void calc(const Arguments& inputs, void calc(const BufferArgs& inputs, const BufferArgs& outputs) override {
const Arguments& outputs,
const Arguments& inouts) override {
CHECK_EQ(inputs.size(), 4); CHECK_EQ(inputs.size(), 4);
CHECK_EQ(outputs.size(), 0); CHECK_EQ(outputs.size(), 2);
CHECK_EQ(inouts.size(), 2);
/// dim of out_grad and out_val == 1, column vector /// dim of out_grad and out_val == 1, column vector
CHECK_EQ(inputs[0].dims_[1], 1UL); CHECK_EQ(inputs[0].shape()[1], 1UL);
CHECK_EQ(inputs[1].dims_[1], 1UL); CHECK_EQ(inputs[1].shape()[1], 1UL);
/// nSamples of out_grad == out_val == in_val1 == in_grad1 /// nSamples of out_grad == out_val == in_val1 == in_grad1
CHECK_EQ(inputs[1].dims_[0], inputs[0].dims_[0]); CHECK_EQ(inputs[1].shape()[0], inputs[0].shape()[0]);
CHECK_EQ(inputs[0].dims_[0], inputs[0].dims_[0]); CHECK_EQ(inputs[0].shape()[0], inputs[0].shape()[0]);
CHECK_EQ(inouts[0].dims_[0], inputs[0].dims_[0]); CHECK_EQ(outputs[0].shape()[0], inputs[0].shape()[0]);
/// dim of in1_val1 == in_val2 == in_grad1 == in_grad2 /// dim of in1_val1 == in_val2 == in_grad1 == in_grad2
CHECK_EQ(inputs[3].dims_[1], inputs[2].dims_[1]); CHECK_EQ(inputs[3].shape()[1], inputs[2].shape()[1]);
CHECK_EQ(inouts[0].dims_[1], inputs[2].dims_[1]); CHECK_EQ(outputs[0].shape()[1], inputs[2].shape()[1]);
CHECK_EQ(inouts[1].dims_[1], inputs[2].dims_[1]); CHECK_EQ(outputs[1].shape()[1], inputs[2].shape()[1]);
CHECK(inputs[0].getData() && inputs[1].getData() && inputs[2].getData() && CHECK(inputs[0].data() && inputs[1].data() && inputs[2].data() &&
inputs[3].getData() && inouts[0].getData() && inouts[1].getData()); inputs[3].data() && outputs[0].data() && outputs[1].data());
const auto out_grad = std::make_shared<typename MatrixT<Device>::type>(
inputs[0].getData(), inputs[0].dims_[0], inputs[0].dims_[1]); CHECK_EQ(outputs[0].getArgType(), ADD_TO);
const auto out_val = std::make_shared<typename MatrixT<Device>::type>( CHECK_EQ(outputs[1].getArgType(), ADD_TO);
inputs[1].getData(), inputs[1].dims_[0], inputs[1].dims_[1]);
const auto in1_val = std::make_shared<typename MatrixT<Device>::type>( const auto out_grad = inputs[0].matrix<Device>();
inputs[2].getData(), inputs[2].dims_[0], inputs[2].dims_[1]); const auto out_val = inputs[1].matrix<Device>();
const auto in2_val = std::make_shared<typename MatrixT<Device>::type>( const auto in1_val = inputs[2].matrix<Device>();
inputs[3].getData(), inputs[3].dims_[0], inputs[3].dims_[1]); const auto in2_val = inputs[3].matrix<Device>();
auto in1_grad = std::make_shared<typename MatrixT<Device>::type>( auto in1_grad = outputs[0].matrix<Device>();
inouts[0].getData(), inouts[0].dims_[0], inouts[0].dims_[1]); auto in2_grad = outputs[1].matrix<Device>();
auto in2_grad = std::make_shared<typename MatrixT<Device>::type>(
inouts[1].getData(), inouts[1].dims_[0], inouts[1].dims_[1]); CosSimBackward<Device>(
out_grad, out_val, in1_val, in2_val, in1_grad, in2_grad, scale_);
CosSimBackward<Device>(out_grad.get(),
out_val.get(),
in1_val.get(),
in2_val.get(),
in1_grad.get(),
in2_grad.get(),
scale_);
} }
private: private:
......
...@@ -32,9 +32,9 @@ namespace paddle { ...@@ -32,9 +32,9 @@ namespace paddle {
* *
*/ */
template <DeviceType Device> template <DeviceType Device>
void CosSimForward(typename MatrixT<Device>::type* output, void CosSimForward(typename Tensor<real, Device>::Matrix& output,
const typename MatrixT<Device>::type* input1, const typename Tensor<real, Device>::Matrix& input1,
const typename MatrixT<Device>::type* input2, const typename Tensor<real, Device>::Matrix& input2,
real scale); real scale);
/** /**
...@@ -50,12 +50,12 @@ void CosSimForward(typename MatrixT<Device>::type* output, ...@@ -50,12 +50,12 @@ void CosSimForward(typename MatrixT<Device>::type* output,
* *
*/ */
template <DeviceType Device> template <DeviceType Device>
void CosSimBackward(const typename MatrixT<Device>::type* out_grad, void CosSimBackward(const typename Tensor<real, Device>::Matrix& out_grad,
const typename MatrixT<Device>::type* out_value, const typename Tensor<real, Device>::Matrix& out_value,
const typename MatrixT<Device>::type* in1_value, const typename Tensor<real, Device>::Matrix& in1_value,
const typename MatrixT<Device>::type* in2_value, const typename Tensor<real, Device>::Matrix& in2_value,
typename MatrixT<Device>::type* in1_grad, typename Tensor<real, Device>::Matrix& in1_grad,
typename MatrixT<Device>::type* in2_grad, typename Tensor<real, Device>::Matrix& in2_grad,
real scale); real scale);
} // namespace paddle } // namespace paddle
...@@ -65,12 +65,12 @@ __global__ void KeCosSim(real* output, ...@@ -65,12 +65,12 @@ __global__ void KeCosSim(real* output,
} }
void hlCossim(real* output, void hlCossim(real* output,
const real* input1, const real* input1,
const real* input2, const real* input2,
size_t width, size_t width,
size_t input1_height, size_t input1_height,
size_t input2_height, size_t input2_height,
real scale) { real scale) {
CHECK_NOTNULL(output); CHECK_NOTNULL(output);
CHECK_NOTNULL(input1); CHECK_NOTNULL(input1);
CHECK_NOTNULL(input2); CHECK_NOTNULL(input2);
...@@ -84,20 +84,20 @@ void hlCossim(real* output, ...@@ -84,20 +84,20 @@ void hlCossim(real* output,
} }
template <> template <>
void CosSimForward<DEVICE_TYPE_GPU>(GpuMatrix* out_mat, void CosSimForward<DEVICE_TYPE_GPU>(GpuMatrix& out_mat,
const GpuMatrix* in1_mat, const GpuMatrix& in1_mat,
const GpuMatrix* in2_mat, const GpuMatrix& in2_mat,
real scale) { real scale) {
CHECK(out_mat && in1_mat && in2_mat); CHECK(out_mat.getData() && in1_mat.getData() && in2_mat.getData());
CHECK(in1_mat->useGpu_ == true && in2_mat->useGpu_ == true) CHECK(in1_mat.useGpu_ == true && in2_mat.useGpu_ == true)
<< "Matrix type are not GPU"; << "Matrix type are not GPU";
size_t num_samples = out_mat->getHeight(); size_t num_samples = out_mat.getHeight();
size_t dim = in1_mat->getWidth(); size_t dim = in1_mat.getWidth();
real* out = out_mat->getData(); real* out = out_mat.getData();
const real* x = in1_mat->getData(); const real* x = in1_mat.getData();
const real* y = in2_mat->getData(); const real* y = in2_mat.getData();
hlCossim(out, x, y, dim, in1_mat->getHeight(), in2_mat->getHeight(), scale); hlCossim(out, x, y, dim, in1_mat.getHeight(), in2_mat.getHeight(), scale);
} }
template<int block_size> template<int block_size>
...@@ -206,25 +206,26 @@ void hlCossimDerivative(const real* grad, ...@@ -206,25 +206,26 @@ void hlCossimDerivative(const real* grad,
} }
template <> template <>
void CosSimBackward<DEVICE_TYPE_GPU>(const GpuMatrix* out_grad, void CosSimBackward<DEVICE_TYPE_GPU>(const GpuMatrix& out_grad,
const GpuMatrix* out_val, const GpuMatrix& out_val,
const GpuMatrix* in1_val, const GpuMatrix& in1_val,
const GpuMatrix* in2_val, const GpuMatrix& in2_val,
GpuMatrix* in1_grad, GpuMatrix& in1_grad,
GpuMatrix* in2_grad, GpuMatrix& in2_grad,
real scale) { real scale) {
CHECK(out_grad && out_val && in1_val && in2_val && in1_grad && in2_grad); CHECK(out_grad.getData() && out_val.getData() && in1_val.getData() &&
CHECK(out_grad->useGpu_ && out_val->useGpu_ && in1_val->useGpu_ in2_val.getData() && in1_grad.getData() && in2_grad.getData());
&& in2_val->useGpu_ && in1_grad->useGpu_ && in2_grad->useGpu_) CHECK(out_grad.useGpu_ && out_val.useGpu_ && in1_val.useGpu_
&& in2_val.useGpu_ && in1_grad.useGpu_ && in2_grad.useGpu_)
<< "Matrix types are not equally GPU"; << "Matrix types are not equally GPU";
size_t dim = in1_val->getWidth(); size_t dim = in1_val.getWidth();
const real* grad = out_grad->getData(); const real* grad = out_grad.getData();
const real* out = out_val->getData(); const real* out = out_val.getData();
const real* prev_out_x = in1_val->getData(); const real* prev_out_x = in1_val.getData();
const real* prev_out_y = in2_val->getData(); const real* prev_out_y = in2_val.getData();
real* prev_grad_x = in1_grad->getData(); real* prev_grad_x = in1_grad.getData();
real* prev_grad_y = in2_grad->getData(); real* prev_grad_y = in2_grad.getData();
hlCossimDerivative(grad, hlCossimDerivative(grad,
out, out,
prev_out_x, prev_out_x,
...@@ -232,8 +233,8 @@ void CosSimBackward<DEVICE_TYPE_GPU>(const GpuMatrix* out_grad, ...@@ -232,8 +233,8 @@ void CosSimBackward<DEVICE_TYPE_GPU>(const GpuMatrix* out_grad,
prev_grad_x, prev_grad_x,
prev_grad_y, prev_grad_y,
dim, dim,
in1_val->getHeight(), in1_val.getHeight(),
in2_val->getHeight(), in2_val.getHeight(),
scale); scale);
} }
......
...@@ -36,16 +36,20 @@ void testCosSimForward(size_t height_x, ...@@ -36,16 +36,20 @@ void testCosSimForward(size_t height_x,
CpuMatrix cpu_out(height_x, 1); CpuMatrix cpu_out(height_x, 1);
GpuMatrix gpu_out(height_x, 1); GpuMatrix gpu_out(height_x, 1);
compare.getCpuFunction()->calc( BufferArgs cpu_inputs;
{Tensor(cpu_arg1.getData(), Dims{height_x, width}), BufferArgs cpu_outputs;
Tensor(cpu_arg2.getData(), Dims{height_y, width})}, cpu_inputs.addArg(cpu_arg1);
{Tensor(cpu_out.getData(), Dims{height_x, 1})}, cpu_inputs.addArg(cpu_arg2);
{}); cpu_outputs.addArg(cpu_out, ASSIGN_TO);
compare.getGpuFunction()->calc(
{Tensor(gpu_arg1.getData(), Dims{height_x, width}), BufferArgs gpu_inputs;
Tensor(gpu_arg2.getData(), Dims{height_y, width})}, BufferArgs gpu_outputs;
{Tensor(gpu_out.getData(), Dims{height_x, 1})}, gpu_inputs.addArg(gpu_arg1);
{}); gpu_inputs.addArg(gpu_arg2);
gpu_outputs.addArg(gpu_out, ASSIGN_TO);
compare.getCpuFunction()->calc(cpu_inputs, cpu_outputs);
compare.getGpuFunction()->calc(gpu_inputs, gpu_outputs);
autotest::TensorCheckErr(cpu_out, gpu_out); autotest::TensorCheckErr(cpu_out, gpu_out);
} }
...@@ -96,23 +100,26 @@ void testCosSimBackward(size_t height_x, ...@@ -96,23 +100,26 @@ void testCosSimBackward(size_t height_x,
gpu_in1_grad.copyFrom(cpu_in1_grad); gpu_in1_grad.copyFrom(cpu_in1_grad);
gpu_in2_grad.copyFrom(cpu_in2_grad); gpu_in2_grad.copyFrom(cpu_in2_grad);
compare.getCpuFunction()->calc( BufferArgs cpu_inputs;
{Tensor(cpu_out_grad.getData(), Dims{height_x, 1}), BufferArgs cpu_outputs;
Tensor(cpu_out_val.getData(), Dims{height_x, 1}), cpu_inputs.addArg(cpu_out_grad);
Tensor(cpu_in1_val.getData(), Dims{height_x, width}), cpu_inputs.addArg(cpu_out_val);
Tensor(cpu_in2_val.getData(), Dims{height_x, width})}, cpu_inputs.addArg(cpu_in1_val);
{}, cpu_inputs.addArg(cpu_in2_val);
{Tensor(cpu_in1_grad.getData(), Dims{height_x, width}), cpu_outputs.addArg(cpu_in1_grad, ADD_TO);
Tensor(cpu_in2_grad.getData(), Dims{height_x, width})}); cpu_outputs.addArg(cpu_in2_grad, ADD_TO);
compare.getGpuFunction()->calc( BufferArgs gpu_inputs;
{Tensor(gpu_out_grad.getData(), Dims{height_x, 1}), BufferArgs gpu_outputs;
Tensor(gpu_out_val.getData(), Dims{height_x, 1}), gpu_inputs.addArg(gpu_out_grad);
Tensor(gpu_in1_val.getData(), Dims{height_x, width}), gpu_inputs.addArg(gpu_out_val);
Tensor(gpu_in2_val.getData(), Dims{height_x, width})}, gpu_inputs.addArg(gpu_in1_val);
{}, gpu_inputs.addArg(gpu_in2_val);
{Tensor(gpu_in1_grad.getData(), Dims{height_x, width}), gpu_outputs.addArg(gpu_in1_grad, ADD_TO);
Tensor(gpu_in2_grad.getData(), Dims{height_x, width})}); gpu_outputs.addArg(gpu_in2_grad, ADD_TO);
compare.getCpuFunction()->calc(cpu_inputs, cpu_outputs);
compare.getGpuFunction()->calc(gpu_inputs, gpu_outputs);
autotest::TensorCheckErr(cpu_in1_grad, gpu_in1_grad); autotest::TensorCheckErr(cpu_in1_grad, gpu_in1_grad);
autotest::TensorCheckErr(cpu_in2_grad, gpu_in2_grad); autotest::TensorCheckErr(cpu_in2_grad, gpu_in2_grad);
......
...@@ -157,6 +157,9 @@ public: ...@@ -157,6 +157,9 @@ public:
cpuSparse_->randomizeUniform(); cpuSparse_->randomizeUniform();
gpuSparse_->copyFrom(*cpuSparse_, stream); gpuSparse_->copyFrom(*cpuSparse_, stream);
hl_stream_synchronize(stream); hl_stream_synchronize(stream);
void addInputs(const SequenceArg& input) {
size_t batchSize = input.shape()[0];
size_t numSeqs = batchSize / 10 + 1;
cpuOutputs_.emplace_back( cpuOutputs_.emplace_back(
std::make_shared<SparseMatrixArg>(*cpuSparse_, argType)); std::make_shared<SparseMatrixArg>(*cpuSparse_, argType));
...@@ -331,6 +334,7 @@ protected: ...@@ -331,6 +334,7 @@ protected:
} }
protected: protected:
<<<<<<< HEAD
std::shared_ptr<FunctionBase> cpuFunc_; std::shared_ptr<FunctionBase> cpuFunc_;
std::shared_ptr<FunctionBase> gpuFunc_; std::shared_ptr<FunctionBase> gpuFunc_;
std::vector<CpuMemHandlePtr> cpuMemory_; std::vector<CpuMemHandlePtr> cpuMemory_;
......
...@@ -56,13 +56,12 @@ void CosSimLayer::forward(PassType passType) { ...@@ -56,13 +56,12 @@ void CosSimLayer::forward(PassType passType) {
MatrixPtr prevOut2 = getInputValue(1); MatrixPtr prevOut2 = getInputValue(1);
CHECK(outV && prevOut1 && prevOut2); CHECK(outV && prevOut1 && prevOut2);
forward_[0]->calc( BufferArgs inputs;
{Tensor(prevOut1->getData(), BufferArgs outputs;
Dims{prevOut1->getHeight(), prevOut1->getWidth()}), inputs.addArg(*prevOut1);
Tensor(prevOut2->getData(), inputs.addArg(*prevOut2);
Dims{prevOut2->getHeight(), prevOut2->getWidth()})}, outputs.addArg(*outV, ASSIGN_TO);
{Tensor(outV->getData(), Dims{outV->getHeight(), outV->getWidth()})}, forward_[0]->calc(inputs, outputs);
{});
} }
} }
...@@ -78,14 +77,16 @@ void CosSimLayer::backward(const UpdateCallback& callback) { ...@@ -78,14 +77,16 @@ void CosSimLayer::backward(const UpdateCallback& callback) {
auto inG1 = this->getInputGrad(0); auto inG1 = this->getInputGrad(0);
auto inG2 = this->getInputGrad(1); auto inG2 = this->getInputGrad(1);
CHECK(outG && outV && inV1 && inV2 && inG1 && inG2); CHECK(outG && outV && inV1 && inV2 && inG1 && inG2);
backward_[0]->calc( BufferArgs inputs;
{Tensor(outG->getData(), Dims{outG->getHeight(), outG->getWidth()}), BufferArgs outputs;
Tensor(outV->getData(), Dims{outV->getHeight(), outV->getWidth()}), inputs.addArg(*outG);
Tensor(inV1->getData(), Dims{inV1->getHeight(), inV1->getWidth()}), inputs.addArg(*outV);
Tensor(inV2->getData(), Dims{inV2->getHeight(), inV2->getWidth()})}, inputs.addArg(*inV1);
{}, inputs.addArg(*inV2);
{Tensor(inG1->getData(), Dims{inG1->getHeight(), inG1->getWidth()}), outputs.addArg(*inG1, ADD_TO);
Tensor(inG2->getData(), Dims{inG2->getHeight(), inG2->getWidth()})}); outputs.addArg(*inG2, ADD_TO);
backward_[0]->calc(inputs, outputs);
} }
} }
......
...@@ -12,11 +12,44 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ...@@ -12,11 +12,44 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. */ limitations under the License. */
#include "CosSimVecMatLayer.h" #include "Layer.h"
#include "paddle/math/Matrix.h"
#include "paddle/utils/Logging.h" #include "paddle/utils/Logging.h"
#include "paddle/utils/Stat.h" #include "paddle/utils/Stat.h"
namespace paddle { namespace paddle {
/**
* @brief A layer for computing cosine similarity between a vector
* and each row of a matrix
* out[i] = cos_scale * cos(in1, in2(i,:));
* @note used in NEURAL TURING MACHINE
*
* Input1: a vector (batchSize * dataDim)
*
* Input2: a matrix in vector form (batchSize * (weightDim*dataDim))
*
* Output: a vector (batchSize * weightDim)
*/
class CosSimVecMatLayer : public Layer {
public:
explicit CosSimVecMatLayer(const LayerConfig& config) : Layer(config) {}
~CosSimVecMatLayer() {}
bool init(const LayerMap& layerMap, const ParameterMap& parameterMap);
void forward(PassType passType);
void backward(const UpdateCallback& callback = nullptr);
protected:
MatrixPtr tmpMtx0;
MatrixPtr tmpMtx1;
MatrixPtr tmpRow0;
MatrixPtr tmpRow1;
MatrixPtr tmpRow2;
MatrixPtr tmpRow3;
};
/** /**
* @brief A layer for computing cosine similarity between a vector * @brief A layer for computing cosine similarity between a vector
...@@ -98,7 +131,6 @@ bool CosSimVecMatLayer::init(const LayerMap& layerMap, ...@@ -98,7 +131,6 @@ bool CosSimVecMatLayer::init(const LayerMap& layerMap,
/* trans= */ false, /* trans= */ false,
useGpu_); useGpu_);
/// todo(tianbing), do we really need to check these shared pointers?
CHECK(tmpRow0 && tmpRow1 && tmpRow2 && tmpRow3 && tmpMtx0 && tmpMtx1); CHECK(tmpRow0 && tmpRow1 && tmpRow2 && tmpRow3 && tmpMtx0 && tmpMtx1);
createFunction(forward_, createFunction(forward_,
...@@ -136,13 +168,12 @@ void CosSimVecMatLayer::forward(PassType passType) { ...@@ -136,13 +168,12 @@ void CosSimVecMatLayer::forward(PassType passType) {
tmpMtx0->setData(inV1->rowBuf(i)); tmpMtx0->setData(inV1->rowBuf(i));
tmpRow2->setData(outV->rowBuf(i)); tmpRow2->setData(outV->rowBuf(i));
forward_[0]->calc({Tensor(tmpMtx0->getData(), BufferArgs inputs;
Dims{tmpMtx0->getHeight(), tmpMtx0->getWidth()}), BufferArgs outputs;
Tensor(tmpRow0->getData(), inputs.addArg(*tmpMtx0);
Dims{tmpRow0->getHeight(), tmpRow0->getWidth()})}, inputs.addArg(*tmpRow0);
{Tensor(tmpRow2->getData(), outputs.addArg(*tmpRow2, ASSIGN_TO);
Dims{tmpRow2->getHeight(), tmpRow2->getWidth()})}, forward_[0]->calc(inputs, outputs);
{});
} }
} }
...@@ -168,20 +199,16 @@ void CosSimVecMatLayer::backward(const UpdateCallback& callback) { ...@@ -168,20 +199,16 @@ void CosSimVecMatLayer::backward(const UpdateCallback& callback) {
tmpRow2->setData(outV->rowBuf(i)); tmpRow2->setData(outV->rowBuf(i));
tmpRow3->setData(outG->rowBuf(i)); tmpRow3->setData(outG->rowBuf(i));
backward_[0]->calc( BufferArgs inputs;
{Tensor(tmpRow3->getData(), BufferArgs outputs;
Dims{tmpRow3->getHeight(), tmpRow3->getWidth()}), inputs.addArg(*tmpRow3);
Tensor(tmpRow2->getData(), inputs.addArg(*tmpRow2);
Dims{tmpRow2->getHeight(), tmpRow2->getWidth()}), inputs.addArg(*tmpMtx0);
Tensor(tmpMtx0->getData(), inputs.addArg(*tmpRow0);
Dims{tmpMtx0->getHeight(), tmpMtx0->getWidth()}), outputs.addArg(*tmpMtx1, ADD_TO);
Tensor(tmpRow0->getData(), outputs.addArg(*tmpRow1, ADD_TO);
Dims{tmpRow0->getHeight(), tmpRow0->getWidth()})},
{}, backward_[0]->calc(inputs, outputs);
{Tensor(tmpMtx1->getData(),
Dims{tmpMtx1->getHeight(), tmpMtx1->getWidth()}),
Tensor(tmpRow1->getData(),
Dims{tmpRow1->getHeight(), tmpRow1->getWidth()})});
} }
} }
......
/* 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. */
#pragma once
#include "Layer.h"
#include "paddle/math/Matrix.h"
namespace paddle {
/**
* @brief A layer for computing cosine similarity between a vector
* and each row of a matrix
* out[i] = cos_scale * cos(in1, in2(i,:));
* @note used in NEURAL TURING MACHINE
*
* Input1: a vector (batchSize * dataDim)
*
* Input2: a matrix in vector form (batchSize * (weightDim*dataDim))
*
* Output: a vector (batchSize * weightDim)
*/
class CosSimVecMatLayer : public Layer {
public:
explicit CosSimVecMatLayer(const LayerConfig& config) : Layer(config) {}
~CosSimVecMatLayer() {}
bool init(const LayerMap& layerMap, const ParameterMap& parameterMap);
void forward(PassType passType);
void backward(const UpdateCallback& callback = nullptr);
protected:
MatrixPtr tmpMtx0;
MatrixPtr tmpMtx1;
MatrixPtr tmpRow0;
MatrixPtr tmpRow1;
MatrixPtr tmpRow2;
MatrixPtr tmpRow3;
};
} // namespace paddle
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册