1 #include "caffe2/operators/expand_squeeze_dims_op.h" 4 REGISTER_CPU_OPERATOR(ExpandDims, ExpandDimsOp<CPUContext>);
5 REGISTER_CPU_OPERATOR(Squeeze, SqueezeOp<CPUContext>);
7 OPERATOR_SCHEMA(ExpandDims)
10 .AllowInplace({{0, 0}})
11 .TensorInferenceFunction([](
const OperatorDef& def,
12 const vector<TensorShape>& in) {
13 ArgumentHelper helper(def);
14 auto dims = helper.template GetRepeatedArgument<int>(
"dims");
15 auto originalSize = dims.size();
16 CAFFE_ENFORCE(originalSize > 0,
"Parameter `dims` must be provided.");
18 std::sort(dims.begin(), dims.end());
19 dims.erase(std::unique(dims.begin(), dims.end()), dims.end());
20 if (dims.size() < originalSize) {
21 LOG(WARNING) <<
"Parameter `dims` has repeated dimensions.";
24 CAFFE_ENFORCE(dims.front() >= 0,
"Dimension ids must be non-negative.");
26 in[0].dims_size() + dims.size(),
28 "Input needs at least ",
29 (1 + dims.back() - dims.size()),
30 " dimensions given `dims`.");
32 vector<TensorShape> out(1);
36 for (
const auto new_dim : dims) {
37 for (
int i = cur_pos; i < new_dim; i++) {
38 out[0].add_dims(in[0].dims(idx++));
41 cur_pos = new_dim + 1;
43 for (; idx < in[0].dims_size(); idx++) {
44 out[0].add_dims(in[0].dims(idx));
46 out[0].set_data_type(in[0].data_type());
50 The *ExpandDims* op inserts single-dimensional entries into the shape of the input tensor *data,* and produces a single output tensor *expanded*. The op also takes an argument *dims* with a list of dimensions for where to add the single dimensional entries. If the same blob is provided as input and output, the operation is copy-free. This is the exact inverse operation of *Squeeze*. 54 - https://github.com/pytorch/pytorch/blob/master/caffe2/operators/expand_squeeze_dims_op.h 55 - https://github.com/pytorch/pytorch/blob/master/caffe2/operators/expand_squeeze_dims_op.cc 60 <summary> <b>Example</b> </summary> 66 workspace.ResetWorkspace() 68 op = core.CreateOperator( 75 workspace.FeedBlob("data", np.zeros((100,100)).astype(np.float32)) 76 print("data.shape:", workspace.FetchBlob("data").shape) 78 workspace.RunOperatorOnce(op) 79 print("expanded.shape:", workspace.FetchBlob("expanded").shape) 87 data.shape: (100, 100) 88 expanded.shape: (1, 1, 100, 100) 97 .Input(0, "data",
"Input tensor of data to be operated on.")
98 .Output(0,
"expanded",
"Reshaped tensor with same data as input.")
101 "*(type: [int])* List of dimensions of *data* to add single dimensional entry.")
102 .InheritOnnxSchema();
104 OPERATOR_SCHEMA(Squeeze)
107 .AllowInplace({{0, 0}})
109 The *Squeeze* op removes single-dimensional entries from the shape of the input tensor *data,* and produces a single output tensor *squeezed*. The op also takes an argument *dims* with a list of dimensions to squeeze. If the same blob is provided as input and output, the operation is copy-free. This is the exact inverse operation of *ExpandDims* given the same *dims* argument. 113 - https://github.com/pytorch/pytorch/blob/master/caffe2/operators/expand_squeeze_dims_op.h 114 - https://github.com/pytorch/pytorch/blob/master/caffe2/operators/expand_squeeze_dims_op.cc 119 <summary> <b>Example</b> </summary> 125 workspace.ResetWorkspace() 127 op = core.CreateOperator( 134 workspace.FeedBlob("data", np.zeros((1,1,100,100)).astype(np.float32)) 135 print("data.shape:", workspace.FetchBlob("data").shape) 137 workspace.RunOperatorOnce(op) 138 print("squeezed.shape:", workspace.FetchBlob("squeezed").shape) 146 data.shape: (1, 1, 100, 100) 147 squeezed.shape: (100, 100) 154 .Input(0, "data",
"Input tensor of data to be operated on.")
155 .Output(0,
"squeezed",
"Reshaped tensor with same data as input.")
156 .Arg(
"dims",
"*(type: [int])* List of dimensions of *data* to squeeze out.")
157 .TensorInferenceFunction([](
const OperatorDef& def,
158 const vector<TensorShape>& in) {
160 auto dims = helper.template GetRepeatedArgument<int>(
"dims");
161 auto originalSize = dims.size();
162 std::sort(dims.begin(), dims.end());
163 dims.erase(std::unique(dims.begin(), dims.end()), dims.end());
164 if (dims.size() < originalSize) {
165 LOG(WARNING) <<
"Parameter `dims` has repeated dimensions.";
167 CAFFE_ENFORCE(dims.front() >= 0,
"Dimension ids must be non-negative.");
169 vector<TensorShape> out(1);
170 std::vector<int> newDims =
172 out[0] = CreateTensorShape(newDims, in[0].data_type());
175 .InheritOnnxSchema();
178 using GradientMakerBase::GradientMakerBase;
179 vector<OperatorDef> GetGradientDefs()
override {
181 "ExpandDims",
"", vector<string>{GO(0)}, vector<string>{GI(0)});
187 using GradientMakerBase::GradientMakerBase;
188 vector<OperatorDef> GetGradientDefs()
override {
190 "Squeeze",
"", vector<string>{GO(0)}, vector<string>{GI(0)});
A helper class to index into arguments.
A global dictionary that holds information about what Caffe2 modules have been loaded in the current ...
static vector< OperatorDef > SingleGradientDef(const Args &...args)
a helper function to allow one to create one single operator def, which is usually the case for many ...