Caffe2 - C++ API
A deep learning, cross platform ML framework
boolean_unmask_ops.cc
1 
17 #include "caffe2/operators/boolean_unmask_ops.h"
18 #include "caffe2/core/operator.h"
19 #include "caffe2/core/tensor.h"
20 
21 namespace caffe2 {
22 
23 template <>
24 bool BooleanUnmaskOp<CPUContext>::RunOnDevice() {
25  int maskSize = Input(0).size();
26  int numMasks = InputSize() / 2;
27  auto& valueMeta = Input(1).meta();
28 
29  auto* valuesOut = Output(0);
30  valuesOut->Resize(maskSize);
31  auto* valuesOutPtr = (char*)valuesOut->raw_mutable_data(valueMeta);
32 
33  std::vector<int> nextValueIndices(numMasks, 0);
34  for (int maskOffset = 0; maskOffset < maskSize; ++maskOffset) {
35  bool maskFound = false;
36  for (int maskIndex = 0; maskIndex < numMasks; ++maskIndex) {
37  auto& mask = Input(maskIndex * 2);
38  CAFFE_ENFORCE_EQ(mask.ndim(), 1);
39  CAFFE_ENFORCE_EQ(mask.size(), maskSize);
40  const auto* maskPtr = mask.template data<bool>();
41 
42  auto& values = Input(maskIndex * 2 + 1);
43  CAFFE_ENFORCE_EQ(values.ndim(), 1);
44  const auto* valuesPtr = (char*)values.raw_data();
45 
46  if (maskPtr[maskOffset]) {
47  auto& valueIndex = nextValueIndices[maskIndex];
48  CAFFE_ENFORCE_LT(valueIndex, values.size());
49  auto* src = valuesPtr + (valueIndex++) * valueMeta.itemsize();
50  auto* dst = valuesOutPtr + maskOffset * valueMeta.itemsize();
51  std::copy(src, src + valueMeta.itemsize(), dst);
52  maskFound = true;
53  break;
54  }
55  }
56  CAFFE_ENFORCE(
57  maskFound, "All masks have False at position ", maskOffset, ".");
58  }
59  // check all indices match value length
60  for (int i = 0; i < numMasks; ++i) {
61  auto& values = Input(i * 2 + 1);
62  CAFFE_ENFORCE_EQ(
63  values.size(),
64  nextValueIndices[i],
65  "The number of true at mask ",
66  i,
67  " does not match the corresponding value size.");
68  }
69  return true;
70 }
71 
72 REGISTER_CPU_OPERATOR(BooleanUnmask, BooleanUnmaskOp<CPUContext>);
73 
74 OPERATOR_SCHEMA(BooleanUnmask)
75  .NumInputs([](int n) { return n > 0 && n % 2 == 0; })
76  .NumOutputs(1)
77  .SetDoc(R"DOC(
78 Given a series of mask and values, reconstruct values together according
79 to masks.
80 
81 A comprehensive example:
82  mask1 = True, False, True, False, False
83  values1 = 1.0, 3.0
84  mask2 = False, True, False, False, False
85  values2 = 2.0
86  mask3 = False, False, False, True, True
87  values3 = 4.0, 5.0
88 
89 Reconstruct by:
90  output = net.BooleanUnmask([mask1, values1, mask2, values2, mask3, values3], ["output"])
91 
92 We get:
93  output = 1.0, 2.0, 3.0, 4.0, 5.0
94 
95 Note that for all mask positions, there must be at least one True. If for a
96 field there are multiple True's, we will accept the first value. For example:
97 
98 
99 Example 1:
100  mask1 = True, False
101  values1 = 1.0
102  mask2 = False, False
103  values2 =
104 
105 This is not allowed:
106  output = net.BooleanUnmask([mask1, values1, mask2, values2], ["output"])
107 
108 Example 2:
109  mask1 = True, False
110  values1 = 1.0
111  mask2 = True, True
112  values2 = 2.0, 2.0
113 
114  output = net.BooleanUnmask([mask1, values1, mask2, values2], ["output"])
115 
116 We get:
117  output = 1.0, 2.0
118 )DOC")
119  .Output(0, "unmasked_data", "The final reconstructed unmasked data");
120 
121 NO_GRADIENT(BooleanUnmask)
122 }
Copyright (c) 2016-present, Facebook, Inc.