File: locally_connected_op.cc

package info (click to toggle)
pytorch 1.13.1%2Bdfsg-4
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 139,252 kB
  • sloc: cpp: 1,100,274; python: 706,454; ansic: 83,052; asm: 7,618; java: 3,273; sh: 2,841; javascript: 612; makefile: 323; xml: 269; ruby: 185; yacc: 144; objc: 68; lex: 44
file content (167 lines) | stat: -rw-r--r-- 5,496 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
#include "caffe2/operators/locally_connected_op.h"

#include <functional>
#include <vector>

#include "caffe2/operators/locally_connected_op_impl.h"

namespace caffe2 {

namespace {

// NOLINTNEXTLINE(modernize-avoid-c-arrays,cppcoreguidelines-avoid-c-arrays)
constexpr char kLCDoc[] = R"DOC(
Note that other parameters, such as the stride and
kernel size, or the pads' sizes in each direction are not necessary for input
because they are provided by the ConvPoolOpBase operator. Various dimension
checks are done implicitly, and the sizes are specified in the Input docs for
this operator. As is expected, the filter is locally connected with a subset of
the image and the bias is added; this is done throughout the image data and the
output is computed. As a side note on the implementation layout:
locally_connected_op_impl.h is the templated implementation of the
locally_connected_op.h file, which is why they are separate files.
)DOC";

std::function<void(OpSchema&)> LCDocGenerator(const char* dim) {
  return [dim](OpSchema& schema) {
    string doc = R"DOC(
The locally connected operator consumes an input vector, a {dim}filter blob
and a bias blob and computes the output. {lc_doc})DOC";
    c10::ReplaceAll(doc, "{dim}", dim);
    c10::ReplaceAll(doc, "{lc_doc}", kLCDoc);
    schema.SetDoc(doc);
    schema.Input(
        1,
        "filter",
        "The filter blob that will be used in the locally connected op; "
        "has size (YH * YW * M x C x kH x kW) if order == NCHW else "
        "(YH * YW * M  * KH * KW * C), where YH and YW are the height "
        "and width of the output image, C is the number of channels, and kH "
        "and kW are the height and width of the kernel.");
    schema.Input(
        2,
        "bias",
        "The 1D bias blob that is added through the locally connected op; "
        "has size (YH * YW * M).");
    schema.Output(
        0,
        "Y",
        "Output data blob that contains the result of the locally connected op."
        "The output dimensions are functions of the kernel size, stride size, "
        "and pad lengths."
        "");
  };
}

} // namespace

REGISTER_CPU_OPERATOR(LC, LocallyConnectedOp<float, CPUContext>);

OPERATOR_SCHEMA(LC)
    .NumInputs(2, 3)
    .NumOutputs(1)
    .TensorInferenceFunction(ConvPoolOpBase<CPUContext>::TensorInferenceForLC)
    .FillUsing(LCDocGenerator(""));

REGISTER_CPU_OPERATOR(LC1D, LocallyConnectedOp<float, CPUContext>);

OPERATOR_SCHEMA(LC1D)
    .NumInputs(2, 3)
    .NumOutputs(1)
    .TensorInferenceFunction(ConvPoolOpBase<CPUContext>::TensorInferenceForLC)
    .FillUsing(LCDocGenerator("1D "));

REGISTER_CPU_OPERATOR(LC2D, LocallyConnectedOp<float, CPUContext>);

OPERATOR_SCHEMA(LC2D)
    .NumInputs(2, 3)
    .NumOutputs(1)
    .TensorInferenceFunction(ConvPoolOpBase<CPUContext>::TensorInferenceForLC)
    .FillUsing(LCDocGenerator("2D "));

REGISTER_CPU_OPERATOR(LC3D, LocallyConnectedOp<float, CPUContext>);

OPERATOR_SCHEMA(LC3D)
    .NumInputs(2, 3)
    .NumOutputs(1)
    .TensorInferenceFunction(ConvPoolOpBase<CPUContext>::TensorInferenceForLC)
    .FillUsing(LCDocGenerator("3D "));

REGISTER_CPU_OPERATOR(
    LCGradient,
    LocallyConnectedGradientOp<float, CPUContext>);

OPERATOR_SCHEMA(LCGradient).NumInputs(2, 3).NumOutputs(1, 3);

REGISTER_CPU_OPERATOR(
    LC1DGradient,
    LocallyConnectedGradientOp<float, CPUContext>);

OPERATOR_SCHEMA(LC1DGradient).NumInputs(2, 3).NumOutputs(1, 3);

REGISTER_CPU_OPERATOR(
    LC2DGradient,
    LocallyConnectedGradientOp<float, CPUContext>);

OPERATOR_SCHEMA(LC2DGradient).NumInputs(2, 3).NumOutputs(1, 3);

REGISTER_CPU_OPERATOR(
    LC3DGradient,
    LocallyConnectedGradientOp<float, CPUContext>);

OPERATOR_SCHEMA(LC3DGradient).NumInputs(2, 3).NumOutputs(1, 3);

namespace {

class GetLocallyConnectedGradient : public GradientMakerBase {
  using GradientMakerBase::GradientMakerBase;

  std::vector<OperatorDef> GetGradientDefs() override {
    CAFFE_ENFORCE(def_.input_size() == 3 || def_.input_size() == 2);
    ArgumentHelper argsHelper(def_);
    const bool compute_dX =
        // NOLINTNEXTLINE(modernize-use-bool-literals)
        !argsHelper.GetSingleArgument<bool>("no_gradient_to_input", 0);

    if (def_.input_size() == 3) {
      if (compute_dX) {
        return SingleGradientDef(
            def_.type() + "Gradient",
            "",
            std::vector<string>{I(0), I(1), GO(0)},
            std::vector<string>{GI(1), GI(2), GI(0)});
      } else {
        return SingleGradientDef(
            def_.type() + "Gradient",
            "",
            std::vector<string>{I(0), I(1), GO(0)},
            std::vector<string>{GI(1), GI(2)});
      }
    } else {
      if (compute_dX) {
        return SingleGradientDef(
            def_.type() + "Gradient",
            "",
            std::vector<string>{I(0), I(1), GO(0)},
            std::vector<string>{GI(1), GI(0)},
            std::vector<Argument>{MakeArgument<int>("no_bias", 1)});
      } else {
        return SingleGradientDef(
            def_.type() + "Gradient",
            "",
            std::vector<string>{I(0), I(1), GO(0)},
            std::vector<string>{GI(1)},
            std::vector<Argument>{MakeArgument<int>("no_bias", 1)});
      }
    }
  }
};

} // namespace

REGISTER_GRADIENT(LC, GetLocallyConnectedGradient);
REGISTER_GRADIENT(LC1D, GetLocallyConnectedGradient);
REGISTER_GRADIENT(LC2D, GetLocallyConnectedGradient);
REGISTER_GRADIENT(LC3D, GetLocallyConnectedGradient);

} // namespace caffe2