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