Merge branch 'master' into HEAD
This commit is contained in:
+2
-2
@@ -85,8 +85,8 @@ build_script:
|
||||
- cd C:\projects\mlpack && mkdir build && cd build
|
||||
- >
|
||||
cmake -G "%VSVER%"
|
||||
-DBLAS_LIBRARY:FILEPATH=%BLAS_LIBRARY%
|
||||
-DLAPACK_LIBRARY:FILEPATH=%BLAS_LIBRARY%
|
||||
-DBLAS_LIBRARIES:FILEPATH=%BLAS_LIBRARY%
|
||||
-DLAPACK_LIBRARIES:FILEPATH=%BLAS_LIBRARY%
|
||||
-DARMADILLO_INCLUDE_DIR="C:/projects/mlpack/armadillo-8.400.0/include"
|
||||
-DARMADILLO_LIBRARY:FILEPATH=%ARMADILLO_LIBRARY%
|
||||
-DBOOST_INCLUDEDIR:PATH=%BOOST_INCLUDE%
|
||||
|
||||
+10
-18
@@ -1,3 +1,12 @@
|
||||
trigger:
|
||||
branches:
|
||||
include:
|
||||
- '*'
|
||||
pr:
|
||||
branches:
|
||||
include:
|
||||
- '*'
|
||||
|
||||
jobs:
|
||||
- job: Linux
|
||||
timeoutInMinutes: 360
|
||||
@@ -28,7 +37,7 @@ jobs:
|
||||
- job: macOS
|
||||
timeoutInMinutes: 360
|
||||
pool:
|
||||
vmImage: macOS-10.13
|
||||
vmImage: macOS-10.14
|
||||
strategy:
|
||||
matrix:
|
||||
Plain:
|
||||
@@ -48,23 +57,6 @@ jobs:
|
||||
steps:
|
||||
- template: macos-steps.yaml
|
||||
|
||||
- job: WindowsVS14
|
||||
timeoutInMinutes: 360
|
||||
displayName: Windows VS14
|
||||
pool:
|
||||
vmImage: vs2015-win2012r2
|
||||
strategy:
|
||||
matrix:
|
||||
Plain:
|
||||
CMakeArgs: '-DDEBUG=ON -DPROFILE=OFF -DBUILD_PYTHON_BINDINGS=OFF'
|
||||
CMakeGenerator: '-G "Visual Studio 14 2015 Win64"'
|
||||
MSBuildVersion: '14.0'
|
||||
ArchiveNoLibs: 'mlpack-windows-vs14-no-libs.zip'
|
||||
ArchiveLibs: 'mlpack-windows-vs14.zip'
|
||||
ArchiveTests: 'mlpack_test-vs14.xml'
|
||||
steps:
|
||||
- template: windows-steps.yaml
|
||||
|
||||
- job: WindowsVS15
|
||||
timeoutInMinutes: 360
|
||||
displayName: Windows VS15
|
||||
|
||||
@@ -14,8 +14,7 @@ steps:
|
||||
set -e
|
||||
sudo xcode-select --switch /Applications/Xcode_10.1.app/Contents/Developer
|
||||
unset BOOST_ROOT
|
||||
pip install cython numpy pandas zipp
|
||||
brew update
|
||||
pip install cython numpy pandas zipp configparser
|
||||
brew install openblas armadillo boost
|
||||
|
||||
if [ "a$(julia.version)" != "a" ]; then
|
||||
|
||||
@@ -28,7 +28,7 @@ steps:
|
||||
# Configure armadillo
|
||||
- bash: |
|
||||
git clone --depth 1 https://github.com/mlpack/jenkins-conf.git conf
|
||||
|
||||
|
||||
curl -O http://masterblaster.mlpack.org:5005/armadillo-8.400.0.tar.gz -o armadillo-8.400.0.tar.gz
|
||||
tar -xzvf armadillo-8.400.0.tar.gz
|
||||
|
||||
@@ -60,12 +60,13 @@ steps:
|
||||
|
||||
cmake $(CMakeGenerator) `
|
||||
$(CMakeArgs) `
|
||||
-DBLAS_LIBRARY:FILEPATH=$(Agent.ToolsDirectory)\OpenBLAS.0.2.14.1\lib\native\lib\x64\libopenblas.dll.a `
|
||||
-DLAPACK_LIBRARY:FILEPATH=$(Agent.ToolsDirectory)\OpenBLAS.0.2.14.1\lib\native\lib\x64\libopenblas.dll.a `
|
||||
-DBLAS_LIBRARIES:FILEPATH=$(Agent.ToolsDirectory)\OpenBLAS.0.2.14.1\lib\native\lib\x64\libopenblas.dll.a `
|
||||
-DLAPACK_LIBRARIES:FILEPATH=$(Agent.ToolsDirectory)\OpenBLAS.0.2.14.1\lib\native\lib\x64\libopenblas.dll.a `
|
||||
-DARMADILLO_INCLUDE_DIR="..\armadillo-8.400.0\include" `
|
||||
-DARMADILLO_LIBRARY="..\armadillo-8.400.0\Release\armadillo.lib" `
|
||||
-DBOOST_INCLUDEDIR=$(Agent.ToolsDirectory)\boost.1.60.0.0\lib\native\include `
|
||||
-DBOOST_LIBRARYDIR=$(Agent.ToolsDirectory)\boost_libs `
|
||||
-DBUILD_JULIA_BINDINGS=OFF `
|
||||
-DCMAKE_BUILD_TYPE=Release ..
|
||||
displayName: 'Configure mlpack'
|
||||
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
# - Find AMD's ACML library (no includes) which provides optimised BLAS and LAPACK functions
|
||||
# This module defines
|
||||
# ACML_LIBRARIES, the libraries needed to use ACML.
|
||||
# ACML_FOUND, If false, do not try to use ACML.
|
||||
# also defined, but not for general use are
|
||||
# ACML_LIBRARY, where to find the ACML library.
|
||||
|
||||
set(ACML_NAMES ${ACML_NAMES} acml)
|
||||
find_library(ACML_LIBRARY
|
||||
NAMES ${ACML_NAMES}
|
||||
PATHS /usr/lib64 /usr/lib /usr/*/lib64 /usr/*/lib /usr/*/gfortran64/lib/ /usr/*/gfortran32/lib/ /usr/local/lib64 /usr/local/lib /opt/lib64 /opt/lib /opt/*/lib64 /opt/*/lib /opt/*/gfortran64/lib/ /opt/*/gfortran32/lib/
|
||||
)
|
||||
|
||||
if (ACML_LIBRARY)
|
||||
set(ACML_LIBRARIES ${ACML_LIBRARY})
|
||||
set(ACML_FOUND "YES")
|
||||
else ()
|
||||
set(ACML_FOUND "NO")
|
||||
endif ()
|
||||
|
||||
|
||||
if (ACML_FOUND)
|
||||
if (NOT ACML_FIND_QUIETLY)
|
||||
message(STATUS "Found the ACML library: ${ACML_LIBRARIES}")
|
||||
endif ()
|
||||
else ()
|
||||
if (ACML_FIND_REQUIRED)
|
||||
message(FATAL_ERROR "Could not find the ACML library")
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
# Deprecated declarations.
|
||||
get_filename_component (NATIVE_ACML_LIB_PATH ${ACML_LIBRARY} PATH)
|
||||
|
||||
mark_as_advanced(
|
||||
ACML_LIBRARY
|
||||
)
|
||||
@@ -1,37 +0,0 @@
|
||||
# - Find AMD's ACMLMP library (no includes) which provides optimised and parallelised BLAS and LAPACK functions
|
||||
# This module defines
|
||||
# ACMLMP_LIBRARIES, the libraries needed to use ACMLMP.
|
||||
# ACMLMP_FOUND, If false, do not try to use ACMLMP.
|
||||
# also defined, but not for general use are
|
||||
# ACMLMP_LIBRARY, where to find the ACMLMP library.
|
||||
|
||||
set(ACMLMP_NAMES ${ACMLMP_NAMES} acml_mp)
|
||||
find_library(ACMLMP_LIBRARY
|
||||
NAMES ${ACMLMP_NAMES}
|
||||
PATHS /usr/lib64 /usr/lib /usr/*/lib64 /usr/*/lib /usr/*/gfortran64_mp/lib/ /usr/*/gfortran32_mp/lib/ /usr/local/lib64 /usr/local/lib /opt/lib64 /opt/lib /opt/*/lib64 /opt/*/lib /opt/*/gfortran64_mp/lib/ /opt/*/gfortran32_mp/lib/
|
||||
)
|
||||
|
||||
if (ACMLMP_LIBRARY)
|
||||
set(ACMLMP_LIBRARIES ${ACMLMP_LIBRARY})
|
||||
set(ACMLMP_FOUND "YES")
|
||||
else ()
|
||||
set(ACMLMP_FOUND "NO")
|
||||
endif ()
|
||||
|
||||
|
||||
if (ACMLMP_FOUND)
|
||||
if (NOT ACMLMP_FIND_QUIETLY)
|
||||
message(STATUS "Found the ACMLMP library: ${ACMLMP_LIBRARIES}")
|
||||
endif ()
|
||||
else ()
|
||||
if (ACMLMP_FIND_REQUIRED)
|
||||
message(FATAL_ERROR "Could not find the ACMLMP library")
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
# Deprecated declarations.
|
||||
get_filename_component (NATIVE_ACMLMP_LIB_PATH ${ACMLMP_LIBRARY} PATH)
|
||||
|
||||
mark_as_advanced(
|
||||
ACMLMP_LIBRARY
|
||||
)
|
||||
@@ -1,39 +0,0 @@
|
||||
# - Try to find ARPACK
|
||||
# Once done this will define
|
||||
#
|
||||
# ARPACK_FOUND - system has ARPACK
|
||||
# ARPACK_LIBRARY - Link this to use ARPACK
|
||||
|
||||
|
||||
find_library(ARPACK_LIBRARY
|
||||
NAMES arpack
|
||||
PATHS /usr/lib64 /usr/lib /usr/local/lib64 /usr/local/lib
|
||||
)
|
||||
|
||||
|
||||
if (ARPACK_LIBRARY)
|
||||
set(ARPACK_FOUND YES)
|
||||
else ()
|
||||
# Search for PARPACK.
|
||||
find_library(ARPACK_LIBRARY
|
||||
NAMES parpack
|
||||
PATHS /usr/lib64 /usr/lib /usr/local/lib64 /usr/local/lib
|
||||
)
|
||||
|
||||
if (ARPACK_LIBRARY)
|
||||
set(ARPACK_FOUND YES)
|
||||
else ()
|
||||
set(ARPACK_FOUND NO)
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
|
||||
if (ARPACK_FOUND)
|
||||
if (NOT ARPACK_FIND_QUIETLY)
|
||||
message(STATUS "Found an ARPACK library: ${ARPACK_LIBRARY}")
|
||||
endif ()
|
||||
else ()
|
||||
if (ARPACK_FIND_REQUIRED)
|
||||
message(FATAL_ERROR "Could not find an ARPACK library")
|
||||
endif ()
|
||||
endif ()
|
||||
@@ -1,44 +0,0 @@
|
||||
# - Find a BLAS library (no includes)
|
||||
# This module defines
|
||||
# BLAS_LIBRARIES, the libraries needed to use BLAS.
|
||||
# BLAS_FOUND, If false, do not try to use BLAS.
|
||||
# also defined, but not for general use are
|
||||
# BLAS_LIBRARY, where to find the BLAS library.
|
||||
|
||||
set(BLAS_NAMES ${BLAS_NAMES} blas)
|
||||
|
||||
# Find the ATLAS version preferentially.
|
||||
find_library(BLAS_LIBRARY
|
||||
NAMES ${BLAS_NAMES}
|
||||
PATHS /usr/lib64/atlas /usr/lib/atlas /usr/local/lib64/atlas /usr/local/lib/atlas
|
||||
NO_DEFAULT_PATH)
|
||||
|
||||
find_library(BLAS_LIBRARY
|
||||
NAMES ${BLAS_NAMES}
|
||||
PATHS /usr/lib64/atlas /usr/lib/atlas /usr/lib64 /usr/lib /usr/local/lib64 /usr/local/lib
|
||||
)
|
||||
|
||||
if (BLAS_LIBRARY)
|
||||
set(BLAS_LIBRARIES ${BLAS_LIBRARY})
|
||||
set(BLAS_FOUND "YES")
|
||||
else ()
|
||||
set(BLAS_FOUND "NO")
|
||||
endif ()
|
||||
|
||||
|
||||
if (BLAS_FOUND)
|
||||
if (NOT BLAS_FIND_QUIETLY)
|
||||
message(STATUS "Found BLAS: ${BLAS_LIBRARIES}")
|
||||
endif ()
|
||||
else ()
|
||||
if (BLAS_FIND_REQUIRED)
|
||||
message(FATAL_ERROR "Could not find BLAS")
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
# Deprecated declarations.
|
||||
get_filename_component (NATIVE_BLAS_LIB_PATH ${BLAS_LIBRARY} PATH)
|
||||
|
||||
mark_as_advanced(
|
||||
BLAS_LIBRARY
|
||||
)
|
||||
@@ -1,47 +0,0 @@
|
||||
# - Find CBLAS (includes and library)
|
||||
# This module defines
|
||||
# CBLAS_INCLUDE_DIR
|
||||
# CBLAS_LIBRARIES
|
||||
# CBLAS_FOUND
|
||||
# also defined, but not for general use are
|
||||
# CBLAS_LIBRARY, where to find the library.
|
||||
|
||||
find_path(CBLAS_INCLUDE_DIR cblas.h
|
||||
/usr/include/atlas/
|
||||
/usr/local/include/atlas/
|
||||
/usr/include/
|
||||
/usr/local/include/
|
||||
)
|
||||
|
||||
set(CBLAS_NAMES ${CBLAS_NAMES} cblas)
|
||||
find_library(CBLAS_LIBRARY
|
||||
NAMES ${CBLAS_NAMES}
|
||||
PATHS /usr/lib64/atlas-sse3 /usr/lib64/atlas /usr/lib64 /usr/local/lib64/atlas /usr/local/lib64 /usr/lib/atlas-sse3 /usr/lib/atlas-sse2 /usr/lib/atlas-sse /usr/lib/atlas-3dnow /usr/lib/atlas /usr/lib /usr/local/lib/atlas /usr/local/lib
|
||||
)
|
||||
|
||||
if (CBLAS_LIBRARY AND CBLAS_INCLUDE_DIR)
|
||||
set(CBLAS_LIBRARIES ${CBLAS_LIBRARY})
|
||||
set(CBLAS_FOUND "YES")
|
||||
else ()
|
||||
set(CBLAS_FOUND "NO")
|
||||
endif ()
|
||||
|
||||
|
||||
if (CBLAS_FOUND)
|
||||
if (NOT CBLAS_FIND_QUIETLY)
|
||||
message(STATUS "Found a CBLAS library: ${CBLAS_LIBRARIES}")
|
||||
endif ()
|
||||
else ()
|
||||
if (CBLAS_FIND_REQUIRED)
|
||||
message(FATAL_ERROR "Could not find a CBLAS library")
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
# Deprecated declarations.
|
||||
set (NATIVE_CBLAS_INCLUDE_PATH ${CBLAS_INCLUDE_DIR} )
|
||||
get_filename_component (NATIVE_CBLAS_LIB_PATH ${CBLAS_LIBRARY} PATH)
|
||||
|
||||
mark_as_advanced(
|
||||
CBLAS_LIBRARY
|
||||
CBLAS_INCLUDE_DIR
|
||||
)
|
||||
@@ -1,48 +0,0 @@
|
||||
# - Find a version of CLAPACK (includes and library)
|
||||
# This module defines
|
||||
# CLAPACK_INCLUDE_DIR
|
||||
# CLAPACK_LIBRARIES
|
||||
# CLAPACK_FOUND
|
||||
# also defined, but not for general use are
|
||||
# CLAPACK_LIBRARY, where to find the library.
|
||||
|
||||
find_path(CLAPACK_INCLUDE_DIR clapack.h
|
||||
/usr/include/atlas/
|
||||
/usr/local/include/atlas/
|
||||
/usr/include/
|
||||
/usr/local/include/
|
||||
)
|
||||
|
||||
set(CLAPACK_NAMES ${CLAPACK_NAMES} lapack_atlas)
|
||||
set(CLAPACK_NAMES ${CLAPACK_NAMES} clapack)
|
||||
find_library(CLAPACK_LIBRARY
|
||||
NAMES ${CLAPACK_NAMES}
|
||||
PATHS /usr/lib64/atlas-sse3 /usr/lib64/atlas /usr/lib64 /usr/local/lib64/atlas /usr/local/lib64 /usr/lib/atlas-sse3 /usr/lib/atlas-sse2 /usr/lib/atlas-sse /usr/lib/atlas-3dnow /usr/lib/atlas /usr/lib /usr/local/lib/atlas /usr/local/lib
|
||||
)
|
||||
|
||||
if (CLAPACK_LIBRARY AND CLAPACK_INCLUDE_DIR)
|
||||
set(CLAPACK_LIBRARIES ${CLAPACK_LIBRARY})
|
||||
set(CLAPACK_FOUND "YES")
|
||||
else ()
|
||||
set(CLAPACK_FOUND "NO")
|
||||
endif ()
|
||||
|
||||
|
||||
if (CLAPACK_FOUND)
|
||||
if (NOT CLAPACK_FIND_QUIETLY)
|
||||
message(STATUS "Found a CLAPACK library: ${CLAPACK_LIBRARIES}")
|
||||
endif ()
|
||||
else ()
|
||||
if (CLAPACK_FIND_REQUIRED)
|
||||
message(FATAL_ERROR "Could not find a CLAPACK library")
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
# Deprecated declarations.
|
||||
set (NATIVE_CLAPACK_INCLUDE_PATH ${CLAPACK_INCLUDE_DIR} )
|
||||
get_filename_component (NATIVE_CLAPACK_LIB_PATH ${CLAPACK_LIBRARY} PATH)
|
||||
|
||||
mark_as_advanced(
|
||||
CLAPACK_LIBRARY
|
||||
CLAPACK_INCLUDE_DIR
|
||||
)
|
||||
@@ -1,44 +0,0 @@
|
||||
# - Find a LAPACK library (no includes)
|
||||
# This module defines
|
||||
# LAPACK_LIBRARIES, the libraries needed to use LAPACK.
|
||||
# LAPACK_FOUND, If false, do not try to use LAPACK.
|
||||
# also defined, but not for general use are
|
||||
# LAPACK_LIBRARY, where to find the LAPACK library.
|
||||
|
||||
set(LAPACK_NAMES ${LAPACK_NAMES} lapack)
|
||||
|
||||
# Check ATLAS paths preferentially, using this necessary hack (I love CMake).
|
||||
find_library(LAPACK_LIBRARY
|
||||
NAMES ${LAPACK_NAMES}
|
||||
PATHS /usr/lib64/atlas /usr/lib/atlas /usr/local/lib64/atlas /usr/local/lib/atlas
|
||||
NO_DEFAULT_PATH)
|
||||
|
||||
find_library(LAPACK_LIBRARY
|
||||
NAMES ${LAPACK_NAMES}
|
||||
PATHS /usr/lib64 /usr/lib /usr/local/lib64 /usr/local/lib
|
||||
)
|
||||
|
||||
if (LAPACK_LIBRARY)
|
||||
set(LAPACK_LIBRARIES ${LAPACK_LIBRARY})
|
||||
set(LAPACK_FOUND "YES")
|
||||
else ()
|
||||
set(LAPACK_FOUND "NO")
|
||||
endif ()
|
||||
|
||||
|
||||
if (LAPACK_FOUND)
|
||||
if (NOT LAPACK_FIND_QUIETLY)
|
||||
message(STATUS "Found LAPACK: ${LAPACK_LIBRARIES}")
|
||||
endif ()
|
||||
else ()
|
||||
if (LAPACK_FIND_REQUIRED)
|
||||
message(FATAL_ERROR "Could not find LAPACK")
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
# Deprecated declarations.
|
||||
get_filename_component (NATIVE_LAPACK_LIB_PATH ${LAPACK_LIBRARY} PATH)
|
||||
|
||||
mark_as_advanced(
|
||||
LAPACK_LIBRARY
|
||||
)
|
||||
@@ -1,49 +0,0 @@
|
||||
# - Find the MKL libraries (no includes)
|
||||
# This module defines
|
||||
# MKL_LIBRARIES, the libraries needed to use Intel's implementation of BLAS & LAPACK.
|
||||
# MKL_FOUND, If false, do not try to use MKL.
|
||||
|
||||
set(MKL_NAMES ${MKL_NAMES} mkl_lapack)
|
||||
set(MKL_NAMES ${MKL_NAMES} mkl_intel_thread)
|
||||
set(MKL_NAMES ${MKL_NAMES} mkl_core)
|
||||
set(MKL_NAMES ${MKL_NAMES} guide)
|
||||
set(MKL_NAMES ${MKL_NAMES} mkl)
|
||||
set(MKL_NAMES ${MKL_NAMES} iomp5)
|
||||
#set(MKL_NAMES ${MKL_NAMES} pthread)
|
||||
|
||||
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
set(MKL_NAMES ${MKL_NAMES} mkl_intel_lp64)
|
||||
else()
|
||||
set(MKL_NAMES ${MKL_NAMES} mkl_intel)
|
||||
endif()
|
||||
|
||||
foreach (MKL_NAME ${MKL_NAMES})
|
||||
find_library(${MKL_NAME}_LIBRARY
|
||||
NAMES ${MKL_NAME}
|
||||
PATHS /usr/lib64 /usr/lib /usr/local/lib64 /usr/local/lib /opt/intel/lib/intel64 /opt/intel/lib/ia32 /opt/intel/mkl/lib/lib64 /opt/intel/mkl/lib/intel64 /opt/intel/mkl/lib/ia32 /opt/intel/mkl/lib /opt/intel/*/mkl/lib/intel64 /opt/intel/*/mkl/lib/ia32/ /opt/mkl/*/lib/em64t /opt/mkl/*/lib/32 /opt/intel/mkl/*/lib/em64t /opt/intel/mkl/*/lib/32
|
||||
)
|
||||
|
||||
set(TMP_LIBRARY ${${MKL_NAME}_LIBRARY})
|
||||
|
||||
if(TMP_LIBRARY)
|
||||
set(MKL_LIBRARIES ${MKL_LIBRARIES} ${TMP_LIBRARY})
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
if (MKL_LIBRARIES)
|
||||
set(MKL_FOUND "YES")
|
||||
else ()
|
||||
set(MKL_FOUND "NO")
|
||||
endif ()
|
||||
|
||||
if (MKL_FOUND)
|
||||
if (NOT MKL_FIND_QUIETLY)
|
||||
message(STATUS "Found MKL libraries: ${MKL_LIBRARIES}")
|
||||
endif ()
|
||||
else ()
|
||||
if (MKL_FIND_REQUIRED)
|
||||
message(FATAL_ERROR "Could not find MKL libraries")
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
# mark_as_advanced(MKL_LIBRARY)
|
||||
@@ -1,37 +0,0 @@
|
||||
# - Find the OpenBLAS library (no includes)
|
||||
# This module defines
|
||||
# OpenBLAS_LIBRARIES, the libraries needed to use OpenBLAS.
|
||||
# OpenBLAS_FOUND, If false, do not try to use OpenBLAS.
|
||||
# also defined, but not for general use are
|
||||
# OpenBLAS_LIBRARY, where to find the OpenBLAS library.
|
||||
|
||||
set(OpenBLAS_NAMES ${OpenBLAS_NAMES} openblas)
|
||||
find_library(OpenBLAS_LIBRARY
|
||||
NAMES ${OpenBLAS_NAMES}
|
||||
PATHS /lib64 /lib /usr/lib64 /usr/lib /usr/local/lib64 /usr/local/lib
|
||||
)
|
||||
|
||||
if (OpenBLAS_LIBRARY)
|
||||
set(OpenBLAS_LIBRARIES ${OpenBLAS_LIBRARY})
|
||||
set(OpenBLAS_FOUND "YES")
|
||||
else ()
|
||||
set(OpenBLAS_FOUND "NO")
|
||||
endif ()
|
||||
|
||||
|
||||
if (OpenBLAS_FOUND)
|
||||
if (NOT OpenBLAS_FIND_QUIETLY)
|
||||
message(STATUS "Found the OpenBLAS library: ${OpenBLAS_LIBRARIES}")
|
||||
endif ()
|
||||
else ()
|
||||
if (OpenBLAS_FIND_REQUIRED)
|
||||
message(FATAL_ERROR "Could not find the OpenBLAS library")
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
# Deprecated declarations.
|
||||
get_filename_component (NATIVE_OpenBLAS_LIB_PATH ${OpenBLAS_LIBRARY} PATH)
|
||||
|
||||
mark_as_advanced(
|
||||
OpenBLAS_LIBRARY
|
||||
)
|
||||
@@ -0,0 +1,55 @@
|
||||
# Searches for an installation of the ARPACK library. On success, it sets the following variables:
|
||||
#
|
||||
# ARPACK_FOUND Set to true to indicate the library was found
|
||||
# ARPACK_LIBRARIES All libraries needed to use ARPACK (with full path)
|
||||
#
|
||||
# To specify an additional directory to search, set ARPACK_ROOT.
|
||||
#
|
||||
# TODO: Do we need to explicitly search for BLAS and LAPACK as well? The source distribution statically links these to
|
||||
# libarpack. Are there any installations that don't do this or the equivalent?
|
||||
#
|
||||
# Author: Siddhartha Chaudhuri, 2009
|
||||
#
|
||||
|
||||
SET(ARPACK_FOUND FALSE)
|
||||
|
||||
# First look in user-provided root directory, then look in system locations
|
||||
FIND_LIBRARY(ARPACK_LIBRARIES NAMES arpack libarpack ARPACK libARPACK PATHS "${ARPACK_ROOT}" "${ARPACK_ROOT}/lib"
|
||||
NO_DEFAULT_PATH)
|
||||
IF(NOT ARPACK_LIBRARIES)
|
||||
FIND_LIBRARY(ARPACK_LIBRARIES NAMES arpack libarpack ARPACK libARPACK)
|
||||
ENDIF(NOT ARPACK_LIBRARIES)
|
||||
|
||||
IF(ARPACK_LIBRARIES)
|
||||
# On OS X we probably also need gfortran and BLAS and LAPACK libraries
|
||||
IF(APPLE)
|
||||
FIND_LIBRARY(ARPACK_LAPACK_LIBRARY NAMES lapack LAPACK PATHS "${ARPACK_ROOT}" "${ARPACK_ROOT}/lib")
|
||||
FIND_LIBRARY(ARPACK_BLAS_LIBRARY NAMES blas BLAS PATHS "${ARPACK_ROOT}" "${ARPACK_ROOT}/lib")
|
||||
FIND_LIBRARY(ARPACK_GFORTRAN_LIBRARY NAMES gfortran PATHS "${ARPACK_ROOT}" "${ARPACK_ROOT}/lib"
|
||||
PATH_SUFFIXES "" "gfortran/lib" "../gfortran/lib")
|
||||
|
||||
IF(ARPACK_BLAS_LIBRARY)
|
||||
SET(ARPACK_LIBRARIES ${ARPACK_LIBRARIES} ${ARPACK_BLAS_LIBRARY})
|
||||
ENDIF(ARPACK_BLAS_LIBRARY)
|
||||
|
||||
IF(ARPACK_LAPACK_LIBRARY)
|
||||
SET(ARPACK_LIBRARIES ${ARPACK_LIBRARIES} ${ARPACK_LAPACK_LIBRARY})
|
||||
ENDIF(ARPACK_LAPACK_LIBRARY)
|
||||
|
||||
IF(ARPACK_GFORTRAN_LIBRARY)
|
||||
SET(ARPACK_LIBRARIES ${ARPACK_LIBRARIES} ${ARPACK_GFORTRAN_LIBRARY})
|
||||
ENDIF(ARPACK_GFORTRAN_LIBRARY)
|
||||
ENDIF(APPLE)
|
||||
|
||||
SET(ARPACK_FOUND TRUE)
|
||||
ENDIF(ARPACK_LIBRARIES)
|
||||
|
||||
IF(ARPACK_FOUND)
|
||||
IF(NOT ARPACK_FIND_QUIETLY)
|
||||
MESSAGE(STATUS "Found ARPACK: libraries at ${ARPACK_LIBRARIES}")
|
||||
ENDIF(NOT ARPACK_FIND_QUIETLY)
|
||||
ELSE(ARPACK_FOUND)
|
||||
IF(ARPACK_FIND_REQUIRED)
|
||||
MESSAGE(FATAL_ERROR "ARPACK not found")
|
||||
ENDIF(ARPACK_FIND_REQUIRED)
|
||||
ENDIF(ARPACK_FOUND)
|
||||
+118
-319
@@ -1,41 +1,41 @@
|
||||
# - Find Armadillo
|
||||
# Find the Armadillo C++ library
|
||||
#
|
||||
# Using Armadillo:
|
||||
# find_package(Armadillo REQUIRED)
|
||||
# include_directories(${ARMADILLO_INCLUDE_DIRS})
|
||||
# add_executable(foo foo.cc)
|
||||
# target_link_libraries(foo ${ARMADILLO_LIBRARIES})
|
||||
# This module sets the following variables:
|
||||
# ARMADILLO_FOUND - set to true if the library is found
|
||||
# ARMADILLO_INCLUDE_DIRS - list of required include directories
|
||||
# ARMADILLO_LIBRARIES - list of libraries to be linked
|
||||
# ARMADILLO_VERSION_MAJOR - major version number
|
||||
# ARMADILLO_VERSION_MINOR - minor version number
|
||||
# ARMADILLO_VERSION_PATCH - patch version number
|
||||
# ARMADILLO_VERSION_STRING - version number as a string (ex: "1.0.4")
|
||||
# ARMADILLO_VERSION_NAME - name of the version (ex: "Antipodean Antileech")
|
||||
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
# file Copyright.txt or https://cmake.org/licensing for details.
|
||||
|
||||
#=============================================================================
|
||||
# Copyright 2011 Clement Creusot <creusot@cs.york.ac.uk>
|
||||
#
|
||||
# Distributed under the OSI-approved BSD License (the "License");
|
||||
# see accompanying file Copyright.txt for details.
|
||||
#
|
||||
# This software is distributed WITHOUT ANY WARRANTY; without even the
|
||||
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
# See the License for more information.
|
||||
#=============================================================================
|
||||
# (To distribute this file outside of CMake, substitute the full
|
||||
# License text for the above reference.)
|
||||
#[=======================================================================[.rst:
|
||||
FindArmadillo
|
||||
-------------
|
||||
|
||||
Find the Armadillo C++ library.
|
||||
Armadillo is a library for linear algebra & scientific computing.
|
||||
|
||||
Using Armadillo:
|
||||
|
||||
::
|
||||
|
||||
find_package(Armadillo REQUIRED)
|
||||
include_directories(${ARMADILLO_INCLUDE_DIRS})
|
||||
add_executable(foo foo.cc)
|
||||
target_link_libraries(foo ${ARMADILLO_LIBRARIES})
|
||||
|
||||
This module sets the following variables:
|
||||
|
||||
::
|
||||
|
||||
ARMADILLO_FOUND - set to true if the library is found
|
||||
ARMADILLO_INCLUDE_DIRS - list of required include directories
|
||||
ARMADILLO_LIBRARIES - list of libraries to be linked
|
||||
ARMADILLO_VERSION_MAJOR - major version number
|
||||
ARMADILLO_VERSION_MINOR - minor version number
|
||||
ARMADILLO_VERSION_PATCH - patch version number
|
||||
ARMADILLO_VERSION_STRING - version number as a string (ex: "1.0.4")
|
||||
ARMADILLO_VERSION_NAME - name of the version (ex: "Antipodean Antileech")
|
||||
#]=======================================================================]
|
||||
|
||||
find_path(ARMADILLO_INCLUDE_DIR
|
||||
NAMES armadillo
|
||||
PATHS "$ENV{ProgramFiles}/Armadillo/include"
|
||||
)
|
||||
|
||||
|
||||
if(ARMADILLO_INCLUDE_DIR)
|
||||
# ------------------------------------------------------------------------
|
||||
# Extract version information from <armadillo>
|
||||
@@ -52,318 +52,117 @@ if(ARMADILLO_INCLUDE_DIR)
|
||||
if(EXISTS "${ARMADILLO_INCLUDE_DIR}/armadillo_bits/arma_version.hpp")
|
||||
|
||||
# Read and parse armdillo version header file for version number
|
||||
file(READ "${ARMADILLO_INCLUDE_DIR}/armadillo_bits/arma_version.hpp" _armadillo_HEADER_CONTENTS)
|
||||
string(REGEX REPLACE ".*#define ARMA_VERSION_MAJOR ([0-9]+).*" "\\1" ARMADILLO_VERSION_MAJOR "${_armadillo_HEADER_CONTENTS}")
|
||||
string(REGEX REPLACE ".*#define ARMA_VERSION_MINOR ([0-9]+).*" "\\1" ARMADILLO_VERSION_MINOR "${_armadillo_HEADER_CONTENTS}")
|
||||
string(REGEX REPLACE ".*#define ARMA_VERSION_PATCH ([0-9]+).*" "\\1" ARMADILLO_VERSION_PATCH "${_armadillo_HEADER_CONTENTS}")
|
||||
file(STRINGS "${ARMADILLO_INCLUDE_DIR}/armadillo_bits/arma_version.hpp" _ARMA_HEADER_CONTENTS REGEX "#define ARMA_VERSION_[A-Z]+ ")
|
||||
string(REGEX REPLACE ".*#define ARMA_VERSION_MAJOR ([0-9]+).*" "\\1" ARMADILLO_VERSION_MAJOR "${_ARMA_HEADER_CONTENTS}")
|
||||
string(REGEX REPLACE ".*#define ARMA_VERSION_MINOR ([0-9]+).*" "\\1" ARMADILLO_VERSION_MINOR "${_ARMA_HEADER_CONTENTS}")
|
||||
string(REGEX REPLACE ".*#define ARMA_VERSION_PATCH ([0-9]+).*" "\\1" ARMADILLO_VERSION_PATCH "${_ARMA_HEADER_CONTENTS}")
|
||||
|
||||
# WARNING: The number of spaces before the version name is not one.
|
||||
string(REGEX REPLACE ".*#define ARMA_VERSION_NAME\ +\"([0-9a-zA-Z\ _-]+)\".*" "\\1" ARMADILLO_VERSION_NAME "${_armadillo_HEADER_CONTENTS}")
|
||||
string(REGEX REPLACE ".*#define ARMA_VERSION_NAME\ +\"([0-9a-zA-Z\ _-]+)\".*" "\\1" ARMADILLO_VERSION_NAME "${_ARMA_HEADER_CONTENTS}")
|
||||
|
||||
endif()
|
||||
|
||||
set(ARMADILLO_VERSION_STRING "${ARMADILLO_VERSION_MAJOR}.${ARMADILLO_VERSION_MINOR}.${ARMADILLO_VERSION_PATCH}")
|
||||
endif ()
|
||||
|
||||
|
||||
#======================
|
||||
|
||||
# Determine what support libraries are being used, and whether or not we need to
|
||||
# link against them. We need to look in config.hpp.
|
||||
set(SUPPORT_INCLUDE_DIRS "")
|
||||
set(SUPPORT_LIBRARIES "")
|
||||
set(ARMA_NEED_LIBRARY true) # Assume true.
|
||||
if(EXISTS "${ARMADILLO_INCLUDE_DIR}/armadillo_bits/config.hpp")
|
||||
file(READ "${ARMADILLO_INCLUDE_DIR}/armadillo_bits/config.hpp" _armadillo_CONFIG_CONTENTS)
|
||||
# ARMA_USE_WRAPPER
|
||||
string(REGEX MATCH "\r?\n[\t ]*#define[ \t]+ARMA_USE_WRAPPER[ \t]*\r?\n" ARMA_USE_WRAPPER "${_armadillo_CONFIG_CONTENTS}")
|
||||
|
||||
# ARMA_USE_LAPACK
|
||||
string(REGEX MATCH "\r?\n[\t ]*#if[\t ]+!defined[(]ARMA_USE_LAPACK[)][\t ]*\r?\n[\t ]*#define[ \t]+ARMA_USE_LAPACK[ \t]*\r?\n" ARMA_USE_LAPACK "${_armadillo_CONFIG_CONTENTS}")
|
||||
|
||||
# ARMA_USE_BLAS
|
||||
string(REGEX MATCH "\r?\n[\t ]*#if[\t ]+!defined[(]ARMA_USE_BLAS[)][\t ]*\r?\n[\t ]*#define[ \t]+ARMA_USE_BLAS[ \t]*\r?\n" ARMA_USE_BLAS "${_armadillo_CONFIG_CONTENTS}")
|
||||
# ARMA_USE_ARPACK
|
||||
# ARMA_USE_ARPACK
|
||||
string(REGEX MATCH "\r?\n[\t ]*#if[\t ]+!defined[(]ARMA_USE_ARPACK[)][\t ]*\r?\n[\t ]*#define[ \t]+ARMA_USE_ARPACK[ \t]*\r?\n" ARMA_USE_ARPACK "${_armadillo_CONFIG_CONTENTS}")
|
||||
|
||||
# Look for #define ARMA_USE_HDF5.
|
||||
string(REGEX MATCH "\r?\n[\t ]*#if[\t ]+!defined[(]ARMA_USE_HDF5[)][\t ]*\r?\n[\t ]*#define[ \t]+ARMA_USE_HDF5[ \t]*\r?\n" ARMA_USE_HDF5 "${_armadillo_CONFIG_CONTENTS}")
|
||||
|
||||
# If we aren't wrapping, things get a little more complex.
|
||||
if("${ARMA_USE_WRAPPER}" STREQUAL "")
|
||||
set(ARMA_NEED_LIBRARY false)
|
||||
message(STATUS "ARMA_USE_WRAPPER is not defined, so all dependencies of "
|
||||
"Armadillo must be manually linked.")
|
||||
|
||||
set(HAVE_LAPACK false)
|
||||
set(HAVE_BLAS false)
|
||||
|
||||
# Search for LAPACK/BLAS (or replacement).
|
||||
if ((NOT "${ARMA_USE_LAPACK}" STREQUAL "") AND
|
||||
(NOT "${ARMA_USE_BLAS}" STREQUAL ""))
|
||||
# In order of preference: MKL, ACML, OpenBLAS, ATLAS
|
||||
set(MKL_FIND_QUIETLY true)
|
||||
include(ARMA_FindMKL)
|
||||
set(ACMLMP_FIND_QUIETLY true)
|
||||
include(ARMA_FindACMLMP)
|
||||
set(ACML_FIND_QUIETLY true)
|
||||
include(ARMA_FindACML)
|
||||
|
||||
if (MKL_FOUND)
|
||||
message(STATUS "Using MKL for LAPACK/BLAS: ${MKL_LIBRARIES}")
|
||||
|
||||
set(SUPPORT_LIBRARIES "${SUPPORT_LIBRARIES}" "${MKL_LIBRARIES}")
|
||||
set(HAVE_LAPACK true)
|
||||
set(HAVE_BLAS true)
|
||||
elseif (ACMLMP_FOUND)
|
||||
message(STATUS "Using multi-core ACML libraries for LAPACK/BLAS:
|
||||
${ACMLMP_LIBRARIES}")
|
||||
|
||||
set(SUPPORT_LIBRARIES "${SUPPORT_LIBRARIES}" "${ACMLMP_LIBRARIES}")
|
||||
set(HAVE_LAPACK true)
|
||||
set(HAVE_BLAS true)
|
||||
elseif (ACML_FOUND)
|
||||
message(STATUS "Using ACML for LAPACK/BLAS: ${ACML_LIBRARIES}")
|
||||
|
||||
set(SUPPORT_LIBRARIES "${SUPPORT_LIBRARIES}" "${ACML_LIBRARIES}")
|
||||
set(HAVE_LAPACK true)
|
||||
set(HAVE_BLAS true)
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
# If we haven't found BLAS, try.
|
||||
if (NOT "${ARMA_USE_BLAS}" STREQUAL "" AND NOT HAVE_BLAS)
|
||||
# Search for BLAS.
|
||||
set(OpenBLAS_FIND_QUIETLY true)
|
||||
include(ARMA_FindOpenBLAS)
|
||||
set(CBLAS_FIND_QUIETLY true)
|
||||
include(ARMA_FindCBLAS)
|
||||
set(BLAS_FIND_QUIETLY true)
|
||||
include(ARMA_FindBLAS)
|
||||
|
||||
if (OpenBLAS_FOUND)
|
||||
# Warn if ATLAS is found also.
|
||||
if (CBLAS_FOUND)
|
||||
message(STATUS "Warning: both OpenBLAS and ATLAS have been found; "
|
||||
"ATLAS will not be used.")
|
||||
endif ()
|
||||
message(STATUS "Using OpenBLAS for BLAS: ${OpenBLAS_LIBRARIES}")
|
||||
|
||||
set(SUPPORT_LIBRARIES "${SUPPORT_LIBRARIES}" "${OpenBLAS_LIBRARIES}")
|
||||
set(HAVE_BLAS true)
|
||||
elseif (CBLAS_FOUND)
|
||||
message(STATUS "Using ATLAS for BLAS: ${CBLAS_LIBRARIES}")
|
||||
|
||||
set(SUPPORT_LIBRARIES "${SUPPORT_LIBRARIES}" "${CBLAS_LIBRARIES}")
|
||||
set(SUPPORT_INCLUDE_DIRS "${SUPPORT_INCLUDE_DIRS}"
|
||||
"${CBLAS_INCLUDE_DIR}")
|
||||
set(HAVE_BLAS true)
|
||||
elseif (BLAS_FOUND)
|
||||
message(STATUS "Using standard BLAS: ${BLAS_LIBRARIES}")
|
||||
|
||||
set(SUPPORT_LIBRARIES "${SUPPORT_LIBRARIES}" "${BLAS_LIBRARIES}")
|
||||
set(HAVE_BLAS true)
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
# If we haven't found LAPACK, try.
|
||||
if (NOT "${ARMA_USE_LAPACK}" STREQUAL "" AND NOT HAVE_LAPACK)
|
||||
# Search for LAPACK.
|
||||
set(CLAPACK_FIND_QUIETLY true)
|
||||
include(ARMA_FindCLAPACK)
|
||||
set(LAPACK_FIND_QUIETLY true)
|
||||
include(ARMA_FindLAPACK)
|
||||
|
||||
# Only use ATLAS if OpenBLAS isn't being used.
|
||||
if (CLAPACK_FOUND AND NOT OpenBLAS_FOUND)
|
||||
message(STATUS "Using ATLAS for LAPACK: ${CLAPACK_LIBRARIES}")
|
||||
|
||||
set(SUPPORT_LIBRARIES "${SUPPORT_LIBRARIES}" "${CLAPACK_LIBRARIES}")
|
||||
set(SUPPORT_INCLUDE_DIRS "${SUPPORT_INCLUDE_DIRS}"
|
||||
"${CLAPACK_INCLUDE_DIR}")
|
||||
set(HAVE_LAPACK true)
|
||||
elseif (LAPACK_FOUND)
|
||||
message(STATUS "Using standard LAPACK: ${LAPACK_LIBRARIES}")
|
||||
|
||||
set(SUPPORT_LIBRARIES "${SUPPORT_LIBRARIES}" "${LAPACK_LIBRARIES}")
|
||||
set(HAVE_LAPACK true)
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
if (NOT "${ARMA_USE_LAPACK}" STREQUAL "" AND NOT HAVE_LAPACK)
|
||||
message(FATAL_ERROR "Cannot find LAPACK library, but ARMA_USE_LAPACK is "
|
||||
"set. Try specifying LAPACK libraries manually by setting the "
|
||||
"LAPACK_LIBRARY variable.")
|
||||
endif ()
|
||||
|
||||
if (NOT "${ARMA_USE_BLAS}" STREQUAL "" AND NOT HAVE_BLAS)
|
||||
message(FATAL_ERROR "Cannot find BLAS library, but ARMA_USE_BLAS is set. "
|
||||
"Try specifying BLAS libraries manually by setting the BLAS_LIBRARY "
|
||||
"variable.")
|
||||
endif ()
|
||||
|
||||
# Search for ARPACK (or replacement).
|
||||
if (NOT "${ARMA_USE_ARPACK}" STREQUAL "")
|
||||
# Use Armadillo ARPACK-finding procedure.
|
||||
set(ARPACK_FIND_QUIETLY true)
|
||||
include(ARMA_FindARPACK)
|
||||
|
||||
if (NOT ARPACK_FOUND)
|
||||
message(FATAL_ERROR "ARMA_USE_ARPACK is defined in "
|
||||
"armadillo_bits/config.hpp, but ARPACK cannot be found. Try "
|
||||
"specifying ARPACK_LIBRARY.")
|
||||
endif ()
|
||||
|
||||
set(SUPPORT_LIBRARIES "${SUPPORT_LIBRARIES}" "${ARPACK_LIBRARY}")
|
||||
endif ()
|
||||
|
||||
# Search for HDF5 (or replacement).
|
||||
if (NOT "${ARMA_USE_HDF5}" STREQUAL "")
|
||||
find_package(HDF5 QUIET)
|
||||
|
||||
if(NOT HDF5_FOUND)
|
||||
# On Debian systems, the HDF5 package has been split into multiple
|
||||
# packages so that it is co-installable. But this may mean that the
|
||||
# include files are hidden somewhere very odd that the FindHDF5.cmake
|
||||
# script will not find. Thus, we'll also quickly check pkgconfig to see
|
||||
# if there is information on what to use there.
|
||||
find_package(PkgConfig)
|
||||
if (PKG_CONFIG_FOUND)
|
||||
pkg_check_modules(HDF5 hdf5)
|
||||
# But using pkgconfig is a little weird because HDF5_LIBRARIES won't
|
||||
# be filled with exact library paths, like the other scripts. So
|
||||
# instead what we get is HDF5_LIBRARY_DIRS which is the equivalent of
|
||||
# what we'd pass to -L.
|
||||
if (HDF5_FOUND)
|
||||
# I'm not sure what I think of doing this here...
|
||||
link_directories("${HDF5_LIBRARY_DIRS}")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(NOT HDF5_FOUND)
|
||||
# We tried but didn't find it.
|
||||
message(FATAL_ERROR "Armadillo HDF5 support is enabled, but HDF5 "
|
||||
"cannot be found on the system. Consider disabling HDF5 support.")
|
||||
endif()
|
||||
|
||||
set(SUPPORT_INCLUDE_DIRS "${SUPPORT_INCLUDE_DIRS}" "${HDF5_INCLUDE_DIRS}")
|
||||
set(SUPPORT_LIBRARIES "${SUPPORT_LIBRARIES}" "${HDF5_LIBRARIES}")
|
||||
endif ()
|
||||
|
||||
else()
|
||||
# Some older versions still require linking against HDF5 since they did not
|
||||
# wrap libhdf5. This was true for versions older than 4.300.
|
||||
if(NOT "${ARMA_USE_HDF5}" STREQUAL "" AND
|
||||
"${ARMADILLO_VERSION_STRING}" VERSION_LESS "4.300.0")
|
||||
message(STATUS "Armadillo HDF5 support is enabled and manual linking is "
|
||||
"required.")
|
||||
# We have HDF5 support and need to link against HDF5.
|
||||
find_package(HDF5)
|
||||
|
||||
if(NOT HDF5_FOUND)
|
||||
# On Debian systems, the HDF5 package has been split into multiple
|
||||
# packages so that it is co-installable. But this may mean that the
|
||||
# include files are hidden somewhere very odd that the FindHDF5.cmake
|
||||
# script will not find. Thus, we'll also quickly check pkgconfig to see
|
||||
# if there is information on what to use there.
|
||||
find_package(PkgConfig)
|
||||
if (PKG_CONFIG_FOUND)
|
||||
pkg_check_modules(HDF5 hdf5)
|
||||
# But using pkgconfig is a little weird because HDF5_LIBRARIES won't
|
||||
# be filled with exact library paths, like the other scripts. So
|
||||
# instead what we get is HDF5_LIBRARY_DIRS which is the equivalent of
|
||||
# what we'd pass to -L.
|
||||
if (HDF5_FOUND)
|
||||
# I'm not sure what I think of doing this here...
|
||||
link_directories("${HDF5_LIBRARY_DIRS}")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(NOT HDF5_FOUND)
|
||||
# We tried but didn't find it.
|
||||
message(FATAL_ERROR "Armadillo HDF5 support is enabled, but HDF5 "
|
||||
"cannot be found on the system. Consider disabling HDF5 support.")
|
||||
endif()
|
||||
|
||||
set(SUPPORT_INCLUDE_DIRS "${HDF5_INCLUDE_DIRS}")
|
||||
set(SUPPORT_LIBRARIES "${HDF5_LIBRARIES}")
|
||||
endif()
|
||||
|
||||
# Versions between 4.300 and 4.500 did successfully wrap HDF5, but didn't have good support for setting the include directory correctly.
|
||||
if(NOT "${ARMA_USE_HDF5}" STREQUAL "" AND
|
||||
"${ARMADILLO_VERSION_STRING}" VERSION_GREATER "4.299.0" AND
|
||||
"${ARMADILLO_VERSION_STRING}" VERSION_LESS "4.450.0")
|
||||
message(STATUS "Armadillo HDF5 support is enabled and include "
|
||||
"directories must be found.")
|
||||
find_package(HDF5)
|
||||
|
||||
if(NOT HDF5_FOUND)
|
||||
# On Debian systems, the HDF5 package has been split into multiple
|
||||
# packages so that it is co-installable. But this may mean that the
|
||||
# include files are hidden somewhere very odd that the FindHDF5.cmake
|
||||
# script will not find. Thus, we'll also quickly check pkgconfig to see
|
||||
# if there is information on what to use there.
|
||||
find_package(PkgConfig)
|
||||
if (PKG_CONFIG_FOUND)
|
||||
pkg_check_modules(HDF5 hdf5)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(NOT HDF5_FOUND)
|
||||
# We tried but didn't find it.
|
||||
message(FATAL_ERROR "Armadillo HDF5 support is enabled, but HDF5 "
|
||||
"cannot be found on the system. Consider disabling HDF5 support.")
|
||||
endif()
|
||||
|
||||
set(SUPPORT_INCLUDE_DIRS "${HDF5_INCLUDE_DIRS}")
|
||||
endif()
|
||||
|
||||
endif()
|
||||
else()
|
||||
message(FATAL_ERROR "${ARMADILLO_INCLUDE_DIR}/armadillo_bits/config.hpp not "
|
||||
"found! Cannot determine what to link against.")
|
||||
file(STRINGS "${ARMADILLO_INCLUDE_DIR}/armadillo_bits/config.hpp" _ARMA_CONFIG_CONTENTS REGEX "^#define ARMA_USE_[A-Z]+")
|
||||
string(REGEX MATCH "ARMA_USE_WRAPPER" _ARMA_USE_WRAPPER "${_ARMA_CONFIG_CONTENTS}")
|
||||
string(REGEX MATCH "ARMA_USE_LAPACK" _ARMA_USE_LAPACK "${_ARMA_CONFIG_CONTENTS}")
|
||||
string(REGEX MATCH "ARMA_USE_BLAS" _ARMA_USE_BLAS "${_ARMA_CONFIG_CONTENTS}")
|
||||
string(REGEX MATCH "ARMA_USE_ARPACK" _ARMA_USE_ARPACK "${_ARMA_CONFIG_CONTENTS}")
|
||||
string(REGEX MATCH "ARMA_USE_HDF5" _ARMA_USE_HDF5 "${_ARMA_CONFIG_CONTENTS}")
|
||||
endif()
|
||||
|
||||
if (ARMA_NEED_LIBRARY)
|
||||
include(FindPackageHandleStandardArgs)
|
||||
|
||||
# If _ARMA_USE_WRAPPER is set, then we just link to armadillo, but if it's not then we need support libraries instead
|
||||
set(_ARMA_SUPPORT_LIBRARIES)
|
||||
|
||||
if(_ARMA_USE_WRAPPER)
|
||||
# UNIX paths are standard, no need to write.
|
||||
find_library(ARMADILLO_LIBRARY
|
||||
NAMES armadillo
|
||||
PATHS "$ENV{ProgramFiles}/Armadillo/lib" "$ENV{ProgramFiles}/Armadillo/lib64" "$ENV{ProgramFiles}/Armadillo"
|
||||
)
|
||||
set(_ARMA_REQUIRED_VARS ARMADILLO_LIBRARY ARMADILLO_INCLUDE_DIR VERSION_VAR ARMADILLO_VERSION_STRING)
|
||||
else()
|
||||
# don't link to armadillo in this case
|
||||
set(ARMADILLO_LIBRARY "")
|
||||
if(_ARMA_USE_LAPACK)
|
||||
if(ARMADILLO_FIND_QUIETLY OR NOT ARMADILLO_FIND_REQUIRED)
|
||||
find_package(LAPACK QUIET)
|
||||
else()
|
||||
find_package(LAPCK REQUIRED)
|
||||
endif()
|
||||
if(LAPACK_FOUND)
|
||||
set(_ARMA_SUPPORT_LIBRARIES "${_ARMA_SUPPORT_LIBRARIES}" "${LAPACK_LIBRARIES}")
|
||||
endif()
|
||||
endif()
|
||||
if(_ARMA_USE_BLAS)
|
||||
if(ARMADILLO_FIND_QUIETLY OR NOT ARMADILLO_FIND_REQUIRED)
|
||||
find_package(BLAS QUIET)
|
||||
else()
|
||||
find_package(BLAS REQUIRED)
|
||||
endif()
|
||||
if(BLAS_FOUND)
|
||||
set(_ARMA_SUPPORT_LIBRARIES "${_ARMA_SUPPORT_LIBRARIES}" "${BLAS_LIBRARIES}")
|
||||
endif()
|
||||
endif()
|
||||
if(_ARMA_USE_ARPACK)
|
||||
if(ARMADILLO_FIND_QUIETLY OR NOT ARMADILLO_FIND_REQUIRED)
|
||||
find_package(ARPACK QUIET)
|
||||
else()
|
||||
find_package(ARPACK REQUIRED)
|
||||
endif()
|
||||
if(ARPACK_FOUND)
|
||||
set(_ARMA_SUPPORT_LIBRARIES "${_ARMA_SUPPORT_LIBRARIES}" "${ARPACK_LIBRARIES}")
|
||||
endif()
|
||||
endif()
|
||||
if(_ARMA_USE_HDF5)
|
||||
find_package(HDF5 QUIET)
|
||||
if(NOT HDF5_FOUND)
|
||||
# On Debian systems, the HDF5 package has been split into multiple
|
||||
# packages so that it is co-installable. But this may mean that the
|
||||
# include files are hidden somewhere very odd that FindHDF5.cmake will
|
||||
# not find. Thus, we'll also quickly check pkgconfig to see if there is
|
||||
# information on what to use there.
|
||||
message(WARNING "HDF5 required but not found; using PkgConfig")
|
||||
find_package(PkgConfig)
|
||||
if (PKG_CONFIG_FOUND)
|
||||
pkg_check_modules(HDF5 REQUIRED hdf5)
|
||||
link_directories("${HDF5_LIBRARY_DIRS}")
|
||||
else()
|
||||
message(FATAL_ERROR "PkgConfig (Used to help find HDF5) was not found")
|
||||
endif()
|
||||
endif()
|
||||
set(_ARMA_SUPPORT_INCLUDE_DIRS "${HDF5_INCLUDE_DIRS}")
|
||||
set(_ARMA_SUPPORT_LIBRARIES "${_ARMA_SUPPORT_LIBRARIES}" "${HDF5_LIBRARIES}")
|
||||
endif()
|
||||
set(ARMADILLO_FOUND true)
|
||||
set(_ARMA_REQUIRED_VARS ARMADILLO_INCLUDE_DIR VERSION_VAR ARMADILLO_VERSION_STRING)
|
||||
endif()
|
||||
|
||||
# Checks 'REQUIRED', 'QUIET' and versions.
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(Armadillo
|
||||
REQUIRED_VARS ARMADILLO_LIBRARY ARMADILLO_INCLUDE_DIR
|
||||
VERSION_VAR ARMADILLO_VERSION_STRING)
|
||||
# version_var fails with cmake < 2.8.4.
|
||||
else ()
|
||||
# Checks 'REQUIRED', 'QUIET' and versions.
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(Armadillo
|
||||
REQUIRED_VARS ARMADILLO_INCLUDE_DIR
|
||||
VERSION_VAR ARMADILLO_VERSION_STRING)
|
||||
endif ()
|
||||
find_package_handle_standard_args(Armadillo REQUIRED_VARS ${_ARMA_REQUIRED_VARS})
|
||||
|
||||
if (ARMADILLO_FOUND)
|
||||
# Also include support include directories.
|
||||
set(ARMADILLO_INCLUDE_DIRS ${ARMADILLO_INCLUDE_DIR} ${SUPPORT_INCLUDE_DIRS})
|
||||
# Also include support libraries to link against.
|
||||
if (ARMA_NEED_LIBRARY)
|
||||
set(ARMADILLO_LIBRARIES ${ARMADILLO_LIBRARY} ${SUPPORT_LIBRARIES})
|
||||
else ()
|
||||
set(ARMADILLO_LIBRARIES ${SUPPORT_LIBRARIES})
|
||||
endif ()
|
||||
message(STATUS "Armadillo libraries: ${ARMADILLO_LIBRARIES}")
|
||||
set(ARMADILLO_INCLUDE_DIRS ${ARMADILLO_INCLUDE_DIR})
|
||||
set(ARMADILLO_LIBRARIES ${ARMADILLO_LIBRARY} ${_ARMA_SUPPORT_LIBRARIES})
|
||||
endif ()
|
||||
|
||||
# Clean up internal variables
|
||||
unset(_ARMA_REQUIRED_VARS)
|
||||
unset(_ARMA_SUPPORT_LIBRARIES)
|
||||
unset(_ARMA_USE_WRAPPER)
|
||||
unset(_ARMA_USE_LAPACK)
|
||||
unset(_ARMA_USE_BLAS)
|
||||
unset(_ARMA_USE_ARPACK)
|
||||
unset(_ARMA_USE_HDF5)
|
||||
unset(_ARMA_CONFIG_CONTENTS)
|
||||
unset(_ARMA_HEADER_CONTENTS)
|
||||
unset(__ARMA_SUPPORT_INCLUDE_DIRS)
|
||||
|
||||
# Hide internal variables
|
||||
mark_as_advanced(
|
||||
ARMADILLO_INCLUDE_DIR
|
||||
ARMADILLO_LIBRARY)
|
||||
|
||||
#======================
|
||||
|
||||
+13
-57
@@ -292,51 +292,6 @@ else()
|
||||
endif ()
|
||||
endif()
|
||||
|
||||
# On Windows, Armadillo should be using LAPACK and BLAS but we still need to
|
||||
# link against it. We don't want to use the FindLAPACK or FindBLAS modules
|
||||
# because then we are required to have a FORTRAN compiler (argh!) so we will try
|
||||
# and find LAPACK and BLAS ourselves, using a slightly modified variant of the
|
||||
# script Armadillo uses to find these.
|
||||
if (WIN32)
|
||||
find_library(LAPACK_LIBRARY
|
||||
NAMES lapack liblapack lapack_win32_MT lapack_win32
|
||||
PATHS "C:/Program Files/Armadillo"
|
||||
PATH_SUFFIXES "examples/lib_win32/")
|
||||
|
||||
if (NOT LAPACK_LIBRARY)
|
||||
message(FATAL_ERROR "Cannot find LAPACK library (.lib)!")
|
||||
endif ()
|
||||
|
||||
find_library(BLAS_LIBRARY
|
||||
NAMES blas libblas blas_win32_MT blas_win32
|
||||
PATHS "C:/Program Files/Armadillo"
|
||||
PATH_SUFFIXES "examples/lib_win32/")
|
||||
|
||||
if (NOT BLAS_LIBRARY)
|
||||
message(FATAL_ERROR "Cannot find BLAS library (.lib)!")
|
||||
endif ()
|
||||
|
||||
# Piggyback LAPACK and BLAS linking into Armadillo link.
|
||||
set(ARMADILLO_LIBRARIES
|
||||
${ARMADILLO_LIBRARIES} ${BLAS_LIBRARY} ${LAPACK_LIBRARY})
|
||||
|
||||
# Ensure that the libraries are added to the MSVC IDE runtime path.
|
||||
get_filename_component(BLAS_DIR ${BLAS_LIBRARY} DIRECTORY)
|
||||
get_filename_component(LAPACK_DIR ${LAPACK_LIBRARY} DIRECTORY)
|
||||
|
||||
# Sometimes, especially with an OpenBLAS install via nuget, the DLLs are
|
||||
# actually in ../../bin/x64/. Automatically add these.
|
||||
if (EXISTS "${BLAS_DIR}/../../bin/x64/")
|
||||
get_filename_component(BLAS_DLL_DIR "${BLAS_DIR}/../../bin/x64" ABSOLUTE)
|
||||
set(DLL_COPY_DIRS ${DLL_COPY_DIRS} "${BLAS_DLL_DIR}")
|
||||
endif ()
|
||||
|
||||
if (EXISTS "${LAPACK_DIR}/../../bin/x64/")
|
||||
get_filename_component(LAPACK_DLL_DIR "${LAPACK_DIR}/../../bin/x64" ABSOLUTE)
|
||||
set(DLL_COPY_DIRS ${DLL_COPY_DIRS} "${BLAS_DLL_DIR}")
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
# Include directories for the previous dependencies.
|
||||
set(MLPACK_INCLUDE_DIRS ${MLPACK_INCLUDE_DIRS} ${ARMADILLO_INCLUDE_DIRS})
|
||||
set(MLPACK_LIBRARIES ${MLPACK_LIBRARIES} ${ARMADILLO_LIBRARIES})
|
||||
@@ -373,6 +328,7 @@ if (NOT STB_IMAGE_FOUND)
|
||||
install(FILES "${CMAKE_BINARY_DIR}/deps/${STB_DIR}/stb_image.h" DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}")
|
||||
install(FILES "${CMAKE_BINARY_DIR}/deps/${STB_DIR}/stb_image_write.h" DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}")
|
||||
add_definitions(-DHAS_STB)
|
||||
set(STB_AVAILABLE "1")
|
||||
else ()
|
||||
message(WARNING
|
||||
"stb/stb_image.h is not installed. Image utilities will not be available!")
|
||||
@@ -393,6 +349,7 @@ else ()
|
||||
# Already has STB installed.
|
||||
add_definitions(-DHAS_STB)
|
||||
set(MLPACK_INCLUDE_DIRS ${MLPACK_INCLUDE_DIRS} ${STB_IMAGE_INCLUDE_DIR})
|
||||
set(STB_AVAILABLE "1")
|
||||
endif ()
|
||||
|
||||
|
||||
@@ -415,7 +372,12 @@ if (NOT ENSMALLEN_FOUND)
|
||||
# Get the name of the directory.
|
||||
file (GLOB ENS_DIRECTORIES RELATIVE "${CMAKE_BINARY_DIR}/deps/"
|
||||
"${CMAKE_BINARY_DIR}/deps/ensmallen-[0-9]*.[0-9]*.[0-9]*")
|
||||
list(FILTER ENS_DIRECTORIES EXCLUDE REGEX "ensmallen-.*\.tar\.gz")
|
||||
# list(FILTER) is not available on 3.5 or older, but try to keep
|
||||
# configuring without filtering the list anyway (it might work if only
|
||||
# the file ensmallen-latest.tar.gz is present.
|
||||
if (${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.6.0")
|
||||
list(FILTER ENS_DIRECTORIES EXCLUDE REGEX "ensmallen-.*\.tar\.gz")
|
||||
endif ()
|
||||
list(LENGTH ENS_DIRECTORIES ENS_DIRECTORIES_LEN)
|
||||
if (ENS_DIRECTORIES_LEN EQUAL 1)
|
||||
list(GET ENS_DIRECTORIES 0 ENSMALLEN_INCLUDE_DIR)
|
||||
@@ -453,6 +415,9 @@ endif ()
|
||||
# Unfortunately this configuration variable is necessary and will need to be
|
||||
# updated as time goes on and new versions are released.
|
||||
set(Boost_ADDITIONAL_VERSIONS
|
||||
"1.72.0" "1.72"
|
||||
"1.71.0" "1.71"
|
||||
"1.70.0" "1.70"
|
||||
"1.69.0" "1.69"
|
||||
"1.68.0" "1.68"
|
||||
"1.67.0" "1.67"
|
||||
@@ -464,23 +429,14 @@ set(Boost_ADDITIONAL_VERSIONS
|
||||
"1.61.1" "1.61.0" "1.61"
|
||||
"1.60.1" "1.60.0" "1.60"
|
||||
"1.59.1" "1.59.0" "1.59"
|
||||
"1.58.1" "1.58.0" "1.58"
|
||||
"1.57.1" "1.57.0" "1.57"
|
||||
"1.56.1" "1.56.0" "1.56"
|
||||
"1.55.1" "1.55.0" "1.55"
|
||||
"1.54.1" "1.54.0" "1.54"
|
||||
"1.53.1" "1.53.0" "1.53"
|
||||
"1.52.1" "1.52.0" "1.52"
|
||||
"1.51.1" "1.51.0" "1.51"
|
||||
"1.50.1" "1.50.0" "1.50"
|
||||
"1.49.1" "1.49.0" "1.49")
|
||||
"1.58.1" "1.58.0" "1.58")
|
||||
# Disable forced config-mode CMake search for Boost, which only imports targets
|
||||
# and does not set the variables that we need.
|
||||
#
|
||||
# TODO for the brave: transition all mlpack's CMake to 'target-based modern
|
||||
# CMake'. Good luck! You'll need it.
|
||||
set(Boost_NO_BOOST_CMAKE 1)
|
||||
find_package(Boost 1.49
|
||||
find_package(Boost 1.58
|
||||
COMPONENTS
|
||||
program_options
|
||||
unit_test_framework
|
||||
|
||||
@@ -28,3 +28,49 @@ Members of the Contributors team are encouraged to review pull requests that
|
||||
have already been reviewed, and pull request contributors are encouraged to seek
|
||||
multiple reviews. Reviews from anyone not on the Contributors team are always
|
||||
appreciated and encouraged!
|
||||
|
||||
## Reviewing Pull Requests
|
||||
|
||||
All mlpack contributors who choose to review and provide feedback on pull
|
||||
requests have a responsibility to both the project and the individual making
|
||||
the contribution.
|
||||
|
||||
Reviews and feedback should be
|
||||
[helpful, insightful, and geared towards improving the contribution](
|
||||
https://www.youtube.com/watch?v=NNXk_WJzyMI).
|
||||
If there are reasons why you feel the PR should not be merged, explain
|
||||
what those are. Be open to having your mind changed. Be open to
|
||||
working with the contributor to make the pull request better.
|
||||
|
||||
Please don't leave dismissive or disrespectful reviews! It's not helpful for
|
||||
anyone.
|
||||
|
||||
When reviewing a pull request, the primary goals are:
|
||||
|
||||
- For the codebase/project to improve
|
||||
- For the person submitting the request to succeed
|
||||
|
||||
Even if a pull request does not get merged, the submitters should come away
|
||||
from the experience feeling like their effort was not wasted or unappreciated.
|
||||
Every pull request from a new contributor is an opportunity to grow the community.
|
||||
|
||||
When changes are necessary, request them, do not demand them, and do not assume
|
||||
that the contributor already knows how to do that. Be there to lend a helping
|
||||
hand in case of need.
|
||||
|
||||
Since there can sometimes be a lot more pull requests being opened than
|
||||
reviewed, we highly encourage everyone to review each others pull request
|
||||
keeping in mind all the above mentioned points.
|
||||
|
||||
Let's welcome new contributors with ❤️.
|
||||
|
||||
## Pull Request Waiting Time
|
||||
|
||||
mlpack is a community-driven project, so everyone only works on it in their
|
||||
free time; this means it may take some time for them to review pull requests.
|
||||
While gentle reminders are welcome, please be patient and avoid constantly
|
||||
messaging contributors or tagging them on pull requests.
|
||||
|
||||
Typically small PRs will be reviewed within a handful of days; larger PRs might
|
||||
take a few weeks for an initial review, and it may be a little bit longer in
|
||||
times of high activity.
|
||||
|
||||
@@ -128,6 +128,9 @@ Copyright:
|
||||
Copyright 2020, Sriram S K <sriramsk1999@gmail.com>
|
||||
Copyright 2020, Manoranjan Kumar Bharti ( Nakul Bharti ) <knakul853@gmail.com>
|
||||
Copyright 2020, Saraansh Tandon <saraanshtandon1999@gmail.com>
|
||||
Copyright 2020, Gaurav Singh <gs8763076@gmail.com>
|
||||
Copyright 2020, Lakshya Ojha <ojhalakshya@gmail.com>
|
||||
Copyright 2020, Bisakh Mondal <bisakhmondal00@gmail.com>
|
||||
|
||||
License: BSD-3-clause
|
||||
All rights reserved.
|
||||
|
||||
+34
-4
@@ -1,10 +1,14 @@
|
||||
### mlpack ?.?.?
|
||||
###### ????-??-??
|
||||
* Templated return type of `Forward function` of loss functions (#2339).
|
||||
|
||||
* Added `R2 Score` regression metric (#2323).
|
||||
|
||||
* Added `mean squared logarithmic error` loss function for neural networks
|
||||
(#2210).
|
||||
|
||||
|
||||
* Added `mean bias loss function` for neural networks (#2210).
|
||||
|
||||
|
||||
* The DecisionStump class has been marked deprecated; use the `DecisionTree`
|
||||
class with `NoRecursion=true` or use `ID3DecisionStump` instead (#2099).
|
||||
|
||||
@@ -25,12 +29,18 @@
|
||||
* Add functions to access parameters of `Convolution` and `AtrousConvolution`
|
||||
layers (#1985).
|
||||
|
||||
* Add Compute Error function in lars regression and changing Train function to
|
||||
return computed error (#2139).
|
||||
|
||||
* Add Julia bindings (#1949). Build settings can be controlled with the
|
||||
`BUILD_JULIA_BINDINGS=(ON/OFF)` and `JULIA_EXECUTABLE=/path/to/julia` CMake
|
||||
parameters.
|
||||
|
||||
* CMake fix for finding STB include directory (#2145).
|
||||
|
||||
* Add bindings for loading and saving images (#2019); `mlpack_image_converter`
|
||||
from the command-line, `mlpack.image_converter()` from Python.
|
||||
|
||||
* Add normalization support for CF binding (#2136).
|
||||
|
||||
* Add Mish activation function (#2158).
|
||||
@@ -42,12 +52,32 @@
|
||||
|
||||
* Better error handling of eigendecompositions and Cholesky decompositions
|
||||
(#2088, #1840).
|
||||
|
||||
|
||||
* Add LiSHT activation function (#2182).
|
||||
|
||||
* Add Valid and Same Padding for Transposed Convolution layer (#2163).
|
||||
|
||||
* Add CELU activation function (#2191)
|
||||
|
||||
* Add Log-Hyperbolic-Cosine Loss function (#2207).
|
||||
* Add Log-Hyperbolic-Cosine Loss function (#2207)
|
||||
|
||||
* Change neural network types to avoid unnecessary use of rvalue references
|
||||
(#2259).
|
||||
|
||||
* Bump minimum Boost version to 1.58 (#2305).
|
||||
|
||||
* Refactor STB support so HAS_STB macro is not needed when compiling against
|
||||
mlpack (#2312).
|
||||
|
||||
* Add Hard Shrink Activation Function (#2186).
|
||||
|
||||
* Add Soft Shrink Activation Function (#2174).
|
||||
|
||||
* Add Hinge Embedding Loss Function (#2229).
|
||||
|
||||
* Add Cosine Embedding Loss Function (#2209).
|
||||
|
||||
* Add Margin Ranking Loss Function (#2264).
|
||||
|
||||
### mlpack 3.2.2
|
||||
###### 2019-11-26
|
||||
|
||||
@@ -17,6 +17,7 @@ src="https://cdn.rawgit.com/mlpack/mlpack.org/e7d36ed8/mlpack-black.svg" style="
|
||||
<a href="http://ci.mlpack.org/job/mlpack%20-%20git%20commit%20test/"><img src="https://img.shields.io/jenkins/build.svg?jobUrl=http%3A%2F%2Fci.mlpack.org%2Fjob%2Fmlpack%2520-%2520git%2520commit%2520test%2F&label=Linux%20build&style=flat-square" alt="Jenkins"></a>
|
||||
<a href="https://coveralls.io/github/mlpack/mlpack?branch=master"><img src="https://img.shields.io/coveralls/mlpack/mlpack/master.svg?style=flat-square" alt="Coveralls"></a>
|
||||
<a href="https://opensource.org/licenses/BSD-3-Clause"><img src="https://img.shields.io/badge/License-BSD%203--Clause-blue.svg?style=flat-square" alt="License"></a>
|
||||
<a href="http://numfocus.org/donate-to-mlpack"><img src="https://img.shields.io/badge/sponsored%20by-NumFOCUS-orange.svg?style=flat-square&colorA=E1523D&colorB=007D8A" alt="NumFOCUS"></a>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
@@ -33,6 +34,8 @@ functions as a "swiss army knife" for machine learning researchers. In addition
|
||||
to its powerful C++ interface, mlpack also provides command-line programs,
|
||||
Python bindings, and Julia bindings.
|
||||
|
||||
[//]: # (numfocus-fiscal-sponsor-attribution)
|
||||
|
||||
mlpack uses an [open governance model](./GOVERNANCE.md) and is fiscally
|
||||
sponsored by [NumFOCUS](https://numfocus.org/). Consider making a
|
||||
[tax-deductible donation](https://numfocus.org/donate-to-mlpack) to help the
|
||||
@@ -40,7 +43,7 @@ project pay for developer time, professional services, travel, workshops, and a
|
||||
variety of other needs.
|
||||
|
||||
<div align="center">
|
||||
<a href="https://numfocus.org/donate-to-mlpack">
|
||||
<a href="https://numfocus.org/">
|
||||
<img height="60px"
|
||||
src="https://raw.githubusercontent.com/numfocus/templates/master/images/numfocus-logo.png"
|
||||
align="center">
|
||||
@@ -97,11 +100,11 @@ Citations are beneficial for the growth and improvement of mlpack.
|
||||
|
||||
mlpack has the following dependencies:
|
||||
|
||||
Armadillo >= 8.400.0
|
||||
Armadillo >= 8.400.0
|
||||
Boost (program_options, math_c99, unit_test_framework, serialization,
|
||||
spirit)
|
||||
CMake >= 3.3.2
|
||||
ensmallen >= 2.10.0
|
||||
spirit) >= 1.58.0
|
||||
CMake >= 3.3.2
|
||||
ensmallen >= 2.10.0
|
||||
|
||||
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
|
||||
|
||||
+1
-1
@@ -79,7 +79,7 @@ system and have headers present:
|
||||
|
||||
- Armadillo >= 8.400.0 (with LAPACK support)
|
||||
- Boost (math_c99, program_options, serialization, unit_test_framework, heap,
|
||||
spirit) >= 1.49
|
||||
spirit) >= 1.58
|
||||
- ensmallen >= 2.10.0 (will be downloaded if not found)
|
||||
|
||||
In addition, mlpack has the following optional dependencies:
|
||||
|
||||
@@ -118,7 +118,7 @@ compiler version, check if the Visual Studio compiler and Windows SDK are instal
|
||||
- Run cmake:
|
||||
|
||||
@code
|
||||
cmake -G "Visual Studio 16 2019" -A x64 -DBLAS_LIBRARY:FILEPATH="C:/mlpack/mlpack/packages/OpenBLAS.0.2.14.1/lib/native/lib/x64/libopenblas.dll.a" -DLAPACK_LIBRARY:FILEPATH="C:/mlpack/mlpack/packages/OpenBLAS.0.2.14.1/lib/native/lib/x64/libopenblas.dll.a" -DARMADILLO_INCLUDE_DIR="C:/mlpack/armadillo/include" -DARMADILLO_LIBRARY:FILEPATH="C:/mlpack/armadillo/build/Debug/armadillo.lib" -DBOOST_INCLUDEDIR:PATH="C:/boost/" -DBOOST_LIBRARYDIR:PATH="C:/boost/lib64-msvc-14.2" -DDEBUG=OFF -DPROFILE=OFF ..
|
||||
cmake -G "Visual Studio 16 2019" -A x64 -DBLAS_LIBRARIES:FILEPATH="C:/mlpack/mlpack/packages/OpenBLAS.0.2.14.1/lib/native/lib/x64/libopenblas.dll.a" -DLAPACK_LIBRARIES:FILEPATH="C:/mlpack/mlpack/packages/OpenBLAS.0.2.14.1/lib/native/lib/x64/libopenblas.dll.a" -DARMADILLO_INCLUDE_DIR="C:/mlpack/armadillo/include" -DARMADILLO_LIBRARY:FILEPATH="C:/mlpack/armadillo/build/Debug/armadillo.lib" -DBOOST_INCLUDEDIR:PATH="C:/boost/" -DBOOST_LIBRARYDIR:PATH="C:/boost/lib64-msvc-14.2" -DDEBUG=OFF -DPROFILE=OFF ..
|
||||
@endcode
|
||||
|
||||
@note cmake will attempt to automatically download the ensmallen dependency. If for some reason cmake can't download the dependency, you will need to manually download ensmallen from http://ensmallen.org/ and extract it to "C:\mlpack\mlpack\deps\". Then, specify the path to ensmallen using the flag: -DENSMALLEN_INCLUDE_DIR=C:/mlpack/mlpack/deps/ensmallen/include
|
||||
|
||||
+31
-25
@@ -330,39 +330,46 @@ mlpack's image saving/loading functionality is based on [stb/](https://github.co
|
||||
|
||||
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.
|
||||
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.
|
||||
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 the matrix as (width * height * channels, NumberOfImages).
|
||||
Therefore @c imageMatrix.col(0) would be the first image if images are loaded in
|
||||
@c imageMatrix.
|
||||
|
||||
@section imageinfo_api_imagetut Accessing Metadata of Images: ImageInfo
|
||||
|
||||
ImageInfo class contains the metadata of the images.
|
||||
@code
|
||||
ImageInfo(const size_t width,
|
||||
const size_t height,
|
||||
const size_t channels);
|
||||
const size_t height,
|
||||
const size_t channels,
|
||||
const size_t quality = 90);
|
||||
@endcode
|
||||
Other public memebers include:
|
||||
- flipVertical Flip the image vertical upon loading.
|
||||
- quality Compression of the image if saved as jpg (0-100).
|
||||
|
||||
The @c quality member denotes the compression of the image if it is saved as
|
||||
`jpg`; it takes values from 0 to 100.
|
||||
|
||||
@section load_api_imagetut Loading Images in C++
|
||||
|
||||
|
||||
Standalone loading of images.
|
||||
|
||||
@code
|
||||
template<typename eT>
|
||||
bool Load(const std::string& filename,
|
||||
arma::Mat<eT>& matrix,
|
||||
ImageInfo& info,
|
||||
const bool fatal,
|
||||
const bool transpose);
|
||||
template<typename eT>
|
||||
bool Load(const std::string& filename,
|
||||
arma::Mat<eT>& matrix,
|
||||
ImageInfo& info,
|
||||
const bool fatal);
|
||||
@endcode
|
||||
|
||||
Loading a test image. It also fills up the ImageInfo class object.
|
||||
The example below loads a test image. It also fills up the ImageInfo class
|
||||
object.
|
||||
|
||||
@code
|
||||
data::ImageInfo info;
|
||||
data::Load("test_image.png", matrix, info, false, true);
|
||||
data::Load("test_image.png", matrix, info, false);
|
||||
@endcode
|
||||
|
||||
ImageInfo requires height, width, number of channels of the image.
|
||||
@@ -377,18 +384,17 @@ More than one image can be loaded into the same matrix.
|
||||
Loading multiple images:
|
||||
|
||||
@code
|
||||
template<typename eT>
|
||||
bool Load(const std::vector<std::string>& files,
|
||||
arma::Mat<eT>& matrix,
|
||||
ImageInfo& info,
|
||||
const bool fatal,
|
||||
const bool transpose);
|
||||
template<typename eT>
|
||||
bool Load(const std::vector<std::string>& files,
|
||||
arma::Mat<eT>& matrix,
|
||||
ImageInfo& info,
|
||||
const bool fatal);
|
||||
@endcode
|
||||
|
||||
@code
|
||||
data::ImageInfo info;
|
||||
std::vector<std::string>> files{"test_image1.bmp","test_image2.bmp"};
|
||||
data::load(files, matrix, info, false, true);
|
||||
data::ImageInfo info;
|
||||
std::vector<std::string>> files{"test_image1.bmp","test_image2.bmp"};
|
||||
data::Load(files, matrix, info, false);
|
||||
@endcode
|
||||
|
||||
@section save_api_imagetut Saving Images in C++
|
||||
|
||||
+61
-27
@@ -204,17 +204,17 @@ using namespace mlpack::ann;
|
||||
|
||||
int main()
|
||||
{
|
||||
// Load the training set.
|
||||
arma::mat dataset;
|
||||
data::Load("thyroid_train.csv", dataset, true);
|
||||
// Load the training set and testing set.
|
||||
arma::mat trainData;
|
||||
data::Load("thyroid_train.csv", trainData, true);
|
||||
arma::mat testData;
|
||||
data::Load("thyroid_test.csv", testData, true);
|
||||
|
||||
// Split the labels from the training set.
|
||||
arma::mat trainData = dataset.submat(0, 0, dataset.n_rows - 4,
|
||||
dataset.n_cols - 1);
|
||||
|
||||
// Split the data from the training set.
|
||||
arma::mat trainLabels = dataset.submat(dataset.n_rows - 3, 0,
|
||||
dataset.n_rows - 1, dataset.n_cols - 1);
|
||||
// Split the labels from the training set and testing set respectively.
|
||||
arma::mat trainLabels = trainData.row(trainData.n_rows - 1);
|
||||
arma::mat testLabels = testData.row(testData.n_rows - 1);
|
||||
trainData.shed_row(trainData.n_rows - 1);
|
||||
testData.shed_row(testData.n_rows - 1);
|
||||
|
||||
// Initialize the network.
|
||||
FFN<> model;
|
||||
@@ -226,14 +226,48 @@ int main()
|
||||
// Train the model.
|
||||
model.Train(trainData, trainLabels);
|
||||
|
||||
// Use the Predict method to get the assignments.
|
||||
arma::mat assignments;
|
||||
model.Predict(trainData, assignments);
|
||||
// Use the Predict method to get the predictions.
|
||||
arma::mat predictionTemp;
|
||||
model.Predict(testData, predictionTemp);
|
||||
|
||||
/*
|
||||
Since the predictionsTemp is of dimensions (3 x number_of_data_points)
|
||||
with continuous values, we first need to reduce it to a dimension of
|
||||
(1 x number_of_data_points) with scalar values, to be able to compare with
|
||||
testLabels.
|
||||
|
||||
The first step towards doing this is to create a matrix of zeros with the
|
||||
desired dimensions (1 x number_of_data_points).
|
||||
|
||||
In predictionsTemp, the 3 dimensions for each data point correspond to the
|
||||
probabilities of belonging to the three possible classes.
|
||||
*/
|
||||
arma::mat prediction = arma::zeros<arma::mat>(1, predictionTemp.n_cols);
|
||||
|
||||
// Find index of max prediction for each data point and store in "prediction"
|
||||
for (size_t i = 0; i < predictionTemp.n_cols; ++i)
|
||||
{
|
||||
// we add 1 to the max index, so that it matches the actual test labels.
|
||||
prediction(i) = arma::as_scalar(arma::find(
|
||||
arma::max(predictionTemp.col(i)) == predictionTemp.col(i), 1)) + 1;
|
||||
}
|
||||
|
||||
/*
|
||||
Compute the error between predictions and testLabels,
|
||||
now that we have the desired predictions.
|
||||
*/
|
||||
size_t correct = arma::accu(prediction == testLabels);
|
||||
double classificationError = 1 - double(correct) / testData.n_cols;
|
||||
|
||||
// Print out the classification error for the testing dataset.
|
||||
std::cout << "Classification Error for the Test set: " << classificationError << std::endl;
|
||||
return 0;
|
||||
}
|
||||
@endcode
|
||||
|
||||
Now, the matrix assignments holds the classification of each point in the
|
||||
dataset.
|
||||
Now, the matrix prediction holds the classification of each point in the
|
||||
dataset. Subsequently, we find the classification error by comparing it
|
||||
with testLabels.
|
||||
|
||||
In the next example, we create simple noisy sine sequences, which are trained
|
||||
later on, using the RNN class in the `RNNModel()` method.
|
||||
@@ -328,7 +362,7 @@ implementation of a \c Forward() method. The interface looks like:
|
||||
|
||||
@code
|
||||
template<typename eT>
|
||||
void Forward(const arma::Mat<eT>&& input, arma::Mat<eT>&& output);
|
||||
void Forward(const arma::Mat<eT>& input, arma::Mat<eT>& output);
|
||||
@endcode
|
||||
|
||||
The method should calculate the output of the layer given the input matrix and
|
||||
@@ -339,9 +373,9 @@ through f:
|
||||
|
||||
@code
|
||||
template<typename eT>
|
||||
void Backward(const arma::Mat<eT>&& input,
|
||||
arma::Mat<eT>&& gy,
|
||||
arma::Mat<eT>&& g);
|
||||
void Backward(const arma::Mat<eT>& input,
|
||||
const arma::Mat<eT>& gy,
|
||||
arma::Mat<eT>& g);
|
||||
@endcode
|
||||
|
||||
Finally, if the layer is differentiable, the layer must also implement
|
||||
@@ -349,9 +383,9 @@ a Gradient() method:
|
||||
|
||||
@code
|
||||
template<typename eT>
|
||||
void Gradient(const arma::Mat<eT>&& input,
|
||||
arma::Mat<eT>&& error,
|
||||
arma::Mat<eT>&& gradient);
|
||||
void Gradient(const arma::Mat<eT>& input,
|
||||
const arma::Mat<eT>& error,
|
||||
arma::Mat<eT>& gradient);
|
||||
@endcode
|
||||
|
||||
The Gradient function should calculate the gradient with respect to the input
|
||||
@@ -434,21 +468,21 @@ API, so we must implement some additional functions.
|
||||
|
||||
@code
|
||||
template<typename InputType, typename OutputType>
|
||||
void Forward(const InputType&& input, OutputType&& output)
|
||||
void Forward(const InputType& input, OutputType& output)
|
||||
{
|
||||
output = arma::ones(input.n_rows, input.n_cols);
|
||||
}
|
||||
|
||||
template<typename InputType, typename ErrorType, typename GradientType>
|
||||
void Backward(const InputType&& input, ErrorType&& gy, GradientType&& g)
|
||||
void Backward(const InputType& input, const ErrorType& gy, GradientType& g)
|
||||
{
|
||||
g = arma::zeros(gy.n_rows, gy.n_cols) + gy;
|
||||
}
|
||||
|
||||
template<typename InputType, typename ErrorType, typename GradientType>
|
||||
void Gradient(const InputType&& input,
|
||||
ErrorType&& error,
|
||||
GradientType&& gradient)
|
||||
void Gradient(const InputType& input,
|
||||
ErrorType& error,
|
||||
GradientType& gradient)
|
||||
{
|
||||
gradient = arma::zeros(input.n_rows, input.n_cols) * error;
|
||||
}
|
||||
|
||||
@@ -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<typename eT>
|
||||
bool Load(const std::string& filename,
|
||||
arma::Mat<eT>& 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<typename eT>
|
||||
bool Load(const std::vector<std::string>& files,
|
||||
arma::Mat<eT>& matrix,
|
||||
ImageInfo& info,
|
||||
const bool fatal,
|
||||
const bool transpose);
|
||||
@endcode
|
||||
|
||||
@code
|
||||
data::ImageInfo info;
|
||||
std::vector<std::string>> 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<typename eT>
|
||||
bool Save(const std::string& filename,
|
||||
arma::Mat<eT>& 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<typename eT>
|
||||
bool Save(const std::vector<std::string>& files,
|
||||
arma::Mat<eT>& 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<std::string>> 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.
|
||||
|
||||
*/
|
||||
@@ -0,0 +1,399 @@
|
||||
/*!
|
||||
@file rl.txt
|
||||
@author Sriram S K
|
||||
@author Joel Joseph
|
||||
@brief Tutorial for how to use the Reinforcement Learning module in mlpack.
|
||||
|
||||
@page rltutorial Reinforcement Learning Tutorial
|
||||
|
||||
@section intro_rltut Introduction
|
||||
|
||||
Reinforcement Learning is one of the hottest topics right now, with
|
||||
interest surging after DeepMind published their article on training
|
||||
deep neural networks to play Atari games to great success. mlpack
|
||||
implements a complete end-to-end framework for Reinforcement Learning,
|
||||
featuring multiple environments, policies and methods. Of course,
|
||||
custom environments and policies can be used and plugged into the
|
||||
existing framework with no runtime overhead.
|
||||
|
||||
mlpack implements typical benchmark environments (Acrobot, Mountain car etc.),
|
||||
commonly used policies, replay methods and supports asynchronous
|
||||
learning as well. In addition, it can [communicate](https://github.com/zoq/gym_tcp_api)
|
||||
with the OpenAI Gym toolkit for more environments.
|
||||
|
||||
@section toc_rltut Table of Contents
|
||||
|
||||
This tutorial is split into the following sections:
|
||||
|
||||
- \ref intro_rltut
|
||||
- \ref toc_rltut
|
||||
- \ref environment_rltut
|
||||
- \ref agent_components_rltut
|
||||
- \ref q_learning_rltut
|
||||
- \ref async_learning_rltut
|
||||
- \ref further_rltut
|
||||
|
||||
@section environment_rltut Reinforcement Learning Environments
|
||||
|
||||
mlpack implements a number of the most popular environments used for testing
|
||||
RL agents and algorithms. These include the Cart Pole, Acrobot, Mountain Car
|
||||
and their variations. Of course, as mentioned above, you can communicate with
|
||||
OpenAI Gym for other environments, like the Atari video games.
|
||||
|
||||
A key component of mlpack is its extensibility. It is a simple process to create
|
||||
your own custom environments, specific to your needs, and use it with mlpack's
|
||||
RL framework. All the environments implement a few specific methods and classes
|
||||
which are used by the agents while learning.
|
||||
|
||||
- \c State: The State class is a representation of the environment. For the CartPole,
|
||||
this would involve storing the position, velocity, angle and angular velocity.
|
||||
|
||||
- \c Action: It is an enum naming all the possible actions the agent can take in the
|
||||
environment. Continuing with the CartPole example, the Action enum would simply
|
||||
contain the two possible actions, backward and forward.
|
||||
|
||||
- \c Sample: This method is perhaps the heart of the environment, providing rewards to
|
||||
the agent depending on the state and the action taken, and updates the state based on
|
||||
the action taken as well.
|
||||
|
||||
Of course, your custom environment will most likely make use of a number of helper methods, depending
|
||||
on your application, such as the \c Dsdt method in the \c Acrobot environment, used in the \c RK4
|
||||
iterative method (also another helper method) to estimate the next state.
|
||||
|
||||
@section agent_components_rltut Components of an RL Agent
|
||||
|
||||
A Reinforcement Learning agent, in general, takes actions in an environment in order
|
||||
to maximize a cumulative reward. To that end, it requires a way to choose actions (\b policy)
|
||||
and a way to sample previous experiences (\b replay).
|
||||
|
||||
An example of a simple policy would be an epsilon-greedy policy. Using such a policy, the agent
|
||||
will choose actions greedily with some probability epsilon. This probability is slowly decreased
|
||||
over time, balancing the line between exploration and exploitation.
|
||||
|
||||
Similarly, an example of a simple replay would be a random replay. At each time step, the
|
||||
interactions between the agent and the environment are saved to a memory buffer and previous
|
||||
experiences are sampled from the buffer to train the agent.
|
||||
|
||||
Instantiating the components of an agent can be easily done by passing the Environment as
|
||||
a templated argument and the parameters of the policy/replay to the constructor.
|
||||
|
||||
To create a Greedy Policy and Prioritized Replay for the CartPole environment, we would do the
|
||||
following:
|
||||
|
||||
@code
|
||||
GreedyPolicy<CartPole> policy(1.0, 1000, 0.1);
|
||||
PrioritizedReplay<CartPole> replayMethod(10, 10000, 0.6);
|
||||
@endcode
|
||||
|
||||
The arguments to `policy` are the initial epsilon values, the interval of decrease in its value
|
||||
and the value at which epsilon bottoms out and won't be reduced further. The arguments to
|
||||
`replayMethod` are size of the batch returned, the number of examples stored in memory, and the
|
||||
degree of prioritization.
|
||||
|
||||
In addition to the above components, an RL agent requires many hyperparameters to be tuned during
|
||||
it's training period. These parameters include everything from the discount rate of the future
|
||||
reward to whether Double Q-learning should be used or not. The `TrainingConfig` class can be
|
||||
instantiated and configured as follows:
|
||||
|
||||
@code
|
||||
TrainingConfig config;
|
||||
config.StepSize() = 0.01;
|
||||
config.Discount() = 0.9;
|
||||
config.TargetNetworkSyncInterval() = 100;
|
||||
config.ExplorationSteps() = 100;
|
||||
config.DoubleQLearning() = false;
|
||||
config.StepLimit() = 200;
|
||||
@endcode
|
||||
|
||||
The object `config` describes an RL agent, using a step size of 0.01 for the optimization process,
|
||||
a discount factor of 0.9, sync interval of 200 episodes. This agent only starts learning after storing
|
||||
100 exploration steps, has a step limit of 200, and does not utilize double q-learning.
|
||||
|
||||
In this way, we can easily configure an RL agent with the desired hyperparameters.
|
||||
|
||||
@section q_learning_rltut Q-Learning in mlpack
|
||||
|
||||
Here, we demonstrate Q-Learning in mlpack through the use of a simple example, the training of a Q-Learning
|
||||
agent on the CartPole environment. The code has been broken into chunks for easy understanding.
|
||||
|
||||
@code
|
||||
#include <mlpack/core.hpp>
|
||||
#include <mlpack/methods/ann/ffn.hpp>
|
||||
#include <mlpack/methods/ann/init_rules/gaussian_init.hpp>
|
||||
#include <mlpack/methods/ann/layer/layer.hpp>
|
||||
#include <mlpack/methods/ann/loss_functions/mean_squared_error.hpp>
|
||||
#include <mlpack/methods/reinforcement_learning/q_learning.hpp>
|
||||
#include <mlpack/methods/reinforcement_learning/environment/cart_pole.hpp>
|
||||
#include <mlpack/methods/reinforcement_learning/policy/greedy_policy.hpp>
|
||||
#include <mlpack/methods/reinforcement_learning/training_config.hpp>
|
||||
#include <ensmallen.hpp>
|
||||
|
||||
using namespace mlpack;
|
||||
using namespace mlpack::ann;
|
||||
using namespace ens;
|
||||
using namespace mlpack::rl;
|
||||
@endcode
|
||||
|
||||
We include all the necessary components of our toy example and declare namespaces for convenience.
|
||||
|
||||
@code
|
||||
int main()
|
||||
{
|
||||
// Set up the network.
|
||||
FFN<MeanSquaredError<>, GaussianInitialization> model(MeanSquaredError<>(),
|
||||
GaussianInitialization(0, 0.001));
|
||||
model.Add<Linear<>>(4, 128);
|
||||
model.Add<ReLULayer<>>();
|
||||
model.Add<Linear<>>(128, 128);
|
||||
model.Add<ReLULayer<>>();
|
||||
model.Add<Linear<>>(128, 2);
|
||||
|
||||
@endcode
|
||||
|
||||
The first step in setting our Q-learning agent is to setup the network for it to use. Here,
|
||||
we use mlpack's ann module to setup a simple FFN network, consisting of a single hidden layer.
|
||||
|
||||
@note
|
||||
The network constructed here has an input shape of 4 and output shape of 2. This corresponds to
|
||||
the structure of the CartPole environment, where each state is represented as a column vector with
|
||||
4 data members (position, velocity, angle, angular velocity). Similarly, the output shape is represented
|
||||
by the number of possible actions, which in this case, is only 2 (foward and backward).
|
||||
|
||||
The next step would be to setup the other components of the Q-learning agent, namely its policy, replay
|
||||
method and hyperparameters.
|
||||
|
||||
@code
|
||||
// Set up the policy and replay method.
|
||||
GreedyPolicy<CartPole> policy(1.0, 1000, 0.1, 0.99);
|
||||
RandomReplay<CartPole> replayMethod(10, 10000);
|
||||
|
||||
TrainingConfig config;
|
||||
config.StepSize() = 0.01;
|
||||
config.Discount() = 0.9;
|
||||
config.TargetNetworkSyncInterval() = 100;
|
||||
config.ExplorationSteps() = 100;
|
||||
config.DoubleQLearning() = false;
|
||||
config.StepLimit() = 200;
|
||||
@endcode
|
||||
|
||||
And now, we get to the heart of the program, declaring a Q-Learning agent.
|
||||
|
||||
@code
|
||||
QLearning<CartPole, decltype(model), AdamUpdate, decltype(policy)>
|
||||
agent(std::move(config), std::move(model), std::move(policy),
|
||||
std::move(replayMethod));
|
||||
@endcode
|
||||
|
||||
Here, we call the `QLearning` constructor, passing in the type of environment,
|
||||
network, updater, policy and replay. We use `decltype(var)` as a shorthand for
|
||||
the variable, saving us the trouble of copying the lengthy templated type.
|
||||
|
||||
Similarly, `std::move` is called for convenience, moving the components instead of
|
||||
duplicating them and copying them over.
|
||||
|
||||
We have our Q-Learning agent `agent` ready to be trained on the Cart Pole environment.
|
||||
|
||||
@code
|
||||
arma::running_stat<double> averageReturn;
|
||||
size_t episodes = 0;
|
||||
bool converged = true;
|
||||
while (true)
|
||||
{
|
||||
double episodeReturn = agent.Episode();
|
||||
averageReturn(episodeReturn);
|
||||
episodes += 1;
|
||||
|
||||
if (episodes > 1000)
|
||||
{
|
||||
std::cout << "Cart Pole with DQN failed." << std::endl;
|
||||
converged = false;
|
||||
break;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reaching running average return 35 is enough to show it works.
|
||||
*/
|
||||
std::cout << "Average return: " << averageReturn.mean()
|
||||
<< " Episode return: " << episodeReturn << std::endl;
|
||||
if (averageReturn.mean() > 35)
|
||||
break;
|
||||
}
|
||||
if (converged)
|
||||
std::cout << "Hooray! Q-Learning agent successfully trained" << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@endcode
|
||||
|
||||
We set up a loop to train the agent. The exit condition is determined by the average
|
||||
reward which can be computed with `arma::running_stat`. It is used for storing running
|
||||
statistics of scalars, which in this case is the reward signal. The agent can be said
|
||||
to have converged when the average return reaches a predetermined value (i.e. > 35).
|
||||
|
||||
Conversely, if the average return does not go beyond that amount even after a thousand
|
||||
episodes, we can conclude that the agent will not converge and exit the training loop.
|
||||
|
||||
@section async_learning_rltut
|
||||
|
||||
In 2016, Researchers at Deepmind and University of Montreal published their paper
|
||||
"Asynchronous Methods for Deep Reinforcement Learning". In it they described asynchronous
|
||||
variants of four standard reinforcement learning algorithms:
|
||||
- One-Step SARSA
|
||||
- One-Step Q-Learning
|
||||
- N-Step Q-Learning
|
||||
- Advantage Actor-Critic(A3C)
|
||||
|
||||
Online RL algorithms and Deep Neural Networks make an unstable combination because of the
|
||||
non-stationary and correlated nature of online updates. Although this is solved by Experience Replay,
|
||||
it has several drawbacks: it uses more memory and computation per real interaction; and it requires
|
||||
off-policy learning algorithms.
|
||||
|
||||
Asynchronous methods, instead of experience replay, asynchronously executes multiple agents
|
||||
in parallel, on multiple instances of the environment, which solves all the above problems.
|
||||
|
||||
Here, we demonstrate Asynchronous Learning methods in mlpack through the training of an async
|
||||
agent. Asynchronous learning involves training several agents simultaneously. Here, each of the
|
||||
agents are referred to as "workers". Currently mlpack has One-Step Q-Learning worker, N-Step
|
||||
Q-Learning worker and One-Step SARSA worker.
|
||||
|
||||
Let's examine the sample code in chunks.
|
||||
|
||||
Apart from the includes used for the q-learning example, two more have to be included:
|
||||
|
||||
@code
|
||||
#include <mlpack/methods/reinforcement_learning/async_learning.hpp>
|
||||
#include <mlpack/methods/reinforcement_learning/policy/aggregated_policy.hpp>
|
||||
@endcode
|
||||
|
||||
Here we don't use experience replay, and instead of a single policy, we use three different
|
||||
policies, each corresponding to its worker. Number of workers created, depends on the number of
|
||||
policies given in the Aggregated Policy. The column vector contains the probability distribution
|
||||
for each child policy. We should make sure its size is same as the number of policies and the sum
|
||||
of its elements is equal to 1.
|
||||
|
||||
@code
|
||||
AggregatedPolicy<GreedyPolicy<CartPole>> policy({GreedyPolicy<CartPole>(0.7, 5000, 0.1),
|
||||
GreedyPolicy<CartPole>(0.7, 5000, 0.01),
|
||||
GreedyPolicy<CartPole>(0.7, 5000, 0.5)},
|
||||
arma::colvec("0.4 0.3 0.3"));
|
||||
@endcode
|
||||
|
||||
Now, we will create the "OneStepQLearning" agent. We could have used "NStepQLearning" or "OneStepSarsa"
|
||||
here according to our requirement.
|
||||
|
||||
@code
|
||||
OneStepQLearning<CartPole, decltype(model), ens::AdamUpdate, decltype(policy)>
|
||||
agent(std::move(config), std::move(model), std::move(policy));
|
||||
@endcode
|
||||
|
||||
Here, unlike the Q-Learning example, instead of the entire while loop, we use the Train method of the Asynchronous
|
||||
Learning class inside a for loop. 100 training episodes will take around 50 seconds.
|
||||
|
||||
@code
|
||||
for (int i = 0; i < 100; i++)
|
||||
{
|
||||
agent.Train(measure);
|
||||
}
|
||||
@endcode
|
||||
|
||||
What is "measure" here? It is a lambda function which returns a boolean value (indicating the end of training)
|
||||
and accepts the episode return (total reward of a deterministic test episode) as parameter.
|
||||
So, let's create that.
|
||||
|
||||
@code
|
||||
arma::vec returns(20, arma::fill::zeros);
|
||||
size_t position = 0;
|
||||
size_t episode = 0;
|
||||
|
||||
auto measure = [&returns, &position, &episode](double episodeReturn)
|
||||
{
|
||||
if(episode > 10000) return true;
|
||||
|
||||
returns[position++] = episodeReturn;
|
||||
position = position % returns.n_elem;
|
||||
episode++;
|
||||
|
||||
std::cout << "Episode No.: " << episode
|
||||
<< "; Episode Return: " << episodeReturn
|
||||
<< "; Average Return: " << arma::mean(returns) << endl;
|
||||
};
|
||||
@endcode
|
||||
|
||||
This will train three different agents on three CPU threads asynchronously and use this data to update the
|
||||
action value estimate.
|
||||
Voila, thats all there is to it.
|
||||
|
||||
Here is the full code to try this right away:
|
||||
|
||||
@code
|
||||
#include <mlpack/core.hpp>
|
||||
#include <mlpack/methods/ann/ffn.hpp>
|
||||
#include <mlpack/methods/ann/init_rules/gaussian_init.hpp>
|
||||
#include <mlpack/methods/ann/layer/layer.hpp>
|
||||
#include <mlpack/methods/ann/loss_functions/mean_squared_error.hpp>
|
||||
#include <mlpack/methods/reinforcement_learning/async_learning.hpp>
|
||||
#include <mlpack/methods/reinforcement_learning/environment/cart_pole.hpp>
|
||||
#include <mlpack/methods/reinforcement_learning/policy/greedy_policy.hpp>
|
||||
#include <mlpack/methods/reinforcement_learning/policy/aggregated_policy.hpp>
|
||||
#include <mlpack/methods/reinforcement_learning/training_config.hpp>
|
||||
#include <ensmallen.hpp>
|
||||
|
||||
using namespace mlpack;
|
||||
using namespace mlpack::ann;
|
||||
using namespace mlpack::rl;
|
||||
int main()
|
||||
{
|
||||
// Set up the network.
|
||||
FFN<MeanSquaredError<>, GaussianInitialization> model(MeanSquaredError<>(), GaussianInitialization(0, 0.001));
|
||||
model.Add<Linear<>>(4, 128);
|
||||
model.Add<ReLULayer<>>();
|
||||
model.Add<Linear<>>(128, 128);
|
||||
model.Add<ReLULayer<>>();
|
||||
model.Add<Linear<>>(128, 2);
|
||||
|
||||
AggregatedPolicy<GreedyPolicy<CartPole>> policy({GreedyPolicy<CartPole>(0.7, 5000, 0.1),
|
||||
GreedyPolicy<CartPole>(0.7, 5000, 0.01),
|
||||
GreedyPolicy<CartPole>(0.7, 5000, 0.5)},
|
||||
arma::colvec("0.4 0.3 0.3"));
|
||||
|
||||
TrainingConfig config;
|
||||
config.StepSize() = 0.01;
|
||||
config.Discount() = 0.9;
|
||||
config.TargetNetworkSyncInterval() = 100;
|
||||
config.ExplorationSteps() = 100;
|
||||
config.DoubleQLearning() = false;
|
||||
config.StepLimit() = 200;
|
||||
|
||||
OneStepQLearning<CartPole, decltype(model), ens::VanillaUpdate, decltype(policy)>
|
||||
agent(std::move(config), std::move(model), std::move(policy));
|
||||
|
||||
arma::vec returns(20, arma::fill::zeros);
|
||||
size_t position = 0;
|
||||
size_t episode = 0;
|
||||
|
||||
auto measure = [&returns, &position, &episode](double episodeReturn)
|
||||
{
|
||||
if(episode > 10000) return true;
|
||||
|
||||
returns[position++] = episodeReturn;
|
||||
position = position % returns.n_elem;
|
||||
episode++;
|
||||
|
||||
std::cout << "Episode No.: " << episode
|
||||
<< "; Episode Return: " << episodeReturn
|
||||
<< "; Average Return: " << arma::mean(returns) << endl;
|
||||
};
|
||||
|
||||
for (int i = 0; i < 100; i++)
|
||||
{
|
||||
agent.Train(measure);
|
||||
}
|
||||
}
|
||||
@endcode
|
||||
|
||||
@section further_rltut Further documentation
|
||||
|
||||
For further documentation on the rl classes, consult the \ref mlpack::rl
|
||||
"complete API documentation".
|
||||
|
||||
*/
|
||||
@@ -18,10 +18,6 @@ if (BUILD_JULIA_BINDINGS)
|
||||
add_custom_command(TARGET julia PRE_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory
|
||||
${CMAKE_BINARY_DIR}/src/mlpack/bindings/julia/mlpack/src/)
|
||||
add_custom_command(TARGET julia PRE_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/mlpack/REQUIRE
|
||||
${CMAKE_BINARY_DIR}/src/mlpack/bindings/julia/mlpack/REQUIRE)
|
||||
|
||||
add_library(mlpack_julia_util
|
||||
julia_util.h
|
||||
@@ -52,12 +48,16 @@ if (BUILD_JULIA_BINDINGS)
|
||||
configure_file(${CMAKE_SOURCE_DIR}/src/mlpack/bindings/julia/mlpack/cli.jl.in
|
||||
${CMAKE_BINARY_DIR}/src/mlpack/bindings/julia/mlpack/src/cli.jl)
|
||||
|
||||
# Create the empty mlpack.jl file that we will fill with includes.
|
||||
file(WRITE
|
||||
"${CMAKE_BINARY_DIR}/src/mlpack/bindings/julia/mlpack/src/mlpack.jl"
|
||||
"module mlpack\n\n"
|
||||
"module util\n\n"
|
||||
"include(\"cli.jl\")\n")
|
||||
# Create the empty mlpack.jl file that we will fill with includes using the
|
||||
# exsiting template. Unfortunately COPY doesn't let us change the extension
|
||||
# so we need a follow-up RENAME command.
|
||||
file(COPY
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/mlpack/mlpack.jl.in"
|
||||
DESTINATION
|
||||
"${CMAKE_BINARY_DIR}/src/mlpack/bindings/julia/mlpack/src/")
|
||||
file(RENAME
|
||||
"${CMAKE_BINARY_DIR}/src/mlpack/bindings/julia/mlpack/src/mlpack.jl.in"
|
||||
"${CMAKE_BINARY_DIR}/src/mlpack/bindings/julia/mlpack/src/mlpack.jl")
|
||||
|
||||
file(WRITE
|
||||
"${CMAKE_BINARY_DIR}/src/mlpack/bindings/julia/mlpack/src/functions.jl"
|
||||
@@ -150,10 +150,10 @@ if (BUILD_JULIA_BINDINGS)
|
||||
# Append the code to define the function in the module.
|
||||
file(APPEND
|
||||
"${CMAKE_BINARY_DIR}/src/mlpack/bindings/julia/mlpack/src/functions.jl"
|
||||
"${name} = util.${name}\n")
|
||||
"${name} = _Internal.${name}\n")
|
||||
endif ()
|
||||
endmacro ()
|
||||
|
||||
if (BUILD_TESTS)
|
||||
if (BUILD_TESTS AND BUILD_JULIA_BINDINGS)
|
||||
add_subdirectory(tests)
|
||||
endif ()
|
||||
|
||||
@@ -116,11 +116,11 @@ std::string DefaultParamImpl(
|
||||
else if (std::is_same<T, arma::Col<size_t>>::value ||
|
||||
std::is_same<T, arma::Row<size_t>>::value)
|
||||
{
|
||||
return "Int64[]";
|
||||
return "Int[]";
|
||||
}
|
||||
else if (std::is_same<T, arma::Mat<size_t>>::value)
|
||||
{
|
||||
return "zeros(Int64, 0, 0)";
|
||||
return "zeros(Int, 0, 0)";
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -101,9 +101,9 @@ inline std::string GetJuliaType(
|
||||
const typename std::enable_if<arma::is_arma_type<T>::value>::type* = 0)
|
||||
{
|
||||
// size_t matrices are special: we want to represent them in Julia as
|
||||
// Array{Int64, X} not UInt64 because Julia displays UInt64s strangely.
|
||||
// Array{Int, X} not UInt because Julia displays UInts strangely.
|
||||
if (std::is_same<typename T::elem_type, size_t>::value)
|
||||
return std::string("Array{Int64, ") + (T::is_col || T::is_row ? "1" : "2")
|
||||
return std::string("Array{Int, ") + (T::is_col || T::is_row ? "1" : "2")
|
||||
+ "}";
|
||||
else
|
||||
return "Array{" + GetJuliaType<typename T::elem_type>() + ", "
|
||||
|
||||
@@ -47,7 +47,7 @@ std::string GetPrintableType(
|
||||
const typename std::enable_if<util::IsStdVector<T>::value>::type*)
|
||||
{
|
||||
if (std::is_same<T, std::vector<int>>::value)
|
||||
return "Array{Int64, 1}";
|
||||
return "Array{Int, 1}";
|
||||
else if (std::is_same<T, std::vector<std::string>>::value)
|
||||
return "Array{String, 1}";
|
||||
else
|
||||
@@ -65,15 +65,15 @@ std::string GetPrintableType(
|
||||
if (std::is_same<T, arma::mat>::value)
|
||||
return "Float64 matrix-like";
|
||||
else if (std::is_same<T, arma::Mat<size_t>>::value)
|
||||
return "Int64 matrix-like";
|
||||
return "Int matrix-like";
|
||||
else if (std::is_same<T, arma::rowvec>::value)
|
||||
return "Float64 vector-like";
|
||||
else if (std::is_same<T, arma::Row<size_t>>::value)
|
||||
return "Int64 vector-like";
|
||||
return "Int vector-like";
|
||||
else if (std::is_same<T, arma::vec>::value)
|
||||
return "Float64 vector-like";
|
||||
else if (std::is_same<T, arma::Col<size_t>>::value)
|
||||
return "Int64 vector-like";
|
||||
return "Int vector-like";
|
||||
else
|
||||
throw std::invalid_argument("unknown Armadillo type " + data.cppType);
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <mlpack/bindings/julia/julia_util.h>
|
||||
#include <mlpack/prereqs.hpp>
|
||||
#include <mlpack/core/util/cli.hpp>
|
||||
#include <stdint.h>
|
||||
|
||||
using namespace mlpack;
|
||||
|
||||
@@ -82,13 +83,14 @@ void CLI_SetParamVectorStrStr(const char* paramName,
|
||||
* Call CLI::SetParam<std::vector<int>>().
|
||||
*/
|
||||
void CLI_SetParamVectorInt(const char* paramName,
|
||||
uint64_t* ints,
|
||||
int* ints,
|
||||
const size_t length)
|
||||
{
|
||||
// Create a std::vector<int> object; unfortunately this requires copying the
|
||||
// vector elements.
|
||||
std::vector<int> vec(length);
|
||||
for (size_t i = 0; i < (size_t) length; ++i)
|
||||
std::vector<int> vec;
|
||||
vec.resize(length);
|
||||
for (size_t i = 0; i < length; ++i)
|
||||
vec[i] = ints[i];
|
||||
|
||||
CLI::GetParam<std::vector<int>>(paramName) = std::move(vec);
|
||||
@@ -105,7 +107,7 @@ void CLI_SetParamMat(const char* paramName,
|
||||
const bool pointsAsRows)
|
||||
{
|
||||
// Create the matrix as an alias.
|
||||
arma::mat m(memptr, rows, cols, false, true);
|
||||
arma::mat m(memptr, arma::uword(rows), arma::uword(cols), false, true);
|
||||
CLI::GetParam<arma::mat>(paramName) = pointsAsRows ? m.t() : std::move(m);
|
||||
CLI::SetPassed(paramName);
|
||||
}
|
||||
@@ -120,7 +122,8 @@ void CLI_SetParamUMat(const char* paramName,
|
||||
const bool pointsAsRows)
|
||||
{
|
||||
// Create the matrix as an alias.
|
||||
arma::Mat<size_t> m(memptr, rows, cols, false, true);
|
||||
arma::Mat<size_t> m(memptr, arma::uword(rows), arma::uword(cols), false,
|
||||
true);
|
||||
CLI::GetParam<arma::Mat<size_t>>(paramName) = pointsAsRows ? m.t() :
|
||||
std::move(m);
|
||||
CLI::SetPassed(paramName);
|
||||
@@ -133,7 +136,7 @@ void CLI_SetParamRow(const char* paramName,
|
||||
double* memptr,
|
||||
const size_t cols)
|
||||
{
|
||||
arma::rowvec m(memptr, cols, false, true);
|
||||
arma::rowvec m(memptr, arma::uword(cols), false, true);
|
||||
CLI::GetParam<arma::rowvec>(paramName) = std::move(m);
|
||||
CLI::SetPassed(paramName);
|
||||
}
|
||||
@@ -145,7 +148,7 @@ void CLI_SetParamURow(const char* paramName,
|
||||
size_t* memptr,
|
||||
const size_t cols)
|
||||
{
|
||||
arma::Row<size_t> m(memptr, cols, false, true);
|
||||
arma::Row<size_t> m(memptr, arma::uword(cols), false, true);
|
||||
CLI::GetParam<arma::Row<size_t>>(paramName) = std::move(m);
|
||||
CLI::SetPassed(paramName);
|
||||
}
|
||||
@@ -157,7 +160,7 @@ void CLI_SetParamCol(const char* paramName,
|
||||
double* memptr,
|
||||
const size_t rows)
|
||||
{
|
||||
arma::vec m(memptr, rows, false, true);
|
||||
arma::vec m(memptr, arma::uword(rows), false, true);
|
||||
CLI::GetParam<arma::vec>(paramName) = std::move(m);
|
||||
CLI::SetPassed(paramName);
|
||||
}
|
||||
@@ -166,10 +169,10 @@ void CLI_SetParamCol(const char* paramName,
|
||||
* Call CLI::SetParam<arma::Row<size_t>>().
|
||||
*/
|
||||
void CLI_SetParamUCol(const char* paramName,
|
||||
size_t* memptr,
|
||||
const size_t rows)
|
||||
size_t* memptr,
|
||||
const size_t rows)
|
||||
{
|
||||
arma::Col<size_t> m(memptr, rows, false, true);
|
||||
arma::Col<size_t> m(memptr, arma::uword(rows), false, true);
|
||||
CLI::GetParam<arma::Col<size_t>>(paramName) = std::move(m);
|
||||
CLI::SetPassed(paramName);
|
||||
}
|
||||
@@ -191,7 +194,7 @@ void CLI_SetParamMatWithInfo(const char* paramName,
|
||||
data::Datatype::numeric;
|
||||
}
|
||||
|
||||
arma::mat m(memptr, rows, cols, false, true);
|
||||
arma::mat m(memptr, arma::uword(rows), arma::uword(cols), false, true);
|
||||
std::get<0>(CLI::GetParam<std::tuple<data::DatasetInfo, arma::mat>>(
|
||||
paramName)) = std::move(d);
|
||||
std::get<1>(CLI::GetParam<std::tuple<data::DatasetInfo, arma::mat>>(
|
||||
@@ -243,7 +246,7 @@ size_t CLI_GetParamVectorStrLen(const char* paramName)
|
||||
/**
|
||||
* Call CLI::GetParam<std::vector<std::string>>() and get the i'th string.
|
||||
*/
|
||||
const char* CLI_GetParamVectorStrStr(const char* paramName, const int i)
|
||||
const char* CLI_GetParamVectorStrStr(const char* paramName, const size_t i)
|
||||
{
|
||||
return CLI::GetParam<std::vector<std::string>>(paramName)[i].c_str();
|
||||
}
|
||||
@@ -261,10 +264,10 @@ size_t CLI_GetParamVectorIntLen(const char* paramName)
|
||||
* The vector will be created in-place and it is expected that the calling
|
||||
* function will take ownership.
|
||||
*/
|
||||
uint64_t* CLI_GetParamVectorIntPtr(const char* paramName)
|
||||
int* CLI_GetParamVectorIntPtr(const char* paramName)
|
||||
{
|
||||
const size_t size = CLI::GetParam<std::vector<int>>(paramName).size();
|
||||
uint64_t* ints = new uint64_t[size];
|
||||
int* ints = new int[size];
|
||||
|
||||
for (size_t i = 0; i < size; ++i)
|
||||
ints[i] = CLI::GetParam<std::vector<int>>(paramName)[i];
|
||||
@@ -335,15 +338,17 @@ size_t CLI_GetParamUMatCols(const char* paramName)
|
||||
*/
|
||||
size_t* CLI_GetParamUMat(const char* paramName)
|
||||
{
|
||||
arma::Mat<size_t>& mat = CLI::GetParam<arma::Mat<size_t>>(paramName);
|
||||
|
||||
// Are we using preallocated memory? If so we have to handle this more
|
||||
// carefully.
|
||||
arma::Mat<size_t>& mat = CLI::GetParam<arma::Mat<size_t>>(paramName);
|
||||
if (mat.n_elem <= arma::arma_config::mat_prealloc)
|
||||
{
|
||||
// Copy the memory to something that we can give back to Julia.
|
||||
size_t* newMem = new size_t[mat.n_elem];
|
||||
arma::arrayops::copy(newMem, mat.mem, mat.n_elem);
|
||||
return newMem; // We believe Julia will free it. Hopefully we are right.
|
||||
// We believe Julia will free it. Hopefully we are right.
|
||||
return newMem;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -399,15 +404,17 @@ size_t CLI_GetParamUColRows(const char* paramName)
|
||||
*/
|
||||
size_t* CLI_GetParamUCol(const char* paramName)
|
||||
{
|
||||
arma::Col<size_t>& vec = CLI::GetParam<arma::Col<size_t>>(paramName);
|
||||
|
||||
// Are we using preallocated memory? If so we have to handle this more
|
||||
// carefully.
|
||||
arma::Col<size_t>& vec = CLI::GetParam<arma::Col<size_t>>(paramName);
|
||||
if (vec.n_elem <= arma::arma_config::mat_prealloc)
|
||||
{
|
||||
// Copy the memory to something we can give back to Julia.
|
||||
size_t* newMem = new size_t[vec.n_elem];
|
||||
arma::arrayops::copy(newMem, vec.mem, vec.n_elem);
|
||||
return newMem; // We believe Julia will free it. Hopefully we are right.
|
||||
// We believe Julia will free it. Hopefully we are right.
|
||||
return newMem;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -463,9 +470,10 @@ size_t CLI_GetParamURowCols(const char* paramName)
|
||||
*/
|
||||
size_t* CLI_GetParamURow(const char* paramName)
|
||||
{
|
||||
arma::Row<size_t>& vec = CLI::GetParam<arma::Row<size_t>>(paramName);
|
||||
|
||||
// Are we using preallocated memory? If so we have to handle this more
|
||||
// carefully.
|
||||
arma::Row<size_t>& vec = CLI::GetParam<arma::Row<size_t>>(paramName);
|
||||
if (vec.n_elem <= arma::arma_config::mat_prealloc)
|
||||
{
|
||||
// Copy the memory to something we can give back to Julia.
|
||||
|
||||
@@ -61,7 +61,7 @@ void CLI_SetParamVectorStrStr(const char* paramName,
|
||||
* Call CLI::SetParam<std::vector<int>>().
|
||||
*/
|
||||
void CLI_SetParamVectorInt(const char* paramName,
|
||||
uint64_t* ints,
|
||||
int* ints,
|
||||
const size_t length);
|
||||
|
||||
/**
|
||||
@@ -149,7 +149,7 @@ size_t CLI_GetParamVectorStrLen(const char* paramName);
|
||||
/**
|
||||
* Call CLI::GetParam<std::vector<std::string>>() and get the i'th string.
|
||||
*/
|
||||
const char* CLI_GetParamVectorStrStr(const char* paramName, const int i);
|
||||
const char* CLI_GetParamVectorStrStr(const char* paramName, const size_t i);
|
||||
|
||||
/**
|
||||
* Call CLI::GetParam<std::vector<int>>() and get the length of the vector.
|
||||
@@ -161,7 +161,7 @@ size_t CLI_GetParamVectorIntLen(const char* paramName);
|
||||
* The vector will be created in-place and it is expected that the calling
|
||||
* function will take ownership.
|
||||
*/
|
||||
uint64_t* CLI_GetParamVectorIntPtr(const char* paramName);
|
||||
int* CLI_GetParamVectorIntPtr(const char* paramName);
|
||||
|
||||
/**
|
||||
* Get the number of rows in a matrix parameter.
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
julia 0.7.0
|
||||
@@ -66,8 +66,8 @@ function CLIRestoreSettings(programName::String)
|
||||
end
|
||||
|
||||
function CLISetParam(paramName::String, paramValue::Int)
|
||||
ccall((:CLI_SetParamInt, library), Nothing, (Cstring, Int), paramName,
|
||||
paramValue);
|
||||
ccall((:CLI_SetParamInt, library), Nothing, (Cstring, Cint), paramName,
|
||||
Cint(paramValue));
|
||||
end
|
||||
|
||||
function CLISetParam(paramName::String, paramValue::Float64)
|
||||
@@ -89,15 +89,15 @@ function CLISetParamMat(paramName::String,
|
||||
paramValue,
|
||||
pointsAsRows::Bool)
|
||||
paramMat = to_matrix(paramValue, Float64)
|
||||
ccall((:CLI_SetParamMat, library), Nothing, (Cstring, Ptr{Float64}, UInt64,
|
||||
UInt64, Bool), paramName, Base.pointer(paramMat), size(paramMat, 1),
|
||||
ccall((:CLI_SetParamMat, library), Nothing, (Cstring, Ptr{Float64}, Csize_t,
|
||||
Csize_t, Bool), paramName, Base.pointer(paramMat), size(paramMat, 1),
|
||||
size(paramMat, 2), pointsAsRows);
|
||||
end
|
||||
|
||||
function CLISetParamUMat(paramName::String,
|
||||
paramValue,
|
||||
pointsAsRows::Bool)
|
||||
paramMat = to_matrix(paramValue, Int64)
|
||||
paramMat = to_matrix(paramValue, Int)
|
||||
|
||||
# Sanity check.
|
||||
if minimum(paramMat) <= 0
|
||||
@@ -105,9 +105,9 @@ function CLISetParamUMat(paramName::String,
|
||||
"Must be 1 or greater."))
|
||||
end
|
||||
|
||||
m = convert(Array{UInt64, 2}, paramMat .- 1)
|
||||
ccall((:CLI_SetParamUMat, library), Nothing, (Cstring, Ptr{UInt64}, UInt64,
|
||||
UInt64, Bool), paramName, Base.pointer(m), size(paramValue, 1),
|
||||
m = convert(Array{Csize_t, 2}, paramMat .- 1)
|
||||
ccall((:CLI_SetParamUMat, library), Nothing, (Cstring, Ptr{Csize_t}, Csize_t,
|
||||
Csize_t, Bool), paramName, Base.pointer(m), size(paramValue, 1),
|
||||
size(paramValue, 2), pointsAsRows);
|
||||
end
|
||||
|
||||
@@ -117,25 +117,26 @@ function CLISetParam(paramName::String,
|
||||
# sequentially. I am not sure if this is fully necessary but I have some
|
||||
# reservations about Julia's support for passing arrays of strings correctly
|
||||
# as a const char**.
|
||||
ccall((:CLI_SetParamVectorStrLen, library), Nothing, (Cstring, UInt64),
|
||||
ccall((:CLI_SetParamVectorStrLen, library), Nothing, (Cstring, Csize_t),
|
||||
paramName, size(vector, 1));
|
||||
for i in 1:size(vector, 1)
|
||||
ccall((:CLI_SetParamVectorStrStr, library), Nothing, (Cstring, Cstring,
|
||||
UInt64), paramName, vector[i], i .- 1);
|
||||
Csize_t), paramName, vector[i], i .- 1);
|
||||
end
|
||||
end
|
||||
|
||||
function CLISetParam(paramName::String,
|
||||
vector::Vector{Int64})
|
||||
ccall((:CLI_SetParamVectorInt, library), Nothing, (Cstring, Ptr{Int64},
|
||||
Int64), paramName, Base.pointer(vector), size(vector, 1));
|
||||
vector::Vector{Int})
|
||||
cint_vec = convert(Vector{Cint}, vector)
|
||||
ccall((:CLI_SetParamVectorInt, library), Nothing, (Cstring, Ptr{Cint},
|
||||
Csize_t), paramName, Base.pointer(cint_vec), size(cint_vec, 1));
|
||||
end
|
||||
|
||||
function CLISetParam(paramName::String,
|
||||
matWithInfo::Tuple{Array{Bool, 1}, Array{Float64, 2}},
|
||||
pointsAsRows::Bool)
|
||||
ccall((:CLI_SetParamMatWithInfo, library), Nothing, (Cstring, Ptr{Bool},
|
||||
Ptr{Float64}, Int64, Int64, Bool), paramName,
|
||||
Ptr{Float64}, Int, Int, Bool), paramName,
|
||||
Base.pointer(matWithInfo[1]), Base.pointer(matWithInfo[2]),
|
||||
size(matWithInfo[2], 1), size(matWithInfo[2], 2), pointsAsRows);
|
||||
end
|
||||
@@ -143,44 +144,44 @@ end
|
||||
function CLISetParamRow(paramName::String,
|
||||
paramValue)
|
||||
paramVec = to_vector(paramValue, Float64)
|
||||
ccall((:CLI_SetParamRow, library), Nothing, (Cstring, Ptr{Float64}, UInt64),
|
||||
ccall((:CLI_SetParamRow, library), Nothing, (Cstring, Ptr{Float64}, Csize_t),
|
||||
paramName, Base.pointer(paramVec), size(paramVec, 1));
|
||||
end
|
||||
|
||||
function CLISetParamCol(paramName::String,
|
||||
paramValue)
|
||||
paramVec = to_vector(paramValue, Float64)
|
||||
ccall((:CLI_SetParamCol, library), Nothing, (Cstring, Ptr{Float64}, UInt64),
|
||||
ccall((:CLI_SetParamCol, library), Nothing, (Cstring, Ptr{Float64}, Csize_t),
|
||||
paramName, Base.pointer(paramVec), size(paramVec, 1));
|
||||
end
|
||||
|
||||
function CLISetParamURow(paramName::String,
|
||||
paramValue)
|
||||
paramVec = to_vector(paramValue, Int64)
|
||||
paramVec = to_vector(paramValue, Int)
|
||||
|
||||
# Sanity check.
|
||||
if minimum(paramVec) <= 0
|
||||
throw(DomainError("Input $(paramName) cannot have 0 or negative values! " *
|
||||
"Must be 1 or greater."))
|
||||
end
|
||||
m = convert(Array{UInt64, 1}, paramVec .- 1)
|
||||
m = convert(Array{Csize_t, 1}, paramVec .- 1)
|
||||
|
||||
ccall((:CLI_SetParamURow, library), Nothing, (Cstring, Ptr{UInt64}, UInt64),
|
||||
ccall((:CLI_SetParamURow, library), Nothing, (Cstring, Ptr{Csize_t}, Csize_t),
|
||||
paramName, Base.pointer(m), size(paramValue, 1));
|
||||
end
|
||||
|
||||
function CLISetParamUCol(paramName::String,
|
||||
paramValue)
|
||||
paramVec = to_vector(paramValue, Int64)
|
||||
paramVec = to_vector(paramValue, Int)
|
||||
|
||||
# Sanity check.
|
||||
if minimum(paramVec) <= 0
|
||||
throw(DomainError("Input $(paramName) cannot have 0 or negative values! " *
|
||||
"Must be 1 or greater."))
|
||||
end
|
||||
m = convert(Array{UInt64, 1}, paramValue .- 1)
|
||||
m = convert(Array{Csize_t, 1}, paramValue .- 1)
|
||||
|
||||
ccall((:CLI_SetParamUCol, library), Nothing, (Cstring, Ptr{UInt64}, UInt64),
|
||||
ccall((:CLI_SetParamUCol, library), Nothing, (Cstring, Ptr{Csize_t}, Csize_t),
|
||||
paramName, Base.pointer(m), size(paramValue, 1));
|
||||
end
|
||||
|
||||
@@ -189,7 +190,7 @@ function CLIGetParamBool(paramName::String)
|
||||
end
|
||||
|
||||
function CLIGetParamInt(paramName::String)
|
||||
return ccall((:CLI_GetParamInt, library), Int64, (Cstring,), paramName)
|
||||
return Int(ccall((:CLI_GetParamInt, library), Cint, (Cstring,), paramName))
|
||||
end
|
||||
|
||||
function CLIGetParamDouble(paramName::String)
|
||||
@@ -201,15 +202,15 @@ function CLIGetParamString(paramName::String)
|
||||
end
|
||||
|
||||
function CLIGetParamVectorStr(paramName::String)
|
||||
local size::UInt64
|
||||
local size::Csize_t
|
||||
local ptr::Ptr{String}
|
||||
|
||||
# Get the size of the vector, then each element.
|
||||
size = ccall((:CLI_GetParamVectorStrLen, library), UInt64, (Cstring,),
|
||||
size = ccall((:CLI_GetParamVectorStrLen, library), Csize_t, (Cstring,),
|
||||
paramName);
|
||||
out = Array{String, 1}()
|
||||
for i = 1:size
|
||||
s = ccall((:CLI_GetParamVectorStrStr, library), Cstring, (Cstring, UInt64),
|
||||
s = ccall((:CLI_GetParamVectorStrStr, library), Cstring, (Cstring, Csize_t),
|
||||
paramName, i .- 1)
|
||||
push!(out, Base.unsafe_string(s))
|
||||
end
|
||||
@@ -218,28 +219,29 @@ function CLIGetParamVectorStr(paramName::String)
|
||||
end
|
||||
|
||||
function CLIGetParamVectorInt(paramName::String)
|
||||
local size::UInt64
|
||||
local ptr::Ptr{Int64}
|
||||
local size::Csize_t
|
||||
local ptr::Ptr{Cint}
|
||||
|
||||
# Get the size of the vector, then the pointer to it. We will own the
|
||||
# pointer.
|
||||
size = ccall((:CLI_GetParamVectorIntLen, library), UInt64, (Cstring,),
|
||||
size = ccall((:CLI_GetParamVectorIntLen, library), Csize_t, (Cstring,),
|
||||
paramName);
|
||||
ptr = ccall((:CLI_GetParamVectorIntPtr, library), Ptr{Int64}, (Cstring,),
|
||||
ptr = ccall((:CLI_GetParamVectorIntPtr, library), Ptr{Cint}, (Cstring,),
|
||||
paramName);
|
||||
|
||||
return Base.unsafe_wrap(Array{Int64, 1}, ptr, (size), own=true)
|
||||
return convert(Array{Int, 1}, Base.unsafe_wrap(Array{Cint, 1}, ptr, (size),
|
||||
own=true))
|
||||
end
|
||||
|
||||
function CLIGetParamMat(paramName::String, pointsAsRows::Bool)
|
||||
# Can we return different return types? For now let's restrict to a matrix to
|
||||
# make it easy...
|
||||
local ptr::Ptr{Float64}
|
||||
local rows::UInt64, cols::UInt64;
|
||||
local rows::Csize_t, cols::Csize_t;
|
||||
# I suppose it would be possible to do this all in one call, but this seems
|
||||
# easy enough.
|
||||
rows = ccall((:CLI_GetParamMatRows, library), UInt64, (Cstring,), paramName);
|
||||
cols = ccall((:CLI_GetParamMatCols, library), UInt64, (Cstring,), paramName);
|
||||
rows = ccall((:CLI_GetParamMatRows, library), Csize_t, (Cstring,), paramName);
|
||||
cols = ccall((:CLI_GetParamMatCols, library), Csize_t, (Cstring,), paramName);
|
||||
ptr = ccall((:CLI_GetParamMat, library), Ptr{Float64}, (Cstring,), paramName);
|
||||
|
||||
if pointsAsRows
|
||||
@@ -255,30 +257,30 @@ end
|
||||
function CLIGetParamUMat(paramName::String, pointsAsRows::Bool)
|
||||
# Can we return different return types? For now let's restrict to a matrix to
|
||||
# make it easy...
|
||||
local ptr::Ptr{UInt64}
|
||||
local rows::UInt64, cols::UInt64;
|
||||
local ptr::Ptr{Csize_t}
|
||||
local rows::Csize_t, cols::Csize_t;
|
||||
# I suppose it would be possible to do this all in one call, but this seems
|
||||
# easy enough.
|
||||
rows = ccall((:CLI_GetParamUMatRows, library), UInt64, (Cstring,), paramName);
|
||||
cols = ccall((:CLI_GetParamUMatCols, library), UInt64, (Cstring,), paramName);
|
||||
ptr = ccall((:CLI_GetParamUMat, library), Ptr{UInt64}, (Cstring,), paramName);
|
||||
rows = ccall((:CLI_GetParamUMatRows, library), Csize_t, (Cstring,), paramName);
|
||||
cols = ccall((:CLI_GetParamUMatCols, library), Csize_t, (Cstring,), paramName);
|
||||
ptr = ccall((:CLI_GetParamUMat, library), Ptr{Csize_t}, (Cstring,), paramName);
|
||||
|
||||
if pointsAsRows
|
||||
# In this case we have to transpose, unfortunately.
|
||||
m = Base.unsafe_wrap(Array{UInt64, 2}, ptr, (rows, cols), own=true);
|
||||
return convert(Array{Int64, 2}, m' .+ 1) # Add 1 because these are indexes.
|
||||
m = Base.unsafe_wrap(Array{Csize_t, 2}, ptr, (rows, cols), own=true);
|
||||
return convert(Array{Int, 2}, m' .+ 1) # Add 1 because these are indexes.
|
||||
else
|
||||
# Here no transpose is necessary.
|
||||
m = Base.unsafe_wrap(Array{UInt64, 2}, ptr, (rows, cols), own=true);
|
||||
return convert(Array{Int64, 2}, m .+ 1)
|
||||
m = Base.unsafe_wrap(Array{Csize_t, 2}, ptr, (rows, cols), own=true);
|
||||
return convert(Array{Int, 2}, m .+ 1)
|
||||
end
|
||||
end
|
||||
|
||||
function CLIGetParamCol(paramName::String)
|
||||
local ptr::Ptr{Float64};
|
||||
local rows::UInt64;
|
||||
local rows::Csize_t;
|
||||
|
||||
rows = ccall((:CLI_GetParamColRows, library), UInt64, (Cstring,), paramName);
|
||||
rows = ccall((:CLI_GetParamColRows, library), Csize_t, (Cstring,), paramName);
|
||||
ptr = ccall((:CLI_GetParamCol, library), Ptr{Float64}, (Cstring,), paramName);
|
||||
|
||||
return Base.unsafe_wrap(Array{Float64, 1}, ptr, rows, own=true);
|
||||
@@ -286,45 +288,45 @@ end
|
||||
|
||||
function CLIGetParamRow(paramName::String)
|
||||
local ptr::Ptr{Float64};
|
||||
local cols::UInt64;
|
||||
local cols::Csize_t;
|
||||
|
||||
cols = ccall((:CLI_GetParamRowCols, library), UInt64, (Cstring,), paramName);
|
||||
cols = ccall((:CLI_GetParamRowCols, library), Csize_t, (Cstring,), paramName);
|
||||
ptr = ccall((:CLI_GetParamRow, library), Ptr{Float64}, (Cstring,), paramName);
|
||||
|
||||
return Base.unsafe_wrap(Array{Float64, 1}, ptr, cols, own=true);
|
||||
end
|
||||
|
||||
function CLIGetParamUCol(paramName::String)
|
||||
local ptr::Ptr{UInt64};
|
||||
local rows::UInt64;
|
||||
local ptr::Ptr{Csize_t};
|
||||
local rows::Csize_t;
|
||||
|
||||
rows = ccall((:CLI_GetParamUColRows, library), UInt64, (Cstring,), paramName);
|
||||
ptr = ccall((:CLI_GetParamUCol, library), Ptr{UInt64}, (Cstring,), paramName);
|
||||
rows = ccall((:CLI_GetParamUColRows, library), Csize_t, (Cstring,), paramName);
|
||||
ptr = ccall((:CLI_GetParamUCol, library), Ptr{Csize_t}, (Cstring,), paramName);
|
||||
|
||||
m = Base.unsafe_wrap(Array{UInt64, 1}, ptr, rows, own=true);
|
||||
return convert(Array{Int64, 1}, m .+ 1)
|
||||
m = Base.unsafe_wrap(Array{Csize_t, 1}, ptr, rows, own=true);
|
||||
return convert(Array{Int, 1}, m .+ 1)
|
||||
end
|
||||
|
||||
function CLIGetParamURow(paramName::String)
|
||||
local ptr::Ptr{UInt64};
|
||||
local cols::UInt64;
|
||||
local ptr::Ptr{Csize_t};
|
||||
local cols::Csize_t;
|
||||
|
||||
cols = ccall((:CLI_GetParamURowCols, library), UInt64, (Cstring,), paramName);
|
||||
ptr = ccall((:CLI_GetParamURow, library), Ptr{UInt64}, (Cstring,), paramName);
|
||||
cols = ccall((:CLI_GetParamURowCols, library), Csize_t, (Cstring,), paramName);
|
||||
ptr = ccall((:CLI_GetParamURow, library), Ptr{Csize_t}, (Cstring,), paramName);
|
||||
|
||||
m = Base.unsafe_wrap(Array{UInt64, 1}, ptr, cols, own=true);
|
||||
return convert(Array{Int64, 1}, m .+ 1)
|
||||
m = Base.unsafe_wrap(Array{Csize_t, 1}, ptr, cols, own=true);
|
||||
return convert(Array{Int, 1}, m .+ 1)
|
||||
end
|
||||
|
||||
function CLIGetParamMatWithInfo(paramName::String, pointsAsRows::Bool)
|
||||
local ptrBool::Ptr{Bool};
|
||||
local ptrData::Ptr{Float64};
|
||||
local rows::UInt64;
|
||||
local cols::UInt64;
|
||||
local rows::Csize_t;
|
||||
local cols::Csize_t;
|
||||
|
||||
rows = ccall((:CLI_GetParamMatWithInfoRows, library), UInt64, (Cstring,),
|
||||
rows = ccall((:CLI_GetParamMatWithInfoRows, library), Csize_t, (Cstring,),
|
||||
paramName);
|
||||
cols = ccall((:CLI_GetParamMatWithInfoCols, library), UInt64, (Cstring,),
|
||||
cols = ccall((:CLI_GetParamMatWithInfoCols, library), Csize_t, (Cstring,),
|
||||
paramName);
|
||||
ptrBool = ccall((:CLI_GetParamMatWithInfoBoolPtr, library), Ptr{Bool},
|
||||
(Cstring,), paramName);
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
"""
|
||||
mlpack
|
||||
|
||||
mlpack is a fast, flexible machine learning library, written in C++, that aims
|
||||
to provide fast, extensible implementations of cutting-edge machine learning
|
||||
algorithms. This module provides those implementations as Julia functions.
|
||||
|
||||
Each function inside the module performs a specific machine learning task.
|
||||
|
||||
For complete documentation of these functions, including example usage, see the
|
||||
mlpack website's documentation for the Julia bindings:
|
||||
|
||||
https://www.mlpack.org/doc/stable/julia_documentation.html
|
||||
|
||||
Each function also contains an equivalent docstring; the Julia REPL's help
|
||||
functionality can be used to access the documentation that way.
|
||||
"""
|
||||
module mlpack
|
||||
|
||||
"""
|
||||
mlpack._Internal
|
||||
|
||||
This module contains internal implementations details of mlpack. There
|
||||
shouldn't be any need to go digging around in here if you're just using mlpack.
|
||||
(But don't let this comment discourage you if you're just curious and poking
|
||||
around!)
|
||||
"""
|
||||
module _Internal
|
||||
|
||||
include("cli.jl")
|
||||
@@ -124,7 +124,7 @@ inline std::string CreateInputArguments(const std::string& paramName,
|
||||
d.cppType == "arma::Col<size_t>")
|
||||
{
|
||||
oss << "julia> " << value << " = CSV.read(\"" << value
|
||||
<< ".csv\"; type=Int64)" << std::endl;
|
||||
<< ".csv\"; type=Int)" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -375,6 +375,9 @@ inline std::string ProgramCall(const std::string& programName, Args... args)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
|
||||
// The code should appear in a Markdown code block.
|
||||
oss << "```julia" << std::endl;
|
||||
|
||||
// Print any input argument definitions. The only input argument definitions
|
||||
// will be the definitions of matrices, which use the CSV.jl package, so we
|
||||
// should also include a `using CSV` in there too.
|
||||
@@ -401,6 +404,9 @@ inline std::string ProgramCall(const std::string& programName, Args... args)
|
||||
// Since `julia> ` is 8 characters, let's indent 12 otherwise it looks weird.
|
||||
oss << util::HyphenateString(ossCall.str(), 12);
|
||||
|
||||
// Close the Markdown code block.
|
||||
oss << std::endl << "```";
|
||||
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@ void PrintJL(const util::ProgramDoc& programInfo,
|
||||
cout << endl;
|
||||
|
||||
// We need to include utility functions.
|
||||
cout << "using mlpack.util.cli" << endl;
|
||||
cout << "using mlpack._Internal.cli" << endl;
|
||||
cout << endl;
|
||||
|
||||
// Make sure the libraries we need are accessible.
|
||||
|
||||
@@ -109,15 +109,15 @@ std::string PrintTypeDoc(
|
||||
if (T::is_col || T::is_row)
|
||||
{
|
||||
return "A 1-d vector-like containing `Int` data (elements should be "
|
||||
"greater than or equal to 0). Could be an `Array{Int64, 1}`, an "
|
||||
"`Array{Int64, 2}` with one dimension of size 1, or anything "
|
||||
"convertible to `Array{Int64, 1}`.";
|
||||
"greater than or equal to 0). Could be an `Array{Int, 1}`, an "
|
||||
"`Array{Int, 2}` with one dimension of size 1, or anything "
|
||||
"convertible to `Array{Int, 1}`.";
|
||||
}
|
||||
else
|
||||
{
|
||||
return "A 2-d matrix-like containing `Int` data (elements should be "
|
||||
"greater than or equal to 0). Could be an `Array{Int64, 2}` or a "
|
||||
"`DataFrame` or anything convertible to an `Array{Int64, 2}`. It is "
|
||||
"greater than or equal to 0). Could be an `Array{Int, 2}` or a "
|
||||
"`DataFrame` or anything convertible to an `Array{Int, 2}`. It is "
|
||||
"expected that each row of the matrix corresponds to a data point, "
|
||||
"unless `points_are_rows` is set to `false` when calling mlpack "
|
||||
"bindings.";
|
||||
|
||||
@@ -129,7 +129,7 @@ end
|
||||
# Same as TestMatrix but with an unsigned matrix.
|
||||
@testset "TestUMatrix" begin
|
||||
# Generate a random matrix of integers.
|
||||
x = convert(Array{Int64, 2}, rand(1:500, (100, 5)))
|
||||
x = convert(Array{Int, 2}, rand(1:500, (100, 5)))
|
||||
|
||||
_, _, _, _, _, _, _, _, _, _, _, umatOut, _, _ =
|
||||
test_julia_binding(4.0, 12, "hello",
|
||||
@@ -138,7 +138,7 @@ end
|
||||
|
||||
@test size(umatOut, 1) == 100
|
||||
@test size(umatOut, 2) == 4
|
||||
@test typeof(umatOut[1, 1]) == Int64
|
||||
@test typeof(umatOut[1, 1]) == Int
|
||||
for i in [0, 1, 3]
|
||||
for j in 1:100
|
||||
@test umatOut[j, i + 1] == x[j, i + 1]
|
||||
@@ -155,7 +155,7 @@ end
|
||||
# Same as TestMatrix but with an unsigned column major matrix.
|
||||
@testset "TestUMatrixColMajor" begin
|
||||
# Generate a random matrix of integers.
|
||||
x = convert(Array{Int64, 2}, rand(1:500, (5, 100)))
|
||||
x = convert(Array{Int, 2}, rand(1:500, (5, 100)))
|
||||
|
||||
_, _, _, _, _, _, _, _, _, _, _, umatOut, _, _ =
|
||||
test_julia_binding(4.0, 12, "hello",
|
||||
@@ -164,7 +164,7 @@ end
|
||||
|
||||
@test size(umatOut, 1) == 4
|
||||
@test size(umatOut, 2) == 100
|
||||
@test typeof(umatOut[1, 1]) == Int64
|
||||
@test typeof(umatOut[1, 1]) == Int
|
||||
for i in 1:100
|
||||
for j in [0, 1, 3]
|
||||
@test umatOut[j + 1, i] == x[j + 1, i]
|
||||
@@ -196,14 +196,14 @@ end
|
||||
|
||||
# Test an unsigned column vector input parameter.
|
||||
@testset "TestUCol" begin
|
||||
x = convert(Array{Int64, 1}, rand(1:500, 100))
|
||||
x = convert(Array{Int, 1}, rand(1:500, 100))
|
||||
|
||||
_, _, _, _, _, _, _, _, _, _, ucolOut, _, _, _ =
|
||||
test_julia_binding(4.0, 12, "hello",
|
||||
ucol_in=x)
|
||||
|
||||
@test size(ucolOut, 1) == 100
|
||||
@test typeof(ucolOut) == Array{Int64, 1}
|
||||
@test typeof(ucolOut) == Array{Int, 1}
|
||||
for i in 1:100
|
||||
# Since we subtract one when we convert to C++, and then add one when we
|
||||
# convert back, we get a slightly different result here.
|
||||
@@ -228,14 +228,14 @@ end
|
||||
|
||||
# Test an unsigned row vector input parameter.
|
||||
@testset "TestURow" begin
|
||||
x = convert(Array{Int64, 1}, rand(1:500, 100))
|
||||
x = convert(Array{Int, 1}, rand(1:500, 100))
|
||||
|
||||
_, _, _, _, _, _, _, _, _, _, _, _, urowOut, _ =
|
||||
test_julia_binding(4.0, 12, "hello",
|
||||
urow_in=x)
|
||||
|
||||
@test size(urowOut, 1) == 100
|
||||
@test typeof(urowOut) == Array{Int64, 1}
|
||||
@test typeof(urowOut) == Array{Int, 1}
|
||||
for i in 1:100
|
||||
# Since we subtract one when we convert to C++, and then add one when we
|
||||
# convert back, we get a slightly different result here.
|
||||
|
||||
@@ -451,20 +451,21 @@ inline std::string PrintModel(const std::string& model)
|
||||
template<typename... Args>
|
||||
std::string ProgramCall(const std::string& programName, Args... args)
|
||||
{
|
||||
std::string s = "```";
|
||||
std::string s;
|
||||
if (BindingInfo::Language() == "cli")
|
||||
{
|
||||
s += "bash\n";
|
||||
s += "```bash\n";
|
||||
s += cli::ProgramCall(programName, args...);
|
||||
}
|
||||
else if (BindingInfo::Language() == "python")
|
||||
{
|
||||
s += "python\n";
|
||||
s += "```python\n";
|
||||
s += python::ProgramCall(programName, args...);
|
||||
}
|
||||
else if (BindingInfo::Language() == "julia")
|
||||
{
|
||||
s += "julia\n";
|
||||
// Julia's ProgramCall() with a set of arguments will automatically enclose
|
||||
// the text in Markdown code, so we don't need to.
|
||||
s += julia::ProgramCall(programName, args...);
|
||||
}
|
||||
else
|
||||
@@ -472,7 +473,10 @@ std::string ProgramCall(const std::string& programName, Args... args)
|
||||
throw std::invalid_argument("ProgramCall(): unknown "
|
||||
"BindingInfo::Language(): " + BindingInfo::Language() + "!");
|
||||
}
|
||||
s += "\n```";
|
||||
|
||||
// Close the Markdown code block, but only if we opened one.
|
||||
if (BindingInfo::Language() != "julia")
|
||||
s += "\n```";
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
@@ -126,7 +126,8 @@ void PrintDocs(const std::string& bindingName,
|
||||
cout << "| ";
|
||||
cout << ParamString(it->second.name) << " | ";
|
||||
cout << ParamType(it->second) << " | ";
|
||||
cout << it->second.desc; // just a string
|
||||
string desc = boost::replace_all_copy(it->second.desc, "|", "\\|");
|
||||
cout << desc; // just a string
|
||||
// Print whether or not it's a "special" language-only parameter.
|
||||
if (it->second.name == "copy_all_inputs" || it->second.name == "help" ||
|
||||
it->second.name == "info" || it->second.name == "version")
|
||||
@@ -180,7 +181,9 @@ void PrintDocs(const std::string& bindingName,
|
||||
cout << "{: #" << languages[i] << "_" << bindingName
|
||||
<< "_detailed-documentation }" << endl;
|
||||
cout << endl;
|
||||
cout << programDoc.documentation() << endl;
|
||||
string doc = boost::replace_all_copy(programDoc.documentation(),
|
||||
"|", "\\|");
|
||||
cout << doc << endl;
|
||||
cout << endl;
|
||||
|
||||
cout << "### See also" << endl;
|
||||
|
||||
@@ -19,6 +19,9 @@ void Cube<eT>::serialize(Archive& ar, const unsigned int /* version */)
|
||||
// mem_state will always be 0 on load, so we don't need to save it.
|
||||
if (Archive::is_loading::value)
|
||||
{
|
||||
// Clean any mat pointers.
|
||||
delete_mat();
|
||||
|
||||
// Don't free if local memory is being used.
|
||||
if (mem_state == 0 && mem != NULL && old_n_elem > arma_config::mat_prealloc)
|
||||
{
|
||||
|
||||
@@ -36,6 +36,12 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Force definition of old HDF5 API. Thanks to Mike Roberts for helping find
|
||||
// this workaround.
|
||||
#if !defined(H5_USE_110_API)
|
||||
#define H5_USE_110_API
|
||||
#endif
|
||||
|
||||
// Include everything we'll need for serialize().
|
||||
#include <boost/serialization/serialization.hpp>
|
||||
#include <boost/serialization/nvp.hpp>
|
||||
|
||||
@@ -2,18 +2,14 @@
|
||||
# Anything not in this list will not be compiled into mlpack.
|
||||
set(SOURCES
|
||||
bernoulli.hpp
|
||||
boost_backport_math.hpp
|
||||
boost_backport_serialization.hpp
|
||||
detail/bernoulli_details.hpp
|
||||
detail/polygamma.hpp
|
||||
detail/unchecked_bernoulli.hpp
|
||||
math_fwd.hpp
|
||||
policy.hpp
|
||||
polygamma.hpp
|
||||
trigamma.hpp
|
||||
unordered_collections_load_imp.hpp
|
||||
unordered_collections_save_imp.hpp
|
||||
unordered_map.hpp
|
||||
vector.hpp
|
||||
string_view.hpp
|
||||
string_view_fwd.hpp
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
/**
|
||||
* @file boost_backport.hpp
|
||||
* @author Yannis Mentekidis
|
||||
*
|
||||
* Centralized control of what boost files to include. We have backported the
|
||||
* following boost functionality here:
|
||||
*
|
||||
* * trigamma and polygamma function evaluation (added in boost 1.58.0)
|
||||
*
|
||||
* For versions 1.56, 1.57 we include the backported polygamma and trigamma
|
||||
* functions. Anything newer, we include from Boost.
|
||||
*/
|
||||
#ifndef MLPACK_CORE_BOOST_BACKPORT_MATH_HPP
|
||||
#define MLPACK_CORE_BOOST_BACKPORT_MATH_HPP
|
||||
|
||||
#include <boost/version.hpp>
|
||||
|
||||
#if BOOST_VERSION < 105800
|
||||
// Backported trigamma and polygamma.
|
||||
#include "mlpack/core/boost_backport/trigamma.hpp"
|
||||
#include "mlpack/core/boost_backport/polygamma.hpp"
|
||||
#else
|
||||
// Boost's version.
|
||||
#include <boost/math/special_functions/trigamma.hpp>
|
||||
#include <boost/math/special_functions/polygamma.hpp>
|
||||
#endif
|
||||
|
||||
#endif // MLPACK_CORE_BOOST_BACKPORT_HPP
|
||||
|
||||
@@ -16,14 +16,7 @@
|
||||
#define MLPACK_CORE_BOOST_BACKPORT_SERIALIZATION_HPP
|
||||
|
||||
#include <boost/version.hpp>
|
||||
|
||||
#if BOOST_VERSION < 105600
|
||||
// Backported unordered_map.
|
||||
#include "mlpack/core/boost_backport/unordered_map.hpp"
|
||||
#else
|
||||
// Boost's version.
|
||||
#include <boost/serialization/unordered_map.hpp>
|
||||
#endif
|
||||
#include <boost/serialization/unordered_map.hpp>
|
||||
|
||||
#if BOOST_VERSION == 105800
|
||||
/**
|
||||
|
||||
@@ -1,94 +0,0 @@
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright 2013 Nikhar Agrawal
|
||||
// Copyright 2013 Christopher Kormanyos
|
||||
// Copyright 2014 John Maddock
|
||||
// Copyright 2013 Paul Bristow
|
||||
// Distributed under the Boost
|
||||
// Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef _BOOST_POLYGAMMA_2013_07_30_HPP_
|
||||
#define _BOOST_POLYGAMMA_2013_07_30_HPP_
|
||||
|
||||
#include "detail/polygamma.hpp"
|
||||
#include "trigamma.hpp"
|
||||
#include <boost/math/special_functions/factorials.hpp>
|
||||
|
||||
// Forward declarations
|
||||
namespace boost { namespace math {
|
||||
template <class T, class Policy>
|
||||
inline typename tools::promote_args<T>::type
|
||||
trigamma(T x, const Policy&);
|
||||
|
||||
template <class T>
|
||||
inline typename tools::promote_args<T>::type
|
||||
trigamma(T x);
|
||||
}}
|
||||
|
||||
namespace boost { namespace math {
|
||||
|
||||
|
||||
template<class T, class Policy>
|
||||
inline typename tools::promote_args<T>::type polygamma(const int n, T x, const Policy& pol)
|
||||
{
|
||||
//
|
||||
// Filter off special cases right at the start:
|
||||
//
|
||||
if(n == 0)
|
||||
return boost::math::digamma(x, pol);
|
||||
if(n == 1)
|
||||
return boost::math::trigamma(x, pol);
|
||||
//
|
||||
// We've found some standard library functions to misbehave if any FPU exception flags
|
||||
// are set prior to their call, this code will clear those flags, then reset them
|
||||
// on exit:
|
||||
//
|
||||
BOOST_FPU_EXCEPTION_GUARD
|
||||
//
|
||||
// The type of the result - the common type of T and U after
|
||||
// any integer types have been promoted to double:
|
||||
//
|
||||
typedef typename tools::promote_args<T>::type result_type;
|
||||
//
|
||||
// The type used for the calculation. This may be a wider type than
|
||||
// the result in order to ensure full precision:
|
||||
//
|
||||
typedef typename policies::evaluation<result_type, Policy>::type value_type;
|
||||
//
|
||||
// The type of the policy to forward to the actual implementation.
|
||||
// We disable promotion of float and double as that's [possibly]
|
||||
// happened already in the line above. Also reset to the default
|
||||
// any policies we don't use (reduces code bloat if we're called
|
||||
// multiple times with differing policies we don't actually use).
|
||||
// Also normalise the type, again to reduce code bloat in case we're
|
||||
// called multiple times with functionally identical policies that happen
|
||||
// to be different types.
|
||||
//
|
||||
typedef typename policies::normalise<
|
||||
Policy,
|
||||
policies::promote_float<false>,
|
||||
policies::promote_double<false>,
|
||||
policies::discrete_quantile<>,
|
||||
policies::assert_undefined<> >::type forwarding_policy;
|
||||
//
|
||||
// Whew. Now we can make the actual call to the implementation.
|
||||
// Arguments are explicitly cast to the evaluation type, and the result
|
||||
// passed through checked_narrowing_cast which handles things like overflow
|
||||
// according to the policy passed:
|
||||
//
|
||||
return policies::checked_narrowing_cast<result_type, forwarding_policy>(
|
||||
detail::polygamma_imp(n, static_cast<value_type>(x), forwarding_policy()),
|
||||
"boost::math::polygamma<%1%>(int, %1%)");
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline typename tools::promote_args<T>::type polygamma(const int n, T x)
|
||||
{
|
||||
return boost::math::polygamma(n, x, policies::policy<>());
|
||||
}
|
||||
|
||||
} } // namespace boost::math
|
||||
|
||||
#endif // _BOOST_BERNOULLI_2013_05_30_HPP_
|
||||
|
||||
@@ -1,469 +0,0 @@
|
||||
// (C) Copyright John Maddock 2006.
|
||||
// Use, modification and distribution are subject to the
|
||||
// Boost Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_MATH_SF_TRIGAMMA_HPP
|
||||
#define BOOST_MATH_SF_TRIGAMMA_HPP
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "math_fwd.hpp"
|
||||
#include "polygamma.hpp"
|
||||
#include <boost/math/tools/rational.hpp>
|
||||
#include <boost/math/tools/series.hpp>
|
||||
#include <boost/math/tools/promotion.hpp>
|
||||
#include <boost/math/policies/error_handling.hpp>
|
||||
#include <boost/math/constants/constants.hpp>
|
||||
#include <boost/mpl/comparison.hpp>
|
||||
#include <boost/math/tools/big_constant.hpp>
|
||||
|
||||
namespace boost{
|
||||
namespace math{
|
||||
namespace detail{
|
||||
|
||||
template<class T, class Policy>
|
||||
T polygamma_imp(const int n, T x, const Policy &pol);
|
||||
|
||||
template <class T, class Policy>
|
||||
T trigamma_prec(T x, const mpl::int_<53>*, const Policy&)
|
||||
{
|
||||
// Max error in interpolated form: 3.736e-017
|
||||
static const T offset = BOOST_MATH_BIG_CONSTANT(T, 53, 2.1093254089355469);
|
||||
static const T P_1_2[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, -1.1093280605946045),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, -3.8310674472619321),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, -3.3703848401898283),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, 0.28080574467981213),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, 1.6638069578676164),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, 0.64468386819102836),
|
||||
};
|
||||
static const T Q_1_2[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, 1.0),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, 3.4535389668541151),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, 4.5208926987851437),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, 2.7012734178351534),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, 0.64468798399785611),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, -0.20314516859987728e-6),
|
||||
};
|
||||
// Max error in interpolated form: 1.159e-017
|
||||
static const T P_2_4[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, -0.13803835004508849e-7),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, 0.50000049158540261),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, 1.6077979838469348),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, 2.5645435828098254),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, 2.0534873203680393),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, 0.74566981111565923),
|
||||
};
|
||||
static const T Q_2_4[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, 1.0),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, 2.8822787662376169),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, 4.1681660554090917),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, 2.7853527819234466),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, 0.74967671848044792),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 53, -0.00057069112416246805),
|
||||
};
|
||||
// Maximum Deviation Found: 6.896e-018
|
||||
// Expected Error Term : -6.895e-018
|
||||
// Maximum Relative Change in Control Points : 8.497e-004
|
||||
static const T P_4_inf[] = {
|
||||
static_cast<T>(0.68947581948701249e-17L),
|
||||
static_cast<T>(0.49999999999998975L),
|
||||
static_cast<T>(1.0177274392923795L),
|
||||
static_cast<T>(2.498208511343429L),
|
||||
static_cast<T>(2.1921221359427595L),
|
||||
static_cast<T>(1.5897035272532764L),
|
||||
static_cast<T>(0.40154388356961734L),
|
||||
};
|
||||
static const T Q_4_inf[] = {
|
||||
static_cast<T>(1.0L),
|
||||
static_cast<T>(1.7021215452463932L),
|
||||
static_cast<T>(4.4290431747556469L),
|
||||
static_cast<T>(2.9745631894384922L),
|
||||
static_cast<T>(2.3013614809773616L),
|
||||
static_cast<T>(0.28360399799075752L),
|
||||
static_cast<T>(0.022892987908906897L),
|
||||
};
|
||||
|
||||
if(x <= 2)
|
||||
{
|
||||
return (offset + boost::math::tools::evaluate_polynomial(P_1_2, x) / tools::evaluate_polynomial(Q_1_2, x)) / (x * x);
|
||||
}
|
||||
else if(x <= 4)
|
||||
{
|
||||
T y = 1 / x;
|
||||
return (1 + tools::evaluate_polynomial(P_2_4, y) / tools::evaluate_polynomial(Q_2_4, y)) / x;
|
||||
}
|
||||
T y = 1 / x;
|
||||
return (1 + tools::evaluate_polynomial(P_4_inf, y) / tools::evaluate_polynomial(Q_4_inf, y)) / x;
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
T trigamma_prec(T x, const mpl::int_<64>*, const Policy&)
|
||||
{
|
||||
// Max error in interpolated form: 1.178e-020
|
||||
static const T offset_1_2 = BOOST_MATH_BIG_CONSTANT(T, 64, 2.109325408935546875);
|
||||
static const T P_1_2[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -1.10932535608960258341),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -4.18793841543017129052),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -4.63865531898487734531),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.919832884430500908047),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 1.68074038333180423012),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 1.21172611429185622377),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.259635673503366427284),
|
||||
};
|
||||
static const T Q_1_2[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 1.0),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 3.77521119359546982995),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 5.664338024578956321),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 4.25995134879278028361),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 1.62956638448940402182),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.259635512844691089868),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.629642219810618032207e-8),
|
||||
};
|
||||
// Max error in interpolated form: 3.912e-020
|
||||
static const T P_2_8[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.387540035162952880976e-11),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.500000000276430504),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 3.21926880986360957306),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 10.2550347708483445775),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 18.9002075150709144043),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 21.0357215832399705625),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 13.4346512182925923978),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 3.98656291026448279118),
|
||||
};
|
||||
static const T Q_2_8[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 1.0),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 6.10520430478613667724),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 18.475001060603645512),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 31.7087534567758405638),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 31.908814523890465398),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 17.4175479039227084798),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 3.98749106958394941276),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.000115917322224411128566),
|
||||
};
|
||||
// Maximum Deviation Found: 2.635e-020
|
||||
// Expected Error Term : 2.635e-020
|
||||
// Maximum Relative Change in Control Points : 1.791e-003
|
||||
static const T P_8_inf[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.263527875092466899848e-19),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.500000000000000058145),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.0730121433777364138677),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 1.94505878379957149534),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.0517092358874932620529),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 1.07995383547483921121),
|
||||
};
|
||||
static const T Q_8_inf[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 1.0),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.187309046577818095504),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 3.95255391645238842975),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -1.14743283327078949087),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 2.52989799376344914499),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, -0.627414303172402506396),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 64, 0.141554248216425512536),
|
||||
};
|
||||
|
||||
if(x <= 2)
|
||||
{
|
||||
return (offset_1_2 + boost::math::tools::evaluate_polynomial(P_1_2, x) / tools::evaluate_polynomial(Q_1_2, x)) / (x * x);
|
||||
}
|
||||
else if(x <= 8)
|
||||
{
|
||||
T y = 1 / x;
|
||||
return (1 + tools::evaluate_polynomial(P_2_8, y) / tools::evaluate_polynomial(Q_2_8, y)) / x;
|
||||
}
|
||||
T y = 1 / x;
|
||||
return (1 + tools::evaluate_polynomial(P_8_inf, y) / tools::evaluate_polynomial(Q_8_inf, y)) / x;
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
T trigamma_prec(T x, const mpl::int_<113>*, const Policy&)
|
||||
{
|
||||
// Max error in interpolated form: 1.916e-035
|
||||
|
||||
static const T P_1_2[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.999999999999999082554457936871832533),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -4.71237311120865266379041700054847734),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -7.94125711970499027763789342500817316),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -5.74657746697664735258222071695644535),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.404213349456398905981223965160595687),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 2.47877781178642876561595890095758896),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 2.07714151702455125992166949812126433),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.858877899162360138844032265418028567),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.20499222604410032375789018837922397),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.0272103140348194747360175268778415049),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.0015764849020876949848954081173520686),
|
||||
};
|
||||
static const T Q_1_2[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.0),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 4.71237311120863419878375031457715223),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 9.58619118655339853449127952145877467),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 11.0940067269829372437561421279054968),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 8.09075424749327792073276309969037885),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 3.87705890159891405185343806884451286),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.22758678701914477836330837816976782),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.249092040606385004109672077814668716),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.0295750413900655597027079600025569048),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.00157648490200498142247694709728858139),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.161264050344059471721062360645432809e-14),
|
||||
};
|
||||
|
||||
// Max error in interpolated form: 8.958e-035
|
||||
static const T P_2_4[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -2.55843734739907925764326773972215085),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -12.2830208240542011967952466273455887),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -23.9195022162767993526575786066414403),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -24.9256431504823483094158828285470862),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -14.7979122765478779075108064826412285),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -4.46654453928610666393276765059122272),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.0191439033405649675717082465687845002),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.515412052554351265708917209749037352),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.195378348786064304378247325360320038),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.0334761282624174313035014426794245393),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.002373665205942206348500250056602687),
|
||||
};
|
||||
static const T Q_2_4[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.0),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 4.80098558454419907830670928248659245),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 9.99220727843170133895059300223445265),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 11.8896146167631330735386697123464976),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 8.96613256683809091593793565879092581),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 4.47254136149624110878909334574485751),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.48600982028196527372434773913633152),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.319570735766764237068541501137990078),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.0407358345787680953107374215319322066),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.00237366520593271641375755486420859837),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.239554887903526152679337256236302116e-15),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.294749244740618656265237072002026314e-17),
|
||||
};
|
||||
|
||||
static const T y_offset_2_4 = BOOST_MATH_BIG_CONSTANT(T, 113, 3.558437347412109375);
|
||||
|
||||
// Max error in interpolated form: 4.319e-035
|
||||
static const T P_4_8[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.166626112697021464248967707021688845e-16),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.499999999999997739552090249208808197),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 6.40270945019053817915772473771553187),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 41.3833374155000608013677627389343329),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 166.803341854562809335667241074035245),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 453.39964786925369319960722793414521),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 851.153712317697055375935433362983944),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1097.70657567285059133109286478004458),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 938.431232478455316020076349367632922),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 487.268001604651932322080970189930074),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 119.953445242335730062471193124820659),
|
||||
};
|
||||
static const T Q_4_8[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.0),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 12.4720855670474488978638945855932398),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 78.6093129753298570701376952709727391),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 307.470246050318322489781182863190127),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 805.140686101151538537565264188630079),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1439.12019760292146454787601409644413),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1735.6105285756048831268586001383127),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1348.32500712856328019355198611280536),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 607.225985860570846699704222144650563),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 119.952317857277045332558673164517227),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.000140165918355036060868680809129436084),
|
||||
};
|
||||
|
||||
// Maximum Deviation Found: 2.867e-035
|
||||
// Expected Error Term : 2.866e-035
|
||||
// Maximum Relative Change in Control Points : 2.662e-004
|
||||
static const T P_8_16[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.184828315274146610610872315609837439e-19),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.500000000000000004122475157735807738),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 3.02533865247313349284875558880415875),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 13.5995927517457371243039532492642734),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 35.3132224283087906757037999452941588),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 67.1639424550714159157603179911505619),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 83.5767733658513967581959839367419891),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 71.073491212235705900866411319363501),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 35.8621515614725564575893663483998663),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 8.72152231639983491987779743154333318),
|
||||
};
|
||||
static const T Q_8_16[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.0),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 5.71734397161293452310624822415866372),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 25.293404179620438179337103263274815),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 62.2619767967468199111077640625328469),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 113.955048909238993473389714972250235),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 130.807138328938966981862203944329408),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 102.423146902337654110717764213057753),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 44.0424772805245202514468199602123565),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 8.89898032477904072082994913461386099),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -0.0296627336872039988632793863671456398),
|
||||
};
|
||||
// Maximum Deviation Found: 1.079e-035
|
||||
// Expected Error Term : -1.079e-035
|
||||
// Maximum Relative Change in Control Points : 7.884e-003
|
||||
static const T P_16_inf[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.0),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.500000000000000000000000000000087317),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.345625669885456215194494735902663968),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 9.62895499360842232127552650044647769),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 3.5936085382439026269301003761320812),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 49.459599118438883265036646019410669),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 7.77519237321893917784735690560496607),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 74.4536074488178075948642351179304121),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 2.75209340397069050436806159297952699),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 23.9292359711471667884504840186561598),
|
||||
};
|
||||
static const T Q_16_inf[] = {
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 1.0),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.357918006437579097055656138920742037),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 19.1386039850709849435325005484512944),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 0.874349081464143606016221431763364517),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 98.6516097434855572678195488061432509),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -16.1051972833382893468655223662534306),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 154.316860216253720989145047141653727),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -40.2026880424378986053105969312264534),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 60.1679136674264778074736441126810223),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, -13.3414844622256422644504472438320114),
|
||||
BOOST_MATH_BIG_CONSTANT(T, 113, 2.53795636200649908779512969030363442),
|
||||
};
|
||||
|
||||
if(x <= 2)
|
||||
{
|
||||
return (2 + boost::math::tools::evaluate_polynomial(P_1_2, x) / tools::evaluate_polynomial(Q_1_2, x)) / (x * x);
|
||||
}
|
||||
else if(x <= 4)
|
||||
{
|
||||
return (y_offset_2_4 + boost::math::tools::evaluate_polynomial(P_2_4, x) / tools::evaluate_polynomial(Q_2_4, x)) / (x * x);
|
||||
}
|
||||
else if(x <= 8)
|
||||
{
|
||||
T y = 1 / x;
|
||||
return (1 + tools::evaluate_polynomial(P_4_8, y) / tools::evaluate_polynomial(Q_4_8, y)) / x;
|
||||
}
|
||||
else if(x <= 16)
|
||||
{
|
||||
T y = 1 / x;
|
||||
return (1 + tools::evaluate_polynomial(P_8_16, y) / tools::evaluate_polynomial(Q_8_16, y)) / x;
|
||||
}
|
||||
T y = 1 / x;
|
||||
return (1 + tools::evaluate_polynomial(P_16_inf, y) / tools::evaluate_polynomial(Q_16_inf, y)) / x;
|
||||
}
|
||||
|
||||
template <class T, class Tag, class Policy>
|
||||
T trigamma_imp(T x, const Tag* t, const Policy& pol)
|
||||
{
|
||||
//
|
||||
// This handles reflection of negative arguments, and all our
|
||||
// error handling, then forwards to the T-specific approximation.
|
||||
//
|
||||
BOOST_MATH_STD_USING // ADL of std functions.
|
||||
|
||||
T result = 0;
|
||||
//
|
||||
// Check for negative arguments and use reflection:
|
||||
//
|
||||
if(x <= 0)
|
||||
{
|
||||
// Reflect:
|
||||
T z = 1 - x;
|
||||
// Argument reduction for tan:
|
||||
if(floor(x) == x)
|
||||
{
|
||||
return policies::raise_pole_error<T>("boost::math::trigamma<%1%>(%1%)", 0, (1-x), pol);
|
||||
}
|
||||
T s = fabs(x) < fabs(z) ? boost::math::sin_pi(x, pol) : boost::math::sin_pi(z, pol);
|
||||
return -trigamma_imp(z, t, pol) + boost::math::pow<2>(constants::pi<T>()) / (s * s);
|
||||
}
|
||||
if(x < 1)
|
||||
{
|
||||
result = 1 / (x * x);
|
||||
x += 1;
|
||||
}
|
||||
return result + trigamma_prec(x, t, pol);
|
||||
}
|
||||
|
||||
template <class T, class Policy>
|
||||
T trigamma_imp(T x, const mpl::int_<0>*, const Policy& pol)
|
||||
{
|
||||
return polygamma_imp(1, x, pol);
|
||||
}
|
||||
//
|
||||
// Initializer: ensure all our constants are initialized prior to the first call of main:
|
||||
//
|
||||
template <class T, class Policy>
|
||||
struct trigamma_initializer
|
||||
{
|
||||
struct init
|
||||
{
|
||||
init()
|
||||
{
|
||||
typedef typename policies::precision<T, Policy>::type precision_type;
|
||||
do_init(mpl::bool_<precision_type::value && (precision_type::value <= 113)>());
|
||||
}
|
||||
void do_init(const mpl::true_&)
|
||||
{
|
||||
boost::math::trigamma(T(2.5), Policy());
|
||||
}
|
||||
void do_init(const mpl::false_&){}
|
||||
void force_instantiate()const{}
|
||||
};
|
||||
static const init initializer;
|
||||
static void force_instantiate()
|
||||
{
|
||||
initializer.force_instantiate();
|
||||
}
|
||||
};
|
||||
|
||||
template <class T, class Policy>
|
||||
const typename trigamma_initializer<T, Policy>::init trigamma_initializer<T, Policy>::initializer;
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <class T, class Policy>
|
||||
inline typename tools::promote_args<T>::type
|
||||
trigamma(T x, const Policy&)
|
||||
{
|
||||
typedef typename tools::promote_args<T>::type result_type;
|
||||
typedef typename policies::evaluation<result_type, Policy>::type value_type;
|
||||
typedef typename policies::precision<T, Policy>::type precision_type;
|
||||
typedef typename mpl::if_<
|
||||
mpl::or_<
|
||||
mpl::less_equal<precision_type, mpl::int_<0> >,
|
||||
mpl::greater<precision_type, mpl::int_<114> >
|
||||
>,
|
||||
mpl::int_<0>,
|
||||
typename mpl::if_<
|
||||
mpl::less<precision_type, mpl::int_<54> >,
|
||||
mpl::int_<53>,
|
||||
typename mpl::if_<
|
||||
mpl::less<precision_type, mpl::int_<65> >,
|
||||
mpl::int_<64>,
|
||||
mpl::int_<113>
|
||||
>::type
|
||||
>::type
|
||||
>::type tag_type;
|
||||
|
||||
typedef typename policies::normalise<
|
||||
Policy,
|
||||
policies::promote_float<false>,
|
||||
policies::promote_double<false>,
|
||||
policies::discrete_quantile<>,
|
||||
policies::assert_undefined<> >::type forwarding_policy;
|
||||
|
||||
// Force initialization of constants:
|
||||
detail::trigamma_initializer<value_type, forwarding_policy>::force_instantiate();
|
||||
|
||||
return policies::checked_narrowing_cast<result_type, Policy>(detail::trigamma_imp(
|
||||
static_cast<value_type>(x),
|
||||
static_cast<const tag_type*>(0), forwarding_policy()), "boost::math::trigamma<%1%>(%1%)");
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline typename tools::promote_args<T>::type
|
||||
trigamma(T x)
|
||||
{
|
||||
return trigamma(x, policies::policy<>());
|
||||
}
|
||||
|
||||
} // namespace math
|
||||
} // namespace boost
|
||||
#endif
|
||||
|
||||
@@ -1,234 +0,0 @@
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// (See accompanying file LICENSE.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
#ifndef BOOST_SERIALIZATION_UNORDERED_MAP_HPP
|
||||
#define BOOST_SERIALIZATION_UNORDERED_MAP_HPP
|
||||
|
||||
// MS compatible compilers support #pragma once
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
|
||||
// serialization/unordered_map.hpp:
|
||||
// serialization for stl unordered_map templates
|
||||
|
||||
// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com .
|
||||
// (C) Copyright 2014 Jim Bell
|
||||
// Use, modification and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// See http://www.boost.org for updates, documentation, and revision history.
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
#include <boost/serialization/utility.hpp>
|
||||
#include "unordered_collections_save_imp.hpp"
|
||||
#include "unordered_collections_load_imp.hpp"
|
||||
#include <boost/serialization/split_free.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace serialization {
|
||||
|
||||
namespace stl {
|
||||
|
||||
// map input
|
||||
template<class Archive, class Container>
|
||||
struct archive_input_unordered_map
|
||||
{
|
||||
inline void operator()(
|
||||
Archive &ar,
|
||||
Container &s,
|
||||
const unsigned int v
|
||||
){
|
||||
typedef typename Container::value_type type;
|
||||
detail::stack_construct<Archive, type> t(ar, v);
|
||||
// borland fails silently w/o full namespace
|
||||
ar >> boost::serialization::make_nvp("item", t.reference());
|
||||
std::pair<typename Container::const_iterator, bool> result =
|
||||
s.insert(t.reference());
|
||||
// note: the following presumes that the map::value_type was NOT tracked
|
||||
// in the archive. This is the usual case, but here there is no way
|
||||
// to determine that.
|
||||
if(result.second){
|
||||
ar.reset_object_address(
|
||||
& (result.first->second),
|
||||
& t.reference().second
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// multimap input
|
||||
template<class Archive, class Container>
|
||||
struct archive_input_unordered_multimap
|
||||
{
|
||||
inline void operator()(
|
||||
Archive &ar,
|
||||
Container &s,
|
||||
const unsigned int v
|
||||
){
|
||||
typedef typename Container::value_type type;
|
||||
detail::stack_construct<Archive, type> t(ar, v);
|
||||
// borland fails silently w/o full namespace
|
||||
ar >> boost::serialization::make_nvp("item", t.reference());
|
||||
typename Container::const_iterator result
|
||||
= s.insert(t.reference());
|
||||
// note: the following presumes that the map::value_type was NOT tracked
|
||||
// in the archive. This is the usual case, but here there is no way
|
||||
// to determine that.
|
||||
ar.reset_object_address(
|
||||
& result->second,
|
||||
& t.reference()
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
} // stl
|
||||
|
||||
template<
|
||||
class Archive,
|
||||
class Key,
|
||||
class HashFcn,
|
||||
class EqualKey,
|
||||
class Allocator
|
||||
>
|
||||
inline void save(
|
||||
Archive & ar,
|
||||
const std::unordered_map<
|
||||
Key, HashFcn, EqualKey, Allocator
|
||||
> &t,
|
||||
const unsigned int /*file_version*/
|
||||
){
|
||||
boost::serialization::stl::save_unordered_collection<
|
||||
Archive,
|
||||
std::unordered_map<
|
||||
Key, HashFcn, EqualKey, Allocator
|
||||
>
|
||||
>(ar, t);
|
||||
}
|
||||
|
||||
template<
|
||||
class Archive,
|
||||
class Key,
|
||||
class HashFcn,
|
||||
class EqualKey,
|
||||
class Allocator
|
||||
>
|
||||
inline void load(
|
||||
Archive & ar,
|
||||
std::unordered_map<
|
||||
Key, HashFcn, EqualKey, Allocator
|
||||
> &t,
|
||||
const unsigned int /*file_version*/
|
||||
){
|
||||
boost::serialization::stl::load_unordered_collection<
|
||||
Archive,
|
||||
std::unordered_map<
|
||||
Key, HashFcn, EqualKey, Allocator
|
||||
>,
|
||||
boost::serialization::stl::archive_input_unordered_map<
|
||||
Archive,
|
||||
std::unordered_map<
|
||||
Key, HashFcn, EqualKey, Allocator
|
||||
>
|
||||
>
|
||||
>(ar, t);
|
||||
}
|
||||
|
||||
// split non-intrusive serialization function member into separate
|
||||
// non intrusive save/load member functions
|
||||
template<
|
||||
class Archive,
|
||||
class Key,
|
||||
class HashFcn,
|
||||
class EqualKey,
|
||||
class Allocator
|
||||
>
|
||||
inline void serialize(
|
||||
Archive & ar,
|
||||
std::unordered_map<
|
||||
Key, HashFcn, EqualKey, Allocator
|
||||
> &t,
|
||||
const unsigned int file_version
|
||||
){
|
||||
boost::serialization::split_free(ar, t, file_version);
|
||||
}
|
||||
|
||||
// unordered_multimap
|
||||
template<
|
||||
class Archive,
|
||||
class Key,
|
||||
class HashFcn,
|
||||
class EqualKey,
|
||||
class Allocator
|
||||
>
|
||||
inline void save(
|
||||
Archive & ar,
|
||||
const std::unordered_multimap<
|
||||
Key, HashFcn, EqualKey, Allocator
|
||||
> &t,
|
||||
const unsigned int /*file_version*/
|
||||
){
|
||||
boost::serialization::stl::save_unordered_collection<
|
||||
Archive,
|
||||
std::unordered_multimap<
|
||||
Key, HashFcn, EqualKey, Allocator
|
||||
>
|
||||
>(ar, t);
|
||||
}
|
||||
|
||||
template<
|
||||
class Archive,
|
||||
class Key,
|
||||
class HashFcn,
|
||||
class EqualKey,
|
||||
class Allocator
|
||||
>
|
||||
inline void load(
|
||||
Archive & ar,
|
||||
std::unordered_multimap<
|
||||
Key, HashFcn, EqualKey, Allocator
|
||||
> &t,
|
||||
const unsigned int /*file_version*/
|
||||
){
|
||||
boost::serialization::stl::load_unordered_collection<
|
||||
Archive,
|
||||
std::unordered_multimap<
|
||||
Key, HashFcn, EqualKey, Allocator
|
||||
>,
|
||||
boost::serialization::stl::archive_input_unordered_multimap<
|
||||
Archive,
|
||||
std::unordered_multimap<
|
||||
Key, HashFcn, EqualKey, Allocator
|
||||
>
|
||||
>
|
||||
>(ar, t);
|
||||
}
|
||||
|
||||
// split non-intrusive serialization function member into separate
|
||||
// non intrusive save/load member functions
|
||||
template<
|
||||
class Archive,
|
||||
class Key,
|
||||
class HashFcn,
|
||||
class EqualKey,
|
||||
class Allocator
|
||||
>
|
||||
inline void serialize(
|
||||
Archive & ar,
|
||||
std::unordered_multimap<
|
||||
Key, HashFcn, EqualKey, Allocator
|
||||
> &t,
|
||||
const unsigned int file_version
|
||||
){
|
||||
boost::serialization::split_free(ar, t, file_version);
|
||||
}
|
||||
|
||||
} // namespace serialization
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_SERIALIZATION_UNORDERED_MAP_HPP
|
||||
@@ -13,6 +13,8 @@ set(SOURCES
|
||||
precision_impl.hpp
|
||||
recall.hpp
|
||||
recall_impl.hpp
|
||||
r2_score.hpp
|
||||
r2_score_impl.hpp
|
||||
)
|
||||
|
||||
# Add directory name to sources.
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
/**
|
||||
* @file r2_score.hpp
|
||||
* @author Bisakh Mondal
|
||||
*
|
||||
* The R^2 (Coefficient of determination) regression metric.
|
||||
*
|
||||
* 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_CV_METRICS_R2SCORE_HPP
|
||||
#define MLPACK_CORE_CV_METRICS_R2SCORE_HPP
|
||||
|
||||
#include <mlpack/core.hpp>
|
||||
|
||||
namespace mlpack {
|
||||
namespace cv {
|
||||
|
||||
/**
|
||||
* The R2 Score is a metric of performance for regression algorithms
|
||||
* that represents the proportion of variance (here y) that has been
|
||||
* explained by the independent variables in the model. It provides
|
||||
* an indication of goodness of fit and therefore a measure of how
|
||||
* well unseen samples are likely to be predicted by the model,
|
||||
* through the proportion of explained variance.
|
||||
* As R2 Score is dataset dependent it can have wide range of values. The
|
||||
* best possible score is @f$R^2 =1.0@f$. Values of R2 outside the range
|
||||
* 0 to 1 can occur when the model fits the data worse than a horizontal
|
||||
* hyperplane. This would occur when the wrong model was chosen, or
|
||||
* nonsensical constraints were applied by mistake. A model which
|
||||
* predicts exactly the expected value of y, disregarding the input
|
||||
* features, gets a R2 Score equals to 0.0.
|
||||
* If a model predicts @f$ \hat{y}_i $@f of the @f$ i $@f-th sample for a true
|
||||
* @f$ y_i $@f for total n samples, the R2 Score is calculated by
|
||||
* @f{eqnarray*}{
|
||||
* R^{2} \left( y, \hat{y} \right) &=& 1-\frac{\sum_{i=1}^{n}
|
||||
* \left( y_i - \hat{y_i} \right)^2 }
|
||||
* {\sum_{i=1}^{n} \left( y_i - \bar{y}\right)^2}\\
|
||||
* @f}
|
||||
*
|
||||
* where @f$ \bar{y} = frac{1}{y}\sum_{i=1}^{n} y_i $@f.
|
||||
* For example, a model having R2Score = 0.85, explains 85 \% variability of
|
||||
* the response data around its mean.
|
||||
*/
|
||||
class R2Score
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Run prediction and calculate the R squared error.
|
||||
*
|
||||
* @param model A regression model.
|
||||
* @param data Column-major data containing test items.
|
||||
* @param responses Ground truth (correct) target values for the test items,
|
||||
* should be either a row vector or a column-major matrix.
|
||||
* @return calculated R2 Score.
|
||||
*/
|
||||
template<typename MLAlgorithm, typename DataType, typename ResponsesType>
|
||||
static double Evaluate(MLAlgorithm& model,
|
||||
const DataType& data,
|
||||
const ResponsesType& responses);
|
||||
|
||||
/**
|
||||
* Information for hyper-parameter tuning code. It indicates that we want
|
||||
* to maximize the measurement.
|
||||
*/
|
||||
static const bool NeedsMinimization = false;
|
||||
};
|
||||
|
||||
} // namespace cv
|
||||
} // namespace mlpack
|
||||
|
||||
// Include implementation.
|
||||
#include "r2_score_impl.hpp"
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,55 @@
|
||||
/**
|
||||
* @file r2_score_impl.hpp
|
||||
* @author Bisakh Mondal
|
||||
*
|
||||
* The implementation of the class R2Score.
|
||||
*
|
||||
* 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_CV_METRICS_R2SCORE_IMPL_HPP
|
||||
#define MLPACK_CORE_CV_METRICS_R2SCORE_IMPL_HPP
|
||||
|
||||
namespace mlpack {
|
||||
namespace cv {
|
||||
|
||||
template<typename MLAlgorithm, typename DataType, typename ResponsesType>
|
||||
double R2Score::Evaluate(MLAlgorithm& model,
|
||||
const DataType& data,
|
||||
const ResponsesType& responses)
|
||||
{
|
||||
if (data.n_cols != responses.n_cols)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << "R2Score::Evaluate(): number of points (" << data.n_cols << ") "
|
||||
<< "does not match number of responses (" << responses.n_cols << ")!"
|
||||
<< std::endl;
|
||||
throw std::invalid_argument(oss.str());
|
||||
}
|
||||
|
||||
ResponsesType predictedResponses;
|
||||
// Taking Predicted Output from the model.
|
||||
model.Predict(data, predictedResponses);
|
||||
// Mean value of response.
|
||||
double meanResponses = arma::mean(responses);
|
||||
|
||||
// Calculate the numerator i.e. residual sum of squares.
|
||||
double residualSumSquared = arma::accu(arma::square(responses -
|
||||
predictedResponses));
|
||||
|
||||
// Calculate the denominator i.e.total sum of squares.
|
||||
double totalSumSquared = arma::accu(arma::square(responses - meanResponses));
|
||||
|
||||
// Handling undefined R2 Score when both denominator and numerator is 0.0.
|
||||
if (residualSumSquared == 0.0)
|
||||
return totalSumSquared ? 1.0 : DBL_MIN;
|
||||
|
||||
return 1 - residualSumSquared / totalSumSquared;
|
||||
}
|
||||
|
||||
} // namespace cv
|
||||
} // namespace mlpack
|
||||
|
||||
#endif
|
||||
@@ -11,6 +11,7 @@ set(SOURCES
|
||||
load_csv.cpp
|
||||
load.hpp
|
||||
load_image_impl.hpp
|
||||
load_image.cpp
|
||||
load_model_impl.hpp
|
||||
load_vec_impl.hpp
|
||||
load_impl.hpp
|
||||
@@ -21,6 +22,7 @@ set(SOURCES
|
||||
normalize_labels_impl.hpp
|
||||
save.hpp
|
||||
save_impl.hpp
|
||||
save_image.cpp
|
||||
serialization_template_version.hpp
|
||||
split_data.hpp
|
||||
imputer.hpp
|
||||
|
||||
@@ -13,28 +13,12 @@
|
||||
#ifndef MLPACK_CORE_DATA_IMAGE_INFO_HPP
|
||||
#define MLPACK_CORE_DATA_IMAGE_INFO_HPP
|
||||
|
||||
|
||||
#include <mlpack/prereqs.hpp>
|
||||
|
||||
#include "extension.hpp"
|
||||
|
||||
#ifdef HAS_STB // Compile this only if stb is present.
|
||||
|
||||
#define STB_IMAGE_STATIC
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#include <stb_image.h>
|
||||
|
||||
#define STB_IMAGE_WRITE_STATIC
|
||||
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
||||
#include <stb_image_write.h>
|
||||
|
||||
#endif
|
||||
|
||||
namespace mlpack {
|
||||
namespace data {
|
||||
|
||||
#ifdef HAS_STB // Compile this only if stb is present.
|
||||
|
||||
/**
|
||||
* Checks if the given image filename is supported.
|
||||
*
|
||||
@@ -44,8 +28,6 @@ namespace data {
|
||||
inline bool ImageFormatSupported(const std::string& fileName,
|
||||
const bool save = false);
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Implements meta-data of images required by data::Load and
|
||||
* data::Save for loading and saving images into arma::Mat.
|
||||
@@ -87,6 +69,15 @@ class ImageInfo
|
||||
//! Modify the image quality.
|
||||
size_t& Quality() { return quality; }
|
||||
|
||||
template<typename Archive>
|
||||
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;
|
||||
|
||||
@@ -291,7 +291,6 @@ bool Load(const std::string& filename,
|
||||
/**
|
||||
* Image load/save interfaces.
|
||||
*/
|
||||
#ifdef HAS_STB
|
||||
|
||||
/**
|
||||
* Load the image file into the given matrix.
|
||||
@@ -300,15 +299,13 @@ bool Load(const std::string& filename,
|
||||
* @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, transpose the matrix after loading.
|
||||
* @return Boolean value indicating success or failure of load.
|
||||
*/
|
||||
template<typename eT>
|
||||
bool Load(const std::string& filename,
|
||||
arma::Mat<eT>& matrix,
|
||||
ImageInfo& info,
|
||||
const bool fatal = false,
|
||||
const bool transpose = true);
|
||||
const bool fatal = false);
|
||||
|
||||
/**
|
||||
* Load the image file into the given matrix.
|
||||
@@ -324,10 +321,13 @@ template<typename eT>
|
||||
bool Load(const std::vector<std::string>& files,
|
||||
arma::Mat<eT>& matrix,
|
||||
ImageInfo& info,
|
||||
const bool fatal = false,
|
||||
const bool transpose = true);
|
||||
const bool fatal = false);
|
||||
|
||||
#endif // HAS_STB.
|
||||
// Implementation found in load_image.cpp.
|
||||
bool LoadImage(const std::string& filename,
|
||||
arma::Mat<unsigned char>& matrix,
|
||||
ImageInfo& info,
|
||||
const bool fatal = false);
|
||||
|
||||
} // namespace data
|
||||
} // namespace mlpack
|
||||
|
||||
@@ -0,0 +1,125 @@
|
||||
/**
|
||||
* @file load_image.cpp
|
||||
* @author Mehul Kumar Nirala
|
||||
*
|
||||
* Implementation of image loading functionality via STB.
|
||||
*/
|
||||
#include "load.hpp"
|
||||
#include "image_info.hpp"
|
||||
|
||||
#ifdef HAS_STB
|
||||
|
||||
#define STB_IMAGE_STATIC
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#include <stb_image.h>
|
||||
|
||||
#define STB_IMAGE_WRITE_STATIC
|
||||
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
||||
#include <stb_image_write.h>
|
||||
|
||||
namespace mlpack {
|
||||
namespace data {
|
||||
|
||||
bool LoadImage(const std::string& filename,
|
||||
arma::Mat<unsigned char>& matrix,
|
||||
ImageInfo& info,
|
||||
const bool fatal)
|
||||
{
|
||||
unsigned char* image;
|
||||
|
||||
if (!ImageFormatSupported(filename))
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << "Load(): file type " << Extension(filename) << " not supported. ";
|
||||
oss << "Currently it supports: ";
|
||||
for (auto extension : loadFileTypes)
|
||||
oss << " " << extension;
|
||||
oss << "." << std::endl;
|
||||
|
||||
if (fatal)
|
||||
{
|
||||
Log::Fatal << oss.str();
|
||||
}
|
||||
else
|
||||
{
|
||||
Log::Warn << oss.str();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Temporary variables needed as stb_image.h supports int parameters.
|
||||
int tempWidth, tempHeight, tempChannels;
|
||||
|
||||
// For grayscale images.
|
||||
if (info.Channels() == 1)
|
||||
{
|
||||
image = stbi_load(filename.c_str(), &tempWidth, &tempHeight, &tempChannels,
|
||||
STBI_grey);
|
||||
}
|
||||
else
|
||||
{
|
||||
image = stbi_load(filename.c_str(), &tempWidth, &tempHeight, &tempChannels,
|
||||
STBI_rgb);
|
||||
}
|
||||
|
||||
if (!image)
|
||||
{
|
||||
if (fatal)
|
||||
{
|
||||
Log::Fatal << "Load(): failed to load image '" << filename << "': "
|
||||
<< stbi_failure_reason() << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
Log::Warn << "Load(): failed to load image '" << filename << "': "
|
||||
<< stbi_failure_reason() << std::endl;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
info.Width() = tempWidth;
|
||||
info.Height() = tempHeight;
|
||||
info.Channels() = tempChannels;
|
||||
|
||||
// Copy image into armadillo Mat.
|
||||
matrix = arma::Mat<unsigned char>(image, info.Width() * info.Height() *
|
||||
info.Channels(), 1, true, true);
|
||||
|
||||
// Free the image pointer.
|
||||
free(image);
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace data
|
||||
} // namespace mlpack
|
||||
|
||||
#else
|
||||
|
||||
namespace mlpack {
|
||||
namespace data {
|
||||
|
||||
bool LoadImage(const std::string& /* filename */,
|
||||
arma::Mat<unsigned char>& /* matrix */,
|
||||
ImageInfo& /* info */,
|
||||
const bool fatal)
|
||||
{
|
||||
if (fatal)
|
||||
{
|
||||
Log::Fatal << "Load(): mlpack was not compiled with STB support, so images "
|
||||
<< "cannot be loaded!" << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
Log::Warn << "Load(): mlpack was not compiled with STB support, so images "
|
||||
<< "cannot be loaded!" << std::endl;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace data
|
||||
} // namespace mlpack
|
||||
|
||||
#endif
|
||||
@@ -19,68 +19,28 @@
|
||||
namespace mlpack {
|
||||
namespace data {
|
||||
|
||||
#ifdef HAS_STB // Compile this only if stb is present.
|
||||
|
||||
// Image loading API.
|
||||
template<typename eT>
|
||||
bool Load(const std::string& filename,
|
||||
arma::Mat<eT>& matrix,
|
||||
ImageInfo& info,
|
||||
const bool /* fatal */,
|
||||
const bool transpose)
|
||||
const bool fatal)
|
||||
{
|
||||
Timer::Start("loading_image");
|
||||
unsigned char* image;
|
||||
|
||||
if (!ImageFormatSupported(filename))
|
||||
// STB loads into unsigned char matrices, so we may have to convert once
|
||||
// loaded.
|
||||
arma::Mat<unsigned char> tempMatrix;
|
||||
const bool result = LoadImage(filename, tempMatrix, info, fatal);
|
||||
|
||||
// If fatal is true, then the program will have already thrown an exception.
|
||||
if (!result)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << "File type " << Extension(filename) << " not supported.\n";
|
||||
oss << "Currently it supports ";
|
||||
for (auto extension : loadFileTypes)
|
||||
oss << " " << extension;
|
||||
oss << std::endl;
|
||||
throw std::runtime_error(oss.str());
|
||||
Timer::Stop("loading_image");
|
||||
return false;
|
||||
}
|
||||
|
||||
stbi_set_flip_vertically_on_load(transpose);
|
||||
|
||||
// Temporary variables needed as stb_image.h supports int parameters.
|
||||
int tempWidth, tempHeight, tempChannels;
|
||||
|
||||
// For grayscale images.
|
||||
if (info.Channels() == 1)
|
||||
{
|
||||
image = stbi_load(filename.c_str(), &tempWidth, &tempHeight, &tempChannels,
|
||||
STBI_grey);
|
||||
}
|
||||
else
|
||||
{
|
||||
image = stbi_load(filename.c_str(), &tempWidth, &tempHeight, &tempChannels,
|
||||
STBI_rgb);
|
||||
}
|
||||
|
||||
if (tempWidth <= 0 || tempHeight <= 0)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << "Image '" << filename << "' not found." << std::endl;
|
||||
free(image);
|
||||
throw std::runtime_error(oss.str());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
info.Width() = tempWidth;
|
||||
info.Height() = tempHeight;
|
||||
info.Channels() = tempChannels;
|
||||
|
||||
// Copy image into armadillo Mat.
|
||||
matrix = arma::Mat<unsigned char>(image, info.Width() * info.Height() *
|
||||
info.Channels(), 1, true, true);
|
||||
|
||||
// Free the image pointer.
|
||||
free(image);
|
||||
matrix = arma::conv_to<arma::Mat<eT>>::from(tempMatrix);
|
||||
Timer::Stop("loading_image");
|
||||
return true;
|
||||
}
|
||||
@@ -90,58 +50,46 @@ template<typename eT>
|
||||
bool Load(const std::vector<std::string>& files,
|
||||
arma::Mat<eT>& matrix,
|
||||
ImageInfo& info,
|
||||
const bool fatal,
|
||||
const bool transpose)
|
||||
const bool fatal)
|
||||
{
|
||||
if (files.size() == 0)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << "Files vector is empty." << std::endl;
|
||||
oss << "Load(): vector of image files is empty." << std::endl;
|
||||
|
||||
if (fatal)
|
||||
Log::Fatal << oss.str();
|
||||
else
|
||||
Log::Warn << oss.str();
|
||||
|
||||
throw std::runtime_error(oss.str());
|
||||
return false;
|
||||
}
|
||||
|
||||
arma::Mat<unsigned char> img;
|
||||
bool status = Load(files[0], img, info, fatal, transpose);
|
||||
bool status = LoadImage(files[0], img, info, fatal);
|
||||
|
||||
if (!status)
|
||||
return false;
|
||||
|
||||
// Decide matrix dimension using the image height and width.
|
||||
matrix.set_size(info.Width() * info.Height() * info.Channels(), files.size());
|
||||
matrix.col(0) = img;
|
||||
arma::Mat<unsigned char> tmpMatrix(
|
||||
info.Width() * info.Height() * info.Channels(), files.size());
|
||||
tmpMatrix.col(0) = img;
|
||||
|
||||
for (size_t i = 1; i < files.size() ; i++)
|
||||
{
|
||||
arma::Mat<unsigned char> colImg(matrix.colptr(i), matrix.n_rows, 1,
|
||||
arma::Mat<unsigned char> colImg(tmpMatrix.colptr(i), tmpMatrix.n_rows, 1,
|
||||
false, true);
|
||||
status &= Load(files[i], colImg, info, fatal, transpose);
|
||||
status = LoadImage(files[i], colImg, info, fatal);
|
||||
|
||||
if (!status)
|
||||
return false;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
#else // No STB.
|
||||
template<typename eT>
|
||||
bool Load(const std::string& filename,
|
||||
arma::Mat<eT>& matrix,
|
||||
ImageInfo& info,
|
||||
const bool fatal = false,
|
||||
const bool transpose = true)
|
||||
{
|
||||
throw std::runtime_error("Load(): HAS_STB is not defined, "
|
||||
"so STB is not available and images cannot be loaded!");
|
||||
matrix = arma::conv_to<arma::Mat<eT>>::from(tmpMatrix);
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename eT>
|
||||
bool Load(const std::vector<std::string>& files,
|
||||
arma::Mat<eT>& matrix,
|
||||
ImageInfo& info,
|
||||
const bool fatal = false,
|
||||
const bool transpose = true)
|
||||
{
|
||||
throw std::runtime_error("Load(): HAS_STB is not defined, "
|
||||
"so STB is not available and images cannot be loaded!");
|
||||
}
|
||||
#endif // HAS_STB.
|
||||
|
||||
} // namespace data
|
||||
} // namespace mlpack
|
||||
|
||||
|
||||
@@ -91,8 +91,6 @@ bool Save(const std::string& filename,
|
||||
const bool fatal = false,
|
||||
format f = format::autodetect);
|
||||
|
||||
#ifdef HAS_STB
|
||||
|
||||
/**
|
||||
* Save the image file from the given matrix.
|
||||
*
|
||||
@@ -107,8 +105,7 @@ template<typename eT>
|
||||
bool Save(const std::string& filename,
|
||||
arma::Mat<eT>& matrix,
|
||||
ImageInfo& info,
|
||||
const bool fatal = false,
|
||||
const bool transpose = true);
|
||||
const bool fatal = false);
|
||||
|
||||
/**
|
||||
* Save the image file from the given matrix.
|
||||
@@ -124,10 +121,15 @@ template<typename eT>
|
||||
bool Save(const std::vector<std::string>& files,
|
||||
arma::Mat<eT>& matrix,
|
||||
ImageInfo& info,
|
||||
const bool fatal = false,
|
||||
const bool transpose = true);
|
||||
const bool fatal = false);
|
||||
|
||||
#endif // HAS_STB.
|
||||
/**
|
||||
* Helper function to save files. Implementation in save_image.cpp.
|
||||
*/
|
||||
bool SaveImage(const std::string& filename,
|
||||
arma::Mat<unsigned char>& image,
|
||||
ImageInfo& info,
|
||||
const bool fatal = false);
|
||||
|
||||
} // namespace data
|
||||
} // namespace mlpack
|
||||
|
||||
@@ -0,0 +1,141 @@
|
||||
/**
|
||||
* @file save_image.cpp
|
||||
* @author Mehul Kumar Nirala
|
||||
*
|
||||
* Implementation of image saving functionality via STB.
|
||||
*/
|
||||
#include "save.hpp"
|
||||
|
||||
#ifdef HAS_STB
|
||||
|
||||
#define STB_IMAGE_STATIC
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#include <stb_image.h>
|
||||
|
||||
#define STB_IMAGE_WRITE_STATIC
|
||||
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
||||
#include <stb_image_write.h>
|
||||
|
||||
namespace mlpack {
|
||||
namespace data {
|
||||
|
||||
bool SaveImage(const std::string& filename,
|
||||
arma::Mat<unsigned char>& image,
|
||||
ImageInfo& info,
|
||||
const bool fatal)
|
||||
{
|
||||
// Check to see if the file type is supported.
|
||||
if (!ImageFormatSupported(filename, true))
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << "Save(): file type " << Extension(filename) << " not supported.\n";
|
||||
oss << "Currently image saving supports ";
|
||||
for (auto extension : saveFileTypes)
|
||||
oss << ", " << extension;
|
||||
oss << "." << std::endl;
|
||||
|
||||
if (fatal)
|
||||
{
|
||||
Log::Fatal << oss.str();
|
||||
}
|
||||
else
|
||||
{
|
||||
Log::Warn << oss.str();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Ensure the shape of the matrix is correct.
|
||||
if (image.n_cols > 1)
|
||||
{
|
||||
Log::Warn << "Save(): given input image matrix contains more than 1 image."
|
||||
<< std::endl;
|
||||
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();
|
||||
|
||||
if ("png" == Extension(filename))
|
||||
{
|
||||
status = stbi_write_png(filename.c_str(), info.Width(), info.Height(),
|
||||
info.Channels(), imageMem, info.Width() * info.Channels());
|
||||
}
|
||||
else if ("bmp" == Extension(filename))
|
||||
{
|
||||
status = stbi_write_bmp(filename.c_str(), info.Width(), info.Height(),
|
||||
info.Channels(), imageMem);
|
||||
}
|
||||
else if ("tga" == Extension(filename))
|
||||
{
|
||||
status = stbi_write_tga(filename.c_str(), info.Width(), info.Height(),
|
||||
info.Channels(), imageMem);
|
||||
}
|
||||
else if ("hdr" == Extension(filename))
|
||||
{
|
||||
// We'll have to convert to float...
|
||||
arma::fmat tmpImage = arma::conv_to<arma::fmat>::from(image);
|
||||
status = stbi_write_hdr(filename.c_str(), info.Width(), info.Height(),
|
||||
info.Channels(), tmpImage.memptr());
|
||||
}
|
||||
else if ("jpg" == Extension(filename))
|
||||
{
|
||||
status = stbi_write_jpg(filename.c_str(), info.Width(), info.Height(),
|
||||
info.Channels(), imageMem, info.Quality());
|
||||
}
|
||||
|
||||
if (!status)
|
||||
{
|
||||
if (fatal)
|
||||
{
|
||||
Log::Fatal << "Save(): error saving image to '" << filename << "'."
|
||||
<< std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
Log::Warn << "Save(): error saving image to '" << filename << "'."
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
} // namespace data
|
||||
} // namespace mlpack
|
||||
|
||||
#else
|
||||
|
||||
namespace mlpack {
|
||||
namespace data {
|
||||
|
||||
bool SaveImage(const std::string& /* filename */,
|
||||
arma::Mat<unsigned char>& /* image */,
|
||||
ImageInfo& /* info */,
|
||||
const bool fatal)
|
||||
{
|
||||
if (fatal)
|
||||
{
|
||||
Log::Fatal << "Save(): mlpack was not compiled with STB support, so images "
|
||||
<< "cannot be saved!" << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
Log::Warn << "Save(): mlpack was not compiled with STB support, so images "
|
||||
<< "cannot be saved!" << std::endl;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace data
|
||||
} // namespace mlpack
|
||||
|
||||
#endif
|
||||
@@ -283,86 +283,25 @@ bool Save(const std::string& filename,
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAS_STB
|
||||
// Image saving API.
|
||||
/**
|
||||
* Save the given image to the given filename.
|
||||
*
|
||||
* @param filename Filename to save to.
|
||||
* @param matrix Matrix containing image to be saved.
|
||||
* @param info Information about the image (width/height/channels/etc.).
|
||||
* @param fatal Whether an exception should be thrown on save failure.
|
||||
*/
|
||||
template<typename eT>
|
||||
bool Save(const std::string& filename,
|
||||
arma::Mat<eT>& matrix,
|
||||
ImageInfo& info,
|
||||
const bool fatal,
|
||||
const bool transpose)
|
||||
const bool fatal)
|
||||
{
|
||||
Timer::Start("saving_image");
|
||||
// We transpose by default. So, un-transpose if necessary.
|
||||
if (!transpose)
|
||||
matrix = arma::trans(matrix);
|
||||
arma::Mat<unsigned char> tmpMatrix =
|
||||
arma::conv_to<arma::Mat<unsigned char>>::from(matrix);
|
||||
|
||||
int tempWidth, tempHeight, tempChannels, tempQuality;
|
||||
|
||||
tempWidth = info.Width();
|
||||
tempHeight = info.Height();
|
||||
tempChannels = info.Channels();
|
||||
tempQuality = info.Quality();
|
||||
|
||||
if (!ImageFormatSupported(filename, true))
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << "File type " << Extension(filename) << " not supported.\n";
|
||||
oss << "Currently it supports ";
|
||||
for (auto extension : saveFileTypes)
|
||||
oss << ", " << extension;
|
||||
oss << std::endl;
|
||||
throw std::runtime_error(oss.str());
|
||||
return false;
|
||||
}
|
||||
if (matrix.n_cols > 1)
|
||||
{
|
||||
std::cout << "Input Matrix contains more than 1 image." << std::endl;
|
||||
std::cout << "Only the firstimage will be saved!" << std::endl;
|
||||
}
|
||||
stbi_flip_vertically_on_write(transpose);
|
||||
|
||||
bool status = false;
|
||||
try
|
||||
{
|
||||
unsigned char* image = matrix.memptr();
|
||||
|
||||
if ("png" == Extension(filename))
|
||||
{
|
||||
status = stbi_write_png(filename.c_str(), tempWidth, tempHeight,
|
||||
tempChannels, image, tempWidth * tempChannels);
|
||||
}
|
||||
else if ("bmp" == Extension(filename))
|
||||
{
|
||||
status = stbi_write_bmp(filename.c_str(), tempWidth, tempHeight,
|
||||
tempChannels, image);
|
||||
}
|
||||
else if ("tga" == Extension(filename))
|
||||
{
|
||||
status = stbi_write_tga(filename.c_str(), tempWidth, tempHeight,
|
||||
tempChannels, image);
|
||||
}
|
||||
else if ("hdr" == Extension(filename))
|
||||
{
|
||||
status = stbi_write_hdr(filename.c_str(), tempWidth, tempHeight,
|
||||
tempChannels, reinterpret_cast<float*>(image));
|
||||
}
|
||||
else if ("jpg" == Extension(filename))
|
||||
{
|
||||
status = stbi_write_jpg(filename.c_str(), tempWidth, tempHeight,
|
||||
tempChannels, image, tempQuality);
|
||||
}
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
Timer::Stop("saving_image");
|
||||
if (fatal)
|
||||
Log::Fatal << e.what() << std::endl;
|
||||
Log::Warn << e.what() << std::endl;
|
||||
return false;
|
||||
}
|
||||
Timer::Stop("saving_image");
|
||||
return status;
|
||||
// Call out to .cpp implementation.
|
||||
return SaveImage(filename, tmpMatrix, info, fatal);
|
||||
}
|
||||
|
||||
// Image saving API for multiple files.
|
||||
@@ -370,59 +309,36 @@ template<typename eT>
|
||||
bool Save(const std::vector<std::string>& files,
|
||||
arma::Mat<eT>& matrix,
|
||||
ImageInfo& info,
|
||||
const bool fatal,
|
||||
const bool transpose)
|
||||
const bool fatal)
|
||||
{
|
||||
if (files.size() == 0)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << "Files vector is empty." << std::endl;
|
||||
if (fatal)
|
||||
{
|
||||
Log::Fatal << "Save(): vector of image files is empty; nothing to save."
|
||||
<< std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
Log::Warn << "Save(): vector of image files is empty; nothing to save."
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
throw std::runtime_error(oss.str());
|
||||
return false;
|
||||
}
|
||||
// We transpose by default. So, un-transpose if necessary.
|
||||
if (!transpose)
|
||||
matrix = arma::trans(matrix);
|
||||
|
||||
arma::Mat<unsigned char> img;
|
||||
bool status = Save(files[0], img, info, fatal, transpose);
|
||||
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<unsigned char> colImg(matrix.colptr(i), matrix.n_rows, 1,
|
||||
arma::Mat<eT> colImg(matrix.colptr(i), matrix.n_rows, 1,
|
||||
false, true);
|
||||
status &= Save(files[i], colImg, info, fatal, transpose);
|
||||
status &= Save(files[i], colImg, info, fatal);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
#else
|
||||
template<typename eT>
|
||||
bool Save(const std::string& filename,
|
||||
arma::Mat<eT>& matrix,
|
||||
ImageInfo& info,
|
||||
const bool fatal = false,
|
||||
const bool transpose = true)
|
||||
{
|
||||
throw std::runtime_error("Save(): HAS_STB is not defined, "
|
||||
"so STB is not available and images cannot be saved!");
|
||||
}
|
||||
|
||||
template<typename eT>
|
||||
bool Save(const std::vector<std::string>& files,
|
||||
arma::Mat<eT>& matrix,
|
||||
ImageInfo& info,
|
||||
const bool fatal = false,
|
||||
const bool transpose = true)
|
||||
{
|
||||
throw std::runtime_error("Save(): HAS_STB is not defined, "
|
||||
"so STB is not available and images cannot be saved!");
|
||||
}
|
||||
#endif // HAS_STB.
|
||||
|
||||
} // namespace data
|
||||
} // namespace mlpack
|
||||
|
||||
@@ -52,10 +52,7 @@ class ZCAWhitening
|
||||
*
|
||||
* @param eps Regularization parameter.
|
||||
*/
|
||||
ZCAWhitening(double eps = 0.00005)
|
||||
{
|
||||
pca = new data::PCAWhitening(eps);
|
||||
}
|
||||
ZCAWhitening(double eps = 0.00005) : pca(eps) { }
|
||||
|
||||
/**
|
||||
* Function to fit features, to find out the min max and scale.
|
||||
@@ -65,7 +62,7 @@ class ZCAWhitening
|
||||
template<typename MatType>
|
||||
void Fit(const MatType& input)
|
||||
{
|
||||
pca->Fit(input);
|
||||
pca.Fit(input);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -77,8 +74,8 @@ class ZCAWhitening
|
||||
template<typename MatType>
|
||||
void Transform(const MatType& input, MatType& output)
|
||||
{
|
||||
pca->Transform(input, output);
|
||||
output = pca->EigenVectors() * output;
|
||||
pca.Transform(input, output);
|
||||
output = pca.EigenVectors() * output;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -90,19 +87,19 @@ class ZCAWhitening
|
||||
template<typename MatType>
|
||||
void InverseTransform(const MatType& input, MatType& output)
|
||||
{
|
||||
output = inv(pca->EigenVectors()) * arma::diagmat(arma::sqrt(
|
||||
pca->EigenValues())) * inv(pca->EigenVectors().t()) * input;
|
||||
output = (output.each_col() + pca->ItemMean());
|
||||
output = inv(pca.EigenVectors()) * arma::diagmat(arma::sqrt(
|
||||
pca.EigenValues())) * inv(pca.EigenVectors().t()) * input;
|
||||
output = (output.each_col() + pca.ItemMean());
|
||||
}
|
||||
|
||||
//! Get the mean row vector.
|
||||
const arma::vec& ItemMean() const { return pca->ItemMean(); }
|
||||
const arma::vec& ItemMean() const { return pca.ItemMean(); }
|
||||
//! Get the eigenvalues vector.
|
||||
const arma::vec& EigenValues() const { return pca->EigenValues(); }
|
||||
const arma::vec& EigenValues() const { return pca.EigenValues(); }
|
||||
//! Get the eigenvector.
|
||||
const arma::mat& EigenVectors() const { return pca->EigenVectors(); }
|
||||
const arma::mat& EigenVectors() const { return pca.EigenVectors(); }
|
||||
//! Get the regularization parameter.
|
||||
double Epsilon() const { return pca->Epsilon(); }
|
||||
double Epsilon() const { return pca.Epsilon(); }
|
||||
|
||||
template<typename Archive>
|
||||
void serialize(Archive& ar, const unsigned int /* version */)
|
||||
@@ -112,7 +109,7 @@ class ZCAWhitening
|
||||
|
||||
private:
|
||||
// A pointer to PcaWhitening Class.
|
||||
PCAWhitening* pca;
|
||||
PCAWhitening pca;
|
||||
}; // class ZCAWhitening
|
||||
|
||||
} // namespace data
|
||||
|
||||
@@ -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<size_t>>.
|
||||
* 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<size_t>>.
|
||||
* 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<typename OutputType,
|
||||
typename TokenizerType,
|
||||
typename PolicyType>
|
||||
template<typename OutputType, typename TokenizerType, typename PolicyType>
|
||||
void EncodeHelper(const std::vector<std::string>& 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<typename TokenizerType, typename PolicyType>
|
||||
template<typename TokenizerType, typename PolicyType, typename ElemType>
|
||||
void EncodeHelper(const std::vector<std::string>& input,
|
||||
std::vector<std::vector<size_t>>& output,
|
||||
std::vector<std::vector<ElemType>>& output,
|
||||
const TokenizerType& tokenizer,
|
||||
PolicyType& policy,
|
||||
typename std::enable_if<StringEncodingPolicyTraits<
|
||||
|
||||
@@ -107,10 +107,12 @@ EncodeHelper(const std::vector<std::string>& 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<std::string>& 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<std::string>& input,
|
||||
}
|
||||
|
||||
template<typename EncodingPolicyType, typename DictionaryType>
|
||||
template<typename TokenizerType, typename PolicyType>
|
||||
template<typename TokenizerType, typename PolicyType, typename ElemType>
|
||||
void StringEncoding<EncodingPolicyType, DictionaryType>::
|
||||
EncodeHelper(const std::vector<std::string>& input,
|
||||
std::vector<std::vector<size_t>>& output,
|
||||
std::vector<std::vector<ElemType>>& output,
|
||||
const TokenizerType& tokenizer,
|
||||
PolicyType& policy,
|
||||
typename std::enable_if<StringEncodingPolicyTraits<
|
||||
PolicyType>::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++)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 <mlpack/prereqs.hpp>
|
||||
#include <mlpack/core/data/string_encoding_policies/policy_traits.hpp>
|
||||
#include <mlpack/core/data/string_encoding.hpp>
|
||||
|
||||
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<typename MatType>
|
||||
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<vector<ElemType>>.
|
||||
*
|
||||
* @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<typename ElemType>
|
||||
static void InitMatrix(std::vector<std::vector<ElemType>>& output,
|
||||
const size_t datasetSize,
|
||||
const size_t /* maxNumTokens */,
|
||||
const size_t dictionarySize)
|
||||
{
|
||||
output.resize(datasetSize, std::vector<ElemType>(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<typename MatType>
|
||||
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<vector<ElemType>> 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<typename ElemType>
|
||||
static void Encode(std::vector<std::vector<ElemType>>& 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<typename Archive>
|
||||
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<typename TokenType>
|
||||
using BagOfWordsEncoding = StringEncoding<BagOfWordsEncodingPolicy,
|
||||
StringEncodingDictionary<TokenType>>;
|
||||
} // namespace data
|
||||
} // namespace mlpack
|
||||
|
||||
#endif
|
||||
@@ -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<typename MatType>
|
||||
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<typename MatType>
|
||||
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<size_t>& output,
|
||||
const size_t value)
|
||||
template<typename ElemType>
|
||||
static void Encode(std::vector<ElemType>& 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.
|
||||
*/
|
||||
|
||||
@@ -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 <mlpack/prereqs.hpp>
|
||||
#include <mlpack/core/data/string_encoding_policies/policy_traits.hpp>
|
||||
#include <mlpack/core/data/string_encoding.hpp>
|
||||
|
||||
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<typename MatType>
|
||||
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<vector<ElemType>>.
|
||||
*
|
||||
* @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<typename ElemType>
|
||||
static void InitMatrix(std::vector<std::vector<ElemType>>& output,
|
||||
const size_t datasetSize,
|
||||
const size_t /* maxNumTokens */,
|
||||
const size_t dictionarySize)
|
||||
{
|
||||
output.resize(datasetSize, std::vector<ElemType>(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<typename MatType>
|
||||
void Encode(MatType& output,
|
||||
const size_t value,
|
||||
const size_t line,
|
||||
const size_t /* index */)
|
||||
{
|
||||
const typename MatType::elem_type tf =
|
||||
TermFrequency<typename MatType::elem_type>(
|
||||
tokensFrequences[line][value], linesSizes[line]);
|
||||
|
||||
const typename MatType::elem_type idf =
|
||||
InverseDocumentFrequency<typename MatType::elem_type>(
|
||||
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<vector<ElemType>> 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<typename ElemType>
|
||||
void Encode(std::vector<std::vector<ElemType>>& output,
|
||||
const size_t value,
|
||||
const size_t line,
|
||||
const size_t /* index */)
|
||||
{
|
||||
const ElemType tf = TermFrequency<ElemType>(
|
||||
tokensFrequences[line][value], linesSizes[line]);
|
||||
|
||||
const ElemType idf = InverseDocumentFrequency<ElemType>(
|
||||
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<std::unordered_map<size_t, size_t>>&
|
||||
TokensFrequences() const { return tokensFrequences; }
|
||||
//! Modify token frequencies.
|
||||
std::vector<std::unordered_map<size_t, size_t>>& TokensFrequences()
|
||||
{
|
||||
return tokensFrequences;
|
||||
}
|
||||
|
||||
//! Get the number of containing strings depending on the given token.
|
||||
const std::unordered_map<size_t, size_t>& NumContainingStrings() const
|
||||
{
|
||||
return numContainingStrings;
|
||||
}
|
||||
|
||||
//! Modify the number of containing strings depending on the given token.
|
||||
std::unordered_map<size_t, size_t>& NumContainingStrings()
|
||||
{
|
||||
return numContainingStrings;
|
||||
}
|
||||
|
||||
//! Return the lines sizes.
|
||||
const std::vector<size_t>& LinesSizes() const { return linesSizes; }
|
||||
//! Modify the lines sizes.
|
||||
std::vector<size_t>& 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<typename Archive>
|
||||
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<typename ValueType>
|
||||
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<ValueType>(numOccurrences) / numTokens;
|
||||
case TfTypes::SUBLINEAR_TF:
|
||||
return std::log(static_cast<ValueType>(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<typename ValueType>
|
||||
ValueType InverseDocumentFrequency(const size_t totalNumLines,
|
||||
const size_t numOccurrences)
|
||||
{
|
||||
if (smoothIdf)
|
||||
{
|
||||
return std::log(static_cast<ValueType>(totalNumLines + 1) /
|
||||
(1 + numOccurrences)) + 1.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return std::log(static_cast<ValueType>(totalNumLines) /
|
||||
numOccurrences) + 1.0;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
//! Used to store the total number of tokens for each line.
|
||||
std::vector<std::unordered_map<size_t, size_t>> tokensFrequences;
|
||||
/**
|
||||
* Used to store the number of strings which contain a token depending
|
||||
* on the given token.
|
||||
*/
|
||||
std::unordered_map<size_t, size_t> numContainingStrings;
|
||||
//! Used to store the number of tokens in each line.
|
||||
std::vector<size_t> 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<typename TokenType>
|
||||
using TfIdfEncoding = StringEncoding<TfIdfEncodingPolicy,
|
||||
StringEncodingDictionary<TokenType>>;
|
||||
} // namespace data
|
||||
} // namespace mlpack
|
||||
|
||||
#endif
|
||||
@@ -11,8 +11,8 @@
|
||||
* http://www.opensource.org/licenses/BSD-3-Clause for more information.
|
||||
*/
|
||||
#include "gamma_distribution.hpp"
|
||||
// This will include digamma and trigamma.
|
||||
#include <mlpack/core/boost_backport/boost_backport_math.hpp>
|
||||
#include <boost/math/special_functions/trigamma.hpp>
|
||||
#include <boost/math/special_functions/polygamma.hpp>
|
||||
|
||||
using namespace mlpack;
|
||||
using namespace mlpack::distribution;
|
||||
|
||||
@@ -49,7 +49,7 @@ IPMetric<KernelType>::~IPMetric()
|
||||
|
||||
template<typename KernelType>
|
||||
IPMetric<KernelType>::IPMetric(const IPMetric& other) :
|
||||
kernel(other.kernel),
|
||||
kernel(!other.kernelOwner ? other.kernel : new KernelType(*other.kernel)),
|
||||
kernelOwner(other.kernelOwner)
|
||||
{
|
||||
// Nothing to do.
|
||||
@@ -90,7 +90,11 @@ void IPMetric<KernelType>::serialize(Archive& ar,
|
||||
// If we're loading, we need to allocate space for the kernel, and we will own
|
||||
// the kernel.
|
||||
if (Archive::is_loading::value)
|
||||
{
|
||||
if (kernelOwner)
|
||||
delete kernel;
|
||||
kernelOwner = true;
|
||||
}
|
||||
|
||||
ar & BOOST_SERIALIZATION_NVP(kernel);
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ template<int TPower, bool TTakeRoot = true>
|
||||
class LMetric
|
||||
{
|
||||
public:
|
||||
/***
|
||||
/**
|
||||
* Default constructor does nothing, but is required to satisfy the Metric
|
||||
* policy.
|
||||
*/
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/***
|
||||
/**
|
||||
* @file mahalanobis_distance.hpp
|
||||
* @author Ryan Curtin
|
||||
*
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/***
|
||||
/**
|
||||
* @file mahalanobis_distance_impl.hpp
|
||||
* @author Ryan Curtin
|
||||
*
|
||||
|
||||
@@ -80,6 +80,9 @@ template<typename TMetricType, typename ElemType>
|
||||
HollowBallBound<TMetricType, ElemType>& HollowBallBound<TMetricType, ElemType>::
|
||||
operator=(const HollowBallBound& other)
|
||||
{
|
||||
if (ownsMetric)
|
||||
delete metric;
|
||||
|
||||
radii = other.radii;
|
||||
center = other.center;
|
||||
hollowCenter = other.hollowCenter;
|
||||
|
||||
@@ -124,7 +124,7 @@ class PrefixedOutStream
|
||||
private:
|
||||
/**
|
||||
* Conducts the base logic required in all the operator << overloads. Mostly
|
||||
* just a good idea to reduce copy-pasta.
|
||||
* just a good idea to reduce copy-paste.
|
||||
*
|
||||
* This overload is for non-Armadillo objects, which need special handling
|
||||
* during printing.
|
||||
@@ -138,7 +138,7 @@ class PrefixedOutStream
|
||||
|
||||
/**
|
||||
* Conducts the base logic required in all the operator << overloads. Mostly
|
||||
* just a good idea to reduce copy-pasta.
|
||||
* just a good idea to reduce copy-paste.
|
||||
*
|
||||
* This overload is for Armadillo objects, which need special handling during
|
||||
* printing.
|
||||
|
||||
@@ -24,6 +24,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/layer/layer_traits.hpp>
|
||||
#include <mlpack/methods/ann/init_rules/random_init.hpp>
|
||||
|
||||
#include <ensmallen.hpp>
|
||||
@@ -72,10 +73,41 @@ class BRNN
|
||||
BRNN(const size_t rho,
|
||||
const bool single = false,
|
||||
OutputLayerType outputLayer = OutputLayerType(),
|
||||
MergeLayerType mergeLayer = MergeLayerType(),
|
||||
MergeOutputType mergeOutput = MergeOutputType(),
|
||||
MergeLayerType* mergeLayer = new MergeLayerType(),
|
||||
MergeOutputType* mergeOutput = new MergeOutputType(),
|
||||
InitializationRuleType initializeRule = InitializationRuleType());
|
||||
|
||||
~BRNN();
|
||||
|
||||
/**
|
||||
* Check if the optimizer has MaxIterations() parameter, if it does
|
||||
* then check if it's value is less than the number of datapoints
|
||||
* in the dataset.
|
||||
*
|
||||
* @tparam OptimizerType Type of optimizer to use to train the model.
|
||||
* @param optimizer optimizer used in the training process.
|
||||
* @param samples Number of datapoints in the dataset.
|
||||
*/
|
||||
template<typename OptimizerType>
|
||||
typename std::enable_if<
|
||||
HasMaxIterations<OptimizerType, size_t&(OptimizerType::*)()>
|
||||
::value, void>::type
|
||||
WarnMessageMaxIterations(OptimizerType& optimizer, size_t samples) const;
|
||||
|
||||
/**
|
||||
* Check if the optimizer has MaxIterations() parameter, if it
|
||||
* doesn't then simply return from the function.
|
||||
*
|
||||
* @tparam OptimizerType Type of optimizer to use to train the model.
|
||||
* @param optimizer optimizer used in the training process.
|
||||
* @param samples Number of datapoints in the dataset.
|
||||
*/
|
||||
template<typename OptimizerType>
|
||||
typename std::enable_if<
|
||||
!HasMaxIterations<OptimizerType, size_t&(OptimizerType::*)()>
|
||||
::value, void>::type
|
||||
WarnMessageMaxIterations(OptimizerType& optimizer, size_t samples) const;
|
||||
|
||||
/**
|
||||
* Train the bidirectional recurrent neural network on the given input data
|
||||
* using the given optimizer.
|
||||
|
||||
@@ -39,13 +39,13 @@ BRNN<OutputLayerType, MergeLayerType, MergeOutputType,
|
||||
const size_t rho,
|
||||
const bool single,
|
||||
OutputLayerType outputLayer,
|
||||
MergeLayerType mergeLayer,
|
||||
MergeOutputType mergeOutput,
|
||||
MergeLayerType* mergeLayer,
|
||||
MergeOutputType* mergeOutput,
|
||||
InitializationRuleType initializeRule) :
|
||||
rho(rho),
|
||||
outputLayer(std::move(outputLayer)),
|
||||
mergeLayer(new MergeLayerType(mergeLayer)),
|
||||
mergeOutput(new MergeOutputType(mergeOutput)),
|
||||
mergeLayer(mergeLayer),
|
||||
mergeOutput(mergeOutput),
|
||||
initializeRule(std::move(initializeRule)),
|
||||
inputSize(0),
|
||||
outputSize(0),
|
||||
@@ -60,6 +60,61 @@ BRNN<OutputLayerType, MergeLayerType, MergeOutputType,
|
||||
/* Nothing to do here. */
|
||||
}
|
||||
|
||||
template<typename OutputLayerType, typename MergeLayerType,
|
||||
typename MergeOutputType, typename InitializationRuleType,
|
||||
typename... CustomLayers>
|
||||
BRNN<OutputLayerType, MergeLayerType, MergeOutputType,
|
||||
InitializationRuleType, CustomLayers...>::~BRNN()
|
||||
{
|
||||
// Remove the last layers from the forward and backward RNNs, as they are held
|
||||
// in mergeLayer. So, when we use DeleteVisitor with mergeLayer, those two
|
||||
// layers will be properly (and not doubly) freed.
|
||||
forwardRNN.network.pop_back();
|
||||
backwardRNN.network.pop_back();
|
||||
|
||||
// Clean up layers that we allocated.
|
||||
boost::apply_visitor(DeleteVisitor(), mergeLayer);
|
||||
boost::apply_visitor(DeleteVisitor(), mergeOutput);
|
||||
}
|
||||
|
||||
template<typename OutputLayerType, typename MergeLayerType,
|
||||
typename MergeOutputType, typename InitializationRuleType,
|
||||
typename... CustomLayers>
|
||||
template<typename OptimizerType>
|
||||
typename std::enable_if<
|
||||
HasMaxIterations<OptimizerType, size_t&(OptimizerType::*)()>
|
||||
::value, void>::type
|
||||
BRNN<OutputLayerType, MergeLayerType, MergeOutputType,
|
||||
InitializationRuleType, CustomLayers...>::WarnMessageMaxIterations
|
||||
(OptimizerType& optimizer, size_t samples) const
|
||||
{
|
||||
if (optimizer.MaxIterations() < samples &&
|
||||
optimizer.MaxIterations() != 0)
|
||||
{
|
||||
Log::Warn << "The optimizer's maximum number of iterations "
|
||||
<< "is less than the size of the dataset; the "
|
||||
<< "optimizer will not pass over the entire "
|
||||
<< "dataset. To fix this, modify the maximum "
|
||||
<< "number of iterations to be at least equal "
|
||||
<< "to the number of points of your dataset "
|
||||
<< "(" << samples << ")." << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename OutputLayerType, typename MergeLayerType,
|
||||
typename MergeOutputType, typename InitializationRuleType,
|
||||
typename... CustomLayers>
|
||||
template<typename OptimizerType>
|
||||
typename std::enable_if<
|
||||
!HasMaxIterations<OptimizerType, size_t&(OptimizerType::*)()>
|
||||
::value, void>::type
|
||||
BRNN<OutputLayerType, MergeLayerType, MergeOutputType,
|
||||
InitializationRuleType, CustomLayers...>::WarnMessageMaxIterations
|
||||
(OptimizerType& optimizer, size_t samples) const
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
template<typename OutputLayerType, typename MergeLayerType,
|
||||
typename MergeOutputType, typename InitializationRuleType,
|
||||
typename... CustomLayers>
|
||||
@@ -83,6 +138,8 @@ double BRNN<OutputLayerType, MergeLayerType, MergeOutputType,
|
||||
ResetParameters();
|
||||
}
|
||||
|
||||
WarnMessageMaxIterations<OptimizerType>(optimizer, this->predictors.n_cols);
|
||||
|
||||
// Train the model.
|
||||
Timer::Start("BRNN_optimization");
|
||||
const double out = optimizer.Optimize(*this, parameter);
|
||||
@@ -117,6 +174,8 @@ double BRNN<OutputLayerType, MergeLayerType, MergeOutputType,
|
||||
|
||||
OptimizerType optimizer;
|
||||
|
||||
WarnMessageMaxIterations<OptimizerType>(optimizer, this->predictors.n_cols);
|
||||
|
||||
// Train the model.
|
||||
const double out = optimizer.Optimize(*this, parameter);
|
||||
|
||||
@@ -166,34 +225,34 @@ void BRNN<OutputLayerType, MergeLayerType, MergeOutputType,
|
||||
size_t(predictors.n_cols - begin));
|
||||
for (size_t seqNum = 0; seqNum < rho; ++seqNum)
|
||||
{
|
||||
forwardRNN.Forward(std::move(arma::mat(
|
||||
forwardRNN.Forward(arma::mat(
|
||||
predictors.slice(seqNum).colptr(begin),
|
||||
predictors.n_rows, effectiveBatchSize, false, true)));
|
||||
predictors.n_rows, effectiveBatchSize, false, true));
|
||||
backwardRNN.Forward(std::move(arma::mat(
|
||||
predictors.slice(rho - seqNum - 1).colptr(begin),
|
||||
predictors.n_rows, effectiveBatchSize, false, true)));
|
||||
|
||||
boost::apply_visitor(SaveOutputParameterVisitor(
|
||||
std::move(results1)), forwardRNN.network.back());
|
||||
boost::apply_visitor(SaveOutputParameterVisitor(
|
||||
std::move(results2)), backwardRNN.network.back());
|
||||
boost::apply_visitor(SaveOutputParameterVisitor(results1),
|
||||
forwardRNN.network.back());
|
||||
boost::apply_visitor(SaveOutputParameterVisitor(results2),
|
||||
backwardRNN.network.back());
|
||||
}
|
||||
reverse(results1.begin(), results1.end());
|
||||
|
||||
// Forward outputs from both RNN's through merge layer for each time step.
|
||||
for (size_t seqNum = 0; seqNum < rho; ++seqNum)
|
||||
{
|
||||
boost::apply_visitor(LoadOutputParameterVisitor(
|
||||
std::move(results1)), forwardRNN.network.back());
|
||||
boost::apply_visitor(LoadOutputParameterVisitor(
|
||||
std::move(results2)), backwardRNN.network.back());
|
||||
boost::apply_visitor(LoadOutputParameterVisitor(results1),
|
||||
forwardRNN.network.back());
|
||||
boost::apply_visitor(LoadOutputParameterVisitor(results2),
|
||||
backwardRNN.network.back());
|
||||
|
||||
boost::apply_visitor(ForwardVisitor(std::move(input),
|
||||
std::move(boost::apply_visitor(outputParameterVisitor, mergeLayer))),
|
||||
boost::apply_visitor(ForwardVisitor(input,
|
||||
boost::apply_visitor(outputParameterVisitor, mergeLayer)),
|
||||
mergeLayer);
|
||||
boost::apply_visitor(ForwardVisitor(
|
||||
std::move(boost::apply_visitor(outputParameterVisitor, mergeLayer)),
|
||||
std::move(boost::apply_visitor(outputParameterVisitor, mergeOutput))),
|
||||
boost::apply_visitor(outputParameterVisitor, mergeLayer),
|
||||
boost::apply_visitor(outputParameterVisitor, mergeOutput)),
|
||||
mergeOutput);
|
||||
results.slice(seqNum).submat(0, begin, results.n_rows - 1, begin +
|
||||
effectiveBatchSize - 1) =
|
||||
@@ -243,17 +302,17 @@ double BRNN<OutputLayerType, MergeLayerType, MergeOutputType,
|
||||
std::vector<arma::mat> results1, results2;
|
||||
for (size_t seqNum = 0; seqNum < rho; ++seqNum)
|
||||
{
|
||||
forwardRNN.Forward(std::move(arma::mat(
|
||||
forwardRNN.Forward(arma::mat(
|
||||
predictors.slice(seqNum).colptr(begin),
|
||||
predictors.n_rows, batchSize, false, true)));
|
||||
backwardRNN.Forward(std::move(arma::mat(
|
||||
predictors.n_rows, batchSize, false, true));
|
||||
backwardRNN.Forward(arma::mat(
|
||||
predictors.slice(rho - seqNum - 1).colptr(begin),
|
||||
predictors.n_rows, batchSize, false, true)));
|
||||
predictors.n_rows, batchSize, false, true));
|
||||
|
||||
boost::apply_visitor(SaveOutputParameterVisitor(
|
||||
std::move(results1)), forwardRNN.network.back());
|
||||
boost::apply_visitor(SaveOutputParameterVisitor(
|
||||
std::move(results2)), backwardRNN.network.back());
|
||||
boost::apply_visitor(SaveOutputParameterVisitor(results1),
|
||||
forwardRNN.network.back());
|
||||
boost::apply_visitor(SaveOutputParameterVisitor(results2),
|
||||
backwardRNN.network.back());
|
||||
}
|
||||
if (outputSize == 0)
|
||||
{
|
||||
@@ -271,22 +330,22 @@ double BRNN<OutputLayerType, MergeLayerType, MergeOutputType,
|
||||
{
|
||||
responseSeq = seqNum;
|
||||
}
|
||||
boost::apply_visitor(LoadOutputParameterVisitor(
|
||||
std::move(results1)), forwardRNN.network.back());
|
||||
boost::apply_visitor(LoadOutputParameterVisitor(
|
||||
std::move(results2)), backwardRNN.network.back());
|
||||
boost::apply_visitor(LoadOutputParameterVisitor(results1),
|
||||
forwardRNN.network.back());
|
||||
boost::apply_visitor(LoadOutputParameterVisitor(results2),
|
||||
backwardRNN.network.back());
|
||||
|
||||
boost::apply_visitor(ForwardVisitor(std::move(input),
|
||||
std::move(boost::apply_visitor(outputParameterVisitor, mergeLayer))),
|
||||
boost::apply_visitor(ForwardVisitor(input,
|
||||
boost::apply_visitor(outputParameterVisitor, mergeLayer)),
|
||||
mergeLayer);
|
||||
boost::apply_visitor(ForwardVisitor(
|
||||
std::move(boost::apply_visitor(outputParameterVisitor, mergeLayer)),
|
||||
std::move(boost::apply_visitor(outputParameterVisitor, mergeOutput))),
|
||||
mergeOutput);
|
||||
performance += outputLayer.Forward(std::move(
|
||||
boost::apply_visitor(outputParameterVisitor, mergeLayer),
|
||||
boost::apply_visitor(outputParameterVisitor, mergeOutput)),
|
||||
std::move(arma::mat(responses.slice(responseSeq).colptr(begin),
|
||||
responses.n_rows, batchSize, false, true)));
|
||||
mergeOutput);
|
||||
performance += outputLayer.Forward(
|
||||
boost::apply_visitor(outputParameterVisitor, mergeOutput),
|
||||
arma::mat(responses.slice(responseSeq).colptr(begin),
|
||||
responses.n_rows, batchSize, false, true));
|
||||
}
|
||||
return performance;
|
||||
}
|
||||
@@ -361,24 +420,24 @@ EvaluateWithGradient(const arma::mat& /* parameters */,
|
||||
std::vector<arma::mat> results1, results2;
|
||||
for (size_t seqNum = 0; seqNum < rho; ++seqNum)
|
||||
{
|
||||
forwardRNN.Forward(std::move(arma::mat(
|
||||
forwardRNN.Forward(arma::mat(
|
||||
predictors.slice(seqNum).colptr(begin),
|
||||
predictors.n_rows, batchSize, false, true)));
|
||||
backwardRNN.Forward(std::move(arma::mat(
|
||||
predictors.n_rows, batchSize, false, true));
|
||||
backwardRNN.Forward(arma::mat(
|
||||
predictors.slice(rho - seqNum - 1).colptr(begin),
|
||||
predictors.n_rows, batchSize, false, true)));
|
||||
predictors.n_rows, batchSize, false, true));
|
||||
|
||||
for (size_t l = 0; l < networkSize; ++l)
|
||||
{
|
||||
boost::apply_visitor(SaveOutputParameterVisitor(
|
||||
std::move(forwardRNNOutputParameter)), forwardRNN.network[l]);
|
||||
forwardRNNOutputParameter), forwardRNN.network[l]);
|
||||
boost::apply_visitor(SaveOutputParameterVisitor(
|
||||
std::move(backwardRNNOutputParameter)), backwardRNN.network[l]);
|
||||
backwardRNNOutputParameter), backwardRNN.network[l]);
|
||||
}
|
||||
boost::apply_visitor(SaveOutputParameterVisitor(
|
||||
std::move(results1)), forwardRNN.network.back());
|
||||
boost::apply_visitor(SaveOutputParameterVisitor(
|
||||
std::move(results2)), backwardRNN.network.back());
|
||||
boost::apply_visitor(SaveOutputParameterVisitor(results1),
|
||||
forwardRNN.network.back());
|
||||
boost::apply_visitor(SaveOutputParameterVisitor(results2),
|
||||
backwardRNN.network.back());
|
||||
}
|
||||
if (outputSize == 0)
|
||||
{
|
||||
@@ -410,18 +469,18 @@ EvaluateWithGradient(const arma::mat& /* parameters */,
|
||||
responseSeq = seqNum;
|
||||
}
|
||||
boost::apply_visitor(LoadOutputParameterVisitor(
|
||||
std::move(results1)), forwardRNN.network.back());
|
||||
results1), forwardRNN.network.back());
|
||||
boost::apply_visitor(LoadOutputParameterVisitor(
|
||||
std::move(results2)), backwardRNN.network.back());
|
||||
boost::apply_visitor(ForwardVisitor(std::move(input),
|
||||
std::move(boost::apply_visitor(outputParameterVisitor, mergeLayer))),
|
||||
results2), backwardRNN.network.back());
|
||||
boost::apply_visitor(ForwardVisitor(input,
|
||||
boost::apply_visitor(outputParameterVisitor, mergeLayer)),
|
||||
mergeLayer);
|
||||
boost::apply_visitor(ForwardVisitor(
|
||||
std::move(boost::apply_visitor(outputParameterVisitor, mergeLayer)),
|
||||
std::move(results.slice(seqNum))), mergeOutput);
|
||||
performance += outputLayer.Forward(std::move(results.slice(seqNum)),
|
||||
std::move(arma::mat(responses.slice(responseSeq).colptr(begin),
|
||||
responses.n_rows, batchSize, false, true)));
|
||||
boost::apply_visitor(outputParameterVisitor, mergeLayer),
|
||||
results.slice(seqNum)), mergeOutput);
|
||||
performance += outputLayer.Forward(results.slice(seqNum),
|
||||
arma::mat(responses.slice(responseSeq).colptr(begin),
|
||||
responses.n_rows, batchSize, false, true));
|
||||
}
|
||||
|
||||
// Calculate and storing delta parameters from output for t = 1 to T.
|
||||
@@ -436,25 +495,25 @@ EvaluateWithGradient(const arma::mat& /* parameters */,
|
||||
}
|
||||
else if (single && seqNum == 0)
|
||||
{
|
||||
outputLayer.Backward(std::move(results.slice(seqNum)),
|
||||
std::move(arma::mat(responses.slice(0).colptr(begin),
|
||||
responses.n_rows, batchSize, false, true)), std::move(error));
|
||||
outputLayer.Backward(results.slice(seqNum),
|
||||
arma::mat(responses.slice(0).colptr(begin),
|
||||
responses.n_rows, batchSize, false, true), error);
|
||||
}
|
||||
else
|
||||
{
|
||||
outputLayer.Backward(std::move(results.slice(seqNum)),
|
||||
std::move(arma::mat(responses.slice(seqNum).colptr(begin),
|
||||
responses.n_rows, batchSize, false, true)), std::move(error));
|
||||
outputLayer.Backward(results.slice(seqNum),
|
||||
arma::mat(responses.slice(seqNum).colptr(begin),
|
||||
responses.n_rows, batchSize, false, true), error);
|
||||
}
|
||||
|
||||
boost::apply_visitor(BackwardVisitor(std::move(results.slice(seqNum)),
|
||||
std::move(error), std::move(delta)), mergeOutput);
|
||||
boost::apply_visitor(BackwardVisitor(results.slice(seqNum), error, delta),
|
||||
mergeOutput);
|
||||
allDelta.push_back(arma::mat(delta));
|
||||
}
|
||||
|
||||
// BPTT ForwardRNN from t = T to 1.
|
||||
totalGradient = arma::mat(gradient.memptr(),
|
||||
parameter.n_elem/2, 1, false, false);
|
||||
parameter.n_elem / 2, 1, false, false);
|
||||
|
||||
forwardGradient.zeros();
|
||||
forwardRNN.ResetGradients(forwardGradient);
|
||||
@@ -467,32 +526,32 @@ EvaluateWithGradient(const arma::mat& /* parameters */,
|
||||
for (size_t l = 0; l < networkSize; ++l)
|
||||
{
|
||||
boost::apply_visitor(LoadOutputParameterVisitor(
|
||||
std::move(forwardRNNOutputParameter)),
|
||||
forwardRNNOutputParameter),
|
||||
forwardRNN.network[networkSize - 1 - l]);
|
||||
}
|
||||
boost::apply_visitor(BackwardVisitor(std::move(boost::apply_visitor(
|
||||
outputParameterVisitor, forwardRNN.network.back())),
|
||||
std::move(allDelta[rho - seqNum - 1]), std::move(delta), 0),
|
||||
boost::apply_visitor(BackwardVisitor(boost::apply_visitor(
|
||||
outputParameterVisitor, forwardRNN.network.back()),
|
||||
allDelta[rho - seqNum - 1], delta, 0),
|
||||
mergeLayer);
|
||||
|
||||
for (size_t i = 2; i < networkSize; ++i)
|
||||
{
|
||||
boost::apply_visitor(BackwardVisitor(
|
||||
std::move(boost::apply_visitor(outputParameterVisitor,
|
||||
forwardRNN.network[networkSize - i])),
|
||||
std::move(boost::apply_visitor(deltaVisitor,
|
||||
forwardRNN.network[networkSize - i + 1])), std::move(
|
||||
boost::apply_visitor(outputParameterVisitor,
|
||||
forwardRNN.network[networkSize - i]),
|
||||
boost::apply_visitor(deltaVisitor,
|
||||
forwardRNN.network[networkSize - i]))),
|
||||
forwardRNN.network[networkSize - i + 1]),
|
||||
boost::apply_visitor(deltaVisitor,
|
||||
forwardRNN.network[networkSize - i])),
|
||||
forwardRNN.network[networkSize - i]);
|
||||
}
|
||||
forwardRNN.Gradient(std::move(
|
||||
forwardRNN.Gradient(
|
||||
arma::mat(predictors.slice(rho - seqNum - 1).colptr(begin),
|
||||
predictors.n_rows, batchSize, false, true)));
|
||||
predictors.n_rows, batchSize, false, true));
|
||||
boost::apply_visitor(GradientVisitor(
|
||||
std::move(boost::apply_visitor(outputParameterVisitor,
|
||||
forwardRNN.network[networkSize - 2])),
|
||||
std::move(allDelta[rho - seqNum - 1]), 0), mergeLayer);
|
||||
boost::apply_visitor(outputParameterVisitor,
|
||||
forwardRNN.network[networkSize - 2]),
|
||||
allDelta[rho - seqNum - 1], 0), mergeLayer);
|
||||
totalGradient += forwardGradient;
|
||||
}
|
||||
|
||||
@@ -506,31 +565,31 @@ EvaluateWithGradient(const arma::mat& /* parameters */,
|
||||
for (size_t l = 0; l < networkSize; ++l)
|
||||
{
|
||||
boost::apply_visitor(LoadOutputParameterVisitor(
|
||||
std::move(backwardRNNOutputParameter)),
|
||||
backwardRNNOutputParameter),
|
||||
backwardRNN.network[networkSize - 1 - l]);
|
||||
}
|
||||
boost::apply_visitor(BackwardVisitor(std::move(
|
||||
boost::apply_visitor(BackwardVisitor(
|
||||
boost::apply_visitor(outputParameterVisitor,
|
||||
backwardRNN.network.back())),
|
||||
std::move(allDelta[seqNum]), std::move(delta), 1), mergeLayer);
|
||||
backwardRNN.network.back()),
|
||||
allDelta[seqNum], delta, 1), mergeLayer);
|
||||
for (size_t i = 2; i < networkSize; ++i)
|
||||
{
|
||||
boost::apply_visitor(BackwardVisitor(
|
||||
std::move(boost::apply_visitor(outputParameterVisitor,
|
||||
backwardRNN.network[networkSize - i])), std::move(boost::apply_visitor(
|
||||
deltaVisitor, backwardRNN.network[networkSize - i + 1])), std::move(
|
||||
boost::apply_visitor(outputParameterVisitor,
|
||||
backwardRNN.network[networkSize - i]), boost::apply_visitor(
|
||||
deltaVisitor, backwardRNN.network[networkSize - i + 1]),
|
||||
boost::apply_visitor(deltaVisitor,
|
||||
backwardRNN.network[networkSize - i]))),
|
||||
backwardRNN.network[networkSize - i])),
|
||||
backwardRNN.network[networkSize - i]);
|
||||
}
|
||||
|
||||
backwardRNN.Gradient(std::move(
|
||||
backwardRNN.Gradient(
|
||||
arma::mat(predictors.slice(seqNum).colptr(begin),
|
||||
predictors.n_rows, batchSize, false, true)));
|
||||
predictors.n_rows, batchSize, false, true));
|
||||
boost::apply_visitor(GradientVisitor(
|
||||
std::move(boost::apply_visitor(outputParameterVisitor,
|
||||
backwardRNN.network[networkSize - 2])),
|
||||
std::move(allDelta[seqNum]), 1), mergeLayer);
|
||||
allDelta[seqNum], 1), mergeLayer);
|
||||
totalGradient += backwardGradient;
|
||||
}
|
||||
return performance;
|
||||
@@ -592,6 +651,8 @@ void BRNN<OutputLayerType, MergeLayerType, MergeOutputType,
|
||||
{
|
||||
if (!reset)
|
||||
{
|
||||
// TODO: what if we call ResetParameters() multiple times? Do we have to
|
||||
// remove any existing mergeLayer?
|
||||
boost::apply_visitor(AddVisitor<CustomLayers...>(
|
||||
forwardRNN.network.back()), mergeLayer);
|
||||
boost::apply_visitor(AddVisitor<CustomLayers...>(
|
||||
@@ -665,6 +726,8 @@ void BRNN<OutputLayerType, MergeLayerType, MergeOutputType,
|
||||
ar & BOOST_SERIALIZATION_NVP(parameter);
|
||||
ar & BOOST_SERIALIZATION_NVP(backwardRNN);
|
||||
ar & BOOST_SERIALIZATION_NVP(forwardRNN);
|
||||
|
||||
// TODO: are there more parameters to be serialized?
|
||||
}
|
||||
|
||||
} // namespace ann
|
||||
|
||||
@@ -60,7 +60,7 @@ class BernoulliDistribution
|
||||
* @param eps The minimum value used for computing logarithms and
|
||||
* denominators.
|
||||
*/
|
||||
BernoulliDistribution(const DataType&& param,
|
||||
BernoulliDistribution(const DataType& param,
|
||||
const bool applyLogistic = true,
|
||||
const double eps = 1e-10);
|
||||
|
||||
@@ -69,7 +69,7 @@ class BernoulliDistribution
|
||||
*
|
||||
* @param observation The observation matrix.
|
||||
*/
|
||||
double Probability(const DataType&& observation) const
|
||||
double Probability(const DataType& observation) const
|
||||
{
|
||||
return std::exp(LogProbability(observation));
|
||||
}
|
||||
@@ -79,7 +79,7 @@ class BernoulliDistribution
|
||||
*
|
||||
* @param observation The observation matrix.
|
||||
*/
|
||||
double LogProbability(const DataType&& observation) const;
|
||||
double LogProbability(const DataType& observation) const;
|
||||
|
||||
/**
|
||||
* Stores the gradient of the log probabilities of the observations in the
|
||||
@@ -88,7 +88,7 @@ class BernoulliDistribution
|
||||
* @param observation The observation matrix.
|
||||
* @param output The output matrix where the gradients are stored.
|
||||
*/
|
||||
void LogProbBackward(const DataType&& observation, DataType&& output) const;
|
||||
void LogProbBackward(const DataType& observation, DataType& output) const;
|
||||
|
||||
/**
|
||||
* Return a matrix of randomly generated samples according to the
|
||||
|
||||
@@ -28,7 +28,7 @@ BernoulliDistribution<DataType>::BernoulliDistribution() :
|
||||
|
||||
template<typename DataType>
|
||||
BernoulliDistribution<DataType>::BernoulliDistribution(
|
||||
const DataType&& param,
|
||||
const DataType& param,
|
||||
const bool applyLogistic,
|
||||
const double eps) :
|
||||
logits(param),
|
||||
@@ -36,7 +36,9 @@ BernoulliDistribution<DataType>::BernoulliDistribution(
|
||||
eps(eps)
|
||||
{
|
||||
if (applyLogistic)
|
||||
{
|
||||
LogisticFunction::Fn(logits, probability);
|
||||
}
|
||||
else
|
||||
{
|
||||
probability = arma::mat(logits.memptr(), logits.n_rows,
|
||||
@@ -58,7 +60,7 @@ DataType BernoulliDistribution<DataType>::Sample() const
|
||||
|
||||
template<typename DataType>
|
||||
double BernoulliDistribution<DataType>::LogProbability(
|
||||
const DataType&& observation) const
|
||||
const DataType& observation) const
|
||||
{
|
||||
return arma::accu(arma::log(probability + eps) % observation +
|
||||
arma::log(1 - probability + eps) % (1 - observation)) /
|
||||
@@ -67,7 +69,7 @@ double BernoulliDistribution<DataType>::LogProbability(
|
||||
|
||||
template<typename DataType>
|
||||
void BernoulliDistribution<DataType>::LogProbBackward(
|
||||
const DataType&& observation, DataType&& output) const
|
||||
const DataType& observation, DataType& output) const
|
||||
{
|
||||
if (!applyLogistic)
|
||||
{
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#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/methods/ann/layer/layer_traits.hpp>
|
||||
#include <ensmallen.hpp>
|
||||
|
||||
namespace mlpack {
|
||||
@@ -82,6 +83,35 @@ class FFN
|
||||
//! Destructor to release allocated memory.
|
||||
~FFN();
|
||||
|
||||
/**
|
||||
* Check if the optimizer has MaxIterations() parameter, if it does
|
||||
* then check if it's value is less than the number of datapoints
|
||||
* in the dataset.
|
||||
*
|
||||
* @tparam OptimizerType Type of optimizer to use to train the model.
|
||||
* @param optimizer optimizer used in the training process.
|
||||
* @param samples Number of datapoints in the dataset.
|
||||
*/
|
||||
template<typename OptimizerType>
|
||||
typename std::enable_if<
|
||||
HasMaxIterations<OptimizerType, size_t&(OptimizerType::*)()>
|
||||
::value, void>::type
|
||||
WarnMessageMaxIterations(OptimizerType& optimizer, size_t samples) const;
|
||||
|
||||
/**
|
||||
* Check if the optimizer has MaxIterations() parameter, if it
|
||||
* doesn't then simply return from the function.
|
||||
*
|
||||
* @tparam OptimizerType Type of optimizer to use to train the model.
|
||||
* @param optimizer optimizer used in the training process.
|
||||
* @param samples Number of datapoints in the dataset.
|
||||
*/
|
||||
template<typename OptimizerType>
|
||||
typename std::enable_if<
|
||||
!HasMaxIterations<OptimizerType, size_t&(OptimizerType::*)()>
|
||||
::value, void>::type
|
||||
WarnMessageMaxIterations(OptimizerType& optimizer, size_t samples) const;
|
||||
|
||||
/**
|
||||
* Train the feedforward network on the given input data using the given
|
||||
* optimizer.
|
||||
@@ -153,7 +183,9 @@ class FFN
|
||||
* @param predictors Input variables.
|
||||
* @param responses Target outputs for input variables.
|
||||
*/
|
||||
double Evaluate(arma::mat predictors, arma::mat responses);
|
||||
template<typename PredictorsType, typename ResponsesType>
|
||||
double Evaluate(const PredictorsType& predictors,
|
||||
const ResponsesType& responses);
|
||||
|
||||
/**
|
||||
* Evaluate the feedforward network with the given parameters. This function
|
||||
@@ -313,7 +345,8 @@ class FFN
|
||||
* @param inputs The input data.
|
||||
* @param results The predicted results.
|
||||
*/
|
||||
void Forward(arma::mat inputs, arma::mat& results);
|
||||
template<typename PredictorsType, typename ResponsesType>
|
||||
void Forward(const PredictorsType& inputs, ResponsesType& results);
|
||||
|
||||
/**
|
||||
* Perform a partial forward pass of the data.
|
||||
@@ -326,8 +359,9 @@ class FFN
|
||||
* @param begin The index of the first layer.
|
||||
* @param end The index of the last layer.
|
||||
*/
|
||||
void Forward(arma::mat inputs,
|
||||
arma::mat& results,
|
||||
template<typename PredictorsType, typename ResponsesType>
|
||||
void Forward(const PredictorsType& inputs ,
|
||||
ResponsesType& results,
|
||||
const size_t begin,
|
||||
const size_t end);
|
||||
|
||||
@@ -342,7 +376,12 @@ class FFN
|
||||
* @param gradients Computed gradients.
|
||||
* @return Training error of the current pass.
|
||||
*/
|
||||
double Backward(arma::mat targets, arma::mat& gradients);
|
||||
template<typename PredictorsType,
|
||||
typename TargetsType,
|
||||
typename GradientsType>
|
||||
double Backward(const PredictorsType& inputs,
|
||||
const TargetsType& targets,
|
||||
GradientsType& gradients);
|
||||
|
||||
private:
|
||||
// Helper functions.
|
||||
@@ -352,7 +391,8 @@ class FFN
|
||||
*
|
||||
* @param input Data sequence to compute probabilities for.
|
||||
*/
|
||||
void Forward(arma::mat&& input);
|
||||
template<typename InputType>
|
||||
void Forward(const InputType& input);
|
||||
|
||||
/**
|
||||
* Prepare the network for the given data.
|
||||
@@ -373,7 +413,8 @@ class FFN
|
||||
* Iterate through all layer modules and update the the gradient using the
|
||||
* layer defined optimizer.
|
||||
*/
|
||||
void Gradient(arma::mat&& input);
|
||||
template<typename InputType>
|
||||
void Gradient(const InputType& input);
|
||||
|
||||
/**
|
||||
* Reset the module status by setting the current deterministic parameter
|
||||
@@ -427,9 +468,6 @@ class FFN
|
||||
//! The current error for the backward pass.
|
||||
arma::mat error;
|
||||
|
||||
//! THe current input of the forward/backward pass.
|
||||
arma::mat currentInput;
|
||||
|
||||
//! Locally-stored delta visitor.
|
||||
DeltaVisitor deltaVisitor;
|
||||
|
||||
@@ -496,7 +534,7 @@ template<typename OutputLayerType,
|
||||
struct version<
|
||||
mlpack::ann::FFN<OutputLayerType, InitializationRuleType, CustomLayer...>>
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(int, value = 1);
|
||||
BOOST_STATIC_CONSTANT(int, value = 2);
|
||||
};
|
||||
|
||||
} // namespace serialization
|
||||
|
||||
@@ -41,7 +41,7 @@ FFN<OutputLayerType, InitializationRuleType, CustomLayers...>::FFN(
|
||||
numFunctions(0),
|
||||
deterministic(true)
|
||||
{
|
||||
/* Nothing to do here */
|
||||
/* Nothing to do here. */
|
||||
}
|
||||
|
||||
template<typename OutputLayerType, typename InitializationRuleType,
|
||||
@@ -67,6 +67,41 @@ void FFN<OutputLayerType, InitializationRuleType, CustomLayers...>::ResetData(
|
||||
ResetParameters();
|
||||
}
|
||||
|
||||
template<typename OutputLayerType, typename InitializationRuleType,
|
||||
typename... CustomLayers>
|
||||
template<typename OptimizerType>
|
||||
typename std::enable_if<
|
||||
HasMaxIterations<OptimizerType, size_t&(OptimizerType::*)()>
|
||||
::value, void>::type
|
||||
FFN<OutputLayerType, InitializationRuleType, CustomLayers...>::
|
||||
WarnMessageMaxIterations(OptimizerType& optimizer, size_t samples) const
|
||||
{
|
||||
if (optimizer.MaxIterations() < samples &&
|
||||
optimizer.MaxIterations() != 0)
|
||||
{
|
||||
Log::Warn << "The optimizer's maximum number of iterations "
|
||||
<< "is less than the size of the dataset; the "
|
||||
<< "optimizer will not pass over the entire "
|
||||
<< "dataset. To fix this, modify the maximum "
|
||||
<< "number of iterations to be at least equal "
|
||||
<< "to the number of points of your dataset "
|
||||
<< "(" << samples << ")." << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename OutputLayerType, typename InitializationRuleType,
|
||||
typename... CustomLayers>
|
||||
template<typename OptimizerType>
|
||||
typename std::enable_if<
|
||||
!HasMaxIterations<OptimizerType, size_t&(OptimizerType::*)()>
|
||||
::value, void>::type
|
||||
FFN<OutputLayerType, InitializationRuleType, CustomLayers...>::
|
||||
WarnMessageMaxIterations(OptimizerType& /* optimizer */, size_t /* samples */)
|
||||
const
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
template<typename OutputLayerType, typename InitializationRuleType,
|
||||
typename... CustomLayers>
|
||||
template<typename OptimizerType, typename... CallbackTypes>
|
||||
@@ -78,6 +113,8 @@ double FFN<OutputLayerType, InitializationRuleType, CustomLayers...>::Train(
|
||||
{
|
||||
ResetData(std::move(predictors), std::move(responses));
|
||||
|
||||
WarnMessageMaxIterations<OptimizerType>(optimizer, this->predictors.n_cols);
|
||||
|
||||
// Train the model.
|
||||
Timer::Start("ffn_optimization");
|
||||
const double out = optimizer.Optimize(*this, parameter, callbacks...);
|
||||
@@ -100,6 +137,8 @@ double FFN<OutputLayerType, InitializationRuleType, CustomLayers...>::Train(
|
||||
|
||||
OptimizerType optimizer;
|
||||
|
||||
WarnMessageMaxIterations<OptimizerType>(optimizer, this->predictors.n_cols);
|
||||
|
||||
// Train the model.
|
||||
Timer::Start("ffn_optimization");
|
||||
const double out = optimizer.Optimize(*this, parameter, callbacks...);
|
||||
@@ -112,8 +151,9 @@ double FFN<OutputLayerType, InitializationRuleType, CustomLayers...>::Train(
|
||||
|
||||
template<typename OutputLayerType, typename InitializationRuleType,
|
||||
typename... CustomLayers>
|
||||
template<typename PredictorsType, typename ResponsesType>
|
||||
void FFN<OutputLayerType, InitializationRuleType, CustomLayers...>::Forward(
|
||||
arma::mat inputs, arma::mat& results)
|
||||
const PredictorsType& inputs, ResponsesType& results)
|
||||
{
|
||||
if (parameter.is_empty())
|
||||
ResetParameters();
|
||||
@@ -124,25 +164,28 @@ void FFN<OutputLayerType, InitializationRuleType, CustomLayers...>::Forward(
|
||||
ResetDeterministic();
|
||||
}
|
||||
|
||||
currentInput = std::move(inputs);
|
||||
Forward(std::move(currentInput));
|
||||
Forward(inputs);
|
||||
results = boost::apply_visitor(outputParameterVisitor, network.back());
|
||||
}
|
||||
|
||||
template<typename OutputLayerType, typename InitializationRuleType,
|
||||
typename... CustomLayers>
|
||||
template<typename PredictorsType, typename ResponsesType>
|
||||
void FFN<OutputLayerType, InitializationRuleType, CustomLayers...>::Forward(
|
||||
arma::mat inputs, arma::mat& results, const size_t begin, const size_t end)
|
||||
const PredictorsType& inputs,
|
||||
ResponsesType& results,
|
||||
const size_t begin,
|
||||
const size_t end)
|
||||
{
|
||||
boost::apply_visitor(ForwardVisitor(std::move(inputs), std::move(
|
||||
boost::apply_visitor(outputParameterVisitor, network[begin]))),
|
||||
boost::apply_visitor(ForwardVisitor(inputs,
|
||||
boost::apply_visitor(outputParameterVisitor, network[begin])),
|
||||
network[begin]);
|
||||
|
||||
for (size_t i = 1; i < end - begin + 1; ++i)
|
||||
{
|
||||
boost::apply_visitor(ForwardVisitor(std::move(boost::apply_visitor(
|
||||
outputParameterVisitor, network[begin + i - 1])), std::move(
|
||||
boost::apply_visitor(outputParameterVisitor, network[begin + i]))),
|
||||
boost::apply_visitor(ForwardVisitor(boost::apply_visitor(
|
||||
outputParameterVisitor, network[begin + i - 1]),
|
||||
boost::apply_visitor(outputParameterVisitor, network[begin + i])),
|
||||
network[begin + i]);
|
||||
}
|
||||
|
||||
@@ -151,25 +194,28 @@ void FFN<OutputLayerType, InitializationRuleType, CustomLayers...>::Forward(
|
||||
|
||||
template<typename OutputLayerType, typename InitializationRuleType,
|
||||
typename... CustomLayers>
|
||||
template<typename PredictorsType, typename TargetsType, typename GradientsType>
|
||||
double FFN<OutputLayerType, InitializationRuleType, CustomLayers...>::Backward(
|
||||
arma::mat targets, arma::mat& gradients)
|
||||
const PredictorsType& inputs,
|
||||
const TargetsType& targets,
|
||||
GradientsType& gradients)
|
||||
{
|
||||
double res = outputLayer.Forward(std::move(boost::apply_visitor(
|
||||
outputParameterVisitor, network.back())), std::move(targets));
|
||||
double res = outputLayer.Forward(boost::apply_visitor(
|
||||
outputParameterVisitor, network.back()), targets);
|
||||
|
||||
for (size_t i = 0; i < network.size(); ++i)
|
||||
{
|
||||
res += boost::apply_visitor(lossVisitor, network[i]);
|
||||
}
|
||||
|
||||
outputLayer.Backward(std::move(boost::apply_visitor(outputParameterVisitor,
|
||||
network.back())), std::move(targets), std::move(error));
|
||||
outputLayer.Backward(boost::apply_visitor(outputParameterVisitor,
|
||||
network.back()), targets, error);
|
||||
|
||||
gradients = arma::zeros<arma::mat>(parameter.n_rows, parameter.n_cols);
|
||||
|
||||
Backward();
|
||||
ResetGradients(gradients);
|
||||
Gradient(std::move(currentInput));
|
||||
Gradient(inputs);
|
||||
|
||||
return res;
|
||||
}
|
||||
@@ -189,8 +235,7 @@ void FFN<OutputLayerType, InitializationRuleType, CustomLayers...>::Predict(
|
||||
}
|
||||
|
||||
arma::mat resultsTemp;
|
||||
Forward(std::move(arma::mat(predictors.colptr(0),
|
||||
predictors.n_rows, 1, false, true)));
|
||||
Forward(arma::mat(predictors.colptr(0), predictors.n_rows, 1, false, true));
|
||||
resultsTemp = boost::apply_visitor(outputParameterVisitor,
|
||||
network.back()).col(0);
|
||||
|
||||
@@ -199,8 +244,7 @@ void FFN<OutputLayerType, InitializationRuleType, CustomLayers...>::Predict(
|
||||
|
||||
for (size_t i = 1; i < predictors.n_cols; i++)
|
||||
{
|
||||
Forward(std::move(arma::mat(predictors.colptr(i),
|
||||
predictors.n_rows, 1, false, true)));
|
||||
Forward(arma::mat(predictors.colptr(i), predictors.n_rows, 1, false, true));
|
||||
|
||||
resultsTemp = boost::apply_visitor(outputParameterVisitor,
|
||||
network.back());
|
||||
@@ -210,8 +254,9 @@ void FFN<OutputLayerType, InitializationRuleType, CustomLayers...>::Predict(
|
||||
|
||||
template<typename OutputLayerType, typename InitializationRuleType,
|
||||
typename... CustomLayers>
|
||||
template<typename PredictorsType, typename ResponsesType>
|
||||
double FFN<OutputLayerType, InitializationRuleType, CustomLayers...>::Evaluate(
|
||||
arma::mat predictors, arma::mat responses)
|
||||
const PredictorsType& predictors, const ResponsesType& responses)
|
||||
{
|
||||
if (parameter.is_empty())
|
||||
ResetParameters();
|
||||
@@ -222,10 +267,10 @@ double FFN<OutputLayerType, InitializationRuleType, CustomLayers...>::Evaluate(
|
||||
ResetDeterministic();
|
||||
}
|
||||
|
||||
Forward(std::move(predictors));
|
||||
Forward(predictors);
|
||||
|
||||
double res = outputLayer.Forward(std::move(boost::apply_visitor(
|
||||
outputParameterVisitor, network.back())), std::move(responses));
|
||||
double res = outputLayer.Forward(boost::apply_visitor(
|
||||
outputParameterVisitor, network.back()), responses);
|
||||
|
||||
for (size_t i = 0; i < network.size(); ++i)
|
||||
{
|
||||
@@ -264,10 +309,10 @@ double FFN<OutputLayerType, InitializationRuleType, CustomLayers...>::Evaluate(
|
||||
ResetDeterministic();
|
||||
}
|
||||
|
||||
Forward(std::move(predictors.cols(begin, begin + batchSize - 1)));
|
||||
Forward(predictors.cols(begin, begin + batchSize - 1));
|
||||
double res = outputLayer.Forward(
|
||||
std::move(boost::apply_visitor(outputParameterVisitor, network.back())),
|
||||
std::move(responses.cols(begin, begin + batchSize - 1)));
|
||||
boost::apply_visitor(outputParameterVisitor, network.back()),
|
||||
responses.cols(begin, begin + batchSize - 1));
|
||||
|
||||
for (size_t i = 0; i < network.size(); ++i)
|
||||
{
|
||||
@@ -325,10 +370,10 @@ EvaluateWithGradient(const arma::mat& /* parameters */,
|
||||
ResetDeterministic();
|
||||
}
|
||||
|
||||
Forward(std::move(predictors.cols(begin, begin + batchSize - 1)));
|
||||
Forward(predictors.cols(begin, begin + batchSize - 1));
|
||||
double res = outputLayer.Forward(
|
||||
std::move(boost::apply_visitor(outputParameterVisitor, network.back())),
|
||||
std::move(responses.cols(begin, begin + batchSize - 1)));
|
||||
boost::apply_visitor(outputParameterVisitor, network.back()),
|
||||
responses.cols(begin, begin + batchSize - 1));
|
||||
|
||||
for (size_t i = 0; i < network.size(); ++i)
|
||||
{
|
||||
@@ -336,13 +381,13 @@ EvaluateWithGradient(const arma::mat& /* parameters */,
|
||||
}
|
||||
|
||||
outputLayer.Backward(
|
||||
std::move(boost::apply_visitor(outputParameterVisitor, network.back())),
|
||||
std::move(responses.cols(begin, begin + batchSize - 1)),
|
||||
std::move(error));
|
||||
boost::apply_visitor(outputParameterVisitor, network.back()),
|
||||
responses.cols(begin, begin + batchSize - 1),
|
||||
error);
|
||||
|
||||
Backward();
|
||||
ResetGradients(gradient);
|
||||
Gradient(std::move(predictors.cols(begin, begin + batchSize - 1)));
|
||||
Gradient(predictors.cols(begin, begin + batchSize - 1));
|
||||
|
||||
return res;
|
||||
}
|
||||
@@ -396,18 +441,19 @@ void FFN<OutputLayerType, InitializationRuleType,
|
||||
size_t offset = 0;
|
||||
for (size_t i = 0; i < network.size(); ++i)
|
||||
{
|
||||
offset += boost::apply_visitor(GradientSetVisitor(std::move(gradient),
|
||||
offset), network[i]);
|
||||
offset += boost::apply_visitor(GradientSetVisitor(gradient, offset),
|
||||
network[i]);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename OutputLayerType, typename InitializationRuleType,
|
||||
typename... CustomLayers>
|
||||
template<typename InputType>
|
||||
void FFN<OutputLayerType, InitializationRuleType,
|
||||
CustomLayers...>::Forward(arma::mat&& input)
|
||||
CustomLayers...>::Forward(const InputType& input)
|
||||
{
|
||||
boost::apply_visitor(ForwardVisitor(std::move(input), std::move(
|
||||
boost::apply_visitor(outputParameterVisitor, network.front()))),
|
||||
boost::apply_visitor(ForwardVisitor(input,
|
||||
boost::apply_visitor(outputParameterVisitor, network.front())),
|
||||
network.front());
|
||||
|
||||
if (!reset)
|
||||
@@ -434,9 +480,9 @@ void FFN<OutputLayerType, InitializationRuleType,
|
||||
boost::apply_visitor(SetInputHeightVisitor(height), network[i]);
|
||||
}
|
||||
|
||||
boost::apply_visitor(ForwardVisitor(std::move(boost::apply_visitor(
|
||||
outputParameterVisitor, network[i - 1])), std::move(
|
||||
boost::apply_visitor(outputParameterVisitor, network[i]))), network[i]);
|
||||
boost::apply_visitor(ForwardVisitor(boost::apply_visitor(
|
||||
outputParameterVisitor, network[i - 1]),
|
||||
boost::apply_visitor(outputParameterVisitor, network[i])), network[i]);
|
||||
|
||||
if (!reset)
|
||||
{
|
||||
@@ -462,37 +508,38 @@ template<typename OutputLayerType, typename InitializationRuleType,
|
||||
typename... CustomLayers>
|
||||
void FFN<OutputLayerType, InitializationRuleType, CustomLayers...>::Backward()
|
||||
{
|
||||
boost::apply_visitor(BackwardVisitor(std::move(boost::apply_visitor(
|
||||
outputParameterVisitor, network.back())), std::move(error), std::move(
|
||||
boost::apply_visitor(deltaVisitor, network.back()))), network.back());
|
||||
boost::apply_visitor(BackwardVisitor(boost::apply_visitor(
|
||||
outputParameterVisitor, network.back()), error,
|
||||
boost::apply_visitor(deltaVisitor, network.back())), network.back());
|
||||
|
||||
for (size_t i = 2; i < network.size(); ++i)
|
||||
{
|
||||
boost::apply_visitor(BackwardVisitor(std::move(boost::apply_visitor(
|
||||
outputParameterVisitor, network[network.size() - i])), std::move(
|
||||
boost::apply_visitor(deltaVisitor, network[network.size() - i + 1])),
|
||||
std::move(boost::apply_visitor(deltaVisitor,
|
||||
network[network.size() - i]))), network[network.size() - i]);
|
||||
boost::apply_visitor(BackwardVisitor(boost::apply_visitor(
|
||||
outputParameterVisitor, network[network.size() - i]),
|
||||
boost::apply_visitor(deltaVisitor, network[network.size() - i + 1]),
|
||||
boost::apply_visitor(deltaVisitor, network[network.size() - i])),
|
||||
network[network.size() - i]);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename OutputLayerType, typename InitializationRuleType,
|
||||
typename... CustomLayers>
|
||||
template<typename InputType>
|
||||
void FFN<OutputLayerType, InitializationRuleType,
|
||||
CustomLayers...>::Gradient(arma::mat&& input)
|
||||
CustomLayers...>::Gradient(const InputType& input)
|
||||
{
|
||||
boost::apply_visitor(GradientVisitor(std::move(input), std::move(
|
||||
boost::apply_visitor(deltaVisitor, network[1]))), network.front());
|
||||
boost::apply_visitor(GradientVisitor(input,
|
||||
boost::apply_visitor(deltaVisitor, network[1])), network.front());
|
||||
|
||||
for (size_t i = 1; i < network.size() - 1; ++i)
|
||||
{
|
||||
boost::apply_visitor(GradientVisitor(std::move(boost::apply_visitor(
|
||||
outputParameterVisitor, network[i - 1])), std::move(
|
||||
boost::apply_visitor(deltaVisitor, network[i + 1]))), network[i]);
|
||||
boost::apply_visitor(GradientVisitor(boost::apply_visitor(
|
||||
outputParameterVisitor, network[i - 1]),
|
||||
boost::apply_visitor(deltaVisitor, network[i + 1])), network[i]);
|
||||
}
|
||||
|
||||
boost::apply_visitor(GradientVisitor(std::move(boost::apply_visitor(
|
||||
outputParameterVisitor, network[network.size() - 2])), std::move(error)),
|
||||
boost::apply_visitor(GradientVisitor(boost::apply_visitor(
|
||||
outputParameterVisitor, network[network.size() - 2]), error),
|
||||
network[network.size() - 1]);
|
||||
}
|
||||
|
||||
@@ -505,7 +552,13 @@ void FFN<OutputLayerType, InitializationRuleType, CustomLayers...>::serialize(
|
||||
ar & BOOST_SERIALIZATION_NVP(parameter);
|
||||
ar & BOOST_SERIALIZATION_NVP(width);
|
||||
ar & BOOST_SERIALIZATION_NVP(height);
|
||||
ar & BOOST_SERIALIZATION_NVP(currentInput);
|
||||
|
||||
// Early versions used the currentInput member, which is now no longer needed.
|
||||
if (version < 2)
|
||||
{
|
||||
arma::mat currentInput; // Temporary matrix to output.
|
||||
ar & BOOST_SERIALIZATION_NVP(currentInput);
|
||||
}
|
||||
|
||||
// Earlier versions of the FFN code did not serialize whether or not the model
|
||||
// was reset.
|
||||
@@ -535,8 +588,8 @@ void FFN<OutputLayerType, InitializationRuleType, CustomLayers...>::serialize(
|
||||
size_t offset = 0;
|
||||
for (size_t i = 0; i < network.size(); ++i)
|
||||
{
|
||||
offset += boost::apply_visitor(WeightSetVisitor(std::move(parameter),
|
||||
offset), network[i]);
|
||||
offset += boost::apply_visitor(WeightSetVisitor(parameter, offset),
|
||||
network[i]);
|
||||
|
||||
boost::apply_visitor(resetVisitor, network[i]);
|
||||
}
|
||||
@@ -562,7 +615,6 @@ void FFN<OutputLayerType, InitializationRuleType,
|
||||
std::swap(parameter, network.parameter);
|
||||
std::swap(numFunctions, network.numFunctions);
|
||||
std::swap(error, network.error);
|
||||
std::swap(currentInput, network.currentInput);
|
||||
std::swap(deterministic, network.deterministic);
|
||||
std::swap(delta, network.delta);
|
||||
std::swap(inputParameter, network.inputParameter);
|
||||
@@ -584,7 +636,6 @@ FFN<OutputLayerType, InitializationRuleType, CustomLayers...>::FFN(
|
||||
parameter(network.parameter),
|
||||
numFunctions(network.numFunctions),
|
||||
error(network.error),
|
||||
currentInput(network.currentInput),
|
||||
deterministic(network.deterministic),
|
||||
delta(network.delta),
|
||||
inputParameter(network.inputParameter),
|
||||
@@ -613,7 +664,6 @@ FFN<OutputLayerType, InitializationRuleType, CustomLayers...>::FFN(
|
||||
parameter(std::move(network.parameter)),
|
||||
numFunctions(network.numFunctions),
|
||||
error(std::move(network.error)),
|
||||
currentInput(std::move(network.currentInput)),
|
||||
deterministic(network.deterministic),
|
||||
delta(std::move(network.delta)),
|
||||
inputParameter(std::move(network.inputParameter)),
|
||||
|
||||
@@ -289,7 +289,7 @@ class GAN
|
||||
*
|
||||
* @param input Sampled noise.
|
||||
*/
|
||||
void Forward(arma::mat&& input);
|
||||
void Forward(const arma::mat& input);
|
||||
|
||||
/**
|
||||
* This function predicts the output of the network on the given input.
|
||||
|
||||
@@ -258,28 +258,27 @@ GAN<Model, InitializationRuleType, Noise, PolicyType>::Evaluate(
|
||||
currentTarget = arma::mat(responses.memptr() + i, 1, batchSize, false,
|
||||
false);
|
||||
|
||||
discriminator.Forward(std::move(currentInput));
|
||||
discriminator.Forward(currentInput);
|
||||
double res = discriminator.outputLayer.Forward(
|
||||
std::move(boost::apply_visitor(
|
||||
boost::apply_visitor(
|
||||
outputParameterVisitor,
|
||||
discriminator.network.back())), std::move(currentTarget));
|
||||
discriminator.network.back()), currentTarget);
|
||||
|
||||
noise.imbue( [&]() { return noiseFunction();} );
|
||||
generator.Forward(std::move(noise));
|
||||
generator.Forward(noise);
|
||||
|
||||
predictors.cols(numFunctions, numFunctions + batchSize - 1) =
|
||||
boost::apply_visitor(outputParameterVisitor, generator.network.back());
|
||||
discriminator.Forward(std::move(predictors.cols(numFunctions,
|
||||
numFunctions + batchSize - 1)));
|
||||
discriminator.Forward(predictors.cols(numFunctions,
|
||||
numFunctions + batchSize - 1));
|
||||
responses.cols(numFunctions, numFunctions + batchSize - 1) =
|
||||
arma::zeros(1, batchSize);
|
||||
|
||||
currentTarget = arma::mat(responses.memptr() + numFunctions,
|
||||
1, batchSize, false, false);
|
||||
res += discriminator.outputLayer.Forward(
|
||||
std::move(boost::apply_visitor(
|
||||
outputParameterVisitor,
|
||||
discriminator.network.back())), std::move(currentTarget));
|
||||
boost::apply_visitor(outputParameterVisitor,
|
||||
discriminator.network.back()), currentTarget);
|
||||
|
||||
return res;
|
||||
}
|
||||
@@ -341,7 +340,7 @@ EvaluateWithGradient(const arma::mat& /* parameters */,
|
||||
i, gradientDiscriminator, batchSize);
|
||||
|
||||
noise.imbue( [&]() { return noiseFunction();} );
|
||||
generator.Forward(std::move(noise));
|
||||
generator.Forward(noise);
|
||||
predictors.cols(numFunctions, numFunctions + batchSize - 1) =
|
||||
boost::apply_visitor(outputParameterVisitor, generator.network.back());
|
||||
responses.cols(numFunctions, numFunctions + batchSize - 1) =
|
||||
@@ -419,18 +418,18 @@ template<
|
||||
typename PolicyType
|
||||
>
|
||||
void GAN<Model, InitializationRuleType, Noise, PolicyType>::Forward(
|
||||
arma::mat&& input)
|
||||
const arma::mat& input)
|
||||
{
|
||||
if (parameter.is_empty())
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
generator.Forward(std::move(input));
|
||||
generator.Forward(input);
|
||||
arma::mat ganOutput = boost::apply_visitor(outputParameterVisitor,
|
||||
generator.network.back());
|
||||
|
||||
discriminator.Forward(std::move(ganOutput));
|
||||
discriminator.Forward(ganOutput);
|
||||
}
|
||||
|
||||
template<
|
||||
@@ -453,7 +452,7 @@ Predict(arma::mat input, arma::mat& output)
|
||||
ResetDeterministic();
|
||||
}
|
||||
|
||||
Forward(std::move(input));
|
||||
Forward(input);
|
||||
|
||||
output = boost::apply_visitor(outputParameterVisitor,
|
||||
discriminator.network.back());
|
||||
@@ -502,8 +501,8 @@ serialize(Archive& ar, const unsigned int /* version */)
|
||||
size_t offset = 0;
|
||||
for (size_t i = 0; i < generator.network.size(); ++i)
|
||||
{
|
||||
offset += boost::apply_visitor(WeightSetVisitor(std::move(
|
||||
generator.parameter), offset), generator.network[i]);
|
||||
offset += boost::apply_visitor(WeightSetVisitor(
|
||||
generator.parameter, offset), generator.network[i]);
|
||||
|
||||
boost::apply_visitor(resetVisitor, generator.network[i]);
|
||||
}
|
||||
@@ -511,8 +510,8 @@ serialize(Archive& ar, const unsigned int /* version */)
|
||||
offset = 0;
|
||||
for (size_t i = 0; i < discriminator.network.size(); ++i)
|
||||
{
|
||||
offset += boost::apply_visitor(WeightSetVisitor(std::move(
|
||||
discriminator.parameter), offset), discriminator.network[i]);
|
||||
offset += boost::apply_visitor(WeightSetVisitor(
|
||||
discriminator.parameter, offset), discriminator.network[i]);
|
||||
|
||||
boost::apply_visitor(resetVisitor, discriminator.network[i]);
|
||||
}
|
||||
|
||||
@@ -50,28 +50,28 @@ GAN<Model, InitializationRuleType, Noise, PolicyType>::Evaluate(
|
||||
currentTarget = arma::mat(responses.memptr() + i, 1, batchSize, false,
|
||||
false);
|
||||
|
||||
discriminator.Forward(std::move(currentInput));
|
||||
discriminator.Forward(currentInput);
|
||||
double res = discriminator.outputLayer.Forward(
|
||||
std::move(boost::apply_visitor(
|
||||
boost::apply_visitor(
|
||||
outputParameterVisitor,
|
||||
discriminator.network.back())), std::move(currentTarget));
|
||||
discriminator.network.back()), currentTarget);
|
||||
|
||||
noise.imbue( [&]() { return noiseFunction();} );
|
||||
generator.Forward(std::move(noise));
|
||||
generator.Forward(noise);
|
||||
|
||||
predictors.cols(numFunctions, numFunctions + batchSize - 1) =
|
||||
boost::apply_visitor(outputParameterVisitor, generator.network.back());
|
||||
discriminator.Forward(std::move(predictors.cols(numFunctions,
|
||||
numFunctions + batchSize - 1)));
|
||||
discriminator.Forward(predictors.cols(numFunctions,
|
||||
numFunctions + batchSize - 1));
|
||||
responses.cols(numFunctions, numFunctions + batchSize - 1) =
|
||||
-arma::ones(1, batchSize);
|
||||
|
||||
currentTarget = arma::mat(responses.memptr() + numFunctions,
|
||||
1, batchSize, false, false);
|
||||
res += discriminator.outputLayer.Forward(
|
||||
std::move(boost::apply_visitor(
|
||||
boost::apply_visitor(
|
||||
outputParameterVisitor,
|
||||
discriminator.network.back())), std::move(currentTarget));
|
||||
discriminator.network.back()), currentTarget);
|
||||
|
||||
return res;
|
||||
}
|
||||
@@ -132,7 +132,7 @@ EvaluateWithGradient(const arma::mat& /* parameters */,
|
||||
i, gradientDiscriminator, batchSize);
|
||||
|
||||
noise.imbue( [&]() { return noiseFunction();} );
|
||||
generator.Forward(std::move(noise));
|
||||
generator.Forward(noise);
|
||||
predictors.cols(numFunctions, numFunctions + batchSize - 1) =
|
||||
boost::apply_visitor(outputParameterVisitor, generator.network.back());
|
||||
responses.cols(numFunctions, numFunctions + batchSize - 1) =
|
||||
|
||||
@@ -92,8 +92,8 @@ class NetworkInitialization
|
||||
// hold various other modules.
|
||||
for (size_t i = 0, offset = parameterOffset; i < network.size(); ++i)
|
||||
{
|
||||
offset += boost::apply_visitor(WeightSetVisitor(std::move(parameter),
|
||||
offset), network[i]);
|
||||
offset += boost::apply_visitor(WeightSetVisitor(parameter, offset),
|
||||
network[i]);
|
||||
|
||||
boost::apply_visitor(resetVisitor, network[i]);
|
||||
}
|
||||
|
||||
@@ -96,6 +96,10 @@ set(SOURCES
|
||||
weight_norm_impl.hpp
|
||||
hardshrink.hpp
|
||||
hardshrink_impl.hpp
|
||||
celu.hpp
|
||||
celu_impl.hpp
|
||||
softshrink.hpp
|
||||
softshrink_impl.hpp
|
||||
)
|
||||
|
||||
# Add directory name to sources.
|
||||
|
||||
@@ -49,7 +49,7 @@ class Add
|
||||
* @param output Resulting output activation.
|
||||
*/
|
||||
template<typename eT>
|
||||
void Forward(const arma::Mat<eT>&& input, arma::Mat<eT>&& output);
|
||||
void Forward(const arma::Mat<eT>& input, arma::Mat<eT>& output);
|
||||
|
||||
/**
|
||||
* Ordinary feed backward pass of a neural network, calculating the function
|
||||
@@ -61,9 +61,9 @@ class Add
|
||||
* @param g The calculated gradient.
|
||||
*/
|
||||
template<typename eT>
|
||||
void Backward(const arma::Mat<eT>&& /* input */,
|
||||
const arma::Mat<eT>&& gy,
|
||||
arma::Mat<eT>&& g);
|
||||
void Backward(const arma::Mat<eT>& /* input */,
|
||||
const arma::Mat<eT>& gy,
|
||||
arma::Mat<eT>& g);
|
||||
|
||||
/**
|
||||
* Calculate the gradient using the output delta and the input activation.
|
||||
@@ -73,9 +73,9 @@ class Add
|
||||
* @param gradient The calculated gradient.
|
||||
*/
|
||||
template<typename eT>
|
||||
void Gradient(const arma::Mat<eT>&& /* input */,
|
||||
arma::Mat<eT>&& error,
|
||||
arma::Mat<eT>&& gradient);
|
||||
void Gradient(const arma::Mat<eT>& /* input */,
|
||||
const arma::Mat<eT>& error,
|
||||
arma::Mat<eT>& gradient);
|
||||
|
||||
//! Get the parameters.
|
||||
OutputDataType const& Parameters() const { return weights; }
|
||||
|
||||
@@ -29,7 +29,7 @@ Add<InputDataType, OutputDataType>::Add(const size_t outSize) :
|
||||
template<typename InputDataType, typename OutputDataType>
|
||||
template<typename eT>
|
||||
void Add<InputDataType, OutputDataType>::Forward(
|
||||
const arma::Mat<eT>&& input, arma::Mat<eT>&& output)
|
||||
const arma::Mat<eT>& input, arma::Mat<eT>& output)
|
||||
{
|
||||
output = input;
|
||||
output.each_col() += weights;
|
||||
@@ -38,9 +38,9 @@ void Add<InputDataType, OutputDataType>::Forward(
|
||||
template<typename InputDataType, typename OutputDataType>
|
||||
template<typename eT>
|
||||
void Add<InputDataType, OutputDataType>::Backward(
|
||||
const arma::Mat<eT>&& /* input */,
|
||||
const arma::Mat<eT>&& gy,
|
||||
arma::Mat<eT>&& g)
|
||||
const arma::Mat<eT>& /* input */,
|
||||
const arma::Mat<eT>& gy,
|
||||
arma::Mat<eT>& g)
|
||||
{
|
||||
g = gy;
|
||||
}
|
||||
@@ -48,9 +48,9 @@ void Add<InputDataType, OutputDataType>::Backward(
|
||||
template<typename InputDataType, typename OutputDataType>
|
||||
template<typename eT>
|
||||
void Add<InputDataType, OutputDataType>::Gradient(
|
||||
const arma::Mat<eT>&& /* input */,
|
||||
arma::Mat<eT>&& error,
|
||||
arma::Mat<eT>&& gradient)
|
||||
const arma::Mat<eT>& /* input */,
|
||||
const arma::Mat<eT>& error,
|
||||
arma::Mat<eT>& gradient)
|
||||
{
|
||||
gradient = error;
|
||||
}
|
||||
|
||||
@@ -50,6 +50,15 @@ class AddMerge
|
||||
*/
|
||||
AddMerge(const bool model = false, const bool run = true);
|
||||
|
||||
/**
|
||||
* Create the AddMerge object using the specified parameters.
|
||||
*
|
||||
* @param model Expose all the network modules.
|
||||
* @param run Call the Forward/Backward method before the output is merged.
|
||||
* @param ownsLayers Delete the layers when this is deallocated.
|
||||
*/
|
||||
AddMerge(const bool model, const bool run, const bool ownsLayers);
|
||||
|
||||
//! Destructor to release allocated memory.
|
||||
~AddMerge();
|
||||
|
||||
@@ -61,7 +70,7 @@ class AddMerge
|
||||
* @param output Resulting output activation.
|
||||
*/
|
||||
template<typename InputType, typename OutputType>
|
||||
void Forward(InputType&& /* input */, OutputType&& output);
|
||||
void Forward(const InputType& /* input */, OutputType& output);
|
||||
|
||||
/**
|
||||
* Ordinary feed backward pass of a neural network, calculating the function
|
||||
@@ -73,9 +82,9 @@ class AddMerge
|
||||
* @param g The calculated gradient.
|
||||
*/
|
||||
template<typename eT>
|
||||
void Backward(const arma::Mat<eT>&& /* input */,
|
||||
arma::Mat<eT>&& gy,
|
||||
arma::Mat<eT>&& g);
|
||||
void Backward(const arma::Mat<eT>& /* input */,
|
||||
const arma::Mat<eT>& gy,
|
||||
arma::Mat<eT>& g);
|
||||
|
||||
/**
|
||||
* This is the overload of Backward() that runs only a specific layer with
|
||||
@@ -87,9 +96,9 @@ class AddMerge
|
||||
* @param The index of the layer to run.
|
||||
*/
|
||||
template<typename eT>
|
||||
void Backward(const arma::Mat<eT>&& /* input */,
|
||||
arma::Mat<eT>&& gy,
|
||||
arma::Mat<eT>&& g,
|
||||
void Backward(const arma::Mat<eT>& /* input */,
|
||||
const arma::Mat<eT>& gy,
|
||||
arma::Mat<eT>& g,
|
||||
const size_t index);
|
||||
|
||||
/*
|
||||
@@ -100,9 +109,9 @@ class AddMerge
|
||||
* @param gradient The calculated gradient.
|
||||
*/
|
||||
template<typename eT>
|
||||
void Gradient(arma::Mat<eT>&& input,
|
||||
arma::Mat<eT>&& error,
|
||||
arma::Mat<eT>&& gradient);
|
||||
void Gradient(const arma::Mat<eT>& input,
|
||||
const arma::Mat<eT>& error,
|
||||
arma::Mat<eT>& gradient);
|
||||
|
||||
/*
|
||||
* This is the overload of Gradient() that runs a specific layer with the
|
||||
@@ -114,9 +123,9 @@ class AddMerge
|
||||
* @param The index of the layer to run.
|
||||
*/
|
||||
template<typename eT>
|
||||
void Gradient(arma::Mat<eT>&& input,
|
||||
arma::Mat<eT>&& error,
|
||||
arma::Mat<eT>&& gradient,
|
||||
void Gradient(const arma::Mat<eT>& input,
|
||||
const arma::Mat<eT>& error,
|
||||
arma::Mat<eT>& gradient,
|
||||
const size_t index);
|
||||
|
||||
/*
|
||||
@@ -184,8 +193,9 @@ class AddMerge
|
||||
//! before merging the output.
|
||||
bool run;
|
||||
|
||||
//! We need this to know whether we should delete the layer in the destructor.
|
||||
bool ownsLayer;
|
||||
//! We need this to know whether we should delete the internally-held layers
|
||||
//! in the destructor.
|
||||
bool ownsLayers;
|
||||
|
||||
//! Locally-stored network modules.
|
||||
std::vector<LayerTypes<CustomLayers...> > network;
|
||||
@@ -221,6 +231,24 @@ class AddMerge
|
||||
} // namespace ann
|
||||
} // namespace mlpack
|
||||
|
||||
//! Set the serialization version of the AddMerge class.
|
||||
namespace boost {
|
||||
namespace serialization {
|
||||
|
||||
template<
|
||||
typename InputDataType,
|
||||
typename OutputDataType,
|
||||
typename... CustomLayers
|
||||
>
|
||||
struct version<mlpack::ann::AddMerge<
|
||||
InputDataType, OutputDataType, CustomLayers...>>
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(int, value = 1);
|
||||
};
|
||||
|
||||
} // namespace serialization
|
||||
} // namespace boost
|
||||
|
||||
// Include implementation.
|
||||
#include "add_merge_impl.hpp"
|
||||
|
||||
|
||||
@@ -27,7 +27,16 @@ template<typename InputDataType, typename OutputDataType,
|
||||
typename... CustomLayers>
|
||||
AddMerge<InputDataType, OutputDataType, CustomLayers...>::AddMerge(
|
||||
const bool model, const bool run) :
|
||||
model(model), run(run), ownsLayer(!model)
|
||||
model(model), run(run), ownsLayers(!model)
|
||||
{
|
||||
// Nothing to do here.
|
||||
}
|
||||
|
||||
template<typename InputDataType, typename OutputDataType,
|
||||
typename... CustomLayers>
|
||||
AddMerge<InputDataType, OutputDataType, CustomLayers...>::AddMerge(
|
||||
const bool model, const bool run, const bool ownsLayers) :
|
||||
model(model), run(run), ownsLayers(ownsLayers)
|
||||
{
|
||||
// Nothing to do here.
|
||||
}
|
||||
@@ -36,7 +45,7 @@ template<typename InputDataType, typename OutputDataType,
|
||||
typename... CustomLayers>
|
||||
AddMerge<InputDataType, OutputDataType, CustomLayers...>::~AddMerge()
|
||||
{
|
||||
if (ownsLayer)
|
||||
if (!model && ownsLayers)
|
||||
{
|
||||
std::for_each(network.begin(), network.end(),
|
||||
boost::apply_visitor(deleteVisitor));
|
||||
@@ -47,14 +56,14 @@ template <typename InputDataType, typename OutputDataType,
|
||||
typename... CustomLayers>
|
||||
template<typename InputType, typename OutputType>
|
||||
void AddMerge<InputDataType, OutputDataType, CustomLayers...>::Forward(
|
||||
InputType&& input, OutputType&& output)
|
||||
const InputType& input, OutputType& output)
|
||||
{
|
||||
if (run)
|
||||
{
|
||||
for (size_t i = 0; i < network.size(); ++i)
|
||||
{
|
||||
boost::apply_visitor(ForwardVisitor(std::move(input), std::move(
|
||||
boost::apply_visitor(outputParameterVisitor, network[i]))),
|
||||
boost::apply_visitor(ForwardVisitor(input,
|
||||
boost::apply_visitor(outputParameterVisitor, network[i])),
|
||||
network[i]);
|
||||
}
|
||||
}
|
||||
@@ -70,15 +79,17 @@ template<typename InputDataType, typename OutputDataType,
|
||||
typename... CustomLayers>
|
||||
template<typename eT>
|
||||
void AddMerge<InputDataType, OutputDataType, CustomLayers...>::Backward(
|
||||
const arma::Mat<eT>&& /* input */, arma::Mat<eT>&& gy, arma::Mat<eT>&& g)
|
||||
const arma::Mat<eT>& /* input */,
|
||||
const arma::Mat<eT>& gy,
|
||||
arma::Mat<eT>& g)
|
||||
{
|
||||
if (run)
|
||||
{
|
||||
for (size_t i = 0; i < network.size(); ++i)
|
||||
{
|
||||
boost::apply_visitor(BackwardVisitor(std::move(boost::apply_visitor(
|
||||
outputParameterVisitor, network[i])), std::move(gy), std::move(
|
||||
boost::apply_visitor(deltaVisitor, network[i]))), network[i]);
|
||||
boost::apply_visitor(BackwardVisitor(boost::apply_visitor(
|
||||
outputParameterVisitor, network[i]), gy,
|
||||
boost::apply_visitor(deltaVisitor, network[i])), network[i]);
|
||||
}
|
||||
|
||||
g = boost::apply_visitor(deltaVisitor, network[0]);
|
||||
@@ -95,12 +106,14 @@ template<typename InputDataType, typename OutputDataType,
|
||||
typename... CustomLayers>
|
||||
template<typename eT>
|
||||
void AddMerge<InputDataType, OutputDataType, CustomLayers...>::Backward(
|
||||
const arma::Mat<eT>&& /* input */, arma::Mat<eT>&& gy, arma::Mat<eT>&& g,
|
||||
const arma::Mat<eT>& /* input */,
|
||||
const arma::Mat<eT>& gy,
|
||||
arma::Mat<eT>& g,
|
||||
const size_t index)
|
||||
{
|
||||
boost::apply_visitor(BackwardVisitor(std::move(boost::apply_visitor(
|
||||
outputParameterVisitor, network[index])), std::move(gy), std::move(
|
||||
boost::apply_visitor(deltaVisitor, network[index]))), network[index]);
|
||||
boost::apply_visitor(BackwardVisitor(boost::apply_visitor(
|
||||
outputParameterVisitor, network[index]), gy,
|
||||
boost::apply_visitor(deltaVisitor, network[index])), network[index]);
|
||||
g = boost::apply_visitor(deltaVisitor, network[index]);
|
||||
}
|
||||
|
||||
@@ -108,16 +121,15 @@ template<typename InputDataType, typename OutputDataType,
|
||||
typename... CustomLayers>
|
||||
template<typename eT>
|
||||
void AddMerge<InputDataType, OutputDataType, CustomLayers...>::Gradient(
|
||||
arma::Mat<eT>&& input,
|
||||
arma::Mat<eT>&& error,
|
||||
arma::Mat<eT>&& /* gradient */ )
|
||||
const arma::Mat<eT>& input,
|
||||
const arma::Mat<eT>& error,
|
||||
arma::Mat<eT>& /* gradient */ )
|
||||
{
|
||||
if (run)
|
||||
{
|
||||
for (size_t i = 0; i < network.size(); ++i)
|
||||
{
|
||||
boost::apply_visitor(GradientVisitor(std::move(input), std::move(error)),
|
||||
network[i]);
|
||||
boost::apply_visitor(GradientVisitor(input, error), network[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -126,20 +138,19 @@ template<typename InputDataType, typename OutputDataType,
|
||||
typename... CustomLayers>
|
||||
template<typename eT>
|
||||
void AddMerge<InputDataType, OutputDataType, CustomLayers...>::Gradient(
|
||||
arma::Mat<eT>&& input,
|
||||
arma::Mat<eT>&& error,
|
||||
arma::Mat<eT>&& /* gradient */,
|
||||
const arma::Mat<eT>& input,
|
||||
const arma::Mat<eT>& error,
|
||||
arma::Mat<eT>& /* gradient */,
|
||||
const size_t index)
|
||||
{
|
||||
boost::apply_visitor(GradientVisitor(std::move(input), std::move(error)),
|
||||
network[index]);
|
||||
boost::apply_visitor(GradientVisitor(input, error), network[index]);
|
||||
}
|
||||
|
||||
template<typename InputDataType, typename OutputDataType,
|
||||
typename... CustomLayers>
|
||||
template<typename Archive>
|
||||
void AddMerge<InputDataType, OutputDataType, CustomLayers...>::serialize(
|
||||
Archive& ar, const unsigned int /* version */)
|
||||
Archive& ar, const unsigned int version)
|
||||
{
|
||||
// Be sure to clear other layers before loading.
|
||||
if (Archive::is_loading::value)
|
||||
@@ -148,7 +159,11 @@ void AddMerge<InputDataType, OutputDataType, CustomLayers...>::serialize(
|
||||
ar & BOOST_SERIALIZATION_NVP(network);
|
||||
ar & BOOST_SERIALIZATION_NVP(model);
|
||||
ar & BOOST_SERIALIZATION_NVP(run);
|
||||
ar & BOOST_SERIALIZATION_NVP(ownsLayer);
|
||||
|
||||
if (version >= 1)
|
||||
ar & BOOST_SERIALIZATION_NVP(ownsLayers);
|
||||
else if (Archive::is_loading::value)
|
||||
ownsLayers = !model;
|
||||
}
|
||||
|
||||
} // namespace ann
|
||||
|
||||
@@ -35,7 +35,8 @@ namespace ann /** Artificial Neural Network. */ {
|
||||
* Andreas Mayr},
|
||||
* title = {Self-Normalizing Neural Networks},
|
||||
* journal = {Advances in Neural Information Processing Systems},
|
||||
* year = {2017}
|
||||
* year = {2017},
|
||||
* url = {https://arxiv.org/abs/1706.02515}
|
||||
* }
|
||||
* @endcode
|
||||
*
|
||||
@@ -65,7 +66,7 @@ class AlphaDropout
|
||||
* @param output Resulting output activation.
|
||||
*/
|
||||
template<typename eT>
|
||||
void Forward(const arma::Mat<eT>&& input, arma::Mat<eT>&& output);
|
||||
void Forward(const arma::Mat<eT>& input, arma::Mat<eT>& output);
|
||||
|
||||
/**
|
||||
* Ordinary feed backward pass of the alpha_dropout layer.
|
||||
@@ -75,9 +76,9 @@ class AlphaDropout
|
||||
* @param g The calculated gradient.
|
||||
*/
|
||||
template<typename eT>
|
||||
void Backward(const arma::Mat<eT>&& /* input */,
|
||||
arma::Mat<eT>&& gy,
|
||||
arma::Mat<eT>&& g);
|
||||
void Backward(const arma::Mat<eT>& /* input */,
|
||||
const arma::Mat<eT>& gy,
|
||||
arma::Mat<eT>& g);
|
||||
|
||||
//! Get the output parameter.
|
||||
OutputDataType const& OutputParameter() const { return outputParameter; }
|
||||
|
||||
@@ -36,7 +36,7 @@ AlphaDropout<InputDataType, OutputDataType>::AlphaDropout(
|
||||
template<typename InputDataType, typename OutputDataType>
|
||||
template<typename eT>
|
||||
void AlphaDropout<InputDataType, OutputDataType>::Forward(
|
||||
const arma::Mat<eT>&& input, arma::Mat<eT>&& output)
|
||||
const arma::Mat<eT>& input, arma::Mat<eT>& output)
|
||||
{
|
||||
// The dropout mask will not be multiplied in the deterministic mode
|
||||
// (during testing).
|
||||
@@ -58,7 +58,7 @@ void AlphaDropout<InputDataType, OutputDataType>::Forward(
|
||||
template<typename InputDataType, typename OutputDataType>
|
||||
template<typename eT>
|
||||
void AlphaDropout<InputDataType, OutputDataType>::Backward(
|
||||
const arma::Mat<eT>&& /* input */, arma::Mat<eT>&& gy, arma::Mat<eT>&& g)
|
||||
const arma::Mat<eT>& /* input */, const arma::Mat<eT>& gy, arma::Mat<eT>& g)
|
||||
{
|
||||
g = gy % mask * a;
|
||||
}
|
||||
|
||||
@@ -137,7 +137,7 @@ class AtrousConvolution
|
||||
* @param output Resulting output activation.
|
||||
*/
|
||||
template<typename eT>
|
||||
void Forward(const arma::Mat<eT>&& input, arma::Mat<eT>&& output);
|
||||
void Forward(const arma::Mat<eT>& input, arma::Mat<eT>& output);
|
||||
|
||||
/**
|
||||
* Ordinary feed backward pass of a neural network, calculating the function
|
||||
@@ -149,9 +149,9 @@ class AtrousConvolution
|
||||
* @param g The calculated gradient.
|
||||
*/
|
||||
template<typename eT>
|
||||
void Backward(const arma::Mat<eT>&& /* input */,
|
||||
arma::Mat<eT>&& gy,
|
||||
arma::Mat<eT>&& g);
|
||||
void Backward(const arma::Mat<eT>& /* input */,
|
||||
const arma::Mat<eT>& gy,
|
||||
arma::Mat<eT>& g);
|
||||
|
||||
/*
|
||||
* Calculate the gradient using the output delta and the input activation.
|
||||
@@ -161,9 +161,9 @@ class AtrousConvolution
|
||||
* @param gradient The calculated gradient.
|
||||
*/
|
||||
template<typename eT>
|
||||
void Gradient(const arma::Mat<eT>&& /* input */,
|
||||
arma::Mat<eT>&& error,
|
||||
arma::Mat<eT>&& gradient);
|
||||
void Gradient(const arma::Mat<eT>& /* input */,
|
||||
const arma::Mat<eT>& error,
|
||||
arma::Mat<eT>& gradient);
|
||||
|
||||
//! Get the parameters.
|
||||
const OutputDataType& Parameters() const { return weights; }
|
||||
@@ -365,9 +365,6 @@ class AtrousConvolution
|
||||
//! Locally-stored transformed output parameter.
|
||||
arma::cube outputTemp;
|
||||
|
||||
//! Locally-stored transformed input parameter.
|
||||
arma::cube inputTemp;
|
||||
|
||||
//! Locally-stored transformed padded input parameter.
|
||||
arma::cube inputPaddedTemp;
|
||||
|
||||
|
||||
@@ -184,10 +184,10 @@ void AtrousConvolution<
|
||||
GradientConvolutionRule,
|
||||
InputDataType,
|
||||
OutputDataType
|
||||
>::Forward(const arma::Mat<eT>&& input, arma::Mat<eT>&& output)
|
||||
>::Forward(const arma::Mat<eT>& input, arma::Mat<eT>& output)
|
||||
{
|
||||
batchSize = input.n_cols;
|
||||
inputTemp = arma::cube(const_cast<arma::Mat<eT>&&>(input).memptr(),
|
||||
arma::cube inputTemp(const_cast<arma::Mat<eT>&>(input).memptr(),
|
||||
inputWidth, inputHeight, inSize * batchSize, false, false);
|
||||
|
||||
if (padding.PadWLeft() != 0 || padding.PadWRight() != 0 ||
|
||||
@@ -200,8 +200,7 @@ void AtrousConvolution<
|
||||
|
||||
for (size_t i = 0; i < inputTemp.n_slices; ++i)
|
||||
{
|
||||
padding.Forward(std::move(inputTemp.slice(i)),
|
||||
std::move(inputPaddedTemp.slice(i)));
|
||||
padding.Forward(inputTemp.slice(i), inputPaddedTemp.slice(i));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -267,14 +266,14 @@ void AtrousConvolution<
|
||||
InputDataType,
|
||||
OutputDataType
|
||||
>::Backward(
|
||||
const arma::Mat<eT>&& /* input */, arma::Mat<eT>&& gy, arma::Mat<eT>&& g)
|
||||
const arma::Mat<eT>& /* input */, const arma::Mat<eT>& gy, arma::Mat<eT>& g)
|
||||
{
|
||||
arma::cube mappedError(gy.memptr(), outputWidth, outputHeight,
|
||||
outSize * batchSize, false, false);
|
||||
arma::cube mappedError(((arma::Mat<eT>&) gy).memptr(), outputWidth,
|
||||
outputHeight, outSize * batchSize, false, false);
|
||||
|
||||
g.set_size(inputTemp.n_rows * inputTemp.n_cols * inSize, batchSize);
|
||||
gTemp = arma::Cube<eT>(g.memptr(), inputTemp.n_rows,
|
||||
inputTemp.n_cols, inputTemp.n_slices, false, false);
|
||||
g.set_size(inputWidth * inputHeight * inSize, batchSize);
|
||||
gTemp = arma::Cube<eT>(g.memptr(), inputWidth, inputHeight,
|
||||
inSize * batchSize, false, false);
|
||||
gTemp.zeros();
|
||||
|
||||
for (size_t outMap = 0, outMapIdx = 0, batchCount = 0; outMap <
|
||||
@@ -326,12 +325,14 @@ void AtrousConvolution<
|
||||
InputDataType,
|
||||
OutputDataType
|
||||
>::Gradient(
|
||||
const arma::Mat<eT>&& /* input */,
|
||||
arma::Mat<eT>&& error,
|
||||
arma::Mat<eT>&& gradient)
|
||||
const arma::Mat<eT>& input,
|
||||
const arma::Mat<eT>& error,
|
||||
arma::Mat<eT>& gradient)
|
||||
{
|
||||
arma::cube mappedError(error.memptr(), outputWidth, outputHeight,
|
||||
outSize * batchSize, false, false);
|
||||
arma::cube mappedError(((arma::Mat<eT>&) error).memptr(), outputWidth,
|
||||
outputHeight, outSize * batchSize, false, false);
|
||||
arma::cube inputTemp(const_cast<arma::Mat<eT>&>(input).memptr(),
|
||||
inputWidth, inputHeight, inSize * batchSize, false, false);
|
||||
|
||||
gradient.set_size(weights.n_elem, 1);
|
||||
gradientTemp = arma::Cube<eT>(gradient.memptr(), weight.n_rows,
|
||||
|
||||
@@ -69,7 +69,7 @@ class BaseLayer
|
||||
* @param output Resulting output activation.
|
||||
*/
|
||||
template<typename InputType, typename OutputType>
|
||||
void Forward(const InputType&& input, OutputType&& output)
|
||||
void Forward(const InputType& input, OutputType& output)
|
||||
{
|
||||
ActivationFunction::Fn(input, output);
|
||||
}
|
||||
@@ -84,9 +84,9 @@ class BaseLayer
|
||||
* @param g The calculated gradient.
|
||||
*/
|
||||
template<typename eT>
|
||||
void Backward(const arma::Mat<eT>&& input,
|
||||
arma::Mat<eT>&& gy,
|
||||
arma::Mat<eT>&& g)
|
||||
void Backward(const arma::Mat<eT>& input,
|
||||
const arma::Mat<eT>& gy,
|
||||
arma::Mat<eT>& g)
|
||||
{
|
||||
arma::Mat<eT> derivative;
|
||||
ActivationFunction::Deriv(input, derivative);
|
||||
|
||||
@@ -81,7 +81,7 @@ class BatchNorm
|
||||
* @param output Resulting output activations.
|
||||
*/
|
||||
template<typename eT>
|
||||
void Forward(const arma::Mat<eT>&& input, arma::Mat<eT>&& output);
|
||||
void Forward(const arma::Mat<eT>& input, arma::Mat<eT>& output);
|
||||
|
||||
/**
|
||||
* Backward pass through the layer.
|
||||
@@ -91,9 +91,9 @@ class BatchNorm
|
||||
* @param g The calculated gradient.
|
||||
*/
|
||||
template<typename eT>
|
||||
void Backward(const arma::Mat<eT>&& input,
|
||||
arma::Mat<eT>&& gy,
|
||||
arma::Mat<eT>&& g);
|
||||
void Backward(const arma::Mat<eT>& input,
|
||||
const arma::Mat<eT>& gy,
|
||||
arma::Mat<eT>& g);
|
||||
|
||||
/**
|
||||
* Calculate the gradient using the output delta and the input activations.
|
||||
@@ -103,9 +103,9 @@ class BatchNorm
|
||||
* @param gradient The calculated gradient.
|
||||
*/
|
||||
template<typename eT>
|
||||
void Gradient(const arma::Mat<eT>&& input,
|
||||
arma::Mat<eT>&& error,
|
||||
arma::Mat<eT>&& gradient);
|
||||
void Gradient(const arma::Mat<eT>& input,
|
||||
const arma::Mat<eT>& error,
|
||||
arma::Mat<eT>& gradient);
|
||||
|
||||
//! Get the parameters.
|
||||
OutputDataType const& Parameters() const { return weights; }
|
||||
|
||||
@@ -63,7 +63,7 @@ void BatchNorm<InputDataType, OutputDataType>::Reset()
|
||||
template<typename InputDataType, typename OutputDataType>
|
||||
template<typename eT>
|
||||
void BatchNorm<InputDataType, OutputDataType>::Forward(
|
||||
const arma::Mat<eT>&& input, arma::Mat<eT>&& output)
|
||||
const arma::Mat<eT>& input, arma::Mat<eT>& output)
|
||||
{
|
||||
// Mean and variance over the entire training set will be used to compute
|
||||
// the forward pass when deterministic is set to true.
|
||||
@@ -106,7 +106,7 @@ void BatchNorm<InputDataType, OutputDataType>::Forward(
|
||||
template<typename InputDataType, typename OutputDataType>
|
||||
template<typename eT>
|
||||
void BatchNorm<InputDataType, OutputDataType>::Backward(
|
||||
const arma::Mat<eT>&& input, arma::Mat<eT>&& gy, arma::Mat<eT>&& g)
|
||||
const arma::Mat<eT>& input, const arma::Mat<eT>& gy, arma::Mat<eT>& g)
|
||||
{
|
||||
const arma::mat stdInv = 1.0 / arma::sqrt(variance + eps);
|
||||
|
||||
@@ -130,9 +130,9 @@ void BatchNorm<InputDataType, OutputDataType>::Backward(
|
||||
template<typename InputDataType, typename OutputDataType>
|
||||
template<typename eT>
|
||||
void BatchNorm<InputDataType, OutputDataType>::Gradient(
|
||||
const arma::Mat<eT>&& /* input */,
|
||||
arma::Mat<eT>&& error,
|
||||
arma::Mat<eT>&& gradient)
|
||||
const arma::Mat<eT>& /* input */,
|
||||
const arma::Mat<eT>& error,
|
||||
arma::Mat<eT>& gradient)
|
||||
{
|
||||
gradient.set_size(size + size, 1);
|
||||
|
||||
|
||||
@@ -65,7 +65,7 @@ class BilinearInterpolation
|
||||
* @param output The resulting interpolated output matrix.
|
||||
*/
|
||||
template<typename eT>
|
||||
void Forward(const arma::Mat<eT>&& input, arma::Mat<eT>&& output);
|
||||
void Forward(const arma::Mat<eT>& input, arma::Mat<eT>& output);
|
||||
|
||||
/**
|
||||
* Ordinary feed backward pass of a neural network, calculating the function
|
||||
@@ -79,9 +79,9 @@ class BilinearInterpolation
|
||||
* @param output The resulting down-sampled output.
|
||||
*/
|
||||
template<typename eT>
|
||||
void Backward(const arma::Mat<eT>&& /*input*/,
|
||||
arma::Mat<eT>&& gradient,
|
||||
arma::Mat<eT>&& output);
|
||||
void Backward(const arma::Mat<eT>& /*input*/,
|
||||
const arma::Mat<eT>& gradient,
|
||||
arma::Mat<eT>& output);
|
||||
|
||||
//! Get the output parameter.
|
||||
OutputDataType const& OutputParameter() const { return outputParameter; }
|
||||
|
||||
@@ -54,7 +54,7 @@ BilinearInterpolation(
|
||||
template<typename InputDataType, typename OutputDataType>
|
||||
template<typename eT>
|
||||
void BilinearInterpolation<InputDataType, OutputDataType>::Forward(
|
||||
const arma::Mat<eT>&& input, arma::Mat<eT>&& output)
|
||||
const arma::Mat<eT>& input, arma::Mat<eT>& output)
|
||||
{
|
||||
batchSize = input.n_cols;
|
||||
if (output.is_empty())
|
||||
@@ -68,7 +68,7 @@ void BilinearInterpolation<InputDataType, OutputDataType>::Forward(
|
||||
assert(inRowSize >= 2);
|
||||
assert(inColSize >= 2);
|
||||
|
||||
arma::cube inputAsCube(const_cast<arma::Mat<eT>&&>(input).memptr(),
|
||||
arma::cube inputAsCube(const_cast<arma::Mat<eT>&>(input).memptr(),
|
||||
inRowSize, inColSize, depth * batchSize, false, false);
|
||||
arma::cube outputAsCube(output.memptr(), outRowSize, outColSize,
|
||||
depth * batchSize, false, true);
|
||||
@@ -114,9 +114,9 @@ void BilinearInterpolation<InputDataType, OutputDataType>::Forward(
|
||||
template<typename InputDataType, typename OutputDataType>
|
||||
template<typename eT>
|
||||
void BilinearInterpolation<InputDataType, OutputDataType>::Backward(
|
||||
const arma::Mat<eT>&& /*input*/,
|
||||
arma::Mat<eT>&& gradient,
|
||||
arma::Mat<eT>&& output)
|
||||
const arma::Mat<eT>& /*input*/,
|
||||
const arma::Mat<eT>& gradient,
|
||||
arma::Mat<eT>& output)
|
||||
{
|
||||
if (output.is_empty())
|
||||
output.set_size(inRowSize * inColSize * depth, batchSize);
|
||||
@@ -129,8 +129,8 @@ void BilinearInterpolation<InputDataType, OutputDataType>::Backward(
|
||||
assert(outRowSize >= 2);
|
||||
assert(outColSize >= 2);
|
||||
|
||||
arma::cube gradientAsCube(gradient.memptr(), outRowSize, outColSize,
|
||||
depth * batchSize, false, false);
|
||||
arma::cube gradientAsCube(((arma::Mat<eT>&) gradient).memptr(), outRowSize,
|
||||
outColSize, depth * batchSize, false, false);
|
||||
arma::cube outputAsCube(output.memptr(), inRowSize, inColSize,
|
||||
depth * batchSize, false, true);
|
||||
|
||||
|
||||
@@ -33,7 +33,8 @@ namespace ann /** Artificial Neural Network. */ {
|
||||
* title = {Understanding and Improving Convolutional Neural Networks
|
||||
* via Concatenated Rectified Linear Units},
|
||||
* author = {LWenling Shang, Kihyuk Sohn, Diogo Almeida, Honglak Lee},
|
||||
* year = {2016}
|
||||
* year = {2016},
|
||||
* url = {https://arxiv.org/abs/1603.05201}
|
||||
* }
|
||||
* @endcode
|
||||
*
|
||||
@@ -57,13 +58,13 @@ class CReLU
|
||||
/**
|
||||
* Ordinary feed forward pass of a neural network, evaluating the function
|
||||
* f(x) by propagating the activity forward through f.
|
||||
* Works only for 2D Tenosrs.
|
||||
* Works only for 2D Tensors.
|
||||
*
|
||||
* @param input Input data used for evaluating the specified function.
|
||||
* @param output Resulting output activation.
|
||||
*/
|
||||
template<typename InputType, typename OutputType>
|
||||
void Forward(const InputType&& input, OutputType&& output);
|
||||
void Forward(const InputType& input, OutputType& output);
|
||||
|
||||
/**
|
||||
* Ordinary feed backward pass of a neural network, calculating the function
|
||||
@@ -75,7 +76,7 @@ class CReLU
|
||||
* @param g The calculated gradient.
|
||||
*/
|
||||
template<typename DataType>
|
||||
void Backward(const DataType&& input, DataType&& gy, DataType&& g);
|
||||
void Backward(const DataType& input, const DataType& gy, DataType& g);
|
||||
|
||||
//! Get the output parameter.
|
||||
OutputDataType const& OutputParameter() const { return outputParameter; }
|
||||
|
||||
@@ -27,7 +27,7 @@ CReLU<InputDataType, OutputDataType>::CReLU()
|
||||
template<typename InputDataType, typename OutputDataType>
|
||||
template<typename InputType, typename OutputType>
|
||||
void CReLU<InputDataType, OutputDataType>::Forward(
|
||||
const InputType&& input, OutputType&& output)
|
||||
const InputType& input, OutputType& output)
|
||||
{
|
||||
output = arma::join_cols(arma::max(input, 0.0 * input), arma::max(
|
||||
(-1 * input), 0.0 * input));
|
||||
@@ -36,7 +36,7 @@ void CReLU<InputDataType, OutputDataType>::Forward(
|
||||
template<typename InputDataType, typename OutputDataType>
|
||||
template<typename DataType>
|
||||
void CReLU<InputDataType, OutputDataType>::Backward(
|
||||
const DataType&& input, DataType&& gy, DataType&& g)
|
||||
const DataType& input, const DataType& gy, DataType& g)
|
||||
{
|
||||
DataType temp;
|
||||
temp = gy % (input >= 0.0);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user