1 /* Copyright 2015 The TensorFlow Authors. All Rights Reserved.
2
3 Licensed under the Apache License, Version 2.0 (the "License");
4 you may not use this file except in compliance with the License.
5 You may obtain a copy of the License at
6
7 http://www.apache.org/licenses/LICENSE-2.0
8
9 Unless required by applicable law or agreed to in writing, software
10 distributed under the License is distributed on an "AS IS" BASIS,
11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 See the License for the specific language governing permissions and
13 limitations under the License.
14 ==============================================================================*/
15
16 #include "tensorflow/core/kernels/eigen_pooling.h"
17 #include "tensorflow/core/platform/test.h"
18
19 namespace Eigen {
20
21 namespace {
EigenApprox(float a,float b)22 void EigenApprox(float a, float b) {
23 ASSERT_TRUE(std::abs(a - b) <= std::min(std::abs(a), std::abs(b)) * 1e-3);
24 }
25 } // namespace
26
TEST(EigenPoolingTest,Simple)27 TEST(EigenPoolingTest, Simple) {
28 const int depth = 10;
29 const int input_rows = 5;
30 const int input_cols = 5;
31 const int num_batches = 13;
32 const int patch_rows = 4;
33 const int patch_cols = 4;
34 const int output_rows = 2;
35 const int output_cols = 2;
36
37 Tensor<float, 4> input(depth, input_rows, input_cols, num_batches);
38 Tensor<float, 4> result(depth, output_rows, output_cols, num_batches);
39 input = input.constant(11.0f) + input.random();
40 result.setRandom();
41 result = result.constant(-1000.f);
42
43 // Max pooling using a 4x4 window and a stride of 1.
44 const int stride = 1;
45 result = SpatialMaxPooling(input, patch_rows, patch_cols, stride, stride,
46 PADDING_VALID);
47
48 EXPECT_EQ(result.dimension(0), depth);
49 EXPECT_EQ(result.dimension(1), output_rows);
50 EXPECT_EQ(result.dimension(2), output_cols);
51 EXPECT_EQ(result.dimension(3), num_batches);
52
53 for (int b = 0; b < num_batches; ++b) {
54 for (int d = 0; d < depth; ++d) {
55 for (int i = 0; i < output_rows; ++i) {
56 for (int j = 0; j < output_cols; ++j) {
57 float expected = -10000.f;
58 for (int r = 0; r < patch_rows; ++r) {
59 for (int c = 0; c < patch_cols; ++c) {
60 expected = (std::max)(expected, input(d, r + i, c + j, b));
61 }
62 }
63 if (result(d, i, j, b) != expected) {
64 std::cout << "at d=" << d << " b=" << b << " i=" << i << " j=" << j
65 << " " << result(d, i, j, b) << " vs " << expected
66 << std::endl;
67 }
68 EigenApprox(result(d, i, j, b), expected);
69 }
70 }
71 }
72 }
73 }
74
TEST(EigenPoolingTest,SimpleRowMajor)75 TEST(EigenPoolingTest, SimpleRowMajor) {
76 const int depth = 10;
77 const int input_rows = 5;
78 const int input_cols = 5;
79 const int num_batches = 13;
80 const int patch_rows = 4;
81 const int patch_cols = 4;
82 const int output_rows = 2;
83 const int output_cols = 2;
84
85 Tensor<float, 4, RowMajor> input(num_batches, input_cols, input_rows, depth);
86 Tensor<float, 4, RowMajor> result(num_batches, output_cols, output_rows,
87 depth);
88 input = input.constant(11.0f) + input.random();
89 result.setRandom();
90 result = result.constant(-1000.f);
91
92 // Max pooling using a 4x4 window and a stride of 1.
93 const int stride = 1;
94 result = SpatialMaxPooling(input, patch_rows, patch_cols, stride, stride,
95 PADDING_VALID);
96
97 EXPECT_EQ(result.dimension(3), depth);
98 EXPECT_EQ(result.dimension(2), output_rows);
99 EXPECT_EQ(result.dimension(1), output_cols);
100 EXPECT_EQ(result.dimension(0), num_batches);
101
102 for (int b = 0; b < num_batches; ++b) {
103 for (int d = 0; d < depth; ++d) {
104 for (int i = 0; i < output_rows; ++i) {
105 for (int j = 0; j < output_cols; ++j) {
106 float expected = -10000.f;
107 for (int r = 0; r < patch_rows; ++r) {
108 for (int c = 0; c < patch_cols; ++c) {
109 expected = (std::max)(expected, input(b, c + j, r + i, d));
110 }
111 }
112 if (result(b, j, i, d) != expected) {
113 std::cout << "at d=" << d << " b=" << b << " i=" << i << " j=" << j
114 << " " << result(b, j, i, d) << " vs " << expected
115 << std::endl;
116 }
117 EigenApprox(result(b, j, i, d), expected);
118 }
119 }
120 }
121 }
122 }
123
TEST(EigenPoolingTest,Cuboid)124 TEST(EigenPoolingTest, Cuboid) {
125 const int channels = 10;
126 const int input_planes = 5;
127 const int input_rows = 5;
128 const int input_cols = 5;
129 const int num_batches = 13;
130 const int patch_rows = 4;
131 const int patch_cols = 3;
132 const int patch_planes = 2;
133 const int output_rows = 2;
134 const int output_cols = 3;
135 const int output_planes = 4;
136
137 Tensor<float, 5> input(channels, input_planes, input_rows, input_cols,
138 num_batches);
139 Tensor<float, 5> result(channels, output_planes, output_rows, output_cols,
140 num_batches);
141 input = input.constant(11.0f) + input.random();
142 result.setRandom();
143 result = result.constant(-1000.0f);
144
145 // Max pooling using a 4x3x2 window and a stride of 1.
146 const int stride = 1;
147 result = CuboidMaxPooling(input, patch_planes, patch_rows, patch_cols, stride,
148 stride, stride, PADDING_VALID);
149
150 EXPECT_EQ(result.dimension(0), channels);
151 EXPECT_EQ(result.dimension(1), output_planes);
152 EXPECT_EQ(result.dimension(2), output_rows);
153 EXPECT_EQ(result.dimension(3), output_cols);
154 EXPECT_EQ(result.dimension(4), num_batches);
155
156 for (int b = 0; b < num_batches; ++b) {
157 for (int d = 0; d < channels; ++d) {
158 for (int i = 0; i < output_planes; ++i) {
159 for (int j = 0; j < output_rows; ++j) {
160 for (int k = 0; k < output_cols; ++k) {
161 float expected = -10000.f;
162 for (int p = 0; p < patch_planes; ++p) {
163 for (int r = 0; r < patch_rows; ++r) {
164 for (int c = 0; c < patch_cols; ++c) {
165 expected =
166 (std::max)(expected, input(d, p + i, r + j, c + k, b));
167 }
168 }
169 }
170 if (result(d, i, j, k, b) != expected) {
171 std::cout << "at d=" << d << " b=" << b << " i=" << i
172 << " j=" << j << " k=" << k << " "
173 << result(d, i, j, k, b) << " vs " << expected
174 << std::endl;
175 }
176 EigenApprox(result(d, i, j, k, b), expected);
177 }
178 }
179 }
180 }
181 }
182 }
183
TEST(EigenPoolingTest,CuboidRowMajor)184 TEST(EigenPoolingTest, CuboidRowMajor) {
185 const int channels = 10;
186 const int input_planes = 5;
187 const int input_rows = 5;
188 const int input_cols = 5;
189 const int num_batches = 13;
190 const int patch_rows = 4;
191 const int patch_cols = 3;
192 const int patch_planes = 2;
193 const int output_rows = 2;
194 const int output_cols = 3;
195 const int output_planes = 4;
196
197 Tensor<float, 5, RowMajor> input(num_batches, input_cols, input_rows,
198 input_planes, channels);
199 Tensor<float, 5, RowMajor> result(num_batches, output_cols, output_rows,
200 output_planes, channels);
201 input = input.constant(11.0f) + input.random();
202 result.setRandom();
203 result = result.constant(-1000.0f);
204
205 // Max pooling using a 4x3x2 window and a stride of 1.
206 const int stride = 1;
207 result = CuboidMaxPooling(input, patch_planes, patch_rows, patch_cols, stride,
208 stride, stride, PADDING_VALID);
209
210 EXPECT_EQ(result.dimension(4), channels);
211 EXPECT_EQ(result.dimension(3), output_planes);
212 EXPECT_EQ(result.dimension(2), output_rows);
213 EXPECT_EQ(result.dimension(1), output_cols);
214 EXPECT_EQ(result.dimension(0), num_batches);
215
216 for (int b = 0; b < num_batches; ++b) {
217 for (int d = 0; d < channels; ++d) {
218 for (int i = 0; i < output_planes; ++i) {
219 for (int j = 0; j < output_rows; ++j) {
220 for (int k = 0; k < output_cols; ++k) {
221 float expected = -10000.f;
222 for (int p = 0; p < patch_planes; ++p) {
223 for (int r = 0; r < patch_rows; ++r) {
224 for (int c = 0; c < patch_cols; ++c) {
225 expected =
226 (std::max)(expected, input(b, c + k, r + j, p + i, d));
227 }
228 }
229 }
230 if (result(b, k, j, i, d) != expected) {
231 std::cout << "at d=" << d << " b=" << b << " i=" << i
232 << " j=" << j << " k=" << k << " "
233 << result(b, k, j, i, d) << " vs " << expected
234 << std::endl;
235 }
236 EigenApprox(result(b, k, j, i, d), expected);
237 }
238 }
239 }
240 }
241 }
242 }
243
TEST(EigenPoolingTest,ValidCuboid)244 TEST(EigenPoolingTest, ValidCuboid) {
245 const int channels = 10;
246 const int input_planes = 5;
247 const int input_rows = 5;
248 const int input_cols = 5;
249 const int num_batches = 13;
250 const int patch_rows = 4;
251 const int patch_cols = 3;
252 const int patch_planes = 2;
253 const int output_rows = 2;
254 const int output_cols = 3;
255 const int output_planes = 4;
256
257 Tensor<float, 5> input(channels, input_planes, input_rows, input_cols,
258 num_batches);
259 Tensor<float, 5> result(channels, output_planes, output_rows, output_cols,
260 num_batches);
261 input = input.constant(11.0f) + input.random();
262 result.setRandom();
263 result = result.constant(-1000.0f);
264
265 // Max pooling using a 4x3x2 window and a stride of 1.
266 const int stride = 1;
267 result = CuboidAvgPooling(input, patch_planes, patch_rows, patch_cols, stride,
268 stride, stride, PADDING_VALID);
269
270 EXPECT_EQ(result.dimension(0), channels);
271 EXPECT_EQ(result.dimension(1), output_planes);
272 EXPECT_EQ(result.dimension(2), output_rows);
273 EXPECT_EQ(result.dimension(3), output_cols);
274 EXPECT_EQ(result.dimension(4), num_batches);
275
276 for (int b = 0; b < num_batches; ++b) {
277 for (int d = 0; d < channels; ++d) {
278 for (int i = 0; i < output_planes; ++i) {
279 for (int j = 0; j < output_rows; ++j) {
280 for (int k = 0; k < output_cols; ++k) {
281 float expected_sum = 0.0f;
282 int expected_count = 0;
283 for (int p = 0; p < patch_planes; ++p) {
284 for (int r = 0; r < patch_rows; ++r) {
285 for (int c = 0; c < patch_cols; ++c) {
286 expected_sum += input(d, p + i, r + j, c + k, b);
287 expected_count++;
288 }
289 }
290 }
291 const float expected = expected_sum / expected_count;
292 if (result(d, i, j, k, b) != expected) {
293 std::cout << "at d=" << d << " b=" << b << " i=" << i
294 << " j=" << j << " k=" << k << " "
295 << result(d, i, j, k, b) << " vs " << expected
296 << std::endl;
297 }
298 EigenApprox(result(d, i, j, k, b), expected);
299 }
300 }
301 }
302 }
303 }
304 }
305
TEST(EigenPoolingTest,ValidCuboidRowMajor)306 TEST(EigenPoolingTest, ValidCuboidRowMajor) {
307 const int channels = 10;
308 const int input_planes = 5;
309 const int input_rows = 5;
310 const int input_cols = 5;
311 const int num_batches = 13;
312 const int patch_rows = 4;
313 const int patch_cols = 3;
314 const int patch_planes = 2;
315 const int output_rows = 2;
316 const int output_cols = 3;
317 const int output_planes = 4;
318
319 Tensor<float, 5, RowMajor> input(num_batches, input_cols, input_rows,
320 input_planes, channels);
321 Tensor<float, 5, RowMajor> result(num_batches, output_cols, output_rows,
322 output_planes, channels);
323 input = input.constant(11.0f) + input.random();
324 result.setRandom();
325 result = result.constant(-1000.0f);
326
327 // Max pooling using a 4x3x2 window and a stride of 1.
328 const int stride = 1;
329 result = CuboidAvgPooling(input, patch_planes, patch_rows, patch_cols, stride,
330 stride, stride, PADDING_VALID);
331
332 EXPECT_EQ(result.dimension(4), channels);
333 EXPECT_EQ(result.dimension(3), output_planes);
334 EXPECT_EQ(result.dimension(2), output_rows);
335 EXPECT_EQ(result.dimension(1), output_cols);
336 EXPECT_EQ(result.dimension(0), num_batches);
337
338 for (int b = 0; b < num_batches; ++b) {
339 for (int d = 0; d < channels; ++d) {
340 for (int i = 0; i < output_planes; ++i) {
341 for (int j = 0; j < output_rows; ++j) {
342 for (int k = 0; k < output_cols; ++k) {
343 float expected_sum = 0.0f;
344 int expected_count = 0;
345 for (int p = 0; p < patch_planes; ++p) {
346 for (int r = 0; r < patch_rows; ++r) {
347 for (int c = 0; c < patch_cols; ++c) {
348 expected_sum += input(b, c + k, r + j, p + i, d);
349 expected_count++;
350 }
351 }
352 }
353 const float expected = expected_sum / expected_count;
354 if (result(b, k, j, i, d) != expected) {
355 std::cout << "at d=" << d << " b=" << b << " i=" << i
356 << " j=" << j << " k=" << k << " "
357 << result(b, k, j, i, d) << " vs " << expected
358 << std::endl;
359 }
360 EigenApprox(result(b, k, j, i, d), expected);
361 }
362 }
363 }
364 }
365 }
366 }
367
TEST(EigenPoolingTest,SameCuboid)368 TEST(EigenPoolingTest, SameCuboid) {
369 const int channels = 10;
370 const int input_planes = 5;
371 const int input_rows = 5;
372 const int input_cols = 5;
373 const int num_batches = 13;
374 const int patch_rows = 4;
375 const int patch_cols = 3;
376 const int patch_planes = 2;
377 const int output_rows = input_rows;
378 const int output_cols = input_cols;
379 const int output_planes = input_planes;
380
381 Tensor<float, 5> input(channels, input_planes, input_rows, input_cols,
382 num_batches);
383 Tensor<float, 5> result(channels, output_planes, output_rows, output_cols,
384 num_batches);
385 input = input.constant(11.0f) + input.random();
386 result.setRandom();
387 result = result.constant(-1000.0f);
388
389 // Max pooling using a 4x3x2 window and a stride of 1.
390 const int stride = 1;
391 result = CuboidAvgPooling(input, patch_planes, patch_rows, patch_cols, stride,
392 stride, stride, PADDING_SAME);
393
394 EXPECT_EQ(result.dimension(0), channels);
395 EXPECT_EQ(result.dimension(1), output_planes);
396 EXPECT_EQ(result.dimension(2), output_rows);
397 EXPECT_EQ(result.dimension(3), output_cols);
398 EXPECT_EQ(result.dimension(4), num_batches);
399
400 const int pad_p = output_planes - input_planes + patch_planes - 1;
401 const int pad_r = output_rows - input_rows + patch_rows - 1;
402 const int pad_c = output_cols - input_cols + patch_cols - 1;
403
404 // Number of pixels the input is extended with at the lower end in every
405 // dimension.
406 const int dp = pad_p / 2;
407 const int dr = pad_r / 2;
408 const int dc = pad_c / 2;
409
410 for (int b = 0; b < num_batches; ++b) {
411 for (int d = 0; d < channels; ++d) {
412 for (int i = 0; i < output_planes; ++i) {
413 for (int j = 0; j < output_rows; ++j) {
414 for (int k = 0; k < output_cols; ++k) {
415 float expected_sum = 0.0f;
416 int expected_count = 0;
417 for (int p = 0; p < patch_planes; ++p) {
418 for (int r = 0; r < patch_rows; ++r) {
419 for (int c = 0; c < patch_cols; ++c) {
420 const int in_p = p + i - dp;
421 const int in_r = r + j - dr;
422 const int in_c = c + k - dc;
423 if (in_p >= 0 && in_p < input_planes && in_r >= 0 &&
424 in_r < input_rows && in_c >= 0 && in_c < input_cols) {
425 expected_sum += input(d, in_p, in_r, in_c, b);
426 expected_count++;
427 }
428 }
429 }
430 }
431 const float expected = expected_sum / expected_count;
432 if (result(d, i, j, k, b) != expected) {
433 std::cout << "at d=" << d << " b=" << b << " i=" << i
434 << " j=" << j << " k=" << k << " "
435 << result(d, i, j, k, b) << " vs " << expected
436 << std::endl;
437 }
438 EigenApprox(result(d, i, j, k, b), expected);
439 }
440 }
441 }
442 }
443 }
444 }
445
TEST(EigenPoolingTest,SameCuboidRowMajor)446 TEST(EigenPoolingTest, SameCuboidRowMajor) {
447 const int channels = 10;
448 const int input_planes = 5;
449 const int input_rows = 5;
450 const int input_cols = 5;
451 const int num_batches = 13;
452 const int patch_rows = 4;
453 const int patch_cols = 3;
454 const int patch_planes = 2;
455 const int output_rows = input_rows;
456 const int output_cols = input_cols;
457 const int output_planes = input_planes;
458
459 Tensor<float, 5, RowMajor> input(num_batches, input_cols, input_rows,
460 input_planes, channels);
461 Tensor<float, 5, RowMajor> result(num_batches, output_cols, output_rows,
462 output_planes, channels);
463 input = input.constant(11.0f) + input.random();
464 result.setRandom();
465 result = result.constant(-1000.0f);
466
467 // Max pooling using a 4x3x2 window and a stride of 1.
468 const int stride = 1;
469 result = CuboidAvgPooling(input, patch_planes, patch_rows, patch_cols, stride,
470 stride, stride, PADDING_SAME);
471
472 EXPECT_EQ(result.dimension(4), channels);
473 EXPECT_EQ(result.dimension(3), output_planes);
474 EXPECT_EQ(result.dimension(2), output_rows);
475 EXPECT_EQ(result.dimension(1), output_cols);
476 EXPECT_EQ(result.dimension(0), num_batches);
477
478 const int pad_p = output_planes - input_planes + patch_planes - 1;
479 const int pad_r = output_rows - input_rows + patch_rows - 1;
480 const int pad_c = output_cols - input_cols + patch_cols - 1;
481
482 // Number of pixels the input is extended with at the lower end in every
483 // dimension.
484 const int dp = pad_p / 2;
485 const int dr = pad_r / 2;
486 const int dc = pad_c / 2;
487
488 for (int b = 0; b < num_batches; ++b) {
489 for (int d = 0; d < channels; ++d) {
490 for (int i = 0; i < output_planes; ++i) {
491 for (int j = 0; j < output_rows; ++j) {
492 for (int k = 0; k < output_cols; ++k) {
493 float expected_sum = 0.0f;
494 int expected_count = 0;
495 for (int p = 0; p < patch_planes; ++p) {
496 for (int r = 0; r < patch_rows; ++r) {
497 for (int c = 0; c < patch_cols; ++c) {
498 const int in_p = p + i - dp;
499 const int in_r = r + j - dr;
500 const int in_c = c + k - dc;
501 if (in_p >= 0 && in_p < input_planes && in_r >= 0 &&
502 in_r < input_rows && in_c >= 0 && in_c < input_cols) {
503 expected_sum += input(b, in_c, in_r, in_p, d);
504 expected_count++;
505 }
506 }
507 }
508 }
509 const float expected = expected_sum / expected_count;
510 if (result(b, k, j, i, d) != expected) {
511 std::cout << "at d=" << d << " b=" << b << " i=" << i
512 << " j=" << j << " k=" << k << " "
513 << result(b, k, j, i, d) << " vs " << expected
514 << std::endl;
515 }
516 EigenApprox(result(b, k, j, i, d), expected);
517 }
518 }
519 }
520 }
521 }
522 }
523
TEST(EigenPoolingTest,Strided)524 TEST(EigenPoolingTest, Strided) {
525 const int depth = 10;
526 const int input_rows = 5;
527 const int input_cols = 5;
528 const int num_batches = 13;
529 const int patch_rows = 3;
530 const int patch_cols = 3;
531 const int output_rows = 2;
532 const int output_cols = 2;
533
534 Tensor<float, 4> input(depth, input_rows, input_cols, num_batches);
535 Tensor<float, 4> result(depth, output_rows, output_cols, num_batches);
536 input = input.constant(11.0f) + input.random();
537 result.setRandom();
538
539 // Max pooling using a 3x3 window and a stride of 2.
540 int stride = 2;
541 result = SpatialMaxPooling(input, patch_rows, patch_cols, stride, stride,
542 PADDING_VALID);
543
544 EXPECT_EQ(result.dimension(0), depth);
545 EXPECT_EQ(result.dimension(1), output_rows);
546 EXPECT_EQ(result.dimension(2), output_cols);
547 EXPECT_EQ(result.dimension(3), num_batches);
548
549 for (int b = 0; b < num_batches; ++b) {
550 for (int d = 0; d < depth; ++d) {
551 for (int i = 0; i < output_rows; ++i) {
552 for (int j = 0; j < output_cols; ++j) {
553 float expected = -10000.f;
554 for (int r = 0; r < patch_rows; ++r) {
555 for (int c = 0; c < patch_cols; ++c) {
556 expected = (std::max)(
557 expected, input(d, r + stride * i, c + stride * j, b));
558 }
559 }
560 if (result(d, i, j, b) != expected) {
561 std::cout << "at d=" << d << " b=" << b << " i=" << i << " j=" << j
562 << " " << result(d, i, j, b) << " vs " << expected
563 << std::endl;
564 }
565 EigenApprox(result(d, i, j, b), expected);
566 }
567 }
568 }
569 }
570 }
571
TEST(EigenPoolingTest,StridedRowMajor)572 TEST(EigenPoolingTest, StridedRowMajor) {
573 const int depth = 10;
574 const int input_rows = 5;
575 const int input_cols = 5;
576 const int num_batches = 13;
577 const int patch_rows = 3;
578 const int patch_cols = 3;
579 const int output_rows = 2;
580 const int output_cols = 2;
581
582 Tensor<float, 4, RowMajor> input(num_batches, input_cols, input_rows, depth);
583 Tensor<float, 4, RowMajor> result(num_batches, output_cols, output_rows,
584 depth);
585 input = input.constant(11.0f) + input.random();
586 result.setRandom();
587
588 // Max pooling using a 3x3 window and a stride of 2.
589 int stride = 2;
590 result = SpatialMaxPooling(input, patch_rows, patch_cols, stride, stride,
591 PADDING_VALID);
592
593 EXPECT_EQ(result.dimension(3), depth);
594 EXPECT_EQ(result.dimension(2), output_rows);
595 EXPECT_EQ(result.dimension(1), output_cols);
596 EXPECT_EQ(result.dimension(0), num_batches);
597
598 for (int b = 0; b < num_batches; ++b) {
599 for (int d = 0; d < depth; ++d) {
600 for (int i = 0; i < output_rows; ++i) {
601 for (int j = 0; j < output_cols; ++j) {
602 float expected = -10000.f;
603 for (int r = 0; r < patch_rows; ++r) {
604 for (int c = 0; c < patch_cols; ++c) {
605 expected = (std::max)(
606 expected, input(b, c + stride * j, r + stride * i, d));
607 }
608 }
609 if (result(b, j, i, d) != expected) {
610 std::cout << "at d=" << d << " b=" << b << " i=" << i << " j=" << j
611 << " " << result(b, j, i, d) << " vs " << expected
612 << std::endl;
613 }
614 EigenApprox(result(b, j, i, d), expected);
615 }
616 }
617 }
618 }
619 }
620
TEST(EigenPoolingTest,StridedCuboid)621 TEST(EigenPoolingTest, StridedCuboid) {
622 const int channels = 10;
623 const int input_planes = 5;
624 const int input_rows = 5;
625 const int input_cols = 5;
626 const int num_batches = 13;
627 const int patch_planes = 3;
628 const int patch_rows = 3;
629 const int patch_cols = 3;
630 const int output_planes = 2;
631 const int output_rows = 2;
632 const int output_cols = 2;
633
634 Tensor<float, 5> input(channels, input_planes, input_rows, input_cols,
635 num_batches);
636 Tensor<float, 5> result(channels, output_planes, output_rows, output_cols,
637 num_batches);
638 input = input.constant(11.0f) + input.random();
639 result.setRandom();
640
641 // Max pooling using a 3x3x3 window and a stride of 2.
642 int stride = 2;
643 result = CuboidMaxPooling(input, patch_planes, patch_rows, patch_cols, stride,
644 stride, stride, PADDING_VALID);
645
646 EXPECT_EQ(result.dimension(0), channels);
647 EXPECT_EQ(result.dimension(1), output_planes);
648 EXPECT_EQ(result.dimension(2), output_rows);
649 EXPECT_EQ(result.dimension(3), output_cols);
650 EXPECT_EQ(result.dimension(4), num_batches);
651
652 for (int b = 0; b < num_batches; ++b) {
653 for (int d = 0; d < channels; ++d) {
654 for (int i = 0; i < output_planes; ++i) {
655 for (int j = 0; j < output_rows; ++j) {
656 for (int k = 0; k < output_cols; ++k) {
657 float expected = -10000.f;
658 for (int p = 0; p < patch_planes; ++p) {
659 for (int r = 0; r < patch_rows; ++r) {
660 for (int c = 0; c < patch_cols; ++c) {
661 expected = (std::max)(expected,
662 input(d, p + stride * i, r + stride * j,
663 c + stride * k, b));
664 }
665 }
666 }
667 if (result(d, i, j, k, b) != expected) {
668 std::cout << "at d=" << d << " b=" << b << " i=" << i
669 << " j=" << j << " " << k << " "
670 << result(d, i, j, k, b) << " vs " << expected
671 << std::endl;
672 }
673 EigenApprox(result(d, i, j, k, b), expected);
674 }
675 }
676 }
677 }
678 }
679 }
680
TEST(EigenPoolingTest,StridedCuboidRowMajor)681 TEST(EigenPoolingTest, StridedCuboidRowMajor) {
682 const int channels = 10;
683 const int input_planes = 5;
684 const int input_rows = 5;
685 const int input_cols = 5;
686 const int num_batches = 13;
687 const int patch_planes = 3;
688 const int patch_rows = 3;
689 const int patch_cols = 3;
690 const int output_planes = 2;
691 const int output_rows = 2;
692 const int output_cols = 2;
693
694 Tensor<float, 5, RowMajor> input(num_batches, input_cols, input_rows,
695 input_planes, channels);
696 Tensor<float, 5, RowMajor> result(num_batches, output_cols, output_rows,
697 output_planes, channels);
698 input = input.constant(11.0f) + input.random();
699 result.setRandom();
700
701 // Max pooling using a 3x3x3 window and a stride of 2.
702 int stride = 2;
703 result = CuboidMaxPooling(input, patch_planes, patch_rows, patch_cols, stride,
704 stride, stride, PADDING_VALID);
705
706 EXPECT_EQ(result.dimension(4), channels);
707 EXPECT_EQ(result.dimension(3), output_planes);
708 EXPECT_EQ(result.dimension(2), output_rows);
709 EXPECT_EQ(result.dimension(1), output_cols);
710 EXPECT_EQ(result.dimension(0), num_batches);
711
712 for (int b = 0; b < num_batches; ++b) {
713 for (int d = 0; d < channels; ++d) {
714 for (int i = 0; i < output_planes; ++i) {
715 for (int j = 0; j < output_rows; ++j) {
716 for (int k = 0; k < output_cols; ++k) {
717 float expected = -10000.f;
718 for (int p = 0; p < patch_planes; ++p) {
719 for (int r = 0; r < patch_rows; ++r) {
720 for (int c = 0; c < patch_cols; ++c) {
721 expected = (std::max)(expected,
722 input(b, c + stride * k, r + stride * j,
723 p + stride * i, d));
724 }
725 }
726 }
727 if (result(b, k, j, i, d) != expected) {
728 std::cout << "at d=" << d << " b=" << b << " i=" << i
729 << " j=" << j << " " << k << " "
730 << result(b, k, j, i, d) << " vs " << expected
731 << std::endl;
732 }
733 EigenApprox(result(b, k, j, i, d), expected);
734 }
735 }
736 }
737 }
738 }
739 }
740
741 } // namespace Eigen
742