Caffe2 - C++ API
A deep learning, cross platform ML framework
pack_rnn_sequence_op.cc
1 
17 #include "caffe2/operators/pack_rnn_sequence_op.h"
18 
19 namespace caffe2 {
20 namespace {
21 
22 REGISTER_CPU_OPERATOR(PackRNNSequence, PackRNNSequenceOpBase<CPUContext, true>);
23 REGISTER_CPU_OPERATOR(
24  UnpackRNNSequence,
25  PackRNNSequenceOpBase<CPUContext, false>);
26 
27 OPERATOR_SCHEMA(PackRNNSequence)
28  .NumInputs(2)
29  .NumOutputs(1)
30  .SetDoc(R"DOC(
31 Pack values based on the length blob. Each number from length blob represents
32 the corresponding values that need to be packed. The dimension for each pack
33 is the same as the maximum number from the length blob (padding with zero is
34 implemented for smaller length value). The overall output dimension is:
35 T * N * D, where T is the max number of lengths, N is the size of lengths,
36 and D is the dimension of each feature value. The following example shows
37 the input and output of this operator:
38 
39 
40 Given:
41  values = [v1, v2, v3, v4, v5, v6, v7, v8]
42  lengths = [2, 3, 1, 2];
43 
44 
45 Output:
46  output = [
47  [v1, v3, v6, v7],
48  [v2, v4, 0, v8],
49  [0, v5, 0, 0 ],
50  ]
51 
52 
53 One application for this operator is the transfer data into the format that is
54 used for RNN models. Note that the gradient operator of PackRNNSequence is
55 UnpackRNNSequence.
56 )DOC")
57  .Input(0, "values", "Data tensor, contains a sequence of features")
58  .Input(1, "lengths", "lengths with each number representing the pack size.")
59  .Output(0, "output", "Output tensor after packing");
60 
61 OPERATOR_SCHEMA(UnpackRNNSequence)
62  .NumInputs(2)
63  .NumOutputs(1)
64  .SetDoc(R"DOC(
65 This is the reverse operator for PackRNNSequence. It maps the packed values
66 back to sequence values based on the length blob. Each number from length blob
67 represents the corresponding values that has been grouped. The dimension
68 for each pack is the same as the maximum number from the length blob (padding
69 with zero was implemented for smaller length value). The overall output
70 dimension is: M * D, where M is the sum of lengths, and D is the dimension of
71 each feature value. The following example shows the input and output of
72 this operator:
73 
74 
75 Given:
76  values = [
77  [v1, v3, v6, v7],
78  [v2, v4, 0, v8],
79  [0, v5, 0, 0 ],
80  ]
81  lengths = [2, 3, 1, 2]
82 
83 
84 Output:
85  output = [v1, v2, v3, v4, v5, v6, v7, v8];
86 
87 
88 One application for this operator is the transfer data from the format of RNN
89 back to sequence values. Note that the gradient operator of
90 UnpackRNNSequence is PackRNNSequence.
91 )DOC")
92  .Input(0, "values", "Data tensor, contains the packed features")
93  .Input(1, "lengths", "lengths with each number representing the pack size.")
94  .Output(0, "output", "Output tensor before packing");
95 
96 class GetPackRNNSequenceGradient : public GradientMakerBase {
97  using GradientMakerBase::GradientMakerBase;
98  vector<OperatorDef> GetGradientDefs() override {
99  CAFFE_ENFORCE_EQ(def_.input_size(), 2);
100  return SingleGradientDef(
101  "UnpackRNNSequence",
102  "",
103  vector<string>{GO(0), I(1)},
104  vector<string>{GI(0)});
105  }
106 };
107 
108 class GetUnpackRNNSequenceGradient : public GradientMakerBase {
109  using GradientMakerBase::GradientMakerBase;
110  vector<OperatorDef> GetGradientDefs() override {
111  CAFFE_ENFORCE_EQ(def_.input_size(), 2);
112  return SingleGradientDef(
113  "PackRNNSequence",
114  "",
115  vector<string>{GO(0), I(1)},
116  vector<string>{GI(0)});
117  }
118 };
119 
120 REGISTER_GRADIENT(PackRNNSequence, GetPackRNNSequenceGradient);
121 REGISTER_GRADIENT(UnpackRNNSequence, GetUnpackRNNSequenceGradient);
122 } // namespace
123 } // namespace caffe2
Copyright (c) 2016-present, Facebook, Inc.