8template <
class Context>
9class BooleanMaskLengthsOp final :
public Operator<Context> {
12 template <
class...
Args>
13 explicit BooleanMaskLengthsOp(
Args&&...
args)
16 bool RunOnDevice()
override {
17 return DispatchHelper<TensorTypes<int32_t, int64_t>>
::call(
this,
Input(0));
21 bool DoRunWithType() {
27 const auto* lengthsPtr =
lengths.template data<T>();
28 const auto* maskPtr =
mask.template data<bool>();
32 auto* lengthsOut =
Output(0,
lengths.sizes(), at::dtype<T>());
33 auto* lengthsOutPtr = lengthsOut->template mutable_data<T>();
35 for (
int i = 0;
i <
lengths.numel(); ++
i) {
37 for (
int j = 0; j < lengthsPtr[
i]; ++j) {
42 lengthsOutPtr[
i] = lengthOut;
58 const auto* maskPtr =
mask.template data<bool>();
60 int outerSize =
mask.numel();
61 for (
int i = 0; i < outerSize; ++i) {
66 std::vector<int64_t> outShape;
67 outShape.push_back(numOutputs);
68 outShape.insert(outShape.end(),
data.sizes().begin() + 1,
data.sizes().end());
69 dataOut->Resize(outShape);
70 auto* outPtr = (
char*)dataOut->raw_mutable_data(
data.dtype());
73 if (OutputSize() == 2) {
74 auto* indicesOut =
Output(1, {numOutputs}, at::dtype<int64_t>());
75 out_vec = indicesOut->template mutable_data<int64_t>();
78 if (numOutputs == 0) {
81 const auto innerSize =
data.size_from_dim(1);
82 const auto innerSizeBytes = innerSize *
data.dtype().itemsize();
85 const auto* inPtr = (
char*)
data.raw_data();
90 if (lastStart != -1 && ((i >= outerSize) || !maskPtr[i])) {
91 const auto*
src = inPtr + lastStart * innerSizeBytes;
92 auto*
dst = outPtr + outStart * innerSizeBytes;
93 int numItems = i - lastStart;
103 if (lastStart == -1 && maskPtr[i]) {
106 if (maskPtr[i] && OutputSize() == 2) {
120 const int data_length_before_mask =
mask.size(0);
122 dX->Resize(data_length_before_mask);
125 T* dXdata =
dX->template mutable_data<T>();
126 const T* dYdata =
dY.template data<T>();
127 const bool* mask_data =
mask.template data<bool>();
131 for (
int i = 0; i < data_length_before_mask; i++) {
132 dXdata[i] = mask_data[i] ? dYdata[ind++] : 0;
148Given a 1D `data` tensor and a boolean `mask` tensor of the same shape, returns a `masked_data` tensor containing only the elements corresponding to positions where the `mask` is True, and a `masked_indices` tensor containing the indices of the True elements.
152- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/boolean_mask_ops.cc
156<summary> <b>Example</b> </summary>
162workspace.ResetWorkspace()
164op = core.CreateOperator(
167 ["masked_data", "masked_indices"]
170workspace.FeedBlob("data", np.array([1,2,3,4,5,6]))
171workspace.FeedBlob("mask", np.array([True,False,False,True,True,False]))
172print("data:", workspace.FetchBlob("data"))
173print("mask:", workspace.FetchBlob("mask"))
174workspace.RunOperatorOnce(op)
175print("masked_data:", workspace.FetchBlob("masked_data"))
176print("masked_indices:", workspace.FetchBlob("masked_indices"))
185mask: [ True False False True True False]
187masked_indices: [0 3 4]
194 .Input(0, "data",
"(*Tensor*): 1D input tensor")
198 "(*Tensor`<bool>`*): tensor of bools which determines the input elements that will be left in the `masked_data` output tensor; same shape as `data`")
202 "(*Tensor*): 1D tensor of same type as `data` input that contains the masked input tensor")
206 "(*Tensor`<int>`*): 1D tensor of indices of the True elements in the `mask` tensor");
212Given a tensor of int32 `lengths` tensor representing segment lengths and a `mask` (boolean) tensor, return the segment lengths of the corresponding segmented tensor after **BooleanMask** is applied.
214If `lengths` tensor is $[a_1, a_2, ..., a_n]$, then length of `mask` tensor must be $a_1 + a_2 + ... + a_n$.
218- https://github.com/pytorch/pytorch/blob/master/caffe2/operators/boolean_mask_ops.cc
222<summary> <b>Example</b> </summary>
228workspace.ResetWorkspace()
230op = core.CreateOperator(
231 "BooleanMaskLengths",
236workspace.FeedBlob("lengths", np.array([1,3,2], dtype=np.int32))
237workspace.FeedBlob("mask", np.array([False,True,True,False,True,True]))
238print("lengths:", workspace.FetchBlob("lengths"))
239print("mask:", workspace.FetchBlob("mask"))
240workspace.RunOperatorOnce(op)
241print("masked_lengths:", workspace.FetchBlob("masked_lengths"))
250mask: [False True True False True True]
251masked_lengths: [0 2 2]
261 "(*Tensor`<int>`*): input tensor containing segment lengths")
262 .Input(1,
"mask",
"(*Tensor`<bool>`*): A 1D bool tensor of values to keep.")
266 "(*Tensor`<int>`*): 1D tensor of same type as inputs that contains the sequence");
273 vector<OperatorDef> GetGradientDefs()
override {
274 return SingleGradientDef(
275 "BooleanMaskGradient",
277 vector<string>{I(1),
GO(0)},
278 vector<string>{GI(0)});
291template <
typename Functor>
306 for (
int i = 0; i <
B; ++i) {
307 for (
int j = 0; j <
N; ++j) {
308 for (
int k = 0; k <
M; ++k) {
312 auto val =
in[
N *
M * i +
M * j + k];
323 for (
int i = 0; i <
N; ++i) {
324 for (
int j = 0; j <
M; ++j) {
333template <
typename Functor>
342 for (
int i = 0; i <
N; ++i) {
343 for (
int j = 0; j <
M; ++j) {
344 for (
int k = 0; k <
D; ++k) {
345 auto val =
in[
M *
D * i +
D * j + k];
354class SequenceFunctor {
356 explicit SequenceFunctor(
const int* sl,
const size_t len)
358 bool operator()(
int i,
int j,
float ) {
370 explicit WindowFunctor(
const int*
c,
int r) :
c(
c),
r(
r) {}
371 bool operator()(
int i,
int j,
float ) {
372 return j >
c[i] +
r || j <
c[i] -
r;
382 bool operator()(
int i,
int j,
float ) {
389 bool operator()(
int i,
int j,
float ) {
394class UpperDiagFunctor {
396 bool operator()(
int i,
int j,
float ) {
401class LowerDiagFunctor {
403 bool operator()(
int i,
int j,
float ) {
412 return DispatchHelper<TensorTypes<float>>
::call(
this,
Input(0));
419 const Tensor* sequence_lengths =
nullptr;
420 const Tensor* window_centers =
nullptr;
422 if (mode_ ==
"sequence") {
423 sequence_lengths = &
Input(1);
424 }
else if (mode_ ==
"window") {
425 window_centers = &
Input(1);
433 int canonical_batch = -1;
434 if ((HasArgument(
"batch"))) {
435 canonical_batch =
input->canonical_axis_index(batch_);
439 if (canonical_batch >= 0) {
446 (canonical_batch >= 0
452 const int batch_dim =
453 (canonical_batch >= 0
454 ?
input->size_to_dim(canonical_batch) *
input->size(canonical_batch)
457 T fill_val = convert::To<float, T>(grad_ ? 0.0f : fill_val_);
458 if (mode_ ==
"sequence") {
460 sequence_lengths,
"Sequence length not provided for mode 'sequence'!");
461 if (HasArgument(
"repeat_from_axis")) {
462 const int canonical_repeat_from =
463 input->canonical_axis_index(repeat_from_);
464 const int repeated_dims =
input->size_from_dim(canonical_repeat_from);
465 const int masked_dims = right / repeated_dims;
472 sequence_lengths->
data<
int>(), sequence_lengths->numel()),
474 output->template mutable_data<T>());
482 sequence_lengths->
data<
int>(), sequence_lengths->numel()),
484 output->template mutable_data<T>());
486 }
else if (mode_ ==
"window") {
492 WindowFunctor(window_centers->
data<
int>(), radius_),
494 output->template mutable_data<T>());
495 }
else if (mode_ ==
"upper") {
503 output->template mutable_data<T>());
504 }
else if (mode_ ==
"lower") {
512 output->template mutable_data<T>());
513 }
else if (mode_ ==
"upperdiag") {
521 output->template mutable_data<T>());
522 }
else if (mode_ ==
"lowerdiag") {
530 output->template mutable_data<T>());
532 CAFFE_ENFORCE(
false,
"Unsupported mode for SequenceMaskOp!");
545Mask op designed for use in attention mechanisms for sequence modeling tasks.
546Supports batching: given batch_dim, collapses dims 0 through batch_dim into a
547single dimension, e.g. if tensor dims are [4,2,1,3,4] and batch_dim=2, first
548collapse tensor to [4*2*1,3,4], then mask each batch [i,:,:].
551Two current operating modes:
5541) Given a 2D input tensor and 1D tensor of sequence lengths, for each row i in
555the input tensor, set elements in that row to -inf if their column index
556j >= sequence_lengths[i]. This mode takes two inputs and argument mode =
5602) Triangular mask. Given row index i and column index j, set elements to -inf
561given the following conditions:
563 mode='upper', x_ij = -inf if j < i
564 mode='lower', x_ij = -inf if j > i
565 mode='upperdiag', x_ij = -inf if j <= i
566 mode='lowerdiag', x_ij = -inf if j >= i
568This mode takes one input.
5713) Window Mask. Given a 2D input tensor and 1D tensor of window centers,
572for each row i in the input tensor, set elements in that row to -inf
573if their column index j outside [center - radius, center + radius].
574This mode takes two inputs and argument mode = 'sequence'.
575Argument 'radius' should be provided.
577 .Input(0, "input",
"Tensor to apply masking to")
578 .Input(1,
"sequence_lengths",
"1D Tensor of sequence lengths for mode #1")
579 .Output(0,
"masked_tensor",
"Input tensor with masking applied")
582 "(string) Mode selection. Possible values: "
583 "'sequence', 'upper', 'lower', 'upperdiag', 'lowerdiag'")
586 "(int) Beginning axis of row elements. All dimensions to the left "
587 "will be treated as row indices and those to the right (inclusive) "
588 "will be treated as column indices in the 2D mask")
589 .Arg(
"grad",
"(bool) operate in gradient mode")
590 .Arg(
"radius",
"(int) radius of windows in window mode")
591 .Arg(
"batch",
"(int) batch dimension of tensor (optional)")
594 "(int) used when mask should be repeated for "
595 "one or more data dimensions (beginning at this axis). "
596 "(currently only supported for sequence mode without batch argument)");
598class GetSequenceMaskGradient :
public GradientMakerBase {
600 vector<OperatorDef> GetGradientDefs()
override {
601 vector<Argument>
args;
603 for (
const auto&
x : Def().
arg()) {
606 args.push_back(MakeArgument<bool>(
"grad",
true));
607 if (
def_.input_size() == 1) {
608 return SingleGradientDef(
611 vector<string>{
GO(0)},
612 vector<string>{GI(0)},
615 return SingleGradientDef(
618 vector<string>{
GO(0), I(1)},
619 vector<string>{GI(0)},
624 bool CopyArguments()
const override {
#define CAFFE_ENFORCE_LT(x, y,...)
Args({2<< 5}) -> Args({2<< 8}) ->Args({2<< 12}) ->Args({2<< 14})
USE_OPERATOR_CONTEXT_FUNCTIONS
void CopyItemsSameDevice(const caffe2::TypeMeta meta, size_t n, const void *src, void *dst)
bool RunOnDevice() override
GradientMakerBase(const OperatorDef &def, const vector< GradientWrapper > &g_output)
bool RunOnDevice() override
void forward(int64_t offset)
constexpr Symbol len(static_cast< unique_t >(_keys::aten_len))
Copyright (c) 2016-present, Facebook, Inc.
const auto canonical_axis
REGISTER_CPU_OPERATOR(ATen, ATenOp< CPUContext >)
void RepeatedMaskWithFunctor(int N, int M, int D, const float *in, Functor fn, float fill_val, float *out)
d int long tensor contains the length in each of the output N dim Tensor where dim boolean false where packed_tensor is true otherwise Padding number in the packed segments Use true to pad infinity
CAFFE_ENFORCE_EQ(in.size(), 1, "New shape must not be specified by the input blob and the " "argument `shape` at the same time.")
GRADIENT_OPERATOR_SCHEMA(FooGradient).NumInputs(1).NumOutputs(1)
NO_GRADIENT(SparseLengthsSumFused4BitRowwiseFakeFP16NNPI)
the other dimension is proportionally scaled Defaults to Whether or not to mirror the image Defaults to Vector of means per color Standard deviation by which to normalize color channels Defaults to Bounding box coordinate Defaults Bounding box coordinate Defaults Bounding box coordinate Defaults Bounding box coordinate Defaults if the input is in Caffe format Defaults to Number of CPU decode transform threads Defaults to Name of the Type of The sizes of any outputs besides the data and shortest side desired for image resize Defaults to[-1, -1] or no random resize desired data
REGISTER_CPU_GRADIENT_OPERATOR(BooleanMaskGradient, BooleanMaskOpGradient< CPUContext >)
we first initialize the output tensor to all and then do accumulation Any further calls to the The input tensor that has to be accumulated to the output tensor If the output size is not the same as input size
SparseLengths8BitsRowwiseOp< CPUContext, 0, 1 >::LENGTHS uint8 tensor obtained with Vector with the same sum of elements as the first dimension of DATA Input(3, "scale_bias", "Matrix of floats, each row r_i of which stores a pair " "s_i, b_i -- scale and bias for i-th row") .Output(0
Maximum number of candidates to carry over to next activation step float Tensor sized[max_activation_length, batch_size, alphabet_size] of network optional int vector containing sequence lengths
const vector< TensorShape > & in
true SparseLengthsFused4BitRowwiseFakeFP16Op< CPUContext, true >::WEIGHTS uint8 tensor obtained with Vector with the same sum of elements as the first dimension of DATA output
Unscaled log probabilities Optional blob to be used to weight the samples for the loss With spatial weighting is by x
const ArgumentHelper args(def)
we first initialize the output tensor to all and then do accumulation Any further calls to the input
See RoIPoolF Gradient of forward dX
required base learning rate default used only for inv policy type default sampling rate on iterations default True in alter policy int64_t
REGISTER_GRADIENT(CTC, GetCTCGradient)
SparseLengths8BitsRowwiseOp< CPUContext, 1, 1 >::LENGTHS uint8 tensor obtained with Integer vector containing indices of the first dimension of DATA for the slices that are being aggregated Matrix of each row r_i of which stores a pair b_i scale and bias for i th row Output(0, "output", "output")
void MaskWithFunctor(int N, int M, int B, const float *in, Functor fn, float fill_val, float *out)
CAFFE_ENFORCE(dims.front() >=0, "Dimension ids must be non-negative.")
static void accumulate(std::vector< Variable > &buffer, const size_t pos, Variable &&var)