pytorch  1.8.2
About: PyTorch provides Tensor computation (like NumPy) with strong GPU acceleration and Deep Neural Networks (in Python) built on a tape-based autograd system. LTS (Long Term Support) release.
  Fossies Dox: pytorch-1.8.2.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

roi_align_gradient_op.cc
Go to the documentation of this file.
2
4#include "caffe2/utils/math.h"
5
6namespace caffe2 {
7namespace {
8
9template <typename T>
10void bilinear_interpolate_gradient(
11 const int height,
12 const int width,
13 T y,
14 T x,
15 T& w1,
16 T& w2,
17 T& w3,
18 T& w4,
19 int& x_low,
20 int& x_high,
21 int& y_low,
22 int& y_high,
23 const int /*index*/ /* index for debug only*/) {
24 // deal with cases that inverse elements are out of feature map boundary
25 if (y < -1.0 || y > height || x < -1.0 || x > width) {
26 // empty
27 w1 = w2 = w3 = w4 = 0.;
28 x_low = x_high = y_low = y_high = -1;
29 return;
30 }
31
32 if (y <= 0) {
33 y = 0;
34 }
35 if (x <= 0) {
36 x = 0;
37 }
38
39 y_low = (int)y;
40 x_low = (int)x;
41
42 if (y_low >= height - 1) {
43 y_high = y_low = height - 1;
44 y = (T)y_low;
45 } else {
46 y_high = y_low + 1;
47 }
48
49 if (x_low >= width - 1) {
50 x_high = x_low = width - 1;
51 x = (T)x_low;
52 } else {
53 x_high = x_low + 1;
54 }
55
56 T ly = y - y_low;
57 T lx = x - x_low;
58 T hy = 1. - ly, hx = 1. - lx;
59
60 // reference in forward
61 // T v1 = bottom_data[y_low * width + x_low];
62 // T v2 = bottom_data[y_low * width + x_high];
63 // T v3 = bottom_data[y_high * width + x_low];
64 // T v4 = bottom_data[y_high * width + x_high];
65 // T val = (w1 * v1 + w2 * v2 + w3 * v3 + w4 * v4);
66
67 w1 = hy * hx, w2 = hy * lx, w3 = ly * hx, w4 = ly * lx;
68
69 return;
70}
71
72template <class T>
73inline void add(const T& val, T* address) {
74 *address += val;
75}
76
77template <typename T>
78void ROIAlignBackwardFeature(
79 const int nthreads,
80 const T* top_diff,
81 const int /*num_rois*/,
82 const T& spatial_scale,
83 const int channels,
84 const int height,
85 const int width,
86 const int pooled_height,
87 const int pooled_width,
88 const int sampling_ratio,
89 T* bottom_diff,
90 const T* bottom_rois,
91 int rois_cols,
92 bool continuous_coordinate) {
93 DCHECK(rois_cols == 4 || rois_cols == 5);
94
95 for (int index = 0; index < nthreads; index++) {
96 // (n, c, ph, pw) is an element in the pooled output
97 int pw = index % pooled_width;
98 int ph = (index / pooled_width) % pooled_height;
99 int c = (index / pooled_width / pooled_height) % channels;
100 int n = index / pooled_width / pooled_height / channels;
101
102 const T* offset_bottom_rois = bottom_rois + n * rois_cols;
103 int roi_batch_ind = 0;
104 if (rois_cols == 5) {
105 roi_batch_ind = offset_bottom_rois[0];
106 offset_bottom_rois++;
107 }
108
109 // Do not using rounding; this implementation detail is critical
110 T roi_offset = continuous_coordinate ? T(0.5) : 0;
111 T roi_start_w = offset_bottom_rois[0] * spatial_scale - roi_offset;
112 T roi_start_h = offset_bottom_rois[1] * spatial_scale - roi_offset;
113 T roi_end_w = offset_bottom_rois[2] * spatial_scale - roi_offset;
114 T roi_end_h = offset_bottom_rois[3] * spatial_scale - roi_offset;
115
116 T roi_width = roi_end_w - roi_start_w;
117 T roi_height = roi_end_h - roi_start_h;
118 if (continuous_coordinate) {
120 roi_width >= 0 && roi_height >= 0,
121 "ROIs in ROIAlign do not have non-negative size!");
122 } else { // backward compatibility
123 // Force malformed ROIs to be 1x1
124 roi_width = std::max(roi_width, (T)1.);
125 roi_height = std::max(roi_height, (T)1.);
126 }
127 T bin_size_h = static_cast<T>(roi_height) / static_cast<T>(pooled_height);
128 T bin_size_w = static_cast<T>(roi_width) / static_cast<T>(pooled_width);
129
130 T* offset_bottom_diff =
131 bottom_diff + (roi_batch_ind * channels + c) * height * width;
132
133 int top_offset = (n * channels + c) * pooled_height * pooled_width;
134 const T* offset_top_diff = top_diff + top_offset;
135 const T top_diff_this_bin = offset_top_diff[ph * pooled_width + pw];
136
137 // We use roi_bin_grid to sample the grid and mimic integral
138 int roi_bin_grid_h = (sampling_ratio > 0)
139 ? sampling_ratio
140 : ceil(roi_height / pooled_height); // e.g., = 2
141 int roi_bin_grid_w =
142 (sampling_ratio > 0) ? sampling_ratio : ceil(roi_width / pooled_width);
143
144 // We do average (integral) pooling inside a bin
145 const T count = roi_bin_grid_h * roi_bin_grid_w; // e.g. = 4
146
147 for (int iy = 0; iy < roi_bin_grid_h; iy++) {
148 const T y = roi_start_h + ph * bin_size_h +
149 static_cast<T>(iy + .5f) * bin_size_h /
150 static_cast<T>(roi_bin_grid_h); // e.g., 0.5, 1.5
151 for (int ix = 0; ix < roi_bin_grid_w; ix++) {
152 const T x = roi_start_w + pw * bin_size_w +
153 static_cast<T>(ix + .5f) * bin_size_w /
154 static_cast<T>(roi_bin_grid_w);
155
156 T w1, w2, w3, w4;
157 int x_low, x_high, y_low, y_high;
158
159 bilinear_interpolate_gradient(
160 height,
161 width,
162 y,
163 x,
164 w1,
165 w2,
166 w3,
167 w4,
168 x_low,
169 x_high,
170 y_low,
171 y_high,
172 index);
173
174 T g1 = top_diff_this_bin * w1 / count;
175 T g2 = top_diff_this_bin * w2 / count;
176 T g3 = top_diff_this_bin * w3 / count;
177 T g4 = top_diff_this_bin * w4 / count;
178
179 if (x_low >= 0 && x_high >= 0 && y_low >= 0 && y_high >= 0) {
180 // atomic add is not needed for now since it is single threaded
181 add(static_cast<T>(g1), offset_bottom_diff + y_low * width + x_low);
182 add(static_cast<T>(g2), offset_bottom_diff + y_low * width + x_high);
183 add(static_cast<T>(g3), offset_bottom_diff + y_high * width + x_low);
184 add(static_cast<T>(g4), offset_bottom_diff + y_high * width + x_high);
185 } // if
186 } // ix
187 } // iy
188 } // for
189} // ROIAlignBackward
190
191} // namespace
192
193template <>
195 auto& X = Input(0); // Input data to pool
196 auto& R = Input(1); // RoIs
197 auto& dY = Input(2); // Gradient of net w.r.t. output of "forward" op
198 // (aka "gradOutput")
199
200 CAFFE_ENFORCE_EQ(R.dim(), 2);
201 // if R has 5 columns, the first column is the index, otherwise 0
202 CAFFE_ENFORCE(R.dim32(1) == 4 || R.dim32(1) == 5);
203
204 auto* dX = Output(
205 0,
206 X.sizes(),
207 at::dtype<float>()); // Gradient of net w.r.t. input to "forward" op (aka
208 // "gradInput")
209
210 // Must zero-out dX before accumulating gradients
211 // (TODO): Kaiming - is this safe?
213 dX->numel(), 0.f, dX->template mutable_data<float>(), &context_);
214
215 if (dY.numel() > 0) { // Handle possibly empty gradient if there were no rois
216 ROIAlignBackwardFeature<float>(
217 dY.numel(),
218 dY.data<float>(),
219 R.dim32(0),
220 spatial_scale_,
221 X.dim32(1),
222 X.dim32(2),
223 X.dim32(3),
224 pooled_height_,
225 pooled_width_,
226 sampling_ratio_,
227 dX->template mutable_data<float>(),
228 R.data<float>(),
229 R.dim32(1),
230 aligned_);
231 }
232 return true;
233}
234
236
237// Input: X, rois, dY (aka "gradOutput");
238// Output: dX (aka "gradInput")
239OPERATOR_SCHEMA(RoIAlignGradient)
240 .NumInputs(3)
241 .NumOutputs(1)
242 .Input(0, "X", "See RoIPoolF.")
243 .Input(1, "RoIs", "See RoIPoolF.")
244 .Input(2, "dY", "Gradient of forward output 0 (Y)")
245 .Output(0, "dX", "Gradient of forward input 0 (X)");
246
247namespace {
248
249class GetRoIAlignGradient : public GradientMakerBase {
251 vector<OperatorDef> GetGradientDefs() override {
252 return SingleGradientDef(
253 "RoIAlignGradient",
254 "",
255 vector<string>{I(0), I(1), GO(0)},
256 vector<string>{GI(0)});
257 }
258};
259
260} // namespace
261
262REGISTER_GRADIENT(RoIAlign, GetRoIAlignGradient);
263
264template <typename T>
266
267} // namespace caffe2
268
270 RoIAlignGradient,
271 "_caffe2::RoIAlignGradient("
272 " Tensor features,"
273 " Tensor rois,"
274 " Tensor grad,"
275 " str order,"
276 " float spatial_scale,"
277 " int pooled_h,"
278 " int pooled_w,"
279 " int sampling_ratio,"
280 " bool aligned"
281 ") -> Tensor",
#define C10_EXPORT
Definition: Export.h:61
int32_t val
Definition: blob_test.cc:32
GradientMakerBase(const OperatorDef &def, const vector< GradientWrapper > &g_output)
CPUContext * context_
uint8_t w3
uint8_t w4
uint8_t w2
uint8_t w1
#define DCHECK(condition)
Tensor add(const Tensor &self, Scalar other, Scalar alpha)
Definition: BinaryOps.cpp:523
Tensor ceil(const Tensor &self)
Definition: UnaryOps.cpp:249
C10_EXPORT void Set< float, CPUContext >(const std::int64_t N, const float alpha, float *Y, CPUContext *)
Definition: elementwise.cc:520
Copyright (c) 2016-present, Facebook, Inc.
Definition: blob.h:13
REGISTER_CPU_OPERATOR(ATen, ATenOp< CPUContext >)
OPERATOR_SCHEMA(ATen)
CAFFE_ENFORCE_EQ(in.size(), 1, "New shape must not be specified by the input blob and the " "argument `shape` at the same time.")
and label is applied to the tensor elementwise If y
float T
Definition: cc_bmm_bg_op.h:11
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
default where $N$ is batch $C$ is number of $H$ is spatial height
See RoIPoolF dY
Unscaled log probabilities Optional blob to be used to weight the samples for the loss With spatial weighting is by x
Output tensor quantization scale X
See RoIPoolF Gradient of forward dX
dimensions depend on whether the NCHW or NHWC operators are being used For in the the input has where N is the batch C is the number of channels
Definition: pad_op.cc:440
REGISTER_GRADIENT(CTC, GetCTCGradient)
We will build R
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")
index
Definition: find_op.cc:9
INT_MAX int
where N is the number of elements in the H and W are the height and width
CAFFE_ENFORCE(dims.front() >=0, "Dimension ids must be non-negative.")
c10::BFloat16 max(c10::BFloat16 a, c10::BFloat16 b)
Definition: BFloat16-math.h:33
C10_EXPORT_CAFFE2_OP_TO_C10_CPU(RoIAlignGradient, "_caffe2::RoIAlignGradient(" " Tensor features," " Tensor rois," " Tensor grad," " str order," " float spatial_scale," " int pooled_h," " int pooled_w," " int sampling_ratio," " bool aligned" ") -> Tensor", caffe2::RoIAlignGradientCPUOp< float >)