Merge branch 'master' into master

This commit is contained in:
Marcus Edel
2018-11-13 21:00:06 +01:00
committed by GitHub
34 changed files with 7611 additions and 7673 deletions
-48
View File
@@ -1,48 +0,0 @@
# This is cloned from
# https://github.com/nitroshare/CXX11-CMake-Macros
# until C++11 support finally hits CMake stable (should be 3.1, I think).
# Copyright (c) 2013 Nathan Osman
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
# Determines whether or not the compiler supports C++11
macro(check_for_cxx11_compiler _VAR)
message(STATUS "Checking for C++11 compiler")
set(${_VAR})
if((MSVC AND (MSVC14)) OR
(CMAKE_COMPILER_IS_GNUCXX AND NOT ${CMAKE_CXX_COMPILER_VERSION} VERSION_LESS 4.6) OR
(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND NOT ${CMAKE_CXX_COMPILER_VERSION} VERSION_LESS 3.1) OR
(CMAKE_CXX_COMPILER_ID STREQUAL "Intel" AND NOT ${CMAKE_CXX_COMPILER_VERSION} VERSION_LESS 12.0))
set(${_VAR} 1)
message(STATUS "Checking for C++11 compiler - available")
else()
message(STATUS "Checking for C++11 compiler - unavailable")
endif()
endmacro()
# Sets the appropriate flag to enable C++11 support
macro(enable_cxx11)
if(CMAKE_COMPILER_IS_GNUCXX OR
CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR
CMAKE_CXX_COMPILER_ID STREQUAL "Intel")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
endif()
endmacro()
+2 -2
View File
@@ -20,7 +20,7 @@ function(find_python_module module)
endif ()
# A module's location is usually a directory, but for binary modules
# it's a .so file.
execute_process(COMMAND "${PYTHON}" "-c"
execute_process(COMMAND "${PYTHON_EXECUTABLE}" "-c"
"import re, ${module}; print(re.compile('/__init__.py.*').sub('',${module}.__file__))"
RESULT_VARIABLE _${module}_status
OUTPUT_VARIABLE _${module}_location
@@ -28,7 +28,7 @@ function(find_python_module module)
if (NOT _${module}_status)
# Now we have to check the version.
if (VERSION_REQ)
execute_process(COMMAND "${PYTHON}" "-c"
execute_process(COMMAND "${PYTHON_EXECUTABLE}" "-c"
"import ${module}; from distutils.version import StrictVersion; print(StrictVersion(${module}.__version__) >= StrictVersion('${VERSION_REQ}'));"
RESULT_VARIABLE _version_status
OUTPUT_VARIABLE _version_compare
+16 -32
View File
@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 2.8.10)
cmake_minimum_required(VERSION 3.3.2)
project(mlpack C CXX)
include(CMake/cotire.cmake)
@@ -12,7 +12,16 @@ option(MATLAB_BINDINGS "Compile MATLAB bindings if MATLAB is found." OFF)
option(TEST_VERBOSE "Run test cases with verbose output." OFF)
option(BUILD_TESTS "Build tests." ON)
option(BUILD_CLI_EXECUTABLES "Build command-line executables." ON)
option(BUILD_PYTHON_BINDINGS "Build Python bindings." ON)
# Currently Python bindings aren't known to build successfully on Windows, so
# set BUILD_PYTHON_BINDINGS to OFF when the platform is Windows.
if (WIN32)
option(BUILD_PYTHON_BINDINGS "Build Python bindings." OFF)
message(WARNING "By default Python bindings are not compiled for Windows because they are not known to work. Set BUILD_PYTHON_BINDINGS to ON if you want them built.")
else ()
option(BUILD_PYTHON_BINDINGS "Build Python bindings." ON)
endif()
option(BUILD_SHARED_LIBS
"Compile shared libraries (if OFF, static libraries are compiled)." ON)
option(BUILD_WITH_COVERAGE
@@ -24,34 +33,9 @@ option(FORCE_CXX11
option(USE_OPENMP "If available, use OpenMP for parallelization." ON)
enable_testing()
# Currently Python bindings aren't known to build successfully on Windows, so
# set BUILD_PYTHON_BINDINGS to OFF when the platform is Windows.
if (WIN32)
option(BUILD_PYTHON_BINDINGS "Build Python bindings." OFF)
message(WARNING "By default Python bindings are not compiled for Windows because they are not known to work. Set BUILD_PYTHON_BINDINGS to ON if you want them built.")
endif()
# Ensure that we have a C++11 compiler. In newer versions of CMake, this is
# done with target_compile_features() when the mlpack library target is added in
# src/mlpack/CMakeLists.txt.
if ((${CMAKE_MAJOR_VERSION} LESS 3 OR
(${CMAKE_MAJOR_VERSION} EQUAL 3 AND ${CMAKE_MINOR_VERSION} LESS 1))
AND NOT FORCE_CXX11)
# Older versions of CMake do not support target_compile_features(), so we have
# to use something kind of hacky.
include(CMake/CXX11.cmake)
check_for_cxx11_compiler(HAS_CXX11)
if(NOT HAS_CXX11)
message(FATAL_ERROR "No C++11 compiler available!")
endif()
enable_cxx11()
else()
# set required standard to c++11
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
endif ()
# Otherwise, we may have to set the C++11 mode after the mlpack target is
# defined.
# Set required standard to c++11
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# Include modules in the CMake directory.
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/CMake")
@@ -462,13 +446,13 @@ add_subdirectory(src/mlpack)
# If we need to keep gitversion.hpp up to date, then make sure the mlpack target
# depends on it.
if (USING_GIT STREQUAL "YES")
add_dependencies(mlpack mlpack_gitversion)
add_dependencies(mlpack_headers mlpack_gitversion)
endif ()
# Make the mlpack_arma_config target depend on mlpack (we couldn't do this
# before the add_subdirectory() call because the mlpack target didn't exist
# before that).
add_dependencies(mlpack mlpack_arma_config)
add_dependencies(mlpack_headers mlpack_arma_config)
# Make a target to generate the documentation. If Doxygen isn't installed, then
# I guess this option will just be unavailable.
+1
View File
@@ -105,6 +105,7 @@ Copyright:
Copyright 2018, Yasmine Dumouchel <yasmine.dumouchel@gmail.com>
Copyright 2018, German Lancioni
Copyright 2018, Ayush Chamoli
Copyright 2018, Tommi Laivamaa <tommi.laivamaa@protonmail.com>
License: BSD-3-clause
All rights reserved.
+6
View File
@@ -1,3 +1,9 @@
### mlpack 3.0.4
###### ????-??-??
* Bump minimum CMake version to 3.3.2.
* CMake fixes for Ninja generator by Marc Espie.
### mlpack 3.0.3
###### 2018-07-27
* Fix Visual Studio compilation issue (#1443).
+3 -3
View File
@@ -46,7 +46,7 @@ Python bindings.
### 1. Introduction
The mlpack website can be found at http://www.mlpack.org and contains numerous
The mlpack website can be found at http://www.mlpack.org and it contains numerous
tutorials and extensive documentation. This README serves as a guide for what
mlpack is, how to install it, how to run it, and where to find more
documentation. The website should be consulted for further information:
@@ -84,13 +84,13 @@ mlpack has the following dependencies:
Armadillo >= 6.500.0
Boost (program_options, math_c99, unit_test_framework, serialization,
spirit)
CMake >= 2.8.5
CMake >= 3.3.2
All of those should be available in your distribution's package manager. If
not, you will have to compile each of them by hand. See the documentation for
each of those packages for more information.
If you would like use or build the mlpack Python bindings, make sure that the
If you would like to use or build the mlpack Python bindings, make sure that the
following Python packages are installed:
setuptools
+2 -1
View File
@@ -85,7 +85,8 @@ foreach(incl_file ${INCLUDE_FILES})
add_custom_command(TARGET mlpack_headers POST_BUILD
COMMAND ${CMAKE_COMMAND} ARGS -E
copy ${CMAKE_CURRENT_SOURCE_DIR}/${incl_file}
${CMAKE_BINARY_DIR}/include/mlpack/${incl_file})
${CMAKE_BINARY_DIR}/include/mlpack/${incl_file}
BYPRODUCTS ${CMAKE_BINARY_DIR}/include/mlpack/${incl_file})
endforeach()
# At install time, we simply install that directory of header files we
+17 -14
View File
@@ -15,11 +15,11 @@ endif ()
# Generate Python setuptools file.
# We can probably use FindPythonInterp when we require CMake 3.0.
find_program(PYTHON "python" REQUIRED)
if (NOT PYTHON)
find_package(PythonInterp)
if (NOT PYTHON_EXECUTABLE)
not_found_return("Python not found; not building Python bindings.")
else ()
message(STATUS "Found Python: ${PYTHON}")
message(STATUS "Found Python: ${PYTHON_EXECUTABLE}")
endif ()
# Import find_python_module.
@@ -116,7 +116,8 @@ endforeach()
add_custom_command(TARGET python_copy PRE_BUILD
COMMAND ${CMAKE_COMMAND} ARGS -E copy
${CMAKE_CURRENT_SOURCE_DIR}/setup.cfg
${CMAKE_BINARY_DIR}/src/mlpack/bindings/python/)
${CMAKE_BINARY_DIR}/src/mlpack/bindings/python/
BYPRODUCTS ${CMAKE_BINARY_DIR}/src/mlpack/bindings/python/mlpack/${cython_file})
add_custom_command(TARGET python_copy PRE_BUILD
COMMAND ${CMAKE_COMMAND} ARGS -E copy
${CMAKE_CURRENT_SOURCE_DIR}/copy_artifacts.py
@@ -127,20 +128,21 @@ if (BUILD_TESTS)
add_custom_command(TARGET python_copy PRE_BUILD
COMMAND ${CMAKE_COMMAND} ARGS -E copy
${CMAKE_CURRENT_SOURCE_DIR}/${test_file}
${CMAKE_BINARY_DIR}/src/mlpack/bindings/python/tests/)
${CMAKE_BINARY_DIR}/src/mlpack/bindings/python/tests/
BYPRODUCTS ${CMAKE_BINARY_DIR}/src/mlpack/bindings/python/tests/${test_file})
endforeach ()
endif ()
# Install any dependencies via setuptools automatically.
add_custom_command(TARGET python_copy POST_BUILD
COMMAND ${CMAKE_COMMAND} -E env NO_BUILD=1 ${PYTHON}
COMMAND ${CMAKE_COMMAND} -E env NO_BUILD=1 ${PYTHON_EXECUTABLE}
${CMAKE_BINARY_DIR}/src/mlpack/bindings/python/setup.py build
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/src/mlpack/bindings/python/)
# Then do the actual build.
add_custom_command(TARGET python POST_BUILD
COMMAND ${PYTHON} ${CMAKE_BINARY_DIR}/src/mlpack/bindings/python/setup.py
build_ext
COMMAND ${PYTHON_EXECUTABLE}
${CMAKE_BINARY_DIR}/src/mlpack/bindings/python/setup.py build_ext
DEPENDS mlpack/arma_numpy.pxd
mlpack/arma_numpy.pyx
mlpack/arma.pxd
@@ -153,19 +155,19 @@ add_custom_command(TARGET python POST_BUILD
# Copy the built artifacts, so that it is also an in-place build.
add_custom_command(TARGET python POST_BUILD
COMMAND ${PYTHON}
COMMAND ${PYTHON_EXECUTABLE}
${CMAKE_BINARY_DIR}/src/mlpack/bindings/python/copy_artifacts.py
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/src/mlpack/bindings/python/)
add_dependencies(python python_copy)
# Configure installation script file.
execute_process(COMMAND ${PYTHON}
execute_process(COMMAND ${PYTHON_EXECUTABLE}
"${CMAKE_CURRENT_SOURCE_DIR}/print_python_version.py" "${CMAKE_INSTALL_PREFIX}"
OUTPUT_VARIABLE NEW_PYTHONPATH)
install(CODE "set(ENV{PYTHONPATH} ${NEW_PYTHONPATH})")
install(CODE "execute_process(COMMAND mkdir -p $ENV{DESTDIR}${NEW_PYTHONPATH})")
install(CODE "execute_process(COMMAND ${PYTHON}
install(CODE "execute_process(COMMAND ${PYTHON_EXECUTABLE}
\"${CMAKE_BINARY_DIR}/src/mlpack/bindings/python/setup.py\" install
--prefix=${CMAKE_INSTALL_PREFIX} --root=$ENV{DESTDIR}
WORKING_DIRECTORY \"${CMAKE_BINARY_DIR}/src/mlpack/bindings/python/\")")
@@ -205,7 +207,8 @@ if (BUILD_PYTHON_BINDINGS)
# enforce it here. Although this will always be rebuilt, that's okay because
# distutils will determine whether or not it *actually* needs to be rebuilt.
add_custom_target(build_pyx_${name}
${PYTHON} ${CMAKE_BINARY_DIR}/src/mlpack/bindings/python/setup.py
${PYTHON_EXECUTABLE}
${CMAKE_BINARY_DIR}/src/mlpack/bindings/python/setup.py
build_ext --module=${name}.pyx
DEPENDS generate_pyx_${name}
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/src/mlpack/bindings/python/
@@ -225,8 +228,8 @@ endmacro ()
# Add a test.
if (BUILD_PYTHON_BINDINGS)
add_test(NAME python_bindings_test
COMMAND ${PYTHON} ${CMAKE_BINARY_DIR}/src/mlpack/bindings/python/setup.py
test
COMMAND ${PYTHON_EXECUTABLE}
${CMAKE_BINARY_DIR}/src/mlpack/bindings/python/setup.py test
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/src/mlpack/bindings/python/)
set_tests_properties(python_bindings_test
PROPERTIES ENVIRONMENT "NO_BUILD=1;LD_LIBRARY_PATH=$ENV{LD_LIBRARY_PATH}:${CMAKE_BINARY_DIR}/lib/")
+2
View File
@@ -250,6 +250,7 @@
* - Shashank Shekhar <contactshashankshekhar@gmail.com>
* - Yasmine Dumouchel <yasmine.dumouchel@gmail.com>
* - German Lancioni
* - Tommi Laivamaa <tommi.laivamaa@protonmail.com>
*/
// First, include all of the prerequisites.
@@ -293,6 +294,7 @@
#include <mlpack/core/kernels/pspectrum_string_kernel.hpp>
#include <mlpack/core/kernels/spherical_kernel.hpp>
#include <mlpack/core/kernels/triangular_kernel.hpp>
#include <mlpack/core/kernels/cauchy_kernel.hpp>
// Use OpenMP if compiled with -DHAS_OPENMP.
#ifdef HAS_OPENMP
+1
View File
@@ -1,6 +1,7 @@
# Define the files we need to compile.
# Anything not in this list will not be compiled into mlpack.
set(SOURCES
cauchy_kernel.hpp
cosine_distance.hpp
cosine_distance_impl.hpp
epanechnikov_kernel.hpp
+98
View File
@@ -0,0 +1,98 @@
/**
* @file cauchy_kernel.hpp
* @author Tommi Laivamaa
*
* Implementation of the Cauchy kernel (CauchyKernel),
*
* 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_KERNELS_CAUCHY_KERNEL_HPP
#define MLPACK_CORE_KERNELS_CAUCHY_KERNEL_HPP
#include <mlpack/prereqs.hpp>
#include <mlpack/core/metrics/lmetric.hpp>
#include <mlpack/core/kernels/kernel_traits.hpp>
namespace mlpack {
namespace kernel {
/**
* The Cauchy kernel. Given two vector @f$ x @f$, @f$ y @f$, and a bandwidth
* @f$ \sigma @f$ (set in the constructor),
*
* @f[
* K(x, y) = \frac{1}{1 + (\frac{|| x - y ||}{\sigma})^2}.
* @f]
*
* For more details, see the following published paper:
*
* @code
* @inproceedings{Basak2008,
* title={A least square kernel machine with box constraints},
* author={Basak, Jayanta},
* booktitle={Pattern Recognition, 2008. ICPR 2008. 19th International
* Conference on},
* pages={1--4},
* year={2008},
* organization={IEEE}
* }
* @endcode
*/
class CauchyKernel
{
public:
/**
* Construct the Cauchy kernel; by default, the bandwidth is 1.0.
*/
CauchyKernel(double bandwidth = 1.0) : bandwidth(bandwidth)
{ }
/**
* Evaluation of the Cauchy kernel. This could be generalized to use any
* distance metric, not the Euclidean distance, but for now, the Euclidean
* distance is used.
*
* @tparam VecTypeA Type of first vector (arma::vec, arma::sp_vec).
* @tparam VecTypeB Type of second vector (arma::vec, arma::sp_vec).
* @param a First vector.
* @param b Second vector.
* @return K(a, b).
*/
template<typename VecTypeA, typename VecTypeB>
double Evaluate(const VecTypeA& a, const VecTypeB& b)
{
return 1 / (1 + (
std::pow(metric::EuclideanDistance::Evaluate(a, b) / bandwidth, 2)));
}
/**
* Serialize the kernel.
*/
template<typename Archive>
void serialize(Archive& ar, const unsigned int /* version */)
{
ar & BOOST_SERIALIZATION_NVP(bandwidth);
}
private:
//! Kernel bandwidth.
double bandwidth;
};
//! Kernel traits for the Cauchy kernel.
template<>
class KernelTraits<CauchyKernel>
{
public:
//! The Cauchy kernel is normalized: K(x, x) = 1 for all x.
static const bool IsNormalized = true;
};
} // namespace kernel
} // namespace mlpack
#endif
@@ -25,7 +25,7 @@ SplitNode(const BoundType& bound, MatType& data, const size_t begin,
const size_t count, SplitInfo& splitInfo)
{
ElemType mu = 0;
size_t vantagePointIndex;
size_t vantagePointIndex = 0;
// Find the best vantage point.
SelectVantagePoint(bound.Metric(), data, begin, count, vantagePointIndex, mu);
@@ -1,5 +1,3 @@
cmake_minimum_required(VERSION 2.8)
# Define the files we need to compile.
# Anything not in this list will not be compiled into mlpack.
set(SOURCES
+19
View File
@@ -28,6 +28,7 @@
#include "init_rules/network_init.hpp"
#include <mlpack/methods/ann/layer/layer_types.hpp>
#include <mlpack/methods/ann/layer/layer.hpp>
#include <mlpack/methods/ann/init_rules/random_init.hpp>
#include <mlpack/core/optimizers/rmsprop/rmsprop.hpp>
@@ -462,6 +463,24 @@ class FFN
} // namespace ann
} // namespace mlpack
//! Set the serialization version of the FFN class. Multiple template arguments
//! makes this ugly...
namespace boost {
namespace serialization {
template<typename OutputLayerType,
typename InitializationRuleType,
typename... CustomLayer>
struct version<
mlpack::ann::FFN<OutputLayerType, InitializationRuleType, CustomLayer...>>
{
BOOST_STATIC_CONSTANT(int, value = 1);
};
} // namespace serialization
} // namespace boost
// Include implementation.
#include "ffn_impl.hpp"
+12 -2
View File
@@ -495,13 +495,20 @@ template<typename OutputLayerType, typename InitializationRuleType,
typename... CustomLayers>
template<typename Archive>
void FFN<OutputLayerType, InitializationRuleType, CustomLayers...>::serialize(
Archive& ar, const unsigned int /* version */)
Archive& ar, const unsigned int version)
{
ar & BOOST_SERIALIZATION_NVP(parameter);
ar & BOOST_SERIALIZATION_NVP(width);
ar & BOOST_SERIALIZATION_NVP(height);
ar & BOOST_SERIALIZATION_NVP(currentInput);
// Earlier versions of the FFN code did not serialize whether or not the model
// was reset.
if (version > 0)
{
ar & BOOST_SERIALIZATION_NVP(reset);
}
// Be sure to clear other layers before loading.
if (Archive::is_loading::value)
{
@@ -515,7 +522,10 @@ void FFN<OutputLayerType, InitializationRuleType, CustomLayers...>::serialize(
// If we are loading, we need to initialize the weights.
if (Archive::is_loading::value)
{
reset = false;
// The behavior in earlier versions was to always assume the weights needed
// to be reset.
if (version == 0)
reset = false;
size_t offset = 0;
for (size_t i = 0; i < network.size(); ++i)
+18
View File
@@ -22,6 +22,7 @@
#include "init_rules/network_init.hpp"
#include <mlpack/methods/ann/layer/layer_types.hpp>
#include <mlpack/methods/ann/layer/layer.hpp>
#include <mlpack/methods/ann/init_rules/random_init.hpp>
#include <mlpack/core/optimizers/sgd/sgd.hpp>
@@ -385,6 +386,23 @@ class RNN
} // namespace ann
} // namespace mlpack
//! Set the serialization version of the RNN class. Multiple template arguments
//! makes this ugly...
namespace boost {
namespace serialization {
template<typename OutputLayerType,
typename InitializationRuleType,
typename... CustomLayer>
struct version<
mlpack::ann::RNN<OutputLayerType, InitializationRuleType, CustomLayer...>>
{
BOOST_STATIC_CONSTANT(int, value = 1);
};
} // namespace serialization
} // namespace boost
// Include implementation.
#include "rnn_impl.hpp"
+11 -2
View File
@@ -504,7 +504,7 @@ template<typename OutputLayerType, typename InitializationRuleType,
typename... CustomLayers>
template<typename Archive>
void RNN<OutputLayerType, InitializationRuleType, CustomLayers...>::serialize(
Archive& ar, const unsigned int /* version */)
Archive& ar, const unsigned int version)
{
ar & BOOST_SERIALIZATION_NVP(parameter);
ar & BOOST_SERIALIZATION_NVP(rho);
@@ -513,6 +513,12 @@ void RNN<OutputLayerType, InitializationRuleType, CustomLayers...>::serialize(
ar & BOOST_SERIALIZATION_NVP(outputSize);
ar & BOOST_SERIALIZATION_NVP(targetSize);
// Earlier versions of the RNN code did not serialize the 'reset' variable.
if (version > 0)
{
ar & BOOST_SERIALIZATION_NVP(reset);
}
if (Archive::is_loading::value)
{
std::for_each(network.begin(), network.end(),
@@ -525,7 +531,10 @@ void RNN<OutputLayerType, InitializationRuleType, CustomLayers...>::serialize(
// If we are loading, we need to initialize the weights.
if (Archive::is_loading::value)
{
reset = false;
// Earlier versions of the RNN code assumed that the weights needed to be
// reset on load.
if (version == 0)
reset = false;
size_t offset = 0;
for (LayerTypes<CustomLayers...>& layer : network)
+3
View File
@@ -179,6 +179,9 @@ class CFType
//! Get the cleaned data matrix.
const arma::sp_mat& CleanedData() const { return cleanedData; }
//! Get the normalization object.
const NormalizationType& Normalization() const { return normalization; }
/**
* Generates the given number of recommendations for all users.
*
@@ -93,7 +93,7 @@ class CombinedNormalization
/**
* Return normalizations tuple.
*/
TupleType Normalizations() const
const TupleType& Normalizations() const
{
return normalizations;
}
@@ -1,5 +1,3 @@
cmake_minimum_required(VERSION 2.8)
# Define the files we need to compile.
# Anything not in this list will not be compiled into mlpack.
set(SOURCES
@@ -1,5 +1,3 @@
cmake_minimum_required(VERSION 2.8)
# Define the files we need to compile.
# Anything not in this list will not be compiled into mlpack.
set(SOURCES
@@ -56,6 +56,8 @@ class DecisionTree :
* minimumGainSplit too small may cause the tree to overfit, but setting them
* too large may cause it to underfit.
*
* Use std::move if data or labels are no longer needed to avoid copies.
*
* @param data Dataset to train on.
* @param datasetInfo Type information for each dimension of the dataset.
* @param labels Labels for each training point.
@@ -64,9 +66,9 @@ class DecisionTree :
* @param minimumGainSplit Minimum gain for the node to split.
*/
template<typename MatType, typename LabelsType>
DecisionTree(MatType&& data,
DecisionTree(MatType data,
const data::DatasetInfo& datasetInfo,
LabelsType&& labels,
LabelsType labels,
const size_t numClasses,
const size_t minimumLeafSize = 10,
const double minimumGainSplit = 1e-7);
@@ -77,6 +79,8 @@ class DecisionTree :
* minimumGainSplit too small may cause the tree to overfit, but setting them
* too large may cause it to underfit.
*
* Use std::move if data or labels are no longer needed to avoid copies.
*
* @param data Dataset to train on.
* @param labels Labels for each training point.
* @param numClasses Number of classes in the dataset.
@@ -84,8 +88,8 @@ class DecisionTree :
* @param minimumGainSplit Minimum gain for the node to split.
*/
template<typename MatType, typename LabelsType>
DecisionTree(MatType&& data,
LabelsType&& labels,
DecisionTree(MatType data,
LabelsType labels,
const size_t numClasses,
const size_t minimumLeafSize = 10,
const double minimumGainSplit = 1e-7);
@@ -96,6 +100,9 @@ class DecisionTree :
* and minimumGainSplit too small may cause the tree to overfit, but setting
* them too large may cause it to underfit.
*
* Use std::move if data, labels or weights are no longer needed to avoid
* copies.
*
* @param data Dataset to train on.
* @param datasetInfo Type information for each dimension of the dataset.
* @param labels Labels for each training point.
@@ -105,11 +112,11 @@ class DecisionTree :
* @param minimumGainSplit Minimum gain for the node to split.
*/
template<typename MatType, typename LabelsType, typename WeightsType>
DecisionTree(MatType&& data,
DecisionTree(MatType data,
const data::DatasetInfo& datasetInfo,
LabelsType&& labels,
LabelsType labels,
const size_t numClasses,
WeightsType&& weights,
WeightsType weights,
const size_t minimumLeafSize = 10,
const double minimumGainSplit = 1e-7,
const std::enable_if_t<arma::is_arma_type<
@@ -122,6 +129,9 @@ class DecisionTree :
* and minimumGainSplit too small may cause the tree to overfit, but setting
* them too large may cause it to underfit.
*
* Use std::move if data, labels or weights are no longer needed to avoid
* copies.
*
* @param data Dataset to train on.
* @param labels Labels for each training point.
* @param numClasses Number of classes in the dataset.
@@ -130,10 +140,10 @@ class DecisionTree :
* @param minimumGainSplit Minimum gain for the node to split.
*/
template<typename MatType, typename LabelsType, typename WeightsType>
DecisionTree(MatType&& data,
LabelsType&& labels,
DecisionTree(MatType data,
LabelsType labels,
const size_t numClasses,
WeightsType&& weights,
WeightsType weights,
const size_t minimumLeafSize = 10,
const double minimumGainSplit = 1e-7,
const std::enable_if_t<arma::is_arma_type<
@@ -191,6 +201,8 @@ class DecisionTree :
* minimumGainSplit too small may cause the tree to overfit, but setting them
* too large may cause it to underfit.
*
* Use std::move if data or labels are no longer needed to avoid copies.
*
* @param data Dataset to train on.
* @param datasetInfo Type information for each dimension.
* @param labels Labels for each training point.
@@ -200,9 +212,9 @@ class DecisionTree :
* @param minimumGainSplit Minimum gain for the node to split.
*/
template<typename MatType, typename LabelsType>
void Train(MatType&& data,
void Train(MatType data,
const data::DatasetInfo& datasetInfo,
LabelsType&& labels,
LabelsType labels,
const size_t numClasses,
const size_t minimumLeafSize = 10,
const double minimumGainSplit = 1e-7);
@@ -213,6 +225,8 @@ class DecisionTree :
* minimumGainSplit too small may cause the tree to overfit, but setting them
* too large may cause it to underfit.
*
* Use std::move if data or labels are no longer needed to avoid copies.
*
* @param data Dataset to train on.
* @param labels Labels for each training point.
* @param numClasses Number of classes in the dataset.
@@ -221,8 +235,8 @@ class DecisionTree :
* @param minimumGainSplit Minimum gain for the node to split.
*/
template<typename MatType, typename LabelsType>
void Train(MatType&& data,
LabelsType&& labels,
void Train(MatType data,
LabelsType labels,
const size_t numClasses,
const size_t minimumLeafSize = 10,
const double minimumGainSplit = 1e-7);
@@ -234,6 +248,9 @@ class DecisionTree :
* minimumGainSplit too small may cause the tree to overfit, but setting them
* too large may cause it to underfit.
*
* Use std::move if data, labels or weights are no longer needed to avoid
* copies.
*
* @param data Dataset to train on.
* @param datasetInfo Type information for each dimension.
* @param labels Labels for each training point.
@@ -243,11 +260,11 @@ class DecisionTree :
* @param minimumGainSplit Minimum gain for the node to split.
*/
template<typename MatType, typename LabelsType, typename WeightsType>
void Train(MatType&& data,
void Train(MatType data,
const data::DatasetInfo& datasetInfo,
LabelsType&& labels,
LabelsType labels,
const size_t numClasses,
WeightsType&& weights,
WeightsType weights,
const size_t minimumLeafSize = 10,
const double minimumGainSplit = 1e-7,
const std::enable_if_t<arma::is_arma_type<typename
@@ -259,6 +276,9 @@ class DecisionTree :
* minimumLeafSize and minimumGainSplit too small may cause the tree to
* overfit, but setting them too large may cause it to underfit.
*
* Use std::move if data, labels or weights are no longer needed to avoid
* copies.
*
* @param data Dataset to train on.
* @param labels Labels for each training point.
* @param numClasses Number of classes in the dataset.
@@ -267,10 +287,10 @@ class DecisionTree :
* @param minimumGainSplit Minimum gain for the node to split.
*/
template<typename MatType, typename LabelsType, typename WeightsType>
void Train(MatType&& data,
LabelsType&& labels,
void Train(MatType data,
LabelsType labels,
const size_t numClasses,
WeightsType&& weights,
WeightsType weights,
const size_t minimumLeafSize = 10,
const double minimumGainSplit = 1e-7,
const std::enable_if_t<arma::is_arma_type<typename
@@ -28,9 +28,9 @@ DecisionTree<FitnessFunction,
CategoricalSplitType,
DimensionSelectionType,
ElemType,
NoRecursion>::DecisionTree(MatType&& data,
NoRecursion>::DecisionTree(MatType data,
const data::DatasetInfo& datasetInfo,
LabelsType&& labels,
LabelsType labels,
const size_t numClasses,
const size_t minimumLeafSize,
const double minimumGainSplit)
@@ -39,8 +39,8 @@ DecisionTree<FitnessFunction,
using TrueLabelsType = typename std::decay<LabelsType>::type;
// Copy or move data.
TrueMatType tmpData(std::forward<MatType>(data));
TrueLabelsType tmpLabels(std::forward<LabelsType>(labels));
TrueMatType tmpData(std::move(data));
TrueLabelsType tmpLabels(std::move(labels));
// Pass off work to the Train() method.
arma::rowvec weights; // Fake weights, not used.
@@ -61,8 +61,8 @@ DecisionTree<FitnessFunction,
CategoricalSplitType,
DimensionSelectionType,
ElemType,
NoRecursion>::DecisionTree(MatType&& data,
LabelsType&& labels,
NoRecursion>::DecisionTree(MatType data,
LabelsType labels,
const size_t numClasses,
const size_t minimumLeafSize,
const double minimumGainSplit)
@@ -71,8 +71,8 @@ DecisionTree<FitnessFunction,
using TrueLabelsType = typename std::decay<LabelsType>::type;
// Copy or move data.
TrueMatType tmpData(std::forward<MatType>(data));
TrueLabelsType tmpLabels(std::forward<LabelsType>(labels));
TrueMatType tmpData(std::move(data));
TrueLabelsType tmpLabels(std::move(labels));
// Pass off work to the Train() method.
arma::rowvec weights; // Fake weights, not used.
@@ -93,11 +93,11 @@ DecisionTree<FitnessFunction,
CategoricalSplitType,
DimensionSelectionType,
ElemType,
NoRecursion>::DecisionTree(MatType&& data,
NoRecursion>::DecisionTree(MatType data,
const data::DatasetInfo& datasetInfo,
LabelsType&& labels,
LabelsType labels,
const size_t numClasses,
WeightsType&& weights,
WeightsType weights,
const size_t minimumLeafSize,
const double minimumGainSplit,
const std::enable_if_t<
@@ -110,9 +110,9 @@ DecisionTree<FitnessFunction,
using TrueWeightsType = typename std::decay<WeightsType>::type;
// Copy or move data.
TrueMatType tmpData(std::forward<MatType>(data));
TrueLabelsType tmpLabels(std::forward<LabelsType>(labels));
TrueWeightsType tmpWeights(std::forward<WeightsType>(weights));
TrueMatType tmpData(std::move(data));
TrueLabelsType tmpLabels(std::move(labels));
TrueWeightsType tmpWeights(std::move(weights));
// Pass off work to the weighted Train() method.
Train<true>(tmpData, 0, tmpData.n_cols, datasetInfo, tmpLabels, numClasses,
@@ -132,10 +132,10 @@ DecisionTree<FitnessFunction,
CategoricalSplitType,
DimensionSelectionType,
ElemType,
NoRecursion>::DecisionTree(MatType&& data,
LabelsType&& labels,
NoRecursion>::DecisionTree(MatType data,
LabelsType labels,
const size_t numClasses,
WeightsType&& weights,
WeightsType weights,
const size_t minimumLeafSize,
const double minimumGainSplit,
const std::enable_if_t<
@@ -148,9 +148,9 @@ DecisionTree<FitnessFunction,
using TrueWeightsType = typename std::decay<WeightsType>::type;
// Copy or move data.
TrueMatType tmpData(std::forward<MatType>(data));
TrueLabelsType tmpLabels(std::forward<LabelsType>(labels));
TrueWeightsType tmpWeights(std::forward<WeightsType>(weights));
TrueMatType tmpData(std::move(data));
TrueLabelsType tmpLabels(std::move(labels));
TrueWeightsType tmpWeights(std::move(weights));
// Pass off work to the weighted Train() method.
Train<true>(tmpData, 0, tmpData.n_cols, tmpLabels, numClasses, tmpWeights,
@@ -345,9 +345,9 @@ void DecisionTree<FitnessFunction,
CategoricalSplitType,
DimensionSelectionType,
ElemType,
NoRecursion>::Train(MatType&& data,
NoRecursion>::Train(MatType data,
const data::DatasetInfo& datasetInfo,
LabelsType&& labels,
LabelsType labels,
const size_t numClasses,
const size_t minimumLeafSize,
const double minimumGainSplit)
@@ -366,8 +366,8 @@ void DecisionTree<FitnessFunction,
using TrueLabelsType = typename std::decay<LabelsType>::type;
// Copy or move data.
TrueMatType tmpData(std::forward<MatType>(data));
TrueLabelsType tmpLabels(std::forward<LabelsType>(labels));
TrueMatType tmpData(std::move(data));
TrueLabelsType tmpLabels(std::move(labels));
// Pass off work to the Train() method.
arma::rowvec weights; // Fake weights, not used.
@@ -388,8 +388,8 @@ void DecisionTree<FitnessFunction,
CategoricalSplitType,
DimensionSelectionType,
ElemType,
NoRecursion>::Train(MatType&& data,
LabelsType&& labels,
NoRecursion>::Train(MatType data,
LabelsType labels,
const size_t numClasses,
const size_t minimumLeafSize,
const double minimumGainSplit)
@@ -408,8 +408,8 @@ void DecisionTree<FitnessFunction,
using TrueLabelsType = typename std::decay<LabelsType>::type;
// Copy or move data.
TrueMatType tmpData(std::forward<MatType>(data));
TrueLabelsType tmpLabels(std::forward<LabelsType>(labels));
TrueMatType tmpData(std::move(data));
TrueLabelsType tmpLabels(std::move(labels));
// Pass off work to the Train() method.
arma::rowvec weights; // Fake weights, not used.
@@ -430,11 +430,11 @@ void DecisionTree<FitnessFunction,
CategoricalSplitType,
DimensionSelectionType,
ElemType,
NoRecursion>::Train(MatType&& data,
NoRecursion>::Train(MatType data,
const data::DatasetInfo& datasetInfo,
LabelsType&& labels,
LabelsType labels,
const size_t numClasses,
WeightsType&& weights,
WeightsType weights,
const size_t minimumLeafSize,
const double minimumGainSplit,
const std::enable_if_t<arma::is_arma_type<
@@ -456,9 +456,9 @@ void DecisionTree<FitnessFunction,
using TrueWeightsType = typename std::decay<WeightsType>::type;
// Copy or move data.
TrueMatType tmpData(std::forward<MatType>(data));
TrueLabelsType tmpLabels(std::forward<LabelsType>(labels));
TrueWeightsType tmpWeights(std::forward<WeightsType>(weights));
TrueMatType tmpData(std::move(data));
TrueLabelsType tmpLabels(std::move(labels));
TrueWeightsType tmpWeights(std::move(weights));
// Pass off work to the Train() method.
Train<true>(tmpData, 0, tmpData.n_cols, datasetInfo, tmpLabels, numClasses,
@@ -478,10 +478,10 @@ void DecisionTree<FitnessFunction,
CategoricalSplitType,
DimensionSelectionType,
ElemType,
NoRecursion>::Train(MatType&& data,
LabelsType&& labels,
NoRecursion>::Train(MatType data,
LabelsType labels,
const size_t numClasses,
WeightsType&& weights,
WeightsType weights,
const size_t minimumLeafSize,
const double minimumGainSplit,
const std::enable_if_t<arma::is_arma_type<
@@ -503,9 +503,9 @@ void DecisionTree<FitnessFunction,
using TrueWeightsType = typename std::decay<WeightsType>::type;
// Copy or move data.
TrueMatType tmpData(std::forward<MatType>(data));
TrueLabelsType tmpLabels(std::forward<LabelsType>(labels));
TrueWeightsType tmpWeights(std::forward<WeightsType>(weights));
TrueMatType tmpData(std::move(data));
TrueLabelsType tmpLabels(std::move(labels));
TrueWeightsType tmpWeights(std::move(weights));
// Pass off work to the Train() method.
Train<true>(tmpData, 0, tmpData.n_cols, tmpLabels, numClasses, tmpWeights,
@@ -180,13 +180,30 @@ static void mlpackMain()
{
arma::Row<double> weights =
std::move(CLI::GetParam<arma::Mat<double>>("weights"));
model->tree = DecisionTree<>(trainingSet, model->info, labels,
numClasses, weights, minLeafSize, minimumGainSplit);
if (CLI::HasParam("print_training_error"))
{
model->tree = DecisionTree<>(trainingSet, model->info, labels,
numClasses, std::move(weights), minLeafSize, minimumGainSplit);
}
else
{
model->tree = DecisionTree<>(std::move(trainingSet), model->info,
std::move(labels), numClasses, std::move(weights), minLeafSize,
minimumGainSplit);
}
}
else
{
model->tree = DecisionTree<>(trainingSet, model->info, labels,
numClasses, minLeafSize, minimumGainSplit);
if (CLI::HasParam("print_training_error"))
{
model->tree = DecisionTree<>(trainingSet, model->info, labels,
numClasses, minLeafSize, minimumGainSplit);
}
else
{
model->tree = DecisionTree<>(std::move(trainingSet), model->info,
std::move(labels), numClasses, minLeafSize, minimumGainSplit);
}
}
// Do we need to print training error?
@@ -68,7 +68,7 @@ EstimateRadius(const MatType& data, double ratio)
arma::rowvec maxDistances = max(distances);
// Calculate and return the radius.
return sum(maxDistances) / (double) data.n_cols;
return arma::sum(maxDistances) / (double) data.n_cols;
}
// Class to compare two vectors.
@@ -218,14 +218,14 @@ inline void MeanShift<UseKernel, KernelType, MatType>::Cluster(
// Initial centroid is the seed itself.
allCentroids.col(i) = pSeeds->unsafe_col(i);
for (size_t completedIterations = 0; completedIterations < maxIterations
|| forceConvergence; completedIterations++)
|| forceConvergence; completedIterations++)
{
// Store new centroid in this.
arma::colvec newCentroid = arma::zeros<arma::colvec>(pSeeds->n_rows);
rangeSearcher.Search(allCentroids.unsafe_col(i), validRadius,
neighbors, distances);
if (neighbors[0].size() <= 1)
if (neighbors[0].size() == 0) // There are no points in the cluster.
break;
// Calculate new centroid.
@@ -265,8 +265,9 @@ inline void MeanShift<UseKernel, KernelType, MatType>::Cluster(
// forcing convergence, take 1 random centroid calculated.
if (centroids.empty())
{
Log::Warn << "No clusters converge, setting 1 random centroid calculated. "
"Try a larger max_iterations or pass force_convergence flag." << std::endl;
Log::Warn << "No clusters converged; setting 1 random centroid calculated. "
<< "Try increasing the maximum number of iterations or setting the "
<< "option to force convergence." << std::endl;
if (maxIterations == 0)
{
@@ -187,42 +187,25 @@ class NeighborSearch
/**
* Set the reference set to a new reference set, and build a tree if
* necessary. This method is called 'Train()' in order to match the rest of
* the mlpack abstractions, even though calling this "training" is maybe a bit
* of a stretch.
* necessary. The dataset is copied by default, but the copy can be avoided by
* transferring the ownership of the dataset using std::move(). This method
* is called 'Train()' in order to match the rest of the mlpack abstractions,
* even though calling this "training" is maybe a bit of a stretch.
*
* @param referenceSet New set of reference data.
*/
void Train(const MatType& referenceSet);
void Train(MatType referenceSet);
/**
* Set the reference set to a new reference set, taking ownership of the set,
* and build a tree if necessary. This method is called 'Train()' in order to
* match the rest of the mlpack abstractions, even though calling this
* "training" is maybe a bit of a stretch.
*
* @param referenceSet New set of reference data.
*/
void Train(MatType&& referenceSet);
/**
* Set the reference tree as a copy of the given reference tree.
*
* This method will copy the given tree. You can avoid this copy by using the
* Train() method that takes a rvalue reference to the tree.
* Set the reference tree to a new reference tree. The tree is copied by
* default, but the copy can be avoided by using std::move() to transfer the
* ownership of the tree. This method is called 'Train()' in order to match
* the rest of the mlpack abstractions, even though calling this "training" is
* maybe a bit of a stretch.
*
* @param referenceTree Pre-built tree for reference points.
*/
void Train(const Tree& referenceTree);
/**
* Set the reference tree to a new reference tree.
*
* This method will take ownership of the given tree.
*
* @param referenceTree Pre-built tree for reference points.
*/
void Train(Tree&& referenceTree);
void Train(Tree referenceTree);
/**
* For each point in the query set, compute the nearest neighbors and store
@@ -359,11 +342,6 @@ class NeighborSearch
//! Reference dataset. In some situations we may be the owner of this.
const MatType* referenceSet;
//! If true, this object created the trees and is responsible for them.
bool treeOwner;
//! If true, we own the reference set.
bool setOwner;
//! Indicates the neighbor search mode.
NeighborSearchMode searchMode;
//! Indicates the relative error to be considered in approximate search.
@@ -63,8 +63,6 @@ SingleTreeTraversalType>::NeighborSearch(MatType referenceSetIn,
BuildTree<Tree>(std::move(referenceSetIn), oldFromNewReferences)),
referenceSet(mode == NAIVE_MODE ? new MatType(std::move(referenceSetIn)) :
&referenceTree->Dataset()),
treeOwner(mode != NAIVE_MODE),
setOwner(mode == NAIVE_MODE),
searchMode(mode),
epsilon(epsilon),
metric(metric),
@@ -92,8 +90,6 @@ SingleTreeTraversalType>::NeighborSearch(Tree referenceTree,
const MetricType metric) :
referenceTree(new Tree(std::move(referenceTree))),
referenceSet(&this->referenceTree->Dataset()),
treeOwner(true),
setOwner(false),
searchMode(mode),
epsilon(epsilon),
metric(metric),
@@ -120,8 +116,6 @@ SingleTreeTraversalType>::NeighborSearch(const NeighborSearchMode mode,
const MetricType metric) :
referenceTree(NULL),
referenceSet(new MatType()), // Empty matrix.
treeOwner(false),
setOwner(true),
searchMode(mode),
epsilon(epsilon),
metric(metric),
@@ -136,7 +130,7 @@ SingleTreeTraversalType>::NeighborSearch(const NeighborSearchMode mode,
if (mode != NAIVE_MODE)
{
referenceTree = BuildTree<Tree>(*referenceSet, oldFromNewReferences);
treeOwner = true;
referenceSet = &referenceTree->Dataset();
}
}
@@ -155,8 +149,6 @@ SingleTreeTraversalType>::NeighborSearch(const NeighborSearch& other) :
referenceTree(other.referenceTree ? new Tree(*other.referenceTree) : NULL),
referenceSet(other.referenceTree ? &referenceTree->Dataset() :
new MatType(*other.referenceSet)),
treeOwner(other.referenceTree),
setOwner(!other.referenceTree),
searchMode(other.searchMode),
epsilon(other.epsilon),
metric(other.metric),
@@ -181,8 +173,6 @@ SingleTreeTraversalType>::NeighborSearch(NeighborSearch&& other) :
oldFromNewReferences(std::move(other.oldFromNewReferences)),
referenceTree(other.referenceTree),
referenceSet(other.referenceSet),
treeOwner(other.treeOwner),
setOwner(other.setOwner),
searchMode(other.searchMode),
epsilon(other.epsilon),
metric(std::move(other.metric)),
@@ -194,8 +184,7 @@ SingleTreeTraversalType>::NeighborSearch(NeighborSearch&& other) :
other.referenceSet = new MatType();
other.referenceTree = BuildTree<Tree>(*other.referenceSet,
other.oldFromNewReferences);
other.treeOwner = true;
other.setOwner = true;
other.referenceSet = &other.referenceTree->Dataset();
other.searchMode = DUAL_TREE_MODE,
other.epsilon = 0.0;
other.baseCases = 0;
@@ -229,17 +218,15 @@ NeighborSearch<SortPolicy,
return *this; // Nothing to do.
// Clean memory first.
if (treeOwner && referenceTree)
if (referenceTree)
delete referenceTree;
if (setOwner && referenceSet)
else
delete referenceSet;
oldFromNewReferences = other.oldFromNewReferences;
referenceTree = other.referenceTree ? new Tree(*other.referenceTree) : NULL;
referenceSet = other.referenceTree ? &referenceTree->Dataset() :
new MatType(*other.referenceSet);
treeOwner = (other.referenceTree != NULL);
setOwner = (other.referenceTree == NULL);
searchMode = other.searchMode;
epsilon = other.epsilon;
metric = other.metric;
@@ -274,16 +261,14 @@ NeighborSearch<SortPolicy,
return *this; // Nothing to do.
// Clean memory first.
if (treeOwner && referenceTree)
if (referenceTree)
delete referenceTree;
if (setOwner && referenceSet)
else
delete referenceSet;
oldFromNewReferences = std::move(other.oldFromNewReferences);
referenceTree = other.referenceTree;
referenceSet = other.referenceSet;
treeOwner = other.treeOwner;
setOwner = other.setOwner;
searchMode = other.searchMode;
epsilon = other.epsilon;
metric = other.metric;
@@ -292,11 +277,9 @@ NeighborSearch<SortPolicy,
treeNeedsReset = other.treeNeedsReset;
// Reset the other object.
other.referenceSet = new MatType();
other.referenceTree = BuildTree<Tree>(*other.referenceSet,
other.oldFromNewReferences);
other.treeOwner = true;
other.setOwner = true;
other.referenceSet = &other.referenceTree->Dataset();
other.searchMode = DUAL_TREE_MODE,
other.epsilon = 0.0;
other.baseCases = 0;
@@ -316,9 +299,9 @@ template<typename SortPolicy,
NeighborSearch<SortPolicy, MetricType, MatType, TreeType, DualTreeTraversalType,
SingleTreeTraversalType>::~NeighborSearch()
{
if (treeOwner && referenceTree)
if (referenceTree)
delete referenceTree;
if (setOwner && referenceSet)
else
delete referenceSet;
}
@@ -331,72 +314,30 @@ template<typename SortPolicy,
template<typename> class DualTreeTraversalType,
template<typename> class SingleTreeTraversalType>
void NeighborSearch<SortPolicy, MetricType, MatType, TreeType,
DualTreeTraversalType, SingleTreeTraversalType>::Train(
const MatType& referenceSet)
DualTreeTraversalType, SingleTreeTraversalType>::Train(MatType referenceSetIn)
{
// Clean up the old tree, if we built one.
if (treeOwner && referenceTree)
if (referenceTree)
{
oldFromNewReferences.clear();
delete referenceTree;
}
// Delete the old reference set, if we owned it.
if (setOwner && this->referenceSet)
delete this->referenceSet;
// We may need to rebuild the tree.
if (searchMode != NAIVE_MODE)
{
referenceTree = BuildTree<Tree>(referenceSet, oldFromNewReferences);
treeOwner = true;
this->referenceSet = &referenceTree->Dataset();
referenceTree = NULL;
}
else
{
treeOwner = false;
this->referenceSet = &referenceSet;
}
setOwner = false; // We don't own the set in either case.
}
template<typename SortPolicy,
typename MetricType,
typename MatType,
template<typename TreeMetricType,
typename TreeStatType,
typename TreeMatType> class TreeType,
template<typename> class DualTreeTraversalType,
template<typename> class SingleTreeTraversalType>
void NeighborSearch<SortPolicy, MetricType, MatType, TreeType,
DualTreeTraversalType, SingleTreeTraversalType>::Train(MatType&& referenceSetIn)
{
// Clean up the old tree, if we built one.
if (treeOwner && referenceTree)
{
oldFromNewReferences.clear();
delete referenceTree;
}
// Delete the old reference set, if we owned it.
if (setOwner && referenceSet)
delete referenceSet;
}
// We may need to rebuild the tree.
if (searchMode != NAIVE_MODE)
{
referenceTree = BuildTree<Tree>(std::move(referenceSetIn),
oldFromNewReferences);
treeOwner = true;
referenceSet = &referenceTree->Dataset();
setOwner = false;
}
else
{
treeOwner = false;
referenceSet = new MatType(std::move(referenceSetIn));
setOwner = true;
}
}
@@ -409,56 +350,24 @@ template<typename SortPolicy,
template<typename> class DualTreeTraversalType,
template<typename> class SingleTreeTraversalType>
void NeighborSearch<SortPolicy, MetricType, MatType, TreeType,
DualTreeTraversalType, SingleTreeTraversalType>::Train(
const Tree& referenceTree)
DualTreeTraversalType, SingleTreeTraversalType>::Train(Tree referenceTree)
{
if (searchMode == NAIVE_MODE)
throw std::invalid_argument("cannot train on given reference tree when "
"naive search (without trees) is desired");
if (treeOwner && this->referenceTree)
if (this->referenceTree)
{
oldFromNewReferences.clear();
delete this->referenceTree;
}
if (setOwner && referenceSet)
delete this->referenceSet;
this->referenceTree = new Tree(referenceTree);
this->referenceSet = &this->referenceTree->Dataset();
treeOwner = true;
setOwner = false;
}
template<typename SortPolicy,
typename MetricType,
typename MatType,
template<typename TreeMetricType,
typename TreeStatType,
typename TreeMatType> class TreeType,
template<typename> class DualTreeTraversalType,
template<typename> class SingleTreeTraversalType>
void NeighborSearch<SortPolicy, MetricType, MatType, TreeType,
DualTreeTraversalType, SingleTreeTraversalType>::Train(Tree&& referenceTree)
{
if (searchMode == NAIVE_MODE)
throw std::invalid_argument("cannot train on given reference tree when "
"naive search (without trees) is desired");
if (treeOwner && this->referenceTree)
else
{
oldFromNewReferences.clear();
delete this->referenceTree;
}
if (setOwner && referenceSet)
delete this->referenceSet;
}
this->referenceTree = new Tree(std::move(referenceTree));
this->referenceSet = &this->referenceTree->Dataset();
treeOwner = true;
setOwner = false;
}
/**
@@ -1046,12 +955,9 @@ DualTreeTraversalType, SingleTreeTraversalType>::serialize(
if (searchMode == NAIVE_MODE)
{
// Delete the current reference set, if necessary and if we are loading.
if (Archive::is_loading::value)
if (Archive::is_loading::value && referenceSet)
{
if (setOwner && referenceSet)
delete referenceSet;
setOwner = true; // We will own the reference set when we load it.
delete referenceSet;
}
ar & BOOST_SERIALIZATION_NVP(referenceSet);
@@ -1060,24 +966,19 @@ DualTreeTraversalType, SingleTreeTraversalType>::serialize(
// If we are loading, set the tree to NULL and clean up memory if necessary.
if (Archive::is_loading::value)
{
if (treeOwner && referenceTree)
if (referenceTree)
delete referenceTree;
referenceTree = NULL;
oldFromNewReferences.clear();
treeOwner = false;
}
}
else
{
// Delete the current reference tree, if necessary and if we are loading.
if (Archive::is_loading::value)
if (Archive::is_loading::value && referenceTree)
{
if (treeOwner && referenceTree)
delete referenceTree;
// After we load the tree, we will own it.
treeOwner = true;
delete referenceTree;
}
ar & BOOST_SERIALIZATION_NVP(referenceTree);
@@ -1087,12 +988,8 @@ DualTreeTraversalType, SingleTreeTraversalType>::serialize(
// necessary.
if (Archive::is_loading::value)
{
if (setOwner && referenceSet)
delete referenceSet;
referenceSet = &referenceTree->Dataset();
metric = referenceTree->Metric(); // Get the metric from the tree.
setOwner = false;
}
}
@@ -1,5 +1,3 @@
cmake_minimum_required(VERSION 2.8)
# Define the files we need to compile.
# Anything not in this list will not be compiled into mlpack.
set(SOURCES
@@ -1,5 +1,3 @@
cmake_minimum_required(VERSION 2.8)
# Define the files we need to compile.
# Anything not in this list will not be compiled into mlpack.
set(SOURCES
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+43 -130
View File
@@ -104,35 +104,17 @@ void BuildVanillaNetwork(MatType& trainData,
BOOST_AUTO_TEST_CASE(VanillaNetworkTest)
{
// Load the dataset.
arma::mat dataset;
data::Load("thyroid_train.csv", dataset, true);
arma::mat trainData;
data::Load("thyroid_train.csv", trainData, true);
arma::mat trainData = dataset.submat(0, 0, dataset.n_rows - 4,
dataset.n_cols - 1);
arma::mat trainLabels = trainData.row(trainData.n_rows - 1);
trainData.shed_row(trainData.n_rows - 1);
arma::mat trainLabelsTemp = dataset.submat(dataset.n_rows - 3, 0,
dataset.n_rows - 1, dataset.n_cols - 1);
arma::mat trainLabels = arma::zeros<arma::mat>(1, trainLabelsTemp.n_cols);
for (size_t i = 0; i < trainLabelsTemp.n_cols; ++i)
{
trainLabels(i) = arma::as_scalar(arma::find(
arma::max(trainLabelsTemp.col(i)) == trainLabelsTemp.col(i), 1)) + 1;
}
arma::mat testData;
data::Load("thyroid_test.csv", testData, true);
data::Load("thyroid_test.csv", dataset, true);
arma::mat testData = dataset.submat(0, 0, dataset.n_rows - 4,
dataset.n_cols - 1);
arma::mat testLabelsTemp = dataset.submat(dataset.n_rows - 3, 0,
dataset.n_rows - 1, dataset.n_cols - 1);
arma::mat testLabels = arma::zeros<arma::mat>(1, testLabelsTemp.n_cols);
for (size_t i = 0; i < testLabels.n_cols; ++i)
{
testLabels(i) = arma::as_scalar(arma::find(
arma::max(testLabelsTemp.col(i)) == testLabelsTemp.col(i), 1)) + 1;
}
arma::mat testLabels = testData.row(testData.n_rows - 1);
testData.shed_row(testData.n_rows - 1);
// Vanilla neural net with logistic activation function.
// Because 92 percent of the patients are not hyperthyroid the neural
@@ -140,6 +122,7 @@ BOOST_AUTO_TEST_CASE(VanillaNetworkTest)
BuildVanillaNetwork<>
(trainData, trainLabels, testData, testLabels, 3, 8, 10, 0.1);
arma::mat dataset;
dataset.load("mnist_first250_training_4s_and_9s.arm");
// Normalize each point since these are images.
@@ -307,35 +290,17 @@ void BuildDropoutNetwork(MatType& trainData,
BOOST_AUTO_TEST_CASE(DropoutNetworkTest)
{
// Load the dataset.
arma::mat dataset;
data::Load("thyroid_train.csv", dataset, true);
arma::mat trainData;
data::Load("thyroid_train.csv", trainData, true);
arma::mat trainData = dataset.submat(0, 0, dataset.n_rows - 4,
dataset.n_cols - 1);
arma::mat trainLabels = trainData.row(trainData.n_rows - 1);
trainData.shed_row(trainData.n_rows - 1);
arma::mat trainLabelsTemp = dataset.submat(dataset.n_rows - 3, 0,
dataset.n_rows - 1, dataset.n_cols - 1);
arma::mat trainLabels = arma::zeros<arma::mat>(1, trainLabelsTemp.n_cols);
for (size_t i = 0; i < trainLabelsTemp.n_cols; ++i)
{
trainLabels(i) = arma::as_scalar(arma::find(
arma::max(trainLabelsTemp.col(i)) == trainLabelsTemp.col(i), 1)) + 1;
}
arma::mat testData;
data::Load("thyroid_test.csv", testData, true);
data::Load("thyroid_test.csv", dataset, true);
arma::mat testData = dataset.submat(0, 0, dataset.n_rows - 4,
dataset.n_cols - 1);
arma::mat testLabelsTemp = dataset.submat(dataset.n_rows - 3, 0,
dataset.n_rows - 1, dataset.n_cols - 1);
arma::mat testLabels = arma::zeros<arma::mat>(1, testLabelsTemp.n_cols);
for (size_t i = 0; i < testLabels.n_cols; ++i)
{
testLabels(i) = arma::as_scalar(arma::find(
arma::max(testLabelsTemp.col(i)) == testLabelsTemp.col(i), 1)) + 1;
}
arma::mat testLabels = testData.row(testData.n_rows - 1);
testData.shed_row(testData.n_rows - 1);
// Vanilla neural net with logistic activation function.
// Because 92 percent of the patients are not hyperthyroid the neural
@@ -343,6 +308,7 @@ BOOST_AUTO_TEST_CASE(DropoutNetworkTest)
BuildDropoutNetwork<>
(trainData, trainLabels, testData, testLabels, 3, 8, 10, 0.1);
arma::mat dataset;
dataset.load("mnist_first250_training_4s_and_9s.arm");
// Normalize each point since these are images.
@@ -436,35 +402,17 @@ void BuildDropConnectNetwork(MatType& trainData,
BOOST_AUTO_TEST_CASE(DropConnectNetworkTest)
{
// Load the dataset.
arma::mat dataset;
data::Load("thyroid_train.csv", dataset, true);
arma::mat trainData;
data::Load("thyroid_train.csv", trainData, true);
arma::mat trainData = dataset.submat(0, 0, dataset.n_rows - 4,
dataset.n_cols - 1);
arma::mat trainLabels = trainData.row(trainData.n_rows - 1);
trainData.shed_row(trainData.n_rows - 1);
arma::mat trainLabelsTemp = dataset.submat(dataset.n_rows - 3, 0,
dataset.n_rows - 1, dataset.n_cols - 1);
arma::mat trainLabels = arma::zeros<arma::mat>(1, trainLabelsTemp.n_cols);
for (size_t i = 0; i < trainLabelsTemp.n_cols; ++i)
{
trainLabels(i) = arma::as_scalar(arma::find(
arma::max(trainLabelsTemp.col(i)) == trainLabelsTemp.col(i), 1)) + 1;
}
arma::mat testData;
data::Load("thyroid_test.csv", testData, true);
data::Load("thyroid_test.csv", dataset, true);
arma::mat testData = dataset.submat(0, 0, dataset.n_rows - 4,
dataset.n_cols - 1);
arma::mat testLabelsTemp = dataset.submat(dataset.n_rows - 3, 0,
dataset.n_rows - 1, dataset.n_cols - 1);
arma::mat testLabels = arma::zeros<arma::mat>(1, testLabelsTemp.n_cols);
for (size_t i = 0; i < testLabels.n_cols; ++i)
{
testLabels(i) = arma::as_scalar(arma::find(
arma::max(testLabelsTemp.col(i)) == testLabelsTemp.col(i), 1)) + 1;
}
arma::mat testLabels = testData.row(testData.n_rows - 1);
testData.shed_row(testData.n_rows - 1);
// Vanilla neural net with logistic activation function.
// Because 92 percent of the patients are not hyperthyroid the neural
@@ -472,6 +420,7 @@ BOOST_AUTO_TEST_CASE(DropConnectNetworkTest)
BuildDropConnectNetwork<>
(trainData, trainLabels, testData, testLabels, 3, 8, 10, 0.1);
arma::mat dataset;
dataset.load("mnist_first250_training_4s_and_9s.arm");
// Normalize each point since these are images.
@@ -509,35 +458,17 @@ BOOST_AUTO_TEST_CASE(FFNMiscTest)
BOOST_AUTO_TEST_CASE(SerializationTest)
{
// Load the dataset.
arma::mat dataset;
data::Load("thyroid_train.csv", dataset, true);
arma::mat trainData;
data::Load("thyroid_train.csv", trainData, true);
arma::mat trainData = dataset.submat(0, 0, dataset.n_rows - 4,
dataset.n_cols - 1);
arma::mat trainLabels = trainData.row(trainData.n_rows - 1);
trainData.shed_row(trainData.n_rows - 1);
arma::mat trainLabelsTemp = dataset.submat(dataset.n_rows - 3, 0,
dataset.n_rows - 1, dataset.n_cols - 1);
arma::mat trainLabels = arma::zeros<arma::mat>(1, trainLabelsTemp.n_cols);
for (size_t i = 0; i < trainLabelsTemp.n_cols; ++i)
{
trainLabels(i) = arma::as_scalar(arma::find(
arma::max(trainLabelsTemp.col(i)) == trainLabelsTemp.col(i), 1)) + 1;
}
arma::mat testData;
data::Load("thyroid_test.csv", testData, true);
data::Load("thyroid_test.csv", dataset, true);
arma::mat testData = dataset.submat(0, 0, dataset.n_rows - 4,
dataset.n_cols - 1);
arma::mat testLabelsTemp = dataset.submat(dataset.n_rows - 3, 0,
dataset.n_rows - 1, dataset.n_cols - 1);
arma::mat testLabels = arma::zeros<arma::mat>(1, testLabelsTemp.n_cols);
for (size_t i = 0; i < testLabels.n_cols; ++i)
{
testLabels(i) = arma::as_scalar(arma::find(
arma::max(testLabelsTemp.col(i)) == testLabelsTemp.col(i), 1)) + 1;
}
arma::mat testLabels = testData.row(testData.n_rows - 1);
testData.shed_row(testData.n_rows - 1);
// Vanilla neural net with logistic activation function.
// Because 92 percent of the patients are not hyperthyroid the neural
@@ -576,35 +507,17 @@ BOOST_AUTO_TEST_CASE(SerializationTest)
BOOST_AUTO_TEST_CASE(CustomLayerTest)
{
// Load the dataset.
arma::mat dataset;
data::Load("thyroid_train.csv", dataset, true);
arma::mat trainData;
data::Load("thyroid_train.csv", trainData, true);
arma::mat trainData = dataset.submat(0, 0, dataset.n_rows - 4,
dataset.n_cols - 1);
arma::mat trainLabels = trainData.row(trainData.n_rows - 1);
trainData.shed_row(trainData.n_rows - 1);
arma::mat trainLabelsTemp = dataset.submat(dataset.n_rows - 3, 0,
dataset.n_rows - 1, dataset.n_cols - 1);
arma::mat trainLabels = arma::zeros<arma::mat>(1, trainLabelsTemp.n_cols);
for (size_t i = 0; i < trainLabelsTemp.n_cols; ++i)
{
trainLabels(i) = arma::as_scalar(arma::find(
arma::max(trainLabelsTemp.col(i)) == trainLabelsTemp.col(i), 1)) + 1;
}
arma::mat testData;
data::Load("thyroid_test.csv", testData, true);
data::Load("thyroid_test.csv", dataset, true);
arma::mat testData = dataset.submat(0, 0, dataset.n_rows - 4,
dataset.n_cols - 1);
arma::mat testLabelsTemp = dataset.submat(dataset.n_rows - 3, 0,
dataset.n_rows - 1, dataset.n_cols - 1);
arma::mat testLabels = arma::zeros<arma::mat>(1, testLabelsTemp.n_cols);
for (size_t i = 0; i < testLabels.n_cols; ++i)
{
testLabels(i) = arma::as_scalar(arma::find(
arma::max(testLabelsTemp.col(i)) == testLabelsTemp.col(i), 1)) + 1;
}
arma::mat testLabels = testData.row(testData.n_rows - 1);
testData.shed_row(testData.n_rows - 1);
FFN<NegativeLogLikelihood<>, RandomInitialization, CustomLayer<> > model;
model.Add<Linear<> >(trainData.n_rows, 8);
+14
View File
@@ -19,6 +19,7 @@
#include <mlpack/core/kernels/polynomial_kernel.hpp>
#include <mlpack/core/kernels/spherical_kernel.hpp>
#include <mlpack/core/kernels/pspectrum_string_kernel.hpp>
#include <mlpack/core/kernels/cauchy_kernel.hpp>
#include <mlpack/core/metrics/lmetric.hpp>
#include <mlpack/core/metrics/mahalanobis_distance.hpp>
@@ -608,4 +609,17 @@ BOOST_AUTO_TEST_CASE(PSpectrumStringEvaluateTest)
BOOST_REQUIRE_CLOSE(p.Evaluate(b, a), 11.0, 1e-5);
}
/**
* Cauchy Kernel test.
*/
BOOST_AUTO_TEST_CASE(CauchyKernelTest)
{
arma::vec a = "0 0 1";
arma::vec b = "0 1 0";
CauchyKernel ck(5.0);
BOOST_REQUIRE_CLOSE(ck.Evaluate(a, b), 0.92592588, 1e-5);
BOOST_REQUIRE_CLOSE(ck.Evaluate(b, a), 0.92592588, 1e-5);
}
BOOST_AUTO_TEST_SUITE_END();
+1
View File
@@ -52,6 +52,7 @@ BOOST_AUTO_TEST_CASE(IsNormalizedTest)
BOOST_REQUIRE_EQUAL((bool) KernelTraits<SphericalKernel>::IsNormalized, true);
BOOST_REQUIRE_EQUAL((bool) KernelTraits<TriangularKernel>::IsNormalized,
true);
BOOST_REQUIRE_EQUAL((bool) KernelTraits<CauchyKernel>::IsNormalized, true);
// Unnormalized kernels.
BOOST_REQUIRE_EQUAL((bool) KernelTraits<LinearKernel>::IsNormalized, false);