Merge pull request #3091 from shrit/header-only

mlpack Header only initiative
This commit is contained in:
Omar Shrit
2022-04-17 11:13:01 +01:00
committed by GitHub
57 changed files with 1079 additions and 974 deletions
+42
View File
@@ -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()
+15
View File
@@ -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 <stb_image.h>
#include <stb_image_write.h>
void A::A()
{
// Do nothing, just to check if the STB library is a working version.
}
+10
View File
@@ -0,0 +1,10 @@
#ifndef A_HPP
#define A_HPP
namespace A {
void A();
}
#endif
+15
View File
@@ -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 <stb_image.h>
#include <stb_image_write.h>
void B::B()
{
// Do nothing, just to check if the STB library is a working version.
}
+10
View File
@@ -0,0 +1,10 @@
#ifndef B_HPP
#define B_HPP
namespace B {
void B();
}
#endif
+16
View File
@@ -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();
}
+9
View File
@@ -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.
+4 -3
View File
@@ -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
+7 -5
View File
@@ -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
@@ -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);
+19 -8
View File
@@ -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<std::string> LoadFileTypes()
{
return std::vector<std::string>({"jpg", "png", "tga", "bmp", "psd", "gif",
"hdr", "pic", "pnm", "jpeg"});
}
inline const std::vector<std::string> SaveFileTypes()
{
return std::vector<std::string>({"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<std::string> loadFileTypes({"jpg", "png", "tga",
"bmp", "psd", "gif", "hdr", "pic", "pnm", "jpeg"});
static const std::vector<std::string> 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;
+2 -43
View File
@@ -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<typename eT>
bool Load(const std::string& filename,
arma::Mat<eT>& 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<typename eT>
bool Load(const std::vector<std::string>& files,
arma::Mat<eT>& matrix,
ImageInfo& info,
const bool fatal = false);
// Implementation found in load_image.cpp.
bool LoadImage(const std::string& filename,
arma::Mat<unsigned char>& 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
-129
View File
@@ -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 <stb_image.h>
namespace mlpack {
namespace data {
bool LoadImage(const std::string& filename,
arma::Mat<unsigned char>& 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<unsigned char>(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<unsigned char>& /* 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
+77
View File
@@ -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 <stb_image.h>
#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<typename eT>
bool Load(const std::string& filename,
arma::Mat<eT>& 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<typename eT>
bool Load(const std::vector<std::string>& files,
arma::Mat<eT>& matrix,
ImageInfo& info,
const bool fatal = false);
// Implementation found in load_image.hpp.
inline bool LoadImage(const std::string& filename,
arma::Mat<unsigned char>& matrix,
ImageInfo& info,
const bool fatal = false);
} // namespace data
} // namespace mlpack
// Include implementation of Load() for images.
#include "load_image_impl.hpp"
#endif
+101 -3
View File
@@ -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<std::string>& files,
return true;
}
#ifdef HAS_STB
inline bool LoadImage(const std::string& filename,
arma::Mat<unsigned char>& 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<unsigned char>(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<unsigned char>& /* 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
+1 -2
View File
@@ -16,13 +16,12 @@
// In case it hasn't already been included.
#include "load.hpp"
#include <exception>
#include <algorithm>
#include <exception>
#include <mlpack/core/util/timers.hpp>
#include "extension.hpp"
#include "detect_file_type.hpp"
#include "string_algorithms.hpp"
namespace mlpack {
+2 -38
View File
@@ -14,6 +14,7 @@
#ifndef MLPACK_CORE_DATA_SAVE_HPP
#define MLPACK_CORE_DATA_SAVE_HPP
#include <mlpack/prereqs.hpp>
#include <mlpack/core/util/log.hpp>
#include <mlpack/core/arma_extend/arma_extend.hpp> // Includes Armadillo.
#include <string>
@@ -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<typename eT>
bool Save(const std::string& filename,
arma::Mat<eT>& 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<typename eT>
bool Save(const std::vector<std::string>& files,
arma::Mat<eT>& 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<unsigned char>& image,
ImageInfo& info,
const bool fatal = false);
} // namespace data
} // namespace mlpack
+72
View File
@@ -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 <stb_image_write.h>
#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<typename eT>
bool Save(const std::string& filename,
arma::Mat<eT>& 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<typename eT>
bool Save(const std::vector<std::string>& files,
arma::Mat<eT>& 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<unsigned char>& image,
ImageInfo& info,
const bool fatal = false);
} //namespace data
} //namespace mlpack
// Include implementation of Save() for images.
#include "save_image_impl.hpp"
#endif
@@ -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 <stb_image_write.h>
#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<unsigned char>& 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<typename eT>
bool Save(const std::string& filename,
arma::Mat<eT>& matrix,
ImageInfo& info,
const bool fatal)
{
arma::Mat<unsigned char> tmpMatrix =
arma::conv_to<arma::Mat<unsigned char>>::from(matrix);
return SaveImage(filename, tmpMatrix, info, fatal);
}
// Image saving API for multiple files.
template<typename eT>
bool Save(const std::vector<std::string>& files,
arma::Mat<eT>& 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<unsigned char> img;
bool status = true;
for (size_t i = 0; i < files.size() ; ++i)
{
arma::Mat<eT> 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<unsigned char>& 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<unsigned char>& /* image */,
ImageInfo& /* info */,
const bool fatal)
inline bool SaveImage(const std::string& /* filename */,
arma::Mat<unsigned char>& /* 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
-61
View File
@@ -16,10 +16,6 @@
#include "save.hpp"
#include "extension.hpp"
#include <cereal/archives/xml.hpp>
#include <cereal/archives/json.hpp>
#include <cereal/archives/binary.hpp>
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<typename eT>
bool Save(const std::string& filename,
arma::Mat<eT>& matrix,
ImageInfo& info,
const bool fatal)
{
arma::Mat<unsigned char> tmpMatrix =
arma::conv_to<arma::Mat<unsigned char>>::from(matrix);
// Call out to .cpp implementation.
return SaveImage(filename, tmpMatrix, info, fatal);
}
// Image saving API for multiple files.
template<typename eT>
bool Save(const std::vector<std::string>& files,
arma::Mat<eT>& 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<unsigned char> img;
bool status = true;
for (size_t i = 0; i < files.size() ; ++i)
{
arma::Mat<eT> colImg(matrix.colptr(i), matrix.n_rows, 1,
false, true);
status &= Save(files[i], colImg, info, fatal);
}
return status;
}
} // namespace data
} // namespace mlpack
-2
View File
@@ -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
)
@@ -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;
}
}
@@ -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.
@@ -41,8 +41,8 @@ inline double EpanechnikovKernel::Evaluate(const VecTypeA& a, const VecTypeB& b)
* @return the convolution integral value.
*/
template<typename VecTypeA, typename VecTypeB>
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<typename Archive>
void EpanechnikovKernel::serialize(Archive& ar,
@@ -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<std::vector<std::string> >& 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<std::string>& 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<std::string, int>& 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;
}
@@ -72,8 +72,8 @@ class PSpectrumStringKernel
* @param datasets Sets of string data.
* @param p The length of substrings to search.
*/
PSpectrumStringKernel(const std::vector<std::vector<std::string> >& datasets,
const size_t p);
inline PSpectrumStringKernel(const std::vector<std::vector<std::string> >& datasets,
const size_t p);
/**
* Evaluate the kernel for the string indices given. As mentioned in the
@@ -22,6 +22,64 @@
namespace mlpack {
namespace kernel {
inline PSpectrumStringKernel::PSpectrumStringKernel(
const std::vector<std::vector<std::string> >& 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<std::string>& 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<std::string, int>& 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
+1 -2
View File
@@ -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
-279
View File
@@ -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 <mlpack/core.hpp>
#include <mlpack/core/math/random.hpp>
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<size_t>& 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<size_t>
(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++;
}
}
}
+17 -15
View File
@@ -13,6 +13,8 @@
#define MLPACK_CORE_MATH_LIN_ALG_HPP
#include <mlpack/prereqs.hpp>
#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<size_t>& rowsToRemove,
arma::mat& output);
inline void RemoveRows(const arma::mat& input,
const std::vector<size_t>& 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.
+264
View File
@@ -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<size_t>& 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<size_t>
(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
+4 -1
View File
@@ -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
@@ -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<mat>(d, d)))
arma::mat r;
if (qr(basis, r, arma::randn<arma::mat>(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)
@@ -17,8 +17,6 @@
#include <mlpack/prereqs.hpp>
#include <mlpack/core/math/random.hpp>
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)); } );
}
/**
@@ -18,8 +18,6 @@
#include "random_init.hpp"
#include "gaussian_init.hpp"
using namespace mlpack::math;
namespace mlpack {
namespace ann /** Artificial Neural Network. */ {
+36 -38
View File
@@ -16,8 +16,6 @@
#include <boost/variant/static_visitor.hpp>
#include <string>
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<std::string>
* @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<std::string>
* @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<std::string>
* @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<std::string>
* @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<std::string>
* @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<std::string>
* @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<std::string>
* @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<std::string>
* @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<std::string>
* @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<std::string>
* @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<std::string>
* @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<std::string>
* @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<std::string>
* @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<std::string>
* @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<std::string>
* @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<std::string>
* @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<std::string>
* @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<std::string>
* @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<std::string>
* @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<std::string>
* @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<std::string>
* @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<std::string>
* @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<std::string>
* @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<std::string>
* @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<std::string>
* @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<std::string>
* @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<std::string>
* @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<std::string>
* @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<std::string>
* @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<std::string>
* @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<std::string>
* @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<std::string>
* @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<std::string>
* @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<std::string>
* @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<std::string>
* @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<std::string>
}
//! Overload function call.
std::string operator()(MoreTypes layer) const
std::string operator()(mlpack::ann::MoreTypes layer) const
{
return layer.apply_visitor(*this);
}
+3 -2
View File
@@ -40,6 +40,7 @@
#include <mlpack/methods/cf/neighbor_search_policies/pearson_search.hpp>
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<int>("seed") == 0)
math::RandomSeed(std::time(NULL));
RandomSeed(std::time(NULL));
else
math::RandomSeed(params.Get<int>("seed"));
RandomSeed(params.Get<int>("seed"));
// Validate parameters.
RequireOnlyOnePassed(params, { "training", "input_model" }, true);
+13 -11
View File
@@ -15,11 +15,9 @@
#include <stack>
#include <vector>
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<MatType, TagType>::FindSplit(const MatType& data,
}
template<typename MatType, typename TagType>
size_t DTree<MatType, TagType>::SplitData(MatType& data,
const size_t splitDim,
const ElemType splitValue,
arma::Col<size_t>& oldFromNew) const
size_t DTree<MatType, TagType>::SplitData(
MatType& data,
const size_t splitDim,
const ElemType splitValue,
arma::Col<size_t>& 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<MatType, TagType>::FindBucket(const VecType& query) const
}
template<typename MatType, typename TagType>
void DTree<MatType, TagType>::ComputeVariableImportance(arma::vec& importances)
const
void DTree<MatType, TagType>::ComputeVariableImportance(
arma::vec& importances) const
{
// Clear and set to right size.
importances.zeros(maxVals.n_elem);
@@ -1036,3 +1035,6 @@ void DTree<MatType, TagType>::serialize(Archive& ar,
FillMinMax(minVals, maxVals);
}
}
} // namespace det
} // namespace mlpack
+4 -2
View File
@@ -11,6 +11,7 @@
*/
#include <mlpack/prereqs.hpp>
#include <mlpack/core/util/io.hpp>
#include <mlpack/core/math/random.hpp>
#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<int>("seed") == 0)
mlpack::math::RandomSeed(time(NULL));
RandomSeed(time(NULL));
else
mlpack::math::RandomSeed((size_t) params.Get<int>("seed"));
RandomSeed((size_t) params.Get<int>("seed"));
RequireParamValue<int>(params, "samples", [](int x) { return x > 0; }, true,
"number of samples must be greater than 0");
+4 -2
View File
@@ -18,6 +18,7 @@
#define BINDING_NAME gmm_train
#include <mlpack/core/util/mlpack_main.hpp>
#include <mlpack/core/math/random.hpp>
#include "gmm.hpp"
#include "diagonal_gmm.hpp"
@@ -27,6 +28,7 @@
#include <mlpack/methods/kmeans/refined_start.hpp>
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<int>("seed") != 0)
math::RandomSeed((size_t) params.Get<int>("seed"));
RandomSeed((size_t) params.Get<int>("seed"));
else
math::RandomSeed((size_t) std::time(NULL));
RandomSeed((size_t) std::time(NULL));
RequireParamValue<int>(params, "gaussians", [](int x) { return x > 0; }, true,
"number of Gaussians must be positive");
+2 -4
View File
@@ -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<ActionType, ArchiveType,
HMM<DiscreteDistribution>>(ar, x);
HMM<distribution::DiscreteDistribution>>(ar, x);
break;
case HMMType::GaussianHMM:
DeserializeHMMAndPerformAction<ActionType, ArchiveType,
HMM<GaussianDistribution>>(ar, x);
HMM<distribution::GaussianDistribution>>(ar, x);
break;
case HMMType::GaussianMixtureModelHMM:
+4 -2
View File
@@ -11,6 +11,7 @@
*/
#include <mlpack/prereqs.hpp>
#include <mlpack/core/util/io.hpp>
#include <mlpack/core/math/random.hpp>
#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<int>("seed") != 0)
math::RandomSeed((size_t) params.Get<int>("seed"));
RandomSeed((size_t) params.Get<int>("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);
@@ -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<int>("seed") != 0)
math::RandomSeed((size_t) params.Get<int>("seed"));
RandomSeed((size_t) params.Get<int>("seed"));
else
math::RandomSeed((size_t) std::time(NULL));
RandomSeed((size_t) std::time(NULL));
// Collect command-line options.
const double lambda = params.Get<double>("lambda");
+3 -2
View File
@@ -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<int>("seed") != 0)
math::RandomSeed((size_t) params.Get<int>("seed"));
RandomSeed((size_t) params.Get<int>("seed"));
else
math::RandomSeed((size_t) std::time(NULL));
RandomSeed((size_t) std::time(NULL));
RequireAtLeastOnePassed(params, { "output" }, false,
"no output will be saved");
+4 -3
View File
@@ -12,6 +12,7 @@
*/
#include <mlpack/prereqs.hpp>
#include <mlpack/core/util/io.hpp>
#include <mlpack/core/math/random.hpp>
#ifdef BINDING_NAME
#undef BINDING_NAME
@@ -19,13 +20,13 @@
#define BINDING_NAME lsh
#include <mlpack/core/util/mlpack_main.hpp>
#include <mlpack/core/metrics/lmetric.hpp>
#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<int>("seed") != 0)
math::RandomSeed((size_t) params.Get<int>("seed"));
RandomSeed((size_t) params.Get<int>("seed"));
else
math::RandomSeed((size_t) time(NULL));
RandomSeed((size_t) time(NULL));
// Get all the parameters after checking them.
if (params.Has("k"))
+3 -2
View File
@@ -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<int>("seed") != 0)
math::RandomSeed((size_t) params.Get<int>("seed"));
RandomSeed((size_t) params.Get<int>("seed"));
else
math::RandomSeed((size_t) std::time(NULL));
RandomSeed((size_t) std::time(NULL));
RequireAtLeastOnePassed(params, { "output" }, false,
"no output will be saved");
@@ -12,6 +12,7 @@
*/
#include <mlpack/prereqs.hpp>
#include <mlpack/core/util/io.hpp>
#include <mlpack/core/math/random.hpp>
#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<int>("seed") != 0)
math::RandomSeed((size_t) params.Get<int>("seed"));
RandomSeed((size_t) params.Get<int>("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);
@@ -12,6 +12,7 @@
*/
#include <mlpack/prereqs.hpp>
#include <mlpack/core/util/io.hpp>
#include <mlpack/core/math/random.hpp>
#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<int>("seed") != 0)
math::RandomSeed((size_t) params.Get<int>("seed"));
RandomSeed((size_t) params.Get<int>("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);
+4 -2
View File
@@ -11,6 +11,7 @@
*/
#include <mlpack/prereqs.hpp>
#include <mlpack/core/util/io.hpp>
#include <mlpack/core/math/random.hpp>
#ifdef BINDING_NAME
#undef BINDING_NAME
@@ -29,6 +30,7 @@
#include <mlpack/methods/amf/termination_policies/simple_residue_termination.hpp>
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<int>("seed") != 0)
math::RandomSeed((size_t) params.Get<int>("seed"));
RandomSeed((size_t) params.Get<int>("seed"));
else
math::RandomSeed((size_t) std::time(NULL));
RandomSeed((size_t) std::time(NULL));
// Gather parameters.
const size_t r = params.Get<int>("rank");
@@ -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<string>("scaler_method");
if (params.Get<int>("seed") == 0)
mlpack::math::RandomSeed(std::time(NULL));
RandomSeed(std::time(NULL));
else
mlpack::math::RandomSeed((size_t) params.Get<int>("seed"));
RandomSeed((size_t) params.Get<int>("seed"));
// Make sure the user specified output filenames.
RequireAtLeastOnePassed(params, { "output", "output_model"}, false,
@@ -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<bool>("stratify_data");
if (params.Get<int>("seed") == 0)
mlpack::math::RandomSeed(std::time(NULL));
RandomSeed(std::time(NULL));
else
mlpack::math::RandomSeed((size_t) params.Get<int>("seed"));
RandomSeed((size_t) params.Get<int>("seed"));
// Make sure the user specified output filenames.
RequireAtLeastOnePassed(params, { "training" }, false, "no training set will "
@@ -18,10 +18,12 @@
#define BINDING_NAME random_forest
#include <mlpack/core/util/mlpack_main.hpp>
#include <mlpack/core/math/random.hpp>
#include <mlpack/methods/random_forest/random_forest.hpp>
#include <mlpack/methods/decision_tree/random_dimension_select.hpp>
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<int>("seed") != 0)
math::RandomSeed((size_t) params.Get<int>("seed"));
RandomSeed((size_t) params.Get<int>("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"))
@@ -13,6 +13,7 @@
*/
#include <mlpack/prereqs.hpp>
#include <mlpack/core/util/io.hpp>
#include <mlpack/core/math/random.hpp>
#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<int>("seed") != 0)
math::RandomSeed((size_t) params.Get<int>("seed"));
RandomSeed((size_t) params.Get<int>("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);
+5 -4
View File
@@ -19,13 +19,14 @@
#define BINDING_NAME krann
#include <mlpack/core/util/mlpack_main.hpp>
#include <mlpack/core/math/random.hpp>
#include <mlpack/methods/neighbor_search/unmap.hpp>
#include "ra_search.hpp"
#include "ra_model.hpp"
#include <mlpack/methods/neighbor_search/unmap.hpp>
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<int>("seed") != 0)
math::RandomSeed((size_t) params.Get<int>("seed"));
RandomSeed((size_t) params.Get<int>("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);
@@ -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<OutputLayerType, InitType>
typename OutputLayerType = ann::EmptyLoss<>,
typename InitType = ann::GaussianInitialization,
typename NetworkType = ann::FFN<OutputLayerType, InitType>
>
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<NoisyLinear<>*>
boost::get<ann::NoisyLinear<>*>
(network.Model()[noisyLayerIndex[i]])->ResetNoise();
}
}
@@ -236,7 +234,7 @@ class CategoricalDQN
std::vector<size_t> noisyLayerIndex;
//! Locally-stored softmax activation function.
Softmax<> softMax;
ann::Softmax<> softMax;
//! Locally-stored activations from softMax.
arma::mat activations;
@@ -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<OutputLayerType, InitType>,
typename FeatureNetworkType = Sequential<>,
typename AdvantageNetworkType = Sequential<>,
typename ValueNetworkType = Sequential<>
typename OutputLayerType = ann::EmptyLoss<>,
typename InitType = ann::GaussianInitialization,
typename CompleteNetworkType = ann::FFN<OutputLayerType, InitType>,
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<NoisyLinear<>*>
boost::get<ann::NoisyLinear<>*>
(valueNetwork->Model()[noisyLayerIndex[i]])->ResetNoise();
boost::get<NoisyLinear<>*>
boost::get<ann::NoisyLinear<>*>
(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
@@ -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<OutputLayerType, InitType>
typename OutputLayerType = ann::MeanSquaredError<>,
typename InitType = ann::GaussianInitialization,
typename NetworkType = ann::FFN<OutputLayerType, InitType>
>
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<NoisyLinear<>*>
boost::get<ann::NoisyLinear<>*>
(network.Model()[noisyLayerIndex[i]])->ResetNoise();
}
}