|
|
@ -34,35 +34,28 @@ class BilinearTensorProductOp : public framework::OperatorWithKernel {
|
|
|
|
auto y_dims = ctx->GetInputDim("Y");
|
|
|
|
auto y_dims = ctx->GetInputDim("Y");
|
|
|
|
auto weight_dims = ctx->GetInputDim("Weight");
|
|
|
|
auto weight_dims = ctx->GetInputDim("Weight");
|
|
|
|
|
|
|
|
|
|
|
|
PADDLE_ENFORCE_EQ(x_dims.size(), 2UL, "The input X must be a 2D Tensor.");
|
|
|
|
PADDLE_ENFORCE_EQ(x_dims.size(), 2UL, "The input(X) must be a 2D Tensor.");
|
|
|
|
PADDLE_ENFORCE_EQ(y_dims.size(), 2UL, "The input Y must be a 2D Tensor.");
|
|
|
|
PADDLE_ENFORCE_EQ(y_dims.size(), 2UL, "The input(Y) must be a 2D Tensor.");
|
|
|
|
PADDLE_ENFORCE_EQ(weight_dims.size(), 3UL,
|
|
|
|
PADDLE_ENFORCE_EQ(weight_dims.size(), 3UL,
|
|
|
|
"The input Weight must be a 3D tensor.");
|
|
|
|
"The input(Weight) must be a 3D tensor.");
|
|
|
|
PADDLE_ENFORCE(weight_dims[0],
|
|
|
|
|
|
|
|
"The first dimension of Weight must be larger than 0.");
|
|
|
|
|
|
|
|
PADDLE_ENFORCE(weight_dims[1],
|
|
|
|
|
|
|
|
"The second dimension of Weight must be larger than 0.");
|
|
|
|
|
|
|
|
PADDLE_ENFORCE(weight_dims[2],
|
|
|
|
|
|
|
|
"The third dimension of Weight must be larger than 0.");
|
|
|
|
|
|
|
|
PADDLE_ENFORCE_EQ(x_dims[0], y_dims[0],
|
|
|
|
PADDLE_ENFORCE_EQ(x_dims[0], y_dims[0],
|
|
|
|
"The first dimension(batch_size) of X must be "
|
|
|
|
"The first dimension(batch_size) of input(X) must be "
|
|
|
|
"equal to the first dimension of the Y.");
|
|
|
|
"equal to the first dimension of the input(Y).");
|
|
|
|
PADDLE_ENFORCE_EQ(x_dims[1], weight_dims[1],
|
|
|
|
PADDLE_ENFORCE_EQ(x_dims[1], weight_dims[1],
|
|
|
|
"The second dimension of X must be equal to the second "
|
|
|
|
"The second dimension of input(X) must be equal to "
|
|
|
|
"dimension of the Weight.");
|
|
|
|
"the second dimension of the input(Weight).");
|
|
|
|
PADDLE_ENFORCE_EQ(y_dims[1], weight_dims[2],
|
|
|
|
PADDLE_ENFORCE_EQ(y_dims[1], weight_dims[2],
|
|
|
|
"The second dimension of Y must be equal to the third "
|
|
|
|
"The second dimension of input(Y) must be equal to "
|
|
|
|
"dimension of the Weight.");
|
|
|
|
"the third dimension of the input(Weight).");
|
|
|
|
|
|
|
|
|
|
|
|
if (ctx->HasInput("Bias")) {
|
|
|
|
if (ctx->HasInput("Bias")) {
|
|
|
|
auto bias_dims = ctx->GetInputDim("Bias");
|
|
|
|
auto bias_dims = ctx->GetInputDim("Bias");
|
|
|
|
PADDLE_ENFORCE_EQ(bias_dims.size(), 2UL,
|
|
|
|
PADDLE_ENFORCE(bias_dims.size() == 2UL && bias_dims[0] == 1UL,
|
|
|
|
"The input Bias must have 2 dimensions.");
|
|
|
|
"The Input(Bias) must be a 2-D tensor with "
|
|
|
|
PADDLE_ENFORCE_EQ(bias_dims[0], 1UL,
|
|
|
|
"the 2nd dimension fixed to 1 (a row vector).");
|
|
|
|
"The first dimention of input Bias must be 1.");
|
|
|
|
|
|
|
|
PADDLE_ENFORCE_EQ(bias_dims[1], weight_dims[0],
|
|
|
|
PADDLE_ENFORCE_EQ(bias_dims[1], weight_dims[0],
|
|
|
|
"The second dimension of Bias must be equal to the "
|
|
|
|
"The second dimension of input(Bias) must be equal "
|
|
|
|
"first dimension of the Weight.");
|
|
|
|
"to the first dimension of the input(Weight).");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ctx->SetOutputDim("Out", {x_dims[0], weight_dims[0]});
|
|
|
|
ctx->SetOutputDim("Out", {x_dims[0], weight_dims[0]});
|
|
|
@ -75,12 +68,13 @@ class BilinearTensorProductOpMaker : public framework::OpProtoAndCheckerMaker {
|
|
|
|
BilinearTensorProductOpMaker(framework::OpProto* proto,
|
|
|
|
BilinearTensorProductOpMaker(framework::OpProto* proto,
|
|
|
|
framework::OpAttrChecker* op_checker)
|
|
|
|
framework::OpAttrChecker* op_checker)
|
|
|
|
: OpProtoAndCheckerMaker(proto, op_checker) {
|
|
|
|
: OpProtoAndCheckerMaker(proto, op_checker) {
|
|
|
|
AddInput("X", "The first input of BilinearTensorProduct op.");
|
|
|
|
AddInput("X", "The first input of bilinear_tensor_product operator.");
|
|
|
|
AddInput("Y", "The second input of BilinearTensorProduct op.");
|
|
|
|
AddInput("Y", "The second input of bilinear_tensor_product operator.");
|
|
|
|
AddInput("Weight", "The input weight of BilinearTensorProduct op.");
|
|
|
|
AddInput("Weight",
|
|
|
|
AddInput("Bias", "The input bias of BilinearTensorProduct op.")
|
|
|
|
"The learnable parameters of bilinear_tensor_product operator.");
|
|
|
|
|
|
|
|
AddInput("Bias", "The learnable bias of bilinear_tensor_product operator.")
|
|
|
|
.AsDispensable();
|
|
|
|
.AsDispensable();
|
|
|
|
AddOutput("Out", "The output of BilinearTensorProduct op.");
|
|
|
|
AddOutput("Out", "The output of bilinear_tensor_product operator.");
|
|
|
|
AddComment(R"DOC(
|
|
|
|
AddComment(R"DOC(
|
|
|
|
Bilinear Tensor Product operator.
|
|
|
|
Bilinear Tensor Product operator.
|
|
|
|
Given input X and Y, a 3D tensor weight, and bias. Each column of the
|
|
|
|
Given input X and Y, a 3D tensor weight, and bias. Each column of the
|
|
|
@ -104,27 +98,29 @@ class BilinearTensorProductOpGrad : public framework::OperatorWithKernel {
|
|
|
|
PADDLE_ENFORCE(ctx->HasInput("Weight"),
|
|
|
|
PADDLE_ENFORCE(ctx->HasInput("Weight"),
|
|
|
|
"Input(Weight) should not be null.");
|
|
|
|
"Input(Weight) should not be null.");
|
|
|
|
PADDLE_ENFORCE(ctx->HasInput(framework::GradVarName("Out")),
|
|
|
|
PADDLE_ENFORCE(ctx->HasInput(framework::GradVarName("Out")),
|
|
|
|
"Input (Out@GRAD) should not be null.");
|
|
|
|
"Input(Out@GRAD) should not be null.");
|
|
|
|
auto x_dims = ctx->GetInputDim("X");
|
|
|
|
auto x_dims = ctx->GetInputDim("X");
|
|
|
|
auto y_dims = ctx->GetInputDim("Y");
|
|
|
|
auto y_dims = ctx->GetInputDim("Y");
|
|
|
|
auto weight_dims = ctx->GetInputDim("Weight");
|
|
|
|
auto weight_dims = ctx->GetInputDim("Weight");
|
|
|
|
auto out_dims = ctx->GetInputDim(framework::GradVarName("Out"));
|
|
|
|
auto out_dims = ctx->GetInputDim(framework::GradVarName("Out"));
|
|
|
|
|
|
|
|
|
|
|
|
PADDLE_ENFORCE_EQ(out_dims.size(), 2UL,
|
|
|
|
PADDLE_ENFORCE_EQ(out_dims.size(), 2UL,
|
|
|
|
"The Out@GRAD must be a 2D Tensor.");
|
|
|
|
"The input(Out@GRAD) must be a 2D Tensor.");
|
|
|
|
PADDLE_ENFORCE_EQ(
|
|
|
|
PADDLE_ENFORCE_EQ(
|
|
|
|
x_dims[0], out_dims[0],
|
|
|
|
x_dims[0], out_dims[0],
|
|
|
|
"The first dimension(batch_size) of Out@GRAD must be equal to "
|
|
|
|
"The first dimension(batch_size) of input(Out@GRAD) must be "
|
|
|
|
"the first dimension of the Input(X).");
|
|
|
|
"equal to the first dimension of the Input(X).");
|
|
|
|
PADDLE_ENFORCE_EQ(weight_dims[0], out_dims[1],
|
|
|
|
PADDLE_ENFORCE_EQ(
|
|
|
|
"The second dimension of Out@GRAD must be equal to "
|
|
|
|
weight_dims[0], out_dims[1],
|
|
|
|
"the third dimension of the Input(Weight).");
|
|
|
|
"The second dimension of input(Out@GRAD) must be equal to "
|
|
|
|
|
|
|
|
"the third dimension of the Input(Weight).");
|
|
|
|
|
|
|
|
|
|
|
|
if (ctx->HasInput("Bias")) {
|
|
|
|
if (ctx->HasInput("Bias")) {
|
|
|
|
auto bias_dims = ctx->GetInputDim("Bias");
|
|
|
|
auto bias_dims = ctx->GetInputDim("Bias");
|
|
|
|
PADDLE_ENFORCE_EQ(bias_dims[1], out_dims[1],
|
|
|
|
PADDLE_ENFORCE_EQ(
|
|
|
|
"The second dimension of Out@GRAD must be equal to "
|
|
|
|
bias_dims[1], out_dims[1],
|
|
|
|
"the second dimension of the Input(Bias).");
|
|
|
|
"The second dimension of input(Out@GRAD) must be equal to "
|
|
|
|
|
|
|
|
"the second dimension of the Input(Bias).");
|
|
|
|
auto bias_grad_name = framework::GradVarName("Bias");
|
|
|
|
auto bias_grad_name = framework::GradVarName("Bias");
|
|
|
|
if (ctx->HasOutput(bias_grad_name))
|
|
|
|
if (ctx->HasOutput(bias_grad_name))
|
|
|
|
ctx->SetOutputDim(bias_grad_name, bias_dims);
|
|
|
|
ctx->SetOutputDim(bias_grad_name, bias_dims);
|
|
|
@ -155,7 +151,9 @@ REGISTER_OP(bilinear_tensor_product, ops::BilinearTensorProductOp,
|
|
|
|
ops::BilinearTensorProductOpGrad);
|
|
|
|
ops::BilinearTensorProductOpGrad);
|
|
|
|
REGISTER_OP_CPU_KERNEL(
|
|
|
|
REGISTER_OP_CPU_KERNEL(
|
|
|
|
bilinear_tensor_product,
|
|
|
|
bilinear_tensor_product,
|
|
|
|
ops::BilinearTensorProductKernel<paddle::platform::CPUPlace, float>);
|
|
|
|
ops::BilinearTensorProductKernel<paddle::platform::CPUPlace, float>,
|
|
|
|
|
|
|
|
ops::BilinearTensorProductKernel<paddle::platform::CPUPlace, double>);
|
|
|
|
REGISTER_OP_CPU_KERNEL(
|
|
|
|
REGISTER_OP_CPU_KERNEL(
|
|
|
|
bilinear_tensor_product_grad,
|
|
|
|
bilinear_tensor_product_grad,
|
|
|
|
ops::BilinearTensorProductGradKernel<paddle::platform::CPUPlace, float>);
|
|
|
|
ops::BilinearTensorProductGradKernel<paddle::platform::CPUPlace, float>,
|
|
|
|
|
|
|
|
ops::BilinearTensorProductGradKernel<paddle::platform::CPUPlace, double>);
|
|
|
|