Caffe2 - C++ API
A deep learning, cross platform ML framework
sparse_to_dense_mask_op.cc
1 #include "caffe2/operators/sparse_to_dense_mask_op.h"
2 
3 namespace caffe2 {
4 namespace {
5 
6 REGISTER_CPU_OPERATOR(SparseToDenseMask, SparseToDenseMaskOp<CPUContext>);
7 REGISTER_CPU_OPERATOR(
8  SparseToDenseMaskGradient,
9  SparseToDenseMaskGradientOp<CPUContext>);
10 
11 OPERATOR_SCHEMA(SparseToDenseMask)
12  .NumInputs(3, 4)
13  .NumOutputs(1, 2)
14  .DisallowInputFillers() // TODO: enable the filler
15  .TensorInferenceFunction([](const OperatorDef& def,
16  const vector<TensorShape>& in) {
17  ArgumentHelper helper(def);
18  auto mask = helper.template GetRepeatedArgument<int64_t>("mask");
19  bool return_presence_mask = helper.template GetSingleArgument<bool>(
20  "return_presence_mask", false);
21  vector<TensorShape> out(1);
22 
23  if (in.size() == 4) {
24  out[0].add_dims(in[3].dims(0));
25  }
26  out[0].add_dims(mask.size());
27  for (const auto dim : in[2].dims()) {
28  out[0].add_dims(dim);
29  }
30  out[0].set_data_type(in[2].data_type());
31 
32  if (return_presence_mask) {
33  out.emplace_back();
34  if (in.size() == 4) {
35  out[1].add_dims(in[3].dims(0));
36  }
37  out[1].add_dims(mask.size());
38  out[1].set_data_type(TensorProto::BOOL);
39  }
40 
41  return out;
42  })
43  .SetDoc(R"DOC(
44 Convert sparse representations to dense with given indices.
45 
46 Transforms a sparse representation of map<id, value> represented as `indices`
47 vector and `values` tensor into a compacted tensor where the first dimension
48 corresponds to each id provided in mask argument. Missing values are filled with
49 the value of `default_value`. After running this op:
50 
51  output[j, :] = values[i] // where mask[j] == indices[i]
52  output[j, ...] = default_value // when mask[j] doesn't appear in indices
53 
54 If `lengths` is provided and not empty, and extra "batch" dimension is prepended
55 to the output.
56 
57 `values` and `default_value` can have additional matching dimensions, operation
58 is performed on the entire subtensor in thise case.
59 
60 For example, if `lengths` is supplied and `values` is 1-D vector of floats and
61 `default_value` is a float scalar, the output is going to be a float matrix
62 of size `len(lengths) X len(mask)`
63 )DOC")
64  .Arg(
65  "mask",
66  "list(int) argument with desired ids on the 'dense' output dimension")
67  .Arg(
68  "return_presence_mask",
69  "bool whether to return presence mask, false by default")
70  .Input(0, "indices", "1-D int32/int64 tensor of concatenated ids of data")
71  .Input(1, "values", "Data tensor, first dimension has to match `indices`")
72  .Input(
73  2,
74  "default_value",
75  "Default value for the output if the id is not present in `indices`. "
76  "Must have the same type as `values` and the same shape, but without "
77  "the first dimension")
78  .Input(
79  3,
80  "lengths",
81  "Optional lengths to represent a batch of `indices` and `values`.")
82  .Output(
83  0,
84  "output",
85  "Output tensor of the same type as `values` of shape `[len(lengths), "
86  "len(mask)] + shape(default_value)` (if `lengths` is not provided the "
87  "first dimension is omitted)")
88  .Output(
89  1,
90  "presence_mask",
91  "Bool tensor of shape `[len(lengths), len(mask)]` (if `lengths` is not "
92  "provided the first dimension is omitted). True when a value for given "
93  "id was present, false otherwise.");
94 
95 OPERATOR_SCHEMA(SparseToDenseMaskGradient)
96  .NumInputs(2, 3)
97  .NumOutputs(1)
98  .DisallowInputFillers() // TODO: enable the filler
99  .SetDoc(R"DOC(
100 The output is the gradient of the input value from SparseToDenseMask. The
101 gradient for default_value has not been implemented.
102 )DOC");
103 
104 class GetSparseToDenseMaskGradient : public GradientMakerBase {
105  using GradientMakerBase::GradientMakerBase;
106  vector<OperatorDef> GetGradientDefs() override {
107  vector<string> blob_names{I(0), GO(0)};
108 
109  // Add lengths blob if given
110  if (def_.input_size() == 4) {
111  blob_names.push_back(I(3));
112  }
113  return SingleGradientDef(
114  "SparseToDenseMaskGradient", "", blob_names, vector<string>{GI(1)});
115  }
116 };
117 REGISTER_GRADIENT(SparseToDenseMask, GetSparseToDenseMaskGradient);
118 } // namespace
119 } // namespace caffe2
A global dictionary that holds information about what Caffe2 modules have been loaded in the current ...
Definition: blob.h:13