提交 b10df8bc 编写于 作者: J JiabinYang

refine code and add none bias ut, test=develop

上级 81e14576
...@@ -118,7 +118,8 @@ class SelectedRows { ...@@ -118,7 +118,8 @@ class SelectedRows {
* *
* @return index of the key. * @return index of the key.
*/ */
int64_t AutoGrownIndex(int64_t key, bool auto_grown, bool is_test = false) { inline int64_t AutoGrownIndex(int64_t key, bool auto_grown,
bool is_test = false) {
if (is_test) { if (is_test) {
auto iter = id_to_index_.find(key); auto iter = id_to_index_.find(key);
if (iter == id_to_index_.end()) { if (iter == id_to_index_.end()) {
......
...@@ -13,8 +13,8 @@ See the License for the specific language governing permissions and ...@@ -13,8 +13,8 @@ See the License for the specific language governing permissions and
limitations under the License. */ limitations under the License. */
#include "paddle/fluid/operators/hierarchical_sigmoid_op.h" #include "paddle/fluid/operators/hierarchical_sigmoid_op.h"
#include <string>
#include <vector> #include <vector>
namespace paddle { namespace paddle {
namespace operators { namespace operators {
...@@ -109,7 +109,8 @@ class HierarchicalSigmoidOpMaker : public framework::OpProtoAndCheckerMaker { ...@@ -109,7 +109,8 @@ class HierarchicalSigmoidOpMaker : public framework::OpProtoAndCheckerMaker {
AddInput("Bias", AddInput("Bias",
"(LoDTensor, optional), The bias is a tensor with shape or " "(LoDTensor, optional), The bias is a tensor with shape or "
"[non_leaf_num, 1]" "[non_leaf_num, 1]"
"[num_classes - 1, 1]."); "[num_classes - 1, 1].")
.AsDispensable();
AddOutput( AddOutput(
"Out", "Out",
"(LoDTensor, required) The output of hierarchical sigmoid operator." "(LoDTensor, required) The output of hierarchical sigmoid operator."
...@@ -173,31 +174,42 @@ class HierarchicalSigmoidGradOpGradVarTypeInference ...@@ -173,31 +174,42 @@ class HierarchicalSigmoidGradOpGradVarTypeInference
public: public:
void operator()(const framework::OpDesc& op_desc, void operator()(const framework::OpDesc& op_desc,
framework::BlockDesc* block) const override { framework::BlockDesc* block) const override {
auto out_W_var_name = op_desc.Output(framework::GradVarName("W")).front(); auto w_grad_var_name = op_desc.Output(framework::GradVarName("W")).front();
auto out_Bias_var_name = auto bias_grad_var_name_vec =
op_desc.Output(framework::GradVarName("Bias")).front(); op_desc.Output(framework::GradVarName("Bias"));
std::string bias_grad_var_name;
bool hasBias = false;
if (bias_grad_var_name_vec.size()) {
hasBias = true;
bias_grad_var_name =
op_desc.Output(framework::GradVarName("Bias")).front();
}
auto attr = op_desc.GetAttr("is_sparse"); auto attr = op_desc.GetAttr("is_sparse");
bool is_sparse = boost::get<bool>(attr); bool is_sparse = boost::get<bool>(attr);
if (is_sparse) { if (is_sparse) {
VLOG(3) << "hierarchical_sigmoid_grad op " << framework::GradVarName("W") VLOG(30) << "hierarchical_sigmoid_grad op " << framework::GradVarName("W")
<< " is set to SelectedRows"; << " is set to SelectedRows";
block->Var(out_W_var_name) block->Var(w_grad_var_name)
->SetType(framework::proto::VarType::SELECTED_ROWS);
VLOG(3) << "hierarchical_sigmoid_grad op "
<< framework::GradVarName("Bias") << " is set to SelectedRows";
block->Var(out_Bias_var_name)
->SetType(framework::proto::VarType::SELECTED_ROWS); ->SetType(framework::proto::VarType::SELECTED_ROWS);
if (hasBias) {
VLOG(30) << "hierarchical_sigmoid_grad op "
<< framework::GradVarName("Bias") << " is set to SelectedRows";
block->Var(bias_grad_var_name)
->SetType(framework::proto::VarType::SELECTED_ROWS);
}
} else { } else {
VLOG(3) << "hierarchical_sigmoid_grad op " << framework::GradVarName("W") VLOG(30) << "hierarchical_sigmoid_grad op " << framework::GradVarName("W")
<< " is set to LoDTensor"; << " is set to LoDTensor";
block->Var(out_W_var_name) block->Var(w_grad_var_name)
->SetType(framework::proto::VarType::LOD_TENSOR);
VLOG(3) << "hierarchical_sigmoid_grad op "
<< framework::GradVarName("Bias") << " is set to LoDTensor";
block->Var(out_Bias_var_name)
->SetType(framework::proto::VarType::LOD_TENSOR); ->SetType(framework::proto::VarType::LOD_TENSOR);
if (hasBias) {
VLOG(30) << "hierarchical_sigmoid_grad op "
<< framework::GradVarName("Bias") << " is set to LoDTensor";
block->Var(bias_grad_var_name)
->SetType(framework::proto::VarType::LOD_TENSOR);
}
} }
block->Var(out_W_var_name)->SetDataType(block->Var("W")->GetDataType()); block->Var(w_grad_var_name)->SetDataType(block->Var("W")->GetDataType());
} }
}; };
......
...@@ -33,7 +33,6 @@ using platform::Transform; ...@@ -33,7 +33,6 @@ using platform::Transform;
std::vector<int64_t> cal_rows(const framework::LoDTensor& path) { std::vector<int64_t> cal_rows(const framework::LoDTensor& path) {
std::set<int64_t> tmp; std::set<int64_t> tmp;
std::vector<int64_t> rows; std::vector<int64_t> rows;
rows.clear();
for (size_t i = 0; i < static_cast<size_t>(path.dims()[0]); i++) { for (size_t i = 0; i < static_cast<size_t>(path.dims()[0]); i++) {
for (size_t j = 0; j < static_cast<size_t>(path.dims()[1]); j++) { for (size_t j = 0; j < static_cast<size_t>(path.dims()[1]); j++) {
int64_t temp = int64_t temp =
...@@ -63,8 +62,6 @@ class HierarchicalSigmoidOpKernel : public framework::OpKernel<T> { ...@@ -63,8 +62,6 @@ class HierarchicalSigmoidOpKernel : public framework::OpKernel<T> {
bool is_custom = false; bool is_custom = false;
if (path) { if (path) {
is_custom = true; is_custom = true;
} else {
is_custom = false;
} }
int64_t code_length = int64_t code_length =
path ? path->dims()[1] : math::FindLastSet(num_classes - 1); path ? path->dims()[1] : math::FindLastSet(num_classes - 1);
...@@ -96,7 +93,7 @@ class HierarchicalSigmoidOpKernel : public framework::OpKernel<T> { ...@@ -96,7 +93,7 @@ class HierarchicalSigmoidOpKernel : public framework::OpKernel<T> {
out->mutable_data<T>(ctx.GetPlace()); out->mutable_data<T>(ctx.GetPlace());
auto out_mat = framework::EigenVector<T>::Flatten(*out); auto out_mat = framework::EigenVector<T>::Flatten(*out);
if (bias) { if (bias) {
bit_code->Add(pre_out, *bias); bit_code->Add(*bias, pre_out);
} }
bit_code->Mul(pre_out, *w, *in); bit_code->Mul(pre_out, *w, *in);
// clip to [-40, 40] // clip to [-40, 40]
...@@ -145,8 +142,6 @@ class HierarchicalSigmoidGradOpKernel : public framework::OpKernel<T> { ...@@ -145,8 +142,6 @@ class HierarchicalSigmoidGradOpKernel : public framework::OpKernel<T> {
bool is_custom = false; bool is_custom = false;
if (path) { if (path) {
is_custom = true; is_custom = true;
} else {
is_custom = false;
} }
std::unique_ptr<math::MatrixBitCodeFunctor<T>> bit_code; std::unique_ptr<math::MatrixBitCodeFunctor<T>> bit_code;
...@@ -192,7 +187,7 @@ class HierarchicalSigmoidGradOpKernel : public framework::OpKernel<T> { ...@@ -192,7 +187,7 @@ class HierarchicalSigmoidGradOpKernel : public framework::OpKernel<T> {
auto* w_grad = auto* w_grad =
ctx.Output<framework::SelectedRows>(framework::GradVarName("W")); ctx.Output<framework::SelectedRows>(framework::GradVarName("W"));
w_grad->set_rows(real_rows); w_grad->set_rows(real_rows);
// build ids -> rows index map // Build a map of id -> row_index to speed up finding the index of one id
w_grad->SyncIndex(); w_grad->SyncIndex();
w_grad->set_height(w->dims()[0]); w_grad->set_height(w->dims()[0]);
auto* w_grad_value = w_grad->mutable_value(); auto* w_grad_value = w_grad->mutable_value();
......
...@@ -19,8 +19,8 @@ namespace operators { ...@@ -19,8 +19,8 @@ namespace operators {
namespace math { namespace math {
template <typename T> template <typename T>
void MatrixBitCodeFunctor<T>::Add(framework::LoDTensor* tmat, void MatrixBitCodeFunctor<T>::Add(const framework::LoDTensor& vec,
const framework::LoDTensor& vec) { framework::LoDTensor* tmat) {
size_t batch_size = tmat->dims()[0]; size_t batch_size = tmat->dims()[0];
size_t width = tmat->dims()[1]; size_t width = tmat->dims()[1];
for (size_t i = 0; i < batch_size; ++i) { for (size_t i = 0; i < batch_size; ++i) {
......
...@@ -234,7 +234,7 @@ class MatrixBitCodeFunctor { ...@@ -234,7 +234,7 @@ class MatrixBitCodeFunctor {
/* For j < code_length /* For j < code_length
tmat(i, j) += vec(0, index(i, j)) tmat(i, j) += vec(0, index(i, j))
*/ */
void Add(framework::LoDTensor* tmat, const framework::LoDTensor& vec); void Add(const framework::LoDTensor& vec, framework::LoDTensor* tmat);
/* For j < code_length /* For j < code_length
vec(0, index(i, j)) += tmat(i, j) vec(0, index(i, j)) += tmat(i, j)
......
...@@ -4535,12 +4535,12 @@ def nce(input, ...@@ -4535,12 +4535,12 @@ def nce(input,
def hsigmoid(input, def hsigmoid(input,
label, label,
num_classes=None, num_classes=None,
non_leaf_num=None,
ptable=None,
pcode=None,
param_attr=None, param_attr=None,
bias_attr=None, bias_attr=None,
name=None, name=None,
non_leaf_num=None,
ptable=None,
pcode=None,
is_costum=False, is_costum=False,
is_sparse=False): is_sparse=False):
""" """
...@@ -4583,7 +4583,8 @@ def hsigmoid(input, ...@@ -4583,7 +4583,8 @@ def hsigmoid(input,
will be named automatically. Default: None. will be named automatically. Default: None.
is_costum: (bool|False)using user defined binary tree instead of default complete binary tree, if costum is is_costum: (bool|False)using user defined binary tree instead of default complete binary tree, if costum is
set you need to set ptable/pcode/non_leaf_num, otherwise num_classes should be set set you need to set ptable/pcode/non_leaf_num, otherwise num_classes should be set
is_sparse: (bool|False)using sparse update instead of dense update is_sparse: (bool|False)using sparse update instead of dense update, if set, the gradient
of W and input will be sparse.
Returns: Returns:
Out: (LodTensor) The cost of hierarchical sigmoid operator. the shape is [N, 1] Out: (LodTensor) The cost of hierarchical sigmoid operator. the shape is [N, 1]
......
...@@ -110,12 +110,13 @@ def hsigmoidWithCustomTree(x, w, ptable, pcode, label, bias, num_classes): ...@@ -110,12 +110,13 @@ def hsigmoidWithCustomTree(x, w, ptable, pcode, label, bias, num_classes):
pre_output = np.zeros((batch_size, code_length)) pre_output = np.zeros((batch_size, code_length))
pre_sum = np.zeros((batch_size, 1)) pre_sum = np.zeros((batch_size, 1))
out = np.zeros((batch_size, 1)).astype("float32") out = np.zeros((batch_size, 1)).astype("float32")
for i in range(batch_size): if isinstance(bias, np.ndarray):
code_table = CodeTableWithCustomTree(ptable, pcode, i) for i in range(batch_size):
length = code_table.get_length() code_table = CodeTableWithCustomTree(ptable, pcode, i)
for j in range(length): length = code_table.get_length()
idx = code_table.cal_index(j) for j in range(length):
pre_output[i][j] += bias[idx][0] idx = code_table.cal_index(j)
pre_output[i][j] += bias[idx][0]
for i in range(batch_size): for i in range(batch_size):
code_table = CodeTableWithCustomTree(ptable, pcode, i) code_table = CodeTableWithCustomTree(ptable, pcode, i)
length = code_table.get_length() length = code_table.get_length()
...@@ -215,11 +216,11 @@ class TestHSigmoidOpWithSparseGrad(unittest.TestCase): ...@@ -215,11 +216,11 @@ class TestHSigmoidOpWithSparseGrad(unittest.TestCase):
cost = fluid.layers.hsigmoid( cost = fluid.layers.hsigmoid(
input=emb, input=emb,
label=label, label=label,
bias_attr=True,
non_leaf_num=3, non_leaf_num=3,
ptable=ptable, ptable=ptable,
pcode=pcode, pcode=pcode,
is_costum=True, is_costum=True,
bias_attr=True,
is_sparse=is_sparse) is_sparse=is_sparse)
avg_cost = fluid.layers.reduce_mean(cost) avg_cost = fluid.layers.reduce_mean(cost)
...@@ -299,5 +300,47 @@ class TestHSigmoidOpWithCostumTree(OpTest): ...@@ -299,5 +300,47 @@ class TestHSigmoidOpWithCostumTree(OpTest):
self.check_grad(['Bias', 'X', 'W'], ['Out'], no_grad_set=set('Label')) self.check_grad(['Bias', 'X', 'W'], ['Out'], no_grad_set=set('Label'))
class TestHSigmoidOpWithCostumTreeWithoutBias(OpTest):
def setUp(self):
self.op_type = "hierarchical_sigmoid"
num_classes = 6 #using 1,2,3,4,5,6 to build a huffman tree and select 1,2,5,6 as sample
feature_size = 8
batch_size = 4
x = np.random.random((batch_size, feature_size)).astype("float32") * 2
w = np.random.random(
(num_classes - 1, feature_size)).astype("float32") * 2
label = np.array([0, 1, 4, 5])
ptable = np.array(
[(0, 2, -1, -1, -1), (0, 1, 3, -1, -1), (0, 1, 4, -1, -1),
(0, 2, -1, -1,
-1)]) #np.array to store 1,2,5,6s' non-leaf path(root -> leaf)
pcode = np.array([(0, 0, -1, -1, -1), (1, 1, 1, -1, -1), (
1, 0, 0, -1, -1), (0, 1, -1, -1, -1)]) #np.array to store
# bias = np.random.random((num_classes - 1, 1)).astype("float32")
self.attrs = {'num_classes': num_classes, 'is_sparse': False}
self.inputs = {
'X': x,
'W': w,
'PTable': ptable,
'PCode': pcode,
'Label': label,
}
pre_output, out = hsigmoidWithCustomTree(
x=x,
w=w,
ptable=ptable,
pcode=pcode,
label=label,
bias=None,
num_classes=num_classes)
self.outputs = {'PreOut': pre_output, 'Out': out}
def test_check_output(self):
self.check_output()
def test_check_grad(self):
self.check_grad(['X', 'W'], ['Out'], no_grad_set=set('Label'))
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main()
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册