Skip to content

Commit 014e50c

Browse files
committed
test=develop
1 parent ba9ff50 commit 014e50c

File tree

7 files changed

+349
-171
lines changed

7 files changed

+349
-171
lines changed

paddle/fluid/framework/mixed_vector.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -533,6 +533,12 @@ class CPUVector : public std::vector<T, std::allocator<T>> {
533533
return os;
534534
}
535535

536+
size_t size() const noexcept {
537+
size_t size =
538+
static_cast<size_t>(std::vector<T, std::allocator<T>>::size());
539+
return size;
540+
}
541+
536542
T &operator[](size_t id) { return this->at(id); }
537543

538544
const T &operator[](size_t id) const { return this->at(id); }

paddle/fluid/operators/hierarchical_sigmoid_op.cc

Lines changed: 51 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -70,13 +70,14 @@ class HierarchicalSigmoidOp : public framework::OperatorWithKernel {
7070
const int64_t batch_size = ctx->GetInputDim("X")[0];
7171
std::vector<int64_t> output_shape({batch_size, 1});
7272
ctx->SetOutputDim("Out", framework::make_ddim(output_shape));
73+
ctx->ShareLoD("X", /*->*/ "Out");
7374
}
7475

7576
protected:
7677
framework::OpKernelType GetExpectedKernelType(
7778
const framework::ExecutionContext& ctx) const override {
7879
return framework::OpKernelType(
79-
framework::ToDataType(ctx.Input<framework::Tensor>("X")->type()),
80+
framework::ToDataType(ctx.Input<framework::LoDTensor>("X")->type()),
8081
ctx.GetPlace());
8182
}
8283
};
@@ -86,32 +87,34 @@ class HierarchicalSigmoidOpMaker : public framework::OpProtoAndCheckerMaker {
8687
public:
8788
void Make() override {
8889
AddInput("X",
89-
"(Tensor, required) The input tensor with shape [N, D], "
90+
"(LoDTensor, required) The input tensor with shape [N, D], "
9091
"where N is the size of mini-batch, and D is the feature size.");
9192
AddInput("W",
92-
"(Tensor, required), The parameters of hierarchical "
93+
"(LoDTensor, required), The parameters of hierarchical "
9394
"sigmoid operator, each of them is a 2-D tensor, the shape is"
9495
"[K, D]. Which K is the num of non-leaf node in Path Tree");
9596
AddInput("Label",
96-
"(Tensor, required), The labels of training data. It's a"
97+
"(LoDTensor, required), The labels of training data. It's a"
9798
"tensor with shape [N, 1].");
9899
AddInput("PTable",
99-
"(Tensor, optional), The Path Table from root to current word"
100+
"(LoDTensor, optional), The Path Table from root to current word"
100101
"it should have shape like [N, L], L is the length of the Path")
101102
.AsDispensable();
102-
AddInput("PCode",
103-
"(Tensor, optional), The Code on each Node of the Path from root "
104-
"to current word"
105-
"it should have shape like [N, L], L is the length of the Path")
103+
AddInput(
104+
"PCode",
105+
"(LoDTensor, optional), The Code on each Node of the Path from root "
106+
"to current word"
107+
"it should have shape like [N, L], L is the length of the Path")
106108
.AsDispensable();
107109
AddInput("Bias",
108-
"(Tensor, optional), The bias is a tensor with shape"
110+
"(LoDTensor, optional), The bias is a tensor with shape"
109111
"[1, num_classes - 1].");
110-
AddOutput("Out",
111-
"(Tensor, required) The output of hierarchical sigmoid operator."
112-
"The shape is [N, 1].");
112+
AddOutput(
113+
"Out",
114+
"(LoDTensor, required) The output of hierarchical sigmoid operator."
115+
"The shape is [N, 1].");
113116
AddOutput("PreOut",
114-
"(Tensor, required) A intermedia 2-D tensor with shape "
117+
"(LoDTensor, required) A intermedia 2-D tensor with shape "
115118
"[batch_size, code_length], where code_length represents the "
116119
"maximum path length from root to leaf nodes.")
117120
.AsIntermediate();
@@ -124,6 +127,10 @@ belonging to the right branch. This idea is from
124127
"F. Morin, Y. Bengio (AISTATS 05):
125128
Hierarchical Probabilistic Neural Network Language Model."
126129
)DOC");
130+
AddAttr<bool>("is_sparse",
131+
"(boolean, default false) "
132+
"Sparse update.")
133+
.SetDefault(false);
127134
}
128135
};
129136

@@ -133,6 +140,8 @@ class HierarchicalSigmoidGradOp : public framework::OperatorWithKernel {
133140
void InferShape(framework::InferShapeContext* ctx) const override {
134141
PADDLE_ENFORCE(ctx->HasInput("W"), "Input(W) should not be null.");
135142
PADDLE_ENFORCE(ctx->HasInput("Label"), "Input(Label) should not be null.");
143+
PADDLE_ENFORCE(ctx->HasInput(framework::GradVarName("Out")),
144+
"Input(Out@Grad) should not be null");
136145
PADDLE_ENFORCE(ctx->HasInput("PreOut"),
137146
"Input(Preout) should not be null.");
138147
PADDLE_ENFORCE(ctx->HasOutput(framework::GradVarName("W")),
@@ -142,27 +151,52 @@ class HierarchicalSigmoidGradOp : public framework::OperatorWithKernel {
142151
ctx->SetOutputDim(framework::GradVarName("Bias"),
143152
ctx->GetInputDim("Bias"));
144153
}
145-
ctx->SetOutputDim(framework::GradVarName("W"), ctx->GetInputDim("W"));
154+
if (!ctx->Attrs().Get<bool>("is_sparse")) {
155+
ctx->SetOutputDim(framework::GradVarName("W"), ctx->GetInputDim("W"));
156+
}
146157
ctx->SetOutputDim(framework::GradVarName("X"), ctx->GetInputDim("X"));
147158
}
148159

149160
protected:
150161
framework::OpKernelType GetExpectedKernelType(
151162
const framework::ExecutionContext& ctx) const override {
152163
return framework::OpKernelType(
153-
framework::ToDataType(ctx.Input<framework::Tensor>("X")->type()),
164+
framework::ToDataType(ctx.Input<framework::LoDTensor>("X")->type()),
154165
ctx.GetPlace());
155166
}
156167
};
157168

169+
class HierarchicalSigmoidGradOpGradVarTypeInference
170+
: public framework::VarTypeInference {
171+
public:
172+
void operator()(const framework::OpDesc& op_desc,
173+
framework::BlockDesc* block) const override {
174+
auto out_var_name = op_desc.Output(framework::GradVarName("W")).front();
175+
auto attr = op_desc.GetAttr("is_sparse");
176+
bool is_sparse = boost::get<bool>(attr);
177+
if (is_sparse) {
178+
VLOG(3) << "hierarchical_sigmoid_grad op " << framework::GradVarName("W")
179+
<< " is set to SelectedRows";
180+
block->Var(out_var_name)
181+
->SetType(framework::proto::VarType::SELECTED_ROWS);
182+
} else {
183+
VLOG(3) << "hierarchical_sigmoid_grad op " << framework::GradVarName("W")
184+
<< " is set to LoDTensor";
185+
block->Var(out_var_name)->SetType(framework::proto::VarType::LOD_TENSOR);
186+
}
187+
block->Var(out_var_name)->SetDataType(block->Var("W")->GetDataType());
188+
}
189+
};
190+
158191
} // namespace operators
159192
} // namespace paddle
160193

161194
namespace ops = paddle::operators;
162195
REGISTER_OPERATOR(hierarchical_sigmoid, ops::HierarchicalSigmoidOp,
163196
ops::HierarchicalSigmoidOpMaker<int>,
164197
paddle::framework::DefaultGradOpDescMaker<true>);
165-
REGISTER_OPERATOR(hierarchical_sigmoid_grad, ops::HierarchicalSigmoidGradOp);
198+
REGISTER_OPERATOR(hierarchical_sigmoid_grad, ops::HierarchicalSigmoidGradOp,
199+
ops::HierarchicalSigmoidGradOpGradVarTypeInference);
166200
REGISTER_OP_CPU_KERNEL(
167201
hierarchical_sigmoid,
168202
ops::HierarchicalSigmoidOpKernel<paddle::platform::CPUDeviceContext, float>,

paddle/fluid/operators/hierarchical_sigmoid_op.h

Lines changed: 66 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,10 @@ limitations under the License. */
1414

1515
#pragma once
1616
#include <iostream>
17+
#include <set>
1718
#include <vector>
19+
#include "paddle/fluid/framework/mixed_vector.h"
1820
#include "paddle/fluid/framework/op_registry.h"
19-
#include "paddle/fluid/framework/selected_rows.h"
2021
#include "paddle/fluid/operators/clip_op.h"
2122
#include "paddle/fluid/operators/math/math_function.h"
2223
#include "paddle/fluid/operators/math/matrix_bit_code.h"
@@ -29,18 +30,37 @@ template <typename T, int MajorType = Eigen::RowMajor,
2930
using EigenMatrix = framework::EigenMatrix<T, MajorType, IndexType>;
3031
using platform::Transform;
3132

33+
std::vector<int64_t> cal_rows(const framework::LoDTensor* path) {
34+
std::set<int64_t> tmp;
35+
std::vector<int64_t> rows;
36+
rows.clear();
37+
for (size_t i = 0; i < static_cast<size_t>(path->dims()[0]); i++) {
38+
for (size_t j = 0; j < static_cast<size_t>(path->dims()[1]); j++) {
39+
int64_t temp =
40+
path->data<int64_t>()[i * static_cast<size_t>(path->dims()[1]) + j];
41+
if (temp >= 0) {
42+
tmp.insert(temp);
43+
}
44+
}
45+
}
46+
for (std::set<int64_t>::iterator it = tmp.begin(); it != tmp.end(); ++it) {
47+
rows.push_back(*it);
48+
}
49+
return rows;
50+
}
51+
3252
template <typename DeviceContext, typename T>
3353
class HierarchicalSigmoidOpKernel : public framework::OpKernel<T> {
3454
public:
3555
void Compute(const framework::ExecutionContext& ctx) const override {
36-
auto* in = ctx.Input<framework::Tensor>("X");
37-
auto* w = ctx.Input<framework::Tensor>("W");
38-
auto* path = ctx.Input<framework::Tensor>("PTable");
39-
auto* code = ctx.Input<framework::Tensor>("PCode");
40-
auto* label = ctx.Input<framework::Tensor>("Label");
41-
auto* bias = ctx.Input<framework::Tensor>("Bias");
42-
auto* out = ctx.Output<framework::Tensor>("Out");
43-
auto* pre_out = ctx.Output<framework::Tensor>("PreOut");
56+
auto* in = ctx.Input<framework::LoDTensor>("X");
57+
auto* w = ctx.Input<framework::LoDTensor>("W");
58+
auto* path = ctx.Input<framework::LoDTensor>("PTable");
59+
auto* code = ctx.Input<framework::LoDTensor>("PCode");
60+
auto* label = ctx.Input<framework::LoDTensor>("Label");
61+
auto* bias = ctx.Input<framework::LoDTensor>("Bias");
62+
auto* out = ctx.Output<framework::LoDTensor>("Out");
63+
auto* pre_out = ctx.Output<framework::LoDTensor>("PreOut");
4464
size_t num_classes = static_cast<size_t>(ctx.Attr<int>("num_classes"));
4565
bool is_custom = false;
4666
if (path) {
@@ -51,7 +71,7 @@ class HierarchicalSigmoidOpKernel : public framework::OpKernel<T> {
5171
int64_t code_length =
5272
path ? path->dims()[1] : math::FindLastSet(num_classes - 1);
5373
int64_t batch_size = in->dims()[0];
54-
framework::Tensor sum;
74+
framework::LoDTensor sum;
5575
auto& dev_ctx = ctx.template device_context<DeviceContext>();
5676
auto* pre_out_data = pre_out->mutable_data<T>(
5777
framework::make_ddim({batch_size, code_length}), ctx.GetPlace());
@@ -102,27 +122,26 @@ template <typename DeviceContext, typename T>
102122
class HierarchicalSigmoidGradOpKernel : public framework::OpKernel<T> {
103123
public:
104124
void Compute(const framework::ExecutionContext& ctx) const override {
105-
auto* in = ctx.Input<framework::Tensor>("X");
106-
auto* w = ctx.Input<framework::Tensor>("W");
107-
auto* path = ctx.Input<framework::Tensor>("PTable");
108-
auto* code = ctx.Input<framework::Tensor>("PCode");
109-
auto* in_grad = ctx.Output<framework::Tensor>(framework::GradVarName("X"));
110-
auto* w_grad = ctx.Output<framework::Tensor>(framework::GradVarName("W"));
125+
auto* in = ctx.Input<framework::LoDTensor>("X");
126+
auto* w = ctx.Input<framework::LoDTensor>("W");
127+
auto* path = ctx.Input<framework::LoDTensor>("PTable");
128+
auto* code = ctx.Input<framework::LoDTensor>("PCode");
129+
auto* in_grad =
130+
ctx.Output<framework::LoDTensor>(framework::GradVarName("X"));
131+
bool is_sparse = ctx.Attr<bool>("is_sparse");
132+
auto& dev_ctx = ctx.template device_context<DeviceContext>();
133+
math::SetConstant<DeviceContext, T> zero;
111134
auto* bias_grad =
112-
ctx.Output<framework::Tensor>(framework::GradVarName("Bias"));
113-
auto* label = ctx.Input<framework::Tensor>("Label");
114-
auto* pre_out = ctx.Input<framework::Tensor>("PreOut");
135+
ctx.Output<framework::LoDTensor>(framework::GradVarName("Bias"));
136+
auto* label = ctx.Input<framework::LoDTensor>("Label");
137+
auto* pre_out = ctx.Input<framework::LoDTensor>("PreOut");
115138
auto* out_grad =
116-
ctx.Input<framework::Tensor>(framework::GradVarName("Out"));
117-
framework::Tensor pre_out_grad;
139+
ctx.Input<framework::LoDTensor>(framework::GradVarName("Out"));
140+
framework::LoDTensor pre_out_grad;
118141

119142
pre_out_grad.mutable_data<T>(pre_out->dims(), ctx.GetPlace());
120143
in_grad->mutable_data<T>(ctx.GetPlace());
121-
w_grad->mutable_data<T>(ctx.GetPlace());
122-
auto& dev_ctx = ctx.template device_context<DeviceContext>();
123-
math::SetConstant<DeviceContext, T> zero;
124144
zero(dev_ctx, in_grad, static_cast<T>(0.0));
125-
zero(dev_ctx, w_grad, static_cast<T>(0.0));
126145

127146
size_t num_classes = static_cast<size_t>(ctx.Attr<int>("num_classes"));
128147

@@ -162,7 +181,28 @@ class HierarchicalSigmoidGradOpKernel : public framework::OpKernel<T> {
162181
zero(dev_ctx, bias_grad, static_cast<T>(0.0));
163182
bit_code->AddGrad(pre_out_grad, bias_grad);
164183
}
165-
bit_code->MulGradWeight(pre_out_grad, w_grad, *in);
184+
if (!is_sparse) {
185+
auto* w_grad =
186+
ctx.Output<framework::LoDTensor>(framework::GradVarName("W"));
187+
w_grad->mutable_data<T>(ctx.GetPlace());
188+
zero(dev_ctx, w_grad, static_cast<T>(0.0));
189+
bit_code->MulGradWeight(pre_out_grad, w_grad, *in);
190+
} else {
191+
framework::Vector<int64_t> real_rows = cal_rows(path);
192+
auto* w_grad =
193+
ctx.Output<framework::SelectedRows>(framework::GradVarName("W"));
194+
195+
w_grad->set_rows(real_rows);
196+
// build ids -> rows index map
197+
w_grad->SyncIndex();
198+
auto* w_grad_value = w_grad->mutable_value();
199+
framework::DDim temp_dim(w->dims());
200+
set(temp_dim, 0, real_rows.size());
201+
202+
w_grad_value->mutable_data<T>(temp_dim, ctx.GetPlace());
203+
zero(dev_ctx, w_grad_value, static_cast<T>(0.0));
204+
bit_code->MulGradWeight(pre_out_grad, w_grad, *in);
205+
}
166206
bit_code->MulGradError(pre_out_grad, *w, in_grad);
167207
}
168208
};

0 commit comments

Comments
 (0)