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