diff --git a/doc/examples/sample-ml-app/sample-ml-app/sample-ml-app.vcxproj b/doc/examples/sample-ml-app/sample-ml-app/sample-ml-app.vcxproj
index fdc41c5d2a..aadce63f17 100644
--- a/doc/examples/sample-ml-app/sample-ml-app/sample-ml-app.vcxproj
+++ b/doc/examples/sample-ml-app/sample-ml-app/sample-ml-app.vcxproj
@@ -104,16 +104,16 @@
true_DEBUG;_CONSOLE;%(PreprocessorDefinitions)false
- C:\boost\boost_1_66_0;C:\mlpack\armadillo-8.500.1\include;C:\mlpack\mlpack-3.2.1\build\include;%(AdditionalIncludeDirectories)
+ C:\boost\boost_1_66_0;C:\mlpack\armadillo-8.500.1\include;C:\mlpack\mlpack-3.3.0\build\include;%(AdditionalIncludeDirectories)Consoletrue
- C:\mlpack\mlpack-3.2.1\build\Debug\mlpack.lib;C:\boost\boost_1_66_0\lib64-msvc-14.1\libboost_serialization-vc141-mt-gd-x64-1_66.lib;C:\boost\boost_1_66_0\lib64-msvc-14.1\libboost_program_options-vc141-mt-gd-x64-1_66.lib;%(AdditionalDependencies)
+ C:\mlpack\mlpack-3.3.0\build\Debug\mlpack.lib;C:\boost\boost_1_66_0\lib64-msvc-14.1\libboost_serialization-vc141-mt-gd-x64-1_66.lib;C:\boost\boost_1_66_0\lib64-msvc-14.1\libboost_program_options-vc141-mt-gd-x64-1_66.lib;%(AdditionalDependencies)
- xcopy /y "C:\mlpack\mlpack-3.2.1\build\Debug\mlpack.dll" $(OutDir)
-xcopy /y "C:\mlpack\mlpack-3.2.1\packages\OpenBLAS.0.2.14.1\lib\native\bin\x64\*.dll" $(OutDir)
+ xcopy /y "C:\mlpack\mlpack-3.3.0\build\Debug\mlpack.dll" $(OutDir)
+xcopy /y "C:\mlpack\mlpack-3.3.0\packages\OpenBLAS.0.2.14.1\lib\native\bin\x64\*.dll" $(OutDir)
xcopy /y "$(ProjectDir)..\..\..\..\src\mlpack\tests\data\german.csv" "$(ProjectDir)data\german.csv*"
diff --git a/doc/guide/build.hpp b/doc/guide/build.hpp
index df5e2edb82..d54dd3274e 100644
--- a/doc/guide/build.hpp
+++ b/doc/guide/build.hpp
@@ -30,7 +30,7 @@ to build mlpack on Windows, see \ref build_windows (alternatively, you can read
is based on older versions).
You can download the latest mlpack release from here:
-mlpack-3.2.2
+mlpack-3.3.0
@section build_simple Simple Linux build instructions
@@ -38,9 +38,9 @@ Assuming all dependencies are installed in the system, you can run the commands
below directly to build and install mlpack.
@code
-$ wget https://www.mlpack.org/files/mlpack-3.2.2.tar.gz
-$ tar -xvzpf mlpack-3.2.2.tar.gz
-$ mkdir mlpack-3.2.2/build && cd mlpack-3.2.2/build
+$ wget https://www.mlpack.org/files/mlpack-3.3.0.tar.gz
+$ tar -xvzpf mlpack-3.3.0.tar.gz
+$ mkdir mlpack-3.3.0/build && cd mlpack-3.3.0/build
$ cmake ../
$ make -j4 # The -j is the number of cores you want to use for a build.
$ sudo make install
@@ -65,8 +65,8 @@ configure mlpack.
First we should unpack the mlpack source and create a build directory.
@code
-$ tar -xvzpf mlpack-3.2.2.tar.gz
-$ cd mlpack-3.2.2
+$ tar -xvzpf mlpack-3.3.0.tar.gz
+$ cd mlpack-3.3.0
$ mkdir build
@endcode
diff --git a/doc/guide/python_quickstart.hpp b/doc/guide/python_quickstart.hpp
index 115eecc107..4a1da9152c 100644
--- a/doc/guide/python_quickstart.hpp
+++ b/doc/guide/python_quickstart.hpp
@@ -31,9 +31,9 @@ build and install mlpack. You can copy-paste the commands into your shell.
@code{.sh}
sudo apt-get install libboost-all-dev g++ cmake libarmadillo-dev python-pip wget
sudo pip install cython setuptools distutils numpy pandas
-wget https://www.mlpack.org/files/mlpack-3.2.1.tar.gz
-tar -xvzpf mlpack-3.2.1.tar.gz
-mkdir -p mlpack-3.2.1/build/ && cd mlpack-3.2.1/build/
+wget https://www.mlpack.org/files/mlpack-3.3.0.tar.gz
+tar -xvzpf mlpack-3.3.0.tar.gz
+mkdir -p mlpack-3.3.0/build/ && cd mlpack-3.3.0/build/
cmake ../ && make -j4 && sudo make install
@endcode
diff --git a/doc/guide/sample_ml_app.hpp b/doc/guide/sample_ml_app.hpp
index 6e42a19c07..1cb4877037 100644
--- a/doc/guide/sample_ml_app.hpp
+++ b/doc/guide/sample_ml_app.hpp
@@ -29,18 +29,18 @@ mlpack and dependencies in Release Mode).
@code
- C:\boost\boost_1_71_0\lib\native\include
- C:\mlpack\armadillo-9.800.3\include
- - C:\mlpack\mlpack-3.2.2\build\include
+ - C:\mlpack\mlpack-3.3.0\build\include
@endcode
- Under Linker > Input > Additional Dependencies add:
@code
- - C:\mlpack\mlpack-3.2.2\build\Debug\mlpack.lib
+ - C:\mlpack\mlpack-3.3.0\build\Debug\mlpack.lib
- C:\boost\boost_1_71_0\lib64-msvc-14.2\libboost_serialization-vc142-mt-gd-x64-1_71.lib
- C:\boost\boost_1_71_0\lib64-msvc-14.2\libboost_program_options-vc142-mt-gd-x64-1_71.lib
@endcode
- Under Build Events > Post-Build Event > Command Line add:
@code
- - xcopy /y "C:\mlpack\mlpack-3.2.2\build\Debug\mlpack.dll" $(OutDir)
- - xcopy /y "C:\mlpack\mlpack-3.2.2\packages\OpenBLAS.0.2.14.1\lib\native\bin\x64\*.dll" $(OutDir)
+ - xcopy /y "C:\mlpack\mlpack-3.3.0\build\Debug\mlpack.dll" $(OutDir)
+ - xcopy /y "C:\mlpack\mlpack-3.3.0\packages\OpenBLAS.0.2.14.1\lib\native\bin\x64\*.dll" $(OutDir)
@endcode
@note Recent versions of Visual Studio set "Conformance Mode" enabled by default. This causes some issues with
diff --git a/doc/tutorials/image/image.txt b/doc/tutorials/image/image.txt
new file mode 100644
index 0000000000..b64a86c24a
--- /dev/null
+++ b/doc/tutorials/image/image.txt
@@ -0,0 +1,188 @@
+/*!
+@file image.txt
+@author Mehul Kumar Nirala
+@brief Tutorial for how to load and save images in mlpack.
+
+@page imagetutorial Image Utilities tutorial
+
+@section intro_imagetut Introduction
+
+Image datasets are becoming increasingly popular in deep learning.
+
+mlpack's image saving/loading functionality is based on [stb/](https://github.com/nothings/stb).
+
+@section toc_imagetut Table of Contents
+
+This tutorial is split into the following sections:
+
+ - \ref intro_imagetut
+ - \ref toc_imagetut
+ - \ref model_api_imagetut
+ - \ref imageinfo_api_imagetut
+ - \ref load_api_imagetut
+ - \ref save_api_imagetut
+
+@section model_api_imagetut Model API
+
+Image utilities supports loading and saving of images.
+
+It supports filetypes "jpg", "png", "tga","bmp", "psd", "gif", "hdr", "pic", "pnm" for loading and "jpg", "png", "tga", "bmp", "hdr" for saving.
+
+The datatype associated is unsigned char to support RGB values in the range 1-255. To feed data into the network typecast of `arma::Mat` may be required. Images are stored in matrix as (width * height * channels, NumberOfImages). Therefore imageMatrix.col(0) would be the first image if images are loaded in imageMatrix.
+
+@section imageinfo_api_imagetut ImageInfo
+
+ImageInfo class contains the metadata of the images.
+@code
+ /**
+ * Instantiate the ImageInfo object with the image width, height, channels.
+ *
+ * @param width Image width.
+ * @param height Image height.
+ * @param channels number of channels in the image.
+ */
+ ImageInfo(const size_t width,
+ const size_t height,
+ const size_t channels);
+@endcode
+Other public memebers include:
+ - quality Compression of the image if saved as jpg (0-100).
+
+@section load_api_imagetut Load
+
+
+Standalone loading of images.
+@code
+ /**
+ * 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).
+ * @param transpose If true, flips the image, same as transposing the
+ * matrix after loading.
+ * @return Boolean value indicating success or failure of load.
+ */
+ template
+ bool Load(const std::string& filename,
+ arma::Mat& matrix,
+ ImageInfo& info,
+ const bool fatal,
+ const bool transpose);
+@endcode
+
+Loading a test image. It also fills up the ImageInfo class object.
+@code
+data::ImageInfo info;
+data::Load("test_image.png", matrix, info, false, true);
+@endcode
+
+ImageInfo requires height, width, number of channels of the image.
+
+@code
+size_t height = 64, width = 64, channels = 1;
+data::ImageInfo info(width, height, channels);
+@endcode
+
+More than one image can be loaded into the same matrix.
+
+Loading multiple images:
+
+@code
+ /**
+ * 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).
+ * @param transpose If true, flips the image, same as transposing the
+ * matrix after loading.
+ * @return Boolean value indicating success or failure of load.
+ */
+ template
+ bool Load(const std::vector& files,
+ arma::Mat& matrix,
+ ImageInfo& info,
+ const bool fatal,
+ const bool transpose);
+@endcode
+
+@code
+ data::ImageInfo info;
+ std::vector> files{"test_image1.bmp","test_image2.bmp"};
+ data::load(files, matrix, info, false, true);
+@endcode
+
+@section save_api_imagetut Save
+
+Save images expects a matrix of type unsigned char in the form (width * height * channels, NumberOfImages).
+Just like load it can be used to save one image or multiple images. Besides image data it also expects the shape of the image as input (width, height, channels).
+
+Saving one image:
+
+@code
+ /**
+ * 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).
+ * @param transpose If true, flips the image, same as transposing the
+ * matrix after loading.
+ * @return Boolean value indicating success or failure of load.
+ */
+ template
+ bool Save(const std::string& filename,
+ arma::Mat& matrix,
+ ImageInfo& info,
+ const bool fatal,
+ const bool transpose);
+@endcode
+
+@code
+ data::ImageInfo info;
+ info.width = info.height = 25;
+ info.channels = 3;
+ info.quality = 90;
+ data::Save("test_image.bmp", matrix, info, false, true);
+@endcode
+
+If the matrix contains more than one image, only the first one is saved.
+
+Saving multiple images:
+
+@code
+ /**
+ * 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).
+ * @param transpose If true, Flips the image, same as transposing the
+ * matrix after loading.
+ * @return Boolean value indicating success or failure of load.
+ */
+ template
+ bool Save(const std::vector& files,
+ arma::Mat& matrix,
+ ImageInfo& info,
+ const bool fatal,
+ const bool transpose);
+@endcode
+
+@code
+ data::ImageInfo info;
+ info.width = info.height = 25;
+ info.channels = 3;
+ info.quality = 90;
+ std::vector> files{"test_image1.bmp", "test_image2.bmp"};
+ data::Save(files, matrix, info, false, true);
+@endcode
+
+Multiple images are saved according to the vector of filenames specified.
+
+*/
diff --git a/src/mlpack/CMakeLists.txt b/src/mlpack/CMakeLists.txt
index 02d60b0c1c..2b2513daff 100644
--- a/src/mlpack/CMakeLists.txt
+++ b/src/mlpack/CMakeLists.txt
@@ -44,7 +44,7 @@ target_link_libraries(mlpack ${MLPACK_LIBRARIES})
set_target_properties(mlpack
PROPERTIES
- VERSION 3.2
+ VERSION 3.3
SOVERSION 3
)
diff --git a/src/mlpack/bindings/julia/get_julia_type.hpp b/src/mlpack/bindings/julia/get_julia_type.hpp
index 096c420ab9..d320494ba2 100644
--- a/src/mlpack/bindings/julia/get_julia_type.hpp
+++ b/src/mlpack/bindings/julia/get_julia_type.hpp
@@ -3,6 +3,11 @@
* @author Ryan Curtin
*
* Get the Julia-named type of an mlpack C++ type.
+ *
+ * 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_BINDINGS_JULIA_GET_JULIA_TYPE_HPP
#define MLPACK_BINDINGS_JULIA_GET_JULIA_TYPE_HPP
diff --git a/src/mlpack/bindings/julia/get_printable_type.hpp b/src/mlpack/bindings/julia/get_printable_type.hpp
index 53747acdf1..c353497349 100644
--- a/src/mlpack/bindings/julia/get_printable_type.hpp
+++ b/src/mlpack/bindings/julia/get_printable_type.hpp
@@ -4,6 +4,11 @@
*
* Get the printable type of a parameter. This type is not the C++ type but
* instead the Julia type that a user would use.
+ *
+ * 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_BINDINGS_JULIA_GET_PRINTABLE_TYPE_HPP
#define MLPACK_BINDINGS_JULIA_GET_PRINTABLE_TYPE_HPP
diff --git a/src/mlpack/bindings/julia/get_printable_type_impl.hpp b/src/mlpack/bindings/julia/get_printable_type_impl.hpp
index 524fe62a0b..2df1a753ec 100644
--- a/src/mlpack/bindings/julia/get_printable_type_impl.hpp
+++ b/src/mlpack/bindings/julia/get_printable_type_impl.hpp
@@ -4,6 +4,11 @@
*
* Get the printable type of a parameter. This type is not the C++ type but
* instead the Julia type that a user would use.
+ *
+ * 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_BINDINGS_JULIA_GET_PRINTABLE_TYPE_IMPL_HPP
#define MLPACK_BINDINGS_JULIA_GET_PRINTABLE_TYPE_IMPL_HPP
diff --git a/src/mlpack/bindings/julia/julia_util.cpp b/src/mlpack/bindings/julia/julia_util.cpp
index faa639956f..ee3bf70681 100644
--- a/src/mlpack/bindings/julia/julia_util.cpp
+++ b/src/mlpack/bindings/julia/julia_util.cpp
@@ -3,6 +3,11 @@
* @author Ryan Curtin
*
* Implementations of Julia binding 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.
*/
#include
#include
diff --git a/src/mlpack/bindings/julia/print_doc.hpp b/src/mlpack/bindings/julia/print_doc.hpp
index 522ea3576b..62a8acdde8 100644
--- a/src/mlpack/bindings/julia/print_doc.hpp
+++ b/src/mlpack/bindings/julia/print_doc.hpp
@@ -3,6 +3,11 @@
* @author Ryan Curtin
*
* Print inline documentation for a single option.
+ *
+ * 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_BINDINGS_JULIA_PRINT_DOC_HPP
#define MLPACK_BINDINGS_JULIA_PRINT_DOC_HPP
diff --git a/src/mlpack/bindings/julia/print_input_param.hpp b/src/mlpack/bindings/julia/print_input_param.hpp
index a76ba172a3..9f7ad35285 100644
--- a/src/mlpack/bindings/julia/print_input_param.hpp
+++ b/src/mlpack/bindings/julia/print_input_param.hpp
@@ -4,6 +4,11 @@
*
* Print the declaration of an input parameter as part of a line in a Julia
* function definition.
+ *
+ * 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_BINDINGS_JULIA_PRINT_INPUT_PARAM_HPP
#define MLPACK_BINDINGS_JULIA_PRINT_INPUT_PARAM_HPP
diff --git a/src/mlpack/bindings/julia/print_input_processing.hpp b/src/mlpack/bindings/julia/print_input_processing.hpp
index a5ae2412bf..317c796d65 100644
--- a/src/mlpack/bindings/julia/print_input_processing.hpp
+++ b/src/mlpack/bindings/julia/print_input_processing.hpp
@@ -3,6 +3,11 @@
* @author Ryan Curtin
*
* Print Julia code to handle input arguments.
+ *
+ * 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_BINDINGS_JULIA_PRINT_INPUT_PROCESSING_HPP
#define MLPACK_BINDINGS_JULIA_PRINT_INPUT_PROCESSING_HPP
diff --git a/src/mlpack/bindings/julia/print_input_processing_impl.hpp b/src/mlpack/bindings/julia/print_input_processing_impl.hpp
index 6839abf29d..cd71693f3e 100644
--- a/src/mlpack/bindings/julia/print_input_processing_impl.hpp
+++ b/src/mlpack/bindings/julia/print_input_processing_impl.hpp
@@ -3,6 +3,11 @@
* @author Ryan Curtin
*
* Print Julia code to handle input arguments.
+ *
+ * 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_BINDINGS_JULIA_PRINT_INPUT_PROCESSING_IMPL_HPP
#define MLPACK_BINDINGS_JULIA_PRINT_INPUT_PROCESSING_IMPL_HPP
diff --git a/src/mlpack/bindings/julia/print_jl.cpp b/src/mlpack/bindings/julia/print_jl.cpp
index 7f4fb86a02..23d0b5ee0e 100644
--- a/src/mlpack/bindings/julia/print_jl.cpp
+++ b/src/mlpack/bindings/julia/print_jl.cpp
@@ -3,6 +3,11 @@
* @author Ryan Curtin
*
* Implementation of utility PrintJL() function.
+ *
+ * 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 "print_jl.hpp"
#include
diff --git a/src/mlpack/bindings/julia/print_jl.hpp b/src/mlpack/bindings/julia/print_jl.hpp
index 6b07dd7e3b..e712fc0a3c 100644
--- a/src/mlpack/bindings/julia/print_jl.hpp
+++ b/src/mlpack/bindings/julia/print_jl.hpp
@@ -3,6 +3,11 @@
* @author Ryan Curtin
*
* Definition of utility PrintJL() function.
+ *
+ * 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_BINDINGS_JULIA_PRINT_JL_HPP
#define MLPACK_BINDINGS_JULIA_PRINT_JL_HPP
diff --git a/src/mlpack/bindings/julia/print_output_processing.hpp b/src/mlpack/bindings/julia/print_output_processing.hpp
index 069b344b6e..6426eb293d 100644
--- a/src/mlpack/bindings/julia/print_output_processing.hpp
+++ b/src/mlpack/bindings/julia/print_output_processing.hpp
@@ -3,6 +3,11 @@
* @author Ryan Curtin
*
* Print Julia code to handle output arguments.
+ *
+ * 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_BINDINGS_JULIA_PRINT_OUTPUT_PROCESSING_HPP
#define MLPACK_BINDINGS_JULIA_PRINT_OUTPUT_PROCESSING_HPP
diff --git a/src/mlpack/bindings/julia/print_output_processing_impl.hpp b/src/mlpack/bindings/julia/print_output_processing_impl.hpp
index 407eb5b657..058bae5b87 100644
--- a/src/mlpack/bindings/julia/print_output_processing_impl.hpp
+++ b/src/mlpack/bindings/julia/print_output_processing_impl.hpp
@@ -3,6 +3,11 @@
* @author Ryan Curtin
*
* Print Julia code to handle output arguments.
+ *
+ * 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_BINDINGS_JULIA_PRINT_OUTPUT_PROCESSING_IMPL_HPP
#define MLPACK_BINDINGS_JULIA_PRINT_OUTPUT_PROCESSING_IMPL_HPP
diff --git a/src/mlpack/bindings/julia/print_param_defn.hpp b/src/mlpack/bindings/julia/print_param_defn.hpp
index 46dc604a2c..84e482431a 100644
--- a/src/mlpack/bindings/julia/print_param_defn.hpp
+++ b/src/mlpack/bindings/julia/print_param_defn.hpp
@@ -4,6 +4,11 @@
*
* If the type is serializable, we need to define a special utility function to
* set a CLI parameter of that type.
+ *
+ * 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_BINDINGS_JULIA_PRINT_PARAM_DEFN_HPP
#define MLPACK_BINDINGS_JULIA_PRINT_PARAM_DEFN_HPP
diff --git a/src/mlpack/bindings/julia/strip_type.hpp b/src/mlpack/bindings/julia/strip_type.hpp
index 3a2a179ac1..087e74e940 100644
--- a/src/mlpack/bindings/julia/strip_type.hpp
+++ b/src/mlpack/bindings/julia/strip_type.hpp
@@ -4,6 +4,11 @@
*
* Given a C++ type name, turn it into something that has no special characters
* that can simply be printed.
+ *
+ * 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_BINDINGS_JULIA_STRIP_TYPE_HPP
#define MLPACK_BINDINGS_JULIA_STRIP_TYPE_HPP
diff --git a/src/mlpack/core/data/image_info.hpp b/src/mlpack/core/data/image_info.hpp
index 9693127500..3fa91ef303 100644
--- a/src/mlpack/core/data/image_info.hpp
+++ b/src/mlpack/core/data/image_info.hpp
@@ -69,6 +69,15 @@ class ImageInfo
//! Modify the image quality.
size_t& Quality() { return quality; }
+ template
+ void serialize(Archive& ar, const unsigned int /* version */)
+ {
+ ar & BOOST_SERIALIZATION_NVP(width);
+ ar & BOOST_SERIALIZATION_NVP(channels);
+ ar & BOOST_SERIALIZATION_NVP(height);
+ ar & BOOST_SERIALIZATION_NVP(quality);
+ }
+
private:
// To store the image width.
size_t width;
diff --git a/src/mlpack/core/data/load_image.cpp b/src/mlpack/core/data/load_image.cpp
index 2796e9a1f4..7801a6d07a 100644
--- a/src/mlpack/core/data/load_image.cpp
+++ b/src/mlpack/core/data/load_image.cpp
@@ -3,19 +3,23 @@
* @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
-#define STB_IMAGE_WRITE_STATIC
-#define STB_IMAGE_WRITE_IMPLEMENTATION
-#include
+#include
namespace mlpack {
namespace data {
diff --git a/src/mlpack/core/data/save_image.cpp b/src/mlpack/core/data/save_image.cpp
index c1802073e4..abc8b701e9 100644
--- a/src/mlpack/core/data/save_image.cpp
+++ b/src/mlpack/core/data/save_image.cpp
@@ -3,18 +3,29 @@
* @author Mehul Kumar Nirala
*
* Implementation of image saving 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 "save.hpp"
#ifdef HAS_STB
-#define STB_IMAGE_STATIC
-#define STB_IMAGE_IMPLEMENTATION
-#include
-
+// 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
-#define STB_IMAGE_WRITE_IMPLEMENTATION
+#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
namespace mlpack {
namespace data {
@@ -54,6 +65,12 @@ bool SaveImage(const std::string& filename,
Log::Warn << "Only the first image will be saved!" << std::endl;
}
+ if (info.Width() * info.Height() * info.Channels() != image.n_elem)
+ {
+ Log::Fatal << "data::Save(): The given image dimensions do not match the "
+ << "dimensions of the matrix to be saved!" << std::endl;
+ }
+
bool status = false;
unsigned char* imageMem = image.memptr();
diff --git a/src/mlpack/core/data/save_impl.hpp b/src/mlpack/core/data/save_impl.hpp
index e19f8928bf..516e0aaf93 100644
--- a/src/mlpack/core/data/save_impl.hpp
+++ b/src/mlpack/core/data/save_impl.hpp
@@ -328,15 +328,11 @@ bool Save(const std::vector& files,
}
arma::Mat img;
- bool status = Save(files[0], img, info, fatal);
+ bool status = true;
- // Decide matrix dimension using the image height and width.
- matrix.set_size(info.Width() * info.Height() * info.Channels(), files.size());
- matrix.col(0) = img;
-
- for (size_t i = 1; i < files.size() ; i++)
+ for (size_t i = 0; i < files.size() ; i++)
{
- arma::Mat colImg(matrix.colptr(i), matrix.n_rows, 1,
+ arma::Mat colImg(matrix.colptr(i), matrix.n_rows, 1,
false, true);
status &= Save(files[i], colImg, info, fatal);
}
diff --git a/src/mlpack/core/data/string_encoding.hpp b/src/mlpack/core/data/string_encoding.hpp
index 6c529fe31f..9ed18cba6e 100644
--- a/src/mlpack/core/data/string_encoding.hpp
+++ b/src/mlpack/core/data/string_encoding.hpp
@@ -24,7 +24,8 @@ namespace data {
/**
* The class translates a set of strings into numbers using various encoding
- * algorithms.
+ * algorithms. The encoder writes data either in the column-major order or
+ * in the row-major order depending on the output data type.
*
* @tparam EncodingPolicyType Type of the encoding algorithm itself.
* @tparam DictionaryType Type of the dictionary.
@@ -90,11 +91,17 @@ class StringEncoding
void Clear();
/**
- * Encode the given text and write the result to the given output.
+ * Encode the given text and write the result to the given output. The encoder
+ * writes data in the column-major order or in the row-major order depending
+ * on the output data type.
+ *
+ * If the output type is either arma::mat or arma::sp_mat then the function
+ * writes it in the column-major order. If the output type is 2D std::vector
+ * then the function writes it in the row major order.
*
* @tparam OutputType Type of the output container. The function supports
* the following types: arma::mat, arma::sp_mat,
- * std::vector>.
+ * std::vector>.
* @tparam TokenizerType Type of the tokenizer.
*
* @param input Corpus of text to encode.
@@ -132,11 +139,16 @@ class StringEncoding
private:
/**
* A helper function to encode the given text and write the result to
- * the given output.
+ * the given output. The encoder writes data in the column-major order or
+ * in the row-major order depending on the output data type.
+ *
+ * If the output type is either arma::mat or arma::sp_mat then the function
+ * writes it in the column-major order. If the output type is 2D std::vector
+ * then the function writes it in the row major order.
*
* @tparam OutputType Type of the output container. The function supports
* the following types: arma::mat, arma::sp_mat,
- * std::vector>.
+ * std::vector>.
* @tparam TokenizerType Type of the tokenizer.
* @tparam PolicyType The type of the encoding policy. It has to be
* equal to EncodingPolicyType.
@@ -153,9 +165,7 @@ class StringEncoding
* 2. IsTokenEmpty() that accepts a token and returns true if the given
* token is empty.
*/
- template
+ template
void EncodeHelper(const std::vector& input,
OutputType& output,
const TokenizerType& tokenizer,
@@ -164,11 +174,13 @@ class StringEncoding
/**
* A helper function to encode the given text and write the result to
* the given output. This is an optimized overload for policies that support
- * the one pass encoding algorithm.
+ * the one pass encoding algorithm. The encoder writes data in the row-major
+ * order.
*
* @tparam TokenizerType Type of the tokenizer.
* @tparam PolicyType The type of the encoding policy. It has to be
* equal to EncodingPolicyType.
+ * @tparam ElemType Type of the output values.
*
* @param input Corpus of text to encode.
* @param output Output container to store the result.
@@ -182,9 +194,9 @@ class StringEncoding
* 2. IsTokenEmpty() that accepts a token and returns true if the given
* token is empty.
*/
- template
+ template
void EncodeHelper(const std::vector& input,
- std::vector>& output,
+ std::vector>& output,
const TokenizerType& tokenizer,
PolicyType& policy,
typename std::enable_if& input,
{
size_t numColumns = 0;
+ policy.Reset();
+
// The first pass adds the extracted tokens to the dictionary.
- for (const std::string& line : input)
+ for (size_t i = 0; i < input.size(); i++)
{
- boost::string_view strView(line);
+ boost::string_view strView(input[i]);
auto token = tokenizer(strView);
static_assert(
@@ -127,9 +129,12 @@ EncodeHelper(const std::vector& input,
if (!dictionary.HasToken(token))
dictionary.AddToken(std::move(token));
+ policy.PreprocessToken(i, numTokens, dictionary.Value(token));
+
token = tokenizer(strView);
numTokens++;
}
+
numColumns = std::max(numColumns, numTokens);
}
@@ -152,15 +157,17 @@ EncodeHelper(const std::vector& input,
}
template
-template
+template
void StringEncoding::
EncodeHelper(const std::vector& input,
- std::vector>& output,
+ std::vector>& output,
const TokenizerType& tokenizer,
PolicyType& policy,
typename std::enable_if::onePassEncoding>::type*)
{
+ policy.Reset();
+
// The loop below extracts the tokens and writes the encoded values
// at once.
for (size_t i = 0; i < input.size(); i++)
diff --git a/src/mlpack/core/data/string_encoding_policies/CMakeLists.txt b/src/mlpack/core/data/string_encoding_policies/CMakeLists.txt
index 8a8c7ab65c..9f570e08d7 100644
--- a/src/mlpack/core/data/string_encoding_policies/CMakeLists.txt
+++ b/src/mlpack/core/data/string_encoding_policies/CMakeLists.txt
@@ -1,8 +1,10 @@
# Define the files that we need to compile.
# Anything not in this list will not be compiled into mlpack.
set(SOURCES
+ bag_of_words_encoding_policy.hpp
dictionary_encoding_policy.hpp
policy_traits.hpp
+ tf_idf_encoding_policy.hpp
)
# add directory name to sources
diff --git a/src/mlpack/core/data/string_encoding_policies/bag_of_words_encoding_policy.hpp b/src/mlpack/core/data/string_encoding_policies/bag_of_words_encoding_policy.hpp
new file mode 100644
index 0000000000..d71a82ac6e
--- /dev/null
+++ b/src/mlpack/core/data/string_encoding_policies/bag_of_words_encoding_policy.hpp
@@ -0,0 +1,171 @@
+/**
+ * @file bag_of_words_encoding_policy.hpp
+ * @author Jeffin Sam
+ * @author Mikhail Lozhnikov
+ *
+ * Definition of the BagOfWordsEncodingPolicy class.
+ *
+ * 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_STR_ENCODING_POLICIES_BAG_OF_WORDS_ENCODING_POLICY_HPP
+#define MLPACK_CORE_DATA_STR_ENCODING_POLICIES_BAG_OF_WORDS_ENCODING_POLICY_HPP
+
+#include
+#include
+#include
+
+namespace mlpack {
+namespace data {
+
+/**
+ * Definition of the BagOfWordsEncodingPolicy class.
+ *
+ * BagOfWords is used as a helper class for StringEncoding. The encoder maps
+ * each dataset item to a vector of size N, where N is equal to the total unique
+ * number of tokens. The i-th coordinate of the output vector is equal to
+ * the number of times when the i-th token occurs in the corresponding dataset
+ * item. The order in which the tokens are labeled is defined by the dictionary
+ * used by the StringEncoding class. The encoder writes data either in the
+ * column-major order or in the row-major order depending on the output data
+ * type.
+ */
+class BagOfWordsEncodingPolicy
+{
+ public:
+ /**
+ * Clear the necessary internal variables.
+ */
+ static void Reset()
+ {
+ // Nothing to do.
+ }
+
+ /**
+ * The function initializes the output matrix. The encoder writes data
+ * in the column-major order.
+ *
+ * @tparam MatType The output matrix type.
+ *
+ * @param output Output matrix to store the encoded results (sp_mat or mat).
+ * @param datasetSize The number of strings in the input dataset.
+ * @param maxNumTokens The maximum number of tokens in the strings of the
+ * input dataset (not used).
+ * @param dictionarySize The size of the dictionary.
+ */
+ template
+ static void InitMatrix(MatType& output,
+ const size_t datasetSize,
+ const size_t /* maxNumTokens */,
+ const size_t dictionarySize)
+ {
+ output.zeros(dictionarySize, datasetSize);
+ }
+
+ /**
+ * The function initializes the output matrix. The encoder writes data
+ * in the row-major order.
+ *
+ * Overloaded function to save the result in vector>.
+ *
+ * @tparam ElemType Type of the output values.
+ *
+ * @param output Output matrix to store the encoded results.
+ * @param datasetSize The number of strings in the input dataset.
+ * @param maxNumTokens The maximum number of tokens in the strings of the
+ * input dataset (not used).
+ * @param dictionarySize The size of the dictionary.
+ */
+ template
+ static void InitMatrix(std::vector>& output,
+ const size_t datasetSize,
+ const size_t /* maxNumTokens */,
+ const size_t dictionarySize)
+ {
+ output.resize(datasetSize, std::vector(dictionarySize));
+ }
+
+ /**
+ * The function performs the bag of words encoding algorithm i.e. it writes
+ * the encoded token to the output. The encoder writes data in the
+ * column-major order.
+ *
+ * @tparam MatType The output matrix type.
+ *
+ * @param output Output matrix to store the encoded results (sp_mat or mat).
+ * @param value The encoded token.
+ * @param line The line number at which the encoding is performed.
+ * @param index The token index in the line.
+ */
+ template
+ static void Encode(MatType& output,
+ const size_t value,
+ const size_t line,
+ const size_t /* index */)
+ {
+ // The labels are assigned sequentially starting from one.
+ output(value - 1, line) += 1;
+ }
+
+ /**
+ * The function performs the bag of words encoding algorithm i.e. it writes
+ * the encoded token to the output. The encoder writes data in the
+ * row-major order.
+ *
+ * Overloaded function to accept vector> as the output
+ * type.
+ *
+ * @tparam ElemType Type of the output values.
+ *
+ * @param output Output matrix to store the encoded results.
+ * @param value The encoded token.
+ * @param line The line number at which the encoding is performed.
+ * @param index The line token number at which the encoding is performed.
+ */
+ template
+ static void Encode(std::vector>& output,
+ const size_t value,
+ const size_t line,
+ const size_t /* index */)
+ {
+ // The labels are assigned sequentially starting from one.
+ output[line][value - 1] += 1;
+ }
+
+ /**
+ * The function is not used by the bag of words encoding policy.
+ *
+ * @param line The line number at which the encoding is performed.
+ * @param index The token sequence number in the line.
+ * @param value The encoded token.
+ */
+ static void PreprocessToken(size_t /* line */,
+ size_t /* index */,
+ size_t /* value */)
+ { }
+
+ /**
+ * Serialize the class to the given archive.
+ */
+ template
+ void serialize(Archive& /* ar */, const unsigned int /* version */)
+ {
+ // Nothing to serialize.
+ }
+};
+
+/**
+ * A convenient alias for the StringEncoding class with BagOfWordsEncodingPolicy
+ * and the default dictionary for the given token type.
+ *
+ * @tparam TokenType Type of the tokens.
+ */
+template
+using BagOfWordsEncoding = StringEncoding>;
+} // namespace data
+} // namespace mlpack
+
+#endif
diff --git a/src/mlpack/core/data/string_encoding_policies/dictionary_encoding_policy.hpp b/src/mlpack/core/data/string_encoding_policies/dictionary_encoding_policy.hpp
index 1e67c6d29f..d9a37cacac 100644
--- a/src/mlpack/core/data/string_encoding_policies/dictionary_encoding_policy.hpp
+++ b/src/mlpack/core/data/string_encoding_policies/dictionary_encoding_policy.hpp
@@ -25,65 +25,92 @@ namespace data {
* The encoder assigns a positive integer number to each unique token and treats
* the dataset as categorical. The numbers are assigned sequentially starting
* from one. The order in which the tokens are labeled is defined by
- * the dictionary used by the StringEncoding class.
+ * the dictionary used by the StringEncoding class. The encoder writes data
+ * either in the column-major order or in the row-major order depending on
+ * the output data type.
*/
class DictionaryEncodingPolicy
{
public:
/**
- * The function initializes the output matrix.
- *
- * @tparam MatType The output matrix type.
- *
- * @param output Output matrix to store the encoded results (sp_mat or mat).
- * @param datasetSize The number of strings in the input dataset.
- * @param maxNumTokens The maximum number of tokens in the strings of the
- input dataset.
- * @param dictionarySize The size of the dictionary (not used).
- */
+ * Clear the necessary internal variables.
+ */
+ static void Reset()
+ {
+ // Nothing to do.
+ }
+
+ /**
+ * The function initializes the output matrix. The encoder writes data
+ * in the column-major order.
+ *
+ * @tparam MatType The output matrix type.
+ *
+ * @param output Output matrix to store the encoded results (sp_mat or mat).
+ * @param datasetSize The number of strings in the input dataset.
+ * @param maxNumTokens The maximum number of tokens in the strings of the
+ * input dataset.
+ * @param dictionarySize The size of the dictionary (not used).
+ */
template
static void InitMatrix(MatType& output,
const size_t datasetSize,
const size_t maxNumTokens,
- const size_t /*dictionarySize*/)
+ const size_t /* dictionarySize */)
{
- output.zeros(datasetSize, maxNumTokens);
+ output.zeros(maxNumTokens, datasetSize);
}
- /**
- * The function performs the dictionary encoding algorithm i.e. it writes
- * the encoded token to the ouput.
- *
- * @tparam MatType The output matrix type.
- *
- * @param output Output matrix to store the encoded results (sp_mat or mat).
- * @param value The encoded token.
- * @param row The row number at which the encoding is performed.
- * @param col The token index in the row.
- */
+ /**
+ * The function performs the dictionary encoding algorithm i.e. it writes
+ * the encoded token to the output. The encoder writes data in the
+ * column-major order.
+ *
+ * @tparam MatType The output matrix type.
+ *
+ * @param output Output matrix to store the encoded results (sp_mat or mat).
+ * @param value The encoded token.
+ * @param line The line number at which the encoding is performed.
+ * @param index The token index in the line.
+ */
template
static void Encode(MatType& output,
const size_t value,
- const size_t row,
- const size_t col)
+ const size_t line,
+ const size_t index)
{
- output(row, col) = value;
+ output(index, line) = value;
}
- /**
+ /**
* The function performs the dictionary encoding algorithm i.e. it writes
- * the encoded token to the ouput. This is an overload function which saves
- * the result into the given vector to avoid padding.
+ * the encoded token to the output. This is an overloaded function which saves
+ * the result into the given vector to avoid padding. The encoder writes data
+ * in the row-major order.
*
- * @param output Output vector to store the encoded results.
+ * @tparam ElemType Type of the output values.
+ *
+ * @param output Output vector to store the encoded line.
* @param value The encoded token.
*/
- static void Encode(std::vector& output,
- const size_t value)
+ template
+ static void Encode(std::vector& output, size_t value)
{
output.push_back(value);
}
+ /**
+ * The function is not used by the dictionary encoding policy.
+ *
+ * @param line The line number at which the encoding is performed.
+ * @param index The token sequence number in the line.
+ * @param value The encoded token.
+ */
+ static void PreprocessToken(const size_t /* line */,
+ const size_t /* index */,
+ const size_t /* value */)
+ { }
+
/**
* Serialize the class to the given archive.
*/
diff --git a/src/mlpack/core/data/string_encoding_policies/tf_idf_encoding_policy.hpp b/src/mlpack/core/data/string_encoding_policies/tf_idf_encoding_policy.hpp
new file mode 100644
index 0000000000..853493e285
--- /dev/null
+++ b/src/mlpack/core/data/string_encoding_policies/tf_idf_encoding_policy.hpp
@@ -0,0 +1,349 @@
+/**
+ * @file tf_idf_encoding_policy.hpp
+ * @author Jeffin Sam
+ * @author Mikhail Lozhnikov
+ *
+ * Definition of the TfIdfEncodingPolicy class.
+ *
+ * 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_STRING_ENCODING_POLICIES_TF_IDF_ENCODING_POLICY_HPP
+#define MLPACK_CORE_DATA_STRING_ENCODING_POLICIES_TF_IDF_ENCODING_POLICY_HPP
+
+#include
+#include
+#include
+
+namespace mlpack {
+namespace data {
+
+/**
+ * Definition of the TfIdfEncodingPolicy class. TfIdfEncodingPolicy is used
+ * as a helper class for StringEncoding.
+ *
+ * Tf-idf is a weighting scheme that takes into account the importance of
+ * encoded tokens. The tf-idf statistics is equal to term frequency (tf)
+ * multiplied by inverse document frequency (idf).
+ * The encoder assigns the corresponding tf-idf value to each token. The order
+ * in which the tokens are labeled is defined by the dictionary used by the
+ * StringEncoding class. The encoder writes data either in the column-major
+ * order or in the row-major order depending on the output data type.
+ */
+class TfIdfEncodingPolicy
+{
+ public:
+ /**
+ * Enum class used to identify the type of the term frequency statistics.
+ *
+ * The present implementation supports the following types:
+ * BINARY Term frequency equals 1 if the row contains the encoded
+ * token and 0 otherwise.
+ * RAW_COUNT Term frequency equals the number of times when the encoded
+ * token occurs in the row.
+ * TERM_FREQUENCY Term frequency equals the number of times when the encoded
+ * token occurs in the row divided by the total number of
+ * tokens in the row.
+ * SUBLINEAR_TF Term frequency equals \f$ 1 + log(rawCount), \f$ where
+ * rawCount is equal to the number of times when the encoded
+ * token occurs in the row.
+ */
+ enum class TfTypes
+ {
+ BINARY,
+ RAW_COUNT,
+ TERM_FREQUENCY,
+ SUBLINEAR_TF,
+ };
+
+ /**
+ * Construct this using the term frequency type and the inverse document
+ * frequency type.
+ *
+ * @param tfType Type of the term frequency statistics.
+ * @param smoothIdf Used to indicate whether to use smooth idf or not.
+ * If idf is smooth it's calculated by the following formula:
+ * \f$ idf(T) = \log \frac{1 + N}{1 + df(T)} + 1, \f$ where
+ * \f$ N \f$ is the total number of strings in the document,
+ * \f$ T \f$ is the current encoded token, \f$ df(T) \f$
+ * equals the number of strings which contain the token.
+ * If idf isn't smooth then the following rule applies:
+ * \f$ idf(T) = \log \frac{N}{df(T)} + 1. \f$
+ */
+ TfIdfEncodingPolicy(const TfTypes tfType = TfTypes::RAW_COUNT,
+ const bool smoothIdf = true) :
+ tfType(tfType),
+ smoothIdf(smoothIdf)
+ { }
+
+ /**
+ * Clear the necessary internal variables.
+ */
+ void Reset()
+ {
+ tokensFrequences.clear();
+ numContainingStrings.clear();
+ linesSizes.clear();
+ }
+
+ /**
+ * The function initializes the output matrix. The encoder writes data
+ * in the row-major order.
+ *
+ * @tparam MatType The output matrix type.
+ *
+ * @param output Output matrix to store the encoded results (sp_mat or mat).
+ * @param datasetSize The number of strings in the input dataset.
+ * @param maxNumTokens The maximum number of tokens in the strings of the
+ * input dataset (not used).
+ * @param dictionarySize The size of the dictionary.
+ */
+ template
+ static void InitMatrix(MatType& output,
+ const size_t datasetSize,
+ const size_t /* maxNumTokens */,
+ const size_t dictionarySize)
+ {
+ output.zeros(dictionarySize, datasetSize);
+ }
+
+ /**
+ * The function initializes the output matrix. The encoder writes data
+ * in the row-major order.
+ *
+ * Overloaded function to save the result in vector>.
+ *
+ * @tparam ElemType Type of the output values.
+ *
+ * @param output Output matrix to store the encoded results.
+ * @param datasetSize The number of strings in the input dataset.
+ * @param maxNumTokens The maximum number of tokens in the strings of the
+ * input dataset (not used).
+ * @param dictionarySize The size of the dictionary.
+ */
+ template
+ static void InitMatrix(std::vector>& output,
+ const size_t datasetSize,
+ const size_t /* maxNumTokens */,
+ const size_t dictionarySize)
+ {
+ output.resize(datasetSize, std::vector(dictionarySize));
+ }
+
+ /**
+ * The function performs the TfIdf encoding algorithm i.e. it writes
+ * the encoded token to the output. The encoder writes data in the
+ * column-major order.
+ *
+ * @tparam MatType The output matrix type.
+ *
+ * @param output Output matrix to store the encoded results (sp_mat or mat).
+ * @param value The encoded token.
+ * @param line The line number at which the encoding is performed.
+ * @param index The token index in the line.
+ */
+ template
+ void Encode(MatType& output,
+ const size_t value,
+ const size_t line,
+ const size_t /* index */)
+ {
+ const typename MatType::elem_type tf =
+ TermFrequency(
+ tokensFrequences[line][value], linesSizes[line]);
+
+ const typename MatType::elem_type idf =
+ InverseDocumentFrequency(
+ output.n_cols, numContainingStrings[value]);
+
+ output(value - 1, line) = tf * idf;
+ }
+
+ /**
+ * The function performs the TfIdf encoding algorithm i.e. it writes
+ * the encoded token to the output. The encoder writes data in the
+ * row-major order.
+ *
+ * Overloaded function to accept vector> as the output
+ * type.
+ *
+ * @tparam ElemType Type of the output values.
+ *
+ * @param output Output matrix to store the encoded results.
+ * @param value The encoded token.
+ * @param line The line number at which the encoding is performed.
+ * @param index The token index in the line.
+ */
+ template
+ void Encode(std::vector>& output,
+ const size_t value,
+ const size_t line,
+ const size_t /* index */)
+ {
+ const ElemType tf = TermFrequency(
+ tokensFrequences[line][value], linesSizes[line]);
+
+ const ElemType idf = InverseDocumentFrequency(
+ output.size(), numContainingStrings[value]);
+
+ output[line][value - 1] = tf * idf;
+ }
+
+ /*
+ * The function calculates the necessary statistics for the purpose
+ * of the tf-idf algorithm during the first pass through the dataset.
+ *
+ * @param line The line number at which the encoding is performed.
+ * @param index The token sequence number in the line.
+ * @param value The encoded token.
+ */
+ void PreprocessToken(const size_t line,
+ const size_t /* index */,
+ const size_t value)
+ {
+ if (line >= tokensFrequences.size())
+ {
+ linesSizes.resize(line + 1);
+ tokensFrequences.resize(line + 1);
+ }
+
+ tokensFrequences[line][value]++;
+
+ if (tokensFrequences[line][value] == 1)
+ numContainingStrings[value]++;
+
+ linesSizes[line]++;
+ }
+
+ //! Return token frequencies.
+ const std::vector>&
+ TokensFrequences() const { return tokensFrequences; }
+ //! Modify token frequencies.
+ std::vector>& TokensFrequences()
+ {
+ return tokensFrequences;
+ }
+
+ //! Get the number of containing strings depending on the given token.
+ const std::unordered_map& NumContainingStrings() const
+ {
+ return numContainingStrings;
+ }
+
+ //! Modify the number of containing strings depending on the given token.
+ std::unordered_map& NumContainingStrings()
+ {
+ return numContainingStrings;
+ }
+
+ //! Return the lines sizes.
+ const std::vector& LinesSizes() const { return linesSizes; }
+ //! Modify the lines sizes.
+ std::vector& LinesSizes() { return linesSizes; }
+
+ //! Return the term frequency type.
+ TfTypes TfType() const { return tfType; }
+ //! Modify the term frequency type.
+ TfTypes& TfType() { return tfType; }
+
+ //! Determine the idf algorithm type (whether it's smooth or not).
+ bool SmoothIdf() const { return smoothIdf; }
+ //! Modify the idf algorithm type (whether it's smooth or not).
+ bool& SmoothIdf() { return smoothIdf; }
+
+ /**
+ * Serialize the class to the given archive.
+ */
+ template
+ void serialize(Archive& ar, const unsigned int /* version */)
+ {
+ ar & BOOST_SERIALIZATION_NVP(tfType);
+ ar & BOOST_SERIALIZATION_NVP(smoothIdf);
+ }
+
+ private:
+ /**
+ * The function calculates the term frequency statistics.
+ *
+ * @tparam ValueType Type of the returned value.
+ *
+ * @param numOccurrences The number of the given token occurrences in
+ * the line.
+ * @param numTokens The total number of tokens in the line.
+ */
+ template
+ ValueType TermFrequency(const size_t numOccurrences,
+ const size_t numTokens)
+ {
+ switch (tfType)
+ {
+ case TfTypes::BINARY:
+ return numOccurrences > 0;
+ case TfTypes::RAW_COUNT:
+ return numOccurrences;
+ case TfTypes::TERM_FREQUENCY:
+ return static_cast(numOccurrences) / numTokens;
+ case TfTypes::SUBLINEAR_TF:
+ return std::log(static_cast(numOccurrences)) + 1;
+ default:
+ Log::Fatal << "Incorrect term frequency type!";
+ return 0;
+ }
+ }
+
+ /**
+ * The function calculates the inverse document frequency statistics.
+ *
+ * @tparam ValueType Type of the returned value.
+ *
+ * @param totalNumLines The total number of strings in the input dataset.
+ * @param numOccurrences The number of strings in the input dataset
+ * which contain the current token.
+ */
+ template
+ ValueType InverseDocumentFrequency(const size_t totalNumLines,
+ const size_t numOccurrences)
+ {
+ if (smoothIdf)
+ {
+ return std::log(static_cast(totalNumLines + 1) /
+ (1 + numOccurrences)) + 1.0;
+ }
+ else
+ {
+ return std::log(static_cast(totalNumLines) /
+ numOccurrences) + 1.0;
+ }
+ }
+
+ private:
+ //! Used to store the total number of tokens for each line.
+ std::vector> tokensFrequences;
+ /**
+ * Used to store the number of strings which contain a token depending
+ * on the given token.
+ */
+ std::unordered_map numContainingStrings;
+ //! Used to store the number of tokens in each line.
+ std::vector linesSizes;
+ //! Type of the term frequency scheme.
+ TfTypes tfType;
+ //! Indicates whether the idf scheme is smooth or not.
+ bool smoothIdf;
+};
+
+/**
+ * A convenient alias for the StringEncoding class with TfIdfEncodingPolicy
+ * and the default dictionary for the given token type.
+ *
+ * @tparam TokenType Type of the tokens.
+ */
+template
+using TfIdfEncoding = StringEncoding>;
+} // namespace data
+} // namespace mlpack
+
+#endif
diff --git a/src/mlpack/core/util/arma_traits.hpp b/src/mlpack/core/util/arma_traits.hpp
index 45e5dac125..155a6a0d82 100644
--- a/src/mlpack/core/util/arma_traits.hpp
+++ b/src/mlpack/core/util/arma_traits.hpp
@@ -81,14 +81,34 @@ struct IsVector >
const static bool value = true;
};
-// I'm not so sure about this one. An SpSubview object can be a row or column,
-// but it can also be a matrix subview.
-// template<>
-template
-struct IsVector >
-{
- const static bool value = true;
-};
+#if ((ARMA_VERSION_MAJOR >= 10) || \
+ ((ARMA_VERSION_MAJOR == 9) && (ARMA_VERSION_MINOR >= 869)))
+
+ // Armadillo 9.869+ has SpSubview_col and SpSubview_row
+
+ template
+ struct IsVector >
+ {
+ const static bool value = true;
+ };
+
+ template
+ struct IsVector >
+ {
+ const static bool value = true;
+ };
+
+#else
+
+ // fallback for older Armadillo versions
+
+ template
+ struct IsVector >
+ {
+ const static bool value = true;
+ };
+
+#endif
#endif
diff --git a/src/mlpack/core/util/version.hpp b/src/mlpack/core/util/version.hpp
index 14d8daa822..a1c421d0fa 100644
--- a/src/mlpack/core/util/version.hpp
+++ b/src/mlpack/core/util/version.hpp
@@ -17,8 +17,8 @@
// The version of mlpack. If this is a git repository, this will be a version
// with higher number than the most recent release.
#define MLPACK_VERSION_MAJOR 3
-#define MLPACK_VERSION_MINOR 2
-#define MLPACK_VERSION_PATCH 3
+#define MLPACK_VERSION_MINOR 3
+#define MLPACK_VERSION_PATCH 1
// The name of the version (for use by --version).
namespace mlpack {
diff --git a/src/mlpack/methods/ann/layer/layer.hpp b/src/mlpack/methods/ann/layer/layer.hpp
index 6006073a99..44cc8b667f 100644
--- a/src/mlpack/methods/ann/layer/layer.hpp
+++ b/src/mlpack/methods/ann/layer/layer.hpp
@@ -12,32 +12,57 @@
#ifndef MLPACK_METHODS_ANN_LAYER_LAYER_HPP
#define MLPACK_METHODS_ANN_LAYER_LAYER_HPP
+#include "add.hpp"
#include "add_merge.hpp"
+#include "alpha_dropout.hpp"
#include "atrous_convolution.hpp"
+#include "base_layer.hpp"
#include "batch_norm.hpp"
+#include "bilinear_interpolation.hpp"
+#include "c_relu.hpp"
+#include "celu.hpp"
#include "concat_performance.hpp"
+#include "concat.hpp"
+#include "concatenate.hpp"
+#include "constant.hpp"
#include "convolution.hpp"
#include "dropconnect.hpp"
+#include "dropout.hpp"
+#include "elu.hpp"
+#include "fast_lstm.hpp"
+#include "flexible_relu.hpp"
#include "glimpse.hpp"
+#include "gru.hpp"
+#include "hard_tanh.hpp"
+#include "hardshrink.hpp"
#include "highway.hpp"
+#include "join.hpp"
#include "layer_norm.hpp"
#include "layer_types.hpp"
+#include "leaky_relu.hpp"
#include "linear.hpp"
#include "linear_no_bias.hpp"
+#include "log_softmax.hpp"
+#include "lookup.hpp"
#include "lstm.hpp"
+#include "max_pooling.hpp"
+#include "mean_pooling.hpp"
#include "minibatch_discrimination.hpp"
+#include "multiply_constant.hpp"
#include "multiply_merge.hpp"
#include "padding.hpp"
-#include "gru.hpp"
-#include "fast_lstm.hpp"
-#include "recurrent.hpp"
+#include "parametric_relu.hpp"
#include "recurrent_attention.hpp"
+#include "recurrent.hpp"
+#include "reinforce_normal.hpp"
#include "reparametrization.hpp"
+#include "select.hpp"
#include "sequential.hpp"
+#include "softshrink.hpp"
#include "subview.hpp"
-#include "concat.hpp"
-#include "vr_class_reward.hpp"
#include "transposed_convolution.hpp"
+#include "virtual_batch_norm.hpp"
+#include "vr_class_reward.hpp"
#include "weight_norm.hpp"
#endif
diff --git a/src/mlpack/methods/ann/layer/layer_types.hpp b/src/mlpack/methods/ann/layer/layer_types.hpp
index 3c17021e45..5a07c59016 100644
--- a/src/mlpack/methods/ann/layer/layer_types.hpp
+++ b/src/mlpack/methods/ann/layer/layer_types.hpp
@@ -30,6 +30,7 @@
#include
#include
#include
+#include
#include
#include
#include
diff --git a/src/mlpack/methods/ann/loss_functions/CMakeLists.txt b/src/mlpack/methods/ann/loss_functions/CMakeLists.txt
index 8a2111091b..c20856a214 100644
--- a/src/mlpack/methods/ann/loss_functions/CMakeLists.txt
+++ b/src/mlpack/methods/ann/loss_functions/CMakeLists.txt
@@ -3,6 +3,8 @@
set(SOURCES
cross_entropy_error.hpp
cross_entropy_error_impl.hpp
+ cosine_embedding_loss.hpp
+ cosine_embedding_loss_impl.hpp
dice_loss.hpp
dice_loss_impl.hpp
earth_mover_distance.hpp
@@ -11,6 +13,8 @@ set(SOURCES
huber_loss_impl.hpp
kl_divergence.hpp
kl_divergence_impl.hpp
+ margin_ranking_loss.hpp
+ margin_ranking_loss_impl.hpp
mean_bias_error.hpp
mean_bias_error_impl.hpp
mean_squared_error.hpp
diff --git a/src/mlpack/methods/ann/loss_functions/cosine_embedding_loss.hpp b/src/mlpack/methods/ann/loss_functions/cosine_embedding_loss.hpp
new file mode 100644
index 0000000000..044fbbdd0e
--- /dev/null
+++ b/src/mlpack/methods/ann/loss_functions/cosine_embedding_loss.hpp
@@ -0,0 +1,141 @@
+/**
+ * @file cosine_embedding_loss.hpp
+ * @author Kartik Dutt
+ *
+ * Definition of the Cosine Embedding loss function.
+ *
+ * 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_METHODS_ANN_LOSS_FUNCTION_COSINE_EMBEDDING_HPP
+#define MLPACK_METHODS_ANN_LOSS_FUNCTION_COSINE_EMBEDDING_HPP
+
+#include
+
+namespace mlpack {
+namespace ann /** Artificial Neural Network. */ {
+
+/**
+ * Cosine Embedding Loss function is used for measuring whether two inputs are
+ * similar or dissimilar, using the cosine distance, and is typically used
+ * for learning nonlinear embeddings or semi-supervised learning.
+ *
+ * @f{eqnarray*}{
+ * f(x) = 1 - cos(x1, x2) , for y = 1
+ * f(x) = max(0, cos(x1, x2) - margin) , for y = -1
+ * @f}
+ *
+ * @tparam InputDataType Type of the input data (arma::colvec, arma::mat,
+ * arma::sp_mat or arma::cube).
+ * @tparam OutputDataType Type of the output data (arma::colvec, arma::mat,
+ * arma::sp_mat or arma::cube).
+ */
+template <
+ typename InputDataType = arma::mat,
+ typename OutputDataType = arma::mat
+>
+class CosineEmbeddingLoss
+{
+ public:
+ /**
+ * Create the CosineEmbeddingLoss object.
+ *
+ * @param margin Increases cosine distance in case of dissimilarity.
+ * Refer definition of cosine-embedding-loss above.
+ * @param similarity Determines whether to use similarity or dissimilarity for
+ * comparision.
+ * @param takeMean Boolean variable to specify whether to take mean or not.
+ * Specifies reduction method i.e. sum or mean corresponding
+ * to 0 and 1 respectively. Default value = 0.
+ */
+ CosineEmbeddingLoss(const double margin = 0.0,
+ const bool similarity = true,
+ const bool takeMean = false);
+
+ /**
+ * Ordinary feed forward pass of a neural network.
+ *
+ * @param input Input data used for evaluating the specified function.
+ * @param target The target vector.
+ */
+ template
+ typename InputType::elem_type Forward(const InputType& input,
+ const TargetType& target);
+
+ /**
+ * Ordinary feed backward pass of a neural network.
+ *
+ * @param input The propagated input activation.
+ * @param target The target vector.
+ * @param output The calculated error.
+ */
+ template
+ void Backward(const InputType& input,
+ const TargetType& target,
+ OutputType& output);
+
+ //! Get the input parameter.
+ InputDataType& InputParameter() const { return inputParameter; }
+ //! Modify the input parameter.
+ InputDataType& InputParameter() { return inputParameter; }
+
+ //! Get the output parameter.
+ OutputDataType& OutputParameter() const { return outputParameter; }
+ //! Modify the output parameter.
+ OutputDataType& OutputParameter() { return outputParameter; }
+
+ //! Get the delta.
+ OutputDataType& Delta() const { return delta; }
+ //! Modify the delta.
+ OutputDataType& Delta() { return delta; }
+
+ //! Get the value of takeMean.
+ bool TakeMean() const { return takeMean; }
+ //! Modify the value of takeMean.
+ bool& TakeMean() { return takeMean; }
+
+ //! Get the value of margin.
+ double Margin() const { return margin; }
+ //! Modify the value of takeMean.
+ double& Margin() { return margin; }
+
+ //! Get the value of similarity hyperparameter.
+ bool Similarity() const { return similarity; }
+ //! Modify the value of takeMean.
+ bool& Similarity() { return similarity; }
+
+ /**
+ * Serialize the layer.
+ */
+ template
+ void serialize(Archive& ar, const unsigned int /* version */);
+
+ private:
+ //! Locally-stored delta object.
+ OutputDataType delta;
+
+ //! Locally-stored input parameter object.
+ InputDataType inputParameter;
+
+ //! Locally-stored output parameter object.
+ OutputDataType outputParameter;
+
+ //! Locally-stored value of similarity hyper-parameter.
+ bool similarity;
+
+ //! Locally-stored value of margin hyper-parameter.
+ double margin;
+
+ //! Locally-stored value of takeMean hyper-parameter.
+ bool takeMean;
+}; // class CosineEmbeddingLoss
+
+} // namespace ann
+} // namespace mlpack
+
+// Include implementation.
+#include "cosine_embedding_loss_impl.hpp"
+
+#endif
diff --git a/src/mlpack/methods/ann/loss_functions/cosine_embedding_loss_impl.hpp b/src/mlpack/methods/ann/loss_functions/cosine_embedding_loss_impl.hpp
new file mode 100644
index 0000000000..b708567b28
--- /dev/null
+++ b/src/mlpack/methods/ann/loss_functions/cosine_embedding_loss_impl.hpp
@@ -0,0 +1,120 @@
+/**
+ * @file cosine_embedding_loss_impl.hpp
+ * @author Kartik Dutt
+ *
+ * Implementation of the Cosine Embedding loss function.
+ *
+ * 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_METHODS_ANN_LOSS_FUNCTION_COSINE_EMBEDDING_IMPL_HPP
+#define MLPACK_METHODS_ANN_LOSS_FUNCTION_COSINE_EMBEDDING_IMPL_HPP
+
+// In case it hasn't yet been included.
+#include "cosine_embedding_loss.hpp"
+
+namespace mlpack {
+namespace ann /** Artificial Neural Network. */ {
+
+template
+CosineEmbeddingLoss::CosineEmbeddingLoss(
+ const double margin, const bool similarity, const bool takeMean):
+ margin(margin), similarity(similarity), takeMean(takeMean)
+{
+ // Nothing to do here.
+}
+
+template
+template
+typename InputType::elem_type
+CosineEmbeddingLoss::Forward(
+ const InputType& input,
+ const TargetType& target)
+{
+ typedef typename InputType::elem_type ElemType;
+
+ const size_t cols = input.n_cols;
+ const size_t batchSize = input.n_elem / cols;
+ if (arma::size(input) != arma::size(target))
+ Log::Fatal << "Input Tensors must have same dimensions." << std::endl;
+
+ arma::colvec inputTemp1 = arma::vectorise(input);
+ arma::colvec inputTemp2 = arma::vectorise(target);
+ ElemType loss = 0.0;
+
+ for (size_t i = 0; i < inputTemp1.n_elem; i += cols)
+ {
+ const ElemType cosDist = kernel::CosineDistance::Evaluate(
+ inputTemp1(arma::span(i, i + cols - 1)), inputTemp2(arma::span(i,
+ i + cols - 1)));
+ if (similarity)
+ loss += 1 - cosDist;
+ else
+ {
+ const ElemType currentLoss = cosDist - margin;
+ loss += currentLoss > 0 ? currentLoss : 0;
+ }
+ }
+
+ if (takeMean)
+ loss = (ElemType) loss / batchSize;
+
+ return loss;
+}
+
+template
+template
+void CosineEmbeddingLoss::Backward(
+ const InputType& input,
+ const TargetType& target,
+ OutputType& output)
+{
+ typedef typename InputType::elem_type ElemType;
+
+ const size_t cols = input.n_cols;
+ const size_t batchSize = input.n_elem / cols;
+ if (arma::size(input) != arma::size(target))
+ Log::Fatal << "Input Tensors must have same dimensions." << std::endl;
+
+ arma::colvec inputTemp1 = arma::vectorise(input);
+ arma::colvec inputTemp2 = arma::vectorise(target);
+ output.set_size(arma::size(inputTemp1));
+
+ arma::colvec outputTemp(output.memptr(), inputTemp1.n_elem,
+ false, false);
+ for (size_t i = 0; i < inputTemp1.n_elem; i += cols)
+ {
+ const ElemType cosDist = kernel::CosineDistance::Evaluate(inputTemp1(
+ arma::span(i, i + cols -1)), inputTemp2(arma::span(i, i + cols -1)));
+
+ if (cosDist < margin && !similarity)
+ outputTemp(arma::span(i, i + cols - 1)).zeros();
+ else
+ {
+ const int multiplier = similarity ? 1 : -1;
+ outputTemp(arma::span(i, i + cols -1)) = -1 * multiplier *
+ (arma::normalise(inputTemp2(arma::span(i, i + cols - 1))) -
+ cosDist * arma::normalise(inputTemp1(arma::span(i, i + cols -
+ 1)))) / std::sqrt(arma::accu(arma::pow(inputTemp1(arma::span(i, i +
+ cols - 1)), 2)));
+ }
+ }
+}
+
+template
+template
+void CosineEmbeddingLoss::serialize(
+ Archive& ar ,
+ const unsigned int /* version */)
+{
+ ar & BOOST_SERIALIZATION_NVP(margin);
+ ar & BOOST_SERIALIZATION_NVP(similarity);
+ ar & BOOST_SERIALIZATION_NVP(takeMean);
+}
+
+} // namespace ann
+} // namespace mlpack
+
+#endif
diff --git a/src/mlpack/methods/ann/loss_functions/margin_ranking_loss.hpp b/src/mlpack/methods/ann/loss_functions/margin_ranking_loss.hpp
new file mode 100644
index 0000000000..e8798dd62b
--- /dev/null
+++ b/src/mlpack/methods/ann/loss_functions/margin_ranking_loss.hpp
@@ -0,0 +1,102 @@
+/**
+ * @file margin_ranking_loss.hpp
+ * @author Andrei Mihalea
+ *
+ * Definition of the Margin Ranking Loss function.
+ *
+ * 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_ANN_LOSS_FUNCTION_MARGIN_RANKING_LOSS_HPP
+#define MLPACK_ANN_LOSS_FUNCTION_MARGIN_RANKING_LOSS_HPP
+
+#include
+
+namespace mlpack {
+namespace ann /** Artificial Neural Network. */ {
+
+/**
+ * Margin ranking loss measures the loss given inputs and a label vector with
+ * values of 1 or -1. If the label is 1 then the first input should be ranked
+ * higher than the second input at a distance larger than a margin, and vice-
+ * versa if the label is -1.
+ *
+ * @tparam InputDataType Type of the input data (arma::colvec, arma::mat,
+ * arma::sp_mat or arma::cube).
+ * @tparam OutputDataType Type of the output data (arma::colvec, arma::mat,
+ * arma::sp_mat or arma::cube).
+ */
+template <
+ typename InputDataType = arma::mat,
+ typename OutputDataType = arma::mat
+>
+class MarginRankingLoss
+{
+ public:
+ /**
+ * Create the MarginRankingLoss object with Hyperparameter margin.
+ * Hyperparameter margin defines a minimum distance between correctly ranked
+ * samples.
+ */
+ MarginRankingLoss(const double margin = 1.0);
+
+ /**
+ * Computes the Margin Ranking Loss function.
+ *
+ * @param input Concatenation of the two inputs for evaluating the specified
+ * function.
+ * @param target The label vector which contains values of -1 or 1.
+ */
+ template
+ typename InputType::elem_type Forward(const InputType& input,
+ const TargetType& target);
+
+ /**
+ * Ordinary feed backward pass of a neural network.
+ *
+ * @param input The propagated concatenated input activation.
+ * @param target The label vector which contains -1 or 1 values.
+ * @param output The calculated error.
+ */
+ template <
+ typename InputType,
+ typename TargetType,
+ typename OutputType
+ >
+ void Backward(const InputType& input,
+ const TargetType& target,
+ OutputType& output);
+
+ //! Get the output parameter.
+ OutputDataType& OutputParameter() const { return outputParameter; }
+ //! Modify the output parameter.
+ OutputDataType& OutputParameter() { return outputParameter; }
+
+ //! Get the margin parameter.
+ double Margin() const { return margin; }
+ //! Modify the margin parameter.
+ double& Margin() { return margin; }
+
+ /**
+ * Serialize the layer.
+ */
+ template
+ void serialize(Archive& ar, const unsigned int /* version */);
+
+ private:
+ //! Locally-stored output parameter object.
+ OutputDataType outputParameter;
+
+ //! The margin value used in calculating Margin Ranking Loss.
+ double margin;
+}; // class MarginRankingLoss
+
+} // namespace ann
+} // namespace mlpack
+
+// include implementation.
+#include "margin_ranking_loss_impl.hpp"
+
+#endif
diff --git a/src/mlpack/methods/ann/loss_functions/margin_ranking_loss_impl.hpp b/src/mlpack/methods/ann/loss_functions/margin_ranking_loss_impl.hpp
new file mode 100644
index 0000000000..59649cbb3a
--- /dev/null
+++ b/src/mlpack/methods/ann/loss_functions/margin_ranking_loss_impl.hpp
@@ -0,0 +1,74 @@
+/**
+ * @file margin_ranking_loss_impl.hpp
+ * @author Andrei Mihalea
+ *
+ * Implementation of the Margin Ranking Loss function.
+ *
+ * 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_METHODS_ANN_LOSS_FUNCTION_MARGIN_IMPL_LOSS_HPP
+#define MLPACK_METHODS_ANN_LOSS_FUNCTION_MARGIN_IMPL_LOSS_HPP
+
+// In case it hasn't been included.
+#include "margin_ranking_loss.hpp"
+
+namespace mlpack {
+namespace ann /** Artifical Neural Network. */ {
+
+template
+MarginRankingLoss::MarginRankingLoss(
+ const double margin) : margin(margin)
+{
+ // Nothing to do here.
+}
+
+template
+template
+typename InputType::elem_type
+MarginRankingLoss::Forward(
+ const InputType& input,
+ const TargetType& target)
+{
+ const int inputRows = input.n_rows;
+ const InputType& input1 = input.rows(0, inputRows / 2 - 1);
+ const InputType& input2 = input.rows(inputRows / 2, inputRows - 1);
+ return arma::accu(arma::max(arma::zeros(size(target)),
+ -target % (input1 - input2) + margin)) / target.n_cols;
+}
+
+template
+template <
+ typename InputType,
+ typename TargetType,
+ typename OutputType
+>
+void MarginRankingLoss::Backward(
+ const InputType& input,
+ const TargetType& target,
+ OutputType& output)
+{
+ const int inputRows = input.n_rows;
+ const InputType& input1 = input.rows(0, inputRows / 2 - 1);
+ const InputType& input2 = input.rows(inputRows / 2, inputRows - 1);
+ output = -target % (input1 - input2) + margin;
+ output.elem(arma::find(output >= 0)).ones();
+ output.elem(arma::find(output < 0)).zeros();
+ output = (input2 - input1) % output / target.n_cols;
+}
+
+template
+template
+void MarginRankingLoss::serialize(
+ Archive& ar,
+ const unsigned int /* version */)
+{
+ ar & BOOST_SERIALIZATION_NVP(margin);
+}
+
+} // namespace ann
+} // namespace mlpack
+
+#endif
diff --git a/src/mlpack/methods/logistic_regression/logistic_regression_impl.hpp b/src/mlpack/methods/logistic_regression/logistic_regression_impl.hpp
index 760af72acd..1f5b81eb33 100644
--- a/src/mlpack/methods/logistic_regression/logistic_regression_impl.hpp
+++ b/src/mlpack/methods/logistic_regression/logistic_regression_impl.hpp
@@ -25,7 +25,6 @@ LogisticRegression::LogisticRegression(
const MatType& predictors,
const arma::Row& responses,
const double lambda) :
- parameters(arma::rowvec(predictors.n_rows + 1, arma::fill::zeros)),
lambda(lambda)
{
Train(predictors, responses);
@@ -60,7 +59,6 @@ LogisticRegression::LogisticRegression(
const arma::Row& responses,
OptimizerType& optimizer,
const double lambda) :
- parameters(arma::rowvec(predictors.n_rows + 1, arma::fill::zeros)),
lambda(lambda)
{
Train(predictors, responses, optimizer);
@@ -85,9 +83,11 @@ double LogisticRegression::Train(
OptimizerType& optimizer,
CallbackTypes&&... callbacks)
{
- LogisticRegressionFunction errorFunction(predictors,
- responses,
- lambda);
+ LogisticRegressionFunction errorFunction(predictors, responses,
+ lambda);
+
+ // Set size of parameters vector according to the input data received.
+ parameters = arma::rowvec(predictors.n_rows + 1, arma::fill::zeros);
errorFunction.InitialPoint() = parameters;
Timer::Start("logistic_regression_optimization");
diff --git a/src/mlpack/methods/preprocess/CMakeLists.txt b/src/mlpack/methods/preprocess/CMakeLists.txt
index 2410d2b1cf..d1b1dd5816 100644
--- a/src/mlpack/methods/preprocess/CMakeLists.txt
+++ b/src/mlpack/methods/preprocess/CMakeLists.txt
@@ -40,4 +40,12 @@ add_markdown_docs(preprocess_imputer "cli" "preprocessing")
add_cli_executable(preprocess_scale)
add_python_binding(preprocess_scale)
-add_markdown_docs(preprocess_scale "cli;python" "preprocessing")
+add_julia_binding(preprocess_scale)
+add_markdown_docs(preprocess_scale "cli;python;julia" "preprocessing")
+
+if (STB_AVAILABLE)
+ add_cli_executable(image_converter)
+ add_python_binding(image_converter)
+ add_julia_binding(image_converter)
+ add_markdown_docs(image_converter "cli;python;julia" "preprocessing")
+endif ()
\ No newline at end of file
diff --git a/src/mlpack/methods/preprocess/image_converter_main.cpp b/src/mlpack/methods/preprocess/image_converter_main.cpp
new file mode 100644
index 0000000000..0d4beecf4b
--- /dev/null
+++ b/src/mlpack/methods/preprocess/image_converter_main.cpp
@@ -0,0 +1,114 @@
+/**
+ * @file image_converter_main.cpp
+ * @author Jeffin Sam
+ *
+ * A CLI executable to load and save a image dataset.
+ *
+ * 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
+#include
+#include
+#include
+
+using namespace mlpack;
+using namespace mlpack::util;
+using namespace arma;
+using namespace std;
+using namespace mlpack::data;
+
+PROGRAM_INFO("Image Converter",
+ // Short description.
+ "A utility to load an image or set of images into a single dataset that"
+ " can then be used by other mlpack methods and utilities. This can also"
+ " unpack an image dataset into individual files, for instance after mlpack"
+ " methods have been used.",
+ // Long description.
+ "This utility takes an image or an array of images and loads them to a"
+ " matrix. You can optionally specify the height " +
+ PRINT_PARAM_STRING("height") + " width " + PRINT_PARAM_STRING("width")
+ + " and channel " + PRINT_PARAM_STRING("channels") + " of the images that"
+ " needs to be loaded; otherwise, these parameters will be automatically"
+ " detected from the image."
+ "\n"
+ "There are other options too, that can be specified such as " +
+ PRINT_PARAM_STRING("quality")
+ + ".\n\n" +
+ "You can also provide a dataset and save them as images using " +
+ PRINT_PARAM_STRING("dataset") + " and " + PRINT_PARAM_STRING("save") +
+ " as an parameter. An example to load an image : " +
+ "\n\n" +
+ PRINT_CALL("image_converter", "input", "X", "height", 256, "width", 256,
+ "channels", 3, "output", "Y") +
+ "\n\n" +
+ " An example to save an image is :" +
+ "\n\n" +
+ PRINT_CALL("image_converter", "input", "X", "height", 256, "width", 256,
+ "channels", 3, "dataset", "Y", "save", true),
+ SEE_ALSO("@preprocess_binarize", "#preprocess_binarize"),
+ SEE_ALSO("@preprocess_describe", "#preprocess_describe"),
+ SEE_ALSO("@preprocess_imputer", "#preprocess_imputer"));
+
+// DEFINE PARAM
+PARAM_VECTOR_IN_REQ(string, "input", "Image filenames which have to "
+ "be loaded/saved.", "i");
+
+PARAM_INT_IN("width", "Width of the image.", "w", 0);
+PARAM_INT_IN("channels", "Number of channels in the image.", "c", 0);
+
+PARAM_MATRIX_OUT("output", "Matrix to save images data to, Only"
+ "needed if you are specifying 'save' option.", "o");
+
+PARAM_INT_IN("quality", "Compression of the image if saved as jpg (0-100).",
+ "q", 90);
+
+PARAM_INT_IN("height", "Height of the images.", "H", 0);
+PARAM_FLAG("save", "Save a dataset as images.", "s");
+PARAM_MATRIX_IN("dataset", "Input matrix to save as images.", "I");
+
+static void mlpackMain()
+{
+ Timer::Start("Loading/Saving Image");
+ // Parse command line options.
+ const vector fileNames = CLI::GetParam >("input");
+ arma::mat out;
+
+ if (!CLI::HasParam("save"))
+ {
+ ReportIgnoredParam("width", "Width of image is determined from file.");
+ ReportIgnoredParam("height", "Height of image is determined from file.");
+ ReportIgnoredParam("channels", "Number of channels determined from file.");
+ data::ImageInfo info;
+ Load(fileNames, out, info, true);
+ if (CLI::HasParam("output"))
+ CLI::GetParam("output") = std::move(out);
+ }
+ else
+ {
+ RequireNoneOrAllPassed({ "save", "width", "height", "channels", "dataset" }
+ , true, "Image size information is needed when 'save' is specified!");
+ // Positive value for width.
+ RequireParamValue("width", [](int x) { return x >= 0;}, true,
+ "width must be positive");
+ // Positive value for height.
+ RequireParamValue("height", [](int x) { return x >= 0;}, true,
+ "height must be positive");
+ // Positive value for channel.
+ RequireParamValue("channels", [](int x) { return x >= 0;}, true,
+ "channels must be positive");
+ // Positive value for quality.
+ RequireParamValue("quality", [](int x) { return x >= 0;}, true,
+ "quality must be positive");
+
+ const size_t height = CLI::GetParam("height");
+ const size_t width = CLI::GetParam("width");
+ const size_t channels = CLI::GetParam("channels");
+ const size_t quality = CLI::GetParam("quality");
+ data::ImageInfo info(width, height, channels, quality);
+ Save(fileNames, CLI::GetParam("dataset"), info, true);
+ }
+}
+
diff --git a/src/mlpack/methods/preprocess/preprocess_scale_main.cpp b/src/mlpack/methods/preprocess/preprocess_scale_main.cpp
index 44d26b3a4b..f4694655e0 100644
--- a/src/mlpack/methods/preprocess/preprocess_scale_main.cpp
+++ b/src/mlpack/methods/preprocess/preprocess_scale_main.cpp
@@ -10,9 +10,10 @@
* http://www.opensource.org/licenses/BSD-3-Clause for more information.
*/
#include
+#include
#include
#include
-#include
+#include
#include
#include
#include
diff --git a/src/mlpack/methods/reinforcement_learning/q_networks/CMakeLists.txt b/src/mlpack/methods/reinforcement_learning/q_networks/CMakeLists.txt
new file mode 100644
index 0000000000..3a8a010bfe
--- /dev/null
+++ b/src/mlpack/methods/reinforcement_learning/q_networks/CMakeLists.txt
@@ -0,0 +1,14 @@
+# Define the files we need to compile
+# Anything not in this list will not be compiled into mlpack.
+set(SOURCES
+ simple_dqn.hpp
+)
+
+# Add directory name to sources.
+set(DIR_SRCS)
+foreach(file ${SOURCES})
+ set(DIR_SRCS ${DIR_SRCS} ${CMAKE_CURRENT_SOURCE_DIR}/${file})
+endforeach()
+# Append sources (with directory name) to list of all mlpack sources (used at
+# the parent scope).
+set(MLPACK_SRCS ${MLPACK_SRCS} ${DIR_SRCS} PARENT_SCOPE)
\ No newline at end of file
diff --git a/src/mlpack/methods/reinforcement_learning/q_networks/simple_dqn.hpp b/src/mlpack/methods/reinforcement_learning/q_networks/simple_dqn.hpp
new file mode 100644
index 0000000000..30d13180a5
--- /dev/null
+++ b/src/mlpack/methods/reinforcement_learning/q_networks/simple_dqn.hpp
@@ -0,0 +1,127 @@
+/**
+ * @file simple_dqn.hpp
+ * @author Nishant Kumar
+ *
+ * This file contains the implementation of the simple deep q network.
+ *
+ * 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_METHODS_RL_SIMPLE_DQN_HPP
+#define MLPACK_METHODS_RL_SIMPLE_DQN_HPP
+
+#include
+#include
+#include
+#include
+#include
+
+namespace mlpack {
+namespace rl {
+
+using namespace mlpack::ann;
+
+/**
+ * @tparam NetworkType The type of network used for simple dqn.
+ */
+template ,
+ GaussianInitialization>>
+class SimpleDQN
+{
+ public:
+ /**
+ * Default constructor.
+ */
+ SimpleDQN() : network()
+ { /* Nothing to do here. */ }
+
+ /**
+ * Construct an instance of SimpleDQN class.
+ *
+ * @param inputDim Number of inputs.
+ * @param h1 Number of neurons in hiddenlayer-1.
+ * @param h2 Number of neurons in hiddenlayer-2.
+ * @param outputDim Number of neurons in output layer.
+ */
+ SimpleDQN(const int inputDim,
+ const int h1,
+ const int h2,
+ const int outputDim) : network()
+ {
+ FFN, GaussianInitialization> model(MeanSquaredError<>(),
+ GaussianInitialization(0, 0.001));
+ model.Add>(inputDim, h1);
+ model.Add>();
+ model.Add>(h1, h2);
+ model.Add>();
+ model.Add>(h2, outputDim);
+ network = model;
+ }
+
+ SimpleDQN(NetworkType network) : network(std::move(network))
+ { /* Nothing to do here. */ }
+
+ /**
+ * Predict the responses to a given set of predictors. The responses will
+ * reflect the output of the given output layer as returned by the
+ * output layer function.
+ *
+ * If you want to pass in a parameter and discard the original parameter
+ * object, be sure to use std::move to avoid unnecessary copy.
+ *
+ * @param state Input state.
+ * @param actionValue Matrix to put output action values of states input.
+ */
+ void Predict(const arma::mat state, arma::mat& actionValue)
+ {
+ network.Predict(state, actionValue);
+ }
+
+ /**
+ * Perform the forward pass of the states in real batch mode.
+ *
+ * @param state The input state.
+ * @param target The predicted target.
+ */
+ void Forward(const arma::mat state, arma::mat& target)
+ {
+ network.Forward(state, target);
+ }
+
+ /**
+ * Resets the parameters of the network.
+ */
+ void ResetParameters()
+ {
+ network.ResetParameters();
+ }
+
+ //! Return the Parameters.
+ const arma::mat& Parameters() const { return network.Parameters(); }
+ //! Modify the Parameters.
+ arma::mat& Parameters() { return network.Parameters(); }
+
+ /**
+ * Perform the backward pass of the state in real batch mode.
+ *
+ * @param state The input state.
+ * @param target The training target.
+ * @return gradient The gradient.
+ */
+ void Backward(const arma::mat state, arma::mat& target,
+arma::mat& gradient)
+ {
+ network.Backward(state, target, gradient);
+ }
+
+ private:
+ //! Locally-stored network.
+ NetworkType network;
+};
+
+} // namespace rl
+} // namespace mlpack
+
+#endif
diff --git a/src/mlpack/methods/softmax_regression/softmax_regression_impl.hpp b/src/mlpack/methods/softmax_regression/softmax_regression_impl.hpp
index 30fc341cf1..a38831d657 100644
--- a/src/mlpack/methods/softmax_regression/softmax_regression_impl.hpp
+++ b/src/mlpack/methods/softmax_regression/softmax_regression_impl.hpp
@@ -65,7 +65,7 @@ double SoftmaxRegression::Train(const arma::mat& data,
{
SoftmaxRegressionFunction regressor(data, labels, numClasses, lambda,
fitIntercept);
- if (parameters.is_empty())
+ if (parameters.n_elem != regressor.GetInitialPoint().n_elem)
parameters = regressor.GetInitialPoint();
// Train the model.
@@ -88,7 +88,7 @@ double SoftmaxRegression::Train(const arma::mat& data,
{
SoftmaxRegressionFunction regressor(data, labels, numClasses, lambda,
fitIntercept);
- if (parameters.is_empty())
+ if (parameters.n_elem != regressor.GetInitialPoint().n_elem)
parameters = regressor.GetInitialPoint();
// Train the model.
diff --git a/src/mlpack/tests/CMakeLists.txt b/src/mlpack/tests/CMakeLists.txt
index 32bc77b5d3..77e4fcc2e4 100644
--- a/src/mlpack/tests/CMakeLists.txt
+++ b/src/mlpack/tests/CMakeLists.txt
@@ -137,6 +137,7 @@ add_executable(mlpack_test
main_tests/kfn_test.cpp
main_tests/knn_test.cpp
main_tests/linear_regression_test.cpp
+ main_tests/image_converter_test.cpp
main_tests/linear_svm_test.cpp
main_tests/logistic_regression_test.cpp
main_tests/local_coordinate_coding_test.cpp
diff --git a/src/mlpack/tests/image_load_test.cpp b/src/mlpack/tests/image_load_test.cpp
index e7c90acb1a..b5172dbeb0 100644
--- a/src/mlpack/tests/image_load_test.cpp
+++ b/src/mlpack/tests/image_load_test.cpp
@@ -12,6 +12,8 @@
#include
#include
+#include "test_tools.hpp"
+#include "serialization.hpp"
using namespace mlpack;
using namespace mlpack::data;
@@ -43,7 +45,11 @@ BOOST_AUTO_TEST_CASE(LoadImageAPITest)
arma::Mat matrix;
data::ImageInfo info;
BOOST_REQUIRE(data::Load("test_image.png", matrix, info, false) == true);
- BOOST_REQUIRE_EQUAL(matrix.n_rows, 50 * 50 * 3); // width * height * channels.
+ // width * height * channels.
+ BOOST_REQUIRE_EQUAL(matrix.n_rows, 50 * 50 * 3);
+ BOOST_REQUIRE_EQUAL(info.Height(), 50);
+ BOOST_REQUIRE_EQUAL(info.Width(), 50);
+ BOOST_REQUIRE_EQUAL(info.Channels(), 3);
BOOST_REQUIRE_EQUAL(matrix.n_cols, 1);
}
@@ -64,8 +70,91 @@ BOOST_AUTO_TEST_CASE(SaveImageAPITest)
BOOST_REQUIRE_EQUAL(im1.n_cols, im2.n_cols);
BOOST_REQUIRE_EQUAL(im1.n_rows, im2.n_rows);
- for (size_t i = 10; i < im1.n_elem; ++i)
+ for (size_t i = 0; i < im1.n_elem; ++i)
BOOST_REQUIRE_EQUAL(im1[i], im2[i]);
+ remove("APITest.bmp");
+}
+
+/**
+ * Test if an image with a wrong dimesion throws an expected
+ * exception while saving.
+ */
+BOOST_AUTO_TEST_CASE(SaveImageWrongInfo)
+{
+ data::ImageInfo info(5, 5, 3, 90);
+
+ arma::Mat im1;
+ size_t dimension = info.Width() * info.Height() * info.Channels();
+ im1 = arma::randi>(24 * 25 * 7, 1);
+ Log::Fatal.ignoreInput = true;
+ BOOST_REQUIRE_THROW(data::Save("APITest.bmp", im1, info, false),
+ std::runtime_error);
+ Log::Fatal.ignoreInput = false;
+}
+
+/**
+ * Test that the image is loaded correctly into the matrix using the API
+ * for vectors.
+ */
+BOOST_AUTO_TEST_CASE(LoadVectorImageAPITest)
+{
+ arma::Mat matrix;
+ data::ImageInfo info;
+ std::vector files = {"test_image.png", "test_image.png"};
+ BOOST_REQUIRE(data::Load(files, matrix, info, false) == true);
+ // width * height * channels.
+ BOOST_REQUIRE_EQUAL(matrix.n_rows, 50 * 50 * 3);
+ BOOST_REQUIRE_EQUAL(info.Height(), 50);
+ BOOST_REQUIRE_EQUAL(info.Width(), 50);
+ BOOST_REQUIRE_EQUAL(info.Channels(), 3);
+ BOOST_REQUIRE_EQUAL(matrix.n_cols, 2);
+}
+
+/**
+ * Test if the image is saved correctly using API for arma mat.
+ */
+BOOST_AUTO_TEST_CASE(SaveImageMatAPITest)
+{
+ data::ImageInfo info(5, 5, 3);
+
+ arma::Mat im1;
+ size_t dimension = info.Width() * info.Height() * info.Channels();
+ im1 = arma::randi>(dimension, 1);
+ arma::mat input = arma::conv_to::from(im1);
+ BOOST_REQUIRE(Save("APITest.bmp", input, info, false) == true);
+
+ arma::mat output;
+ BOOST_REQUIRE(Load("APITest.bmp", output, info, false) == true);
+
+ BOOST_REQUIRE_EQUAL(input.n_cols, output.n_cols);
+ BOOST_REQUIRE_EQUAL(input.n_rows, output.n_rows);
+ for (size_t i = 0; i < input.n_elem; ++i)
+ BOOST_REQUIRE_CLOSE(input[i], output[i], 1e-5);
+ remove("APITest.bmp");
+}
+
+/**
+ * Serialization test for the ImageInfo class.
+ */
+BOOST_AUTO_TEST_CASE(ImageInfoSerialization)
+{
+ data::ImageInfo info(5, 5, 3, 90);
+ data::ImageInfo xmlInfo, textInfo, binaryInfo;
+
+ SerializeObjectAll(info, xmlInfo, textInfo, binaryInfo);
+
+ BOOST_REQUIRE_EQUAL(info.Width(), xmlInfo.Width());
+ BOOST_REQUIRE_EQUAL(info.Height(), xmlInfo.Height());
+ BOOST_REQUIRE_EQUAL(info.Channels(), xmlInfo.Channels());
+ BOOST_REQUIRE_EQUAL(info.Quality(), xmlInfo.Quality());
+ BOOST_REQUIRE_EQUAL(info.Width(), textInfo.Width());
+ BOOST_REQUIRE_EQUAL(info.Height(), textInfo.Height());
+ BOOST_REQUIRE_EQUAL(info.Channels(), textInfo.Channels());
+ BOOST_REQUIRE_EQUAL(info.Quality(), textInfo.Quality());
+ BOOST_REQUIRE_EQUAL(info.Width(), binaryInfo.Width());
+ BOOST_REQUIRE_EQUAL(info.Height(), binaryInfo.Height());
+ BOOST_REQUIRE_EQUAL(info.Channels(), binaryInfo.Channels());
+ BOOST_REQUIRE_EQUAL(info.Quality(), binaryInfo.Quality());
}
BOOST_AUTO_TEST_SUITE_END();
diff --git a/src/mlpack/tests/logistic_regression_test.cpp b/src/mlpack/tests/logistic_regression_test.cpp
index d603004a28..f3bbe6b32d 100644
--- a/src/mlpack/tests/logistic_regression_test.cpp
+++ b/src/mlpack/tests/logistic_regression_test.cpp
@@ -1002,4 +1002,25 @@ BOOST_AUTO_TEST_CASE(LogisticRegressionTrainReturnObjective)
BOOST_REQUIRE_EQUAL(std::isfinite(objVal), true);
}
+/**
+ * Test that construction *then* training works fine. Thanks @Trento89 for the
+ * test case (see #2358).
+ */
+BOOST_AUTO_TEST_CASE(ConstructionThenTraining)
+{
+ arma::mat myMatrix;
+
+ // Four points, three dimensions.
+ myMatrix << 0.555950 << 0.274690 << 0.540605 << 0.798938 << arma::endr
+ << 0.948014 << 0.973234 << 0.216504 << 0.883152 << arma::endr
+ << 0.023787 << 0.675382 << 0.231751 << 0.450332 << arma::endr;
+
+ arma::Row myTargets("1 0 1 0");
+
+ regression::LogisticRegression<> lr;
+
+ // Make sure that training doesn't crash with invalid parameter sizes.
+ BOOST_REQUIRE_NO_THROW(lr.Train(myMatrix, myTargets));
+}
+
BOOST_AUTO_TEST_SUITE_END();
diff --git a/src/mlpack/tests/loss_functions_test.cpp b/src/mlpack/tests/loss_functions_test.cpp
index e361c398d0..145ef3b418 100644
--- a/src/mlpack/tests/loss_functions_test.cpp
+++ b/src/mlpack/tests/loss_functions_test.cpp
@@ -22,11 +22,13 @@
#include
#include
#include
+#include
#include
#include
#include
#include
#include
+#include
#include
#include
@@ -578,4 +580,135 @@ BOOST_AUTO_TEST_CASE(HingeEmbeddingLossTest)
BOOST_REQUIRE_EQUAL(output.n_rows, input.n_rows);
BOOST_REQUIRE_EQUAL(output.n_cols, input.n_cols);
}
+
+/**
+ * Simple test for the Cosine Embedding loss function.
+ */
+BOOST_AUTO_TEST_CASE(CosineEmbeddingLossTest)
+{
+ arma::mat input1, input2, y, output;
+ double loss;
+ CosineEmbeddingLoss<> module;
+
+ // Test the Forward function. Loss should be 0 if input1 = input2 and y = 1.
+ input1 = arma::mat(1, 10);
+ input2 = arma::mat(1, 10);
+ input1.ones();
+ input2.ones();
+ y = arma::mat(1, 1);
+ y.ones();
+ loss = module.Forward(input1, input1);
+ BOOST_REQUIRE_SMALL(loss, 1e-6);
+
+ // Test the Backward function.
+ module.Backward(input1, input1, output);
+ BOOST_REQUIRE_SMALL(arma::accu(output), 1e-6);
+
+ // Check for dissimilarity.
+ module.Similarity() = false;
+ loss = module.Forward(input1, input1);
+ BOOST_REQUIRE_CLOSE(loss, 1.0, 1e-4);
+
+ // Test the Backward function.
+ module.Backward(input1, input1, output);
+ BOOST_REQUIRE_SMALL(arma::accu(output), 1e-6);
+
+ input1 = arma::mat(3, 2);
+ input2 = arma::mat(3, 2);
+ input1.fill(1);
+ input1(4) = 2;
+ input2.fill(1);
+ input2(0) = 2;
+ input2(1) = 2;
+ input2(2) = 2;
+ loss = module.Forward(input1, input2);
+ // Calculated using torch.nn.CosineEmbeddingLoss().
+ BOOST_REQUIRE_CLOSE(loss, 2.897367, 1e-3);
+
+ // Test the Backward function.
+ module.Backward(input1, input2, output);
+ BOOST_REQUIRE_CLOSE(arma::accu(output), 0.06324556, 1e-3);
+
+ // Check for correctness for cube.
+ CosineEmbeddingLoss<> module2(0.5, true);
+
+ arma::cube input3(3, 2, 2);
+ arma::cube input4(3, 2, 2);
+ input3.fill(1);
+ input4.fill(1);
+ input3(0) = 2;
+ input3(1) = 2;
+ input3(4) = 2;
+ input3(6) = 2;
+ input3(8) = 2;
+ input3(10) = 2;
+ input4(2) = 2;
+ input4(9) = 2;
+ input4(11) = 2;
+ loss = module2.Forward(input3, input4);
+ // Calculated using torch.nn.CosineEmbeddingLoss().
+ BOOST_REQUIRE_CLOSE(loss, 0.55395, 1e-3);
+
+ // Test the Backward function.
+ module2.Backward(input3, input4, output);
+ BOOST_REQUIRE_CLOSE(arma::accu(output), -0.36649111, 1e-3);
+
+ // Check Output for mean type of reduction.
+ CosineEmbeddingLoss<> module3(0.0, true, true);
+ loss = module3.Forward(input3, input4);
+ BOOST_REQUIRE_CLOSE(loss, 0.092325, 1e-3);
+
+ // Check correctness for cube.
+ module3.Similarity() = false;
+ loss = module3.Forward(input3, input4);
+ BOOST_REQUIRE_CLOSE(loss, 0.90767498236, 1e-3);
+
+ // Test the Backward function.
+ module3.Backward(input3, input4, output);
+ BOOST_REQUIRE_CLOSE(arma::accu(output), 0.36649111, 1e-4);
+}
+
+/*
+ * Simple test for the Margin Ranking Loss function.
+ */
+BOOST_AUTO_TEST_CASE(MarginRankingLossTest)
+{
+ arma::mat input, input1, input2, target, output;
+ MarginRankingLoss<> module;
+
+ // Test the Forward function on a user generator input and compare it against
+ // the manually calculated result.
+ input1 = arma::mat("1 2 5 7 -1 -3");
+ input2 = arma::mat("-1 3 -4 11 3 -3");
+ input = arma::join_cols(input1, input2);
+ target = arma::mat("1 -1 -1 1 -1 1");
+ double error = module.Forward(input, target);
+ // Computed using torch.nn.functional.margin_ranking_loss()
+ BOOST_REQUIRE_CLOSE(error, 2.66667, 1e-3);
+
+ // Test the Backward function.
+ module.Backward(input, target, output);
+
+ CheckMatrices(output, arma::mat("-0.000000 0.166667 -1.500000 0.666667 "
+ "0.000000 -0.000000"), 1e-3);
+ BOOST_REQUIRE_EQUAL(output.n_rows, target.n_rows);
+ BOOST_REQUIRE_EQUAL(output.n_cols, target.n_cols);
+
+ // Test the error function on another input.
+ input1 = arma::mat("0.4287 -1.6208 -1.5006 -0.4473 1.5208 -4.5184 9.3574 "
+ "-4.8090 4.3455 5.2070");
+ input2 = arma::mat("-4.5288 -9.2766 -0.5882 -5.6643 -6.0175 8.8506 3.4759 "
+ "-9.4886 2.2755 8.4951");
+ input = arma::join_cols(input1, input2);
+ target = arma::mat("1 1 -1 1 -1 1 1 1 -1 1");
+ error = module.Forward(input, target);
+ BOOST_REQUIRE_CLOSE(error, 3.03530, 1e-3);
+
+ // Test the Backward function on the second input.
+ module.Backward(input, target, output);
+
+ CheckMatrices(output, arma::mat("0.000000 0.000000 0.091240 0.000000 "
+ "-0.753830 1.336900 0.000000 0.000000 -0.207000 0.328810"), 1e-6);
+}
+
BOOST_AUTO_TEST_SUITE_END();
diff --git a/src/mlpack/tests/main_tests/image_converter_test.cpp b/src/mlpack/tests/main_tests/image_converter_test.cpp
new file mode 100644
index 0000000000..cd77cbaf66
--- /dev/null
+++ b/src/mlpack/tests/main_tests/image_converter_test.cpp
@@ -0,0 +1,185 @@
+/**
+ * @file image_converter_test.cpp
+ * @author Jeffin Sam
+ *
+ * Test mlpackMain() of load_save_image_main.cpp.
+ *
+ * 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.
+ */
+#define BINDING_TYPE BINDING_TYPE_TEST
+
+#include
+static const std::string testName = "ImageConverter";
+
+#include
+#include
+
+#include "test_helper.hpp"
+#include
+#include "../test_tools.hpp"
+
+using namespace mlpack;
+
+struct ImageConverterTestFixture
+{
+ public:
+ ImageConverterTestFixture()
+ {
+ // Cache in the options for this program.
+ CLI::RestoreSettings(testName);
+ }
+
+ ~ImageConverterTestFixture()
+ {
+ // Clear the settings.
+ remove("test_image777.png");
+ remove("test_image999.png");
+ bindings::tests::CleanMemory();
+ CLI::ClearSettings();
+ }
+};
+
+BOOST_FIXTURE_TEST_SUITE(ImageConverterMainTest,
+ ImageConverterTestFixture);
+
+BOOST_AUTO_TEST_CASE(LoadImageTest)
+{
+ SetInputParam>("input", {"test_image.png", "test_image.png"});
+
+ mlpackMain();
+ arma::mat output = CLI::GetParam("output");
+ // width * height * channels.
+ BOOST_REQUIRE_EQUAL(output.n_rows, 50 * 50 * 3);
+ BOOST_REQUIRE_EQUAL(output.n_cols, 2);
+}
+
+BOOST_AUTO_TEST_CASE(SaveImageTest)
+{
+ arma::mat testimage = arma::conv_to::from(
+ arma::randi>((5 * 5 * 3), 2));
+ SetInputParam>("input", {"test_image777.png",
+ "test_image999.png"});
+ SetInputParam("height", 5);
+ SetInputParam("width", 5);
+ SetInputParam("channels", 3);
+ SetInputParam("save", true);
+ SetInputParam("dataset", testimage);
+ mlpackMain();
+
+ CLI::ClearSettings();
+ CLI::RestoreSettings(testName);
+
+ SetInputParam>("input", {"test_image777.png",
+ "test_image999.png"});
+ SetInputParam("height", 5);
+ SetInputParam("width", 5);
+ SetInputParam("channels", 3);
+
+ mlpackMain();
+ arma::mat output = CLI::GetParam("output");
+ BOOST_REQUIRE_EQUAL(output.n_rows, 5 * 5 * 3);
+ BOOST_REQUIRE_EQUAL(output.n_cols, 2);
+ for (size_t i = 0; i < output.n_elem; ++i)
+ BOOST_REQUIRE_CLOSE(testimage[i], output[i], 1e-5);
+}
+
+/**
+ * Check whether binding throws error if height, width or channel are not
+ * specified.
+ */
+BOOST_AUTO_TEST_CASE(IncompleteTest)
+{
+ arma::mat testimage = arma::conv_to::from(
+ arma::randi>((5 * 5 * 3), 2));
+ SetInputParam>("input", {"test_image777.png",
+ "test_image999.png"});
+ SetInputParam("save", true);
+ SetInputParam("height", 50);
+ SetInputParam("width", 50);
+ SetInputParam("dataset", testimage);
+
+ Log::Fatal.ignoreInput = true;
+ BOOST_REQUIRE_THROW(mlpackMain(), std::runtime_error);
+ Log::Fatal.ignoreInput = false;
+}
+
+/**
+ * Check for invalid height values.
+ */
+BOOST_AUTO_TEST_CASE(InvalidInputTest)
+{
+ arma::mat testimage = arma::conv_to::from(
+ arma::randi>((5 * 5 * 3), 2));
+ SetInputParam>("input", {"test_image777.png",
+ "test_image999.png"});
+ SetInputParam("save", true);
+ SetInputParam("dataset", testimage);
+
+ SetInputParam("height", -50);
+ SetInputParam("width", 50);
+ SetInputParam("channels", 3);
+
+ Log::Fatal.ignoreInput = true;
+ BOOST_REQUIRE_THROW(mlpackMain(), std::runtime_error);
+ Log::Fatal.ignoreInput = false;
+}
+
+/**
+ * Check for invalid width values.
+ */
+BOOST_AUTO_TEST_CASE(InvalidWidthTest)
+{
+ arma::mat testimage = arma::conv_to::from(
+ arma::randi>((5 * 5 * 3), 2));
+ SetInputParam>("input", {"test_image777.png",
+ "test_image999.png"});
+ SetInputParam("save", true);
+ SetInputParam("dataset", testimage);
+ SetInputParam("height", 50);
+ SetInputParam("width", -50);
+ SetInputParam("channels", 3);
+
+ Log::Fatal.ignoreInput = true;
+ BOOST_REQUIRE_THROW(mlpackMain(), std::runtime_error);
+ Log::Fatal.ignoreInput = false;
+}
+
+/**
+ * Check for invalid channel values.
+ */
+BOOST_AUTO_TEST_CASE(InvalidChannelTest)
+{
+ arma::mat testimage = arma::conv_to::from(
+ arma::randi>((5 * 5 * 3), 2));
+ SetInputParam>("input", {"test_image777.png",
+ "test_image999.png"});
+ SetInputParam("save", true);
+ SetInputParam("dataset", testimage);
+ SetInputParam("height", 50);
+ SetInputParam("width", 50);
+ SetInputParam("channels", -1);
+
+ Log::Fatal.ignoreInput = true;
+ BOOST_REQUIRE_THROW(mlpackMain(), std::runtime_error);
+ Log::Fatal.ignoreInput = false;
+}
+
+/**
+ * Check for invalid input values.
+ */
+BOOST_AUTO_TEST_CASE(EmptyInputTest)
+{
+ SetInputParam>("input", {});
+ SetInputParam("height", 50);
+ SetInputParam("width", 50);
+ SetInputParam("channels", 50);
+
+ Log::Fatal.ignoreInput = true;
+ BOOST_REQUIRE_THROW(mlpackMain(), std::runtime_error);
+ Log::Fatal.ignoreInput = false;
+}
+
+BOOST_AUTO_TEST_SUITE_END();
diff --git a/src/mlpack/tests/q_learning_test.cpp b/src/mlpack/tests/q_learning_test.cpp
index 95a26f40ad..67a62d651d 100644
--- a/src/mlpack/tests/q_learning_test.cpp
+++ b/src/mlpack/tests/q_learning_test.cpp
@@ -18,6 +18,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -41,13 +42,7 @@ BOOST_AUTO_TEST_SUITE(QLearningTest);
BOOST_AUTO_TEST_CASE(CartPoleWithDQN)
{
// Set up the network.
- FFN, GaussianInitialization> model(MeanSquaredError<>(),
- GaussianInitialization(0, 0.001));
- model.Add>(4, 128);
- model.Add>();
- model.Add>(128, 128);
- model.Add>();
- model.Add>(128, 2);
+ SimpleDQN<> model(4, 128, 128, 2);
// Set up the policy and replay method.
GreedyPolicy policy(1.0, 1000, 0.1, 0.99);
@@ -107,13 +102,7 @@ BOOST_AUTO_TEST_CASE(CartPoleWithDQN)
BOOST_AUTO_TEST_CASE(CartPoleWithDQNPrioritizedReplay)
{
// Set up the network.
- FFN, GaussianInitialization> model(MeanSquaredError<>(),
- GaussianInitialization(0, 0.001));
- model.Add>(4, 128);
- model.Add>();
- model.Add>(128, 128);
- model.Add