1 #include "caffe2/operators/boolean_unmask_ops.h" 2 #include "caffe2/core/operator.h" 3 #include "caffe2/core/tensor.h" 8 bool BooleanUnmaskOp<CPUContext>::RunOnDevice() {
9 int maskSize = Input(0).numel();
10 int numMasks = InputSize() / 2;
11 auto& valueMeta = Input(1).dtype();
13 auto* valuesOut = Output(0);
14 valuesOut->Resize(maskSize);
15 auto* valuesOutPtr = (
char*)valuesOut->raw_mutable_data(valueMeta);
17 std::vector<int> nextValueIndices(numMasks, 0);
18 for (
int maskOffset = 0; maskOffset < maskSize; ++maskOffset) {
19 bool maskFound =
false;
20 for (
int maskIndex = 0; maskIndex < numMasks; ++maskIndex) {
21 auto& mask = Input(maskIndex * 2);
22 CAFFE_ENFORCE_EQ(mask.dim(), 1);
23 CAFFE_ENFORCE_EQ(mask.numel(), maskSize);
24 const auto* maskPtr = mask.template data<bool>();
26 auto& values = Input(maskIndex * 2 + 1);
27 CAFFE_ENFORCE_EQ(values.dim(), 1);
28 const auto* valuesPtr = (
char*)values.raw_data();
30 if (maskPtr[maskOffset]) {
31 auto& valueIndex = nextValueIndices[maskIndex];
32 CAFFE_ENFORCE_LT(valueIndex, values.numel());
33 auto* src = valuesPtr + (valueIndex++) * valueMeta.itemsize();
34 auto* dst = valuesOutPtr + maskOffset * valueMeta.itemsize();
35 std::copy(src, src + valueMeta.itemsize(), dst);
41 maskFound,
"All masks have False at position ", maskOffset,
".");
44 for (
int i = 0; i < numMasks; ++i) {
45 auto& values = Input(i * 2 + 1);
49 "The number of true at mask ",
51 " does not match the corresponding value size.");
56 REGISTER_CPU_OPERATOR(BooleanUnmask, BooleanUnmaskOp<CPUContext>);
58 OPERATOR_SCHEMA(BooleanUnmask)
59 .NumInputs([](
int n) {
return n > 0 && n % 2 == 0; })
62 Given a series of masks and values, reconstruct values together according to masks. A comprehensive example: 64 mask1 = True, False, True, False, False 66 mask2 = False, True, False, False, False 68 mask3 = False, False, False, True, True 75 output = net.BooleanUnmask([mask1, values1, mask2, values2, mask3, values3], ["output"]) 76 output = 1.0, 2.0, 3.0, 4.0, 5.0 79 Note that for all mask positions, there must be at least one True. This is not allowed: 87 output = net.BooleanUnmask([mask1, values1, mask2, values2], ["output"]) 90 If there are multiple True values for a field, we accept the first value, and no longer expect a value for that location: 98 output = net.BooleanUnmask([mask1, values1, mask2, values2], ["output"]) 102 *** Note that we alternate `data` and `mask` inputs 105 - https://github.com/pytorch/pytorch/blob/master/caffe2/operators/boolean_unmask_ops.cc 109 <summary> <b>Example</b> </summary> 115 workspace.ResetWorkspace() 117 op = core.CreateOperator( 119 ["mask1", "data1", "mask2", "data2"], 123 workspace.FeedBlob("mask1", np.array([True,False,False,True,True,False])) 124 workspace.FeedBlob("data1", np.array([1,4,5])) 125 workspace.FeedBlob("mask2", np.array([False,True,True,False,False,True])) 126 workspace.FeedBlob("data2", np.array([2,3,6])) 128 print("data1:", workspace.FetchBlob("data1")) 129 print("mask1:", workspace.FetchBlob("mask1")) 130 print("data2:", workspace.FetchBlob("data2")) 131 print("mask2:", workspace.FetchBlob("mask2")) 132 workspace.RunOperatorOnce(op) 133 print("unmasked_data:", workspace.FetchBlob("unmasked_data")) 142 mask1: [ True False False True True False] 144 mask2: [False True True False False True] 145 unmasked_data: [1 2 3 4 5 6] 151 .Input(0,"data",
"(*Tensor*): 1D input tensor(s)")
152 .Input(1,
"mask",
"(*Tensor`<bool>`*): 1D boolean mask tensor(s)")
153 .Output(0,
"unmasked_data",
"(*Tensor*): 1D tensor of same type as `data` input that contains the unmasked input tensor");
155 NO_GRADIENT(BooleanUnmask)
A global dictionary that holds information about what Caffe2 modules have been loaded in the current ...