#include #include #include namespace F = torch::nn::functional; using namespace torch::nn; struct FunctionalTest : torch::test::SeedingFixture {}; TEST_F(FunctionalTest, MaxPool1d) { auto x = torch::ones({1, 1, 5}); auto y = F::max_pool1d(x, MaxPool1dOptions(3).stride(2)); ASSERT_EQ(y.ndimension(), 3); ASSERT_TRUE(torch::allclose(y, torch::ones({1, 1, 2}))); ASSERT_EQ(y.sizes(), torch::IntArrayRef({1, 1, 2})); } TEST_F(FunctionalTest, MaxPool2d) { auto x = torch::ones({2, 5, 5}); auto y = F::max_pool2d(x, MaxPool2dOptions(3).stride(2)); ASSERT_EQ(y.ndimension(), 3); ASSERT_TRUE(torch::allclose(y, torch::ones({2, 2, 2}))); ASSERT_EQ(y.sizes(), torch::IntArrayRef({2, 2, 2})); } TEST_F(FunctionalTest, MaxPool3d) { auto x = torch::ones({2, 5, 5, 5}); auto y = F::max_pool3d(x, MaxPool3dOptions(3).stride(2)); ASSERT_EQ(y.ndimension(), 4); ASSERT_TRUE(torch::allclose(y, torch::ones({2, 2, 2, 2}))); ASSERT_EQ(y.sizes(), torch::IntArrayRef({2, 2, 2, 2})); } TEST_F(FunctionalTest, AvgPool1d) { auto x = torch::ones({1, 1, 5}); auto y = F::avg_pool1d(x, AvgPool1dOptions(3).stride(2)); ASSERT_EQ(y.ndimension(), 3); ASSERT_TRUE(torch::allclose(y, torch::ones({1, 1, 2}))); ASSERT_EQ(y.sizes(), torch::IntArrayRef({1, 1, 2})); } TEST_F(FunctionalTest, AvgPool2d) { auto x = torch::ones({2, 5, 5}); auto y = F::avg_pool2d(x, AvgPool2dOptions(3).stride(2)); ASSERT_EQ(y.ndimension(), 3); ASSERT_TRUE(torch::allclose(y, torch::ones({2, 2, 2}))); ASSERT_EQ(y.sizes(), torch::IntArrayRef({2, 2, 2})); } TEST_F(FunctionalTest, AvgPool3d) { auto x = torch::ones({2, 5, 5, 5}); auto y = F::avg_pool3d(x, AvgPool3dOptions(3).stride(2)); ASSERT_EQ(y.ndimension(), 4); ASSERT_TRUE(torch::allclose(y, torch::ones({2, 2, 2, 2}))); ASSERT_EQ(y.sizes(), torch::IntArrayRef({2, 2, 2, 2})); } TEST_F(FunctionalTest, CosineSimilarity) { auto input1 = torch::tensor({{1, 2, 3}, {4, 5, 6}}, torch::kFloat); auto input2 = torch::tensor({{1, 8, 3}, {2, 1, 6}}, torch::kFloat); auto output = F::cosine_similarity(input1, input2, CosineSimilarityOptions().dim(1)); auto expected = torch::tensor({0.8078, 0.8721}, torch::kFloat); ASSERT_TRUE(output.allclose(expected, 1e-04)); } TEST_F(FunctionalTest, PairwiseDistance) { auto input1 = torch::tensor({{1, 2, 3}, {4, 5, 6}}, torch::kFloat); auto input2 = torch::tensor({{1, 8, 3}, {2, 1, 6}}, torch::kFloat); auto output = F::pairwise_distance(input1, input2, PairwiseDistanceOptions(1)); auto expected = torch::tensor({6, 6}, torch::kFloat); ASSERT_TRUE(output.allclose(expected)); } TEST_F(FunctionalTest, PDist) { { auto input = torch::tensor({{-1.0, -5.0, -1.0}, {2.0, 4.0, 6.0}}); auto output = F::pdist(input); auto expected = torch::tensor({11.7898}); ASSERT_TRUE(output.allclose(expected)); } { auto input = torch::tensor({{1.0, -1.0}, {1.0, 3.0}, {3.0, 3.0}}); auto output = F::pdist(input, 1.5); auto expected = torch::tensor({4.0, 4.8945, 2.0}); ASSERT_TRUE(output.allclose(expected)); } } TEST_F(FunctionalTest, AdaptiveMaxPool1d) { auto x = torch::ones({1, 1, 5}); auto y = F::adaptive_max_pool1d(x, AdaptiveMaxPool1dOptions(3)); ASSERT_EQ(y.ndimension(), 3); ASSERT_TRUE(torch::allclose(y, torch::ones({1, 1, 3}))); ASSERT_EQ(y.sizes(), torch::IntArrayRef({1, 1, 3})); } TEST_F(FunctionalTest, AdaptiveMaxPool2d) { auto x = torch::ones({2, 5, 5}); auto y = F::adaptive_max_pool2d(x, AdaptiveMaxPool2dOptions(3)); ASSERT_EQ(y.ndimension(), 3); ASSERT_TRUE(torch::allclose(y, torch::ones({2, 3, 3}))); ASSERT_EQ(y.sizes(), torch::IntArrayRef({2, 3, 3})); } TEST_F(FunctionalTest, AdaptiveMaxPool3d) { auto x = torch::ones({2, 5, 5, 5}); auto y = F::adaptive_max_pool3d(x, AdaptiveMaxPool3dOptions(3)); ASSERT_EQ(y.ndimension(), 4); ASSERT_TRUE(torch::allclose(y, torch::ones({2, 3, 3, 3}))); ASSERT_EQ(y.sizes(), torch::IntArrayRef({2, 3, 3, 3})); } TEST_F(FunctionalTest, AdaptiveAvgPool1d) { auto x = torch::ones({1, 1, 5}); auto y = F::adaptive_avg_pool1d(x, AdaptiveAvgPool1dOptions(3)); ASSERT_EQ(y.ndimension(), 3); ASSERT_TRUE(torch::allclose(y, torch::ones({1, 1, 3}))); ASSERT_EQ(y.sizes(), torch::IntArrayRef({1, 1, 3})); } TEST_F(FunctionalTest, AdaptiveAvgPool2d) { auto x = torch::ones({2, 5, 5}); auto y = F::adaptive_avg_pool2d(x, AdaptiveAvgPool2dOptions(3)); ASSERT_EQ(y.ndimension(), 3); ASSERT_TRUE(torch::allclose(y, torch::ones({2, 3, 3}))); ASSERT_EQ(y.sizes(), torch::IntArrayRef({2, 3, 3})); } TEST_F(FunctionalTest, AdaptiveAvgPool3d) { auto x = torch::ones({2, 5, 5, 5}); auto y = F::adaptive_avg_pool3d(x, AdaptiveAvgPool3dOptions(3)); ASSERT_EQ(y.ndimension(), 4); ASSERT_TRUE(torch::allclose(y, torch::ones({2, 3, 3, 3}))); ASSERT_EQ(y.sizes(), torch::IntArrayRef({2, 3, 3, 3})); } TEST_F(FunctionalTest, HingeEmbeddingLoss) { auto input = torch::tensor({{2, 22, 4}, {20, 10, 0}}, torch::kFloat); auto target = torch::tensor({{2, 6, 4}, {1, 10, 0}}, torch::kFloat); auto output = F::hinge_embedding_loss( input, target, HingeEmbeddingLossOptions().margin(2)); auto expected = torch::tensor({10}, torch::kFloat); ASSERT_TRUE(output.allclose(expected)); } TEST_F(FunctionalTest, MaxUnpool1d) { auto x = torch::tensor({{{2, 4, 5}}}, torch::requires_grad()); auto indices = torch::tensor({{{1, 3, 4}}}, torch::kLong); auto y = F::max_unpool1d(x, indices, MaxUnpool1dOptions(3)); ASSERT_EQ(y.ndimension(), 3); ASSERT_TRUE(torch::allclose( y, torch::tensor({{{0, 2, 0, 4, 5, 0, 0, 0, 0}}}, torch::kFloat))); ASSERT_EQ(y.sizes(), torch::IntArrayRef({1, 1, 9})); x = torch::tensor({{{2, 4, 5}}}, torch::requires_grad()); indices = torch::tensor({{{1, 3, 4}}}, torch::kLong); y = F::max_unpool1d( x, indices, MaxUnpool1dOptions(3), c10::IntArrayRef({1, 1, 9})); ASSERT_EQ(y.ndimension(), 3); ASSERT_TRUE(torch::allclose( y, torch::tensor({{{0, 2, 0, 4, 5, 0, 0, 0, 0}}}, torch::kFloat))); ASSERT_EQ(y.sizes(), torch::IntArrayRef({1, 1, 9})); x = torch::tensor({{{2, 4, 5}}}, torch::requires_grad()); indices = torch::tensor({{{1, 3, 4}}}, torch::kLong); y = F::max_unpool1d(x, indices, MaxUnpool1dOptions(3).stride(2).padding(1)); ASSERT_EQ(y.ndimension(), 3); ASSERT_TRUE( torch::allclose(y, torch::tensor({{{0, 2, 0, 4, 5}}}, torch::kFloat))); ASSERT_EQ(y.sizes(), torch::IntArrayRef({1, 1, 5})); } TEST_F(FunctionalTest, MaxUnpool2d) { auto indices = torch::tensor({ {{{ 6, 8, 9}, {16, 18, 19}, {21, 23, 24}}}, {{{ 6, 8, 9}, {16, 18, 19}, {21, 23, 24}}}}, torch::kLong); auto x = torch::tensor({ {{{ 6, 8, 9}, {16, 18, 19}, {21, 23, 24}}}, {{{31, 33, 34}, {41, 43, 44}, {46, 48, 49}}}}, torch::requires_grad()); auto y = F::max_unpool2d(x, indices, MaxUnpool2dOptions(3).stride(2).padding(1)); ASSERT_EQ(y.dim(), 4); ASSERT_TRUE(torch::allclose(y, torch::tensor( {{{{ 0, 0, 0, 0, 0}, { 0, 6, 0, 8, 9}, { 0, 0, 0, 0, 0}, { 0, 16, 0, 18, 19}, { 0, 21, 0, 23, 24}}}, {{{ 0, 0, 0, 0, 0}, { 0, 31, 0, 33, 34}, { 0, 0, 0, 0, 0}, { 0, 41, 0, 43, 44}, { 0, 46, 0, 48, 49}}}} , torch::kFloat))); ASSERT_EQ(y.sizes(), torch::IntArrayRef({2, 1, 5, 5})); } TEST_F(FunctionalTest, ELU) { const auto size = 3; for (const auto inplace : {false, true}) { for (const auto alpha : {0.0, 0.42, 1.0, 4.2, 42.42}) { auto x = torch::linspace(-10.0, 10.0, size * size * size); x.resize_({size, size, size}); auto y_exp = torch::max(torch::zeros_like(x), x) + torch::min(torch::zeros_like(x), alpha * (torch::exp(x) - 1.0)); auto y = F::elu(x, ELUOptions().alpha(alpha).inplace(inplace)); ASSERT_EQ(y.ndimension(), 3); ASSERT_EQ(y.sizes(), torch::IntArrayRef({size, size, size})); ASSERT_TRUE(torch::allclose(y, y_exp)); if (inplace) { ASSERT_TRUE(torch::allclose(x, y_exp)); } } } } TEST_F(FunctionalTest, Hardshrink) { const auto size = 3; for (const auto lambda : {-4.2, -1.0, -0.42, 0.0, 0.42, 1.0, 4.2, 42.42}) { auto x = torch::linspace(-10.0, 10.0, size * size * size); x.resize_({size, size, size}).set_requires_grad(true); auto y = F::hardshrink(x, HardshrinkOptions().lambda(lambda)); torch::Tensor s = y.sum(); s.backward(); ASSERT_EQ(s.ndimension(), 0); ASSERT_EQ(y.ndimension(), 3); ASSERT_EQ(y.sizes(), torch::IntArrayRef({size, size, size})); auto y_exp = (x.abs() > lambda) * x; ASSERT_TRUE(torch::allclose(y, y_exp)); } } TEST_F(FunctionalTest, OneHot) { { // Test #1 auto x = torch::arange(0, 5, torch::kLong); auto y = F::one_hot(x % 3); auto expected = torch::tensor( {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}, {1, 0, 0}, {0, 1, 0}}, torch::kLong); ASSERT_EQ(y.ndimension(), 2); ASSERT_TRUE(torch::allclose(y, expected)); ASSERT_EQ(y.sizes(), torch::IntArrayRef({5, 3})); } { // Test #2 auto x = torch::arange(0, 5, torch::kLong); auto y = F::one_hot(x % 3, 5); auto expected = torch::tensor( {{1, 0, 0, 0, 0}, {0, 1, 0, 0, 0}, {0, 0, 1, 0, 0}, {1, 0, 0, 0, 0}, {0, 1, 0, 0, 0}}, torch::kLong); ASSERT_EQ(y.ndimension(), 2); ASSERT_TRUE(torch::allclose(y, expected)); ASSERT_EQ(y.sizes(), torch::IntArrayRef({5, 5})); } { // Test #3 auto x = torch::arange(0, 6, torch::kLong); auto y = F::one_hot(x.view(torch::IntArrayRef({3, 2})) % 3); auto expected = torch::tensor( {{{1, 0, 0}, {0, 1, 0}}, {{0, 0, 1}, {1, 0, 0}}, {{0, 1, 0}, {0, 0, 1}}}, torch::kLong); ASSERT_EQ(y.ndimension(), 3); ASSERT_TRUE(torch::allclose(y, expected)); ASSERT_EQ(y.sizes(), torch::IntArrayRef({3, 2, 3})); } }