Merge branch 'master' into random-split

This commit is contained in:
Rishabh Garg
2021-05-09 06:52:44 +05:30
committed by GitHub
47 changed files with 961 additions and 349 deletions
+4 -4
View File
@@ -21,7 +21,7 @@ steps:
unset BOOST_ROOT
echo "##vso[task.setvariable variable=BOOST_ROOT]"$BOOST_ROOT
sudo apt-get install -y --allow-unauthenticated libopenblas-dev g++ libboost1.70-dev xz-utils
sudo apt-get install -y --allow-unauthenticated libopenblas-dev g++ libboost-all-dev xz-utils
if [ "$(binding)" == "python" ]; then
export PYBIN=$(which python)
@@ -41,7 +41,7 @@ steps:
# Install cereal.
wget https://github.com/USCiLab/cereal/archive/v1.3.0.tar.gz
tar -xvzpf v1.3.0.tar.gz # Unpack into cereal-1.3.0/.
cd cereal-1.3.0/
displayName: 'Install Build Dependencies'
# Configure mlpack (CMake)
@@ -56,12 +56,12 @@ steps:
displayName: 'CMake'
# Build mlpack
- script: cd build && make
- script: cd build && make && make mlpack_test
condition: eq(variables['CMakeArgs'], '-DDEBUG=ON -DPROFILE=OFF -DBUILD_PYTHON_BINDINGS=OFF -DBUILD_JULIA_BINDINGS=OFF -DBUILD_GO_BINDINGS=OFF -DBUILD_R_BINDINGS=OFF')
displayName: 'Build'
# Build mlpack
- script: cd build && make -j2
- script: cd build && make -j2 && make -j2 mlpack_test
condition: ne(variables['CMakeArgs'], '-DDEBUG=ON -DPROFILE=OFF -DBUILD_PYTHON_BINDINGS=OFF -DBUILD_JULIA_BINDINGS=OFF -DBUILD_GO_BINDINGS=OFF -DBUILD_R_BINDINGS=OFF')
displayName: 'Build'
+2 -2
View File
@@ -45,7 +45,7 @@ steps:
displayName: 'CMake'
# Build mlpack
- script: cd build && make -j2
- script: cd build && make -j2 && make -j2 mlpack_test
displayName: 'Build'
# Run tests via ctest.
@@ -65,4 +65,4 @@ steps:
inputs:
pathtoPublish: 'build/Testing/'
artifactName: 'Tests'
displayName: 'Publish artifacts test results'
displayName: 'Publish artifacts test results'
+1
View File
@@ -88,6 +88,7 @@ steps:
# Run tests via ctest.
- bash: |
cd build
cmake --build . --target mlpack_test -C Release
CTEST_OUTPUT_ON_FAILURE=1 ctest -T Test -C Release . -j1
displayName: 'Run tests via ctest'
+1 -1
View File
@@ -68,7 +68,7 @@ jobs:
- name: Build
run: |
cd build && make -j2
cd build && make -j2 && make -j2 mlpack_test
- name: Run tests via ctest
run: |
+56
View File
@@ -0,0 +1,56 @@
## This function auto-downloads mlpack dependencies.
## You need to pass the LINK to download from, the name of
## the dependency, and the name of the compressed package such as
## armadillo.tar.gz
## At each download, this module sets a GENERIC_INCLUDE_DIR path,
## which means that you need to set the main path for the include
## directories for each package.
## Note that, the package should be compressed only as .tar.gz
macro(get_deps LINK DEPS_NAME PACKAGE)
if (NOT EXISTS "${CMAKE_BINARY_DIR}/deps/${PACKAGE}")
file(DOWNLOAD ${LINK}
"${CMAKE_BINARY_DIR}/deps/${PACKAGE}"
STATUS DOWNLOAD_STATUS_LIST LOG DOWNLOAD_LOG
SHOW_PROGRESS)
list(GET DOWNLOAD_STATUS_LIST 0 DOWNLOAD_STATUS)
if (DOWNLOAD_STATUS EQUAL 0)
execute_process(COMMAND ${CMAKE_COMMAND} -E
tar xf "${CMAKE_BINARY_DIR}/deps/${PACKAGE}"
WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/deps/")
else ()
list(GET DOWNLOAD_STATUS_LIST 1 DOWNLOAD_ERROR)
message(FATAL_ERROR
"Could not download ${DEPS_NAME}! Error code ${DOWNLOAD_STATUS}: ${DOWNLOAD_ERROR}! Error log: ${DOWNLOAD_LOG}")
endif()
endif()
# Get the name of the directory.
file (GLOB DIRECTORIES RELATIVE "${CMAKE_BINARY_DIR}/deps/"
"${CMAKE_BINARY_DIR}/deps/${DEPS_NAME}*.*")
# Clean this line when boost is removed.
if (${DEPS_NAME} MATCHES "boost")
file (GLOB DIRECTORIES RELATIVE "${CMAKE_BINARY_DIR}/deps/"
"${CMAKE_BINARY_DIR}/deps/${DEPS_NAME}*_*")
elseif(${DEPS_NAME} MATCHES "stb")
file (GLOB DIRECTORIES RELATIVE "${CMAKE_BINARY_DIR}/deps/"
"${CMAKE_BINARY_DIR}/deps/${DEPS_NAME}")
endif()
# list(FILTER) is not available on 3.5 or older, but try to keep
# configuring without filtering the list anyway
# (it works only if the file is present as .tar.gz).
if (${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.6.0")
list(FILTER DIRECTORIES EXCLUDE REGEX ".*\.tar\.gz")
endif ()
list(LENGTH DIRECTORIES DIRECTORIES_LEN)
if (DIRECTORIES_LEN GREATER 0)
list(GET DIRECTORIES 0 DEPENDENCY_DIR)
set(GENERIC_INCLUDE_DIR "${CMAKE_BINARY_DIR}/deps/${DEPENDENCY_DIR}/include")
# Clean this line when boost is removed.
if (${DEPS_NAME} MATCHES "boost")
set(Boost_INCLUDE_DIR "${CMAKE_BINARY_DIR}/deps/${DEPENDENCY_DIR}/")
endif()
else ()
message(FATAL_ERROR
"Problem unpacking ${DEPS_NAME}! Expected only one directory ${DEPS_NAME};. Try to remove the directory ${CMAKE_BINARY_DIR}/deps and reconfigure.")
endif ()
endmacro()
+44
View File
@@ -0,0 +1,44 @@
# This file adds the necessary configurations to cross compile
# mlpack for embedded systems. You need to set the following variables
# from the command line: CMAKE_SYSROOT and TOOLCHAIN_PREFIX.
# This file will compile OpenBLAS if it is downloaded and it is not
# available on your system in order to find the BLAS library. If OpenBLAS will
# be compiled, the OPENBLAS_TARGET variable must be set. This can be done
# by, e.g., setting BOARD_NAME (which will set OPENBLAS_TARGET in
# `board/flags-config.cmake`).
if (CMAKE_CROSSCOMPILING)
include(board/flags-config.cmake)
if (NOT CMAKE_SYSROOT AND (NOT TOOLCHAIN_PREFIX))
message(FATAL_ERROR "Neither CMAKE_SYSROOT nor TOOLCHAIN_PREFIX are set; please set both of them and try again.")
elseif(NOT CMAKE_SYSROOT)
message(FATAL_ERROR "Cannot configure: CMAKE_SYSROOT must be set when performing cross-compiling!")
elseif(NOT TOOLCHAIN_PREFIX)
message(FATAL_ERROR "Cannot configure: TOOLCHAIN_PREFIX must be set when performing cross-compiling!")
endif()
endif()
macro(search_openblas version)
set(BLA_STATIC ON)
find_package(BLAS)
if (NOT BLAS_FOUND OR (NOT BLAS_LIBRARIES))
if(NOT OPENBLAS_TARGET)
message(FATAL_ERROR "Cannot compile OpenBLAS: OPENBLAS_TARGET is not set. Either set that variable, or set BOARD_NAME correctly!")
endif()
get_deps(https://github.com/xianyi/OpenBLAS/releases/download/v${version}/OpenBLAS-${version}.tar.gz OpenBLAS OpenBLAS-${version}.tar.gz)
if (NOT MSVC)
if (NOT EXISTS "${CMAKE_BINARY_DIR}/deps/OpenBLAS-${version}/libopenblas.a")
execute_process(COMMAND make TARGET=${OPENBLAS_TARGET} BINARY=${OPENBLAS_BINARY} HOSTCC=gcc CC=${CMAKE_C_COMPILER} FC=${CMAKE_FORTRAN_COMPILER} NO_SHARED=1
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/deps/OpenBLAS-${version})
endif()
file(GLOB OPENBLAS_LIBRARIES "${CMAKE_BINARY_DIR}/deps/OpenBLAS-${version}/libopenblas.a")
set(BLAS_openblas_LIBRARY ${OPENBLAS_LIBRARIES})
set(LAPACK_openblas_LIBRARY ${OPENBLAS_LIBRARIES})
set(BLA_VENDOR OpenBLAS)
set(BLAS_FOUND ON)
endif()
endif()
find_library(GFORTRAN NAMES libgfortran.a)
find_library(PTHREAD NAMES libpthread.a)
set(COMPILER_SUPPORT_LIBRARIES ${COMPILER_SUPPORT_LIBRARIES} ${GFORTRAN} ${PTHREAD})
endmacro()
+5 -3
View File
@@ -77,13 +77,14 @@ else()
# don't link to armadillo in this case
set(ARMADILLO_LIBRARY "")
endif()
# Link to support libraries in either case on MSVC.
if(NOT _ARMA_USE_WRAPPER OR MSVC)
if(_ARMA_USE_LAPACK)
if(ARMADILLO_FIND_QUIETLY OR NOT ARMADILLO_FIND_REQUIRED)
find_package(LAPACK QUIET)
else()
find_package(LAPCK REQUIRED)
find_package(LAPACK REQUIRED)
endif()
if(LAPACK_FOUND)
set(_ARMA_SUPPORT_LIBRARIES "${_ARMA_SUPPORT_LIBRARIES}" "${LAPACK_LIBRARIES}")
@@ -154,5 +155,6 @@ unset(__ARMA_SUPPORT_INCLUDE_DIRS)
# Hide internal variables
mark_as_advanced(
ARMADILLO_INCLUDE_DIR
ARMADILLO_LIBRARY)
ARMADILLO_INCLUDE_DIR
ARMADILLO_LIBRARY
ARMADILLO_LIBRARIES)
+94 -135
View File
@@ -3,6 +3,8 @@ project(mlpack C CXX)
include(CMake/cotire.cmake)
include(CMake/CheckHash.cmake)
include(CMake/Autodownload.cmake)
include(CMake/ConfigureCrossCompile.cmake)
# First, define all the compilation options.
# We default to debugging mode for developers.
@@ -24,15 +26,29 @@ set(ENSMALLEN_VERSION "2.10.0")
set(BOOST_VERSION "1.58")
set(CEREAL_VERSION "1.1.2")
# If BUILD_SHARED_LIBS is OFF then the mlpack library will be built statically.
# In addition, all mlpack CLI bindings will be linked statically as well.
if (WIN32)
option(BUILD_SHARED_LIBS
"Compile shared libraries (if OFF, static libraries are compiled)." OFF)
"Compile shared libraries (if OFF, static libraries and binaries are compiled)." OFF)
set(DLL_COPY_DIRS "" CACHE STRING "List of directories (separated by ';') containing DLLs to copy for runtime.")
set(DLL_COPY_LIBS "" CACHE STRING "List of DLLs (separated by ';') that should be copied for runtime.")
else ()
elseif(CMAKE_CROSSCOMPILING)
option(BUILD_SHARED_LIBS
"Compile shared libraries (if OFF, static libraries are compiled)." ON)
"Compile shared libraries (if OFF, static libraries and binaries are compiled)." OFF)
else()
option(BUILD_SHARED_LIBS
"Compile shared libraries (if OFF, static libraries and binaries are compiled)." ON)
endif()
# Support preference of static libs by adjusting CMAKE_FIND_LIBRARY_SUFFIXES.
if (NOT BUILD_SHARED_LIBS)
if(WIN32)
list(INSERT CMAKE_FIND_LIBRARY_SUFFIXES 0 .lib .a)
else()
set(CMAKE_FIND_LIBRARY_SUFFIXES .a)
endif()
endif()
# Detect whether the user passed BUILD_PYTHON_BINDINGS in order to determine if
@@ -93,12 +109,6 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
# Include modules in the CMake directory.
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/CMake")
# Disable any downloads if needed.
if (DISABLE_DOWNLOADS)
set(DOWNLOAD_ENSMALLEN OFF)
set(DOWNLOAD_STB_IMAGE OFF)
endif ()
# If we are on a Unix-like system, use the GNU install directories module.
# Otherwise set the values manually.
if (UNIX)
@@ -112,12 +122,12 @@ else ()
endif ()
# This is as of yet unused.
#option(PGO "Use profile-guided optimization if not a debug build" ON)
# option(PGO "Use profile-guided optimization if not a debug build" ON)
# Set the CFLAGS and CXXFLAGS depending on the options the user specified.
# Only GCC-like compilers support -Wextra, and other compilers give tons of
# output for -Wall, so only -Wall and -Wextra on GCC.
if(CMAKE_COMPILER_IS_GNUCC OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
if (CMAKE_COMPILER_IS_GNUCC OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
# Ensure that we can't compile with clang 3.4, since this causes strange
# issues.
if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.5)
@@ -144,7 +154,7 @@ endif ()
# If we are using MINGW, we need sections and big-obj, otherwise we create too
# many sections.
if(CMAKE_COMPILER_IS_GNUCC AND WIN32)
if (CMAKE_COMPILER_IS_GNUCC AND WIN32)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ffunction-sections -fdata-sections -Wa,-mbig-obj")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ffunction-sections -fdata-sections -Wa,-mbig-obj")
endif()
@@ -153,7 +163,7 @@ endif()
# OS (at least on some systems). Further, gcc sometimes optimizes calls to
# math.h functions, making -lm unnecessary with gcc, but it may still be
# necessary with clang.
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
if (APPLE)
# Detect OS X version. Use '/usr/bin/sw_vers -productVersion' to
# extract V from '10.V.x'.
@@ -166,7 +176,7 @@ if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
# OSX Lion (10.7) and OS X Mountain Lion (10.8) doesn't automatically
# select the right stdlib.
if(${MACOSX_VERSION} LESS 9)
if (${MACOSX_VERSION} LESS 9)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -stdlib=libc++")
set(CMAKE_SHARED_LINKER_FLAGS
"${CMAKE_SHARED_LINKER_FLAGS} -stdlib=libc++")
@@ -187,14 +197,14 @@ endif()
# If we're using gcc, then we need to link against pthreads to use std::thread,
# which we do in the tests.
if(CMAKE_COMPILER_IS_GNUCC)
if (CMAKE_COMPILER_IS_GNUCC)
find_package(Threads)
set(COMPILER_SUPPORT_LIBRARIES ${COMPILER_SUPPORT_LIBRARIES}
${CMAKE_THREAD_LIBS_INIT})
endif()
# Debugging CFLAGS. Turn optimizations off; turn debugging symbols on.
if(DEBUG)
if (DEBUG)
if (NOT MSVC)
add_definitions(-DDEBUG)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -O0 -ftemplate-backtrace-limit=0")
@@ -203,10 +213,10 @@ if(DEBUG)
# mlpack uses it's own mlpack::backtrace class based on Binary File Descriptor
# <bfd.h> and linux Dynamic Loader <libdl.h> and more portable version in future
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
find_package(Bfd)
find_package(LibDL)
if(LIBBFD_FOUND AND LIBDL_FOUND)
if (LIBBFD_FOUND AND LIBDL_FOUND)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -rdynamic")
set(MLPACK_INCLUDE_DIRS ${MLPACK_INCLUDE_DIRS} ${LIBBFD_INCLUDE_DIRS}
${LIBDL_INCLUDE_DIRS})
@@ -230,19 +240,19 @@ else()
endif()
# Profiling CFLAGS. Turn profiling information on.
if(CMAKE_COMPILER_IS_GNUCC AND PROFILE)
if (CMAKE_COMPILER_IS_GNUCC AND PROFILE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pg")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pg")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pg")
endif()
# If the user asked for running test cases with verbose output, turn that on.
if(TEST_VERBOSE)
if (TEST_VERBOSE)
add_definitions(-DTEST_VERBOSE)
endif()
# If the user asked for extra Armadillo debugging output, turn that on.
if(ARMA_EXTRA_DEBUG)
if (ARMA_EXTRA_DEBUG)
add_definitions(-DARMA_EXTRA_DEBUG)
endif()
@@ -254,131 +264,73 @@ endif()
# ARMADILLO_INCLUDE_DIRS - directories necessary for Armadillo includes
# BOOST_ROOT - root of Boost installation
# BOOST_INCLUDEDIR - include directory for Boost
# CEREAL_INCLUDE_DIR - include directory for cereal
# ENSMALLEN_INCLUDE_DIR - include directory for ensmallen
# STB_IMAGE_INCLUDE_DIR - include directory for STB image library
# MATHJAX_ROOT - root of MathJax installation
find_package(Armadillo "${ARMADILLO_VERSION}" REQUIRED)
# Download and compile OpenBLAS if we are cross compiling mlpack for a specific
# architecture. The function takes the version of OpenBLAS as variable.
if (CMAKE_CROSSCOMPILING)
search_openblas(0.3.13)
endif()
if (DISABLE_DOWNLOADS)
find_package(Armadillo "${ARMADILLO_VERSION}" REQUIRED)
else()
find_package(Armadillo "${ARMADILLO_VERSION}")
if (NOT ARMADILLO_FOUND)
get_deps(http://files.mlpack.org/armadillo-10.3.0.tar.gz armadillo armadillo-10.3.0.tar.gz)
set(ARMADILLO_INCLUDE_DIR ${GENERIC_INCLUDE_DIR})
find_package(Armadillo REQUIRED)
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})
# Find stb_image.h and stb_image_write.h.
find_package(StbImage)
# Download stb_image for image loading.
if (NOT STB_IMAGE_FOUND)
if (DOWNLOAD_STB_IMAGE)
set(STB_DIR "stb")
install(DIRECTORY DESTINATION "${CMAKE_BINARY_DIR}/deps/${STB_DIR}")
file(DOWNLOAD http://mlpack.org/files/stb-2.22/stb_image.h
"${CMAKE_BINARY_DIR}/deps/${STB_DIR}/stb_image.h"
STATUS STB_IMAGE_DOWNLOAD_STATUS_LIST LOG STB_IMAGE_DOWNLOAD_LOG
SHOW_PROGRESS)
list(GET STB_IMAGE_DOWNLOAD_STATUS_LIST 0 STB_IMAGE_DOWNLOAD_STATUS)
file(DOWNLOAD http://mlpack.org/files/stb-1.13/stb_image_write.h
"${CMAKE_BINARY_DIR}/deps/${STB_DIR}/stb_image_write.h"
STATUS STB_IMAGE_WRITE_DOWNLOAD_STATUS_LIST
LOG STB_IMAGE_WRITE_DOWNLOAD_LOG
SHOW_PROGRESS)
list(GET STB_IMAGE_WRITE_DOWNLOAD_STATUS_LIST 0
STB_IMAGE_WRITE_DOWNLOAD_STATUS)
if (STB_IMAGE_DOWNLOAD_STATUS EQUAL 0 AND
STB_IMAGE_WRITE_DOWNLOAD_STATUS EQUAL 0)
check_hash (http://mlpack.org/files/stb/hash.md5 "${CMAKE_BINARY_DIR}/deps/${STB_DIR}"
HASH_CHECK_FAIL)
if (HASH_CHECK_FAIL EQUAL 0)
set(MLPACK_INCLUDE_DIRS ${MLPACK_INCLUDE_DIRS}
"${CMAKE_BINARY_DIR}/deps/${STB_DIR}/")
message(STATUS
"Successfully downloaded stb into ${CMAKE_BINARY_DIR}/deps/${STB_DIR}/")
# Now we have to also ensure these header files get installed.
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!")
endif ()
else ()
file(REMOVE_RECURSE "${CMAKE_BINARY_DIR}/deps/${STB_DIR}/")
list(GET STB_IMAGE_DOWNLOAD_STATUS_LIST 1 STB_DOWNLOAD_ERROR)
message(WARNING
"Could not download stb! Error code ${STB_DOWNLOAD_STATUS}: ${STB_DOWNLOAD_ERROR}! Error log: ${STB_DOWNLOAD_LOG}")
message(WARNING
"stb/stb_image.h is not installed. Image utilities will not be available!")
endif ()
else ()
message(WARNING
"stb/stb_image.h is not installed. Image utilities will not be available!")
endif ()
else ()
# Already has STB installed.
if (DISABLE_DOWNLOADS)
find_package(StbImage)
else()
find_package(StbImage)
if (NOT STB_IMAGE_FOUND)
get_deps(http://mlpack.org/files/stb.tar.gz stb stb.tar.gz)
set(STB_IMAGE_INCLUDE_DIR ${GENERIC_INCLUDE_DIR})
find_package(StbImage REQUIRED)
endif()
endif()
if (STB_IMAGE_FOUND)
add_definitions(-DHAS_STB)
set(MLPACK_INCLUDE_DIRS ${MLPACK_INCLUDE_DIRS} ${STB_IMAGE_INCLUDE_DIR})
set(STB_AVAILABLE "1")
endif ()
endif()
set(MLPACK_INCLUDE_DIRS ${MLPACK_INCLUDE_DIRS} "${STB_IMAGE_INCLUDE_DIR}")
# Find ensmallen.
# Once ensmallen is readily available in package repos, the automatic downloader
# here can be removed.
find_package(Ensmallen "${ENSMALLEN_VERSION}")
if (NOT ENSMALLEN_FOUND)
if (DOWNLOAD_ENSMALLEN)
file(DOWNLOAD http://www.ensmallen.org/files/ensmallen-latest.tar.gz
"${CMAKE_BINARY_DIR}/deps/ensmallen-latest.tar.gz"
STATUS ENS_DOWNLOAD_STATUS_LIST LOG ENS_DOWNLOAD_LOG
SHOW_PROGRESS)
list(GET ENS_DOWNLOAD_STATUS_LIST 0 ENS_DOWNLOAD_STATUS)
if (ENS_DOWNLOAD_STATUS EQUAL 0)
execute_process(COMMAND ${CMAKE_COMMAND} -E
tar xzf "${CMAKE_BINARY_DIR}/deps/ensmallen-latest.tar.gz"
WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/deps/")
if (DISABLE_DOWNLOADS)
find_package(Ensmallen "${ENSMALLEN_VERSION}" REQUIRED)
else()
find_package(Ensmallen "${ENSMALLEN_VERSION}")
if (NOT ENSMALLEN_FOUND)
get_deps(http://www.ensmallen.org/files/ensmallen-latest.tar.gz ensmallen ensmallen-latest.tar.gz)
set(ENSMALLEN_INCLUDE_DIR ${GENERIC_INCLUDE_DIR})
find_package(Ensmallen REQUIRED)
endif()
endif()
set(MLPACK_INCLUDE_DIRS ${MLPACK_INCLUDE_DIRS} "${ENSMALLEN_INCLUDE_DIR}")
# 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) 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)
set(MLPACK_INCLUDE_DIRS ${MLPACK_INCLUDE_DIRS}
"${CMAKE_BINARY_DIR}/deps/${ENSMALLEN_INCLUDE_DIR}/include")
message(STATUS
"Successfully downloaded ensmallen into ${CMAKE_BINARY_DIR}/deps/${ENSMALLEN_INCLUDE_DIR}/")
# Now we have to also ensure these header files get installed.
install(DIRECTORY "${CMAKE_BINARY_DIR}/deps/${ENSMALLEN_INCLUDE_DIR}/include/ensmallen_bits/" DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/ensmallen_bits")
install(FILES "${CMAKE_BINARY_DIR}/deps/${ENSMALLEN_INCLUDE_DIR}/include/ensmallen.hpp" DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}")
else ()
message(FATAL_ERROR "Problem unpacking ensmallen! Expected only one directory ensmallen-x.y.z/; found ${ENS_DIRECTORIES}. Try removing the directory ${CMAKE_BINARY_DIR}/deps and reconfiguring.")
endif ()
else ()
list(GET ENS_DOWNLOAD_STATUS_LIST 1 ENS_DOWNLOAD_ERROR)
message(FATAL_ERROR
"Could not download ensmallen! Error code ${ENS_DOWNLOAD_STATUS}: ${ENS_DOWNLOAD_ERROR}! Error log: ${ENS_DOWNLOAD_LOG}")
endif ()
else ()
# Release versions will have ensmallen packaged with the release so we can
# just reference that.
if (EXISTS "${CMAKE_SOURCE_DIR}/src/mlpack/core/optimizers/ensmallen/ensmallen.hpp")
set(MLPACK_INCLUDE_DIRS ${MLPACK_INCLUDE_DIRS} ${ARMADILLO_INCLUDE_DIRS}
"${CMAKE_SOURCE_DIR}/src/mlpack/core/optimizers/ensmallen")
else ()
message(FATAL_ERROR
"Cannot find ensmallen headers! Try setting ENSMALLEN_INCLUDE_DIR!")
endif ()
endif ()
else ()
set(MLPACK_INCLUDE_DIRS ${MLPACK_INCLUDE_DIRS} "${ENSMALLEN_INCLUDE_DIR}")
endif ()
find_package(cereal "${CEREAL_VERSION}" REQUIRED)
# Find cereal.
if (DISABLE_DOWNLOADS)
find_package(cereal "${CEREAL_VERSION}" REQUIRED)
else()
find_package(cereal "${CEREAL_VERSION}")
if (NOT CEREAL_FOUND)
get_deps(https://github.com/USCiLab/cereal/archive/refs/tags/v1.3.0.tar.gz cereal cereal-1.3.0.tar.gz)
set(CEREAL_INCLUDE_DIR ${GENERIC_INCLUDE_DIR})
find_package(cereal REQUIRED)
endif()
endif()
set(MLPACK_INCLUDE_DIRS ${MLPACK_INCLUDE_DIRS} ${CEREAL_INCLUDE_DIR})
# Unfortunately this configuration variable is necessary and will need to be
@@ -409,8 +361,15 @@ set(Boost_ADDITIONAL_VERSIONS
# 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 "${BOOST_VERSION}")
if (DISABLE_DOWNLOADS)
find_package(Boost "${BOOST_VERSION}" REQUIRED)
else()
find_package(Boost "${BOOST_VERSION}")
if (NOT Boost_FOUND)
get_deps(https://boostorg.jfrog.io/artifactory/main/release/1.76.0/source/boost_1_76_0.tar.gz boost boost_1_76_0.tar.gz)
find_package(Boost REQUIRED)
endif()
endif()
set(MLPACK_INCLUDE_DIRS ${MLPACK_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS})
set(MLPACK_LIBRARIES ${MLPACK_LIBRARIES})
set(MLPACK_LIBRARY_DIRS ${MLPACK_LIBRARY_DIRS})
@@ -433,7 +392,7 @@ if (OPENMP_FOUND)
add_definitions(-DHAS_OPENMP)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
if(OpenMP_CXX_FOUND)
if (OpenMP_CXX_FOUND)
set(MLPACK_LIBRARIES ${MLPACK_LIBRARIES} ${OpenMP_CXX_LIBRARIES})
endif ()
else ()
+1
View File
@@ -143,6 +143,7 @@ Copyright:
Copyright 2020, Anmolpreet Singh <anmol323c@gmail.com>
Copyright 2021, Tru Hoang <trugiahoang@gmail.com>
Copyright 2021, Mark Fischinger <markfischinger@gmail.com>
Copyright 2021, Muhammad Fawwaz Mayda <maydafawwaz@gmail.com>
License: BSD-3-clause
All rights reserved.
+5
View File
@@ -3,6 +3,8 @@
* Added Extra Trees Algorithm (#2883). Currently, it can be used using the
* class `mlpack::tree::ExtraTrees`, but only through C++.
* Add Flatten T Swish activation function (`flatten-t-swish.hpp`)
* Added warm start feature to Random Forest (#2881); this feature is
accessible from mlpack's bindings to different languages.
@@ -49,6 +51,9 @@
* Fix Python binding build when the CMake variable `USE_OPENMP` is set to
`OFF` (#2884).
* The `mlpack_test` target is no longer built as part of `make all`. Use
`make mlpack_test` to build the tests.
### mlpack 3.4.2
###### 2020-10-26
* Added Mean Absolute Percentage Error.
+17 -3
View File
@@ -211,8 +211,8 @@ Options are specified with the -D flag. The allowed options include:
BUILD_R_BINDINGS=(ON/OFF): whether or not to build R bindings
R_EXECUTABLE=(/path/to/R): Path to specific R executable
BUILD_TESTS=(ON/OFF): whether or not to build tests
BUILD_SHARED_LIBS=(ON/OFF): compile shared libraries as opposed to
static libraries
BUILD_SHARED_LIBS=(ON/OFF): compile shared libraries and executables as
opposed to static libraries
DISABLE_DOWNLOADS=(ON/OFF): whether to disable all downloads during build
DOWNLOAD_ENSMALLEN=(ON/OFF): If ensmallen is not found, download it
ENSMALLEN_INCLUDE_DIR=(/path/to/ensmallen/include): path to include directory
@@ -224,6 +224,11 @@ Options are specified with the -D flag. The allowed options include:
BUILD_DOCS=(ON/OFF): build Doxygen documentation, if Doxygen is available
(default ON)
For example, to build mlpack library and CLI bindings statically the following
command can be used:
$ cmake -D BUILD_SHARED_LIBS=OFF ../
Other tools can also be used to configure CMake, but those are not documented
here. See [this section of the build guide](https://www.mlpack.org/doc/mlpack-git/doxygen/build.html#build_config)
for more details, including a full list of options, and their default values.
@@ -234,7 +239,7 @@ also be built. OpenMP will be used for parallelization when possible by
default.
Once CMake is configured, building the library is as simple as typing 'make'.
This will build all library components as well as 'mlpack_test'.
This will build all library components and bindings.
$ make
@@ -243,6 +248,12 @@ of the build can be specified:
$ make mlpack_pca mlpack_knn mlpack_kfn
If you want to build the tests, just make the `mlpack_test` target, and use
`ctest` to run the tests:
$ make mlpack_test
$ ctest .
If the build fails and you cannot figure out why, register an account on Github
and submit an issue. The mlpack developers will quickly help you figure it out:
@@ -355,6 +366,9 @@ older versions of mlpack:
- [Development Site (Github)](https://www.github.com/mlpack/mlpack/)
- [API documentation (Doxygen)](https://www.mlpack.org/doc/mlpack-git/doxygen/index.html)
To learn about the development goals of mlpack in the short- and medium-term
future, see the [vision document](https://www.mlpack.org/papers/vision.pdf).
### 8. Bug reporting
(see also [mlpack help](https://www.mlpack.org/questions.html))
+40
View File
@@ -0,0 +1,40 @@
## This file handles cross-compilation configurations for aarch64,
## known as arm64. The objective of this file is to find and assign
## cross-compiler and the entire toolchain.
##
## This configuration works best with the buildroot toolchain. When using this
## file, be sure to set the TOOLCHAIN_PREFIX and CMAKE_SYSROOT variables,
## preferably via the CMake configuration command (e.g. `-DCMAKE_SYSROOT=<...>`).
##
## Currently, we recommend using buildroot toolchain for
## cross-compilation. Here is the link to download the toolchains:
## https://toolchains.bootlin.com/
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSROOT)
set(TOOLCHAIN_PREFIX "" CACHE STRING "Path for toolchain for cross compiler and other compilation tools.")
# Ensure that CMake tries to build static libraries when testing the compiler.
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
set(CMAKE_AR "${TOOLCHAIN_PREFIX}gcc-ar" CACHE FILEPATH "" FORCE)
set(CMAKE_C_COMPILER ${TOOLCHAIN_PREFIX}gcc)
set(CMAKE_CXX_COMPILER ${TOOLCHAIN_PREFIX}g++)
set(CMAKE_LINKER ${TOOLCHAIN_PREFIX}ld)
set(CMAKE_C_ARCHIVE_CREATE "<CMAKE_AR> qcs <TARGET> <LINK_FLAGS> <OBJECTS>")
set(CMAKE_C_ARCHIVE_FINISH true)
set(CMAKE_FORTRAN_COMPILER ${TOOLCHAIN_PREFIX}gfortran)
set(CMAKE_ASM_COMPILER ${CMAKE_C_COMPILER})
set(CMAKE_OBJCOPY ${TOOLCHAIN_PREFIX}objcopy CACHE INTERNAL "objcopy tool")
set(CMAKE_SIZE_UTIL ${TOOLCHAIN_PREFIX}size CACHE INTERNAL "size tool")
## Here are the standard ROOT_PATH if you are using the standard toolchain
## if you are using a different toolchain you have to specify that too.
set(CMAKE_FIND_ROOT_PATH "${CMAKE_SYSROOT}")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --sysroot=${CMAKE_SYSROOT}" CACHE INTERNAL "" FORCE)
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
+69
View File
@@ -0,0 +1,69 @@
# This function provides a set of specific flags for each supported board
# depending on the processor type. The objective is to optimize for size.
# Thus, all of the following flags are chosen carefully to reduce binary
# footprints.
# Set generic minimization flags for all platforms.
# These flags are the same for all cross-compilation cases.
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Os -fdata-sections -ffunction-sections")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fomit-frame-pointer -fno-unwind-tables")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-asynchronous-unwind-tables -fvisibility=hidden")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fshort-enums -finline-small-functions")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -findirect-inlining -fno-common")
#-flto -fuse-ld=gold # There is an issue with gold link when compiling on
# Ubuntu 16. At that point gcc linker did not integrate the flto support
# inside and it was a separate plugin that need to be added. Therefore,
# this can be added when mlpack Azure CI moves toward Ubuntu 20.
set(BOARD_NAME "" CACHE STRING "Specify Board name to optimize for.")
string(TOUPPER ${BOARD_NAME} BOARD)
# Set specific platforms CMAKE CXX flags.
if(BOARD MATCHES "RPI0" OR BOARD MATCHES "RPI1")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mtune=arm1176jzf-s")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections")
set(OPENBLAS_TARGET "ARMV6")
set(OPENBLAS_BINARY "32")
elseif(BOARD MATCHES "RPI2")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mtune=cortex-a7")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections")
set(OPENBLAS_TARGET "ARMV7")
set(OPENBLAS_BINARY "32")
elseif(BOARD MATCHES "RPI3")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mtune=cortex-a53")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections")
set(OPENBLAS_TARGET "CORTEXA53")
set(OPENBLAS_BINARY "64")
elseif(BOARD MATCHES "RPI4")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mtune=cortex-a72")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections")
set(OPENBLAS_TARGET "CORTEXA72")
set(OPENBLAS_BINARY "64")
elseif(BOARD MATCHES "BV")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections")
set(OPENBLAS_TARGET "RISCV64_GENERIC")
set(OPENBLAS_BINARY "64")
elseif(BOARD MATCHES "JETSONAGX")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -matune=cortex-a76")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections")
set(OPENBLAS_TARGET "ARM8")
set(OPENBLAS_BINARY "64")
elseif(BOARD MATCHES "KATAMI")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=pentium3")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections")
set(OPENBLAS_TARGET "KATAMI")
set(OPENBLAS_BINARY "32")
elseif(BOARD MATCHES "COPPERMINE")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=pentium3")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections")
set(OPENBLAS_TARGET "COPPERMINE")
set(OPENBLAS_BINARY "32")
elseif(BOARD MATCHES "NORTHWOOD")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=pentium4")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections")
set(OPENBLAS_TARGET "NORTHWOOD")
set(OPENBLAS_BINARY "32")
elseif(BOARD)
## TODO: update documentation with a list of the supported boards.
message(FATAL_ERROR "Given BOARD_NAME is not known; please choose a supported board from the list")
endif()
+26 -12
View File
@@ -170,7 +170,8 @@ The full list of options mlpack allows:
- PROFILE=(ON/OFF): compile with profiling symbols (default OFF)
- ARMA_EXTRA_DEBUG=(ON/OFF): compile with extra Armadillo debugging symbols
(default OFF)
- BUILD_TESTS=(ON/OFF): compile the \c mlpack_test program (default ON)
- BUILD_TESTS=(ON/OFF): compile the \c mlpack_test program when `make` is run
(default ON)
- BUILD_CLI_EXECUTABLES=(ON/OFF): compile the mlpack command-line executables
(i.e. \c mlpack_knn, \c mlpack_kfn, \c mlpack_logistic_regression, etc.)
(default ON)
@@ -182,7 +183,7 @@ The full list of options mlpack allows:
and Gonum exist. (default OFF)
- BUILD_JULIA_BINDINGS=(ON/OFF): compile Julia bindings, if Julia is found
(default OFF)
- BUILD_SHARED_LIBS=(ON/OFF): compile shared libraries as opposed to
- BUILD_SHARED_LIBS=(ON/OFF): compile shared libraries and executables as opposed to
static libraries (default ON)
- TEST_VERBOSE=(ON/OFF): run test cases in \c mlpack_test with verbose output
(default OFF)
@@ -209,6 +210,14 @@ The full list of options mlpack allows:
Each option can be specified to CMake with the '-D' flag. Other tools can also
be used to configure CMake, but those are not documented here.
For example, if you would like to build mlpack and its CLI bindings statically, then
you need to execute the following commands:
@code
$ cd build
$ cmake -D BUILD_SHARED_LIBS=OFF ../
@endcode
In addition, the following directories may be specified, to find include files
and libraries. These also use the '-D' flag.
@@ -216,23 +225,21 @@ and libraries. These also use the '-D' flag.
- ARMADILLO_LIBRARY=(/path/to/armadillo/libarmadillo.so): location of Armadillo
library
- BOOST_ROOT=(/path/to/boost/): path to root of boost installation
- CEREAL_INCLUDE_DIR=(/path/to/cereal/include): path to include directory for
cereal
- ENSMALLEN_INCLUDE_DIR=(/path/to/ensmallen/include): path to include directory
for ensmallen
- STB_IMAGE_INCLUDE_DIR=(/path/to/stb/include): path to include directory for
STB image library
STB image library
- MATHJAX_ROOT=(/path/to/mathjax): path to root of MathJax installation
@section build_build Building mlpack
Once CMake is configured, building the library is as simple as typing 'make'.
This will build all library components as well as 'mlpack_test'.
This will build all library components.
@code
$ make
Scanning dependencies of target mlpack
[ 1%] Building CXX object
src/mlpack/CMakeFiles/mlpack.dir/core/optimizers/aug_lagrangian/aug_lagrangian_test_functions.cpp.o
<...>
@endcode
It's often useful to specify \c -jN to the \c make command, which will build on
@@ -247,17 +254,24 @@ $ make mlpack_pca mlpack_knn mlpack_kfn
@endcode
One particular component of interest is mlpack_test, which runs the mlpack test
suite. You can build this component with
suite. This is not built when @c make is run. You can build this component
with
@code
$ make mlpack_test
@endcode
We use <a href="https://github.com/catchorg/Catch2">Catch2</a> to write our tests.
To run all tests, you can simply run:
To run all tests, you can simply use CTest:
@code
$ ./bin/mlpack_test
$ ctest .
@endcode
Or, you can run the test suite manually:
@code
$ bin/mlpack_test
@endcode
To run all tests in a particular file you can run:
@@ -266,7 +280,7 @@ To run all tests in a particular file you can run:
$ ./bin/mlpack_test "[testname]"
@endcode
where testname is the name of the test suite.
where testname is the name of the test suite.
For example to run all collaborative filtering tests implemented in cf_test.cpp you can run:
@code
+15 -5
View File
@@ -50,11 +50,21 @@ if (BUILD_CLI_EXECUTABLES)
add_executable(mlpack_${name}
${name}_main.cpp
)
target_link_libraries(mlpack_${name}
mlpack
${ARMADILLO_LIBRARIES}
${COMPILER_SUPPORT_LIBRARIES}
)
# Build mlpack CLI binding binaries statically.
if(NOT BUILD_SHARED_LIBS)
target_link_libraries(mlpack_${name} -static
mlpack
${ARMADILLO_LIBRARIES}
${COMPILER_SUPPORT_LIBRARIES}
)
else()
# Build mlpack CLI binding binaries dynamically.
target_link_libraries(mlpack_${name}
mlpack
${ARMADILLO_LIBRARIES}
${COMPILER_SUPPORT_LIBRARIES}
)
endif()
# Make sure that we set BINDING_TYPE to cli so the command-line program is
# compiled with the correct int main() call.
set_target_properties(mlpack_${name} PROPERTIES COMPILE_FLAGS
@@ -432,13 +432,6 @@ inline std::string ProgramCall(const std::string& programName)
std::ostringstream ossOptions;
ossOptions << "param := mlpack." << goProgramName << "Options()\n";
oss << util::HyphenateString(ossOptions.str(), 4);
std::vector<std::string> outputOptions;
for (auto it = parameters.begin(); it != parameters.end(); ++it)
{
util::ParamData& d = it->second;
if (!d.input)
outputOptions.push_back(it->first);
}
std::string result = oss.str();
oss.str("");
std::ostringstream ossInputs;
@@ -58,7 +58,6 @@ double EpanechnikovKernel::ConvolutionIntegral(const VecTypeA& a,
(3.0 * bandwidth) + 2.0 * distance * distance * distance /
(3.0 * bandwidth * bandwidth) -
std::pow(distance, 5.0) / (30.0 * std::pow(bandwidth, 4.0)));
break;
case 2:
return 1.0 / volumeSquared *
((2.0 / 3.0 * bandwidth * bandwidth - distance * distance) *
@@ -67,12 +66,10 @@ double EpanechnikovKernel::ConvolutionIntegral(const VecTypeA& a,
(distance / 6.0 + 2.0 / 9.0 * distance *
std::pow(distance / bandwidth, 2.0) - distance / 72.0 *
std::pow(distance / bandwidth, 4.0)));
break;
default:
Log::Fatal << "EpanechnikovKernel::ConvolutionIntegral(): dimension "
<< a.n_rows << " not supported.";
return -1.0; // This line will not execute.
break;
}
}
+1 -4
View File
@@ -56,7 +56,7 @@ class SphericalKernel
* @tparam VecTypeB Type of second vector.
* @param a First vector.
* @param b Second vector.
* @return the convolution integral value.
* @return The convolution integral value.
*/
template<typename VecTypeA, typename VecTypeB>
double ConvolutionIntegral(const VecTypeA& a, const VecTypeB& b) const
@@ -72,17 +72,14 @@ class SphericalKernel
{
case 1:
return 1.0 / volumeSquared * (2.0 * bandwidth - distance);
break;
case 2:
return 1.0 / volumeSquared *
(2.0 * bandwidth * bandwidth * acos(distance/(2.0 * bandwidth)) -
distance / 4.0 * sqrt(4.0*bandwidth*bandwidth-distance*distance));
break;
default:
Log::Fatal << "The spherical kernel does not support convolution\
integrals above dimension two, yet..." << std::endl;
return -1.0;
break;
}
}
double Normalizer(size_t dimension) const
+4 -1
View File
@@ -178,7 +178,10 @@ ElemType BLEU<ElemType, PrecisionType>::Evaluate(
else
geometricMean = 0.0;
ratio = ElemType(translationLength) / referenceLength;
ratio = ElemType(translationLength);
if (referenceLength > 0)
ratio /= referenceLength;
brevityPenalty = (ratio > 1.0) ? 1.0 : std::exp(1.0 - 1.0 / ratio);
bleuScore = geometricMean * brevityPenalty;
@@ -86,20 +86,23 @@ class CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::
/**
* Helper function for traversal of the two trees.
*/
void Traverse(CoverTree& queryNode,
std::map<int, std::vector<DualCoverTreeMapEntry> >&
referenceMap);
void Traverse(
CoverTree& queryNode,
std::map<int, std::vector<DualCoverTreeMapEntry>,
std::greater<int>>& referenceMap);
//! Prepare map for recursion.
void PruneMap(CoverTree& queryNode,
std::map<int, std::vector<DualCoverTreeMapEntry> >&
referenceMap,
std::map<int, std::vector<DualCoverTreeMapEntry> >&
childMap);
void PruneMap(
CoverTree& queryNode,
std::map<int, std::vector<DualCoverTreeMapEntry>,
std::greater<int>>& referenceMap,
std::map<int, std::vector<DualCoverTreeMapEntry>,
std::greater<int>>& childMap);
void ReferenceRecursion(CoverTree& queryNode,
std::map<int, std::vector<DualCoverTreeMapEntry> >&
referenceMap);
void ReferenceRecursion(
CoverTree& queryNode,
std::map<int, std::vector<DualCoverTreeMapEntry>,
std::greater<int>>& referenceMap);
};
} // namespace tree
@@ -43,7 +43,7 @@ DualTreeTraverser<RuleType>::Traverse(CoverTree& queryNode,
CoverTree& referenceNode)
{
// Start by creating a map and adding the reference root node to it.
std::map<int, std::vector<DualCoverTreeMapEntry> > refMap;
std::map<int, std::vector<DualCoverTreeMapEntry>, std::greater<int>> refMap;
DualCoverTreeMapEntry rootRefEntry;
@@ -70,7 +70,8 @@ template<typename RuleType>
void CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::
DualTreeTraverser<RuleType>::Traverse(
CoverTree& queryNode,
std::map<int, std::vector<DualCoverTreeMapEntry> >& referenceMap)
std::map<int, std::vector<DualCoverTreeMapEntry>, std::greater<int>>&
referenceMap)
{
if (referenceMap.size() == 0)
return; // Nothing to do!
@@ -85,7 +86,7 @@ DualTreeTraverser<RuleType>::Traverse(
// Now, reduce the scale of the query node by recursing. But we can't recurse
// if the query node is a leaf node.
if ((queryNode.Scale() != INT_MIN) &&
(queryNode.Scale() >= (*referenceMap.rbegin()).first))
(queryNode.Scale() >= (*referenceMap.begin()).first))
{
// Recurse into the non-self-children first. The recursion order cannot
// affect the runtime of the algorithm, because each query child recursion's
@@ -95,11 +96,15 @@ DualTreeTraverser<RuleType>::Traverse(
for (size_t i = 1; i < queryNode.NumChildren(); ++i)
{
// We need a copy of the map for this child.
std::map<int, std::vector<DualCoverTreeMapEntry> > childMap;
std::map<int, std::vector<DualCoverTreeMapEntry>, std::greater<int>>
childMap;
PruneMap(queryNode.Child(i), referenceMap, childMap);
Traverse(queryNode.Child(i), childMap);
}
std::map<int, std::vector<DualCoverTreeMapEntry> > selfChildMap;
std::map<int, std::vector<DualCoverTreeMapEntry>, std::greater<int>>
selfChildMap;
PruneMap(queryNode.Child(0), referenceMap, selfChildMap);
Traverse(queryNode.Child(0), selfChildMap);
}
@@ -111,8 +116,7 @@ DualTreeTraverser<RuleType>::Traverse(
// evaluations to do.
Log::Assert((*referenceMap.begin()).first == INT_MIN);
Log::Assert(queryNode.Scale() == INT_MIN);
std::vector<DualCoverTreeMapEntry>& pointVector =
(*referenceMap.begin()).second;
std::vector<DualCoverTreeMapEntry>& pointVector = referenceMap[INT_MIN];
for (size_t i = 0; i < pointVector.size(); ++i)
{
@@ -156,25 +160,25 @@ template<typename RuleType>
void CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::
DualTreeTraverser<RuleType>::PruneMap(
CoverTree& queryNode,
std::map<int, std::vector<DualCoverTreeMapEntry> >& referenceMap,
std::map<int, std::vector<DualCoverTreeMapEntry> >& childMap)
std::map<int, std::vector<DualCoverTreeMapEntry>, std::greater<int>>&
referenceMap,
std::map<int, std::vector<DualCoverTreeMapEntry>, std::greater<int>>&
childMap)
{
if (referenceMap.empty())
return; // Nothing to do.
// Copy the zero set first.
if ((*referenceMap.begin()).first == INT_MIN)
if (referenceMap.count(INT_MIN) == 1)
{
// Get a reference to the vector representing the entries at this scale.
std::vector<DualCoverTreeMapEntry>& scaleVector =
(*referenceMap.begin()).second;
std::vector<DualCoverTreeMapEntry>& scaleVector = referenceMap[INT_MIN];
// Before traversing all the points in this scale, sort by score.
std::sort(scaleVector.begin(), scaleVector.end());
const int thisScale = (*referenceMap.begin()).first;
childMap[thisScale].reserve(scaleVector.size());
std::vector<DualCoverTreeMapEntry>& newScaleVector = childMap[thisScale];
childMap[INT_MIN].reserve(scaleVector.size());
std::vector<DualCoverTreeMapEntry>& newScaleVector = childMap[INT_MIN];
// Loop over each entry in the vector.
for (size_t j = 0; j < scaleVector.size(); ++j)
@@ -208,13 +212,13 @@ DualTreeTraverser<RuleType>::PruneMap(
// If we didn't add anything, then strike this vector from the map.
if (newScaleVector.size() == 0)
childMap.erase((*referenceMap.begin()).first);
childMap.erase(INT_MIN);
}
typename std::map<int, std::vector<DualCoverTreeMapEntry> >::reverse_iterator
it = referenceMap.rbegin();
typename std::map<int, std::vector<DualCoverTreeMapEntry>,
std::greater<int>>::iterator it = referenceMap.begin();
while ((it != referenceMap.rend()))
while ((it != referenceMap.end()))
{
const int thisScale = (*it).first;
if (thisScale == INT_MIN) // We already did it.
@@ -277,28 +281,26 @@ template<typename RuleType>
void CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::
DualTreeTraverser<RuleType>::ReferenceRecursion(
CoverTree& queryNode,
std::map<int, std::vector<DualCoverTreeMapEntry> >& referenceMap)
std::map<int, std::vector<DualCoverTreeMapEntry>, std::greater<int>>&
referenceMap)
{
// First, reduce the maximum scale in the reference map down to the scale of
// the query node.
while (!referenceMap.empty())
{
const int maxScale = ((*referenceMap.begin()).first);
// Hacky bullshit to imitate jl cover tree.
if (queryNode.Parent() == NULL && (*referenceMap.rbegin()).first <
queryNode.Scale())
if (queryNode.Parent() == NULL && maxScale < queryNode.Scale())
break;
if (queryNode.Parent() != NULL && (*referenceMap.rbegin()).first <=
queryNode.Scale())
if (queryNode.Parent() != NULL && maxScale <= queryNode.Scale())
break;
// If the query node's scale is INT_MIN and the reference map's maximum
// scale is INT_MIN, don't try to recurse...
if ((queryNode.Scale() == INT_MIN) &&
((*referenceMap.rbegin()).first == INT_MIN))
if (queryNode.Scale() == INT_MIN && maxScale == INT_MIN)
break;
// Get a reference to the current largest scale.
std::vector<DualCoverTreeMapEntry>& scaleVector =
(*referenceMap.rbegin()).second;
std::vector<DualCoverTreeMapEntry>& scaleVector = referenceMap[maxScale];
// Before traversing all the points in this scale, sort by score.
std::sort(scaleVector.begin(), scaleVector.end());
@@ -308,7 +310,6 @@ DualTreeTraverser<RuleType>::ReferenceRecursion(
{
// Get a reference to the current element.
const DualCoverTreeMapEntry& frame = scaleVector.at(i);
CoverTree* refNode = frame.referenceNode;
// Create the score for the children.
@@ -344,13 +345,12 @@ DualTreeTraverser<RuleType>::ReferenceRecursion(
newFrame.score = childScore; // Use the score of the parent.
newFrame.baseCase = baseCase;
newFrame.traversalInfo = rule.TraversalInfo();
referenceMap[newFrame.referenceNode->Scale()].push_back(newFrame);
}
}
// Now clear the memory for this scale; it isn't needed anymore.
referenceMap.erase((*referenceMap.rbegin()).first);
referenceMap.erase(maxScale);
}
}
@@ -80,9 +80,9 @@ SingleTreeTraverser<RuleType>::Traverse(
// and then the vector is all the nodes in that scale which need to be
// investigated. Because no point in a scale can add a point in its own
// scale, we know that the vector for each scale is final when we get to it.
// In addition, map is organized in such a way that rbegin() will return the
// largest scale.
std::map<int, std::vector<MapEntryType> > mapQueue;
// In addition, the map is organized in such a way that begin() will return
// the largest scale.
std::map<int, std::vector<MapEntryType>, std::greater<int>> mapQueue;
// Create the score for the children.
double rootChildScore = rule.Score(queryIndex, referenceNode);
@@ -123,14 +123,13 @@ SingleTreeTraverser<RuleType>::Traverse(
// Now begin the iteration through the map, but only if it has anything in it.
if (mapQueue.empty())
return;
typename std::map<int, std::vector<MapEntryType> >::reverse_iterator rit =
mapQueue.rbegin();
int maxScale = mapQueue.cbegin()->first;
// We will treat the leaves differently (below).
while ((*rit).first != INT_MIN)
while (maxScale != INT_MIN)
{
// Get a reference to the current scale.
std::vector<MapEntryType>& scaleVector = (*rit).second;
std::vector<MapEntryType>& scaleVector = mapQueue[maxScale];
// Before traversing all the points in this scale, sort by score.
std::sort(scaleVector.begin(), scaleVector.end());
@@ -170,7 +169,9 @@ SingleTreeTraverser<RuleType>::Traverse(
// trees using TreeTraits::FirstPointIsCentroid; this is an optimization
// that (theoretically) the compiler should get right.
if (point != parent)
{
baseCase = rule.BaseCase(queryIndex, point);
}
// Don't add the self-leaf.
size_t j = 0;
@@ -193,7 +194,8 @@ SingleTreeTraverser<RuleType>::Traverse(
}
// Now clear the memory for this scale; it isn't needed anymore.
mapQueue.erase((*rit).first);
mapQueue.erase(maxScale);
maxScale = mapQueue.begin()->first;
}
// Now deal with the leaves.
@@ -435,7 +435,8 @@ bool XTreeSplit::SplitNonLeafNode(TreeType *tree, std::vector<bool>& relevels)
bool useMinOverlapSplit = false;
if (tiedOnOverlap)
{
if (overlapBestAreaAxis / areaBestAreaAxis < MAX_OVERLAP)
if (areaBestAreaAxis > 0 &&
overlapBestAreaAxis / areaBestAreaAxis < MAX_OVERLAP)
{
tree->numDescendants = 0;
tree->bound.Clear();
@@ -79,7 +79,7 @@ class SimpleToleranceTermination
WH = W * H;
// compute residue
// Compute residue.
residueOld = residue;
size_t n = V->n_rows;
size_t m = V->n_cols;
@@ -99,48 +99,51 @@ class SimpleToleranceTermination
}
}
}
residue = sum / count;
residue = sum;
if (count > 0)
residue /= count;
residue = sqrt(residue);
// increment iteration count
// Increment iteration count.
iteration++;
Log::Info << "Iteration " << iteration << "; residue "
<< ((residueOld - residue) / residueOld) << ".\n";
// if residue tolerance is not satisfied
// If residue tolerance is not satisfied.
if ((residueOld - residue) / residueOld < tolerance && iteration > 4)
{
// check if this is a first of successive drops
// Check if this is a first of successive drops.
if (reverseStepCount == 0 && isCopy == false)
{
// store a copy of W and H matrix
// Store a copy of W and H matrix.
isCopy = true;
this->W = W;
this->H = H;
// store residue values
// Store residue values.
c_index = residue;
c_indexOld = residueOld;
}
// increase successive drop count
// Increase successive drop count.
reverseStepCount++;
}
// if tolerance is satisfied
// If tolerance is satisfied.
else
{
// initialize successive drop count
// Initialize successive drop count.
reverseStepCount = 0;
// if residue is droped below minimum scrap stored values
// If residue is droped below minimum scrap stored values.
if (residue <= c_indexOld && isCopy == true)
{
isCopy = false;
}
}
// check if termination criterion is met
// Check if termination criterion is met.
if (reverseStepCount == reverseStepTolerance || iteration > maxIterations)
{
// if stored values are present replace them with current value as they
// represent the minimum residue point
// If stored values are present replace them with current value as they
// represent the minimum residue point.
if (isCopy)
{
W = this->W;
@@ -149,49 +152,50 @@ class SimpleToleranceTermination
}
return true;
}
else return false;
return false;
}
//! Get current value of residue
//! Get current value of residue.
const double& Index() const { return residue; }
//! Get current iteration count
//! Get current iteration count.
const size_t& Iteration() const { return iteration; }
//! Access upper limit of iteration count
//! Access upper limit of iteration count.
const size_t& MaxIterations() const { return maxIterations; }
size_t& MaxIterations() { return maxIterations; }
//! Access tolerance value
//! Access tolerance value.
const double& Tolerance() const { return tolerance; }
double& Tolerance() { return tolerance; }
private:
//! tolerance
//! Locally-stored tolerance.
double tolerance;
//! iteration threshold
//! Locally-stored iteration threshold.
size_t maxIterations;
//! pointer to matrix being factorized
//! Pointer to matrix being factorized.
const MatType* V;
//! current iteration count
//! Current iteration count.
size_t iteration;
//! residue values
//! Locally-stored residue values.
double residueOld;
double residue;
//! tolerance on successive residue drops
//! Tolerance on successive residue drops.
size_t reverseStepTolerance;
//! successive residue drops
//! Successive residue drops.
size_t reverseStepCount;
//! indicates whether a copy of information is available which corresponds to
//! minimum residue point
//! Indicates whether a copy of information is available which corresponds to
//! minimum residue point.
bool isCopy;
//! variables to store information of minimum residue poi
//! Variables to store information of minimum residue poi.
arma::mat W;
arma::mat H;
double c_indexOld;
@@ -21,6 +21,7 @@ set(SOURCES
gaussian_function.hpp
hard_swish_function.hpp
tanh_exponential_function.hpp
silu_function.hpp
)
# Add directory name to sources.
@@ -0,0 +1,96 @@
/**
* @file methods/ann/activation_functions/silu_function.hpp
* @author Fawwaz Mayda
*
* Definition and implementation of the Sigmoid Weighted Linear Unit function (SILU).
*
* For more information see the following paper
*
* @code
* @misc{elfwing2017sigmoidweighted ,
* title = {Sigmoid-Weighted Linear Units for Neural Network Function Approximation in Reinforcement Learning},
* author = {Stefan Elfwing and Eiji Uchibe and Kenji Doya},
* year = {2017},
* url = {https://arxiv.org/pdf/1702.03118.pdf},
* eprint = {1702.03118},
* archivePrefix = {arXiv},
* primaryClass = {cs.LG} }
* @endcode
*
* mlpack is free software; you may redistribute it and/or modify it under the
* terms of the 3-clause BSD license. You should have received a copy of the
* 3-clause BSD license along with mlpack. If not, see
* http://www.opensource.org/licenses/BSD-3-Clause for more information.
*/
#ifndef MLPACK_METHODS_ANN_ACTIVATION_FUNCTIONS_SILU_FUNCTION_HPP
#define MLPACK_METHODS_ANN_ACTIVATION_FUNCTIONS_SILU_FUNCTION_HPP
#include <mlpack/prereqs.hpp>
namespace mlpack {
namespace ann /* Artificial Neural Network */ {
/**
* The SILU function, defined by
*
* @f{eqnarray*}{
* f(x) &=& x * \frac{1}{1 + e^{-x}}\\
* f'(x) &=& \frac{1}{1 + e^{-x}} * (1 + x * (1-\frac{1}{1 + e^{-x}}))\\
* @f}
*/
class SILUFunction
{
public:
/**
* Computes the SILU function.
*
* @param x Input data.
* @return f(x).
*/
static double Fn(const double x)
{
return x / (1.0 + std::exp(-x));
}
/**
* Computes the SILU function.
*
* @param x Input data.
* @param y The resulting output activation.
*/
template<typename InputVecType, typename OutputVecType>
static void Fn(const InputVecType &x, OutputVecType &y)
{
y = x / (1.0 + arma::exp(-x));
}
/**
* Computes the first derivative of the SILU function.
*
* @param y Input activation.
* @return f'(x)
*/
static double Deriv(const double x)
{
double sigmoid = 1.0 / (1.0 + std::exp(-x));
return sigmoid * (1.0 + x * (1.0 - sigmoid));
}
/**
* Computes the first derivatives of the SILU function.
*
* @param y Input activations.
* @param x The resulting derivatives.
*/
template<typename InputVecType, typename OutputVecType>
static void Deriv(const InputVecType &x, OutputVecType &y)
{
OutputVecType sigmoid = 1.0 / (1.0 + arma::exp(-x));
y = sigmoid % (1.0 + x % (1.0 - sigmoid));
}
}; // class SILUFunction
} // namespace ann
} // namespace mlpack
#endif
@@ -36,6 +36,8 @@ set(SOURCES
elu_impl.hpp
fast_lstm.hpp
fast_lstm_impl.hpp
flatten_t_swish.hpp
flatten_t_swish_impl.hpp
flexible_relu.hpp
flexible_relu_impl.hpp
glimpse.hpp
@@ -29,6 +29,7 @@
#include <mlpack/methods/ann/activation_functions/gaussian_function.hpp>
#include <mlpack/methods/ann/activation_functions/hard_swish_function.hpp>
#include <mlpack/methods/ann/activation_functions/tanh_exponential_function.hpp>
#include <mlpack/methods/ann/activation_functions/silu_function.hpp>
namespace mlpack {
namespace ann /** Artificial Neural Network. */ {
@@ -54,6 +55,7 @@ namespace ann /** Artificial Neural Network. */ {
* - GaussianLayer
* - HardSwishLayer
* - TanhExpLayer
* - SILULayer
*
* @tparam ActivationFunction Activation function used for the embedding layer.
* @tparam InputDataType Type of the input data (arma::colvec, arma::mat,
@@ -303,6 +305,18 @@ template <
using TanhExpFunctionLayer = BaseLayer<
ActivationFunction, InputDataType, OutputDataType>;
/**
* Standard SILU-Layer using the SILU activation function.
*/
template <
class ActivationFunction = SILUFunction,
typename InputDataType = arma::mat,
typename OutputDataType = arma::mat
>
using SILUFunctionLayer = BaseLayer<
ActivationFunction, InputDataType,OutputDataType
>;
} // namespace ann
} // namespace mlpack
@@ -0,0 +1,124 @@
/**
* @file methods/ann/layer/flatten_t_swish.hpp
* @author Fawwaz Mayda
*
* Definition of Flatten T Swish layer first introduced in the acoustic model,
* Hock Hung Chieng, Noorhaniza Wahid, Pauline Ong, Sai Raj Kishore Perla,
* "Flatten-T Swish: a thresholded ReLU-Swish-like activation function for deep learning", 2018
*
* mlpack is free software; you may redistribute it and/or modify it under the
* terms of the 3-clause BSD license. You should have received a copy of the
* 3-clause BSD license along with mlpack. If not, see
* http://www.opensource.org/licenses/BSD-3-Clause for more information.
*/
#ifndef MLPACK_METHODS_ANN_LAYER_FLATTEN_T_SWISH_HPP
#define MLPACK_METHODS_ANN_LAYER_FLATTEN_T_SWISH_HPP
#include <mlpack/prereqs.hpp>
namespace mlpack {
namespace ann /** Artificial Neural Network. */ {
/**
* The Flatten T Swish activation function, defined by
*
* @f{eqnarray*}{
* f'(x) &=& \left\{
* \begin{array}{lr}
* frac{x}{1+exp(-x)} + T & : x \ge 0 \\
* T & : x < 0
* \end{array}
* \right. \\
* f'(x) &=& \left\{
* \begin{array}{lr}
* \sigma(x)(1 - f(x)) + f(x) & : x > 0 \\
* 0 & : x \le 0
* \end{array}
* \right.
* @f}
*
* @tparam InputDataType Type of the input data (arma::colvec, arma::mat,
* arma::sp_mat or arma::cube).
* @tparam OutputDataType Type of the output data (arma::colvec, arma::mat,
* arma::sp_mat or arma::cube).
*/
template <
typename InputDataType = arma::mat,
typename OutputDataType = arma::mat
>
class FlattenTSwish
{
public:
/**
* Create the Flatten T Swish object using the specified parameters.
* The thresholded value T can be adjusted via T paramaters.
* When the x is < 0, T will be used instead of 0.
* The default value of T is -0.20 as suggested in the paper.
* @param T
*/
FlattenTSwish(const double T = -0.20);
/**
* Ordinary feed forward pass of a neural network, evaluating the function
* f(x) by propagating the activity forward through f.
*
* @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);
/**
* Ordinary feed backward pass of a neural network, calculating the function
* f(x) by propagating x backwards through f. Using the results from the feed
* forward pass.
*
* @param input The propagated input activation.
* @param gy The backpropagated error.
* @param g The calculated gradient.
*/
template<typename DataType>
void Backward(const DataType& input, const DataType& gy, DataType& g);
//! Get the output parameter.
OutputDataType const& OutputParameter() const { return outputParameter; }
//! Modify the output parameter.
OutputDataType& OutputParameter() { return outputParameter; }
//! Get the delta.
OutputDataType const& Delta() const { return delta; }
//! Modify the delta.
OutputDataType& Delta() { return delta; }
//! Get the T parameter.
double const& T() const { return t; }
//! Modify the T parameter.
double& T() { return t; }
//! Get size of weights.
size_t WeightSize() const { return 0; }
/**
* Serialize the layer.
*/
template<typename Archive>
void serialize(Archive& ar, const uint32_t /* version */);
private:
//! Locally-stored delta object.
OutputDataType delta;
//! Locally-stored output parameter object.
OutputDataType outputParameter;
//! T Parameter from paper.
double t;
}; // class FlattenTSwish
} // namespace ann
} // namespace mlpack
// Include implementation.
#include "flatten_t_swish_impl.hpp"
#endif
@@ -0,0 +1,80 @@
/**
* @file methods/ann/layer/flatten_t_swish_impl.hpp
* @author Fawwaz Mayda
*
* Definition of Flatten T Swish layer first introduced in the acoustic model,
* Hock Hung Chieng, Noorhaniza Wahid, Pauline Ong, Sai Raj Kishore Perla,
* "Flatten-T Swish: a thresholded ReLU-Swish-like activation function for deep learning", 2018
*
* mlpack is free software; you may redistribute it and/or modify it under the
* terms of the 3-clause BSD license. You should have received a copy of the
* 3-clause BSD license along with mlpack. If not, see
* http://www.opensource.org/licenses/BSD-3-Clause for more information.
*/
#ifndef MLPACK_METHODS_ANN_LAYER_FLATTEN_T_SWISH_IMPL_HPP
#define MLPACK_METHODS_ANN_LAYER_FLATTEN_T_SWISH_IMPL_HPP
// In case it hasn't yet been included.
#include "flatten_t_swish.hpp"
#include <mlpack/methods/ann/activation_functions/logistic_function.hpp>
#include <mlpack/methods/ann/activation_functions/rectifier_function.hpp>
namespace mlpack {
namespace ann /** Artificial Neural Network. */ {
template<typename InputDataType, typename OutputDataType>
FlattenTSwish<InputDataType, OutputDataType>::FlattenTSwish(
const double T) : t(T)
{
// Nothing to do here.
}
template<typename InputDataType, typename OutputDataType>
template<typename InputType, typename OutputType>
void FlattenTSwish<InputDataType, OutputDataType>::Forward(
const InputType& input, OutputType& output)
{
// Placeholder for Relu values.
OutputDataType relu;
RectifierFunction::Fn(input, relu);
LogisticFunction::Fn(input, output);
// F(x) = relu * sigmoid + t.
output = relu % output + t;
}
template<typename InputDataType, typename OutputDataType>
template<typename DataType>
void FlattenTSwish<InputDataType, OutputDataType>::Backward(
const DataType& input, const DataType& gy, DataType& g)
{
DataType derivate, sigmoid;
LogisticFunction::Fn(input,sigmoid);
derivate.set_size(arma::size(input));
for(size_t i = 0; i < input.n_elem; ++i)
{
if (input(i) >= 0)
{
// F(x) = x * sigmoid(x).
// We don't put '+ t' here because this is a derivate.
derivate(i) = input(i) * sigmoid(i);
derivate(i) = sigmoid(i) * (1.0 - derivate(i)) + derivate(i);
}
else
derivate(i) = 0;
}
g = gy % derivate;
}
template<typename InputDataType, typename OutputDataType>
template<typename Archive>
void FlattenTSwish<InputDataType, OutputDataType>::serialize(
Archive& ar,
const uint32_t /* version */)
{
ar(CEREAL_NVP(t));
}
} // namespace ann
} // namespace mlpack
#endif
+1
View File
@@ -32,6 +32,7 @@
#include "dropout.hpp"
#include "elu.hpp"
#include "fast_lstm.hpp"
#include "flatten_t_swish.hpp"
#include "flexible_relu.hpp"
#include "glimpse.hpp"
#include "gru.hpp"
+37 -17
View File
@@ -167,9 +167,17 @@ class LpPooling
for (size_t i = 0, rowidx = 0; i < output.n_rows;
++i, rowidx += strideWidth)
{
size_t rowEnd = rowidx + kernelWidth - 1;
size_t colEnd = colidx + kernelHeight - 1;
if (rowEnd > input.n_rows - 1)
rowEnd = input.n_rows - 1;
if (colEnd > input.n_cols - 1)
colEnd = input.n_cols - 1;
arma::mat subInput = input(
arma::span(rowidx, rowidx + kernelWidth - 1 - offset),
arma::span(colidx, colidx + kernelHeight - 1 - offset));
arma::span(rowidx, rowEnd),
arma::span(colidx, colEnd));
output(i, j) = pow(arma::accu(arma::pow(subInput,
normType)), 1.0 / normType);
@@ -188,24 +196,39 @@ class LpPooling
const arma::Mat<eT>& error,
arma::Mat<eT>& output)
{
const size_t rStep = input.n_rows / error.n_rows - offset;
const size_t cStep = input.n_cols / error.n_cols - offset;
arma::Mat<eT> unpooledError;
for (size_t j = 0; j < input.n_cols - cStep; j += cStep)
for (size_t j = 0, colidx = 0; j < input.n_cols; j += strideHeight, colidx++)
{
for (size_t i = 0; i < input.n_rows - rStep; i += rStep)
for (size_t i = 0, rowidx = 0; i < input.n_rows; i += strideWidth, rowidx++)
{
const arma::Mat<eT>& inputArea = input(arma::span(i, i + rStep - 1),
arma::span(j, j + cStep - 1));
size_t sum = pow(arma::accu(arma::pow(inputArea, normType)),
size_t rowEnd = i + kernelWidth - 1;
size_t colEnd = j + kernelHeight - 1;
if (rowEnd > input.n_rows - 1)
{
if (floor)
continue;
rowEnd = input.n_rows - 1;
}
if (colEnd > input.n_cols - 1)
{
if (floor)
continue;
colEnd = input.n_cols - 1;
}
arma::mat InputArea = input(arma::span(i, rowEnd), arma::span(j, colEnd));
size_t sum = pow(arma::accu(arma::pow(InputArea, normType)),
(normType - 1) / normType);
unpooledError = arma::Mat<eT>(inputArea.n_rows, inputArea.n_cols);
unpooledError.fill(error(i / rStep, j / cStep));
unpooledError %= arma::pow(inputArea, normType - 1);
unpooledError = arma::Mat<eT>(InputArea.n_rows, InputArea.n_cols);
unpooledError.fill(error(rowidx, colidx) / InputArea.n_elem);
unpooledError %= arma::pow(InputArea, normType - 1);
unpooledError /= sum;
output(arma::span(i, i + rStep - 1 - offset),
arma::span(j, j + cStep - 1 - offset)) += unpooledError;
output(arma::span(i, i + InputArea.n_rows - 1),
arma::span(j, j + InputArea.n_cols - 1)) += unpooledError;
}
}
}
@@ -249,9 +272,6 @@ class LpPooling
//! Locally-stored reset parameter used to initialize the module once.
bool reset;
//! Locally-stored stored rounding offset.
size_t offset;
//! Locally-stored number of input units.
size_t batchSize;
@@ -46,7 +46,6 @@ LpPooling<InputDataType, OutputDataType>::LpPooling(
outputWidth(0),
outputHeight(0),
reset(false),
offset(0),
batchSize(0)
{
// Nothing to do here.
@@ -68,8 +67,6 @@ void LpPooling<InputDataType, OutputDataType>::Forward(
(double) kernelWidth) / (double) strideWidth + 1);
outputHeight = std::floor((inputHeight -
(double) kernelHeight) / (double) strideHeight + 1);
offset = 0;
}
else
{
@@ -77,8 +74,6 @@ void LpPooling<InputDataType, OutputDataType>::Forward(
(double) kernelWidth) / (double) strideWidth + 1);
outputHeight = std::ceil((inputHeight -
(double) kernelHeight) / (double) strideHeight + 1);
offset = 1;
}
outputTemp = arma::zeros<arma::Cube<eT> >(outputWidth, outputHeight,
+12 -7
View File
@@ -188,18 +188,25 @@ class MaxPooling
for (size_t i = 0, rowidx = 0; i < output.n_rows;
++i, rowidx += strideWidth)
{
size_t rowEnd = rowidx + kernelWidth - 1;
size_t colEnd = colidx + kernelHeight - 1;
if (rowEnd > input.n_rows - 1)
rowEnd = input.n_rows - 1;
if (colEnd > input.n_cols - 1)
colEnd = input.n_cols - 1;
arma::mat subInput = input(
arma::span(rowidx, rowidx + kernelWidth - 1 - offset),
arma::span(colidx, colidx + kernelHeight - 1 - offset));
arma::span(rowidx, rowEnd),
arma::span(colidx, colEnd));
const size_t idx = pooling.Pooling(subInput);
output(i, j) = subInput(idx);
if (!deterministic)
{
arma::Mat<size_t> subIndices = indices(arma::span(rowidx,
rowidx + kernelWidth - 1 - offset),
arma::span(colidx, colidx + kernelHeight - 1 - offset));
arma::Mat<size_t> subIndices = indices(arma::span(rowidx, rowEnd),
arma::span(colidx, colEnd));
poolingIndices(i, j) = subIndices(idx);
}
@@ -264,8 +271,6 @@ class MaxPooling
//! If true use maximum a posteriori during the forward pass.
bool deterministic;
//! Locally-stored stored rounding offset.
size_t offset;
//! Locally-stored number of input units.
size_t batchSize;
@@ -45,7 +45,6 @@ MaxPooling<InputDataType, OutputDataType>::MaxPooling(
outputWidth(0),
outputHeight(0),
deterministic(false),
offset(0),
batchSize(0)
{
// Nothing to do here.
@@ -67,7 +66,6 @@ void MaxPooling<InputDataType, OutputDataType>::Forward(
(double) kernelWidth) / (double) strideWidth + 1);
outputHeight = std::floor((inputHeight -
(double) kernelHeight) / (double) strideHeight + 1);
offset = 0;
}
else
{
@@ -75,7 +73,6 @@ void MaxPooling<InputDataType, OutputDataType>::Forward(
(double) kernelWidth) / (double) strideWidth + 1);
outputHeight = std::ceil((inputHeight -
(double) kernelHeight) / (double) strideHeight + 1);
offset = 1;
}
outputTemp = arma::zeros<arma::Cube<eT> >(outputWidth, outputHeight,
@@ -1,6 +1,6 @@
/**
* @file methods/bayesian_linear_regression/bayesian_linear_regression.cpp
* @author Clement Mercier
* @author Clement Mercier
*
* Implementation of Bayesian linear regression.
*
@@ -58,12 +58,12 @@ double BayesianLinearRegression::Train(const arma::mat& data,
beta = 1 / (var(t, 1) * 0.1);
unsigned short i = 0;
double deltaAlpha = 1.0, deltaBeta = 1.0, crit = 1.0;
double deltaAlpha = 1.0, crit = 1.0;
while ((crit > tolerance) && (i < maxIterations))
{
deltaAlpha = -alpha;
deltaBeta = -beta;
double deltaBeta = -beta;
// Update the solution.
omega = eigVec * diagmat(1 / (eigVal + (alpha / beta))) * eigVecInvPhitT;
-5
View File
@@ -89,31 +89,26 @@ CFWrapperBase* TrainHelper(const DecompositionPolicy& decomposition,
return new CFWrapper<DecompositionPolicy, NoNormalization>(data,
decomposition, numUsersForSimilarity, rank, maxIterations, minResidue,
mit);
break;
case CFModel::ITEM_MEAN_NORMALIZATION:
return new CFWrapper<DecompositionPolicy, ItemMeanNormalization>(data,
decomposition, numUsersForSimilarity, rank, maxIterations, minResidue,
mit);
break;
case CFModel::USER_MEAN_NORMALIZATION:
return new CFWrapper<DecompositionPolicy, UserMeanNormalization>(data,
decomposition, numUsersForSimilarity, rank, maxIterations, minResidue,
mit);
break;
case CFModel::OVERALL_MEAN_NORMALIZATION:
return new CFWrapper<DecompositionPolicy, OverallMeanNormalization>(data,
decomposition, numUsersForSimilarity, rank, maxIterations, minResidue,
mit);
break;
case CFModel::Z_SCORE_NORMALIZATION:
return new CFWrapper<DecompositionPolicy, ZScoreNormalization>(data,
decomposition, numUsersForSimilarity, rank, maxIterations, minResidue,
mit);
break;
}
// This shouldn't ever happen.
+4 -10
View File
@@ -874,19 +874,13 @@ double DTree<MatType, TagType>::ComputeValue(const VecType& query) const
}
if (subtreeLeaves == 1) // If we are a leaf...
{
return std::exp(std::log(ratio) - logVolume);
}
else
{
// Return either of the two children - left or right, depending on the
// splitValue
return (query[splitDim] <= splitValue) ?
// Return either of the two children - left or right, depending on the
// splitValue.
return (query[splitDim] <= splitValue) ?
left->ComputeValue(query) :
right->ComputeValue(query);
}
return 0.0;
}
// Index the buckets for possible usage later.
+1 -1
View File
@@ -262,7 +262,7 @@ static void mlpackMain()
// Delete the memory, if needed.
if (IO::HasParam("reference"))
delete model;
throw e;
throw;
}
}
@@ -373,10 +373,6 @@ static void mlpackMain()
oss << IO::GetPrintableParam<arma::mat>("test");
std::string testOutput = oss.str();
if (!IO::HasParam("training"))
{
numClasses = model->svm.NumClasses();
}
// Get the test dataset, and get predictions.
testSet = std::move(IO::GetParam<arma::mat>("test"));
arma::Row<size_t> predictions;
@@ -397,9 +397,7 @@ inline double NeighborSearchRules<SortPolicy, MetricType, TreeType>::
// take the better of the two.
double worstDistance = SortPolicy::BestDistance();
double bestDistance = SortPolicy::WorstDistance();
double bestPointDistance = SortPolicy::WorstDistance();
double auxDistance = SortPolicy::WorstDistance();
// Loop over points held in the node.
for (size_t i = 0; i < queryNode.NumPoints(); ++i)
@@ -411,7 +409,7 @@ inline double NeighborSearchRules<SortPolicy, MetricType, TreeType>::
bestPointDistance = distance;
}
auxDistance = bestPointDistance;
double auxDistance = bestPointDistance;
// Loop over children of the node, and use their cached information to
// assemble bounds.
@@ -428,7 +426,7 @@ inline double NeighborSearchRules<SortPolicy, MetricType, TreeType>::
// Add triangle inequality adjustment to best distance. It is possible this
// could be tighter for some certain types of trees.
bestDistance = SortPolicy::CombineWorst(auxDistance,
double bestDistance = SortPolicy::CombineWorst(auxDistance,
2 * queryNode.FurthestDescendantDistance());
// Add triangle inequality adjustment to best distance of points in node.
+20 -6
View File
@@ -1,5 +1,8 @@
include(CTest)
# mlpack test executable.
add_executable(mlpack_test
EXCLUDE_FROM_ALL
activation_functions_test.cpp
adaboost_test.cpp
akfn_test.cpp
@@ -175,12 +178,21 @@ add_executable(mlpack_test
main_tests/test_helper.hpp
)
# Link dependencies of test executable.
target_link_libraries(mlpack_test
mlpack
${ARMADILLO_LIBRARIES}
${COMPILER_SUPPORT_LIBRARIES}
)
if(NOT BUILD_SHARED_LIBS)
# Build mlpack test executable statically.
target_link_libraries(mlpack_test -static
mlpack
${ARMADILLO_LIBRARIES}
${COMPILER_SUPPORT_LIBRARIES}
)
else()
# Build mlpack test executable dynamically.
target_link_libraries(mlpack_test
mlpack
${ARMADILLO_LIBRARIES}
${COMPILER_SUPPORT_LIBRARIES}
)
endif()
set_target_properties(mlpack_test PROPERTIES COTIRE_CXX_PREFIX_HEADER_INIT "../core.hpp")
cotire(mlpack_test)
@@ -203,3 +215,5 @@ add_custom_command(TARGET mlpack_test
)
add_test(NAME "catch_test" COMMAND mlpack_test WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
set_tests_properties("catch_test" PROPERTIES TIMEOUT 0)
@@ -34,6 +34,7 @@
#include <mlpack/methods/ann/activation_functions/gaussian_function.hpp>
#include <mlpack/methods/ann/activation_functions/hard_swish_function.hpp>
#include <mlpack/methods/ann/activation_functions/tanh_exponential_function.hpp>
#include <mlpack/methods/ann/activation_functions/silu_function.hpp>
#include "catch.hpp"
@@ -659,6 +660,48 @@ void CheckSoftminDerivativeCorrect(const arma::colvec input,
}
}
/**
* Implementation of the Flatten T Swish activation function test. The function is
* implemented as Flatten T Swish layer in the file flatten_t_swish.hpp.
*
* @param input Input data used for evaluating the Flatten T Swish activation function.
* @param target Target data used to evaluate the Flatten T Swish activation.
*/
void CheckFlattenTSwishActivationCorrect(const arma::colvec input, const arma::colvec target)
{
FlattenTSwish<> fts(0.4);
arma::colvec activations;
fts.Forward(input,activations);
for(size_t i = 0; i < activations.n_elem; ++i)
{
REQUIRE(activations.at(i) == Approx(target.at(i)).epsilon(1e-5));
}
}
/**
* Implementation of the Softmin activation function derivative test.
* The function is implemented as Softmin layer in the file softmin.hpp.
*
* @param input Input data used for evaluating the Softmin activation function.
* @param target Target data used to evaluate the Softmin activation.
*/
void CheckFlattenTSwishDerivateCorrect(const arma::colvec input, const arma::colvec target)
{
FlattenTSwish<> fts;
// Set the error to 1 to get the actual derivative.
arma::colvec error = arma::ones<arma::colvec>(input.n_elem);
arma::colvec derivate;
fts.Backward(input,error,derivate);
for(size_t i = 0; i < derivate.n_elem; ++i)
{
REQUIRE(derivate.at(i) == Approx(target.at(i)).epsilon(1e-5));
}
}
/**
* Basic test of the tanh function.
*/
@@ -1241,3 +1284,45 @@ TEST_CASE("TanhExpFunctionTest", "[ActivationFunctionsTest]")
CheckActivationCorrect<TanhExpFunction>(activationData, desiredActivations);
CheckDerivativeCorrect<TanhExpFunction>(desiredActivations, desiredDerivatives);
}
/**
* Basic test of the SILU(Sigmoid Weighted Linear Unit) Function
*/
TEST_CASE("SILUFunctionTest","[ActivationFunctionsTest]")
{
// Random generated values.
const arma::colvec activationData("-2 2 4.5 -5.7 -1 1 0 10");
// Calculated with PyTorch.
arma::colvec desiredActivation("-0.23840583860874176 1.7615940570831299 4.450558662414551 \
-0.01900840364396572 -0.2689414322376251 0.7310585975646973 \
0.0 9.99954605102539");
// Calculated with PyTorch.
arma::colvec desiredDerivate("0.38191673159599304 1.073788046836853 1.0392179489135742 \
0.49049633741378784 0.36713290214538574 0.8354039788246155 \
0.5 1.0004087686538696");
CheckActivationCorrect<SILUFunction>(activationData,desiredActivation);
CheckDerivativeCorrect<SILUFunction>(desiredActivation,desiredDerivate);
}
/**
* Basic test of Flatten T Swish function.
*/
TEST_CASE("FlattenTSwishFunctionTest","[ActivationFunctionsTest]")
{
// Random Value.
arma::colvec input("-4.0 -1.0 2 3 4 5 6");
// Hand Calculated and using PyTorch.
arma::colvec desiredActivation("0.4000000059604645 0.4000000059604645 2.1615941524505615 \
3.2577223777770996 4.328054904937744 5.3665361404418945 6.385164737701416");
// Hand Calculated and using PyTorch.
arma::colvec desiredDerivation("0.694792 0.694792 1.096893 1.079178 1.042602 \
1.020182 1.009048");
CheckFlattenTSwishActivationCorrect(input,desiredActivation);
CheckFlattenTSwishDerivateCorrect(desiredActivation,desiredDerivation);
}
-1
View File
@@ -241,4 +241,3 @@ TEST_CASE("AKFNDualBallTreeTest", "[AKFNTest]")
for (size_t i = 0; i < neighborsBallTree.n_elem; ++i)
REQUIRE_RELATIVE_ERR(distancesBallTree(i), distancesExact(i), 0.05);
}
+2 -2
View File
@@ -341,7 +341,7 @@ TEST_CASE("TestComputeValue", "[DETTest]")
REQUIRE(d3 == Approx(testDTree.ComputeValue(q3)).epsilon(1e-12));
REQUIRE(0.0 == Approx(testDTree.ComputeValue(q4)).epsilon(1e-12));
alpha = testDTree.PruneAndUpdate(alpha, testData.n_cols, false);
testDTree.PruneAndUpdate(alpha, testData.n_cols, false);
double d = 1.0 / exp(log(4.0) + log(7.0) + log(7.0));
@@ -448,7 +448,7 @@ TEST_CASE("TestSparseComputeValue", "[DETTest]")
REQUIRE(d3 == Approx(testDTree.ComputeValue(q3)).epsilon(1e-12));
REQUIRE(0.0 == Approx(testDTree.ComputeValue(q4)).epsilon(1e-12));
alpha = testDTree.PruneAndUpdate(alpha, testData.n_cols, false);
testDTree.PruneAndUpdate(alpha, testData.n_cols, false);
double d = 1.0 / exp(log(4.0) + log(7.0) + log(7.0));
+2 -1
View File
@@ -368,7 +368,8 @@ TEST_CASE("DualCoverTreeTest", "[KRANNTest]")
RACoverTreeSearch tsdRann(&refTree, false, 1.0, 0.95, false, false, 5);
arma::Mat<size_t> qrRanks;
if (!data::Load("rann_test_qr_ranks.csv", qrRanks, false, false)) // No transpose.
// No transpose.
if (!data::Load("rann_test_qr_ranks.csv", qrRanks, false, false))
FAIL("Cannot load dataset rann_test_qr_ranks.csv");
size_t numRounds = 100;
-20
View File
@@ -29,19 +29,16 @@ void TestArmadilloSerialization(arma::Cube<CubeType>& x)
// Use type_info name to get unique file name for serialization test files.
std::string fileName = FilterFileName(typeid(IArchiveType).name());
std::ofstream ofs(fileName, std::ios::binary);
bool success = true;
{
OArchiveType o(ofs);
o(CEREAL_NVP(x));
}
REQUIRE(success == true);
ofs.close();
// Now load it.
arma::Cube<CubeType> orig(x);
success = true;
std::ifstream ifs(fileName, std::ios::binary);
{
@@ -52,8 +49,6 @@ void TestArmadilloSerialization(arma::Cube<CubeType>& x)
remove(fileName.c_str());
REQUIRE(success == true);
REQUIRE(x.n_rows == orig.n_rows);
REQUIRE(x.n_cols == orig.n_cols);
REQUIRE(x.n_elem_slice == orig.n_elem_slice);
@@ -99,19 +94,16 @@ void TestArmadilloSerialization(MatType& x)
// First save it.
std::string fileName = FilterFileName(typeid(IArchiveType).name());
std::ofstream ofs(fileName, std::ios::binary);
bool success = true;
{
OArchiveType o(ofs);
o(CEREAL_NVP(x));
}
REQUIRE(success == true);
ofs.close();
// Now load it.
MatType orig(x);
success = true;
std::ifstream ifs(fileName, std::ios::binary);
{
@@ -122,8 +114,6 @@ void TestArmadilloSerialization(MatType& x)
remove(fileName.c_str());
REQUIRE(success == true);
REQUIRE(x.n_rows == orig.n_rows);
REQUIRE(x.n_cols == orig.n_cols);
REQUIRE(x.n_elem == orig.n_elem);
@@ -156,7 +146,6 @@ void SerializeObject(T& t, T& newT)
{
std::string fileName = FilterFileName(typeid(T).name());
std::ofstream ofs(fileName, std::ios::binary);
bool success = true;
{
OArchiveType o(ofs);
@@ -166,8 +155,6 @@ void SerializeObject(T& t, T& newT)
}
ofs.close();
REQUIRE(success == true);
std::ifstream ifs(fileName, std::ios::binary);
{
@@ -178,8 +165,6 @@ void SerializeObject(T& t, T& newT)
ifs.close();
remove(fileName.c_str());
REQUIRE(success == true);
}
// Test mlpack serialization with all three archive types.
@@ -200,7 +185,6 @@ void SerializePointerObject(T* t, T*& newT)
{
std::string fileName = FilterFileName(typeid(T).name());
std::ofstream ofs(fileName, std::ios::binary);
bool success = true;
{
OArchiveType o(ofs);
@@ -208,8 +192,6 @@ void SerializePointerObject(T* t, T*& newT)
}
ofs.close();
REQUIRE(success == true);
std::ifstream ifs(fileName, std::ios::binary);
{
@@ -218,8 +200,6 @@ void SerializePointerObject(T* t, T*& newT)
}
ifs.close();
remove(fileName.c_str());
REQUIRE(success == true);
}
template<typename T>