Caffe2 - C++ API
A deep learning, cross platform ML framework
feature_maps_ops.cc
1 #include "feature_maps_ops.h"
2 
3 #include "caffe2/core/context.h"
4 
5 namespace caffe2 {
6 namespace {
7 
8 const std::string doc = R"DOC(
9  Single-feature representation:
10  - scalar features:
11  <feature full name> T
12  - list features:
13  <feature full name>.lengths int32
14  <feature full name>.values T
15  - map features:
16  <feature full name>.lengths int32
17  <feature full name>.keys K
18  <feature full name>.values V
19 
20  Missing values are set to zero, and value presence flag is set accordingly:
21  <feature full name>.presence bool
22 
23  Multi-feature representation:
24  - scalar features:
25  <feature type>.lengths int32
26  <feature type>.keys int64
27  <feature type>.values T
28  - list features:
29  <feature type>.lengths int32
30  <feature type>.keys int64
31  <feature type>.values.lengths int32
32  <feature type>.values.values T
33  - map features:
34  <feature type>.lengths int32
35  <feature type>.keys int64
36  <feature type>.values.lengths int32
37  <feature type>.values.keys K
38  <feature type>.values.values V
39 
40  You can read more about representing batches of lists and maps here:
41  https://our.intern.facebook.com/intern/dex/caffe2/sparse-operations/
42 )DOC";
43 
44 REGISTER_CPU_OPERATOR(
45  MergeSingleScalarFeatureTensors,
46  MergeSingleScalarFeatureTensorsOp<CPUContext>);
47 OPERATOR_SCHEMA(MergeSingleScalarFeatureTensors)
48  .SetDoc(
49  "Merge given single-feature tensors with scalar features into one "
50  "multi-feature tensor." +
51  doc)
52  .NumInputs([](int n) { return n >= 2 && n % 2 == 0; })
53  .NumOutputs(3)
54  .Input(0, "in1", "")
55  .Input(1, "in1_presence", ".presence")
56  .Output(0, "out_lengths", ".lengths")
57  .Output(1, "out_keys", ".keys")
58  .Output(2, "out_values", ".values")
59  .Arg("feature_ids", "feature ids");
60 
61 class GetMergeSingleScalarFeatureTensorsGradient : public GradientMakerBase {
62  using GradientMakerBase::GradientMakerBase;
63  vector<OperatorDef> GetGradientDefs() override {
64  vector<string> input_blob_names{};
65  vector<string> output_blob_names{};
66 
67  for (int inputIdx = 0; inputIdx < def_.input_size() / 2; ++inputIdx) {
68  input_blob_names.push_back(I(inputIdx * 2 + 1));
69  output_blob_names.push_back(GI(inputIdx * 2));
70  }
71  input_blob_names.push_back(GO(2));
72 
73  return SingleGradientDef(
74  "MergeSingleScalarFeatureTensorsGradient",
75  "", /* name */
76  input_blob_names,
77  output_blob_names);
78  }
79 };
80 
81 REGISTER_CPU_OPERATOR(
82  MergeSingleScalarFeatureTensorsGradient,
83  MergeSingleScalarFeatureTensorsGradientOp<CPUContext>);
84 OPERATOR_SCHEMA(MergeSingleScalarFeatureTensorsGradient)
85  .SetDoc(
86  "Explode multi-feature tensor of scalar features into one or more"
87  "single-feature tensors" +
88  doc)
89  .NumInputs([](int n) { return n >= 2; })
90  .NumOutputs([](int n) { return n >= 1; })
91  .Input(0, "in1_presence", ".presence")
92  .Input(1, ".values_grad", ".values_grad")
93  .Output(0, "in1_grad", "_grad of inputs");
94 REGISTER_GRADIENT(
95  MergeSingleScalarFeatureTensors,
96  GetMergeSingleScalarFeatureTensorsGradient);
97 
98 // ##########################################################
99 
100 REGISTER_CPU_OPERATOR(
101  MergeSingleListFeatureTensors,
102  MergeSingleListFeatureTensorsOp<CPUContext>);
103 OPERATOR_SCHEMA(MergeSingleListFeatureTensors)
104  .SetDoc(
105  "Merge given single-feature tensors with list features into one "
106  "multi-feature tensor." +
107  doc)
108  .NumInputs([](int n) { return n >= 3 && n % 3 == 0; })
109  .NumOutputs(4)
110  .Input(0, "in1_lengths", ".lengths")
111  .Input(1, "in1_values", ".values")
112  .Input(2, "in1_presence", ".presence")
113  .Output(0, "out_lengths", ".lengths")
114  .Output(1, "out_keys", ".keys")
115  .Output(2, "out_values_lengths", ".values.lengths")
116  .Output(3, "out_values_values", ".values.values")
117  .Arg("feature_ids", "feature ids");
118 
119 class GetMergeSingleListFeatureTensorsGradient : public GradientMakerBase {
120  using GradientMakerBase::GradientMakerBase;
121  vector<OperatorDef> GetGradientDefs() override {
122  vector<string> input_blob_names{};
123  vector<string> output_blob_names{};
124 
125  for (int inputIdx = 0; inputIdx < def_.input_size() / 3; ++inputIdx) {
126  input_blob_names.push_back(I(inputIdx * 3));
127  input_blob_names.push_back(I(inputIdx * 3 + 2));
128  output_blob_names.push_back(GI(inputIdx * 3 + 1));
129  }
130  input_blob_names.push_back(GO(3));
131 
132  return SingleGradientDef(
133  "MergeSingleListFeatureTensorsGradient",
134  "",
135  input_blob_names,
136  output_blob_names);
137  }
138 };
139 
140 REGISTER_CPU_OPERATOR(
141  MergeSingleListFeatureTensorsGradient,
142  MergeSingleListOrMapFeatureTensorsGradientOp<CPUContext>);
143 OPERATOR_SCHEMA(MergeSingleListFeatureTensorsGradient)
144  .SetDoc(
145  "Explode multi-feature tensors with list features into "
146  "single-feature tensors." +
147  doc)
148  .NumInputs([](int n) { return n >= 3 && n % 2 == 1; })
149  .NumOutputs([](int n) { return n >= 1; })
150  .Input(0, "in1_lengths", ".lengths")
151  .Input(1, "in1_presence", ".presence")
152  .Input(2, "out_values_values", ".values.values_grad")
153  .Output(0, "out1_values", ".values_grad");
154 REGISTER_GRADIENT(
155  MergeSingleListFeatureTensors,
156  GetMergeSingleListFeatureTensorsGradient);
157 
158 // ##########################################################
159 
160 REGISTER_CPU_OPERATOR(
161  MergeSingleMapFeatureTensors,
162  MergeSingleMapFeatureTensorsOp<CPUContext>);
163 OPERATOR_SCHEMA(MergeSingleMapFeatureTensors)
164  .SetDoc(
165  "Merge given single-feature tensors with map features into one "
166  "multi-feature tensor." +
167  doc)
168  .NumInputs([](int n) { return n >= 4 && n % 4 == 0; })
169  .NumOutputs(5)
170  .Input(0, "in1_lengths", ".lengths")
171  .Input(1, "in1_keys", ".keys")
172  .Input(2, "in1_values", ".values")
173  .Input(3, "in1_presence", ".presence")
174  .Output(0, "out_lengths", ".lengths")
175  .Output(1, "out_keys", ".keys")
176  .Output(2, "out_values_lengths", ".values.lengths")
177  .Output(3, "out_values_keys", ".values.keys")
178  .Output(4, "out_values_values", ".values.values")
179  .Arg("feature_ids", "feature ids");
180 
181 class GetMergeSingleMapFeatureTensorsGradient : public GradientMakerBase {
182  using GradientMakerBase::GradientMakerBase;
183  vector<OperatorDef> GetGradientDefs() override {
184  vector<string> input_blob_names{};
185  vector<string> output_blob_names{};
186 
187  for (int inputIdx = 0; inputIdx < def_.input_size() / 4; ++inputIdx) {
188  input_blob_names.push_back(I(inputIdx * 4));
189  input_blob_names.push_back(I(inputIdx * 4 + 3));
190  output_blob_names.push_back(GI(inputIdx * 4 + 2));
191  }
192  input_blob_names.push_back(GO(4));
193 
194  return SingleGradientDef(
195  "MergeSingleMapFeatureTensorsGradient",
196  "",
197  input_blob_names,
198  output_blob_names);
199  }
200 };
201 
202 REGISTER_CPU_OPERATOR(
203  MergeSingleMapFeatureTensorsGradient,
204  MergeSingleListOrMapFeatureTensorsGradientOp<CPUContext>);
205 OPERATOR_SCHEMA(MergeSingleMapFeatureTensorsGradient)
206  .SetDoc(
207  "Explode given multi-feature tensors with map features into "
208  "multiple single-feature tensor." +
209  doc)
210  .NumInputs([](int n) { return n >= 3 && n % 2 == 1; })
211  .NumOutputs([](int n) { return n >= 1; })
212  .Input(0, "in1_lengths", ".lengths")
213  .Input(1, "in1_presence", ".presence")
214  .Input(2, "out_values_values_grad", ".values.values_grad")
215  .Output(0, "in1_values_grad", ".values_grad");
216 REGISTER_GRADIENT(
217  MergeSingleMapFeatureTensors,
218  GetMergeSingleMapFeatureTensorsGradient);
219 
220 // ##########################################################
221 
222 REGISTER_CPU_OPERATOR(
223  MergeMultiScalarFeatureTensors,
224  MergeMultiScalarFeatureTensorsOp<CPUContext>);
225 OPERATOR_SCHEMA(MergeMultiScalarFeatureTensors)
226  .SetDoc(
227  "Merge given multi-feature tensors with scalar features into one." +
228  doc)
229  .NumInputs([](int n) { return n >= 3 && n % 3 == 0; })
230  .NumOutputs(3)
231  .Input(0, "in1_lengths", ".lengths")
232  .Input(1, "in1_keys", ".keys")
233  .Input(2, "in1_values", ".values")
234  .Output(0, "out_lengths", ".lengths")
235  .Output(1, "out_keys", ".keys")
236  .Output(2, "out_values", ".values");
237 
238 class GetMergeMultiScalarFeatureTensorsGradient : public GradientMakerBase {
239  using GradientMakerBase::GradientMakerBase;
240  vector<OperatorDef> GetGradientDefs() override {
241  vector<string> input_blob_names{};
242  vector<string> output_blob_names{};
243 
244  for (int inputIdx = 0; inputIdx < def_.input_size() / kNumTensorsPerInput;
245  ++inputIdx) {
246  input_blob_names.push_back(I(inputIdx * kNumTensorsPerInput));
247  output_blob_names.push_back(GI(inputIdx * kNumTensorsPerInput + 2));
248  }
249  input_blob_names.push_back(GO(2));
250 
251  return SingleGradientDef(
252  "MergeMultiScalarFeatureTensorsGradient",
253  "",
254  input_blob_names,
255  output_blob_names);
256  }
257 
258  private:
259  const int kNumTensorsPerInput = 3;
260 };
261 
262 REGISTER_CPU_OPERATOR(
263  MergeMultiScalarFeatureTensorsGradient,
264  MergeMultiScalarFeatureTensorsGradientOp<CPUContext>);
265 OPERATOR_SCHEMA(MergeMultiScalarFeatureTensorsGradient)
266  .SetDoc(
267  "Explode given multi-feature tensors with scalar features into many." +
268  doc)
269  .NumInputs([](int n) { return n >= 2; })
270  .NumOutputs([](int n) { return n >= 1; })
271  .Input(0, "in1_lengths", ".lengths")
272  .Input(1, "out_values_grad", ".values_grad")
273  .Output(0, "in1_values_grad", ".values_grad");
274 REGISTER_GRADIENT(
275  MergeMultiScalarFeatureTensors,
276  GetMergeMultiScalarFeatureTensorsGradient);
277 
278 // ##########################################################
279 
280 REGISTER_CPU_OPERATOR(
281  MergeMultiListFeatureTensors,
282  MergeMultiListFeatureTensorsOp<CPUContext>);
283 REGISTER_CPU_OPERATOR(
284  MergeMultiListFeatureTensorsGradient,
285  MergeMultiListOrMapFeatureTensorsGradientOp<CPUContext>);
286 OPERATOR_SCHEMA(MergeMultiListFeatureTensors)
287  .SetDoc(
288  "Merge given multi-feature tensors with list features into one." + doc)
289  .NumInputs([](int n) { return n >= 4 && n % 4 == 0; })
290  .NumOutputs(4)
291  .Input(0, "in1_lengths", ".lengths")
292  .Input(1, "in1_keys", ".keys")
293  .Input(2, "in1_values_lengths", ".values.lengths")
294  .Input(3, "in1_values_values", ".values.values")
295  .Output(0, "out_lengths", ".lengths")
296  .Output(1, "out_keys", ".keys")
297  .Output(2, "out_values_lengths", ".values.lengths")
298  .Output(3, "out_values_values", ".values.values");
299 OPERATOR_SCHEMA(MergeMultiListFeatureTensorsGradient)
300  .SetDoc(
301  "Explode given multi-feature tensors with list features "
302  "into many." +
303  doc)
304  .NumInputs([](int n) { return n >= 3 && n % 2 == 1; })
305  .NumOutputs([](int n) { return n >= 1; })
306  .Input(0, "in1_lengths", ".lengths")
307  .Input(1, "in1_values_lengths", ".values.lengths")
308  .Input(2, "out_values_values_grad", ".values.values_grad")
309  .Output(0, "in1_values_values_grad", ".values.values_grad");
310 
311 class GetMergeMultiListFeatureTensorsGradient : public GradientMakerBase {
312  using GradientMakerBase::GradientMakerBase;
313  vector<OperatorDef> GetGradientDefs() override {
314  vector<string> input_blob_names{};
315  vector<string> output_blob_names{};
316 
317  for (int inputIdx = 0; inputIdx < def_.input_size() / kNumTensorsPerInput;
318  ++inputIdx) {
319  input_blob_names.push_back(I(inputIdx * kNumTensorsPerInput));
320  input_blob_names.push_back(I(inputIdx * kNumTensorsPerInput + 2));
321  output_blob_names.push_back(GI(inputIdx * kNumTensorsPerInput + 3));
322  }
323  input_blob_names.push_back(GO(3));
324 
325  return SingleGradientDef(
326  "MergeMultiListFeatureTensorsGradient",
327  "",
328  input_blob_names,
329  output_blob_names);
330  }
331 
332  private:
333  const int kNumTensorsPerInput = 4;
334 };
335 
336 REGISTER_GRADIENT(
337  MergeMultiListFeatureTensors,
338  GetMergeMultiListFeatureTensorsGradient);
339 
340 // ##########################################################
341 
342 REGISTER_CPU_OPERATOR(
343  MergeMultiMapFeatureTensors,
344  MergeMultiMapFeatureTensorsOp<CPUContext>);
345 OPERATOR_SCHEMA(MergeMultiMapFeatureTensors)
346  .SetDoc(
347  "Merge given multi-feature tensors with map features into one." + doc)
348  .NumInputs([](int n) { return n >= 5 && n % 5 == 0; })
349  .NumOutputs(5)
350  .Input(0, "in1_lengths", ".lengths")
351  .Input(1, "in1_keys", ".keys")
352  .Input(2, "in1_values_lengths", ".values.lengths")
353  .Input(3, "in1_values_keys", ".values.keys")
354  .Input(4, "in1_values_values", ".values.values")
355  .Output(0, "out_lengths", ".lengths")
356  .Output(1, "out_keys", ".keys")
357  .Output(2, "out_values_lengths", ".values_lengths")
358  .Output(3, "out_values_keys", ".values.keys")
359  .Output(4, "out_values_values", ".values.values");
360 
361 class GetMergeMultiMapFeatureTensorsGradient : public GradientMakerBase {
362  using GradientMakerBase::GradientMakerBase;
363  vector<OperatorDef> GetGradientDefs() override {
364  vector<string> input_blob_names{};
365  vector<string> output_blob_names{};
366 
367  for (int inputIdx = 0; inputIdx < def_.input_size() / kNumTensorsPerInput;
368  ++inputIdx) {
369  input_blob_names.push_back(I(inputIdx * kNumTensorsPerInput));
370  input_blob_names.push_back(I(inputIdx * kNumTensorsPerInput + 2));
371  output_blob_names.push_back(GI(inputIdx * kNumTensorsPerInput + 4));
372  }
373  input_blob_names.push_back(GO(4));
374 
375  return SingleGradientDef(
376  "MergeMultiMapFeatureTensorsGradient",
377  "",
378  input_blob_names,
379  output_blob_names);
380  }
381 
382  private:
383  const int kNumTensorsPerInput = 5;
384 };
385 
386 REGISTER_CPU_OPERATOR(
387  MergeMultiMapFeatureTensorsGradient,
388  MergeMultiListOrMapFeatureTensorsGradientOp<CPUContext>);
389 OPERATOR_SCHEMA(MergeMultiMapFeatureTensorsGradient)
390  .SetDoc(
391  "Explode given multi-feature tensors with map features "
392  "into many." +
393  doc)
394  .NumInputs([](int n) { return n >= 3 && n % 2 == 1; })
395  .NumOutputs([](int n) { return n >= 1; })
396  .Input(0, "in1_lengths", ".lengths")
397  .Input(1, "in1_values_lengths", ".values.lengths")
398  .Input(2, "out_values_values_grad", ".values.values_grad")
399  .Output(0, "in1_values_values_grad", ".values.values_grad");
400 REGISTER_GRADIENT(
401  MergeMultiMapFeatureTensors,
402  GetMergeMultiMapFeatureTensorsGradient);
403 
404 } // namespace
405 } // namespace caffe2
A global dictionary that holds information about what Caffe2 modules have been loaded in the current ...
Definition: blob.h:13