/
githubmirror
/
incubator-mxnet
Обзор
Документация
Войти
/
githubmirror
/
incubator-mxnet
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
tests/cpp/operator/krprod_test.cc
443 строки
13 KB
mozga
[master][clang-format] Re-format cc. .h. .cu files; cond. (#20704)
19 ноя 2021, 11:27
Не верифицирован
19 ноя 2021, 11:27
1add250
Код
Авторство
О чём код?
/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ /*! * \file krprod_test.cc * \brief Test Khatri-Rao product * \author Jencir Lee */ #include <vector> #include <random> #include <cmath> #include "gtest/gtest.h" #include "operator/contrib/krprod.h" namespace mxnet { namespace op { using namespace mshadow; using namespace mshadow::expr; using DType = double; #define EXPECT_DOUBLE_EQ_MATRIX(expected, actual) \ { \ for (int i = 0; i < static_cast<int>(actual.size(0)); ++i) \ for (int j = 0; j < static_cast<int>(actual.size(1)); ++j) \ EXPECT_LE(std::abs(actual[i][j] - expected[i][j]), 1e-10); \ } TEST(row_wise_kronecker, OneInputMatrix) { // Input matrices of shape (2, 4) which is also the expected result DType mat[8]{1, 2, 3, 4, 5, 6, 7, 8}; // Make input tensors std::vector<Tensor<cpu, 2, DType> > ts_arr; ts_arr.emplace_back(mat, Shape2(2, 4), 4, nullptr); // Compute Khatri-Rao product Tensor<cpu, 2, DType> result(Shape2(2, 4)); AllocSpace(&result); row_wise_kronecker(result, ts_arr); // Check against expected result EXPECT_DOUBLE_EQ_MATRIX(ts_arr[0], result); FreeSpace(&result); } TEST(row_wise_kronecker, TwoInputMatrices) { // Input matrices of shape (2, 3) and (2, 4) DType mat1[6]{1, 2, 3, 4, 5, 6}; DType mat2[8]{1, 2, 3, 4, 5, 6, 7, 8}; // Expect result of shape (2, 12) DType expected[24]{1, 2, 3, 4, 2, 4, 6, 8, 3, 6, 9, 12, 20, 24, 28, 32, 25, 30, 35, 40, 30, 36, 42, 48}; // Make input tensors std::vector<Tensor<cpu, 2, DType> > ts_arr; ts_arr.emplace_back(mat1, Shape2(2, 3), 3, nullptr); ts_arr.emplace_back(mat2, Shape2(2, 4), 4, nullptr); // Compute Khatri-Rao product Tensor<cpu, 2, DType> result(Shape2(2, 12)); AllocSpace(&result); row_wise_kronecker(result, ts_arr); // Check against expected result Tensor<cpu, 2, DType> ts_expected(expected, Shape2(2, 12), 12, nullptr); EXPECT_DOUBLE_EQ_MATRIX(ts_expected, result); FreeSpace(&result); } TEST(row_wise_kronecker, TwoInputMatrices2) { // Input matrices of shape (2, 3) and (2, 1) DType mat1[6]{1, 2, 3, 4, 5, 6}; DType mat2[2]{1, 2}; // Expect result of shape (2, 3) DType expected[6]{1, 2, 3, 8, 10, 12}; // Make input tensors std::vector<Tensor<cpu, 2, DType> > ts_arr; ts_arr.emplace_back(mat1, Shape2(2, 3), 3, nullptr); ts_arr.emplace_back(mat2, Shape2(2, 1), 1, nullptr); // Compute Khatri-Rao product Tensor<cpu, 2, DType> result(Shape2(2, 3)); AllocSpace(&result); row_wise_kronecker(result, ts_arr); // Check against expected result Tensor<cpu, 2, DType> ts_expected(expected, Shape2(2, 3), 3, nullptr); EXPECT_DOUBLE_EQ_MATRIX(ts_expected, result); FreeSpace(&result); } TEST(row_wise_kronecker, ThreeInputMatrices) { std::default_random_engine generator; std::uniform_int_distribution<int> distribution(1, 6); Tensor<cpu, 2, DType> in1(Shape2(3, 4)), in2(Shape2(3, 2)), in3(Shape2(3, 3)), kr12(Shape2(3, 8)), kr13(Shape2(3, 24)), result(Shape2(3, 24)); AllocSpace(&in1); AllocSpace(&in2); AllocSpace(&in3); AllocSpace(&kr12); AllocSpace(&kr13); AllocSpace(&result); std::vector<Tensor<cpu, 2, DType> > ts_arr{in1, in2, in3}; for (auto& in : ts_arr) { for (int i = 0; i < static_cast<int>(in.size(0)); ++i) for (int j = 0; j < static_cast<int>(in.size(1)); ++j) in[i][j] = distribution(generator); } row_wise_kronecker(kr12, {in1, in2}); row_wise_kronecker(kr13, {kr12, in3}); row_wise_kronecker(result, ts_arr); EXPECT_DOUBLE_EQ_MATRIX(kr13, result); for (auto& in : ts_arr) FreeSpace(&in); FreeSpace(&kr12); FreeSpace(&kr13); FreeSpace(&result); } TEST(row_wise_kronecker, ThreeInputMatrices2) { std::default_random_engine generator; std::uniform_int_distribution<int> distribution(1, 6); Tensor<cpu, 2, DType> in1(Shape2(3, 4)), in2(Shape2(3, 1)), in3(Shape2(3, 3)), kr12(Shape2(3, 4)), kr13(Shape2(3, 12)), result(Shape2(3, 12)); AllocSpace(&in1); AllocSpace(&in2); AllocSpace(&in3); AllocSpace(&kr12); AllocSpace(&kr13); AllocSpace(&result); std::vector<Tensor<cpu, 2, DType> > ts_arr{in1, in2, in3}; for (auto& in : ts_arr) { for (int i = 0; i < static_cast<int>(in.size(0)); ++i) for (int j = 0; j < static_cast<int>(in.size(1)); ++j) in[i][j] = distribution(generator); } row_wise_kronecker(kr12, {in1, in2}); row_wise_kronecker(kr13, {kr12, in3}); row_wise_kronecker(result, ts_arr); EXPECT_DOUBLE_EQ_MATRIX(kr13, result); for (auto& in : ts_arr) FreeSpace(&in); FreeSpace(&kr12); FreeSpace(&kr13); FreeSpace(&result); } TEST(row_wise_kronecker, ThreeInputMatrices3) { std::default_random_engine generator; std::uniform_int_distribution<int> distribution(1, 6); Tensor<cpu, 2, DType> in1(Shape2(3, 1)), in2(Shape2(3, 4)), in3(Shape2(3, 3)), kr12(Shape2(3, 4)), kr13(Shape2(3, 12)), result(Shape2(3, 12)); AllocSpace(&in1); AllocSpace(&in2); AllocSpace(&in3); AllocSpace(&kr12); AllocSpace(&kr13); AllocSpace(&result); std::vector<Tensor<cpu, 2, DType> > ts_arr{in1, in2, in3}; for (auto& in : ts_arr) { for (int i = 0; i < static_cast<int>(in.size(0)); ++i) for (int j = 0; j < static_cast<int>(in.size(1)); ++j) in[i][j] = distribution(generator); } row_wise_kronecker(kr12, {in1, in2}); row_wise_kronecker(kr13, {kr12, in3}); row_wise_kronecker(result, ts_arr); EXPECT_DOUBLE_EQ_MATRIX(kr13, result); for (auto& in : ts_arr) FreeSpace(&in); FreeSpace(&kr12); FreeSpace(&kr13); FreeSpace(&result); } TEST(row_wise_kronecker, FourInputMatrices) { std::default_random_engine generator; std::uniform_int_distribution<int> distribution(1, 6); Tensor<cpu, 2, DType> in1(Shape2(3, 47)), in2(Shape2(3, 1)), in3(Shape2(3, 5)), in4(Shape2(3, 2173)), kr12(Shape2(3, 47)), kr13(Shape2(3, 47 * 5)), kr14(Shape2(3, 47 * 5 * 2173)), result(Shape2(3, 47 * 5 * 2173)); AllocSpace(&in1); AllocSpace(&in2); AllocSpace(&in3); AllocSpace(&in4); AllocSpace(&kr12); AllocSpace(&kr13); AllocSpace(&kr14); AllocSpace(&result); std::vector<Tensor<cpu, 2, DType> > ts_arr{in1, in2, in3, in4}; for (auto& in : ts_arr) { for (int i = 0; i < static_cast<int>(in.size(0)); ++i) for (int j = 0; j < static_cast<int>(in.size(1)); ++j) in[i][j] = distribution(generator); } row_wise_kronecker(kr12, {in1, in2}); row_wise_kronecker(kr13, {kr12, in3}); row_wise_kronecker(kr14, {kr13, in4}); row_wise_kronecker(result, ts_arr); EXPECT_DOUBLE_EQ_MATRIX(kr14, result); for (auto& in : ts_arr) FreeSpace(&in); FreeSpace(&kr12); FreeSpace(&kr13); FreeSpace(&kr14); FreeSpace(&result); } #if MXNET_USE_LAPACK == 1 TEST(khatri_rao, OneInputMatrix) { // Input matrices of shape (2, 4) which is also the expected result DType mat[8]{1, 2, 3, 4, 5, 6, 7, 8}; // Make input tensors std::vector<Tensor<cpu, 2, DType> > ts_arr; ts_arr.emplace_back(mat, Shape2(2, 4), 4, nullptr); // Compute Khatri-Rao product Tensor<cpu, 2, DType> result(Shape2(2, 4)); AllocSpace(&result); khatri_rao(result, ts_arr); // Check against expected result EXPECT_DOUBLE_EQ_MATRIX(ts_arr[0], result); FreeSpace(&result); } TEST(khatri_rao, TwoInputMatrices) { // Input matrices of shape (3, 2) and (4, 2) DType mat1[6]{1, 4, 2, 5, 3, 6}; DType mat2[8]{1, 5, 2, 6, 3, 7, 4, 8}; // Expect result of shape (12, 2) DType expected[24]{1, 20, 2, 24, 3, 28, 4, 32, 2, 25, 4, 30, 6, 35, 8, 40, 3, 30, 6, 36, 9, 42, 12, 48}; // Make input tensors std::vector<Tensor<cpu, 2, DType> > ts_arr; ts_arr.emplace_back(mat1, Shape2(3, 2), 2, nullptr); ts_arr.emplace_back(mat2, Shape2(4, 2), 2, nullptr); // Compute Khatri-Rao product Tensor<cpu, 2, DType> result(Shape2(12, 2)); AllocSpace(&result); khatri_rao(result, ts_arr); // Check against expected result Tensor<cpu, 2, DType> ts_expected(expected, Shape2(12, 2), 2, nullptr); EXPECT_DOUBLE_EQ_MATRIX(ts_expected, result); FreeSpace(&result); } TEST(khatri_rao, ThreeInputMatrices) { std::default_random_engine generator; std::uniform_int_distribution<int> distribution(1, 6); Tensor<cpu, 2, DType> in1(Shape2(4, 3)), in2(Shape2(2, 3)), in3(Shape2(3, 3)), kr12(Shape2(8, 3)), kr13(Shape2(24, 3)), result(Shape2(24, 3)); AllocSpace(&in1); AllocSpace(&in2); AllocSpace(&in3); AllocSpace(&kr12); AllocSpace(&kr13); AllocSpace(&result); std::vector<Tensor<cpu, 2, DType> > ts_arr{in1, in2, in3}; for (auto& in : ts_arr) { for (int i = 0; i < static_cast<int>(in.size(0)); ++i) for (int j = 0; j < static_cast<int>(in.size(1)); ++j) in[i][j] = distribution(generator); } khatri_rao(kr12, {in1, in2}); khatri_rao(kr13, {kr12, in3}); khatri_rao(result, ts_arr); EXPECT_DOUBLE_EQ_MATRIX(kr13, result); for (auto& in : ts_arr) FreeSpace(&in); FreeSpace(&kr12); FreeSpace(&kr13); FreeSpace(&result); } TEST(inv_khatri_rao, OneInputMatrixTransposed) { DType mat[8]{1, 2, 3, 4, 5, 6, 7, 8}; // Make input tensors std::vector<Tensor<cpu, 2, DType> > ts_arr; ts_arr.emplace_back(mat, Shape2(2, 4), 4, nullptr); // Compute inverse Khatri-Rao product Tensor<cpu, 2, DType> inv_kr(Shape2(2, 4)); AllocSpace(&inv_kr); inv_khatri_rao(inv_kr, ts_arr, true); // Check against expected result Tensor<cpu, 2, DType> actual_dot(Shape2(2, 4)); AllocSpace(&actual_dot); actual_dot = implicit_dot(implicit_dot(inv_kr, ts_arr[0].T()), inv_kr); EXPECT_DOUBLE_EQ_MATRIX(inv_kr, actual_dot); FreeSpace(&inv_kr); FreeSpace(&actual_dot); } TEST(inv_khatri_rao, TwoInputMatrices) { // Input matrices of shape (3, 2) and (4, 2) DType mat1[6]{1, 4, 2, 5, 3, 6}; DType mat2[8]{1, 5, 2, 6, 3, 7, 4, 8}; // Make input tensors std::vector<Tensor<cpu, 2, DType> > ts_arr; ts_arr.emplace_back(mat1, Shape2(3, 2), 2, nullptr); ts_arr.emplace_back(mat2, Shape2(4, 2), 2, nullptr); // Compute inverse Khatri-Rao product Tensor<cpu, 2, DType> inv_kr(Shape2(2, 12)), kr(Shape2(12, 2)); AllocSpace(&inv_kr); AllocSpace(&kr); inv_khatri_rao(inv_kr, ts_arr, false); khatri_rao(kr, ts_arr); // Check against expected result Tensor<cpu, 2, DType> actual_dot(Shape2(2, 12)); AllocSpace(&actual_dot); actual_dot = implicit_dot(implicit_dot(inv_kr, kr), inv_kr); EXPECT_DOUBLE_EQ_MATRIX(inv_kr, actual_dot); FreeSpace(&inv_kr); FreeSpace(&kr); FreeSpace(&actual_dot); } TEST(inv_khatri_rao, TwoInputMatricesTransposed) { // Transposed input matrices of shape (2, 3) and (2, 4) DType mat1[6]{1, 2, 3, 4, 5, 6}; DType mat2[8]{1, 2, 3, 4, 5, 6, 7, 8}; // Make input tensors std::vector<Tensor<cpu, 2, DType> > ts_arr; ts_arr.emplace_back(mat1, Shape2(2, 3), 3, nullptr); ts_arr.emplace_back(mat2, Shape2(2, 4), 4, nullptr); // Compute invser Khatri-Rao product Tensor<cpu, 2, DType> inv_kr(Shape2(2, 12)), kr_t(Shape2(2, 12)); AllocSpace(&inv_kr); AllocSpace(&kr_t); inv_khatri_rao(inv_kr, ts_arr, true); row_wise_kronecker(kr_t, ts_arr); // Check against expected result Tensor<cpu, 2, DType> actual_dot(Shape2(2, 12)); AllocSpace(&actual_dot); actual_dot = implicit_dot(implicit_dot(inv_kr, kr_t.T()), inv_kr); EXPECT_DOUBLE_EQ_MATRIX(inv_kr, actual_dot); FreeSpace(&inv_kr); FreeSpace(&kr_t); FreeSpace(&actual_dot); } TEST(inv_khatri_rao, ThreeInputMatricesTranposed) { // Randomly initialise the transposed input matrices std::default_random_engine generator; std::uniform_int_distribution<int> distribution(1, 6); Tensor<cpu, 2, DType> in1(Shape2(3, 4)), in2(Shape2(3, 2)), in3(Shape2(3, 3)); AllocSpace(&in1); AllocSpace(&in2); AllocSpace(&in3); std::vector<Tensor<cpu, 2, DType> > ts_arr{in1, in2, in3}; for (auto& in : ts_arr) { for (int i = 0; i < static_cast<int>(in.size(0)); ++i) for (int j = 0; j < static_cast<int>(in.size(1)); ++j) in[i][j] = distribution(generator); } // Compute inv_kr & kr Tensor<cpu, 2, DType> inv_kr(Shape2(3, 24)), kr_t(Shape2(3, 24)); AllocSpace(&inv_kr); AllocSpace(&kr_t); inv_khatri_rao(inv_kr, ts_arr, true); row_wise_kronecker(kr_t, ts_arr); // Check dot result Tensor<cpu, 2, DType> actual_dot(Shape2(3, 24)); AllocSpace(&actual_dot); actual_dot = implicit_dot(implicit_dot(inv_kr, kr_t.T()), inv_kr); EXPECT_DOUBLE_EQ_MATRIX(inv_kr, actual_dot); for (auto& in : ts_arr) FreeSpace(&in); FreeSpace(&inv_kr); FreeSpace(&kr_t); FreeSpace(&actual_dot); } #endif // MXNET_USE_LAPACK == 1 } // namespace op } // namespace mxnet