diff --git a/CMake/TestStaticSTB.cmake b/CMake/TestStaticSTB.cmake new file mode 100644 index 0000000000..b4b76adc63 --- /dev/null +++ b/CMake/TestStaticSTB.cmake @@ -0,0 +1,42 @@ +# Author: Omar Shrit + +#[=======================================================================[.rst: +TestForSTB +---------- + +Test to verify if the available version of STB contains a working static +implementation that can be used from multiple translation units. + +:: + + CMAKE_HAS_WORKING_STATIC_STB - defined by the results +#]=======================================================================] + +if(NOT DEFINED CMAKE_HAS_WORKING_STATIC_STB) + message(STATUS "Check that STB static implementation mode links correctly...") + try_compile(CMAKE_HAS_WORKING_STATIC_STB + ${CMAKE_BINARY_DIR}/CMakeFiles/CMakeTmp/ + SOURCES + ${CMAKE_SOURCE_DIR}/CMake/stb/main.cpp + ${CMAKE_SOURCE_DIR}/CMake/stb/a.cpp + ${CMAKE_SOURCE_DIR}/CMake/stb/b.cpp + CMAKE_FLAGS "-DINCLUDE_DIRECTORIES=${STB_IMAGE_INCLUDE_DIR}" + OUTPUT_VARIABLE out) + if (CMAKE_HAS_WORKING_STATIC_STB) + message(STATUS "Check that STB static implementation mode links " + "correctly... success") + set(CMAKE_HAS_WORKING_STATIC_STB 1 CACHE INTERNAL + "Does STB static implementation mode link correctly") + file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log + "Determining if STB's static implementation can link correctly passed " + "with the following output:\n${out}\n\n") + else () + message(STATUS "Check that STB static implementation mode links " + "correctly... fail") + set(CMAKE_HAS_WORKING_STATIC_STB 0 CACHE INTERNAL + "Does STB static implementation mode link correctly") + file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log + "Determining if STB's static implementation can link correctly failed " + "with the following output:\n${out}\n\n") + endif () +endif() diff --git a/CMake/stb/a.cpp b/CMake/stb/a.cpp new file mode 100644 index 0000000000..4a99350577 --- /dev/null +++ b/CMake/stb/a.cpp @@ -0,0 +1,15 @@ +#include "a.hpp" + +// Include the static implementation of all STB functions. +#define STB_IMAGE_STATIC +#define STB_IMAGE_IMPLEMENTATION +#define STB_IMAGE_WRITE_STATIC +#define STB_IMAGE_WRITE_IMPLEMENTATION + +#include +#include + +void A::A() +{ + // Do nothing, just to check if the STB library is a working version. +} diff --git a/CMake/stb/a.hpp b/CMake/stb/a.hpp new file mode 100644 index 0000000000..be30807b5e --- /dev/null +++ b/CMake/stb/a.hpp @@ -0,0 +1,10 @@ +#ifndef A_HPP +#define A_HPP + +namespace A { + +void A(); + +} + +#endif diff --git a/CMake/stb/b.cpp b/CMake/stb/b.cpp new file mode 100644 index 0000000000..a11a8f15e7 --- /dev/null +++ b/CMake/stb/b.cpp @@ -0,0 +1,15 @@ +#include "b.hpp" + +// Include the static implementation of all STB functions. +#define STB_IMAGE_STATIC +#define STB_IMAGE_IMPLEMENTATION +#define STB_IMAGE_WRITE_STATIC +#define STB_IMAGE_WRITE_IMPLEMENTATION + +#include +#include + +void B::B() +{ + // Do nothing, just to check if the STB library is a working version. +} diff --git a/CMake/stb/b.hpp b/CMake/stb/b.hpp new file mode 100644 index 0000000000..0a287e6b17 --- /dev/null +++ b/CMake/stb/b.hpp @@ -0,0 +1,10 @@ +#ifndef B_HPP +#define B_HPP + +namespace B { + +void B(); + +} + +#endif diff --git a/CMake/stb/main.cpp b/CMake/stb/main.cpp new file mode 100644 index 0000000000..02cf644606 --- /dev/null +++ b/CMake/stb/main.cpp @@ -0,0 +1,16 @@ +// The purpose of this file is to include STB's implementation in two separate +// translation units. One is a.cpp, and one is b.cpp. This file simply +// includes both of those, so that when we get to the linking phase, we will +// have to link both translation units. +// +// Some versions of STB fail to correctly define some functions as +// static---which will cause a linking failure. Thus, if this fails to +// compile, then mlpack's use of STB will fail. +#include "a.hpp" +#include "b.hpp" + +int main() +{ + A::A(); + B::B(); +} diff --git a/CMakeLists.txt b/CMakeLists.txt index 6756c0bacb..40a447b282 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -340,6 +340,15 @@ if (STB_IMAGE_FOUND) add_definitions(-DHAS_STB) set(STB_AVAILABLE "1") set(MLPACK_INCLUDE_DIRS ${MLPACK_INCLUDE_DIRS} "${STB_IMAGE_INCLUDE_DIR}") + + # Make sure that we can link STB in multiple translation units. + include(CMake/TestStaticSTB.cmake) + if (NOT CMAKE_HAS_WORKING_STATIC_STB) + message(FATAL_ERROR "STB implementations's static mode cannot link across " + "multiple translation units! Try upgrading your STB implementation, " + "or using the auto-downloader (set DOWNLOAD_DEPENDENCIES=ON in the " + "CMake configuration command.") + endif () endif() # Find ensmallen. diff --git a/src/mlpack/core/data/CMakeLists.txt b/src/mlpack/core/data/CMakeLists.txt index 33f0c23dab..0b83444c00 100644 --- a/src/mlpack/core/data/CMakeLists.txt +++ b/src/mlpack/core/data/CMakeLists.txt @@ -4,7 +4,7 @@ set(SOURCES dataset_mapper.hpp dataset_mapper_impl.hpp detect_file_type.hpp - detect_file_type.cpp + detect_file_type_impl.hpp extension.hpp format.hpp has_serialize.hpp @@ -14,7 +14,7 @@ set(SOURCES load_categorical_csv.hpp load.hpp load_image_impl.hpp - load_image.cpp + load_image.hpp load_model_impl.hpp load_vec_impl.hpp load_impl.hpp @@ -24,7 +24,8 @@ set(SOURCES normalize_labels_impl.hpp save.hpp save_impl.hpp - save_image.cpp + save_image.hpp + save_image_impl.hpp split_data.hpp string_algorithms.hpp imputer.hpp diff --git a/src/mlpack/core/data/detect_file_type.hpp b/src/mlpack/core/data/detect_file_type.hpp index 14a9fc4a6d..668a2c2433 100644 --- a/src/mlpack/core/data/detect_file_type.hpp +++ b/src/mlpack/core/data/detect_file_type.hpp @@ -25,7 +25,7 @@ namespace data { * * @param type Type to get the logical name of. */ -std::string GetStringType(const FileType& type); +inline std::string GetStringType(const FileType& type); /** * Given an istream, attempt to guess the file type. This is taken originally @@ -38,7 +38,7 @@ std::string GetStringType(const FileType& type); * * @param f Opened istream to look into to guess the file type. */ -FileType GuessFileType(std::istream& f); +inline FileType GuessFileType(std::istream& f); /** * Attempt to auto-detect the type of a file given its extension, and by @@ -53,8 +53,8 @@ FileType GuessFileType(std::istream& f); * @param filename Name of the file. * @return The detected file type. arma::file_type_unknown if unknown. */ -FileType AutoDetect(std::fstream& stream, - const std::string& filename); +inline FileType AutoDetect(std::fstream& stream, + const std::string& filename); /** * Return the type based only on the extension. @@ -62,9 +62,11 @@ FileType AutoDetect(std::fstream& stream, * @param filename Name of the file whose type we should detect. * @return Detected type of file. arma::file_type_unknown if unknown. */ -FileType DetectFromExtension(const std::string& filename); +inline FileType DetectFromExtension(const std::string& filename); } // namespace data } // namespace mlpack +#include "detect_file_type_impl.hpp" + #endif diff --git a/src/mlpack/core/data/detect_file_type.cpp b/src/mlpack/core/data/detect_file_type_impl.hpp similarity index 96% rename from src/mlpack/core/data/detect_file_type.cpp rename to src/mlpack/core/data/detect_file_type_impl.hpp index 0219f95074..afb6e7fbc0 100644 --- a/src/mlpack/core/data/detect_file_type.cpp +++ b/src/mlpack/core/data/detect_file_type_impl.hpp @@ -1,5 +1,5 @@ /** - * @file core/data/detect_file_type.cpp + * @file core/data/detect_file_type_impl.hpp * @author Conrad Sanderson * @author Ryan Curtin * @@ -24,7 +24,7 @@ namespace data { * * @param type Type to get the logical name of. */ -std::string GetStringType(const FileType& type) +inline std::string GetStringType(const FileType& type) { switch (type) { @@ -50,7 +50,7 @@ std::string GetStringType(const FileType& type) * * @param f Opened istream to look into to guess the file type. */ -FileType GuessFileType(std::istream& f) +inline FileType GuessFileType(std::istream& f) { f.clear(); const std::fstream::pos_type pos1 = f.tellg(); @@ -186,7 +186,7 @@ FileType GuessFileType(std::istream& f) * @param filename Name of the file. * @return The detected file type. */ -FileType AutoDetect(std::fstream& stream, const std::string& filename) +inline FileType AutoDetect(std::fstream& stream, const std::string& filename) { // Get the extension. std::string extension = Extension(filename); @@ -304,7 +304,7 @@ FileType AutoDetect(std::fstream& stream, const std::string& filename) * @param filename Name of the file whose type we should detect. * @return Detected type of file. */ -FileType DetectFromExtension(const std::string& filename) +inline FileType DetectFromExtension(const std::string& filename) { const std::string extension = Extension(filename); diff --git a/src/mlpack/core/data/image_info_impl.hpp b/src/mlpack/core/data/image_info_impl.hpp index 3040a38415..f963ae28d8 100644 --- a/src/mlpack/core/data/image_info_impl.hpp +++ b/src/mlpack/core/data/image_info_impl.hpp @@ -13,6 +13,23 @@ #ifndef MLPACK_CORE_DATA_IMAGE_INFO_IMPL_HPP #define MLPACK_CORE_DATA_IMAGE_INFO_IMPL_HPP +namespace mlpack { +namespace data { + +inline const std::vector LoadFileTypes() +{ + return std::vector({"jpg", "png", "tga", "bmp", "psd", "gif", + "hdr", "pic", "pnm", "jpeg"}); +} + +inline const std::vector SaveFileTypes() +{ + return std::vector({"jpg", "png", "tga", "bmp", "hdr"}); +} + +} +} + #ifdef HAS_STB // Compile this only if stb is present. // In case it hasn't been included yet. @@ -21,18 +38,12 @@ namespace mlpack { namespace data { -static const std::vector loadFileTypes({"jpg", "png", "tga", - "bmp", "psd", "gif", "hdr", "pic", "pnm", "jpeg"}); - -static const std::vector saveFileTypes({"jpg", "png", "tga", - "bmp", "hdr"}); - inline bool ImageFormatSupported(const std::string& fileName, const bool save) { if (save) { // Iterate over all supported file types that can be saved. - for (auto extension : saveFileTypes) + for (auto extension : SaveFileTypes()) { if (extension == Extension(fileName)) return true; @@ -41,7 +52,7 @@ inline bool ImageFormatSupported(const std::string& fileName, const bool save) else { // Iterate over all supported file types that can be loaded. - for (auto extension : loadFileTypes) + for (auto extension : LoadFileTypes()) { if (extension == Extension(fileName)) return true; diff --git a/src/mlpack/core/data/load.hpp b/src/mlpack/core/data/load.hpp index bd0fd7a066..195838affe 100644 --- a/src/mlpack/core/data/load.hpp +++ b/src/mlpack/core/data/load.hpp @@ -20,10 +20,11 @@ #include "format.hpp" #include "dataset_mapper.hpp" +#include "detect_file_type.hpp" #include "image_info.hpp" #include "load_csv.hpp" #include "load_arff.hpp" -#include "detect_file_type.hpp" +#include "load_image.hpp" namespace mlpack { namespace data /** Functions to load and save matrices and models. */ { @@ -250,46 +251,6 @@ bool Load(const std::string& filename, const bool fatal = false, format f = format::autodetect); -/** - * Image load/save interfaces. - */ - -/** - * Load the image file into the given matrix. - * - * @param filename Name of the image file. - * @param matrix Matrix to load the image into. - * @param info An object of ImageInfo class. - * @param fatal If an error should be reported as fatal (default false). - * @return Boolean value indicating success or failure of load. - */ -template -bool Load(const std::string& filename, - arma::Mat& matrix, - ImageInfo& info, - const bool fatal = false); - -/** - * Load the image file into the given matrix. - * - * @param files A vector consisting of filenames. - * @param matrix Matrix to save the image from. - * @param info An object of ImageInfo class. - * @param fatal If an error should be reported as fatal (default false). - * @return Boolean value indicating success or failure of load. - */ -template -bool Load(const std::vector& files, - arma::Mat& matrix, - ImageInfo& info, - const bool fatal = false); - -// Implementation found in load_image.cpp. -bool LoadImage(const std::string& filename, - arma::Mat& matrix, - ImageInfo& info, - const bool fatal = false); - } // namespace data } // namespace mlpack @@ -299,7 +260,5 @@ bool LoadImage(const std::string& filename, #include "load_model_impl.hpp" // Include implementation of Load() for vectors. #include "load_vec_impl.hpp" -// Include implementation of Load() for images. -#include "load_image_impl.hpp" #endif diff --git a/src/mlpack/core/data/load_image.cpp b/src/mlpack/core/data/load_image.cpp deleted file mode 100644 index a25e711796..0000000000 --- a/src/mlpack/core/data/load_image.cpp +++ /dev/null @@ -1,129 +0,0 @@ -/** - * @file core/data/load_image.cpp - * @author Mehul Kumar Nirala - * - * Implementation of image loading functionality via STB. - * - * mlpack is free software; you may redistribute it and/or modify it under the - * terms of the 3-clause BSD license. You should have received a copy of the - * 3-clause BSD license along with mlpack. If not, see - * http://www.opensource.org/licenses/BSD-3-Clause for more information. - */ -#include "load.hpp" -#include "image_info.hpp" - -#ifdef HAS_STB - -// The definition of STB_IMAGE_IMPLEMENTATION means that the implementation will -// be included here directly. -#define STB_IMAGE_STATIC -#define STB_IMAGE_IMPLEMENTATION - -#include - -namespace mlpack { -namespace data { - -bool LoadImage(const std::string& filename, - arma::Mat& matrix, - ImageInfo& info, - const bool fatal) -{ - unsigned char* image; - - if (!ImageFormatSupported(filename)) - { - std::ostringstream oss; - oss << "Load(): file type " << Extension(filename) << " not supported. "; - oss << "Currently it supports: "; - for (auto extension : loadFileTypes) - oss << " " << extension; - oss << "." << std::endl; - - if (fatal) - { - Log::Fatal << oss.str(); - } - else - { - Log::Warn << oss.str(); - } - - return false; - } - - // Temporary variables needed as stb_image.h supports int parameters. - int tempWidth, tempHeight, tempChannels; - - // For grayscale images. - if (info.Channels() == 1) - { - image = stbi_load(filename.c_str(), &tempWidth, &tempHeight, &tempChannels, - STBI_grey); - } - else - { - image = stbi_load(filename.c_str(), &tempWidth, &tempHeight, &tempChannels, - STBI_rgb); - } - - if (!image) - { - if (fatal) - { - Log::Fatal << "Load(): failed to load image '" << filename << "': " - << stbi_failure_reason() << std::endl; - } - else - { - Log::Warn << "Load(): failed to load image '" << filename << "': " - << stbi_failure_reason() << std::endl; - } - - return false; - } - - info.Width() = tempWidth; - info.Height() = tempHeight; - info.Channels() = tempChannels; - - // Copy image into armadillo Mat. - matrix = arma::Mat(image, info.Width() * info.Height() * - info.Channels(), 1, true, true); - - // Free the image pointer. - free(image); - return true; -} - -} // namespace data -} // namespace mlpack - -#else - -namespace mlpack { -namespace data { - -bool LoadImage(const std::string& /* filename */, - arma::Mat& /* matrix */, - ImageInfo& /* info */, - const bool fatal) -{ - if (fatal) - { - Log::Fatal << "Load(): mlpack was not compiled with STB support, so images " - << "cannot be loaded!" << std::endl; - } - else - { - Log::Warn << "Load(): mlpack was not compiled with STB support, so images " - << "cannot be loaded!" << std::endl; - } - - return false; -} - -} // namespace data -} // namespace mlpack - -#endif diff --git a/src/mlpack/core/data/load_image.hpp b/src/mlpack/core/data/load_image.hpp new file mode 100644 index 0000000000..36e4015302 --- /dev/null +++ b/src/mlpack/core/data/load_image.hpp @@ -0,0 +1,77 @@ +/** + * @file core/data/load_image.hpp + * @author Mehul Kumar Nirala + * + * Implementation of image loading functionality via STB. + * + * mlpack is free software; you may redistribute it and/or modify it under the + * terms of the 3-clause BSD license. You should have received a copy of the + * 3-clause BSD license along with mlpack. If not, see + * http://www.opensource.org/licenses/BSD-3-Clause for more information. + */ + +#ifndef MLPACK_CORE_DATA_LOAD_IMAGE_HPP +#define MLPACK_CORE_DATA_LOAD_IMAGE_HPP + +#include "image_info.hpp" + +#ifdef HAS_STB + +// The definition of STB_IMAGE_IMPLEMENTATION means that the implementation will +// be included here directly. +#define STB_IMAGE_STATIC +#define STB_IMAGE_IMPLEMENTATION +#include + +#endif // HAS_STB + +namespace mlpack { +namespace data { + +/** + * Image load/save interfaces. + */ + +/** + * Load the image file into the given matrix. + * + * @param filename Name of the image file. + * @param matrix Matrix to load the image into. + * @param info An object of ImageInfo class. + * @param fatal If an error should be reported as fatal (default false). + * @return Boolean value indicating success or failure of load. + */ +template +bool Load(const std::string& filename, + arma::Mat& matrix, + ImageInfo& info, + const bool fatal = false); + +/** + * Load the image file into the given matrix. + * + * @param files A vector consisting of filenames. + * @param matrix Matrix to save the image from. + * @param info An object of ImageInfo class. + * @param fatal If an error should be reported as fatal (default false). + * @return Boolean value indicating success or failure of load. + */ +template +bool Load(const std::vector& files, + arma::Mat& matrix, + ImageInfo& info, + const bool fatal = false); + +// Implementation found in load_image.hpp. +inline bool LoadImage(const std::string& filename, + arma::Mat& matrix, + ImageInfo& info, + const bool fatal = false); + +} // namespace data +} // namespace mlpack + +// Include implementation of Load() for images. +#include "load_image_impl.hpp" + +#endif diff --git a/src/mlpack/core/data/load_image_impl.hpp b/src/mlpack/core/data/load_image_impl.hpp index 9a757838b9..fe7e4c8519 100644 --- a/src/mlpack/core/data/load_image_impl.hpp +++ b/src/mlpack/core/data/load_image_impl.hpp @@ -2,19 +2,19 @@ * @file core/data/load_image_impl.hpp * @author Mehul Kumar Nirala * - * An image loading utility implementation. + * An image loading utility implementation via STB. * * mlpack is free software; you may redistribute it and/or modify it under the * terms of the 3-clause BSD license. You should have received a copy of the * 3-clause BSD license along with mlpack. If not, see * http://www.opensource.org/licenses/BSD-3-Clause for more information. */ - #ifndef MLPACK_CORE_DATA_LOAD_IMAGE_IMPL_HPP #define MLPACK_CORE_DATA_LOAD_IMAGE_IMPL_HPP // In case it hasn't been included yet. -#include "load.hpp" +#include "load_image.hpp" +#include "image_info.hpp" namespace mlpack { namespace data { @@ -90,6 +90,104 @@ bool Load(const std::vector& files, return true; } +#ifdef HAS_STB + +inline bool LoadImage(const std::string& filename, + arma::Mat& matrix, + ImageInfo& info, + const bool fatal) +{ + unsigned char* image; + + if (!ImageFormatSupported(filename)) + { + std::ostringstream oss; + oss << "Load(): file type " << Extension(filename) << " not supported. "; + oss << "Currently it supports:"; + auto x = LoadFileTypes(); + for (auto extension : x) + oss << " " << extension; + oss << "." << std::endl; + + if (fatal) + { + Log::Fatal << oss.str(); + } + else + { + Log::Warn << oss.str(); + } + + return false; + } + + // Temporary variables needed as stb_image.h supports int parameters. + int tempWidth, tempHeight, tempChannels; + + // For grayscale images. + if (info.Channels() == 1) + { + image = stbi_load(filename.c_str(), &tempWidth, &tempHeight, &tempChannels, + STBI_grey); + } + else + { + image = stbi_load(filename.c_str(), &tempWidth, &tempHeight, &tempChannels, + STBI_rgb); + } + + if (!image) + { + if (fatal) + { + Log::Fatal << "Load(): failed to load image '" << filename << "': " + << stbi_failure_reason() << std::endl; + } + else + { + Log::Warn << "Load(): failed to load image '" << filename << "': " + << stbi_failure_reason() << std::endl; + } + + return false; + } + + info.Width() = tempWidth; + info.Height() = tempHeight; + info.Channels() = tempChannels; + + // Copy image into armadillo Mat. + matrix = arma::Mat(image, info.Width() * info.Height() * + info.Channels(), 1, true, true); + + // Free the image pointer. + free(image); + return true; +} + +#else // HAS_STB + +inline bool LoadImage(const std::string& /* filename */, + arma::Mat& /* matrix */, + ImageInfo& /* info */, + const bool fatal) +{ + if (fatal) + { + Log::Fatal << "Load(): mlpack was not compiled with STB support, so images " + << "cannot be loaded!" << std::endl; + } + else + { + Log::Warn << "Load(): mlpack was not compiled with STB support, so images " + << "cannot be loaded!" << std::endl; + } + + return false; +} + +#endif + } // namespace data } // namespace mlpack diff --git a/src/mlpack/core/data/load_impl.hpp b/src/mlpack/core/data/load_impl.hpp index 226960a7e0..03993716db 100644 --- a/src/mlpack/core/data/load_impl.hpp +++ b/src/mlpack/core/data/load_impl.hpp @@ -16,13 +16,12 @@ // In case it hasn't already been included. #include "load.hpp" -#include #include +#include #include #include "extension.hpp" #include "detect_file_type.hpp" - #include "string_algorithms.hpp" namespace mlpack { diff --git a/src/mlpack/core/data/save.hpp b/src/mlpack/core/data/save.hpp index 19e11ee161..2faf180618 100644 --- a/src/mlpack/core/data/save.hpp +++ b/src/mlpack/core/data/save.hpp @@ -14,6 +14,7 @@ #ifndef MLPACK_CORE_DATA_SAVE_HPP #define MLPACK_CORE_DATA_SAVE_HPP +#include #include #include // Includes Armadillo. #include @@ -21,6 +22,7 @@ #include "format.hpp" #include "image_info.hpp" #include "detect_file_type.hpp" +#include "save_image.hpp" namespace mlpack { namespace data /** Functions to load and save matrices. */ { @@ -130,44 +132,6 @@ bool Save(const std::string& filename, const bool fatal = false, format f = format::autodetect); -/** - * Save the image file from the given matrix. - * - * @param filename Name of the image file. - * @param matrix Matrix to save the image from. - * @param info An object of ImageInfo class. - * @param fatal If an error should be reported as fatal (default false). - * @return Boolean value indicating success or failure of load. - */ -template -bool Save(const std::string& filename, - arma::Mat& matrix, - ImageInfo& info, - const bool fatal = false); - -/** - * Save the image file from the given matrix. - * - * @param files A vector consisting of filenames. - * @param matrix Matrix to save the image from. - * @param info An object of ImageInfo class. - * @param fatal If an error should be reported as fatal (default false). - * @return Boolean value indicating success or failure of load. - */ -template -bool Save(const std::vector& files, - arma::Mat& matrix, - ImageInfo& info, - const bool fatal = false); - -/** - * Helper function to save files. Implementation in save_image.cpp. - */ -bool SaveImage(const std::string& filename, - arma::Mat& image, - ImageInfo& info, - const bool fatal = false); - } // namespace data } // namespace mlpack diff --git a/src/mlpack/core/data/save_image.hpp b/src/mlpack/core/data/save_image.hpp new file mode 100644 index 0000000000..c23ec9a8c3 --- /dev/null +++ b/src/mlpack/core/data/save_image.hpp @@ -0,0 +1,72 @@ +/** + * @file core/data/save_image.hpp + * @author Ryan Curtin + * + * Implementation of save functionality. + * + * mlpack is free software; you may redistribute it and/or modify it under the + * terms of the 3-clause BSD license. You should have received a copy of the + * 3-clause BSD license along with mlpack. If not, see + * http://www.opensource.org/licenses/BSD-3-Clause for more information. + */ +#ifndef MLPACK_CORE_DATA_SAVE_IMAGE_HPP +#define MLPACK_CORE_DATA_SAVE_IMAGE_HPP + +#include "image_info.hpp" + +#ifdef HAS_STB + +#define STB_IMAGE_WRITE_STATIC +#define STB_IMAGE_WRITE_IMPLEMENTATION +#include + +#endif // HAS_STB + +namespace mlpack { +namespace data { + +/** + * Save the image file from the given matrix. + * + * @param filename Name of the image file. + * @param matrix Matrix to save the image from. + * @param info An object of ImageInfo class. + * @param fatal If an error should be reported as fatal (default false). + * @return Boolean value indicating success or failure of load. + */ +template +bool Save(const std::string& filename, + arma::Mat& matrix, + ImageInfo& info, + const bool fatal = false); + +/** + * Save the image file from the given matrix. + * + * @param files A vector consisting of filenames. + * @param matrix Matrix to save the image from. + * @param info An object of ImageInfo class. + * @param fatal If an error should be reported as fatal (default false). + * @return Boolean value indicating success or failure of load. + */ +template +bool Save(const std::vector& files, + arma::Mat& matrix, + ImageInfo& info, + const bool fatal = false); + +/** + * Helper function to save files. Implementation in save_image.hpp. + */ +inline bool SaveImage(const std::string& filename, + arma::Mat& image, + ImageInfo& info, + const bool fatal = false); + +} //namespace data +} //namespace mlpack + +// Include implementation of Save() for images. +#include "save_image_impl.hpp" + +#endif diff --git a/src/mlpack/core/data/save_image.cpp b/src/mlpack/core/data/save_image_impl.hpp similarity index 59% rename from src/mlpack/core/data/save_image.cpp rename to src/mlpack/core/data/save_image_impl.hpp index 86ff95a106..c83a81cc71 100644 --- a/src/mlpack/core/data/save_image.cpp +++ b/src/mlpack/core/data/save_image_impl.hpp @@ -1,5 +1,5 @@ /** - * @file core/data/save_image.cpp + * @file core/data/save_image_impl.hpp * @author Mehul Kumar Nirala * * Implementation of image saving functionality via STB. @@ -9,31 +9,78 @@ * 3-clause BSD license along with mlpack. If not, see * http://www.opensource.org/licenses/BSD-3-Clause for more information. */ -#include "save.hpp" +#ifndef MLPACK_CORE_DATA_SAVE_IMAGE_IMPL_HPP +#define MLPACK_CORE_DATA_SAVE_IMAGE_IMPL_HPP -#ifdef HAS_STB - -// The implementation of the functions is included directly, so we need to make -// sure it doesn't get included twice. This is to work around a bug in old -// versions of STB where not all functions were correctly marked static. -#define STB_IMAGE_WRITE_STATIC -#ifndef STB_IMAGE_WRITE_IMPLEMENTATION - #define STB_IMAGE_WRITE_IMPLEMENTATION -#else - #undef STB_IMAGE_WRITE_IMPLEMENTATION -#endif -#include -#ifndef STB_IMAGE_WRITE_IMPLEMENTATION - #define STB_IMAGE_WRITE_IMPLEMENTATION -#endif +// In case it hasn't been included yet. +#include "save_image.hpp" +#include "image_info.hpp" namespace mlpack { namespace data { -bool SaveImage(const std::string& filename, - arma::Mat& image, - ImageInfo& info, - const bool fatal) +/** + * Save the given image to the given filename. + * + * @param filename Filename to save to. + * @param matrix Matrix containing image to be saved. + * @param info Information about the image (width/height/channels/etc.). + * @param fatal Whether an exception should be thrown on save failure. + */ +template +bool Save(const std::string& filename, + arma::Mat& matrix, + ImageInfo& info, + const bool fatal) +{ + arma::Mat tmpMatrix = + arma::conv_to>::from(matrix); + + return SaveImage(filename, tmpMatrix, info, fatal); +} + +// Image saving API for multiple files. +template +bool Save(const std::vector& files, + arma::Mat& matrix, + ImageInfo& info, + const bool fatal) +{ + if (files.size() == 0) + { + if (fatal) + { + Log::Fatal << "Save(): vector of image files is empty; nothing to save." + << std::endl; + } + else + { + Log::Warn << "Save(): vector of image files is empty; nothing to save." + << std::endl; + } + + return false; + } + + arma::Mat img; + bool status = true; + + for (size_t i = 0; i < files.size() ; ++i) + { + arma::Mat colImg(matrix.colptr(i), matrix.n_rows, 1, + false, true); + status &= Save(files[i], colImg, info, fatal); + } + + return status; +} + +#ifdef HAS_STB + +inline bool SaveImage(const std::string& filename, + arma::Mat& image, + ImageInfo& info, + const bool fatal) { // Check to see if the file type is supported. if (!ImageFormatSupported(filename, true)) @@ -41,8 +88,8 @@ bool SaveImage(const std::string& filename, std::ostringstream oss; oss << "Save(): file type " << Extension(filename) << " not supported.\n"; oss << "Currently image saving supports "; - for (auto extension : saveFileTypes) - oss << ", " << extension; + for (auto extension : SaveFileTypes()) + oss << " " << extension; oss << "." << std::endl; if (fatal) @@ -119,18 +166,12 @@ bool SaveImage(const std::string& filename, return status; } -} // namespace data -} // namespace mlpack +#else // HAS_STB -#else - -namespace mlpack { -namespace data { - -bool SaveImage(const std::string& /* filename */, - arma::Mat& /* image */, - ImageInfo& /* info */, - const bool fatal) +inline bool SaveImage(const std::string& /* filename */, + arma::Mat& /* image */, + ImageInfo& /* info */, + const bool fatal) { if (fatal) { @@ -146,6 +187,8 @@ bool SaveImage(const std::string& /* filename */, return false; } +#endif + } // namespace data } // namespace mlpack diff --git a/src/mlpack/core/data/save_impl.hpp b/src/mlpack/core/data/save_impl.hpp index 18a353dbc6..2d3c92e9ff 100644 --- a/src/mlpack/core/data/save_impl.hpp +++ b/src/mlpack/core/data/save_impl.hpp @@ -16,10 +16,6 @@ #include "save.hpp" #include "extension.hpp" -#include -#include -#include - namespace mlpack { namespace data { @@ -344,63 +340,6 @@ bool Save(const std::string& filename, } } -/** - * Save the given image to the given filename. - * - * @param filename Filename to save to. - * @param matrix Matrix containing image to be saved. - * @param info Information about the image (width/height/channels/etc.). - * @param fatal Whether an exception should be thrown on save failure. - */ -template -bool Save(const std::string& filename, - arma::Mat& matrix, - ImageInfo& info, - const bool fatal) -{ - arma::Mat tmpMatrix = - arma::conv_to>::from(matrix); - - // Call out to .cpp implementation. - return SaveImage(filename, tmpMatrix, info, fatal); -} - -// Image saving API for multiple files. -template -bool Save(const std::vector& files, - arma::Mat& matrix, - ImageInfo& info, - const bool fatal) -{ - if (files.size() == 0) - { - if (fatal) - { - Log::Fatal << "Save(): vector of image files is empty; nothing to save." - << std::endl; - } - else - { - Log::Warn << "Save(): vector of image files is empty; nothing to save." - << std::endl; - } - - return false; - } - - arma::Mat img; - bool status = true; - - for (size_t i = 0; i < files.size() ; ++i) - { - arma::Mat colImg(matrix.colptr(i), matrix.n_rows, 1, - false, true); - status &= Save(files[i], colImg, info, fatal); - } - - return status; -} - } // namespace data } // namespace mlpack diff --git a/src/mlpack/core/kernels/CMakeLists.txt b/src/mlpack/core/kernels/CMakeLists.txt index fa77bd7beb..06c5a93c69 100644 --- a/src/mlpack/core/kernels/CMakeLists.txt +++ b/src/mlpack/core/kernels/CMakeLists.txt @@ -6,7 +6,6 @@ set(SOURCES cosine_distance_impl.hpp epanechnikov_kernel.hpp epanechnikov_kernel_impl.hpp - epanechnikov_kernel.cpp example_kernel.hpp gaussian_kernel.hpp hyperbolic_tangent_kernel.hpp @@ -16,7 +15,6 @@ set(SOURCES polynomial_kernel.hpp pspectrum_string_kernel.hpp pspectrum_string_kernel_impl.hpp - pspectrum_string_kernel.cpp spherical_kernel.hpp triangular_kernel.hpp ) diff --git a/src/mlpack/core/kernels/epanechnikov_kernel.cpp b/src/mlpack/core/kernels/epanechnikov_kernel.cpp deleted file mode 100644 index c245200a76..0000000000 --- a/src/mlpack/core/kernels/epanechnikov_kernel.cpp +++ /dev/null @@ -1,80 +0,0 @@ -/** - * @file core/kernels/epanechnikov_kernel.cpp - * @author Neil Slagle - * - * Implementation of non-template Epanechnikov kernels. - * - * mlpack is free software; you may redistribute it and/or modify it under the - * terms of the 3-clause BSD license. You should have received a copy of the - * 3-clause BSD license along with mlpack. If not, see - * http://www.opensource.org/licenses/BSD-3-Clause for more information. - */ -#include "epanechnikov_kernel.hpp" - -using namespace mlpack; -using namespace mlpack::kernel; - -/** - * Compute the normalizer of this Epanechnikov kernel for the given dimension. - * - * @param dimension Dimension to calculate the normalizer for. - */ -double EpanechnikovKernel::Normalizer(const size_t dimension) -{ - return 2.0 * pow(bandwidth, (double) dimension) * - std::pow(M_PI, dimension / 2.0) / - (std::tgamma(dimension / 2.0 + 1.0) * (dimension + 2.0)); -} - -/** - * Evaluate the kernel not for two points but for a numerical value. - */ -double EpanechnikovKernel::Evaluate(const double distance) const -{ - return std::max(0.0, 1 - std::pow(distance, 2.0) * inverseBandwidthSquared); -} - -/** - * Evaluate gradient of the kernel not for two points - * but for a numerical value. - */ -double EpanechnikovKernel::Gradient(const double distance) const -{ - if (std::abs(bandwidth) < std::abs(distance)) - { - return 0; - } - else if (std::abs(bandwidth) > std::abs(distance)) - { - return -2 * inverseBandwidthSquared * distance; - } - else - { - // The gradient doesn't exist. - return arma::datum::nan; - } -} - -/** - * Evaluate gradient of the kernel not for two points - * but for a numerical value. - */ -double EpanechnikovKernel::GradientForSquaredDistance(const double - distanceSquared) const -{ - double bandwidthSquared = bandwidth * bandwidth; - if (distanceSquared < bandwidthSquared) - { - return -1 * inverseBandwidthSquared; - } - else if (distanceSquared > bandwidthSquared && - distanceSquared >= 0) - { - return 0; - } - else - { - // The gradient doesn't exist. - return arma::datum::nan; - } -} diff --git a/src/mlpack/core/kernels/epanechnikov_kernel.hpp b/src/mlpack/core/kernels/epanechnikov_kernel.hpp index d0c6b17b24..482b80c028 100644 --- a/src/mlpack/core/kernels/epanechnikov_kernel.hpp +++ b/src/mlpack/core/kernels/epanechnikov_kernel.hpp @@ -55,21 +55,21 @@ class EpanechnikovKernel * Evaluate the Epanechnikov kernel given that the distance between the two * input points is known. */ - double Evaluate(const double distance) const; + inline double Evaluate(const double distance) const; /** * Evaluate the Gradient of Epanechnikov kernel * given that the distance between the two * input points is known. */ - double Gradient(const double distance) const; + inline double Gradient(const double distance) const; /** * Evaluate the Gradient of Epanechnikov kernel * given that the squared distance between the two * input points is known. */ - double GradientForSquaredDistance(const double distanceSquared) const; + inline double GradientForSquaredDistance(const double distanceSquared) const; /** * Obtains the convolution integral [integral of K(||x-a||) K(||b-x||) dx] * for the two vectors. @@ -87,7 +87,7 @@ class EpanechnikovKernel * * @param dimension Dimension to calculate the normalizer for. */ - double Normalizer(const size_t dimension); + inline double Normalizer(const size_t dimension); /** * Serialize the kernel. diff --git a/src/mlpack/core/kernels/epanechnikov_kernel_impl.hpp b/src/mlpack/core/kernels/epanechnikov_kernel_impl.hpp index eee34daaee..4bc302c00d 100644 --- a/src/mlpack/core/kernels/epanechnikov_kernel_impl.hpp +++ b/src/mlpack/core/kernels/epanechnikov_kernel_impl.hpp @@ -41,8 +41,8 @@ inline double EpanechnikovKernel::Evaluate(const VecTypeA& a, const VecTypeB& b) * @return the convolution integral value. */ template -double EpanechnikovKernel::ConvolutionIntegral(const VecTypeA& a, - const VecTypeB& b) +inline double EpanechnikovKernel::ConvolutionIntegral(const VecTypeA& a, + const VecTypeB& b) { double distance = sqrt(metric::SquaredEuclideanDistance::Evaluate(a, b)); if (distance >= 2.0 * bandwidth) @@ -73,6 +73,70 @@ double EpanechnikovKernel::ConvolutionIntegral(const VecTypeA& a, } } +/** + * Compute the normalizer of this Epanechnikov kernel for the given dimension. + * + * @param dimension Dimension to calculate the normalizer for. + */ +inline double EpanechnikovKernel::Normalizer(const size_t dimension) +{ + return 2.0 * pow(bandwidth, (double) dimension) * + std::pow(M_PI, dimension / 2.0) / + (std::tgamma(dimension / 2.0 + 1.0) * (dimension + 2.0)); +} + +/** + * Evaluate the kernel not for two points but for a numerical value. + */ +inline double EpanechnikovKernel::Evaluate(const double distance) const +{ + return std::max(0.0, 1 - std::pow(distance, 2.0) * inverseBandwidthSquared); +} + +/** + * Evaluate gradient of the kernel not for two points + * but for a numerical value. + */ +inline double EpanechnikovKernel::Gradient(const double distance) const +{ + if (std::abs(bandwidth) < std::abs(distance)) + { + return 0; + } + else if (std::abs(bandwidth) > std::abs(distance)) + { + return -2 * inverseBandwidthSquared * distance; + } + else + { + // The gradient doesn't exist. + return arma::datum::nan; + } +} + +/** + * Evaluate gradient of the kernel not for two points + * but for a numerical value. + */ +inline double EpanechnikovKernel::GradientForSquaredDistance( + const double distanceSquared) const +{ + double bandwidthSquared = bandwidth * bandwidth; + if (distanceSquared < bandwidthSquared) + { + return -1 * inverseBandwidthSquared; + } + else if (distanceSquared > bandwidthSquared && + distanceSquared >= 0) + { + return 0; + } + else + { + // The gradient doesn't exist. + return arma::datum::nan; + } +} //! Serialize the kernel. template void EpanechnikovKernel::serialize(Archive& ar, diff --git a/src/mlpack/core/kernels/pspectrum_string_kernel.cpp b/src/mlpack/core/kernels/pspectrum_string_kernel.cpp deleted file mode 100644 index f83eb0c444..0000000000 --- a/src/mlpack/core/kernels/pspectrum_string_kernel.cpp +++ /dev/null @@ -1,87 +0,0 @@ -/** - * @file core/kernels/pspectrum_string_kernel.cpp - * @author Ryan Curtin - * - * Implementation of the p-spectrum string kernel, created for use with FastMKS. - * Instead of passing a data matrix to FastMKS which stores the kernels, pass a - * one-dimensional data matrix (data vector) to FastMKS which stores indices of - * strings; then, the actual strings are given to the PSpectrumStringKernel at - * construction time, and the kernel knows to map the indices to actual strings. - * - * mlpack is free software; you may redistribute it and/or modify it under the - * terms of the 3-clause BSD license. You should have received a copy of the - * 3-clause BSD license along with mlpack. If not, see - * http://www.opensource.org/licenses/BSD-3-Clause for more information. - */ -#include "pspectrum_string_kernel.hpp" - -using namespace std; -using namespace mlpack; -using namespace mlpack::kernel; - -/** - * Initialize the PSpectrumStringKernel with the given string datasets. For - * more information on this, see the general class documentation. - * - * @param datasets Sets of string data. @param p The length of substrings to - * search. - */ -mlpack::kernel::PSpectrumStringKernel::PSpectrumStringKernel( - const std::vector >& datasets, - const size_t p) : - p(p) -{ - // We have to assemble the counts of substrings. This is not a particularly - // fast operation, unfortunately, but it only needs to be done once. - Log::Info << "Assembling counts of substrings of length " << p << "." - << std::endl; - - // Resize for number of datasets. - counts.resize(datasets.size()); - - for (size_t dataset = 0; dataset < datasets.size(); ++dataset) - { - const std::vector& set = datasets[dataset]; - - // Resize for number of strings in dataset. - counts[dataset].resize(set.size()); - - // Inspect each string in the dataset. - for (size_t index = 0; index < set.size(); ++index) - { - // Convenience references. - const std::string& str = set[index]; - std::map& mapping = counts[dataset][index]; - - size_t start = 0; - while ((start + p) <= str.length()) - { - string sub = str.substr(start, p); - - // Convert all characters to lowercase. - bool invalid = false; - for (size_t j = 0; j < p; ++j) - { - if (!isalnum(sub[j])) - { - invalid = true; - break; // Only consider substrings with alphanumerics. - } - - sub[j] = tolower(sub[j]); - } - - // Increment position in string. - ++start; - - if (!invalid) - { - // Add to the map. - ++mapping[sub]; - } - } - } - } - - Log::Info << "Substring extraction complete." << std::endl; -} diff --git a/src/mlpack/core/kernels/pspectrum_string_kernel.hpp b/src/mlpack/core/kernels/pspectrum_string_kernel.hpp index 9e8f74af23..d76acb24a2 100644 --- a/src/mlpack/core/kernels/pspectrum_string_kernel.hpp +++ b/src/mlpack/core/kernels/pspectrum_string_kernel.hpp @@ -72,8 +72,8 @@ class PSpectrumStringKernel * @param datasets Sets of string data. * @param p The length of substrings to search. */ - PSpectrumStringKernel(const std::vector >& datasets, - const size_t p); + inline PSpectrumStringKernel(const std::vector >& datasets, + const size_t p); /** * Evaluate the kernel for the string indices given. As mentioned in the diff --git a/src/mlpack/core/kernels/pspectrum_string_kernel_impl.hpp b/src/mlpack/core/kernels/pspectrum_string_kernel_impl.hpp index cf04b8bdd6..b00b7b7731 100644 --- a/src/mlpack/core/kernels/pspectrum_string_kernel_impl.hpp +++ b/src/mlpack/core/kernels/pspectrum_string_kernel_impl.hpp @@ -22,6 +22,64 @@ namespace mlpack { namespace kernel { +inline PSpectrumStringKernel::PSpectrumStringKernel( + const std::vector >& datasets, + const size_t p) : p(p) +{ + // We have to assemble the counts of substrings. This is not a particularly + // fast operation, unfortunately, but it only needs to be done once. + Log::Info << "Assembling counts of substrings of length " << p << "." + << std::endl; + + // Resize for number of datasets. + counts.resize(datasets.size()); + + for (size_t dataset = 0; dataset < datasets.size(); ++dataset) + { + const std::vector& set = datasets[dataset]; + + // Resize for number of strings in dataset. + counts[dataset].resize(set.size()); + + // Inspect each string in the dataset. + for (size_t index = 0; index < set.size(); ++index) + { + // Convenience references. + const std::string& str = set[index]; + std::map& mapping = counts[dataset][index]; + + size_t start = 0; + while ((start + p) <= str.length()) + { + std::string sub = str.substr(start, p); + + // Convert all characters to lowercase. + bool invalid = false; + for (size_t j = 0; j < p; ++j) + { + if (!isalnum(sub[j])) + { + invalid = true; + break; // Only consider substrings with alphanumerics. + } + + sub[j] = tolower(sub[j]); + } + + // Increment position in string. + ++start; + + if (!invalid) + { + // Add to the map. + ++mapping[sub]; + } + } + } + } + Log::Info << "Substring extraction complete." << std::endl; +} + /** * Evaluate the kernel for the string indices given. As mentioned in the class * documentation, a and b should be 2-element vectors, where the first element diff --git a/src/mlpack/core/math/CMakeLists.txt b/src/mlpack/core/math/CMakeLists.txt index 28131b2f31..26c1e32fed 100644 --- a/src/mlpack/core/math/CMakeLists.txt +++ b/src/mlpack/core/math/CMakeLists.txt @@ -7,7 +7,6 @@ set(SOURCES digamma.hpp lin_alg.hpp lin_alg_impl.hpp - lin_alg.cpp log_add.hpp log_add_impl.hpp make_alias.hpp @@ -17,7 +16,7 @@ set(SOURCES random.hpp random.cpp random_basis.hpp - random_basis.cpp + random_basis_impl.hpp range.hpp range_impl.hpp round.hpp diff --git a/src/mlpack/core/math/lin_alg.cpp b/src/mlpack/core/math/lin_alg.cpp deleted file mode 100644 index 11f4f93fcd..0000000000 --- a/src/mlpack/core/math/lin_alg.cpp +++ /dev/null @@ -1,279 +0,0 @@ -/** - * @file core/math/lin_alg.cpp - * @author Nishant Mehta - * - * Linear algebra utilities. - * - * mlpack is free software; you may redistribute it and/or modify it under the - * terms of the 3-clause BSD license. You should have received a copy of the - * 3-clause BSD license along with mlpack. If not, see - * http://www.opensource.org/licenses/BSD-3-Clause for more information. - */ -#include "lin_alg.hpp" -#include -#include - -using namespace mlpack; -using namespace math; - -/** - * Auxiliary function to raise vector elements to a specific power. The sign - * is ignored in the power operation and then re-added. Useful for - * eigenvalues. - */ -void mlpack::math::VectorPower(arma::vec& vec, const double power) -{ - for (size_t i = 0; i < vec.n_elem; ++i) - { - if (std::abs(vec(i)) > 1e-12) - vec(i) = (vec(i) > 0) ? std::pow(vec(i), (double) power) : - -std::pow(-vec(i), (double) power); - else - vec(i) = 0; - } -} - -/** - * Creates a centered matrix, where centering is done by subtracting - * the sum over the columns (a column vector) from each column of the matrix. - * - * @param x Input matrix - * @param xCentered Matrix to write centered output into - */ -void mlpack::math::Center(const arma::mat& x, arma::mat& xCentered) -{ - // Get the mean of the elements in each row. - arma::vec rowMean = arma::sum(x, 1) / x.n_cols; - - xCentered = x - arma::repmat(rowMean, 1, x.n_cols); -} - -/** - * Whitens a matrix using the singular value decomposition of the covariance - * matrix. Whitening means the covariance matrix of the result is the identity - * matrix. - */ -void mlpack::math::WhitenUsingSVD(const arma::mat& x, - arma::mat& xWhitened, - arma::mat& whiteningMatrix) -{ - arma::mat covX, u, v, invSMatrix, temp1; - arma::vec sVector; - - covX = mlpack::math::ColumnCovariance(x); - - svd(u, sVector, v, covX); - - size_t d = sVector.n_elem; - invSMatrix.zeros(d, d); - invSMatrix.diag() = 1 / sqrt(sVector); - - whiteningMatrix = v * invSMatrix * trans(u); - - xWhitened = whiteningMatrix * x; -} - -/** - * Overwrites a dimension-N vector to a random vector on the unit sphere in R^N. - */ -void mlpack::math::RandVector(arma::vec& v) -{ - v.zeros(); - - for (size_t i = 0; i + 1 < v.n_elem; i += 2) - { - double a = Random(); - double b = Random(); - double first_term = sqrt(-2 * log(a)); - double second_term = 2 * M_PI * b; - v[i] = first_term * cos(second_term); - v[i + 1] = first_term * sin(second_term); - } - - if ((v.n_elem % 2) == 1) - { - v[v.n_elem - 1] = sqrt(-2 * log(math::Random())) * cos(2 * M_PI * - math::Random()); - } - - v /= sqrt(dot(v, v)); -} - -/** - * Orthogonalize x and return the result in W, using eigendecomposition. - * We will be using the formula \f$ W = x (x^T x)^{-0.5} \f$. - */ -void mlpack::math::Orthogonalize(const arma::mat& x, arma::mat& W) -{ - // For a matrix A, A^N = V * D^N * V', where VDV' is the - // eigendecomposition of the matrix A. - arma::mat eigenvalues, eigenvectors; - arma::vec egval; - eig_sym(egval, eigenvectors, mlpack::math::ColumnCovariance(x)); - VectorPower(egval, -0.5); - - eigenvalues.zeros(egval.n_elem, egval.n_elem); - eigenvalues.diag() = egval; - - arma::mat at = (eigenvectors * eigenvalues * trans(eigenvectors)); - - W = at * x; -} - -/** - * Orthogonalize x in-place. This could be sped up by a custom - * implementation. - */ -void mlpack::math::Orthogonalize(arma::mat& x) -{ - Orthogonalize(x, x); -} - -/** - * Remove a certain set of rows in a matrix while copying to a second matrix. - * - * @param input Input matrix to copy. - * @param rowsToRemove Vector containing indices of rows to be removed. - * @param output Matrix to copy non-removed rows into. - */ -void mlpack::math::RemoveRows(const arma::mat& input, - const std::vector& rowsToRemove, - arma::mat& output) -{ - const size_t nRemove = rowsToRemove.size(); - const size_t nKeep = input.n_rows - nRemove; - - if (nRemove == 0) - { - output = input; // Copy everything. - } - else - { - output.set_size(nKeep, input.n_cols); - - size_t curRow = 0; - size_t removeInd = 0; - // First, check 0 to first row to remove. - if (rowsToRemove[0] > 0) - { - // Note that this implies that n_rows > 1. - output.rows(0, rowsToRemove[0] - 1) = input.rows(0, rowsToRemove[0] - 1); - curRow += rowsToRemove[0]; - } - - // Now, check i'th row to remove to (i + 1)'th row to remove, until i is the - // penultimate row. - while (removeInd < nRemove - 1) - { - const size_t height = rowsToRemove[removeInd + 1] - - rowsToRemove[removeInd] - 1; - - if (height > 0) - { - output.rows(curRow, curRow + height - 1) = - input.rows(rowsToRemove[removeInd] + 1, - rowsToRemove[removeInd + 1] - 1); - curRow += height; - } - - removeInd++; - } - - // Now that i is the last row to remove, check last row to remove to last - // row. - if (rowsToRemove[removeInd] < input.n_rows - 1) - { - output.rows(curRow, nKeep - 1) = input.rows(rowsToRemove[removeInd] + 1, - input.n_rows - 1); - } - } -} - -void mlpack::math::Svec(const arma::mat& input, arma::vec& output) -{ - const size_t n = input.n_rows; - const size_t n2bar = n * (n + 1) / 2; - - output.zeros(n2bar); - - size_t idx = 0; - for (size_t i = 0; i < n; ++i) - { - for (size_t j = i; j < n; ++j) - { - if (i == j) - output(idx++) = input(i, j); - else - output(idx++) = M_SQRT2 * input(i, j); - } - } -} - -void mlpack::math::Svec(const arma::sp_mat& input, arma::sp_vec& output) -{ - const size_t n = input.n_rows; - const size_t n2bar = n * (n + 1) / 2; - - output.zeros(n2bar, 1); - - for (auto it = input.begin(); it != input.end(); ++it) - { - const size_t i = it.row(); - const size_t j = it.col(); - if (i > j) - continue; - if (i == j) - output(SvecIndex(i, j, n)) = *it; - else - output(SvecIndex(i, j, n)) = M_SQRT2 * (*it); - } -} - -void mlpack::math::Smat(const arma::vec& input, arma::mat& output) -{ - const size_t n = static_cast - (ceil((-1. + sqrt(1. + 8. * input.n_elem))/2.)); - - - output.zeros(n, n); - - size_t idx = 0; - for (size_t i = 0; i < n; ++i) - { - for (size_t j = i; j < n; ++j) - { - if (i == j) - output(i, j) = input(idx++); - else - output(i, j) = output(j, i) = M_SQRT1_2 * input(idx++); - } - } -} - -void mlpack::math::SymKronId(const arma::mat& A, arma::mat& op) -{ - // TODO(stephentu): there's probably an easier way to build this operator - - const size_t n = A.n_rows; - const size_t n2bar = n * (n + 1) / 2; - op.zeros(n2bar, n2bar); - - size_t idx = 0; - for (size_t i = 0; i < n; ++i) - { - for (size_t j = i; j < n; ++j) - { - for (size_t k = 0; k < n; ++k) - { - op(idx, SvecIndex(k, j, n)) += - ((k == j) ? 1. : M_SQRT1_2) * A(i, k); - op(idx, SvecIndex(i, k, n)) += - ((k == i) ? 1. : M_SQRT1_2) * A(k, j); - } - op.row(idx) *= 0.5; - if (i != j) - op.row(idx) *= M_SQRT2; - idx++; - } - } -} diff --git a/src/mlpack/core/math/lin_alg.hpp b/src/mlpack/core/math/lin_alg.hpp index 6d5ed028b7..7452e2ed4b 100644 --- a/src/mlpack/core/math/lin_alg.hpp +++ b/src/mlpack/core/math/lin_alg.hpp @@ -13,6 +13,8 @@ #define MLPACK_CORE_MATH_LIN_ALG_HPP #include +#include "ccov.hpp" +#include "random.hpp" /** * Linear algebra utility functions, generally performed on matrices or vectors. @@ -25,7 +27,7 @@ namespace math { * is ignored in the power operation and then re-added. Useful for * eigenvalues. */ -void VectorPower(arma::vec& vec, const double power); +inline void VectorPower(arma::vec& vec, const double power); /** * Creates a centered matrix, where centering is done by subtracting @@ -34,34 +36,34 @@ void VectorPower(arma::vec& vec, const double power); * @param x Input matrix * @param xCentered Matrix to write centered output into */ -void Center(const arma::mat& x, arma::mat& xCentered); +inline void Center(const arma::mat& x, arma::mat& xCentered); /** * Whitens a matrix using the singular value decomposition of the covariance * matrix. Whitening means the covariance matrix of the result is the identity * matrix. */ -void WhitenUsingSVD(const arma::mat& x, - arma::mat& xWhitened, - arma::mat& whiteningMatrix); +inline void WhitenUsingSVD(const arma::mat& x, + arma::mat& xWhitened, + arma::mat& whiteningMatrix); /** * Overwrites a dimension-N vector to a random vector on the unit sphere in R^N. */ -void RandVector(arma::vec& v); +inline void RandVector(arma::vec& v); /** * Orthogonalize x and return the result in W, using eigendecomposition. * We will be using the formula \f$ W = x (x^T x)^{-0.5} \f$. */ -void Orthogonalize(const arma::mat& x, arma::mat& W); +inline void Orthogonalize(const arma::mat& x, arma::mat& W); /** * Orthogonalize x in-place. This could be sped up by a custom * implementation. */ -void Orthogonalize(arma::mat& x); +inline void Orthogonalize(arma::mat& x); /** * Remove a certain set of rows in a matrix while copying to a second matrix. @@ -70,9 +72,9 @@ void Orthogonalize(arma::mat& x); * @param rowsToRemove Vector containing indices of rows to be removed. * @param output Matrix to copy non-removed rows into. */ -void RemoveRows(const arma::mat& input, - const std::vector& rowsToRemove, - arma::mat& output); +inline void RemoveRows(const arma::mat& input, + const std::vector& rowsToRemove, + arma::mat& output); /** * Upper triangular representation of a symmetric matrix, scaled such that, @@ -83,9 +85,9 @@ void RemoveRows(const arma::mat& input, * @param input A symmetric matrix * @param output */ -void Svec(const arma::mat& input, arma::vec& output); +inline void Svec(const arma::mat& input, arma::vec& output); -void Svec(const arma::sp_mat& input, arma::sp_vec& output); +inline void Svec(const arma::sp_mat& input, arma::sp_vec& output); /** * The inverse of Svec. That is, Smat(Svec(A)) == A. @@ -93,7 +95,7 @@ void Svec(const arma::sp_mat& input, arma::sp_vec& output); * @param input * @param output A symmetric matrix */ -void Smat(const arma::vec& input, arma::mat& output); +inline void Smat(const arma::vec& input, arma::mat& output); /** * Return the index such that A[i,j] == factr(i, j) * svec(A)[pos(i, j)], @@ -115,7 +117,7 @@ inline size_t SvecIndex(size_t i, size_t j, size_t n); * @param A * @param op */ -void SymKronId(const arma::mat& A, arma::mat& op); +inline void SymKronId(const arma::mat& A, arma::mat& op); /** * Signum function. diff --git a/src/mlpack/core/math/lin_alg_impl.hpp b/src/mlpack/core/math/lin_alg_impl.hpp index f0429921d6..76ba56b861 100644 --- a/src/mlpack/core/math/lin_alg_impl.hpp +++ b/src/mlpack/core/math/lin_alg_impl.hpp @@ -1,7 +1,10 @@ /** * @file core/math/lin_alg_impl.hpp * @author Stephen Tu + * @author Nishant Mehta * + * Linear algebra utilities. + * * mlpack is free software; you may redistribute it and/or modify it under the * terms of the 3-clause BSD license. You should have received a copy of the * 3-clause BSD license along with mlpack. If not, see @@ -22,6 +25,267 @@ inline size_t SvecIndex(size_t i, size_t j, size_t n) return (j-i) + (n*(n+1) - (n-i)*(n-i+1))/2; } +/** + * Auxiliary function to raise vector elements to a specific power. The sign + * is ignored in the power operation and then re-added. Useful for + * eigenvalues. + */ +inline void VectorPower(arma::vec& vec, const double power) +{ + for (size_t i = 0; i < vec.n_elem; ++i) + { + if (std::abs(vec(i)) > 1e-12) + { + vec(i) = (vec(i) > 0) ? std::pow(vec(i), (double) power) : + -std::pow(-vec(i), (double) power); + } + else + vec(i) = 0; + } +} + +/** + * Creates a centered matrix, where centering is done by subtracting + * the sum over the columns (a column vector) from each column of the matrix. + * + * @param x Input matrix + * @param xCentered Matrix to write centered output into + */ +inline void Center(const arma::mat& x, arma::mat& xCentered) +{ + // Get the mean of the elements in each row. + arma::vec rowMean = arma::sum(x, 1) / x.n_cols; + + xCentered = x - arma::repmat(rowMean, 1, x.n_cols); +} + +/** + * Whitens a matrix using the singular value decomposition of the covariance + * matrix. Whitening means the covariance matrix of the result is the identity + * matrix. + */ +inline void WhitenUsingSVD(const arma::mat& x, + arma::mat& xWhitened, + arma::mat& whiteningMatrix) +{ + arma::mat covX, u, v, invSMatrix, temp1; + arma::vec sVector; + + covX = ColumnCovariance(x); + + svd(u, sVector, v, covX); + + size_t d = sVector.n_elem; + invSMatrix.zeros(d, d); + invSMatrix.diag() = 1 / sqrt(sVector); + + whiteningMatrix = v * invSMatrix * trans(u); + + xWhitened = whiteningMatrix * x; +} + +/** + * Overwrites a dimension-N vector to a random vector on the unit sphere in R^N. + */ +inline void RandVector(arma::vec& v) +{ + for (size_t i = 0; i + 1 < v.n_elem; i += 2) + { + double a = math::Random(); + double b = math::Random(); + double first_term = sqrt(-2 * log(a)); + double second_term = 2 * M_PI * b; + v[i] = first_term * cos(second_term); + v[i + 1] = first_term * sin(second_term); + } + + if ((v.n_elem % 2) == 1) + { + v[v.n_elem - 1] = sqrt(-2 * log(math::Random())) * cos(2 * M_PI * + math::Random()); + } + + v /= sqrt(dot(v, v)); +} + +/** + * Orthogonalize x and return the result in W, using eigendecomposition. + * We will be using the formula \f$ W = x (x^T x)^{-0.5} \f$. + */ +inline void Orthogonalize(const arma::mat& x, arma::mat& W) +{ + // For a matrix A, A^N = V * D^N * V', where VDV' is the + // eigendecomposition of the matrix A. + arma::mat eigenvalues, eigenvectors; + arma::vec egval; + eig_sym(egval, eigenvectors, ColumnCovariance(x)); + VectorPower(egval, -0.5); + + eigenvalues.zeros(egval.n_elem, egval.n_elem); + eigenvalues.diag() = egval; + + arma::mat at = (eigenvectors * eigenvalues * trans(eigenvectors)); + + W = at * x; +} + +/** + * Orthogonalize x in-place. This could be sped up by a custom + * implementation. + */ +inline void Orthogonalize(arma::mat& x) +{ + Orthogonalize(x, x); +} + +/** + * Remove a certain set of rows in a matrix while copying to a second matrix. + * + * @param input Input matrix to copy. + * @param rowsToRemove Vector containing indices of rows to be removed. + * @param output Matrix to copy non-removed rows into. + */ +inline void RemoveRows(const arma::mat& input, + const std::vector& rowsToRemove, + arma::mat& output) +{ + const size_t nRemove = rowsToRemove.size(); + const size_t nKeep = input.n_rows - nRemove; + + if (nRemove == 0) + { + output = input; // Copy everything. + } + else + { + output.set_size(nKeep, input.n_cols); + + size_t curRow = 0; + size_t removeInd = 0; + // First, check 0 to first row to remove. + if (rowsToRemove[0] > 0) + { + // Note that this implies that n_rows > 1. + output.rows(0, rowsToRemove[0] - 1) = input.rows(0, rowsToRemove[0] - 1); + curRow += rowsToRemove[0]; + } + + // Now, check i'th row to remove to (i + 1)'th row to remove, until i is the + // penultimate row. + while (removeInd < nRemove - 1) + { + const size_t height = rowsToRemove[removeInd + 1] - + rowsToRemove[removeInd] - 1; + + if (height > 0) + { + output.rows(curRow, curRow + height - 1) = + input.rows(rowsToRemove[removeInd] + 1, + rowsToRemove[removeInd + 1] - 1); + curRow += height; + } + + removeInd++; + } + + // Now that i is the last row to remove, check last row to remove to last + // row. + if (rowsToRemove[removeInd] < input.n_rows - 1) + { + output.rows(curRow, nKeep - 1) = input.rows(rowsToRemove[removeInd] + 1, + input.n_rows - 1); + } + } +} + +inline void Svec(const arma::mat& input, arma::vec& output) +{ + const size_t n = input.n_rows; + const size_t n2bar = n * (n + 1) / 2; + + output.zeros(n2bar); + + size_t idx = 0; + for (size_t i = 0; i < n; ++i) + { + for (size_t j = i; j < n; ++j) + { + if (i == j) + output(idx++) = input(i, j); + else + output(idx++) = M_SQRT2 * input(i, j); + } + } +} + +inline void Svec(const arma::sp_mat& input, arma::sp_vec& output) +{ + const size_t n = input.n_rows; + const size_t n2bar = n * (n + 1) / 2; + + output.zeros(n2bar, 1); + + for (auto it = input.begin(); it != input.end(); ++it) + { + const size_t i = it.row(); + const size_t j = it.col(); + if (i > j) + continue; + if (i == j) + output(SvecIndex(i, j, n)) = *it; + else + output(SvecIndex(i, j, n)) = M_SQRT2 * (*it); + } +} + +inline void Smat(const arma::vec& input, arma::mat& output) +{ + const size_t n = static_cast + (ceil((-1. + sqrt(1. + 8. * input.n_elem)) / 2.)); + + output.zeros(n, n); + + size_t idx = 0; + for (size_t i = 0; i < n; ++i) + { + for (size_t j = i; j < n; ++j) + { + if (i == j) + output(i, j) = input(idx++); + else + output(i, j) = output(j, i) = M_SQRT1_2 * input(idx++); + } + } +} + +inline void SymKronId(const arma::mat& A, arma::mat& op) +{ + // TODO(stephentu): there's probably an easier way to build this operator + + const size_t n = A.n_rows; + const size_t n2bar = n * (n + 1) / 2; + op.zeros(n2bar, n2bar); + + size_t idx = 0; + for (size_t i = 0; i < n; ++i) + { + for (size_t j = i; j < n; ++j) + { + for (size_t k = 0; k < n; ++k) + { + op(idx, SvecIndex(k, j, n)) += + ((k == j) ? 1. : M_SQRT1_2) * A(i, k); + op(idx, SvecIndex(i, k, n)) += + ((k == i) ? 1. : M_SQRT1_2) * A(k, j); + } + op.row(idx) *= 0.5; + if (i != j) + op.row(idx) *= M_SQRT2; + idx++; + } + } +} + } // namespace math } // namespace mlpack diff --git a/src/mlpack/core/math/random_basis.hpp b/src/mlpack/core/math/random_basis.hpp index 6d605b846e..3d7faa4a64 100644 --- a/src/mlpack/core/math/random_basis.hpp +++ b/src/mlpack/core/math/random_basis.hpp @@ -24,9 +24,12 @@ namespace math { * @param basis Matrix to store basis in. * @param d Desired number of dimensions in the basis. */ -void RandomBasis(arma::mat& basis, const size_t d); +inline void RandomBasis(arma::mat& basis, const size_t d); } // namespace math } // namespace mlpack +//! Include the implementation file. +#include "random_basis_impl.hpp" + #endif diff --git a/src/mlpack/core/math/random_basis.cpp b/src/mlpack/core/math/random_basis_impl.hpp similarity index 81% rename from src/mlpack/core/math/random_basis.cpp rename to src/mlpack/core/math/random_basis_impl.hpp index f891b1e2eb..e8d0b0c4d4 100644 --- a/src/mlpack/core/math/random_basis.cpp +++ b/src/mlpack/core/math/random_basis_impl.hpp @@ -1,5 +1,5 @@ /** - * @file core/math/random_basis.cpp + * @file core/math/random_basis_impl.hpp * @author Ryan Curtin * * Generate a random d-dimensional basis. @@ -11,21 +11,19 @@ */ #include "random_basis.hpp" -using namespace arma; - namespace mlpack { namespace math { -void RandomBasis(mat& basis, const size_t d) +inline void RandomBasis(arma::mat& basis, const size_t d) { while (true) { // [Q, R] = qr(randn(d, d)); // Q = Q * diag(sign(diag(R))); - mat r; - if (qr(basis, r, randn(d, d))) + arma::mat r; + if (qr(basis, r, arma::randn(d, d))) { - vec rDiag(r.n_rows); + arma::vec rDiag(r.n_rows); for (size_t i = 0; i < rDiag.n_elem; ++i) { if (r(i, i) < 0) diff --git a/src/mlpack/methods/ann/init_rules/gaussian_init.hpp b/src/mlpack/methods/ann/init_rules/gaussian_init.hpp index 96478d4bad..50e8b93742 100644 --- a/src/mlpack/methods/ann/init_rules/gaussian_init.hpp +++ b/src/mlpack/methods/ann/init_rules/gaussian_init.hpp @@ -17,8 +17,6 @@ #include #include -using namespace mlpack::math; - namespace mlpack { namespace ann /** Artificial Neural Network. */ { @@ -55,7 +53,7 @@ class GaussianInitialization if (W.is_empty()) W.set_size(rows, cols); - W.imbue( [&]() { return arma::as_scalar(RandNormal(mean, variance)); } ); + W.imbue( [&]() { return arma::as_scalar(mlpack::math::RandNormal(mean, variance)); } ); } /** @@ -69,7 +67,7 @@ class GaussianInitialization if (W.is_empty()) Log::Fatal << "Cannot initialize an empty matrix." << std::endl; - W.imbue( [&]() { return arma::as_scalar(RandNormal(mean, variance)); } ); + W.imbue( [&]() { return arma::as_scalar(mlpack::math::RandNormal(mean, variance)); } ); } /** diff --git a/src/mlpack/methods/ann/init_rules/glorot_init.hpp b/src/mlpack/methods/ann/init_rules/glorot_init.hpp index 4c526b8ab0..f2d02bbb1c 100644 --- a/src/mlpack/methods/ann/init_rules/glorot_init.hpp +++ b/src/mlpack/methods/ann/init_rules/glorot_init.hpp @@ -18,8 +18,6 @@ #include "random_init.hpp" #include "gaussian_init.hpp" -using namespace mlpack::math; - namespace mlpack { namespace ann /** Artificial Neural Network. */ { diff --git a/src/mlpack/methods/ann/layer_names.hpp b/src/mlpack/methods/ann/layer_names.hpp index 15596efea3..60b7cc4aa1 100644 --- a/src/mlpack/methods/ann/layer_names.hpp +++ b/src/mlpack/methods/ann/layer_names.hpp @@ -16,8 +16,6 @@ #include #include -using namespace mlpack::ann; - /** * Implementation of a class that returns the string representation of the * name of the given layer. @@ -36,7 +34,7 @@ class LayerNameVisitor : public boost::static_visitor * @param * Given layer of type AdaptiveMaxPooling. * @return The string representation of the layer. */ - std::string LayerString(AdaptiveMaxPooling<> * /*layer*/) const + std::string LayerString(mlpack::ann::AdaptiveMaxPooling<> * /*layer*/) const { return "adaptivemaxpooling"; } @@ -47,7 +45,7 @@ class LayerNameVisitor : public boost::static_visitor * @param * Given layer of type AdaptiveMeanPooling. * @return The string representation of the layer. */ - std::string LayerString(AdaptiveMeanPooling<> * /*layer*/) const + std::string LayerString(mlpack::ann::AdaptiveMeanPooling<> * /*layer*/) const { return "adaptivemeanpooling"; } @@ -58,7 +56,7 @@ class LayerNameVisitor : public boost::static_visitor * @param * Given layer of type AtrousConvolution. * @return The string representation of the layer. */ - std::string LayerString(AtrousConvolution<>* /*layer*/) const + std::string LayerString(mlpack::ann::AtrousConvolution<>* /*layer*/) const { return "atrousconvolution"; } @@ -69,7 +67,7 @@ class LayerNameVisitor : public boost::static_visitor * @param * Given layer of type AlphaDropout. * @return The string representation of the layer. */ - std::string LayerString(AlphaDropout<>* /*layer*/) const + std::string LayerString(mlpack::ann::AlphaDropout<>* /*layer*/) const { return "alphadropout"; } @@ -80,7 +78,7 @@ class LayerNameVisitor : public boost::static_visitor * @param * Given layer of type BatchNorm. * @return The string representation of the layer. */ - std::string LayerString(BatchNorm<>* /*layer*/) const + std::string LayerString(mlpack::ann::BatchNorm<>* /*layer*/) const { return "batchnorm"; } @@ -91,7 +89,7 @@ class LayerNameVisitor : public boost::static_visitor * @param * Given layer of type Constant. * @return The string representation of the layer. */ - std::string LayerString(Constant<>* /*layer*/) const + std::string LayerString(mlpack::ann::Constant<>* /*layer*/) const { return "constant"; } @@ -102,7 +100,7 @@ class LayerNameVisitor : public boost::static_visitor * @param * Given layer of type Convolution. * @return The string representation of the layer. */ - std::string LayerString(Convolution<>* /*layer*/) const + std::string LayerString(mlpack::ann::Convolution<>* /*layer*/) const { return "convolution"; } @@ -113,7 +111,7 @@ class LayerNameVisitor : public boost::static_visitor * @param * Given layer of type DropConnect. * @return The string representation of the layer. */ - std::string LayerString(DropConnect<>* /*layer*/) const + std::string LayerString(mlpack::ann::DropConnect<>* /*layer*/) const { return "dropconnect"; } @@ -124,7 +122,7 @@ class LayerNameVisitor : public boost::static_visitor * @param * Given layer of type Dropout. * @return The string representation of the layer. */ - std::string LayerString(Dropout<>* /*layer*/) const + std::string LayerString(mlpack::ann::Dropout<>* /*layer*/) const { return "dropout"; } @@ -135,7 +133,7 @@ class LayerNameVisitor : public boost::static_visitor * @param * Given layer of type FlexibleReLU. * @return The string representation of the layer. */ - std::string LayerString(FlexibleReLU<>* /*layer*/) const + std::string LayerString(mlpack::ann::FlexibleReLU<>* /*layer*/) const { return "flexiblerelu"; } @@ -146,7 +144,7 @@ class LayerNameVisitor : public boost::static_visitor * @param * Given layer of type LayerNorm. * @return The string representation of the layer. */ - std::string LayerString(LayerNorm<>* /*layer*/) const + std::string LayerString(mlpack::ann::LayerNorm<>* /*layer*/) const { return "layernorm"; } @@ -157,7 +155,7 @@ class LayerNameVisitor : public boost::static_visitor * @param * Given layer of type Linear. * @return The string representation of the layer. */ - std::string LayerString(Linear<>* /*layer*/) const + std::string LayerString(mlpack::ann::Linear<>* /*layer*/) const { return "linear"; } @@ -168,7 +166,7 @@ class LayerNameVisitor : public boost::static_visitor * @param * Given layer of type LinearNoBias. * @return The string representation of the layer. */ - std::string LayerString(LinearNoBias<>* /*layer*/) const + std::string LayerString(mlpack::ann::LinearNoBias<>* /*layer*/) const { return "linearnobias"; } @@ -179,7 +177,7 @@ class LayerNameVisitor : public boost::static_visitor * @param * Given layer of type NoisyLinear. * @return The string representation of the layer. */ - std::string LayerString(NoisyLinear<>* /*layer*/) const + std::string LayerString(mlpack::ann::NoisyLinear<>* /*layer*/) const { return "noisylinear"; } @@ -190,7 +188,7 @@ class LayerNameVisitor : public boost::static_visitor * @param * Given layer of type MaxPooling. * @return The string representation of the layer. */ - std::string LayerString(MaxPooling<>* /*layer*/) const + std::string LayerString(mlpack::ann::MaxPooling<>* /*layer*/) const { return "maxpooling"; } @@ -201,7 +199,7 @@ class LayerNameVisitor : public boost::static_visitor * @param * Given layer of type MeanPooling. * @return The string representation of the layer. */ - std::string LayerString(MeanPooling<>* /*layer*/) const + std::string LayerString(mlpack::ann::MeanPooling<>* /*layer*/) const { return "meanpooling"; } @@ -212,7 +210,7 @@ class LayerNameVisitor : public boost::static_visitor * @param * Given layer of type LpPooling. * @return The string representation of the layer. */ - std::string LayerString(LpPooling<>* /*layer*/) const + std::string LayerString(mlpack::ann::LpPooling<>* /*layer*/) const { return "lppooling"; } @@ -223,7 +221,7 @@ class LayerNameVisitor : public boost::static_visitor * @param * Given layer of type MultiplyConstant. * @return The string representation of the layer. */ - std::string LayerString(MultiplyConstant<>* /*layer*/) const + std::string LayerString(mlpack::ann::MultiplyConstant<>* /*layer*/) const { return "multiplyconstant"; } @@ -234,7 +232,7 @@ class LayerNameVisitor : public boost::static_visitor * @param * Given layer of type ReLULayer. * @return The string representation of the layer. */ - std::string LayerString(ReLULayer<>* /*layer*/) const + std::string LayerString(mlpack::ann::ReLULayer<>* /*layer*/) const { return "relu"; } @@ -246,7 +244,7 @@ class LayerNameVisitor : public boost::static_visitor * @param * Given layer of type TransposedConvolution. * @return The string representation of the layer. */ - std::string LayerString(TransposedConvolution<>* /*layer*/) const + std::string LayerString(mlpack::ann::TransposedConvolution<>* /*layer*/) const { return "transposedconvolution"; } @@ -257,7 +255,7 @@ class LayerNameVisitor : public boost::static_visitor * @param * Given layer of type IdentityLayer. * @return The string representation of the layer. */ - std::string LayerString(IdentityLayer<>* /*layer*/) const + std::string LayerString(mlpack::ann::IdentityLayer<>* /*layer*/) const { return "identity"; } @@ -268,7 +266,7 @@ class LayerNameVisitor : public boost::static_visitor * @param * Given layer of type TanHLayer. * @return The string representation of the layer. */ - std::string LayerString(TanHLayer<>* /*layer*/) const + std::string LayerString(mlpack::ann::TanHLayer<>* /*layer*/) const { return "tanh"; } @@ -279,7 +277,7 @@ class LayerNameVisitor : public boost::static_visitor * @param * Given layer of type ELU. * @return The string representation of the layer. */ - std::string LayerString(ELU<>* /*layer*/) const + std::string LayerString(mlpack::ann::ELU<>* /*layer*/) const { return "elu"; } @@ -290,7 +288,7 @@ class LayerNameVisitor : public boost::static_visitor * @param * Given layer of type HardTanH. * @return The string representation of the layer. */ - std::string LayerString(HardTanH<>* /*layer*/) const + std::string LayerString(mlpack::ann::HardTanH<>* /*layer*/) const { return "hardtanh"; } @@ -301,7 +299,7 @@ class LayerNameVisitor : public boost::static_visitor * @param * Given layer of type LeakyReLU. * @return The string representation of the layer. */ - std::string LayerString(LeakyReLU<>* /*layer*/) const + std::string LayerString(mlpack::ann::LeakyReLU<>* /*layer*/) const { return "leakyrelu"; } @@ -312,7 +310,7 @@ class LayerNameVisitor : public boost::static_visitor * @param * Given layer of type PReLU. * @return The string representation of the layer. */ - std::string LayerString(PReLU<>* /*layer*/) const + std::string LayerString(mlpack::ann::PReLU<>* /*layer*/) const { return "prelu"; } @@ -323,7 +321,7 @@ class LayerNameVisitor : public boost::static_visitor * @param * Given layer of type SigmoidLayer. * @return The string representation of the layer. */ - std::string LayerString(SigmoidLayer<>* /*layer*/) const + std::string LayerString(mlpack::ann::SigmoidLayer<>* /*layer*/) const { return "sigmoid"; } @@ -334,7 +332,7 @@ class LayerNameVisitor : public boost::static_visitor * @param * Given layer of type LogSoftMax. * @return The string representation of the layer. */ - std::string LayerString(LogSoftMax<>* /*layer*/) const + std::string LayerString(mlpack::ann::LogSoftMax<>* /*layer*/) const { return "logsoftmax"; } @@ -345,7 +343,7 @@ class LayerNameVisitor : public boost::static_visitor * @param * Given layer of type LSTM. * @return The string representation of the layer. */ - std::string LayerString(LSTM<>* /*layer*/) const + std::string LayerString(mlpack::ann::LSTM<>* /*layer*/) const { return "lstm"; } @@ -356,7 +354,7 @@ class LayerNameVisitor : public boost::static_visitor * @param * Given layer of type CReLU. * @return The string representation of the layer. */ - std::string LayerString(CReLU<>* /*layer*/) const + std::string LayerString(mlpack::ann::CReLU<>* /*layer*/) const { return "crelu"; } @@ -367,7 +365,7 @@ class LayerNameVisitor : public boost::static_visitor * @param * Given layer of type Highway. * @return The string representation of the layer. */ - std::string LayerString(Highway<>* /*layer*/) const + std::string LayerString(mlpack::ann::Highway<>* /*layer*/) const { return "highway"; } @@ -378,7 +376,7 @@ class LayerNameVisitor : public boost::static_visitor * @param * Given layer of type GRU. * @return The string representation of the layer. */ - std::string LayerString(GRU<>* /*layer*/) const + std::string LayerString(mlpack::ann::GRU<>* /*layer*/) const { return "gru"; } @@ -389,7 +387,7 @@ class LayerNameVisitor : public boost::static_visitor * @param * Given layer of type Glimpse. * @return The string representation of the layer. */ - std::string LayerString(Glimpse<>* /*layer*/) const + std::string LayerString(mlpack::ann::Glimpse<>* /*layer*/) const { return "glimpse"; } @@ -400,7 +398,7 @@ class LayerNameVisitor : public boost::static_visitor * @param * Given layer of type FastLSTM. * @return The string representation of the layer. */ - std::string LayerString(FastLSTM<>* /*layer*/) const + std::string LayerString(mlpack::ann::FastLSTM<>* /*layer*/) const { return "fastlstm"; } @@ -411,7 +409,7 @@ class LayerNameVisitor : public boost::static_visitor * @param * Given layer of type WeightNorm. * @return The string representation of the layer. */ - std::string LayerString(WeightNorm<>* /*layer*/) const + std::string LayerString(mlpack::ann::WeightNorm<>* /*layer*/) const { return "weightnorm"; } @@ -429,7 +427,7 @@ class LayerNameVisitor : public boost::static_visitor } //! Overload function call. - std::string operator()(MoreTypes layer) const + std::string operator()(mlpack::ann::MoreTypes layer) const { return layer.apply_visitor(*this); } diff --git a/src/mlpack/methods/cf/cf_main.cpp b/src/mlpack/methods/cf/cf_main.cpp index d756aedabe..3df5caf161 100644 --- a/src/mlpack/methods/cf/cf_main.cpp +++ b/src/mlpack/methods/cf/cf_main.cpp @@ -40,6 +40,7 @@ #include using namespace mlpack; +using namespace mlpack::math; using namespace mlpack::cf; using namespace mlpack::amf; using namespace mlpack::svd; @@ -202,9 +203,9 @@ PARAM_STRING_IN("neighbor_search", "Algorithm used for neighbor search.", void BINDING_FUNCTION(util::Params& params, util::Timers& timers) { if (params.Get("seed") == 0) - math::RandomSeed(std::time(NULL)); + RandomSeed(std::time(NULL)); else - math::RandomSeed(params.Get("seed")); + RandomSeed(params.Get("seed")); // Validate parameters. RequireOnlyOnePassed(params, { "training", "input_model" }, true); diff --git a/src/mlpack/methods/det/dtree_impl.hpp b/src/mlpack/methods/det/dtree_impl.hpp index dfdb994049..240156ae61 100644 --- a/src/mlpack/methods/det/dtree_impl.hpp +++ b/src/mlpack/methods/det/dtree_impl.hpp @@ -15,11 +15,9 @@ #include #include -using namespace mlpack; -using namespace det; - -namespace details -{ +namespace mlpack { +namespace det { +namespace details { /** * This one sorts and scand the given per-dimension extract and puts all splits @@ -552,10 +550,11 @@ bool DTree::FindSplit(const MatType& data, } template -size_t DTree::SplitData(MatType& data, - const size_t splitDim, - const ElemType splitValue, - arma::Col& oldFromNew) const +size_t DTree::SplitData( + MatType& data, + const size_t splitDim, + const ElemType splitValue, + arma::Col& oldFromNew) const { // Swap all columns such that any columns with value in dimension splitDim // less than or equal to splitValue are on the left side, and all others are @@ -933,8 +932,8 @@ TagType DTree::FindBucket(const VecType& query) const } template -void DTree::ComputeVariableImportance(arma::vec& importances) - const +void DTree::ComputeVariableImportance( + arma::vec& importances) const { // Clear and set to right size. importances.zeros(maxVals.n_elem); @@ -1036,3 +1035,6 @@ void DTree::serialize(Archive& ar, FillMinMax(minVals, maxVals); } } + +} // namespace det +} // namespace mlpack diff --git a/src/mlpack/methods/gmm/gmm_generate_main.cpp b/src/mlpack/methods/gmm/gmm_generate_main.cpp index b270cfa5e2..1fd588c809 100644 --- a/src/mlpack/methods/gmm/gmm_generate_main.cpp +++ b/src/mlpack/methods/gmm/gmm_generate_main.cpp @@ -11,6 +11,7 @@ */ #include #include +#include #ifdef BINDING_NAME #undef BINDING_NAME @@ -22,6 +23,7 @@ using namespace std; using namespace mlpack; +using namespace mlpack::math; using namespace mlpack::gmm; using namespace mlpack::util; @@ -74,9 +76,9 @@ void BINDING_FUNCTION(util::Params& params, util::Timers& /* timers */) "no results will be saved"); if (params.Get("seed") == 0) - mlpack::math::RandomSeed(time(NULL)); + RandomSeed(time(NULL)); else - mlpack::math::RandomSeed((size_t) params.Get("seed")); + RandomSeed((size_t) params.Get("seed")); RequireParamValue(params, "samples", [](int x) { return x > 0; }, true, "number of samples must be greater than 0"); diff --git a/src/mlpack/methods/gmm/gmm_train_main.cpp b/src/mlpack/methods/gmm/gmm_train_main.cpp index e1ebf6a12c..ebeb2b074e 100644 --- a/src/mlpack/methods/gmm/gmm_train_main.cpp +++ b/src/mlpack/methods/gmm/gmm_train_main.cpp @@ -18,6 +18,7 @@ #define BINDING_NAME gmm_train #include +#include #include "gmm.hpp" #include "diagonal_gmm.hpp" @@ -27,6 +28,7 @@ #include using namespace mlpack; +using namespace mlpack::math; using namespace mlpack::gmm; using namespace mlpack::util; using namespace mlpack::kmeans; @@ -155,9 +157,9 @@ void BINDING_FUNCTION(util::Params& params, util::Timers& timers) { // Check parameters and load data. if (params.Get("seed") != 0) - math::RandomSeed((size_t) params.Get("seed")); + RandomSeed((size_t) params.Get("seed")); else - math::RandomSeed((size_t) std::time(NULL)); + RandomSeed((size_t) std::time(NULL)); RequireParamValue(params, "gaussians", [](int x) { return x > 0; }, true, "number of Gaussians must be positive"); diff --git a/src/mlpack/methods/hmm/hmm_util_impl.hpp b/src/mlpack/methods/hmm/hmm_util_impl.hpp index 017cc65bcd..75938845e4 100644 --- a/src/mlpack/methods/hmm/hmm_util_impl.hpp +++ b/src/mlpack/methods/hmm/hmm_util_impl.hpp @@ -78,18 +78,16 @@ void LoadHMMAndPerformActionHelper(const std::string& modelFile, char type; ar(CEREAL_NVP(type)); - using namespace mlpack::distribution; - switch (type) { case HMMType::DiscreteHMM: DeserializeHMMAndPerformAction>(ar, x); + HMM>(ar, x); break; case HMMType::GaussianHMM: DeserializeHMMAndPerformAction>(ar, x); + HMM>(ar, x); break; case HMMType::GaussianMixtureModelHMM: diff --git a/src/mlpack/methods/kmeans/kmeans_main.cpp b/src/mlpack/methods/kmeans/kmeans_main.cpp index 67b60a8d79..7b32db8171 100644 --- a/src/mlpack/methods/kmeans/kmeans_main.cpp +++ b/src/mlpack/methods/kmeans/kmeans_main.cpp @@ -11,6 +11,7 @@ */ #include #include +#include #ifdef BINDING_NAME #undef BINDING_NAME @@ -30,6 +31,7 @@ #include "dual_tree_kmeans.hpp" using namespace mlpack; +using namespace mlpack::math; using namespace mlpack::kmeans; using namespace mlpack::util; using namespace std; @@ -191,9 +193,9 @@ void BINDING_FUNCTION(util::Params& params, util::Timers& timers) { // Initialize random seed. if (params.Get("seed") != 0) - math::RandomSeed((size_t) params.Get("seed")); + RandomSeed((size_t) params.Get("seed")); else - math::RandomSeed((size_t) std::time(NULL)); + RandomSeed((size_t) std::time(NULL)); RequireOnlyOnePassed(params, { "refined_start", "kmeans_plus_plus" }, true, "Only one initialization strategy can be specified!", true); diff --git a/src/mlpack/methods/linear_svm/linear_svm_main.cpp b/src/mlpack/methods/linear_svm/linear_svm_main.cpp index 4dd20021b1..a037ec2271 100644 --- a/src/mlpack/methods/linear_svm/linear_svm_main.cpp +++ b/src/mlpack/methods/linear_svm/linear_svm_main.cpp @@ -26,6 +26,7 @@ using namespace std; using namespace mlpack; +using namespace mlpack::math; using namespace mlpack::svm; using namespace mlpack::util; @@ -178,9 +179,9 @@ PARAM_MATRIX_OUT("probabilities", "If test data is specified, this " void BINDING_FUNCTION(util::Params& params, util::Timers& timers) { if (params.Get("seed") != 0) - math::RandomSeed((size_t) params.Get("seed")); + RandomSeed((size_t) params.Get("seed")); else - math::RandomSeed((size_t) std::time(NULL)); + RandomSeed((size_t) std::time(NULL)); // Collect command-line options. const double lambda = params.Get("lambda"); diff --git a/src/mlpack/methods/lmnn/lmnn_main.cpp b/src/mlpack/methods/lmnn/lmnn_main.cpp index 18c430b63a..beea8339a8 100644 --- a/src/mlpack/methods/lmnn/lmnn_main.cpp +++ b/src/mlpack/methods/lmnn/lmnn_main.cpp @@ -187,6 +187,7 @@ PARAM_INT_IN("range", "Number of iterations after which impostors needs to be " PARAM_INT_IN("seed", "Random seed. If 0, 'std::time(NULL)' is used.", "s", 0); using namespace mlpack; +using namespace mlpack::math; using namespace mlpack::lmnn; using namespace mlpack::metric; using namespace mlpack::util; @@ -238,9 +239,9 @@ double KNNAccuracy(const arma::mat& dataset, void BINDING_FUNCTION(util::Params& params, util::Timers& timers) { if (params.Get("seed") != 0) - math::RandomSeed((size_t) params.Get("seed")); + RandomSeed((size_t) params.Get("seed")); else - math::RandomSeed((size_t) std::time(NULL)); + RandomSeed((size_t) std::time(NULL)); RequireAtLeastOnePassed(params, { "output" }, false, "no output will be saved"); diff --git a/src/mlpack/methods/lsh/lsh_main.cpp b/src/mlpack/methods/lsh/lsh_main.cpp index 66d93a46cd..48365e5a27 100644 --- a/src/mlpack/methods/lsh/lsh_main.cpp +++ b/src/mlpack/methods/lsh/lsh_main.cpp @@ -12,6 +12,7 @@ */ #include #include +#include #ifdef BINDING_NAME #undef BINDING_NAME @@ -19,13 +20,13 @@ #define BINDING_NAME lsh #include - #include #include "lsh_search.hpp" using namespace std; using namespace mlpack; +using namespace mlpack::math; using namespace mlpack::neighbor; using namespace mlpack::util; @@ -114,9 +115,9 @@ PARAM_INT_IN("seed", "Random seed. If 0, 'std::time(NULL)' is used.", "s", 0); void BINDING_FUNCTION(util::Params& params, util::Timers& timers) { if (params.Get("seed") != 0) - math::RandomSeed((size_t) params.Get("seed")); + RandomSeed((size_t) params.Get("seed")); else - math::RandomSeed((size_t) time(NULL)); + RandomSeed((size_t) time(NULL)); // Get all the parameters after checking them. if (params.Has("k")) diff --git a/src/mlpack/methods/nca/nca_main.cpp b/src/mlpack/methods/nca/nca_main.cpp index 44bb94dc3e..79b22e6f15 100644 --- a/src/mlpack/methods/nca/nca_main.cpp +++ b/src/mlpack/methods/nca/nca_main.cpp @@ -144,6 +144,7 @@ PARAM_DOUBLE_IN("max_step", "Maximum step of line search for L-BFGS.", "M", PARAM_INT_IN("seed", "Random seed. If 0, 'std::time(NULL)' is used.", "s", 0); using namespace mlpack; +using namespace mlpack::math; using namespace mlpack::nca; using namespace mlpack::metric; using namespace mlpack::util; @@ -152,9 +153,9 @@ using namespace std; void BINDING_FUNCTION(util::Params& params, util::Timers& timers) { if (params.Get("seed") != 0) - math::RandomSeed((size_t) params.Get("seed")); + RandomSeed((size_t) params.Get("seed")); else - math::RandomSeed((size_t) std::time(NULL)); + RandomSeed((size_t) std::time(NULL)); RequireAtLeastOnePassed(params, { "output" }, false, "no output will be saved"); diff --git a/src/mlpack/methods/neighbor_search/kfn_main.cpp b/src/mlpack/methods/neighbor_search/kfn_main.cpp index a0a902ddb9..0b6c1b01c9 100644 --- a/src/mlpack/methods/neighbor_search/kfn_main.cpp +++ b/src/mlpack/methods/neighbor_search/kfn_main.cpp @@ -12,6 +12,7 @@ */ #include #include +#include #ifdef BINDING_NAME #undef BINDING_NAME @@ -30,6 +31,7 @@ using namespace std; using namespace mlpack; +using namespace mlpack::math; using namespace mlpack::neighbor; using namespace mlpack::tree; using namespace mlpack::metric; @@ -124,9 +126,9 @@ PARAM_DOUBLE_IN("percentage", "If specified, will do approximate furthest " void BINDING_FUNCTION(util::Params& params, util::Timers& timers) { if (params.Get("seed") != 0) - math::RandomSeed((size_t) params.Get("seed")); + RandomSeed((size_t) params.Get("seed")); else - math::RandomSeed((size_t) std::time(NULL)); + RandomSeed((size_t) std::time(NULL)); // A user cannot specify both reference data and a model. RequireOnlyOnePassed(params, { "reference", "input_model" }, true); diff --git a/src/mlpack/methods/neighbor_search/knn_main.cpp b/src/mlpack/methods/neighbor_search/knn_main.cpp index 9a071caf3b..5ade397868 100644 --- a/src/mlpack/methods/neighbor_search/knn_main.cpp +++ b/src/mlpack/methods/neighbor_search/knn_main.cpp @@ -12,6 +12,7 @@ */ #include #include +#include #ifdef BINDING_NAME #undef BINDING_NAME @@ -32,6 +33,7 @@ using namespace std; using namespace mlpack; +using namespace mlpack::math; using namespace mlpack::neighbor; using namespace mlpack::tree; using namespace mlpack::metric; @@ -132,9 +134,9 @@ PARAM_DOUBLE_IN("epsilon", "If specified, will do approximate nearest neighbor " void BINDING_FUNCTION(util::Params& params, util::Timers& timers) { if (params.Get("seed") != 0) - math::RandomSeed((size_t) params.Get("seed")); + RandomSeed((size_t) params.Get("seed")); else - math::RandomSeed((size_t) std::time(NULL)); + RandomSeed((size_t) std::time(NULL)); // A user cannot specify both reference data and a model. RequireOnlyOnePassed(params, { "reference", "input_model" }, true); diff --git a/src/mlpack/methods/nmf/nmf_main.cpp b/src/mlpack/methods/nmf/nmf_main.cpp index eab57c5cb7..364ede383f 100644 --- a/src/mlpack/methods/nmf/nmf_main.cpp +++ b/src/mlpack/methods/nmf/nmf_main.cpp @@ -11,6 +11,7 @@ */ #include #include +#include #ifdef BINDING_NAME #undef BINDING_NAME @@ -29,6 +30,7 @@ #include using namespace mlpack; +using namespace mlpack::math; using namespace mlpack::amf; using namespace mlpack::util; using namespace std; @@ -217,9 +219,9 @@ void BINDING_FUNCTION(util::Params& params, util::Timers& /* timers */) { // Initialize random seed. if (params.Get("seed") != 0) - math::RandomSeed((size_t) params.Get("seed")); + RandomSeed((size_t) params.Get("seed")); else - math::RandomSeed((size_t) std::time(NULL)); + RandomSeed((size_t) std::time(NULL)); // Gather parameters. const size_t r = params.Get("rank"); diff --git a/src/mlpack/methods/preprocess/preprocess_scale_main.cpp b/src/mlpack/methods/preprocess/preprocess_scale_main.cpp index 351421e89d..d345b80715 100644 --- a/src/mlpack/methods/preprocess/preprocess_scale_main.cpp +++ b/src/mlpack/methods/preprocess/preprocess_scale_main.cpp @@ -29,6 +29,7 @@ #include "mlpack/methods/preprocess/scaling_model.hpp" using namespace mlpack; +using namespace mlpack::math; using namespace mlpack::util; using namespace mlpack::data; using namespace arma; @@ -122,9 +123,9 @@ void BINDING_FUNCTION(util::Params& params, util::Timers& timers) const std::string scalerMethod = params.Get("scaler_method"); if (params.Get("seed") == 0) - mlpack::math::RandomSeed(std::time(NULL)); + RandomSeed(std::time(NULL)); else - mlpack::math::RandomSeed((size_t) params.Get("seed")); + RandomSeed((size_t) params.Get("seed")); // Make sure the user specified output filenames. RequireAtLeastOnePassed(params, { "output", "output_model"}, false, diff --git a/src/mlpack/methods/preprocess/preprocess_split_main.cpp b/src/mlpack/methods/preprocess/preprocess_split_main.cpp index d74801895c..d088b9c659 100644 --- a/src/mlpack/methods/preprocess/preprocess_split_main.cpp +++ b/src/mlpack/methods/preprocess/preprocess_split_main.cpp @@ -106,6 +106,7 @@ PARAM_FLAG("no_shuffle", "Avoid shuffling the data before splitting.", "S"); PARAM_FLAG("stratify_data", "Stratify the data according to labels", "z") using namespace mlpack; +using namespace mlpack::math; using namespace mlpack::data; using namespace mlpack::util; using namespace arma; @@ -119,9 +120,9 @@ void BINDING_FUNCTION(util::Params& params, util::Timers& timers) const bool stratifyData = params.Get("stratify_data"); if (params.Get("seed") == 0) - mlpack::math::RandomSeed(std::time(NULL)); + RandomSeed(std::time(NULL)); else - mlpack::math::RandomSeed((size_t) params.Get("seed")); + RandomSeed((size_t) params.Get("seed")); // Make sure the user specified output filenames. RequireAtLeastOnePassed(params, { "training" }, false, "no training set will " diff --git a/src/mlpack/methods/random_forest/random_forest_main.cpp b/src/mlpack/methods/random_forest/random_forest_main.cpp index d2663c8d09..ff724f0f46 100644 --- a/src/mlpack/methods/random_forest/random_forest_main.cpp +++ b/src/mlpack/methods/random_forest/random_forest_main.cpp @@ -18,10 +18,12 @@ #define BINDING_NAME random_forest #include +#include #include #include using namespace mlpack; +using namespace mlpack::math; using namespace mlpack::tree; using namespace mlpack::util; using namespace std; @@ -171,9 +173,9 @@ void BINDING_FUNCTION(util::Params& params, util::Timers& timers) { // Initialize random seed if needed. if (params.Get("seed") != 0) - math::RandomSeed((size_t) params.Get("seed")); + RandomSeed((size_t) params.Get("seed")); else - math::RandomSeed((size_t) std::time(NULL)); + RandomSeed((size_t) std::time(NULL)); // Check for incompatible input parameters. if (!params.Has("warm_start")) diff --git a/src/mlpack/methods/range_search/range_search_main.cpp b/src/mlpack/methods/range_search/range_search_main.cpp index b745eaabb3..26343d2715 100644 --- a/src/mlpack/methods/range_search/range_search_main.cpp +++ b/src/mlpack/methods/range_search/range_search_main.cpp @@ -13,6 +13,7 @@ */ #include #include +#include #ifdef BINDING_NAME #undef BINDING_NAME @@ -28,6 +29,7 @@ using namespace std; using namespace mlpack; +using namespace mlpack::math; using namespace mlpack::range; using namespace mlpack::tree; using namespace mlpack::metric; @@ -123,9 +125,9 @@ PARAM_FLAG("single_mode", "If true, single-tree search is used (as opposed to " void BINDING_FUNCTION(util::Params& params, util::Timers& timers) { if (params.Get("seed") != 0) - math::RandomSeed((size_t) params.Get("seed")); + RandomSeed((size_t) params.Get("seed")); else - math::RandomSeed((size_t) std::time(NULL)); + RandomSeed((size_t) std::time(NULL)); // A user cannot specify both reference data and a model. RequireOnlyOnePassed(params, { "reference", "input_model" }, true); diff --git a/src/mlpack/methods/rann/krann_main.cpp b/src/mlpack/methods/rann/krann_main.cpp index 4085bd4c9b..ad73b16ae0 100644 --- a/src/mlpack/methods/rann/krann_main.cpp +++ b/src/mlpack/methods/rann/krann_main.cpp @@ -19,13 +19,14 @@ #define BINDING_NAME krann #include - +#include +#include #include "ra_search.hpp" #include "ra_model.hpp" -#include using namespace std; using namespace mlpack; +using namespace mlpack::math; using namespace mlpack::neighbor; using namespace mlpack::tree; using namespace mlpack::metric; @@ -127,9 +128,9 @@ PARAM_INT_IN("single_sample_limit", "The limit on the maximum number of " void BINDING_FUNCTION(util::Params& params, util::Timers& timers) { if (params.Get("seed") != 0) - math::RandomSeed((size_t) params.Get("seed")); + RandomSeed((size_t) params.Get("seed")); else - math::RandomSeed((size_t) std::time(NULL)); + RandomSeed((size_t) std::time(NULL)); // A user cannot specify both reference data and a model. RequireOnlyOnePassed(params, { "reference", "input_model" }, true); diff --git a/src/mlpack/methods/reinforcement_learning/q_networks/categorical_dqn.hpp b/src/mlpack/methods/reinforcement_learning/q_networks/categorical_dqn.hpp index aab2c4bc1b..ba5c1f7abb 100644 --- a/src/mlpack/methods/reinforcement_learning/q_networks/categorical_dqn.hpp +++ b/src/mlpack/methods/reinforcement_learning/q_networks/categorical_dqn.hpp @@ -23,8 +23,6 @@ namespace mlpack { namespace rl { -using namespace mlpack::ann; - /** * Implementation of the Categorical Deep Q-Learning network. * For more information, see the following. @@ -43,9 +41,9 @@ using namespace mlpack::ann; * @tparam NetworkType The type of network used for simple dqn. */ template< - typename OutputLayerType = EmptyLoss<>, - typename InitType = GaussianInitialization, - typename NetworkType = FFN + typename OutputLayerType = ann::EmptyLoss<>, + typename InitType = ann::GaussianInitialization, + typename NetworkType = ann::FFN > class CategoricalDQN { @@ -83,21 +81,21 @@ class CategoricalDQN vMax(config.VMax()), isNoisy(isNoisy) { - network.Add(new Linear<>(inputDim, h1)); - network.Add(new ReLULayer<>()); + network.Add(new ann::Linear<>(inputDim, h1)); + network.Add(new ann::ReLULayer<>()); if (isNoisy) { noisyLayerIndex.push_back(network.Model().size()); - network.Add(new NoisyLinear<>(h1, h2)); - network.Add(new ReLULayer<>()); + network.Add(new ann::NoisyLinear<>(h1, h2)); + network.Add(new ann::ReLULayer<>()); noisyLayerIndex.push_back(network.Model().size()); - network.Add(new NoisyLinear<>(h2, outputDim * atomSize)); + network.Add(new ann::NoisyLinear<>(h2, outputDim * atomSize)); } else { - network.Add(new Linear<>(h1, h2)); - network.Add(new ReLULayer<>()); - network.Add(new Linear<>(h2, outputDim * atomSize)); + network.Add(new ann::Linear<>(h1, h2)); + network.Add(new ann::ReLULayer<>()); + network.Add(new ann::Linear<>(h2, outputDim * atomSize)); } } @@ -181,9 +179,9 @@ class CategoricalDQN */ void ResetNoise() { - for (size_t i = 0; i < noisyLayerIndex.size(); i++) + for (size_t i = 0; i < noisyLayerIndex.size(); ++i) { - boost::get*> + boost::get*> (network.Model()[noisyLayerIndex[i]])->ResetNoise(); } } @@ -236,7 +234,7 @@ class CategoricalDQN std::vector noisyLayerIndex; //! Locally-stored softmax activation function. - Softmax<> softMax; + ann::Softmax<> softMax; //! Locally-stored activations from softMax. arma::mat activations; diff --git a/src/mlpack/methods/reinforcement_learning/q_networks/dueling_dqn.hpp b/src/mlpack/methods/reinforcement_learning/q_networks/dueling_dqn.hpp index 6a160a48ac..c4b26a353f 100644 --- a/src/mlpack/methods/reinforcement_learning/q_networks/dueling_dqn.hpp +++ b/src/mlpack/methods/reinforcement_learning/q_networks/dueling_dqn.hpp @@ -22,8 +22,6 @@ namespace mlpack { namespace rl { -using namespace mlpack::ann; - /** * Implementation of the Dueling Deep Q-Learning network. * For more information, see the following. @@ -46,12 +44,12 @@ using namespace mlpack::ann; * @tparam ValueNetworkType The type of network used for value network. */ template < - typename OutputLayerType = EmptyLoss<>, - typename InitType = GaussianInitialization, - typename CompleteNetworkType = FFN, - typename FeatureNetworkType = Sequential<>, - typename AdvantageNetworkType = Sequential<>, - typename ValueNetworkType = Sequential<> + typename OutputLayerType = ann::EmptyLoss<>, + typename InitType = ann::GaussianInitialization, + typename CompleteNetworkType = ann::FFN, + typename FeatureNetworkType = ann::Sequential<>, + typename AdvantageNetworkType = ann::Sequential<>, + typename ValueNetworkType = ann::Sequential<> > class DuelingDQN { @@ -59,14 +57,14 @@ class DuelingDQN //! Default constructor. DuelingDQN() : isNoisy(false) { - featureNetwork = new Sequential<>(); - valueNetwork = new Sequential<>(); - advantageNetwork = new Sequential<>(); - concat = new Concat<>(true); + featureNetwork = new ann::Sequential<>(); + valueNetwork = new ann::Sequential<>(); + advantageNetwork = new ann::Sequential<>(); + concat = new ann::Concat<>(true); concat->Add(valueNetwork); concat->Add(advantageNetwork); - completeNetwork.Add(new IdentityLayer<>()); + completeNetwork.Add(new ann::IdentityLayer<>()); completeNetwork.Add(featureNetwork); completeNetwork.Add(concat); } @@ -92,42 +90,42 @@ class DuelingDQN completeNetwork(outputLayer, init), isNoisy(isNoisy) { - featureNetwork = new Sequential<>(); - featureNetwork->Add(new Linear<>(inputDim, h1)); - featureNetwork->Add(new ReLULayer<>()); + featureNetwork = new ann::Sequential<>(); + featureNetwork->Add(new ann::Linear<>(inputDim, h1)); + featureNetwork->Add(new ann::ReLULayer<>()); - valueNetwork = new Sequential<>(); - advantageNetwork = new Sequential<>(); + valueNetwork = new ann::Sequential<>(); + advantageNetwork = new ann::Sequential<>(); if (isNoisy) { noisyLayerIndex.push_back(valueNetwork->Model().size()); - valueNetwork->Add(new NoisyLinear<>(h1, h2)); - advantageNetwork->Add(new NoisyLinear<>(h1, h2)); + valueNetwork->Add(new ann::NoisyLinear<>(h1, h2)); + advantageNetwork->Add(new ann::NoisyLinear<>(h1, h2)); - valueNetwork->Add(new ReLULayer<>()); - advantageNetwork->Add(new ReLULayer<>()); + valueNetwork->Add(new ann::ReLULayer<>()); + advantageNetwork->Add(new ann::ReLULayer<>()); noisyLayerIndex.push_back(valueNetwork->Model().size()); - valueNetwork->Add(new NoisyLinear<>(h2, 1)); - advantageNetwork->Add(new NoisyLinear<>(h2, outputDim)); + valueNetwork->Add(new ann::NoisyLinear<>(h2, 1)); + advantageNetwork->Add(new ann::NoisyLinear<>(h2, outputDim)); } else { - valueNetwork->Add(new Linear<>(h1, h2)); - valueNetwork->Add(new ReLULayer<>()); - valueNetwork->Add(new Linear<>(h2, 1)); + valueNetwork->Add(new ann::Linear<>(h1, h2)); + valueNetwork->Add(new ann::ReLULayer<>()); + valueNetwork->Add(new ann::Linear<>(h2, 1)); - advantageNetwork->Add(new Linear<>(h1, h2)); - advantageNetwork->Add(new ReLULayer<>()); - advantageNetwork->Add(new Linear<>(h2, outputDim)); + advantageNetwork->Add(new ann::Linear<>(h1, h2)); + advantageNetwork->Add(new ann::ReLULayer<>()); + advantageNetwork->Add(new ann::Linear<>(h2, outputDim)); } - concat = new Concat<>(true); + concat = new ann::Concat<>(true); concat->Add(valueNetwork); concat->Add(advantageNetwork); - completeNetwork.Add(new IdentityLayer<>()); + completeNetwork.Add(new ann::IdentityLayer<>()); completeNetwork.Add(featureNetwork); completeNetwork.Add(concat); this->ResetParameters(); @@ -150,10 +148,10 @@ class DuelingDQN valueNetwork(valueNetwork), isNoisy(isNoisy) { - concat = new Concat<>(true); + concat = new ann::Concat<>(true); concat->Add(valueNetwork); concat->Add(advantageNetwork); - completeNetwork.Add(new IdentityLayer<>()); + completeNetwork.Add(new ann::IdentityLayer<>()); completeNetwork.Add(featureNetwork); completeNetwork.Add(concat); this->ResetParameters(); @@ -245,9 +243,9 @@ class DuelingDQN { for (size_t i = 0; i < noisyLayerIndex.size(); i++) { - boost::get*> + boost::get*> (valueNetwork->Model()[noisyLayerIndex[i]])->ResetNoise(); - boost::get*> + boost::get*> (advantageNetwork->Model()[noisyLayerIndex[i]])->ResetNoise(); } } @@ -262,7 +260,7 @@ class DuelingDQN CompleteNetworkType completeNetwork; //! Locally-stored concat network. - Concat<>* concat; + ann::Concat<>* concat; //! Locally-stored feature network. FeatureNetworkType* featureNetwork; @@ -283,7 +281,7 @@ class DuelingDQN arma::mat actionValues; //! Locally-stored loss function. - MeanSquaredError<> lossFunction; + ann::MeanSquaredError<> lossFunction; }; } // namespace rl diff --git a/src/mlpack/methods/reinforcement_learning/q_networks/simple_dqn.hpp b/src/mlpack/methods/reinforcement_learning/q_networks/simple_dqn.hpp index 818e004a4d..54ad55f01e 100644 --- a/src/mlpack/methods/reinforcement_learning/q_networks/simple_dqn.hpp +++ b/src/mlpack/methods/reinforcement_learning/q_networks/simple_dqn.hpp @@ -21,17 +21,15 @@ namespace mlpack { namespace rl { -using namespace mlpack::ann; - /** * @tparam OutputLayerType The output layer type of the network. * @tparam InitType The initialization type used for the network. * @tparam NetworkType The type of network used for simple dqn. */ template< - typename OutputLayerType = MeanSquaredError<>, - typename InitType = GaussianInitialization, - typename NetworkType = FFN + typename OutputLayerType = ann::MeanSquaredError<>, + typename InitType = ann::GaussianInitialization, + typename NetworkType = ann::FFN > class SimpleDQN { @@ -63,21 +61,21 @@ class SimpleDQN network(outputLayer, init), isNoisy(isNoisy) { - network.Add(new Linear<>(inputDim, h1)); - network.Add(new ReLULayer<>()); + network.Add(new ann::Linear<>(inputDim, h1)); + network.Add(new ann::ReLULayer<>()); if (isNoisy) { noisyLayerIndex.push_back(network.Model().size()); - network.Add(new NoisyLinear<>(h1, h2)); - network.Add(new ReLULayer<>()); + network.Add(new ann::NoisyLinear<>(h1, h2)); + network.Add(new ann::ReLULayer<>()); noisyLayerIndex.push_back(network.Model().size()); - network.Add(new NoisyLinear<>(h2, outputDim)); + network.Add(new ann::NoisyLinear<>(h2, outputDim)); } else { - network.Add(new Linear<>(h1, h2)); - network.Add(new ReLULayer<>()); - network.Add(new Linear<>(h2, outputDim)); + network.Add(new ann::Linear<>(h1, h2)); + network.Add(new ann::ReLULayer<>()); + network.Add(new ann::Linear<>(h2, outputDim)); } } @@ -134,7 +132,7 @@ class SimpleDQN { for (size_t i = 0; i < noisyLayerIndex.size(); i++) { - boost::get*> + boost::get*> (network.Model()[noisyLayerIndex[i]])->ResetNoise(); } }