Merge branch 'master' into Fix-solaris-winndows-r
This commit is contained in:
-219
@@ -1,219 +0,0 @@
|
||||
clone_depth: 10
|
||||
|
||||
environment:
|
||||
BOOST_MATH : "C:/projects/mlpack/\
|
||||
boost_math_c99-vc140.1.60.0.0/lib/native/address-model-64/lib/*.*"
|
||||
BOOST_RANDOM : "C:/projects/mlpack/\
|
||||
boost_random-vc140.1.60.0.0/lib/native/address-model-64/lib/*.*"
|
||||
ARMADILLO_DOWNLOAD : "https://data.kurg.org/armadillo-8.400.0.tar.xz"
|
||||
ARMADILLO_LIBRARY : "C:/projects/mlpack/armadillo-8.400.0/\
|
||||
build/Debug/armadillo.lib"
|
||||
BLAS_LIBRARY : "%APPVEYOR_BUILD_FOLDER%/OpenBLAS.0.2.14.1/lib/native/lib/x64/\
|
||||
libopenblas.dll.a"
|
||||
BOOST_INCLUDE : "C:/projects/mlpack/boost.1.60.0.0/lib/native/include"
|
||||
JENKINS_DOC_DOWNLOAD : "http://ci.mlpack.org/job/mlpack%20-%20doxygen%20\
|
||||
build/lastSuccessfulBuild/artifact/build/doc/html/*zip*/html.zip"
|
||||
JENKINS_DOC : "C:/projects/mlpack/dist/win-installer/jenkinsdoc.zip"
|
||||
GIT_VERSION_FILE : "C:/projects/mlpack/src/mlpack/core/util/gitversion.hpp"
|
||||
matrix:
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
|
||||
VSVER: Visual Studio 16 2019
|
||||
MSBUILD: C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Current\Bin\MSBuild.exe
|
||||
|
||||
# We have removed the VS studio 15 2017 build since it is not possible to complete
|
||||
# or finish the build due to the `compiler out of heap space issues`.
|
||||
# Therefore, in the meanwhile, we are only doing the installation for VS 16 2019.
|
||||
|
||||
configuration: Release
|
||||
|
||||
os: Visual Studio 2019
|
||||
|
||||
install:
|
||||
- ps: nuget install boost -o "${env:APPVEYOR_BUILD_FOLDER}" -Version 1.60.0
|
||||
- ps: >
|
||||
nuget install boost_random-vc140
|
||||
-o "${env:APPVEYOR_BUILD_FOLDER}" -Version 1.60.0
|
||||
- ps: >
|
||||
nuget install boost_math_c99-vc140
|
||||
-o "${env:APPVEYOR_BUILD_FOLDER}" -Version 1.60.0
|
||||
- ps: >
|
||||
nuget install unofficial-flayan-cereal
|
||||
-o "${env:APPVEYOR_BUILD_FOLDER}"
|
||||
- ps: nuget install OpenBLAS -o "${env:APPVEYOR_BUILD_FOLDER}"
|
||||
- set path=C:\Program Files (x86)\WiX Toolset v3.11\bin;%path%
|
||||
|
||||
build_script:
|
||||
- mkdir boost_libs
|
||||
- ps: cp ${env:BOOST_MATH} C:\projects\mlpack\boost_libs\
|
||||
- ps: cp ${env:BOOST_RANDOM} C:\projects\mlpack\boost_libs\
|
||||
- echo TEST_ARMA is %ARMADILLO_DOWNLOAD%
|
||||
- >
|
||||
appveyor DownloadFile %ARMADILLO_DOWNLOAD%
|
||||
-FileName armadillo.tar.xz
|
||||
- 7z x armadillo.tar.xz -so -txz | 7z x -si -ttar > nul
|
||||
- cd armadillo-8.400.0 && mkdir build && cd build
|
||||
- >
|
||||
cmake -G "%VSVER%"
|
||||
-DBLAS_LIBRARY:FILEPATH=%BLAS_LIBRARY%
|
||||
-DLAPACK_LIBRARY:FILEPATH=%BLAS_LIBRARY%
|
||||
-DCMAKE_PREFIX:FILEPATH="%APPVEYOR_BUILD_FOLDER%/armadillo"
|
||||
-DBUILD_SHARED_LIBS=OFF
|
||||
-DCMAKE_BUILD_TYPE=Release ..
|
||||
- >
|
||||
"%MSBUILD%" "C:\projects\mlpack\armadillo-8.400.0\build\armadillo.sln"
|
||||
/m /verbosity:quiet /p:Configuration=Release;Platform=x64
|
||||
- cd C:\projects\mlpack && mkdir build && cd build
|
||||
- >
|
||||
cmake -G "%VSVER%"
|
||||
-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%
|
||||
-DCEREAL_INCLUDE_DIR="C:/projects/mlpack/unofficial-flayan-cereal.1.2.2/build/native/include"
|
||||
-DBOOST_INCLUDEDIR:PATH=%BOOST_INCLUDE%
|
||||
-DDEBUG=OFF
|
||||
-DPROFILE=OFF
|
||||
-DBUILD_PYTHON_BINDINGS=OFF
|
||||
-DBUILD_GO_BINDINGS=OFF
|
||||
-DBUILD_R_BINDINGS=OFF
|
||||
-DBUILD_TESTS=OFF
|
||||
-DCMAKE_BUILD_TYPE=Release ..
|
||||
- >
|
||||
"%MSBUILD%" "C:\projects\mlpack\build\mlpack.sln"
|
||||
/m /verbosity:minimal /nologo /p:BuildInParallel=true
|
||||
/p:Configuration=Release;Platform=x64
|
||||
|
||||
# Zip Artifacts.
|
||||
- >
|
||||
7z a mlpack-windows-no-libs.zip
|
||||
"%APPVEYOR_BUILD_FOLDER%\build\Release\*.exe"
|
||||
- >
|
||||
7z a mlpack-windows.zip
|
||||
"%APPVEYOR_BUILD_FOLDER%\build\Release\*.*"
|
||||
"%APPVEYOR_BUILD_FOLDER%/OpenBLAS.0.2.14.1/lib/native/lib/x64/*.*"
|
||||
|
||||
# Pulling documentation for the installer.
|
||||
- ps: >
|
||||
try{(new-object net.webclient).DownloadFile(${env:JENKINS_DOC_DOWNLOAD},
|
||||
'C:\projects\mlpack\dist\win-installer\jenkinsdoc.zip')}
|
||||
catch{Write-Output "Unable to pull jenkins doc, skipping!"}
|
||||
- ps: >
|
||||
try{(Add-Type -AssemblyName System.IO.Compression.FileSystem);
|
||||
[System.IO.Compression.ZipFile]::ExtractToDirectory(${env:JENKINS_DOC},
|
||||
'C:\projects\mlpack\dist\win-installer\staging\doc')}
|
||||
catch{Write-Output "Unable to add doc to installer, skipping!"}
|
||||
|
||||
# Preparing installer staging.
|
||||
- cd C:\projects\mlpack\dist\win-installer\staging && mkdir lib
|
||||
- ps: >
|
||||
cp C:\projects\mlpack\build\Release\*.lib
|
||||
C:\projects\mlpack\dist\win-installer\staging\lib\
|
||||
- ps: >
|
||||
cp C:\projects\mlpack\build\Release\*.exp
|
||||
C:\projects\mlpack\dist\win-installer\staging\lib\
|
||||
- ps: >
|
||||
cp C:\projects\mlpack\build\Release\*.dll
|
||||
C:\projects\mlpack\dist\win-installer\staging\
|
||||
- ps: >
|
||||
cp C:\projects\mlpack\build\Release\*.exe
|
||||
C:\projects\mlpack\dist\win-installer\staging\
|
||||
- ps: >
|
||||
cp C:\projects\mlpack\OpenBLAS.0.2.14.1\lib\native\bin\x64\*.dll
|
||||
C:\projects\mlpack\dist\win-installer\staging\
|
||||
- ps: >
|
||||
cp C:\projects\mlpack\build\include\mlpack
|
||||
C:\projects\mlpack\dist\win-installer\staging -recurse
|
||||
- ps: >
|
||||
cp C:\projects\mlpack\doc\examples
|
||||
C:\projects\mlpack\dist\win-installer\staging -recurse
|
||||
- ps: >
|
||||
cp C:\projects\mlpack\src\mlpack\tests\data\german.csv
|
||||
C:\projects\mlpack\dist\win-installer\staging\examples\sample-ml-app\sample-ml-app\data\
|
||||
|
||||
# Checking current gitversion or mlpack version.
|
||||
- ps: >
|
||||
$ver = (Get-Content
|
||||
"${env:APPVEYOR_BUILD_FOLDER}\src\mlpack\core\util\version.hpp" |
|
||||
where {$_ -like "*MLPACK_VERSION*"});
|
||||
$env:MLPACK_VERSION += $ver[0].substring($ver[0].length - 1, 1) + '.';
|
||||
$env:MLPACK_VERSION += $ver[1].substring($ver[1].length - 1, 1) + '.';
|
||||
$env:MLPACK_VERSION += $ver[2].substring($ver[2].length - 1, 1);
|
||||
|
||||
if (Test-Path ${env:GIT_VERSION_FILE})
|
||||
{
|
||||
$ver = (Get-Content ${env:GIT_VERSION_FILE});
|
||||
$env:INSTALL_VERSION = $ver.Split('"')[1].Split(' ')[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
$env:INSTALL_VERSION = $env:MLPACK_VERSION;
|
||||
}
|
||||
- echo INSTALL_VERSION is %INSTALL_VERSION%
|
||||
|
||||
# Building MSI installer.
|
||||
- cd C:\projects\mlpack\dist\win-installer\mlpack-win-installer
|
||||
- >
|
||||
heat dir ..\staging
|
||||
-cg HeatGenerated
|
||||
-dr INSTALLFOLDER
|
||||
-sreg
|
||||
-srd
|
||||
-var var.HarvestPath
|
||||
-ag
|
||||
-sfrag
|
||||
-out HeatGeneratedFileList.wxs
|
||||
- >
|
||||
candle -dHarvestPath=..\staging
|
||||
-dConfiguration=Release
|
||||
-dOutDir=bin\x64\Release\
|
||||
-dPlatform=x64
|
||||
-dProjectDir=.
|
||||
-dProjectExt=.wixproj
|
||||
-dProjectFileName=mlpack-win-installer.wixproj
|
||||
-dProjectName=mlpack-win-installer
|
||||
-dProjectPath=mlpack-win-installer.wixproj
|
||||
-dTargetDir=.\bin\x64\Release\
|
||||
-dTargetExt=.msi
|
||||
-dTargetFileName=mlpack-windows.msi
|
||||
-dTargetName=mlpack-windows
|
||||
-dTargetPath=.\bin\x64\Release\mlpack-windows.msi
|
||||
-out obj\x64\Release\
|
||||
-arch x64
|
||||
-ext "C:\Program Files (x86)\WiX Toolset v3.11\bin\\WixUIExtension.dll"
|
||||
Product.wxs HeatGeneratedFileList.wxs
|
||||
- >
|
||||
light -out .\bin\x64\Release\mlpack-%INSTALL_VERSION%.msi
|
||||
-pdbout .\bin\x64\Release\mlpack-windows.wixpdb
|
||||
-cultures:null
|
||||
-loc mlpack-localization.wxl
|
||||
-ext "C:\Program Files (x86)\WiX Toolset v3.11\bin\\WixUIExtension.dll"
|
||||
-contentsfile
|
||||
obj\x64\Release\mlpack-win-installer.wixproj.BindContentsFileListnull.txt
|
||||
-outputsfile
|
||||
obj\x64\Release\mlpack-win-installer.wixproj.BindOutputsFileListnull.txt
|
||||
-builtoutputsfile
|
||||
obj\x64\Release\mlpack-win-installer.wixproj.BindBuiltOutputsFileListnull.txt
|
||||
-wixprojectfile
|
||||
mlpack-win-installer.wixproj
|
||||
obj\x64\Release\Product.wixobj
|
||||
obj\x64\Release\HeatGeneratedFileList.wixobj
|
||||
|
||||
artifacts:
|
||||
- path: 'build\*.zip'
|
||||
name: mlpack-windows-zip
|
||||
|
||||
- path: 'dist\win-installer\mlpack-win-installer\bin\x64\Release\*.msi'
|
||||
name: mlpack-windows-installer
|
||||
|
||||
notifications:
|
||||
- provider: Email
|
||||
to:
|
||||
- mlpack-git@lists.mlpack.org
|
||||
on_build_success: true
|
||||
on_build_failure: true
|
||||
on_build_status_changed: true
|
||||
|
||||
cache:
|
||||
- packages -> **\packages.config
|
||||
- armadillo.tar.xz -> appveyor.yaml
|
||||
|
||||
@@ -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 liblapack-dev g++ libboost1.70-dev libarmadillo-dev xz-utils
|
||||
sudo apt-get install -y --allow-unauthenticated libopenblas-dev g++ libboost1.70-dev xz-utils
|
||||
|
||||
if [ "$(binding)" == "python" ]; then
|
||||
export PYBIN=$(which python)
|
||||
|
||||
@@ -14,7 +14,7 @@ steps:
|
||||
set -e
|
||||
sudo xcode-select --switch /Applications/Xcode_12.2.app/Contents/Developer
|
||||
unset BOOST_ROOT
|
||||
brew install openblas armadillo boost cereal
|
||||
brew install libomp openblas armadillo boost cereal
|
||||
|
||||
if [ "$(binding)" == "python" ]; then
|
||||
pip install --upgrade pip
|
||||
@@ -22,7 +22,7 @@ steps:
|
||||
fi
|
||||
|
||||
if [ "a$(julia.version)" != "a" ]; then
|
||||
brew cask install julia
|
||||
brew install --cask julia
|
||||
fi
|
||||
|
||||
git clone --depth 1 https://github.com/mlpack/jenkins-conf.git conf
|
||||
@@ -65,4 +65,4 @@ steps:
|
||||
inputs:
|
||||
pathtoPublish: 'build/Testing/'
|
||||
artifactName: 'Tests'
|
||||
displayName: 'Publish artifacts test results'
|
||||
displayName: 'Publish artifacts test results'
|
||||
@@ -1,110 +0,0 @@
|
||||
# This module looks for mex, the MATLAB compiler.
|
||||
# The following variables are defined when the script completes:
|
||||
# MATLAB_MEX: location of mex compiler
|
||||
# MATLAB_ROOT: root of MATLAB installation
|
||||
# MATLABMEX_FOUND: 0 if not found, 1 if found
|
||||
|
||||
set(MATLABMEX_FOUND 0)
|
||||
|
||||
if(WIN32)
|
||||
# This is untested but taken from the older FindMatlab.cmake script as well as
|
||||
# the modifications by Ramon Casero and Tom Doel for Gerardus.
|
||||
|
||||
# Search for a version of Matlab available, starting from the most modern one
|
||||
# to older versions.
|
||||
foreach(MATVER "7.20" "7.19" "7.18" "7.17" "7.16" "7.15" "7.14" "7.13" "7.12"
|
||||
"7.11" "7.10" "7.9" "7.8" "7.7" "7.6" "7.5" "7.4")
|
||||
if((NOT DEFINED MATLAB_ROOT)
|
||||
OR ("${MATLAB_ROOT}" STREQUAL "")
|
||||
OR ("${MATLAB_ROOT}" STREQUAL "/registry"))
|
||||
get_filename_component(MATLAB_ROOT
|
||||
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\MathWorks\\MATLAB\\${MATVER};MATLABROOT]"
|
||||
ABSOLUTE)
|
||||
set(MATLAB_VERSION ${MATVER})
|
||||
endif()
|
||||
OR ("${MATLAB_ROOT}" STREQUAL "")
|
||||
OR ("${MATLAB_ROOT}" STREQUAL "/registry"))
|
||||
endforeach()
|
||||
|
||||
find_program(MATLAB_MEX
|
||||
mex
|
||||
${MATLAB_ROOT}/bin
|
||||
)
|
||||
else()
|
||||
# Check if this is a Mac.
|
||||
if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
|
||||
# This code is untested but taken from the older FindMatlab.cmake script as
|
||||
# well as the modifications by Ramon Casero and Tom Doel for Gerardus.
|
||||
|
||||
set(LIBRARY_EXTENSION .dylib)
|
||||
|
||||
# If this is a Mac and the attempts to find MATLAB_ROOT have so far failed,~
|
||||
# we look in the applications folder
|
||||
if((NOT DEFINED MATLAB_ROOT) OR ("${MATLAB_ROOT}" STREQUAL ""))
|
||||
|
||||
# Search for a version of Matlab available, starting from the most modern
|
||||
# one to older versions
|
||||
foreach(MATVER "R2013b" "R2013a" "R2012b" "R2012a" "R2011b" "R2011a"
|
||||
"R2010b" "R2010a" "R2009b" "R2009a" "R2008b")
|
||||
if((NOT DEFINED MATLAB_ROOT) OR ("${MATLAB_ROOT}" STREQUAL ""))
|
||||
if(EXISTS /Applications/MATLAB_${MATVER}.app)
|
||||
set(MATLAB_ROOT /Applications/MATLAB_${MATVER}.app)
|
||||
|
||||
endif()
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
endif()
|
||||
|
||||
find_program(MATLAB_MEX
|
||||
mex
|
||||
PATHS
|
||||
${MATLAB_ROOT}/bin
|
||||
)
|
||||
|
||||
else()
|
||||
# On a Linux system. The goal is to find MATLAB_ROOT.
|
||||
set(LIBRARY_EXTENSION .so)
|
||||
|
||||
find_program(MATLAB_MEX_POSSIBLE_LINK
|
||||
mex
|
||||
PATHS
|
||||
${MATLAB_ROOT}/bin
|
||||
/opt/matlab/bin
|
||||
/usr/local/matlab/bin
|
||||
$ENV{HOME}/matlab/bin
|
||||
# Now all the versions
|
||||
/opt/matlab/[rR]20[0-9][0-9][abAB]/bin
|
||||
/usr/local/matlab/[rR]20[0-9][0-9][abAB]/bin
|
||||
/opt/matlab-[rR]20[0-9][0-9][abAB]/bin
|
||||
/opt/matlab_[rR]20[0-9][0-9][abAB]/bin
|
||||
/usr/local/matlab-[rR]20[0-9][0-9][abAB]/bin
|
||||
/usr/local/matlab_[rR]20[0-9][0-9][abAB]/bin
|
||||
$ENV{HOME}/matlab/[rR]20[0-9][0-9][abAB]/bin
|
||||
$ENV{HOME}/matlab-[rR]20[0-9][0-9][abAB]/bin
|
||||
$ENV{HOME}/matlab_[rR]20[0-9][0-9][abAB]/bin
|
||||
)
|
||||
|
||||
get_filename_component(MATLAB_MEX "${MATLAB_MEX_POSSIBLE_LINK}" REALPATH)
|
||||
get_filename_component(MATLAB_BIN_ROOT "${MATLAB_MEX}" PATH)
|
||||
# Strip ./bin/.
|
||||
get_filename_component(MATLAB_ROOT "${MATLAB_BIN_ROOT}" PATH)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(NOT EXISTS "${MATLAB_MEX}" AND "${MatlabMex_FIND_REQUIRED}")
|
||||
message(FATAL_ERROR "Could not find MATLAB mex compiler; try specifying MATLAB_ROOT.")
|
||||
else()
|
||||
if(EXISTS "${MATLAB_MEX}")
|
||||
message(STATUS "Found MATLAB mex compiler: ${MATLAB_MEX}")
|
||||
message(STATUS "MATLAB root: ${MATLAB_ROOT}")
|
||||
set(MATLABMEX_FOUND 1)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
mark_as_advanced(
|
||||
MATLAB_MEX
|
||||
MATLABMEX_FOUND
|
||||
MATLAB_ROOT
|
||||
)
|
||||
|
||||
@@ -1,135 +0,0 @@
|
||||
#!/bin/bash
|
||||
# This script gets the test coverage for mlpack_test.
|
||||
test_case="ALL"
|
||||
gcov_loc=""
|
||||
token=""
|
||||
clean=true
|
||||
current_log_file=`date +'%Y.%h.%d:%H:%M:%S-coverage.log'`
|
||||
current_coverage_file=`date +'%Y.%h.%d:%H:%M:%S-coverage.info'`
|
||||
max_cov_count=50000
|
||||
|
||||
# default directories
|
||||
root_dir="../"
|
||||
|
||||
# Extract arguments.
|
||||
for i in "$@"
|
||||
do
|
||||
case $i in
|
||||
-h|--help)
|
||||
echo "Usage: mlpack_coverage --help|-h"
|
||||
echo " mlpack_coverage [-r=test_suite] [-g=gcov_tool_location]"
|
||||
echo " [--token=coveralls_token]"
|
||||
echo "Optional parameters:"
|
||||
echo " -n|--no_test Do not run test before coverage computation"
|
||||
echo " -r|--run_test Run tests with specific test suite"
|
||||
echo " --no_clean Do not remove existing gcda file"
|
||||
echo " -g|--gcov_tool_location Gcov location if not default"
|
||||
echo " -t|--token Upload to coveralls with given token"
|
||||
echo " --max_cov_count Max line coverage count (default 50000)"
|
||||
echo " --root_dir Set the root directory from which gcov will be called. (default ../)"
|
||||
exit 0
|
||||
shift
|
||||
;;
|
||||
-n|--no_test)
|
||||
test_case=""
|
||||
shift
|
||||
;;
|
||||
-r=*|--run_test=*)
|
||||
test_case="${i#*=}"
|
||||
shift # past argument=value
|
||||
;;
|
||||
--no_clean)
|
||||
clean=false
|
||||
shift
|
||||
;;
|
||||
-g=*|--gcov_tool_location=*)
|
||||
gcov_loc="${i#*=}"
|
||||
shift # past argument=value
|
||||
;;
|
||||
-t=*|--token=*)
|
||||
token="${i#*=}"
|
||||
shift # past argument=value
|
||||
;;
|
||||
--max_cov_count)
|
||||
max_cov_count="${i#*=}"
|
||||
shift
|
||||
;;
|
||||
--root_dir=*)
|
||||
root_dir="${i#*=}"
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
# unknown option
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ "$clean" = true ]; then
|
||||
echo "Deleting existing coverage data..."
|
||||
find ./ -name "*.gcda" -type f -delete
|
||||
fi
|
||||
|
||||
# Initial pass.
|
||||
echo "Generating primary coverage report."
|
||||
[[ -d ./coveragehistory/ ]] || mkdir coveragehistory
|
||||
lcov -b . -c -i -d ./ -o .coverage.wtest.base > ./coveragehistory/$current_log_file
|
||||
|
||||
# Run the tests.
|
||||
if [ "$test_case" = "ALL" ]; then
|
||||
echo "Running all the tests..."
|
||||
"@CMAKE_BINARY_DIR@"/bin/mlpack_test
|
||||
elif ! [ "$test_case" = "" ]; then
|
||||
echo "Running test suite: $test_case"
|
||||
"@CMAKE_BINARY_DIR@"/bin/mlpack_test --run_test=$test_case
|
||||
fi
|
||||
|
||||
# Generate coverage based on executed tests.
|
||||
echo "Computing coverage..."
|
||||
if [ "$gcov_loc" = "" ];
|
||||
then lcov -b . -c -d ./ -o .coverage.wtest.run >> ./coveragehistory/$current_log_file
|
||||
else
|
||||
lcov -b . -c -d ./ -o .coverage.wtest.run --gcov-tool=$gcov_loc >> ./coveragehistory/$current_log_file
|
||||
fi
|
||||
|
||||
echo "Filtering coverage files..."
|
||||
# Clear negative entries in coverage file
|
||||
sed -E 's/-([0-9]+)/$max_cov_count/g' -i .coverage.wtest.run
|
||||
# Merge coverage tracefiles.
|
||||
lcov -a .coverage.wtest.base -a .coverage.wtest.run -o .coverage.total >> ./coveragehistory/$current_log_file
|
||||
|
||||
# Filtering, extracting project files.
|
||||
lcov -e .coverage.total "@CMAKE_CURRENT_SOURCE_DIR@/src/mlpack/*" -o .coverage.total.filtered >> ./coveragehistory/$current_log_file
|
||||
|
||||
# Filtering, removing test-files and main.cpp.
|
||||
lcov -r .coverage.total.filtered "@CMAKE_CURRENT_SOURCE_DIR@/src/mlpack/*/*_main.cpp" -o .coverage.total.filtered >> ./coveragehistory/$current_log_file
|
||||
lcov -r .coverage.total.filtered "@CMAKE_CURRENT_SOURCE_DIR@/src/mlpack/tests/*" -o .coverage.total.filtered >> ./coveragehistory/$current_log_file
|
||||
|
||||
# Remove untestable files.
|
||||
lcov -r .coverage.total.filtered "@CMAKE_CURRENT_SOURCE_DIR@/src/mlpack/core/util/gitversion.hpp" -o .coverage.total.filtered >> ./coveragehistory/$current_log_file
|
||||
lcov -r .coverage.total.filtered "@CMAKE_CURRENT_SOURCE_DIR@/src/mlpack/core/util/arma_config.hpp" -o .coverage.total.filtered >> ./coveragehistory/$current_log_file
|
||||
|
||||
# Extra: Replace /build/ with /src/ to unify directories.
|
||||
cat .coverage.total.filtered > .coverage.total
|
||||
|
||||
# Extra: Clear up previous data, create html folder.
|
||||
if [[ -d ./coverage/ ]] ; then
|
||||
rm -rf ./coverage/*
|
||||
else
|
||||
mkdir coverage
|
||||
fi
|
||||
|
||||
# Step 9: Generate webpage.
|
||||
genhtml -o ./coverage/ .coverage.total
|
||||
|
||||
# Extra: Preserve coverage file in coveragehistory folder.
|
||||
coverage_file=$current_coverage_file
|
||||
cp .coverage.total ./coveragehistory/$current_coverage_file
|
||||
|
||||
# Clean temporary coverage files.
|
||||
#rm .coverage.*
|
||||
|
||||
# Upload the result to coveralls if token is provided.
|
||||
if ! [ "$token" = "" ]; then
|
||||
cpp-coveralls -n -r $root_dir -b $root_dir -l ./coveragehistory/$current_coverage_file -t "$token" --max-cov-count $max_cov_count
|
||||
fi
|
||||
|
||||
+3
-35
@@ -9,7 +9,6 @@ include(CMake/CheckHash.cmake)
|
||||
option(DEBUG "Compile with debugging information." OFF)
|
||||
option(PROFILE "Compile with profiling information." OFF)
|
||||
option(ARMA_EXTRA_DEBUG "Compile with extra Armadillo debugging symbols." OFF)
|
||||
option(MATLAB_BINDINGS "Compile MATLAB bindings if MATLAB is found." OFF)
|
||||
option(TEST_VERBOSE "Run test cases with verbose output." OFF)
|
||||
option(BUILD_TESTS "Build tests." ON)
|
||||
option(BUILD_CLI_EXECUTABLES "Build command-line executables." ON)
|
||||
@@ -80,8 +79,6 @@ option(BUILD_R_BINDINGS "Build R bindings." OFF)
|
||||
# generation.
|
||||
option(BUILD_MARKDOWN_BINDINGS "Build Markdown bindings for website documentation." OFF)
|
||||
|
||||
option(BUILD_WITH_COVERAGE
|
||||
"Build with support for code coverage tools (gcc only)." OFF)
|
||||
option(MATHJAX
|
||||
"Use MathJax for HTML Doxygen output (disabled by default)." OFF)
|
||||
option(FORCE_CXX11
|
||||
@@ -196,38 +193,6 @@ if(CMAKE_COMPILER_IS_GNUCC)
|
||||
${CMAKE_THREAD_LIBS_INIT})
|
||||
endif()
|
||||
|
||||
# Setup build for test coverage
|
||||
if(BUILD_WITH_COVERAGE)
|
||||
# Currently coverage only works with GNU g++.
|
||||
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
|
||||
# Find gcov and lcov
|
||||
find_program(GCOV gcov)
|
||||
find_program(LCOV lcov)
|
||||
|
||||
if(NOT GCOV)
|
||||
message(FATAL_ERROR
|
||||
"gcov not found! gcov is required when BUILD_WITH_COVERAGE=ON.")
|
||||
endif()
|
||||
|
||||
set(MLPACK_LIBRARIES ${MLPACK_LIBRARIES} "supc++")
|
||||
set(MLPACK_LIBRARIES ${MLPACK_LIBRARIES} "quadmath")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --coverage -fno-inline -fno-inline-small-functions -fno-default-inline -fprofile-arcs -fkeep-inline-functions")
|
||||
message(STATUS "Adding debug compile options for code coverage.")
|
||||
# Remove optimizations for better line coverage
|
||||
set(DEBUG ON)
|
||||
|
||||
if(LCOV)
|
||||
configure_file(CMake/mlpack_coverage.in mlpack_coverage @ONLY)
|
||||
add_custom_target(mlpack_coverage DEPENDS mlpack_test COMMAND ${PROJECT_BINARY_DIR}/mlpack_coverage)
|
||||
else()
|
||||
message(WARNING "'lcov' not found; local coverage report is disabled. "
|
||||
"Install 'lcov' and rerun cmake to generate local coverage report.")
|
||||
endif()
|
||||
else()
|
||||
message(FATAL_ERROR "BUILD_WITH_COVERAGE can only work with GNU environment.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Debugging CFLAGS. Turn optimizations off; turn debugging symbols on.
|
||||
if(DEBUG)
|
||||
if (NOT MSVC)
|
||||
@@ -467,6 +432,9 @@ 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)
|
||||
set(MLPACK_LIBRARIES ${MLPACK_LIBRARIES} ${OpenMP_CXX_LIBRARIES})
|
||||
endif ()
|
||||
else ()
|
||||
# Disable warnings for all the unknown OpenMP pragmas.
|
||||
if (NOT MSVC)
|
||||
|
||||
+2
-1
@@ -7,7 +7,7 @@ Source:
|
||||
|
||||
Files: *
|
||||
Copyright:
|
||||
Copyright 2008-2020, Ryan Curtin <ryan@ratml.org>
|
||||
Copyright 2008-2021, Ryan Curtin <ryan@ratml.org>
|
||||
Copyright 2008-2013, Bill March <march@gatech.edu>
|
||||
Copyright 2008-2012, Dongryeol Lee <dongryel@cc.gatech.edu>
|
||||
Copyright 2008-2013, Nishant Mehta <niche@cc.gatech.edu>
|
||||
@@ -141,6 +141,7 @@ Copyright:
|
||||
Copyright 2020, Alex Nguyen <alexvn.edu@gmail.com>
|
||||
Copyright 2020, Gaurav Ghati <gauravghatii@gmail.com>
|
||||
Copyright 2020, Anmolpreet Singh <anmol323c@gmail.com>
|
||||
Copyright 2021, Tru Hoang <trugiahoang@gmail.com>
|
||||
|
||||
License: BSD-3-clause
|
||||
All rights reserved.
|
||||
|
||||
+22
-2
@@ -1,5 +1,10 @@
|
||||
### mlpack ?.?.?
|
||||
###### ????-??-??
|
||||
* Added Pixel Shuffle layer (#2563).
|
||||
|
||||
* Add "check_input_matrices" option to python bindings that checks
|
||||
for NaN and inf values in all the input matrices (#2787).
|
||||
|
||||
* Add Adjusted R squared functionality to R2Score::Evaluate (#2624).
|
||||
|
||||
* Disabled all the bindings by default in CMake (#2782).
|
||||
@@ -12,10 +17,26 @@
|
||||
* Add Triplet Margin Loss function (#2762).
|
||||
|
||||
* Add finalizers to Julia binding model types to fix memory handling (#2756).
|
||||
|
||||
|
||||
* HMM: add functions to calculate likelihood for data stream with/without
|
||||
pre-calculated emission probability (#2142).
|
||||
|
||||
* Replace Boost serialization library with Cereal (#2458).
|
||||
|
||||
* Add `PYTHON_INSTALL_PREFIX` CMake option to specify installation root for
|
||||
Python bindings (#2797).
|
||||
|
||||
* Removed `boost::visitor` from model classes for `knn`, `kfn`, `cf`,
|
||||
`range_search`, `krann`, and `kde` bindings (#2803).
|
||||
|
||||
* Add k-means++ initialization strategy (#2813).
|
||||
|
||||
* `NegativeLogLikelihood<>` now expects classes in the range `0` to
|
||||
`numClasses - 1` (#2534).
|
||||
|
||||
* Add `Lambda1()`, `Lambda2()`, `UseCholesky()`, and `Tolerance()` members to
|
||||
`LARS` so parameters for training can be modified (#2861).
|
||||
|
||||
### mlpack 3.4.2
|
||||
###### 2020-10-26
|
||||
* Added Mean Absolute Percentage Error.
|
||||
@@ -36,7 +57,6 @@
|
||||
|
||||
### mlpack 3.4.0
|
||||
###### 2020-09-01
|
||||
|
||||
* Issue warnings when metrics produce NaNs in KFoldCV (#2595).
|
||||
|
||||
* Added bindings for _R_ during Google Summer of Code (#2556).
|
||||
|
||||
@@ -15,7 +15,6 @@ src="https://cdn.rawgit.com/mlpack/mlpack.org/e7d36ed8/mlpack-black.svg" style="
|
||||
|
||||
<p align="center">
|
||||
<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>
|
||||
@@ -203,6 +202,7 @@ Options are specified with the -D flag. The allowed options include:
|
||||
BUILD_CLI_EXECUTABLES=(ON/OFF): whether or not to build command-line programs
|
||||
BUILD_PYTHON_BINDINGS=(ON/OFF): whether or not to build Python bindings
|
||||
PYTHON_EXECUTABLE=(/path/to/python_version): Path to specific Python executable
|
||||
PYTHON_INSTALL_PREFIX=(/path/to/python/): Path to root of Python installation
|
||||
BUILD_JULIA_BINDINGS=(ON/OFF): whether or not to build Julia bindings
|
||||
JULIA_EXECUTABLE=(/path/to/julia): Path to specific Julia executable
|
||||
BUILD_GO_BINDINGS=(ON/OFF): whether or not to build Go bindings
|
||||
|
||||
+7
-4
@@ -175,9 +175,13 @@ The full list of options mlpack allows:
|
||||
(i.e. \c mlpack_knn, \c mlpack_kfn, \c mlpack_logistic_regression, etc.)
|
||||
(default ON)
|
||||
- BUILD_PYTHON_BINDINGS=(ON/OFF): compile the bindings for Python, if the
|
||||
necessary Python libraries are available (default ON except on Windows)
|
||||
necessary Python libraries are available (default OFF)
|
||||
- BUILD_R_BINDINGS=(ON/OFF): compile the bindings for R, if R is found
|
||||
(default OFF)
|
||||
- BUILD_GO_BINDINGS=(ON/OFF): compile Go bindings, if Go and the necessary Go
|
||||
and Gonum exist. (default OFF)
|
||||
- BUILD_JULIA_BINDINGS=(ON/OFF): compile Julia bindings, if Julia is found
|
||||
(default ON)
|
||||
(default OFF)
|
||||
- BUILD_SHARED_LIBS=(ON/OFF): compile shared libraries as opposed to
|
||||
static libraries (default ON)
|
||||
- TEST_VERBOSE=(ON/OFF): run test cases in \c mlpack_test with verbose output
|
||||
@@ -187,9 +191,8 @@ The full list of options mlpack allows:
|
||||
- DOWNLOAD_ENSMALLEN=(ON/OFF): If ensmallen is not found, download it
|
||||
(default ON)
|
||||
- DOWNLOAD_STB_IMAGE=(ON/OFF): If STB is not found, download it (default ON)
|
||||
- BUILD_WITH_COVERAGE=(ON/OFF): Build with support for code coverage tools
|
||||
(gcc only) (default OFF)
|
||||
- PYTHON_EXECUTABLE=(/path/to/python_version): Path to specific Python executable
|
||||
- PYTHON_INSTALL_PREFIX=(/path/to/python/): Path to root of Python installation
|
||||
- JULIA_EXECUTABLE=(/path/to/julia): Path to specific Julia executable
|
||||
- BUILD_MARKDOWN_BINDINGS=(ON/OFF): Build Markdown bindings for website
|
||||
documentation (default OFF)
|
||||
|
||||
@@ -210,8 +210,9 @@ int main()
|
||||
data::Load("thyroid_test.csv", testData, true);
|
||||
|
||||
// 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);
|
||||
// Decrement the labels by 1, so they are in the range 0 to (numClasses - 1).
|
||||
arma::mat trainLabels = trainData.row(trainData.n_rows - 1) - 1;
|
||||
arma::mat testLabels = testData.row(testData.n_rows - 1) - 1;
|
||||
trainData.shed_row(trainData.n_rows - 1);
|
||||
testData.shed_row(testData.n_rows - 1);
|
||||
|
||||
@@ -246,9 +247,8 @@ int main()
|
||||
// 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;
|
||||
arma::max(predictionTemp.col(i)) == predictionTemp.col(i), 1));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -311,7 +311,7 @@ void RNNModel()
|
||||
for (size_t i = 0; i < labelsTemp.n_cols; ++i)
|
||||
{
|
||||
const int value = arma::as_scalar(arma::find(
|
||||
arma::max(labelsTemp.col(i)) == labelsTemp.col(i), 1)) + 1;
|
||||
arma::max(labelsTemp.col(i)) == labelsTemp.col(i), 1));
|
||||
labels.col(i).fill(value);
|
||||
}
|
||||
|
||||
@@ -589,8 +589,9 @@ arma::mat trainData = dataset.submat(0, 0, dataset.n_rows - 4,
|
||||
dataset.n_cols - 1);
|
||||
|
||||
// Split the data from the training set.
|
||||
// Subtract 1 so the labels are the range from 0 to (numClasses - 1).
|
||||
arma::mat trainLabels = dataset.submat(dataset.n_rows - 3, 0,
|
||||
dataset.n_rows - 1, dataset.n_cols - 1);
|
||||
dataset.n_rows - 1, dataset.n_cols - 1) - 1;
|
||||
|
||||
// Initialize the network.
|
||||
FFN<> model;
|
||||
|
||||
@@ -87,6 +87,93 @@ if (BUILD_R_BINDINGS)
|
||||
|
||||
string(TIMESTAMP PACKAGE_DATE "%Y-%m-%d")
|
||||
|
||||
# We need to generate an Authors@R list using every single contributor in
|
||||
# COPYRIGHT.txt. That takes a little bit of processing.
|
||||
file(READ "${CMAKE_SOURCE_DIR}/COPYRIGHT.txt" COPYRIGHT_TXT_CONTENTS)
|
||||
string(REGEX MATCHALL " Copyright [0-9-]*, ([^\n]*)\n" CONTRIBUTORS_LIST
|
||||
"${COPYRIGHT_TXT_CONTENTS}")
|
||||
|
||||
# These are the authors meant to be listed as 'authors' and not
|
||||
# 'contributors'. If you contributed specifically to the R bindings, you
|
||||
# should probably be listed here, so if you're not, open a PR to fix it! :)
|
||||
set(SPECIAL_AUTHORS "Yashwant Singh Parihar" "Ryan Curtin" "Dirk Eddelbuettel"
|
||||
"James Balamuta")
|
||||
|
||||
string(CONCAT AUTHORS_R "c(\n"
|
||||
" person(\"Yashwant\", \"Singh Parihar\", "
|
||||
"email = \"yashwantsingh.sngh@gmail.com\", "
|
||||
"role = c(\"aut\", \"ctb\", \"cph\")),\n"
|
||||
" person(\"Ryan\", \"Curtin\", email = \"ryan@ratml.org\", "
|
||||
"role = c(\"aut\", \"ctb\", \"cph\", \"cre\")),\n"
|
||||
" person(\"Dirk\", \"Eddelbuettel\", email = \"edd@debian.org\", "
|
||||
"role = c(\"aut\", \"ctb\", \"cph\")),\n"
|
||||
" person(\"James\", \"Balamuta\", "
|
||||
"email = \"james.balamuta@gmail.com\", "
|
||||
"role = c(\"aut\", \"ctb\", \"cph\")),")
|
||||
foreach (CONTRIBUTOR_LINE ${CONTRIBUTORS_LIST})
|
||||
# Strip 'Copyright XXXX-YYYY, '.
|
||||
string(REGEX REPLACE "^ Copyright [0-9-]*, (.*)\n$" "\\1"
|
||||
CONTRIBUTOR_FILTERED "${CONTRIBUTOR_LINE}")
|
||||
|
||||
# Extract the email if it exists.
|
||||
string(REGEX MATCH "^[^<]*<(.*)>.*$" HAS_EMAIL "${CONTRIBUTOR_FILTERED}")
|
||||
|
||||
# The first name is just the first space-delimited word. (That may not
|
||||
# always be right, but we have no way to know what is a first name and last
|
||||
# name and therefore must assume.)
|
||||
string(REGEX REPLACE "^([^ ]*) .*$" "\\1" CONTRIBUTOR_FIRST_NAME
|
||||
"${CONTRIBUTOR_FILTERED}")
|
||||
|
||||
# Extracting the last name is just the rest of the tokens, but the regex is
|
||||
# different depending on whether we managed to get an email.
|
||||
if (HAS_EMAIL)
|
||||
string(REGEX REPLACE "^[^<]*<(.*)>.*$" "\\1" CONTRIBUTOR_EMAIL
|
||||
"${CONTRIBUTOR_FILTERED}")
|
||||
string(REGEX MATCH "^[^ ]* (.*) <.*$" CONTRIBUTOR_LAST_NAME
|
||||
"${CONTRIBUTOR_FILTERED}")
|
||||
if (NOT CONTRIBUTOR_LAST_NAME)
|
||||
set (CONTRIBUTOR_LAST_NAME "")
|
||||
else ()
|
||||
string(REGEX REPLACE "^[^ ]* (.*) <.*$" "\\1" CONTRIBUTOR_LAST_NAME
|
||||
"${CONTRIBUTOR_FILTERED}")
|
||||
endif ()
|
||||
|
||||
# Skip anyone already listed as an author.
|
||||
if ("${CONTRIBUTOR_FIRST_NAME} ${CONTRIBUTOR_LAST_NAME}" IN_LIST
|
||||
SPECIAL_AUTHORS)
|
||||
continue()
|
||||
endif ()
|
||||
|
||||
string(CONCAT AUTHORS_R "${AUTHORS_R}\n "
|
||||
"person(\"${CONTRIBUTOR_FIRST_NAME}\", \"${CONTRIBUTOR_LAST_NAME}\", "
|
||||
"email = \"${CONTRIBUTOR_EMAIL}\", role = c(\"ctb\", \"cph\")),")
|
||||
|
||||
else ()
|
||||
# No email is available. So just get the last name.
|
||||
string(REGEX MATCH "^[^ ]* (.*)$" CONTRIBUTOR_LAST_NAME
|
||||
"${CONTRIBUTOR_FILTERED}")
|
||||
if (NOT CONTRIBUTOR_LAST_NAME)
|
||||
set (CONTRIBUTOR_LAST_NAME "")
|
||||
else ()
|
||||
string(REGEX REPLACE "^[^ ]* (.*)$" "\\1" CONTRIBUTOR_LAST_NAME
|
||||
"${CONTRIBUTOR_FILTERED}")
|
||||
endif ()
|
||||
|
||||
# Skip anyone already listed as an author.
|
||||
if ("${CONTRIBUTOR_FIRST_NAME} ${CONTRIBUTOR_LAST_NAME}" IN_LIST
|
||||
SPECIAL_AUTHORS)
|
||||
continue()
|
||||
endif ()
|
||||
|
||||
string(CONCAT AUTHORS_R "${AUTHORS_R}\n "
|
||||
"person(\"${CONTRIBUTOR_FIRST_NAME}\", \"${CONTRIBUTOR_LAST_NAME}\", "
|
||||
"role = c(\"ctb\", \"cph\")),")
|
||||
endif ()
|
||||
endforeach ()
|
||||
# We also have to remove the final comma...
|
||||
string(REGEX REPLACE ",$" "" AUTHORS_R_OUT "${AUTHORS_R}")
|
||||
set(AUTHORS_R "${AUTHORS_R_OUT})")
|
||||
|
||||
configure_file(${CMAKE_SOURCE_DIR}/src/mlpack/bindings/R/mlpack/DESCRIPTION.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/mlpack/DESCRIPTION
|
||||
@ONLY)
|
||||
@@ -136,9 +223,11 @@ if (BUILD_R_BINDINGS)
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/mlpack/tests/testthat.R"
|
||||
)
|
||||
|
||||
set(LICENSE_SOURCES
|
||||
"${CMAKE_SOURCE_DIR}/LICENSE.txt"
|
||||
)
|
||||
# Configure the license file.
|
||||
string(TIMESTAMP LICENSE_YEAR "%Y")
|
||||
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/mlpack/LICENSE.in"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/mlpack/LICENSE")
|
||||
|
||||
add_custom_target(r_copy ALL)
|
||||
|
||||
# First we have to create all the required directories for copy.
|
||||
@@ -160,22 +249,22 @@ if (BUILD_R_BINDINGS)
|
||||
|
||||
# Copy all necessary files for building package.
|
||||
foreach(cpp_file ${CPP_SOURCES})
|
||||
add_custom_command(TARGET r_copy PRE_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different
|
||||
${cpp_file}
|
||||
${CMAKE_CURRENT_BINARY_DIR}/mlpack/src/)
|
||||
add_custom_command(TARGET r_copy PRE_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different
|
||||
${cpp_file}
|
||||
${CMAKE_CURRENT_BINARY_DIR}/mlpack/src/)
|
||||
endforeach()
|
||||
foreach(r_file ${R_SOURCES})
|
||||
add_custom_command(TARGET r_copy PRE_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different
|
||||
${r_file}
|
||||
${CMAKE_CURRENT_BINARY_DIR}/mlpack/R/)
|
||||
add_custom_command(TARGET r_copy PRE_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different
|
||||
${r_file}
|
||||
${CMAKE_CURRENT_BINARY_DIR}/mlpack/R/)
|
||||
endforeach()
|
||||
foreach(bindings_file ${BINDINGS_SOURCES})
|
||||
add_custom_command(TARGET r_copy PRE_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different
|
||||
${bindings_file}
|
||||
${CMAKE_CURRENT_BINARY_DIR}/mlpack/src/mlpack/bindings/R)
|
||||
add_custom_command(TARGET r_copy PRE_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different
|
||||
${bindings_file}
|
||||
${CMAKE_CURRENT_BINARY_DIR}/mlpack/src/mlpack/bindings/R)
|
||||
endforeach()
|
||||
add_custom_command(TARGET r_copy PRE_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different
|
||||
@@ -185,14 +274,6 @@ if (BUILD_R_BINDINGS)
|
||||
COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different
|
||||
${R_TESTS_SOURCES}
|
||||
${CMAKE_CURRENT_BINARY_DIR}/mlpack/tests)
|
||||
add_custom_command(TARGET r_copy PRE_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different
|
||||
${LICENSE_SOURCES}
|
||||
${CMAKE_CURRENT_BINARY_DIR}/mlpack)
|
||||
add_custom_command(TARGET r_copy PRE_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} ARGS -E rename
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/mlpack/LICENSE.txt"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/mlpack/LICENSE")
|
||||
# This file will take care of multiple definition of functions in .cpp files.
|
||||
add_custom_command(TARGET r_copy PRE_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} ARGS -E touch
|
||||
@@ -234,8 +315,8 @@ if (BUILD_R_BINDINGS)
|
||||
# Installation script for the packagae.
|
||||
install(CODE
|
||||
"execute_process(
|
||||
COMMAND R CMD INSTALL mlpack_${PACKAGE_VERSION}.tar.gz
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}"
|
||||
COMMAND ${R_EXECUTABLE} CMD INSTALL mlpack_${PACKAGE_VERSION}.tar.gz
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})"
|
||||
)
|
||||
|
||||
add_dependencies(R r_build)
|
||||
|
||||
@@ -2,11 +2,11 @@ Package: mlpack
|
||||
Title: 'Rcpp' Integration for the 'mlpack' Library
|
||||
Version: @PACKAGE_VERSION@
|
||||
Date: @PACKAGE_DATE@
|
||||
Author: mlpack Team
|
||||
Maintainer: Ryan Curtin <ryan@ratml.org>
|
||||
Description: 'mlpack' is a fast, flexible machine learning library, written
|
||||
in C++, that aims to provide fast, extensible implementations of
|
||||
cutting-edge machine learning algorithms.
|
||||
Authors@R: @AUTHORS_R@
|
||||
Description: A fast, flexible machine learning library, written in C++, that
|
||||
aims to provide fast, extensible implementations of cutting-edge
|
||||
machine learning algorithms. See also Curtin et al. (2018)
|
||||
<doi:10.21105/joss.00726>.
|
||||
SystemRequirements: A C++11 compiler. Versions 4.8.*, 4.9.* or later of GCC
|
||||
will be fine.
|
||||
License: BSD_3_clause + file LICENSE
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
YEAR: ${LICENSE_YEAR}
|
||||
COPYRIGHT HOLDER: mlpack Team
|
||||
ORGANIZATION: mlpack
|
||||
@@ -84,7 +84,7 @@ std::string PrintTypeDoc(
|
||||
*/
|
||||
template<typename T>
|
||||
std::string PrintTypeDoc(
|
||||
util::ParamData& data,
|
||||
util::ParamData& /* data */,
|
||||
const typename std::enable_if<arma::is_arma_type<T>::value>::type*)
|
||||
{
|
||||
if (T::is_col || T::is_row)
|
||||
|
||||
@@ -36,8 +36,18 @@ void PrintHeaders(const std::string& bindingName,
|
||||
{
|
||||
BindingInfo::Language() = languages[i];
|
||||
|
||||
cout << " - [" << GetBindingName(bindingName) << "](#" << languages[i]
|
||||
<< "_" << bindingName << "){: .language-link #" << languages[i] << " }"
|
||||
// Get the name of the binding in the target language, and convert it to
|
||||
// lowercase (since the anchor link will be in lowercase).
|
||||
const std::string langBindingName = GetBindingName(bindingName);
|
||||
std::string anchorName = langBindingName;
|
||||
std::transform(anchorName.begin(), anchorName.end(), anchorName.begin(),
|
||||
[](unsigned char c) { return std::tolower(c); });
|
||||
// Strip '()' from the end if needed.
|
||||
if (anchorName.substr(anchorName.size() - 2, 2) == "()")
|
||||
anchorName = anchorName.substr(0, anchorName.size() - 2);
|
||||
|
||||
cout << " - [" << langBindingName << "](#" << languages[i]
|
||||
<< "_" << anchorName << "){: .language-link #" << languages[i] << " }"
|
||||
<< endl;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -214,14 +214,20 @@ add_custom_command(TARGET python POST_BUILD
|
||||
add_dependencies(python python_configured)
|
||||
|
||||
# Configure installation script file.
|
||||
if (NOT PYTHON_INSTALL_PREFIX)
|
||||
set(PYTHON_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}")
|
||||
endif ()
|
||||
|
||||
execute_process(COMMAND ${PYTHON_EXECUTABLE}
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/print_python_version.py" "${CMAKE_INSTALL_PREFIX}"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/print_python_version.py"
|
||||
"${PYTHON_INSTALL_PREFIX}"
|
||||
OUTPUT_VARIABLE CMAKE_PYTHON_PATH)
|
||||
string(STRIP "${CMAKE_PYTHON_PATH}" CMAKE_PYTHON_PATH)
|
||||
install(CODE "set(ENV{PYTHONPATH} ${CMAKE_PYTHON_PATH})")
|
||||
install(CODE "set(PYTHON_EXECUTABLE \"${PYTHON_EXECUTABLE}\")")
|
||||
install(CODE "set(CMAKE_BINARY_DIR \"${CMAKE_BINARY_DIR}\")")
|
||||
install(CODE "set(CMAKE_INSTALL_PREFIX \"${CMAKE_INSTALL_PREFIX}\")")
|
||||
|
||||
install(CODE "set(PYTHON_INSTALL_PREFIX \"${PYTHON_INSTALL_PREFIX}\")")
|
||||
install(CODE "execute_process(COMMAND mkdir -p $ENV{DESTDIR}${CMAKE_PYTHON_PATH})")
|
||||
install(SCRIPT "${CMAKE_CURRENT_SOURCE_DIR}/PythonInstall.cmake")
|
||||
|
||||
|
||||
@@ -5,13 +5,13 @@
|
||||
if (DEFINED ENV{DESTDIR})
|
||||
execute_process(COMMAND ${PYTHON_EXECUTABLE}
|
||||
"${CMAKE_BINARY_DIR}/src/mlpack/bindings/python/setup.py" install
|
||||
--prefix=${CMAKE_INSTALL_PREFIX} --root=$ENV{DESTDIR}
|
||||
--prefix=${PYTHON_INSTALL_PREFIX} --root=$ENV{DESTDIR}
|
||||
WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/src/mlpack/bindings/python/"
|
||||
RESULT_VARIABLE setup_res)
|
||||
else ()
|
||||
execute_process(COMMAND ${PYTHON_EXECUTABLE}
|
||||
"${CMAKE_BINARY_DIR}/src/mlpack/bindings/python/setup.py" install
|
||||
--prefix=${CMAKE_INSTALL_PREFIX}
|
||||
--prefix=${PYTHON_INSTALL_PREFIX}
|
||||
WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/src/mlpack/bindings/python/"
|
||||
RESULT_VARIABLE setup_res)
|
||||
endif ()
|
||||
|
||||
@@ -38,6 +38,9 @@ cdef extern from "<mlpack/core/util/io.hpp>" namespace "mlpack" nogil:
|
||||
@staticmethod
|
||||
void ClearSettings() nogil except +
|
||||
|
||||
@staticmethod
|
||||
void CheckInputMatrices() nogil except +
|
||||
|
||||
cdef extern from "<mlpack/bindings/python/mlpack/io_util.hpp>" \
|
||||
namespace "mlpack::util" nogil:
|
||||
void SetParam[T](string, T&) nogil except +
|
||||
|
||||
@@ -224,6 +224,16 @@ void PrintPYX(const util::BindingDetails& doc,
|
||||
cout << " IO.SetPassed(<const string> '" << d.name << "')" << endl;
|
||||
}
|
||||
|
||||
// Checking the type of check_input_matrices parameter.
|
||||
cout << " if not isinstance(check_input_matrices, bool):" << endl;
|
||||
cout << " raise TypeError(" <<"\"'check_input_matrices\' must have type "
|
||||
<< "\'bool'!\")" << endl;
|
||||
cout << endl;
|
||||
|
||||
// Before calling mlpackMain(), we check input matrices for NaN values if needed.
|
||||
cout << " if check_input_matrices:" << endl;
|
||||
cout << " IO.CheckInputMatrices()" << endl;
|
||||
|
||||
// Call the method.
|
||||
cout << " # Call the mlpack program." << endl;
|
||||
cout << " mlpackMain()" << endl;
|
||||
|
||||
@@ -64,8 +64,10 @@ class PyOption
|
||||
data.required = required;
|
||||
data.input = input;
|
||||
data.loaded = false;
|
||||
// Only "verbose" and "copy_all_inputs" will be persistent.
|
||||
if (identifier == "verbose" || identifier == "copy_all_inputs")
|
||||
// Only "verbose", "copy_all_inputs" and "check_input_matrices"
|
||||
// will be persistent.
|
||||
if (identifier == "verbose" || identifier == "copy_all_inputs" ||
|
||||
identifier == "check_input_matrices")
|
||||
data.persistent = true;
|
||||
else
|
||||
data.persistent = false;
|
||||
|
||||
@@ -1336,5 +1336,101 @@ class TestPythonBinding(unittest.TestCase):
|
||||
self.assertEqual(output2['model_bw_out'], 20.0)
|
||||
self.assertEqual(output3['model_bw_out'], 20.0)
|
||||
|
||||
def testCheckInputMatricesNaN(self):
|
||||
"""
|
||||
Checks that an exception is thrown if the input matrix contains
|
||||
NaN values.
|
||||
"""
|
||||
x = np.random.rand(100, 5)
|
||||
a = np.random.randint(low=0, high=100)
|
||||
b = np.random.randint(low=0, high=5)
|
||||
x[a][b] = np.nan
|
||||
self.assertRaises(RuntimeError,
|
||||
lambda : test_python_binding(string_in="hello",
|
||||
int_in=12,
|
||||
double_in=4.0,
|
||||
mat_req_in=[[1.0]],
|
||||
col_req_in=[1.0],
|
||||
matrix_in=x,
|
||||
check_input_matrices=True))
|
||||
|
||||
x_vec = np.random.rand(100)
|
||||
a = np.random.randint(low=0, high=100)
|
||||
x_vec[a] = np.nan
|
||||
self.assertRaises(RuntimeError,
|
||||
lambda : test_python_binding(string_in="hello",
|
||||
int_in=12,
|
||||
double_in=4.0,
|
||||
mat_req_in=[[1.0]],
|
||||
col_req_in=[1.0],
|
||||
row_in=x_vec,
|
||||
check_input_matrices=True))
|
||||
|
||||
self.assertRaises(RuntimeError,
|
||||
lambda : test_python_binding(string_in="hello",
|
||||
int_in=12,
|
||||
double_in=4.0,
|
||||
mat_req_in=[[1.0]],
|
||||
col_req_in=[1.0],
|
||||
col_in=x_vec,
|
||||
check_input_matrices=True))
|
||||
|
||||
self.assertRaises(RuntimeError,
|
||||
lambda : test_python_binding(string_in="hello",
|
||||
int_in=12,
|
||||
double_in=4.0,
|
||||
mat_req_in=[[1.0]],
|
||||
col_req_in=[1.0],
|
||||
matrix_and_info_in=x,
|
||||
check_input_matrices=True))
|
||||
|
||||
def testCheckInputMatricesInf(self):
|
||||
"""
|
||||
Checks that an exception is thrown if the input matrix contains
|
||||
inf values.
|
||||
"""
|
||||
x = np.random.rand(100, 5)
|
||||
a = np.random.randint(low=0, high=100)
|
||||
b = np.random.randint(low=0, high=5)
|
||||
x[a][b] = np.inf
|
||||
self.assertRaises(RuntimeError,
|
||||
lambda : test_python_binding(string_in="hello",
|
||||
int_in=12,
|
||||
double_in=4.0,
|
||||
mat_req_in=[[1.0]],
|
||||
col_req_in=[1.0],
|
||||
matrix_in=x,
|
||||
check_input_matrices=True))
|
||||
|
||||
x_vec = np.random.rand(100)
|
||||
a = np.random.randint(low=0, high=100)
|
||||
x_vec[a] = np.inf
|
||||
self.assertRaises(RuntimeError,
|
||||
lambda : test_python_binding(string_in="hello",
|
||||
int_in=12,
|
||||
double_in=4.0,
|
||||
mat_req_in=[[1.0]],
|
||||
col_req_in=[1.0],
|
||||
row_in=x_vec,
|
||||
check_input_matrices=True))
|
||||
|
||||
self.assertRaises(RuntimeError,
|
||||
lambda : test_python_binding(string_in="hello",
|
||||
int_in=12,
|
||||
double_in=4.0,
|
||||
mat_req_in=[[1.0]],
|
||||
col_req_in=[1.0],
|
||||
col_in=x_vec,
|
||||
check_input_matrices=True))
|
||||
|
||||
self.assertRaises(RuntimeError,
|
||||
lambda : test_python_binding(string_in="hello",
|
||||
int_in=12,
|
||||
double_in=4.0,
|
||||
mat_req_in=[[1.0]],
|
||||
col_req_in=[1.0],
|
||||
matrix_and_info_in=x,
|
||||
check_input_matrices=True))
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
||||
@@ -89,6 +89,7 @@
|
||||
#include <mlpack/core/dists/gamma_distribution.hpp>
|
||||
#include <mlpack/core/dists/diagonal_gaussian_distribution.hpp>
|
||||
#include <mlpack/core/data/confusion_matrix.hpp>
|
||||
#include <mlpack/core/data/one_hot_encoding.hpp>
|
||||
|
||||
// mlpack::backtrace only for linux
|
||||
#ifdef HAS_BFD_DL
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
#ifndef MLPACK_CORE_CV_CV_BASE_IMPL_HPP
|
||||
#define MLPACK_CORE_CV_CV_BASE_IMPL_HPP
|
||||
|
||||
#include <mlpack/prereqs.hpp>
|
||||
|
||||
namespace mlpack {
|
||||
namespace cv {
|
||||
|
||||
@@ -106,14 +108,8 @@ void CVBase<MLAlgorithm,
|
||||
WeightsType>::AssertDataConsistency(const MatType& xs,
|
||||
const PredictionsType& ys)
|
||||
{
|
||||
if (xs.n_cols != ys.n_cols)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << "CVBase::AssertDataConsistency(): number of data points ("
|
||||
<< xs.n_cols << ") does not match number of predictions (" << ys.n_cols
|
||||
<< ")!" << std::endl;
|
||||
throw std::invalid_argument(oss.str());
|
||||
}
|
||||
util::CheckSameSizes(xs, (size_t) ys.n_cols, "CVBase::AssertDataConsistency()",
|
||||
"predictions");
|
||||
}
|
||||
|
||||
template<typename MLAlgorithm,
|
||||
@@ -129,14 +125,8 @@ void CVBase<MLAlgorithm,
|
||||
static_assert(MIE::SupportsWeights,
|
||||
"The given MLAlgorithm does not support weighted learning");
|
||||
|
||||
if (weights.n_elem != xs.n_cols)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << "CVBase::AssertWeightsConsistency(): number of weights ("
|
||||
<< weights.n_elem << ") does not match number of data points ("
|
||||
<< xs.n_cols << ")!" << std::endl;
|
||||
throw std::invalid_argument(oss.str());
|
||||
}
|
||||
util::CheckSameSizes(xs, weights, "CVBase::AssertWeightsConsistency()",
|
||||
"weights");
|
||||
}
|
||||
|
||||
template<typename MLAlgorithm,
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#define MLPACK_CORE_CV_METRICS_ACCURACY_HPP
|
||||
|
||||
#include <mlpack/core.hpp>
|
||||
#include <mlpack/prereqs.hpp>
|
||||
|
||||
namespace mlpack {
|
||||
namespace cv {
|
||||
|
||||
@@ -12,8 +12,6 @@
|
||||
#ifndef MLPACK_CORE_CV_METRICS_ACCURACY_IMPL_HPP
|
||||
#define MLPACK_CORE_CV_METRICS_ACCURACY_IMPL_HPP
|
||||
|
||||
#include <mlpack/core/cv/metrics/facilities.hpp>
|
||||
|
||||
namespace mlpack {
|
||||
namespace cv {
|
||||
|
||||
@@ -22,7 +20,7 @@ double Accuracy::Evaluate(MLAlgorithm& model,
|
||||
const DataType& data,
|
||||
const arma::Row<size_t>& labels)
|
||||
{
|
||||
AssertSizes(data, labels, "Accuracy::Evaluate()");
|
||||
util::CheckSameSizes(data, labels, "Accuracy::Evaluate()");
|
||||
|
||||
arma::Row<size_t> predictedLabels;
|
||||
model.Classify(data, predictedLabels);
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
#define MLPACK_CORE_CV_METRICS_F1_IMPL_HPP
|
||||
|
||||
#include <mlpack/core/cv/metrics/accuracy.hpp>
|
||||
#include <mlpack/core/cv/metrics/facilities.hpp>
|
||||
|
||||
namespace mlpack {
|
||||
namespace cv {
|
||||
@@ -33,7 +32,7 @@ double F1<AS, PC>::Evaluate(MLAlgorithm& model,
|
||||
const DataType& data,
|
||||
const arma::Row<size_t>& labels)
|
||||
{
|
||||
AssertSizes(data, labels, "F1<Binary>::Evaluate()");
|
||||
util::CheckSameSizes(data, labels, "F1<Binary>::Evaluate()");
|
||||
|
||||
arma::Row<size_t> predictedLabels;
|
||||
model.Classify(data, predictedLabels);
|
||||
@@ -56,7 +55,7 @@ double F1<AS, PC>::Evaluate(MLAlgorithm& model,
|
||||
const DataType& data,
|
||||
const arma::Row<size_t>& labels)
|
||||
{
|
||||
AssertSizes(data, labels, "F1<Micro>::Evaluate()");
|
||||
util::CheckSameSizes(data, labels, "F1<Micro>::Evaluate()");
|
||||
|
||||
// Microaveraged F1 is really the same as microaveraged precision and
|
||||
// microaveraged recall, which are in turn the same as accuracy.
|
||||
@@ -70,7 +69,7 @@ double F1<AS, PC>::Evaluate(MLAlgorithm& model,
|
||||
const DataType& data,
|
||||
const arma::Row<size_t>& labels)
|
||||
{
|
||||
AssertSizes(data, labels, "F1<Macro>::Evaluate()");
|
||||
util::CheckSameSizes(data, labels, "F1<Macro>::Evaluate()");
|
||||
|
||||
arma::Row<size_t> predictedLabels;
|
||||
model.Classify(data, predictedLabels);
|
||||
|
||||
@@ -19,29 +19,6 @@
|
||||
namespace mlpack {
|
||||
namespace cv {
|
||||
|
||||
/**
|
||||
* Assert there is the same number of the given data points and labels.
|
||||
*
|
||||
* @param data Column-major data.
|
||||
* @param labels Labels.
|
||||
* @param callerDescription A description of the caller that can be used for
|
||||
* error generation.
|
||||
*/
|
||||
template<typename DataType>
|
||||
void AssertSizes(const DataType& data,
|
||||
const arma::Row<size_t>& labels,
|
||||
const std::string& callerDescription)
|
||||
{
|
||||
if (data.n_cols != labels.n_elem)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << callerDescription << ": number of points (" << data.n_cols << ") "
|
||||
<< "does not match number of labels (" << labels.n_elem << ")!"
|
||||
<< std::endl;
|
||||
throw std::invalid_argument(oss.str());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Pairwise distance of the given data.
|
||||
*
|
||||
|
||||
@@ -20,14 +20,8 @@ double MSE::Evaluate(MLAlgorithm& model,
|
||||
const DataType& data,
|
||||
const ResponsesType& responses)
|
||||
{
|
||||
if (data.n_cols != responses.n_cols)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << "MSE::Evaluate(): number of points (" << data.n_cols << ") "
|
||||
<< "does not match number of responses (" << responses.n_cols << ")!"
|
||||
<< std::endl;
|
||||
throw std::invalid_argument(oss.str());
|
||||
}
|
||||
util::CheckSameSizes(data, (size_t) responses.n_cols, "MSE::Evaluate()",
|
||||
"responses");
|
||||
|
||||
ResponsesType predictedResponses;
|
||||
model.Predict(data, predictedResponses);
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
#define MLPACK_CORE_CV_METRICS_PRECISION_IMPL_HPP
|
||||
|
||||
#include <mlpack/core/cv/metrics/accuracy.hpp>
|
||||
#include <mlpack/core/cv/metrics/facilities.hpp>
|
||||
|
||||
namespace mlpack {
|
||||
namespace cv {
|
||||
@@ -33,7 +32,7 @@ double Precision<AS, PC>::Evaluate(MLAlgorithm& model,
|
||||
const DataType& data,
|
||||
const arma::Row<size_t>& labels)
|
||||
{
|
||||
AssertSizes(data, labels, "Precision<Binary>::Evaluate()");
|
||||
util::CheckSameSizes(data, labels, "Precision<Binary>::Evaluate()");
|
||||
|
||||
arma::Row<size_t> predictedLabels;
|
||||
model.Classify(data, predictedLabels);
|
||||
@@ -51,7 +50,7 @@ double Precision<AS, PC>::Evaluate(MLAlgorithm& model,
|
||||
const DataType& data,
|
||||
const arma::Row<size_t>& labels)
|
||||
{
|
||||
AssertSizes(data, labels, "Precision<Micro>::Evaluate()");
|
||||
util::CheckSameSizes(data, labels, "Precision<Micro>::Evaluate()");
|
||||
|
||||
// Microaveraged precision turns out to be just accuracy.
|
||||
return Accuracy::Evaluate(model, data, labels);
|
||||
@@ -64,7 +63,7 @@ double Precision<AS, PC>::Evaluate(MLAlgorithm& model,
|
||||
const DataType& data,
|
||||
const arma::Row<size_t>& labels)
|
||||
{
|
||||
AssertSizes(data, labels, "Precision<Macro>::Evaluate()");
|
||||
util::CheckSameSizes(data, labels, "Precision<Macro>::Evaluate()");
|
||||
|
||||
arma::Row<size_t> predictedLabels;
|
||||
model.Classify(data, predictedLabels);
|
||||
|
||||
@@ -21,14 +21,8 @@ double R2Score<AdjustedR2>::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());
|
||||
}
|
||||
util::CheckSameSizes(data, (size_t) responses.n_cols, "R2Score::Evaluate()",
|
||||
"responses");
|
||||
|
||||
ResponsesType predictedResponses;
|
||||
// Taking Predicted Output from the model.
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
#define MLPACK_CORE_CV_METRICS_RECALL_IMPL_HPP
|
||||
|
||||
#include <mlpack/core/cv/metrics/accuracy.hpp>
|
||||
#include <mlpack/core/cv/metrics/facilities.hpp>
|
||||
|
||||
namespace mlpack {
|
||||
namespace cv {
|
||||
@@ -33,7 +32,7 @@ double Recall<AS, PC>::Evaluate(MLAlgorithm& model,
|
||||
const DataType& data,
|
||||
const arma::Row<size_t>& labels)
|
||||
{
|
||||
AssertSizes(data, labels, "Recall<Binary>::Evaluate()");
|
||||
util::CheckSameSizes(data, labels, "Recall<Binary>::Evaluate()");
|
||||
|
||||
arma::Row<size_t> predictedLabels;
|
||||
model.Classify(data, predictedLabels);
|
||||
@@ -51,7 +50,7 @@ double Recall<AS, PC>::Evaluate(MLAlgorithm& model,
|
||||
const DataType& data,
|
||||
const arma::Row<size_t>& labels)
|
||||
{
|
||||
AssertSizes(data, labels, "Recall<Micro>::Evaluate()");
|
||||
util::CheckSameSizes(data, labels, "Recall<Micro>::Evaluate()");
|
||||
|
||||
// Microaveraged recall is really the same as accuracy.
|
||||
return Accuracy::Evaluate(model, data, labels);
|
||||
@@ -64,7 +63,7 @@ double Recall<AS, PC>::Evaluate(MLAlgorithm& model,
|
||||
const DataType& data,
|
||||
const arma::Row<size_t>& labels)
|
||||
{
|
||||
AssertSizes(data, labels, "Recall<Macro>::Evaluate()");
|
||||
util::CheckSameSizes(data, labels, "Recall<Macro>::Evaluate()");
|
||||
|
||||
arma::Row<size_t> predictedLabels;
|
||||
model.Classify(data, predictedLabels);
|
||||
|
||||
@@ -22,7 +22,7 @@ double SilhouetteScore::Overall(const DataType& X,
|
||||
const arma::Row<size_t>& labels,
|
||||
const Metric& metric)
|
||||
{
|
||||
AssertSizes(X, labels, "SilhouetteScore::Overall()");
|
||||
util::CheckSameSizes(X, labels, "SilhouetteScore::Overall()");
|
||||
return arma::mean(SamplesScore(X, labels, metric));
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ template<typename DataType>
|
||||
arma::rowvec SilhouetteScore::SamplesScore(const DataType& distances,
|
||||
const arma::Row<size_t>& labels)
|
||||
{
|
||||
AssertSizes(distances, labels, "SilhouetteScore::SamplesScore()");
|
||||
util::CheckSameSizes(distances, labels, "SilhouetteScore::SamplesScore()");
|
||||
|
||||
// Stores the silhouette scores of individual samples.
|
||||
arma::rowvec sampleScores(distances.n_rows);
|
||||
@@ -76,7 +76,7 @@ arma::rowvec SilhouetteScore::SamplesScore(const DataType& X,
|
||||
const arma::Row<size_t>& labels,
|
||||
const Metric& metric)
|
||||
{
|
||||
AssertSizes(X, labels, "SilhouetteScore::SamplesScore()");
|
||||
util::CheckSameSizes(X, labels, "SilhouetteScore::SamplesScore()");
|
||||
DataType distances = PairwiseDistances(X, metric);
|
||||
return SamplesScore(distances, labels);
|
||||
}
|
||||
|
||||
@@ -18,11 +18,57 @@
|
||||
namespace mlpack {
|
||||
namespace data {
|
||||
|
||||
/**
|
||||
* This helper function splits any `input` data into training and testing parts.
|
||||
* In order to shuffle the input data before spliting, an array of shuffled
|
||||
* indices of the input data is passed in the form of argument `order`.
|
||||
*/
|
||||
template<typename InputType>
|
||||
void SplitHelper(const InputType& input,
|
||||
InputType& train,
|
||||
InputType& test,
|
||||
const double testRatio,
|
||||
const arma::uvec& order = arma::uvec())
|
||||
{
|
||||
const size_t testSize = static_cast<size_t>(input.n_cols * testRatio);
|
||||
const size_t trainSize = input.n_cols - testSize;
|
||||
|
||||
// Initialising the sizes of outputs if not already initialized.
|
||||
train.set_size(input.n_rows, trainSize);
|
||||
test.set_size(input.n_rows, testSize);
|
||||
|
||||
// Shuffling and spliting simultaneously.
|
||||
if (!order.is_empty())
|
||||
{
|
||||
if (trainSize > 0)
|
||||
{
|
||||
for (size_t i = 0; i < trainSize; ++i)
|
||||
train.col(i) = input.col(order(i));
|
||||
}
|
||||
if (trainSize < input.n_cols)
|
||||
{
|
||||
for (size_t i = trainSize; i < input.n_cols; ++i)
|
||||
test.col(i - trainSize) = input.col(order(i));
|
||||
}
|
||||
}
|
||||
// Spliting only.
|
||||
else
|
||||
{
|
||||
if (trainSize > 0)
|
||||
train = input.cols(0, trainSize - 1);
|
||||
|
||||
if (trainSize < input.n_cols)
|
||||
test = input.cols(trainSize, input.n_cols - 1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an input dataset and labels, stratify into a training set and test set.
|
||||
* It is recommended to have the input labels between the range [0, n) where n
|
||||
* is the number of different labels. The NormalizeLabels() function in
|
||||
* mlpack::data can be used for this.
|
||||
* Expects labels to be of type arma::Row<> or arma::Col<>.
|
||||
* Throws a runtime error if this is not the case.
|
||||
* Example usage below. This overload places the stratified dataset into the
|
||||
* four output parameters given (trainData, testData, trainLabel,
|
||||
* and testLabel).
|
||||
@@ -52,13 +98,14 @@ namespace data {
|
||||
* @param shuffleData If true, the sample order is shuffled; otherwise, each
|
||||
* sample is visited in linear order. (Default true.)
|
||||
*/
|
||||
template<typename T, typename U>
|
||||
template<typename T, typename LabelsType,
|
||||
typename = std::enable_if_t<arma::is_arma_type<LabelsType>::value> >
|
||||
void StratifiedSplit(const arma::Mat<T>& input,
|
||||
const arma::Row<U>& inputLabel,
|
||||
const LabelsType& inputLabel,
|
||||
arma::Mat<T>& trainData,
|
||||
arma::Mat<T>& testData,
|
||||
arma::Row<U>& trainLabel,
|
||||
arma::Row<U>& testLabel,
|
||||
LabelsType& trainLabel,
|
||||
LabelsType& testLabel,
|
||||
const double testRatio,
|
||||
const bool shuffleData = true)
|
||||
{
|
||||
@@ -95,29 +142,24 @@ void StratifiedSplit(const arma::Mat<T>& input,
|
||||
* 0
|
||||
* 1 1
|
||||
*/
|
||||
const bool typeCheck = (arma::is_Row<LabelsType>::value)
|
||||
|| (arma::is_Col<LabelsType>::value);
|
||||
if (!typeCheck)
|
||||
throw std::runtime_error("data::Split(): when stratified sampling is done, "
|
||||
"labels must have type `arma::Row<>`!");
|
||||
size_t trainIdx = 0;
|
||||
size_t testIdx = 0;
|
||||
size_t trainSize = 0;
|
||||
size_t testSize = 0;
|
||||
arma::uvec labelCounts;
|
||||
arma::uvec testLabelCounts;
|
||||
U maxLabel = inputLabel.max();
|
||||
typename LabelsType::elem_type maxLabel = inputLabel.max();
|
||||
|
||||
labelCounts.zeros(maxLabel+1);
|
||||
testLabelCounts.zeros(maxLabel+1);
|
||||
|
||||
arma::uvec order =
|
||||
arma::linspace<arma::uvec>(0, input.n_cols - 1, input.n_cols);
|
||||
|
||||
if (shuffleData)
|
||||
{
|
||||
order = arma::shuffle(order);
|
||||
}
|
||||
|
||||
for (U label : inputLabel)
|
||||
{
|
||||
for (typename LabelsType::elem_type label : inputLabel)
|
||||
++labelCounts[label];
|
||||
}
|
||||
|
||||
for (arma::uword labelCount : labelCounts)
|
||||
{
|
||||
@@ -127,24 +169,50 @@ void StratifiedSplit(const arma::Mat<T>& input,
|
||||
|
||||
trainData.set_size(input.n_rows, trainSize);
|
||||
testData.set_size(input.n_rows, testSize);
|
||||
trainLabel.set_size(trainSize);
|
||||
testLabel.set_size(testSize);
|
||||
trainLabel.set_size(inputLabel.n_rows, trainSize);
|
||||
testLabel.set_size(inputLabel.n_rows, testSize);
|
||||
|
||||
for (arma::uword i : order)
|
||||
if (shuffleData)
|
||||
{
|
||||
U label = inputLabel[i];
|
||||
if (testLabelCounts[label] < floor(labelCounts[label] * testRatio))
|
||||
arma::uvec order = arma::shuffle(
|
||||
arma::linspace<arma::uvec>(0, input.n_cols - 1, input.n_cols));
|
||||
|
||||
for (arma::uword i : order)
|
||||
{
|
||||
testLabelCounts[label] += 1;
|
||||
testData.col(testIdx) = input.col(i);
|
||||
testLabel[testIdx] = inputLabel[i];
|
||||
testIdx += 1;
|
||||
typename LabelsType::elem_type label = inputLabel[i];
|
||||
if (testLabelCounts[label] < floor(labelCounts[label] * testRatio))
|
||||
{
|
||||
testLabelCounts[label] += 1;
|
||||
testData.col(testIdx) = input.col(i);
|
||||
testLabel[testIdx] = inputLabel[i];
|
||||
testIdx += 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
trainData.col(trainIdx) = input.col(i);
|
||||
trainLabel[trainIdx] = inputLabel[i];
|
||||
trainIdx += 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
}
|
||||
else
|
||||
{
|
||||
for (arma::uword i = 0; i < input.n_cols; i++)
|
||||
{
|
||||
trainData.col(trainIdx) = input.col(i);
|
||||
trainLabel[trainIdx] = inputLabel[i];
|
||||
trainIdx += 1;
|
||||
typename LabelsType::elem_type label = inputLabel[i];
|
||||
if (testLabelCounts[label] < floor(labelCounts[label] * testRatio))
|
||||
{
|
||||
testLabelCounts[label] += 1;
|
||||
testData.col(testIdx) = input.col(i);
|
||||
testLabel[testIdx] = inputLabel[i];
|
||||
testIdx += 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
trainData.col(trainIdx) = input.col(i);
|
||||
trainLabel[trainIdx] = inputLabel[i];
|
||||
trainIdx += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -169,6 +237,9 @@ void StratifiedSplit(const arma::Mat<T>& input,
|
||||
* testData, trainLabel, testLabel, 0.3);
|
||||
* @endcode
|
||||
*
|
||||
* @tparam T Type of the elements of the input matrix.
|
||||
* @tparam LabelsType Type of input labels. It can be arma::Mat, arma::Row,
|
||||
* arma::Cube or arma::SpMat.
|
||||
* @param input Input dataset to split.
|
||||
* @param inputLabel Input labels to split.
|
||||
* @param trainData Matrix to store training data into.
|
||||
@@ -179,50 +250,28 @@ void StratifiedSplit(const arma::Mat<T>& input,
|
||||
* @param shuffleData If true, the sample order is shuffled; otherwise, each
|
||||
* sample is visited in linear order. (Default true.)
|
||||
*/
|
||||
template<typename T, typename U>
|
||||
template<typename T, typename LabelsType,
|
||||
typename = std::enable_if_t<arma::is_arma_type<LabelsType>::value> >
|
||||
void Split(const arma::Mat<T>& input,
|
||||
const arma::Row<U>& inputLabel,
|
||||
const LabelsType& inputLabel,
|
||||
arma::Mat<T>& trainData,
|
||||
arma::Mat<T>& testData,
|
||||
arma::Row<U>& trainLabel,
|
||||
arma::Row<U>& testLabel,
|
||||
LabelsType& trainLabel,
|
||||
LabelsType& testLabel,
|
||||
const double testRatio,
|
||||
const bool shuffleData = true)
|
||||
{
|
||||
const size_t testSize = static_cast<size_t>(input.n_cols * testRatio);
|
||||
const size_t trainSize = input.n_cols - testSize;
|
||||
trainData.set_size(input.n_rows, trainSize);
|
||||
testData.set_size(input.n_rows, testSize);
|
||||
trainLabel.set_size(trainSize);
|
||||
testLabel.set_size(testSize);
|
||||
|
||||
if (shuffleData)
|
||||
{
|
||||
arma::uvec order = arma::shuffle(arma::linspace<arma::uvec>(
|
||||
0, input.n_cols - 1, input.n_cols));
|
||||
if (trainSize > 0)
|
||||
{
|
||||
trainData = input.cols(order.subvec(0, trainSize - 1));
|
||||
trainLabel = inputLabel.cols(order.subvec(0, trainSize - 1));
|
||||
}
|
||||
if (trainSize < input.n_cols)
|
||||
{
|
||||
testData = input.cols(order.subvec(trainSize, input.n_cols - 1));
|
||||
testLabel = inputLabel.cols(order.subvec(trainSize, input.n_cols - 1));
|
||||
}
|
||||
arma::uvec order = arma::shuffle(arma::linspace<arma::uvec>(0,
|
||||
input.n_cols - 1, input.n_cols));
|
||||
SplitHelper(input, trainData, testData, testRatio, order);
|
||||
SplitHelper(inputLabel, trainLabel, testLabel, testRatio, order);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (trainSize > 0)
|
||||
{
|
||||
trainData = input.cols(0, trainSize - 1);
|
||||
trainLabel = inputLabel.subvec(0, trainSize - 1);
|
||||
}
|
||||
if (trainSize < input.n_cols)
|
||||
{
|
||||
testData = input.cols(trainSize , input.n_cols - 1);
|
||||
testLabel = inputLabel.subvec(trainSize , input.n_cols - 1);
|
||||
}
|
||||
SplitHelper(input, trainData, testData, testRatio);
|
||||
SplitHelper(inputLabel, trainLabel, testLabel, testRatio);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -256,29 +305,15 @@ void Split(const arma::Mat<T>& input,
|
||||
const double testRatio,
|
||||
const bool shuffleData = true)
|
||||
{
|
||||
const size_t testSize = static_cast<size_t>(input.n_cols * testRatio);
|
||||
const size_t trainSize = input.n_cols - testSize;
|
||||
trainData.set_size(input.n_rows, trainSize);
|
||||
testData.set_size(input.n_rows, testSize);
|
||||
|
||||
if (shuffleData)
|
||||
{
|
||||
arma::uvec order = arma::shuffle(arma::linspace<arma::uvec>(
|
||||
0, input.n_cols - 1, input.n_cols));
|
||||
|
||||
if (trainSize > 0)
|
||||
trainData = input.cols(order.subvec(0, trainSize - 1));
|
||||
|
||||
if (trainSize < input.n_cols)
|
||||
testData = input.cols(order.subvec(trainSize, input.n_cols - 1));
|
||||
arma::uvec order = arma::shuffle(arma::linspace<arma::uvec>(0,
|
||||
input.n_cols - 1, input.n_cols));
|
||||
SplitHelper(input, trainData, testData, testRatio, order);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (trainSize > 0)
|
||||
trainData = input.cols(0, trainSize - 1);
|
||||
|
||||
if (trainSize < input.n_cols)
|
||||
testData = input.cols(trainSize , input.n_cols - 1);
|
||||
SplitHelper(input, trainData, testData, testRatio);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -295,6 +330,9 @@ void Split(const arma::Mat<T>& input,
|
||||
* auto splitResult = Split(input, label, 0.2);
|
||||
* @endcode
|
||||
*
|
||||
* @tparam T Type of the elements of the input matrix.
|
||||
* @tparam LabelsType Type of input labels. It can be arma::Mat, arma::Row,
|
||||
* arma::Cube or arma::SpMat.
|
||||
* @param input Input dataset to split.
|
||||
* @param inputLabel Input labels to split.
|
||||
* @param testRatio Percentage of dataset to use for test set (between 0 and 1).
|
||||
@@ -302,22 +340,24 @@ void Split(const arma::Mat<T>& input,
|
||||
* sample is visited in linear order. (Default true).
|
||||
* @param stratifyData If true, the train and test splits are stratified
|
||||
* so that the ratio of each class in the training and test sets is the same
|
||||
* as in the original dataset.
|
||||
* as in the original dataset. Expects labels to be of type arma::Row<> or
|
||||
* arma::Col<>.
|
||||
* @return std::tuple containing trainData (arma::Mat<T>), testData
|
||||
* (arma::Mat<T>), trainLabel (arma::Row<U>), and testLabel (arma::Row<U>).
|
||||
*/
|
||||
template<typename T, typename U>
|
||||
std::tuple<arma::Mat<T>, arma::Mat<T>, arma::Row<U>, arma::Row<U>>
|
||||
template<typename T, typename LabelsType,
|
||||
typename = std::enable_if_t<arma::is_arma_type<LabelsType>::value> >
|
||||
std::tuple<arma::Mat<T>, arma::Mat<T>, LabelsType, LabelsType>
|
||||
Split(const arma::Mat<T>& input,
|
||||
const arma::Row<U>& inputLabel,
|
||||
const LabelsType& inputLabel,
|
||||
const double testRatio,
|
||||
const bool shuffleData = true,
|
||||
const bool stratifyData = false)
|
||||
{
|
||||
arma::Mat<T> trainData;
|
||||
arma::Mat<T> testData;
|
||||
arma::Row<U> trainLabel;
|
||||
arma::Row<U> testLabel;
|
||||
LabelsType trainLabel;
|
||||
LabelsType testLabel;
|
||||
|
||||
if (stratifyData)
|
||||
{
|
||||
@@ -368,6 +408,208 @@ Split(const arma::Mat<T>& input,
|
||||
std::move(testData));
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an input dataset and labels, split into a training set and test set.
|
||||
* Example usage below. This overload places the split dataset into the four
|
||||
* output parameters given (trainData, testData, trainLabel, and testLabel).
|
||||
*
|
||||
* The input dataset must be of type arma::field. It should have the shape -
|
||||
* (n_rows = 1, n_cols = Number of samples, n_slices = 1).
|
||||
*
|
||||
* NOTE: Here FieldType could be arma::field<arma::mat> or arma::field<arma::vec>.
|
||||
*
|
||||
* @code
|
||||
* arma::field<arma::mat> input = loadData();
|
||||
* arma::field<arma::vec> label = loadLabel();
|
||||
* arma::field<arma::mat> trainData;
|
||||
* arma::field<arma::mat> testData;
|
||||
* arma::field<arma::vec> trainLabel;
|
||||
* arma::field<arma::vec> testLabel;
|
||||
* math::RandomSeed(100); // Set the seed if you like.
|
||||
*
|
||||
* // Split the dataset into a training and test set, with 30% of the data being
|
||||
* // held out for the test set.
|
||||
* Split(input, label, trainData, testData, trainLabel, testLabel, 0.3);
|
||||
* @endcode
|
||||
*
|
||||
* @param input Input dataset to split.
|
||||
* @param inputLabel Input labels to split.
|
||||
* @param trainData FieldType to store training data into.
|
||||
* @param testData FieldType test data into.
|
||||
* @param trainLabel Field vector to store training labels into.
|
||||
* @param testLabel Field vector to store test labels into.
|
||||
* @param testRatio Percentage of dataset to use for test set (between 0 and 1).
|
||||
* @param shuffleData If true, the sample order is shuffled; otherwise, each
|
||||
* sample is visited in linear order. (Default true.)
|
||||
*/
|
||||
template <typename FieldType, typename T,
|
||||
typename = std::enable_if_t<
|
||||
arma::is_Col<typename FieldType::object_type>::value ||
|
||||
arma::is_Mat_only<typename FieldType::object_type>::value>>
|
||||
void Split(const FieldType& input,
|
||||
const arma::field<T>& inputLabel,
|
||||
FieldType& trainData,
|
||||
arma::field<T>& trainLabel,
|
||||
FieldType& testData,
|
||||
arma::field<T>& testLabel,
|
||||
const double testRatio,
|
||||
const bool shuffleData = true)
|
||||
{
|
||||
if (shuffleData)
|
||||
{
|
||||
arma::uvec order = arma::shuffle(arma::linspace<arma::uvec>(0,
|
||||
input.n_cols - 1, input.n_cols));
|
||||
SplitHelper(input, trainData, testData, testRatio, order);
|
||||
SplitHelper(inputLabel, trainLabel, testLabel, testRatio, order);
|
||||
}
|
||||
else
|
||||
{
|
||||
SplitHelper(input, trainData, testData, testRatio);
|
||||
SplitHelper(inputLabel, trainLabel, testLabel, testRatio);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an input dataset, split into a training set and test set.
|
||||
* Example usage below. This overload places the split dataset into the two
|
||||
* output parameters given (trainData, testData).
|
||||
*
|
||||
* The input dataset must be of type arma::field. It should have the shape -
|
||||
* (n_rows = 1, n_cols = Number of samples, n_slices = 1)
|
||||
*
|
||||
* NOTE: Here FieldType could be arma::field<arma::mat> or arma::field<arma::vec>
|
||||
*
|
||||
* @code
|
||||
* arma::field<arma::mat> input = loadData();
|
||||
* arma::field<arma::mat> trainData;
|
||||
* arma::field<arma::mat> testData;
|
||||
* math::RandomSeed(100); // Set the seed if you like.
|
||||
*
|
||||
* // Split the dataset into a training and test set, with 30% of the data being
|
||||
* // held out for the test set.
|
||||
* Split(input, trainData, testData, 0.3);
|
||||
* @endcode
|
||||
*
|
||||
* @param input Input dataset to split.
|
||||
* @param trainData FieldType to store training data into.
|
||||
* @param testData FieldType test data into.
|
||||
* @param testRatio Percentage of dataset to use for test set (between 0 and 1).
|
||||
* @param shuffleData If true, the sample order is shuffled; otherwise, each
|
||||
* sample is visited in linear order. (Default true).
|
||||
*/
|
||||
template <class FieldType,
|
||||
class = std::enable_if_t<
|
||||
arma::is_Col<typename FieldType::object_type>::value ||
|
||||
arma::is_Mat_only<typename FieldType::object_type>::value>>
|
||||
void Split(const FieldType& input,
|
||||
FieldType& trainData,
|
||||
FieldType& testData,
|
||||
const double testRatio,
|
||||
const bool shuffleData = true)
|
||||
{
|
||||
if (shuffleData)
|
||||
{
|
||||
arma::uvec order = arma::shuffle(arma::linspace<arma::uvec>(0,
|
||||
input.n_cols - 1, input.n_cols));
|
||||
SplitHelper(input, trainData, testData, testRatio, order);
|
||||
}
|
||||
else
|
||||
{
|
||||
SplitHelper(input, trainData, testData, testRatio);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an input dataset and labels, split into a training set and test set.
|
||||
* Example usage below. This overload returns the split dataset as a std::tuple
|
||||
* with four elements: an FieldType containing the training data, an
|
||||
* FieldType containing the test data, an arma::field<arma::vec> containing the
|
||||
* training labels, and an arma::field<arma::vec> containing the test labels.
|
||||
*
|
||||
* The input dataset must be of type arma::field. It should have the shape -
|
||||
* (n_rows = 1, n_cols = Number of samples, n_slices = 1)
|
||||
*
|
||||
* NOTE: Here FieldType could be arma::field<arma::mat> or arma::field<arma::vec>
|
||||
*
|
||||
* @code
|
||||
* arma::field<arma::mat> input = loadData();
|
||||
* arma::field<arma::vec> label = loadLabel();
|
||||
* auto splitResult = Split(input, label, 0.2);
|
||||
* @endcode
|
||||
*
|
||||
* @param input Input dataset to split.
|
||||
* @param inputLabel Input labels to split.
|
||||
* @param testRatio Percentage of dataset to use for test set (between 0 and 1).
|
||||
* @param shuffleData If true, the sample order is shuffled; otherwise, each
|
||||
* sample is visited in linear order. (Default true).
|
||||
* @return std::tuple containing trainData (FieldType), testData
|
||||
* (FieldType), trainLabel (arma::field<arma::vec>), and
|
||||
* testLabel (arma::field<arma::vec>).
|
||||
*/
|
||||
template <class FieldType, typename T,
|
||||
class = std::enable_if_t<
|
||||
arma::is_Col<typename FieldType::object_type>::value ||
|
||||
arma::is_Mat_only<typename FieldType::object_type>::value>>
|
||||
std::tuple<FieldType, FieldType, arma::field<T>, arma::field<T>>
|
||||
Split(const FieldType& input,
|
||||
const arma::field<T>& inputLabel,
|
||||
const double testRatio,
|
||||
const bool shuffleData = true)
|
||||
{
|
||||
FieldType trainData;
|
||||
FieldType testData;
|
||||
arma::field<T> trainLabel;
|
||||
arma::field<T> testLabel;
|
||||
|
||||
Split(input, inputLabel, trainData, trainLabel, testData, testLabel,
|
||||
testRatio, shuffleData);
|
||||
|
||||
return std::make_tuple(std::move(trainData),
|
||||
std::move(testData),
|
||||
std::move(trainLabel),
|
||||
std::move(testLabel));
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an input dataset, split into a training set and test set.
|
||||
* Example usage below. This overload returns the split dataset as a std::tuple
|
||||
* with two elements: an FieldType containing the training data and an
|
||||
* FieldType containing the test data.
|
||||
*
|
||||
* The input dataset must be of type arma::field. It should have the shape -
|
||||
* (n_rows = 1, n_cols = Number of samples, n_slices = 1)
|
||||
*
|
||||
* NOTE: Here FieldType could be arma::field<arma::mat> or arma::field<arma::vec>
|
||||
*
|
||||
* @code
|
||||
* arma::field<arma::mat> input = loadData();
|
||||
* auto splitResult = Split(input, 0.2);
|
||||
* @endcode
|
||||
*
|
||||
* @param input Input dataset to split.
|
||||
* @param testRatio Percentage of dataset to use for test set (between 0 and 1).
|
||||
* @param shuffleData If true, the sample order is shuffled; otherwise, each
|
||||
* sample is visited in linear order. (Default true).
|
||||
* @return std::tuple containing trainData (FieldType)
|
||||
* and testData (FieldType).
|
||||
*/
|
||||
template <class FieldType,
|
||||
class = std::enable_if_t<
|
||||
arma::is_Col<typename FieldType::object_type>::value ||
|
||||
arma::is_Mat_only<typename FieldType::object_type>::value>>
|
||||
std::tuple<FieldType, FieldType>
|
||||
Split(const FieldType& input,
|
||||
const double testRatio,
|
||||
const bool shuffleData = true)
|
||||
{
|
||||
FieldType trainData;
|
||||
FieldType testData;
|
||||
Split(input, trainData, testData, testRatio, shuffleData);
|
||||
|
||||
return std::make_tuple(std::move(trainData),
|
||||
std::move(testData));
|
||||
}
|
||||
|
||||
} // namespace data
|
||||
} // namespace mlpack
|
||||
|
||||
|
||||
@@ -81,6 +81,9 @@ class BallBound
|
||||
//! Move constructor: take possession of another bound.
|
||||
BallBound(BallBound&& other);
|
||||
|
||||
//! Move assignment operator.
|
||||
BallBound& operator=(BallBound&& other);
|
||||
|
||||
//! Destructor to release allocated memory.
|
||||
~BallBound();
|
||||
|
||||
|
||||
@@ -71,10 +71,14 @@ template<typename MetricType, typename VecType>
|
||||
BallBound<MetricType, VecType>& BallBound<MetricType, VecType>::operator=(
|
||||
const BallBound& other)
|
||||
{
|
||||
radius = other.radius;
|
||||
center = other.center;
|
||||
metric = other.metric;
|
||||
ownsMetric = false;
|
||||
if (this != &other)
|
||||
{
|
||||
radius = other.radius;
|
||||
center = other.center;
|
||||
metric = other.metric;
|
||||
ownsMetric = false;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
//! Move constructor.
|
||||
@@ -92,6 +96,26 @@ BallBound<MetricType, VecType>::BallBound(BallBound&& other) :
|
||||
other.ownsMetric = false;
|
||||
}
|
||||
|
||||
//! Move assignment operator.
|
||||
template<typename MetricType, typename VecType>
|
||||
BallBound<MetricType, VecType>& BallBound<MetricType, VecType>::operator=(
|
||||
BallBound&& other)
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
radius = other.radius;
|
||||
center = std::move(other.center);
|
||||
metric = other.metric;
|
||||
ownsMetric = other.ownsMetric;
|
||||
|
||||
other.radius = 0.0;
|
||||
other.center = VecType();
|
||||
other.metric = nullptr;
|
||||
other.ownsMetric = false;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
//! Destructor to release allocated memory.
|
||||
template<typename MetricType, typename VecType>
|
||||
BallBound<MetricType, VecType>::~BallBound()
|
||||
|
||||
@@ -86,6 +86,9 @@ class HollowBallBound
|
||||
//! Move constructor: take possession of another bound.
|
||||
HollowBallBound(HollowBallBound&& other);
|
||||
|
||||
//! Move assignment operator.
|
||||
HollowBallBound& operator=(HollowBallBound&& other);
|
||||
|
||||
//! Destructor to release allocated memory.
|
||||
~HollowBallBound();
|
||||
|
||||
|
||||
@@ -80,15 +80,17 @@ 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;
|
||||
metric = other.metric;
|
||||
ownsMetric = false;
|
||||
if (this != &other)
|
||||
{
|
||||
if (ownsMetric)
|
||||
delete metric;
|
||||
|
||||
radii = other.radii;
|
||||
center = other.center;
|
||||
hollowCenter = other.hollowCenter;
|
||||
metric = other.metric;
|
||||
ownsMetric = false;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -111,6 +113,29 @@ HollowBallBound<TMetricType, ElemType>::HollowBallBound(
|
||||
other.ownsMetric = false;
|
||||
}
|
||||
|
||||
//! Move assignment operator.
|
||||
template<typename TMetricType, typename ElemType>
|
||||
HollowBallBound<TMetricType, ElemType>& HollowBallBound<TMetricType, ElemType>::
|
||||
operator=(HollowBallBound&& other)
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
radii = other.radii;
|
||||
center = std::move(other.center);
|
||||
hollowCenter = std::move(other.hollowCenter);
|
||||
metric = other.metric;
|
||||
ownsMetric = other.ownsMetric;
|
||||
|
||||
other.radii.Hi() = 0.0;
|
||||
other.radii.Lo() = 0.0;
|
||||
other.center = arma::Col<ElemType>();
|
||||
other.hollowCenter = arma::Col<ElemType>();
|
||||
other.metric = nullptr;
|
||||
other.ownsMetric = false;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
//! Destructor to release allocated memory.
|
||||
template<typename TMetricType, typename ElemType>
|
||||
HollowBallBound<TMetricType, ElemType>::~HollowBallBound()
|
||||
|
||||
@@ -73,12 +73,16 @@ class HRectBound
|
||||
|
||||
//! Copy constructor; necessary to prevent memory leaks.
|
||||
HRectBound(const HRectBound& other);
|
||||
|
||||
//! Same as copy constructor; necessary to prevent memory leaks.
|
||||
HRectBound& operator=(const HRectBound& other);
|
||||
|
||||
//! Move constructor: take possession of another bound's information.
|
||||
HRectBound(HRectBound&& other);
|
||||
|
||||
//! Move assignment operator.
|
||||
HRectBound& operator=(HRectBound&& other);
|
||||
|
||||
//! Destructor: clean up memory.
|
||||
~HRectBound();
|
||||
|
||||
|
||||
@@ -103,6 +103,26 @@ inline HRectBound<MetricType, ElemType>::HRectBound(
|
||||
other.minWidth = 0.0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Move assignment operator.
|
||||
*/
|
||||
template<typename MetricType, typename ElemType>
|
||||
inline HRectBound<MetricType, ElemType>&
|
||||
HRectBound<MetricType, ElemType>::operator=(
|
||||
HRectBound<MetricType, ElemType>&& other)
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
bounds = other.bounds;
|
||||
minWidth = other.minWidth;
|
||||
dim = other.dim;
|
||||
other.dim = 0;
|
||||
other.bounds = nullptr;
|
||||
other.minWidth = 0.0;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Destructor: clean up memory.
|
||||
*/
|
||||
|
||||
@@ -177,10 +177,18 @@ class DiscreteHilbertValue
|
||||
/**
|
||||
* Copy the local Hilbert value's pointer.
|
||||
*
|
||||
* @param val The DiscreteHilbertValue object from which the dataset
|
||||
* @param other The DiscreteHilbertValue object from which the dataset
|
||||
* will be copied.
|
||||
*/
|
||||
DiscreteHilbertValue& operator=(const DiscreteHilbertValue& val);
|
||||
DiscreteHilbertValue& operator=(const DiscreteHilbertValue& other);
|
||||
|
||||
/**
|
||||
* Move the local Hilbert object.
|
||||
*
|
||||
* @param other The DiscreteHilbertValue object from which the dataset
|
||||
* will be copied.
|
||||
*/
|
||||
DiscreteHilbertValue& operator=(DiscreteHilbertValue&& other);
|
||||
|
||||
/**
|
||||
* Nullify the localHilbertValues pointer in order to prevent an invalid free.
|
||||
|
||||
@@ -434,22 +434,43 @@ RemoveNode(TreeType* node, const size_t nodeIndex)
|
||||
|
||||
template<typename TreeElemType>
|
||||
DiscreteHilbertValue<TreeElemType>& DiscreteHilbertValue<TreeElemType>::
|
||||
operator=(const DiscreteHilbertValue& val)
|
||||
operator=(const DiscreteHilbertValue& other)
|
||||
{
|
||||
if (this == &val)
|
||||
if (this == &other)
|
||||
return *this;
|
||||
|
||||
if (ownsLocalHilbertValues)
|
||||
delete localHilbertValues;
|
||||
|
||||
localHilbertValues = const_cast<arma::Mat<HilbertElemType>* >
|
||||
(val.LocalHilbertValues());
|
||||
(other.LocalHilbertValues());
|
||||
ownsLocalHilbertValues = false;
|
||||
numValues = val.NumValues();
|
||||
numValues = other.NumValues();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename TreeElemType>
|
||||
DiscreteHilbertValue<TreeElemType>& DiscreteHilbertValue<TreeElemType>::
|
||||
operator=(DiscreteHilbertValue&& other)
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
localHilbertValues = other.localHilbertValues;
|
||||
ownsLocalHilbertValues = other.ownsLocalHilbertValues;
|
||||
numValues = other.numValues;
|
||||
valueToInsert = other.valueToInsert;
|
||||
ownsValueToInsert = other.ownsValueToInsert;
|
||||
|
||||
other.localHilbertValues = nullptr;
|
||||
other.ownsLocalHilbertValues = false;
|
||||
other.numValues = 0;
|
||||
other.valueToInsert = nullptr;
|
||||
other.ownsValueToInsert = false;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename TreeElemType>
|
||||
void DiscreteHilbertValue<TreeElemType>::NullifyData()
|
||||
{
|
||||
|
||||
@@ -26,6 +26,7 @@ set(SOURCES
|
||||
prefixedoutstream_impl.hpp
|
||||
program_doc.hpp
|
||||
program_doc.cpp
|
||||
size_checks.hpp
|
||||
sfinae_utility.hpp
|
||||
singletons.cpp
|
||||
timers.hpp
|
||||
|
||||
@@ -267,3 +267,32 @@ void IO::ClearSettings()
|
||||
GetSingleton().aliases = persistentAliases;
|
||||
GetSingleton().functionMap = persistentFunctions;
|
||||
}
|
||||
|
||||
void IO::CheckInputMatrices()
|
||||
{
|
||||
typedef typename std::tuple<data::DatasetInfo, arma::mat> TupleType;
|
||||
std::map<std::string, util::ParamData>::iterator itr;
|
||||
|
||||
for (itr = IO::Parameters().begin(); itr != IO::Parameters().end(); ++itr)
|
||||
{
|
||||
std::string paramName = itr->first;
|
||||
std::string paramType = itr->second.cppType;
|
||||
if (paramType == "arma::mat")
|
||||
{
|
||||
IO::CheckInputMatrix(IO::GetParam<arma::mat>(paramName), paramName);
|
||||
}
|
||||
else if (paramType == "arma::vec")
|
||||
{
|
||||
IO::CheckInputMatrix(IO::GetParam<arma::vec>(paramName), paramName);
|
||||
}
|
||||
else if (paramType == "arma::rowvec")
|
||||
{
|
||||
IO::CheckInputMatrix(IO::GetParam<arma::rowvec>(paramName), paramName);
|
||||
}
|
||||
else if (paramType == "std::tuple<mlpack::data::DatasetInfo, arma::mat>")
|
||||
{
|
||||
IO::CheckInputMatrix(
|
||||
std::get<1>(IO::GetParam<TupleType>(paramName)), paramName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -219,6 +219,15 @@ class IO
|
||||
template<typename T>
|
||||
static T& GetRawParam(const std::string& identifier);
|
||||
|
||||
/**
|
||||
* Utility function for CheckInputMatrices().
|
||||
*
|
||||
* @param matrix Matrix to check.
|
||||
* @param identifier Name of the parameter in question.
|
||||
*/
|
||||
template<typename T>
|
||||
static void CheckInputMatrix(const T& matrix, const std::string& identifier);
|
||||
|
||||
/**
|
||||
* Given two (matrix) parameters, ensure that the first is an in-place copy of
|
||||
* the second. This will generally do nothing (as the bindings already do
|
||||
@@ -285,6 +294,11 @@ class IO
|
||||
*/
|
||||
static void ClearSettings();
|
||||
|
||||
/**
|
||||
* Checks all input matrices for NaN and inf values, exits if found any.
|
||||
*/
|
||||
static void CheckInputMatrices();
|
||||
|
||||
private:
|
||||
//! Convenience map from alias values to names.
|
||||
std::map<char, std::string> aliases;
|
||||
|
||||
@@ -145,6 +145,18 @@ T& IO::GetRawParam(const std::string& identifier)
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void IO::CheckInputMatrix(const T& matrix, const std::string& identifier)
|
||||
{
|
||||
std::string errMsg1 = "The input " + identifier + " has NaN values.";
|
||||
std::string errMsg2 = "The input " + identifier + " has inf values.";
|
||||
|
||||
if (matrix.has_nan())
|
||||
Log::Fatal << errMsg1 << std::endl;
|
||||
if (matrix.has_inf())
|
||||
Log::Fatal << errMsg2 << std::endl;
|
||||
}
|
||||
|
||||
} // namespace mlpack
|
||||
|
||||
#endif
|
||||
|
||||
@@ -230,6 +230,8 @@ PARAM_FLAG("copy_all_inputs", "If specified, all input parameters will be deep"
|
||||
" copied before the method is run. This is useful for debugging problems "
|
||||
"where the input parameters are being modified by the algorithm, but can "
|
||||
"slow down the code.", "");
|
||||
PARAM_FLAG("check_input_matrices", "If specified, the input matrix is checked for"
|
||||
" NaN and inf values; an exception is thrown if any are found.", "");
|
||||
|
||||
// Nothing else needs to be defined---the binding will use mlpackMain() as-is.
|
||||
|
||||
|
||||
@@ -1015,7 +1015,9 @@ using DatasetInfo = DatasetMapper<IncrementPolicy, std::string>;
|
||||
*/
|
||||
#define TUPLE_TYPE std::tuple<mlpack::data::DatasetInfo, arma::mat>
|
||||
#define PARAM_MATRIX_AND_INFO_IN(ID, DESC, ALIAS) \
|
||||
PARAM_IN(TUPLE_TYPE, ID, DESC, ALIAS, TUPLE_TYPE(), false)
|
||||
PARAM(TUPLE_TYPE, ID, DESC, ALIAS, \
|
||||
"std::tuple<mlpack::data::DatasetInfo, arma::mat>", false, true, true, \
|
||||
TUPLE_TYPE())
|
||||
|
||||
/**
|
||||
* Define an input model. From the command line, the user can specify the file
|
||||
@@ -1207,11 +1209,44 @@ using DatasetInfo = DatasetMapper<IncrementPolicy, std::string>;
|
||||
PARAM_IN(std::vector<T>, ID, DESC, ALIAS, std::vector<T>(), true);
|
||||
|
||||
/**
|
||||
* Define an input parameter. Don't use this function; use the other ones above
|
||||
* that call it. Note that we are using the __LINE__ macro for naming these
|
||||
* actual parameters when __COUNTER__ does not exist, which is a bit of an ugly
|
||||
* hack... but this is the preprocessor, after all. We don't have much choice
|
||||
* other than ugliness.
|
||||
* Defining useful macros using PARAM macro defined later.
|
||||
*/
|
||||
#define PARAM_IN(T, ID, DESC, ALIAS, DEF, REQ) \
|
||||
PARAM(T, ID, DESC, ALIAS, #T, REQ, true, false, DEF);
|
||||
|
||||
#define PARAM_OUT(T, ID, DESC, ALIAS, DEF, REQ) \
|
||||
PARAM(T, ID, DESC, ALIAS, #T, REQ, false, false, DEF);
|
||||
|
||||
#define PARAM_MATRIX(ID, DESC, ALIAS, REQ, TRANS, IN) \
|
||||
PARAM(arma::mat, ID, DESC, ALIAS, "arma::mat", REQ, IN, \
|
||||
TRANS, arma::mat());
|
||||
|
||||
#define PARAM_UMATRIX(ID, DESC, ALIAS, REQ, TRANS, IN) \
|
||||
PARAM(arma::Mat<size_t>, ID, DESC, ALIAS, "arma::Mat<size_t>", \
|
||||
REQ, IN, TRANS, arma::Mat<size_t>());
|
||||
|
||||
#define PARAM_COL(ID, DESC, ALIAS, REQ, TRANS, IN) \
|
||||
PARAM(arma::vec, ID, DESC, ALIAS, "arma::vec", REQ, IN, TRANS, \
|
||||
arma::vec());
|
||||
|
||||
#define PARAM_UCOL(ID, DESC, ALIAS, REQ, TRANS, IN) \
|
||||
PARAM(arma::Col<size_t>, ID, DESC, ALIAS, "arma::Col<size_t>", \
|
||||
REQ, IN, TRANS, arma::Col<size_t>());
|
||||
|
||||
#define PARAM_ROW(ID, DESC, ALIAS, REQ, TRANS, IN) \
|
||||
PARAM(arma::rowvec, ID, DESC, ALIAS, "arma::rowvec", REQ, IN, \
|
||||
TRANS, arma::rowvec());
|
||||
|
||||
#define PARAM_UROW(ID, DESC, ALIAS, REQ, TRANS, IN) \
|
||||
PARAM(arma::Row<size_t>, ID, DESC, ALIAS, "arma::Row<size_t>", \
|
||||
REQ, IN, TRANS, arma::Row<size_t>());
|
||||
|
||||
/**
|
||||
* Define the PARAM(), PARAM_MODEL() macro. Don't use this function;
|
||||
* use the other ones above that call it. Note that we are using the __LINE__
|
||||
* macro for naming these actual parameters when __COUNTER__ does not exist,
|
||||
* which is a bit of an ugly hack... but this is the preprocessor, after all.
|
||||
* We don't have much choice other than ugliness.
|
||||
*
|
||||
* @param T Type of the parameter.
|
||||
* @param ID Name of the parameter.
|
||||
@@ -1223,51 +1258,10 @@ using DatasetInfo = DatasetMapper<IncrementPolicy, std::string>;
|
||||
* @param REQ Whether or not parameter is required (boolean value).
|
||||
*/
|
||||
#ifdef __COUNTER__
|
||||
#define PARAM_IN(T, ID, DESC, ALIAS, DEF, REQ) \
|
||||
#define PARAM(T, ID, DESC, ALIAS, NAME, REQ, IN, TRANS, DEF) \
|
||||
static mlpack::util::Option<T> \
|
||||
JOIN(io_option_dummy_object_in_, __COUNTER__) \
|
||||
(DEF, ID, DESC, ALIAS, #T, REQ, true, false, testName);
|
||||
|
||||
#define PARAM_OUT(T, ID, DESC, ALIAS, DEF, REQ) \
|
||||
static mlpack::util::Option<T> \
|
||||
JOIN(io_option_dummy_object_out_, __COUNTER__) \
|
||||
(DEF, ID, DESC, ALIAS, #T, REQ, false, false, testName);
|
||||
|
||||
#define PARAM_MATRIX(ID, DESC, ALIAS, REQ, TRANS, IN) \
|
||||
static mlpack::util::Option<arma::mat> \
|
||||
JOIN(io_option_dummy_matrix_, __COUNTER__) \
|
||||
(arma::mat(), ID, DESC, ALIAS, "arma::mat", \
|
||||
REQ, IN, !TRANS, testName);
|
||||
|
||||
#define PARAM_UMATRIX(ID, DESC, ALIAS, REQ, TRANS, IN) \
|
||||
static mlpack::util::Option<arma::Mat<size_t>> \
|
||||
JOIN(io_option_dummy_umatrix_, __COUNTER__) \
|
||||
(arma::Mat<size_t>(), ID, DESC, ALIAS, "arma::Mat<size_t>", \
|
||||
REQ, IN, !TRANS, testName);
|
||||
|
||||
#define PARAM_COL(ID, DESC, ALIAS, REQ, TRANS, IN) \
|
||||
static mlpack::util::Option<arma::vec> \
|
||||
JOIN(io_option_dummy_col_, __COUNTER__) \
|
||||
(arma::vec(), ID, DESC, ALIAS, "arma::vec", \
|
||||
REQ, IN, !TRANS, testName);
|
||||
|
||||
#define PARAM_UCOL(ID, DESC, ALIAS, REQ, TRANS, IN) \
|
||||
static mlpack::util::Option<arma::Col<size_t>> \
|
||||
JOIN(io_option_dummy_ucol_, __COUNTER__) \
|
||||
(arma::Col<size_t>(), ID, DESC, ALIAS, "arma::Col<size_t>", \
|
||||
REQ, IN, !TRANS, testName);
|
||||
|
||||
#define PARAM_ROW(ID, DESC, ALIAS, REQ, TRANS, IN) \
|
||||
static mlpack::util::Option<arma::rowvec> \
|
||||
JOIN(io_option_dummy_row_, __COUNTER__) \
|
||||
(arma::rowvec(), ID, DESC, ALIAS, "arma::rowvec", \
|
||||
REQ, IN, !TRANS, testName);
|
||||
|
||||
#define PARAM_UROW(ID, DESC, ALIAS, REQ, TRANS, IN) \
|
||||
static mlpack::util::Option<arma::Row<size_t>> \
|
||||
JOIN(io_option_dummy_urow_, __COUNTER__) \
|
||||
(arma::Row<size_t>(), ID, DESC, ALIAS, "arma::Row<size_t>", \
|
||||
REQ, IN, !TRANS, testName);
|
||||
(DEF, ID, DESC, ALIAS, NAME, REQ, IN, !TRANS, testName);
|
||||
|
||||
// There are no uses of required models, so that is not an option to this
|
||||
// macro (it would be easy to add).
|
||||
@@ -1280,51 +1274,10 @@ using DatasetInfo = DatasetMapper<IncrementPolicy, std::string>;
|
||||
// don't think we can absolutely guarantee success, but it should be "good
|
||||
// enough". We use the __LINE__ macro and the type of the parameter to try
|
||||
// and get a good guess at something unique.
|
||||
#define PARAM_IN(T, ID, DESC, ALIAS, DEF, REQ) \
|
||||
#define PARAM(T, ID, DESC, ALIAS, NAME, REQ, IN, TRANS, DEF) \
|
||||
static mlpack::util::Option<T> \
|
||||
JOIN(JOIN(io_option_dummy_object_in_, __LINE__), opt) \
|
||||
(DEF, ID, DESC, ALIAS, #T, REQ, true, false, testName);
|
||||
|
||||
#define PARAM_OUT(T, ID, DESC, ALIAS, DEF, REQ) \
|
||||
static mlpack::util::Option<T> \
|
||||
JOIN(JOIN(io_option_dummy_object_out_, __LINE__), opt) \
|
||||
(DEF, ID, DESC, ALIAS, #T, REQ, false, false, testName);
|
||||
|
||||
#define PARAM_MATRIX(ID, DESC, ALIAS, REQ, TRANS, IN) \
|
||||
static mlpack::util::Option<arma::mat> \
|
||||
JOIN(JOIN(io_option_dummy_object_matrix_, __LINE__), opt) \
|
||||
(arma::mat(), ID, DESC, ALIAS, "arma::mat", REQ, IN, !TRANS, \
|
||||
testName);
|
||||
|
||||
#define PARAM_UMATRIX(ID, DESC, ALIAS, REQ, TRANS, IN) \
|
||||
static mlpack::util::Option<arma::Mat<size_t>> \
|
||||
JOIN(JOIN(io_option_dummy_object_umatrix_, __LINE__), opt) \
|
||||
(arma::Mat<size_t>(), ID, DESC, ALIAS, "arma::Mat<size_t>", REQ, IN, \
|
||||
!TRANS, testName);
|
||||
|
||||
#define PARAM_COL(ID, DESC, ALIAS, REQ, TRANS, IN) \
|
||||
static mlpack::util::Option<arma::vec> \
|
||||
JOIN(io_option_dummy_object_col_, __LINE__) \
|
||||
(arma::vec(), ID, DESC, ALIAS, "arma::vec", REQ, IN, !TRANS, \
|
||||
testName);
|
||||
|
||||
#define PARAM_UCOL(ID, DESC, ALIAS, REQ, TRANS, IN) \
|
||||
static mlpack::util::Option<arma::Col<size_t>> \
|
||||
JOIN(io_option_dummy_object_ucol_, __LINE__) \
|
||||
(arma::Col<size_t>(), ID, DESC, ALIAS, "arma::Col<size_t>", REQ, IN, \
|
||||
!TRANS, testName);
|
||||
|
||||
#define PARAM_ROW(ID, DESC, ALIAS, REQ, TRANS, IN) \
|
||||
static mlpack::util::Option<arma::rowvec> \
|
||||
JOIN(io_option_dummy_object_row_, __LINE__) \
|
||||
(arma::rowvec(), ID, DESC, ALIAS, "arma::rowvec", REQ, IN, !TRANS, \
|
||||
testName);
|
||||
|
||||
#define PARAM_UROW(ID, DESC, ALIAS, REQ, TRANS, IN) \
|
||||
static mlpack::util::Option<arma::Row<size_t>> \
|
||||
JOIN(io_option_dummy_object_urow_, __LINE__) \
|
||||
(arma::Row<size_t>(), ID, DESC, ALIAS, "arma::Row<size_t>", REQ, IN, \
|
||||
!TRANS, testName);
|
||||
(DEF, ID, DESC, ALIAS, NAME, REQ, IN, !TRANS, testName);
|
||||
|
||||
#define PARAM_MODEL(TYPE, ID, DESC, ALIAS, REQ, IN) \
|
||||
static mlpack::util::Option<TYPE*> \
|
||||
|
||||
@@ -43,11 +43,14 @@ namespace util {
|
||||
* @param fatal If true, output goes to Log::Fatal instead of Log::Warn and an
|
||||
* exception is thrown.
|
||||
* @param customErrorMessage Error message to append.
|
||||
* @param allowNone If true, then no error message will be thrown if none of the
|
||||
* parameters in the constraints were passed.
|
||||
*/
|
||||
void RequireOnlyOnePassed(
|
||||
const std::vector<std::string>& constraints,
|
||||
const bool fatal = true,
|
||||
const std::string& customErrorMessage = "");
|
||||
const std::string& customErrorMessage = "",
|
||||
const bool allowNone = false);
|
||||
|
||||
/**
|
||||
* Require that at least one of the given parameters in the constraints set was
|
||||
|
||||
@@ -21,7 +21,8 @@ namespace util {
|
||||
inline void RequireOnlyOnePassed(
|
||||
const std::vector<std::string>& constraints,
|
||||
const bool fatal,
|
||||
const std::string& errorMessage)
|
||||
const std::string& errorMessage,
|
||||
const bool allowNone)
|
||||
{
|
||||
if (BINDING_IGNORE_CHECK(constraints))
|
||||
return;
|
||||
@@ -57,7 +58,7 @@ inline void RequireOnlyOnePassed(
|
||||
stream << "; " << errorMessage;
|
||||
stream << "!" << std::endl;
|
||||
}
|
||||
else if (set == 0)
|
||||
else if (set == 0 && !allowNone)
|
||||
{
|
||||
stream << (fatal ? "Must " : "Should ");
|
||||
|
||||
|
||||
@@ -178,8 +178,7 @@ PrefixedOutStream::BaseLogic(const T& val)
|
||||
if (maxVal == 0.0)
|
||||
maxVal = 1;
|
||||
|
||||
int maxLog = log10(maxVal);
|
||||
maxLog = (maxLog > 0) ? floor(maxLog) + 1 : 1;
|
||||
const int maxLog = int(log10(maxVal)) + 1;
|
||||
const int padding = 4;
|
||||
convert.width(convert.precision() + maxLog + padding);
|
||||
printVal.raw_print(convert);
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
/**
|
||||
* @file size_checks.hpp
|
||||
* @author Kirill Mishchenko
|
||||
* @author Bisakh Mondal
|
||||
*
|
||||
* Utility for checking same size & same dimensionality.
|
||||
*
|
||||
* 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_UTIL_SIZE_CHECKS_HPP
|
||||
#define MLPACK_UTIL_SIZE_CHECKS_HPP
|
||||
|
||||
|
||||
namespace mlpack {
|
||||
namespace util {
|
||||
|
||||
/**
|
||||
* Check for if the given data points & labels have same size.
|
||||
*
|
||||
* @param data data.
|
||||
* @param labels Labels.
|
||||
* @param callerDescription A description of the caller that can be used for
|
||||
* error generation.
|
||||
* @param addInfo Name to use for labels for precise error generation. Default
|
||||
* is "labels"; for example, "weights" could also be used.
|
||||
*/
|
||||
template<typename DataType, typename LabelsType>
|
||||
inline void CheckSameSizes(const DataType& data,
|
||||
const LabelsType& label,
|
||||
const std::string& callerDescription,
|
||||
const std::string& addInfo = "labels")
|
||||
{
|
||||
if (data.n_cols != label.n_elem)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << callerDescription << ": number of points (" << data.n_cols << ") "
|
||||
<< "does not match number of " << addInfo << " (" << label.n_elem << ")!"
|
||||
<< std::endl;
|
||||
throw std::invalid_argument(oss.str());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An overload of CheckSameSizes() where the size to be checked is known
|
||||
* previously. The second parameter is of type unsigned int.
|
||||
*/
|
||||
template<typename DataType>
|
||||
inline void CheckSameSizes(const DataType& data,
|
||||
const size_t& size,
|
||||
const std::string& callerDescription,
|
||||
const std::string& addInfo = "labels")
|
||||
{
|
||||
if (data.n_cols != size)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << callerDescription << ": number of points (" << data.n_cols << ") "
|
||||
<< "does not match number of " << addInfo << " (" << size << ")!"
|
||||
<< std::endl;
|
||||
throw std::invalid_argument(oss.str());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check for if the given dataset dimension matches with the model's.
|
||||
*
|
||||
* @param data dataset.
|
||||
* @param dimension Dimension of the model.
|
||||
* @param callerDescription A description of the caller that can be used for
|
||||
* error generation.
|
||||
* @param addInfo Name to use for dataset for precise error generation. Default
|
||||
* is "dataset"; for example, "weights" could also be used.
|
||||
*/
|
||||
template<typename DataType, typename DimType>
|
||||
inline void CheckSameDimensionality(const DataType& data,
|
||||
const DimType& dimension,
|
||||
const std::string& callerDescription,
|
||||
const std::string& addInfo = "dataset")
|
||||
{
|
||||
if (data.n_rows != dimension.n_rows)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << callerDescription << ": dimensionality of " << addInfo << " ("
|
||||
<< data.n_rows << ") is not equal to the dimensionality of the model"
|
||||
" (" << dimension.n_rows << ")!";
|
||||
|
||||
throw std::invalid_argument(oss.str());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An overload of CheckSameDimensionality() where the dimension to be checked
|
||||
* is known second param is unsigned long int.
|
||||
*/
|
||||
template<typename DataType>
|
||||
inline void CheckSameDimensionality(const DataType& data,
|
||||
const size_t& dimension,
|
||||
const std::string& callerDescription,
|
||||
const std::string& addInfo = "dataset")
|
||||
{
|
||||
if (data.n_rows != dimension)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << callerDescription << ": dimensionality of " << addInfo << " ("
|
||||
<< data.n_rows << ") is not equal to the dimensionality of the model"
|
||||
" (" << dimension << ")!";
|
||||
throw std::invalid_argument(oss.str());
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace util
|
||||
} // namespace mlpack
|
||||
|
||||
#endif
|
||||
@@ -19,12 +19,13 @@ namespace util {
|
||||
* Convert a string to lowercase letters.
|
||||
*
|
||||
* @param input The string to convert.
|
||||
* @param output The string to be converted.
|
||||
*/
|
||||
inline void ToLower(const std::string& input, std::string& output)
|
||||
inline std::string ToLower(const std::string& input)
|
||||
{
|
||||
std::transform(input.begin(), input.end(), output.begin(),
|
||||
std::string output;
|
||||
std::transform(input.begin(), input.end(), std::back_inserter(output),
|
||||
[](unsigned char c){ return std::tolower(c); });
|
||||
return output;
|
||||
}
|
||||
|
||||
} // namespace util
|
||||
|
||||
@@ -72,19 +72,40 @@ AdaBoostModel::AdaBoostModel(AdaBoostModel&& other) :
|
||||
//! Copy assignment operator.
|
||||
AdaBoostModel& AdaBoostModel::operator=(const AdaBoostModel& other)
|
||||
{
|
||||
mappings = other.mappings;
|
||||
weakLearnerType = other.weakLearnerType;
|
||||
if (this != &other)
|
||||
{
|
||||
mappings = other.mappings;
|
||||
weakLearnerType = other.weakLearnerType;
|
||||
|
||||
delete dsBoost;
|
||||
dsBoost = (other.dsBoost == NULL) ? NULL :
|
||||
new AdaBoost<ID3DecisionStump>(*other.dsBoost);
|
||||
delete dsBoost;
|
||||
dsBoost = (other.dsBoost == NULL) ? NULL :
|
||||
new AdaBoost<ID3DecisionStump>(*other.dsBoost);
|
||||
|
||||
delete pBoost;
|
||||
pBoost = (other.pBoost == NULL) ? NULL :
|
||||
new AdaBoost<Perceptron<>>(*other.pBoost);
|
||||
delete pBoost;
|
||||
pBoost = (other.pBoost == NULL) ? NULL :
|
||||
new AdaBoost<Perceptron<>>(*other.pBoost);
|
||||
|
||||
dimensionality = other.dimensionality;
|
||||
dimensionality = other.dimensionality;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
//! Move assignment operator.
|
||||
AdaBoostModel& AdaBoostModel::operator=(AdaBoostModel&& other)
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
mappings = std::move(other.mappings);
|
||||
weakLearnerType = other.weakLearnerType;
|
||||
|
||||
dsBoost = other.dsBoost;
|
||||
other.dsBoost = nullptr;
|
||||
|
||||
pBoost = other.pBoost;
|
||||
other.pBoost = nullptr;
|
||||
|
||||
dimensionality = other.dimensionality;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
@@ -61,6 +61,9 @@ class AdaBoostModel
|
||||
//! Copy assignment operator.
|
||||
AdaBoostModel& operator=(const AdaBoostModel& other);
|
||||
|
||||
//! Move assignment operator.
|
||||
AdaBoostModel& operator=(AdaBoostModel&& other);
|
||||
|
||||
//! Clean up memory.
|
||||
~AdaBoostModel();
|
||||
|
||||
|
||||
@@ -36,7 +36,8 @@ class CompleteIncrementalTermination
|
||||
*/
|
||||
CompleteIncrementalTermination(
|
||||
TerminationPolicy tPolicy = TerminationPolicy()) :
|
||||
tPolicy(tPolicy) { }
|
||||
tPolicy(tPolicy), incrementalIndex(0), iteration(0)
|
||||
{ /* Nothing to do here. */ }
|
||||
|
||||
/**
|
||||
* Initializes the termination policy before stating the factorization.
|
||||
@@ -119,4 +120,3 @@ class CompleteIncrementalTermination
|
||||
} // namespace mlpack
|
||||
|
||||
#endif // MLPACK_METHODS_AMF_COMPLETE_INCREMENTAL_TERMINATION_HPP
|
||||
|
||||
|
||||
@@ -35,7 +35,8 @@ class IncompleteIncrementalTermination
|
||||
*/
|
||||
IncompleteIncrementalTermination(
|
||||
TerminationPolicy tPolicy = TerminationPolicy()) :
|
||||
tPolicy(tPolicy) { }
|
||||
tPolicy(tPolicy), incrementalIndex(0), iteration(0)
|
||||
{ /* Nothing to do here. */ }
|
||||
|
||||
/**
|
||||
* Initializes the termination policy before stating the factorization.
|
||||
|
||||
@@ -40,8 +40,16 @@ class SimpleResidueTermination
|
||||
* @param maxIterations Maximum number of iterations.
|
||||
*/
|
||||
SimpleResidueTermination(const double minResidue = 1e-5,
|
||||
const size_t maxIterations = 10000)
|
||||
: minResidue(minResidue), maxIterations(maxIterations) { }
|
||||
const size_t maxIterations = 10000) :
|
||||
minResidue(minResidue),
|
||||
maxIterations(maxIterations),
|
||||
residue(0.0),
|
||||
iteration(0),
|
||||
normOld(0),
|
||||
nm(0)
|
||||
{
|
||||
// Nothing to do here.
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the termination policy before stating the factorization.
|
||||
|
||||
@@ -56,7 +56,7 @@ class SVDCompleteIncrementalLearning
|
||||
SVDCompleteIncrementalLearning(double u = 0.0001,
|
||||
double kw = 0,
|
||||
double kh = 0)
|
||||
: u(u), kw(kw), kh(kh)
|
||||
: u(u), kw(kw), kh(kh), currentUserIndex(0), currentItemIndex(0)
|
||||
{
|
||||
// Nothing to do.
|
||||
}
|
||||
@@ -172,7 +172,7 @@ class SVDCompleteIncrementalLearning<arma::sp_mat>
|
||||
SVDCompleteIncrementalLearning(double u = 0.01,
|
||||
double kw = 0,
|
||||
double kh = 0)
|
||||
: u(u), kw(kw), kh(kh), it(NULL)
|
||||
: u(u), kw(kw), kh(kh), n(0), m(0), it(NULL), isStart(false)
|
||||
{}
|
||||
|
||||
~SVDCompleteIncrementalLearning()
|
||||
|
||||
@@ -53,7 +53,7 @@ class SVDIncompleteIncrementalLearning
|
||||
SVDIncompleteIncrementalLearning(double u = 0.001,
|
||||
double kw = 0,
|
||||
double kh = 0)
|
||||
: u(u), kw(kw), kh(kh)
|
||||
: u(u), kw(kw), kh(kh), currentUserIndex(0)
|
||||
{
|
||||
// Nothing to do.
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ set(SOURCES
|
||||
multi_quadratic_function.hpp
|
||||
poisson1_function.hpp
|
||||
gaussian_function.hpp
|
||||
hard_swish_function.hpp
|
||||
)
|
||||
|
||||
# Add directory name to sources.
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
/**
|
||||
* @file methods/ann/activation_functions/hard_swish_function.hpp
|
||||
* @author Anush Kini
|
||||
*
|
||||
* Definition and implementation of the Hard Swish function as described by
|
||||
* Howard A, Sandler M, Chu G, Chen LC, Chen B, Tan M, Wang W, Zhu Y, Pang R,
|
||||
* Vasudevan V and Le QV.
|
||||
* For more information, see the following paper.
|
||||
*
|
||||
* @code
|
||||
* @misc{
|
||||
* author = {Howard A, Sandler M, Chu G, Chen LC, Chen B, Tan M, Wang W,
|
||||
* Zhu Y, Pang R, Vasudevan V and Le QV},
|
||||
* title = {Searching for MobileNetV3},
|
||||
* year = {2019}
|
||||
* }
|
||||
* @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_HARD_SWISH_FUNCTION_HPP
|
||||
#define MLPACK_METHODS_ANN_ACTIVATION_FUNCTIONS_HARD_SWISH_FUNCTION_HPP
|
||||
|
||||
#include <mlpack/prereqs.hpp>
|
||||
|
||||
namespace mlpack {
|
||||
namespace ann /** Artificial Neural Network. */ {
|
||||
/**
|
||||
* The Hard Swish function, defined by
|
||||
*
|
||||
* @f{eqnarray*}{
|
||||
* f(x) &=& \begin{cases}
|
||||
* 0 & x \leq -3\\
|
||||
* x & x \geq +3\\
|
||||
* \frac{x * (x + 3)}{6} & otherwise\\
|
||||
* \end{cases} \\
|
||||
* f'(x) &=& \begin{cases}
|
||||
* 0 & x \leq -3\\
|
||||
* 1 & x \geq +3\\
|
||||
* \frac{2x + 3}{6} & otherwise\\
|
||||
* \end{cases}
|
||||
* @f}
|
||||
*/
|
||||
class HardSwishFunction
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Computes the Hard Swish function.
|
||||
*
|
||||
* @param x Input data.
|
||||
* @return f(x).
|
||||
*/
|
||||
static double Fn(const double x)
|
||||
{
|
||||
if (x <= -3)
|
||||
return 0;
|
||||
else if (x >= 3)
|
||||
return x;
|
||||
|
||||
return x * (x + 3) / 6;
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the Hard Swish 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.set_size(size(x));
|
||||
|
||||
for (size_t i = 0; i < x.n_elem; i++)
|
||||
y(i) = Fn(x(i));
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the first derivative of the Hard Swish function.
|
||||
*
|
||||
* @param y Input data.
|
||||
* @return f'(x).
|
||||
*/
|
||||
static double Deriv(const double y)
|
||||
{
|
||||
if (y <= -3)
|
||||
return 0;
|
||||
else if (y >= 3)
|
||||
return 1;
|
||||
|
||||
return (2 * y + 3.0) / 6.0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the first derivatives of the Hard Swish function.
|
||||
*
|
||||
* @param y Input data.
|
||||
* @param x The resulting derivatives.
|
||||
*/
|
||||
template <typename InputVecType, typename OutputVecType>
|
||||
static void Deriv(const InputVecType &y, OutputVecType &x)
|
||||
{
|
||||
x.set_size(size(y));
|
||||
|
||||
for (size_t i = 0; i < y.n_elem; i++)
|
||||
x(i) = Deriv(y(i));
|
||||
}
|
||||
}; // class HardSwishFunction
|
||||
|
||||
} // namespace ann
|
||||
} // namespace mlpack
|
||||
|
||||
#endif
|
||||
@@ -46,6 +46,8 @@ set(SOURCES
|
||||
hard_tanh_impl.hpp
|
||||
highway.hpp
|
||||
highway_impl.hpp
|
||||
isrlu.hpp
|
||||
isrlu_impl.hpp
|
||||
join.hpp
|
||||
join_impl.hpp
|
||||
layer.hpp
|
||||
@@ -63,6 +65,8 @@ set(SOURCES
|
||||
log_softmax_impl.hpp
|
||||
lookup.hpp
|
||||
lookup_impl.hpp
|
||||
lp_pooling.hpp
|
||||
lp_pooling_impl.hpp
|
||||
lstm.hpp
|
||||
lstm_impl.hpp
|
||||
max_pooling.hpp
|
||||
@@ -81,6 +85,8 @@ set(SOURCES
|
||||
noisylinear_impl.hpp
|
||||
parametric_relu.hpp
|
||||
parametric_relu_impl.hpp
|
||||
pixel_shuffle.hpp
|
||||
pixel_shuffle_impl.hpp
|
||||
positional_encoding.hpp
|
||||
positional_encoding_impl.hpp
|
||||
recurrent.hpp
|
||||
|
||||
@@ -125,8 +125,7 @@ AtrousConvolution<
|
||||
weights.set_size(WeightSize(), 1);
|
||||
|
||||
// Transform paddingType to lowercase.
|
||||
std::string paddingTypeLow = paddingType;
|
||||
util::ToLower(paddingType, paddingTypeLow);
|
||||
const std::string paddingTypeLow = util::ToLower(paddingType);
|
||||
|
||||
size_t padWLeft = std::get<0>(padW);
|
||||
size_t padWRight = std::get<1>(padW);
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include <mlpack/methods/ann/activation_functions/elliot_function.hpp>
|
||||
#include <mlpack/methods/ann/activation_functions/elish_function.hpp>
|
||||
#include <mlpack/methods/ann/activation_functions/gaussian_function.hpp>
|
||||
#include <mlpack/methods/ann/activation_functions/hard_swish_function.hpp>
|
||||
|
||||
namespace mlpack {
|
||||
namespace ann /** Artificial Neural Network. */ {
|
||||
@@ -50,6 +51,7 @@ namespace ann /** Artificial Neural Network. */ {
|
||||
* - ELiSHLayer
|
||||
* - ElliotLayer
|
||||
* - GaussianLayer
|
||||
* - HardSwishLayer
|
||||
*
|
||||
* @tparam ActivationFunction Activation function used for the embedding layer.
|
||||
* @tparam InputDataType Type of the input data (arma::colvec, arma::mat,
|
||||
@@ -277,6 +279,17 @@ template <
|
||||
using GaussianFunctionLayer = BaseLayer<
|
||||
ActivationFunction, InputDataType, OutputDataType>;
|
||||
|
||||
/**
|
||||
* Standard HardSwish-Layer using the HardSwish activation function.
|
||||
*/
|
||||
template <
|
||||
class ActivationFunction = HardSwishFunction,
|
||||
typename InputDataType = arma::mat,
|
||||
typename OutputDataType = arma::mat
|
||||
>
|
||||
using HardSwishFunctionLayer = BaseLayer<
|
||||
ActivationFunction, InputDataType, OutputDataType>;
|
||||
|
||||
} // namespace ann
|
||||
} // namespace mlpack
|
||||
|
||||
|
||||
@@ -79,6 +79,12 @@ class Constant
|
||||
//! Get the output size.
|
||||
size_t OutSize() const { return outSize; }
|
||||
|
||||
//! Get the size of the weights.
|
||||
size_t WeightSize() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Serialize the layer.
|
||||
*/
|
||||
|
||||
@@ -29,6 +29,35 @@ namespace ann /** Artificial Neural Network. */ {
|
||||
/**
|
||||
* Implementation of the Convolution class. The Convolution class represents a
|
||||
* single layer of a neural network.
|
||||
* Example usage:
|
||||
*
|
||||
* Suppose we want to pass a matrix M (2744x100) to a `Convolution` layer;
|
||||
* in this example, `M` was obtained from "flattening" 100 images (or Mel
|
||||
* cepstral coefficients, if we talk about speech, or whatever you like) of
|
||||
* dimension 196x14. In other words, the first 196 columns of each row of M
|
||||
* will be made of the 196 columns of the first row of each of the 100 images
|
||||
* (or Mel cepstral coefficients). Then the next 295 columns of M (196 - 393)
|
||||
* will be made of the 196 columns of the second row of the 100 images (or Mel
|
||||
* cepstral coefficients), etc. Given that the size of our 2-D input images is
|
||||
* 196x14, the parameters for our `Convolution` layer will be something like
|
||||
* this:
|
||||
*
|
||||
* ```
|
||||
* Convolution<> c(1, // Number of input activation maps.
|
||||
* 14, // Number of output activation maps.
|
||||
* 3, // Filter width.
|
||||
* 3, // Filter height.
|
||||
* 1, // Stride along width.
|
||||
* 1, // Stride along height.
|
||||
* 0, // Padding width.
|
||||
* 0, // Padding height.
|
||||
* 196, // Input width.
|
||||
* 14); // Input height.
|
||||
* ```
|
||||
*
|
||||
* This `Convolution<>` layer will treat each column of the input matrix `M` as
|
||||
* a 2-D image (or object) of the original 196x14 size, using this as the input
|
||||
* for the 14 filters of this example.
|
||||
*
|
||||
* @tparam ForwardConvolutionRule Convolution to perform forward process.
|
||||
* @tparam BackwardConvolutionRule Convolution to perform backward process.
|
||||
|
||||
@@ -120,8 +120,7 @@ Convolution<
|
||||
weights.set_size(WeightSize(), 1);
|
||||
|
||||
// Transform paddingType to lowercase.
|
||||
std::string paddingTypeLow = paddingType;
|
||||
util::ToLower(paddingType, paddingTypeLow);
|
||||
const std::string paddingTypeLow = util::ToLower(paddingType);
|
||||
|
||||
if (paddingTypeLow == "valid")
|
||||
{
|
||||
|
||||
@@ -163,33 +163,20 @@ void FastLSTM<InputDataType, OutputDataType>::ResetCell(const size_t size)
|
||||
gradientStep = batchSize * size - 1;
|
||||
|
||||
const size_t rhoBatchSize = size * batchSize;
|
||||
if (gate.is_empty() || gate.n_cols != rhoBatchSize)
|
||||
{
|
||||
gate.set_size(4 * outSize, rhoBatchSize);
|
||||
gateActivation.set_size(outSize * 3, rhoBatchSize);
|
||||
stateActivation.set_size(outSize, rhoBatchSize);
|
||||
cellActivation.set_size(outSize, rhoBatchSize);
|
||||
prevError.set_size(4 * outSize, batchSize);
|
||||
|
||||
if (prevOutput.is_empty())
|
||||
{
|
||||
prevOutput = arma::zeros<OutputDataType>(outSize, batchSize);
|
||||
cell = arma::zeros(outSize, size * batchSize);
|
||||
cellActivationError = arma::zeros<OutputDataType>(outSize, batchSize);
|
||||
outParameter = arma::zeros<OutputDataType>(
|
||||
outSize, (size + 1) * batchSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
// To preserve the leading zeros, recreate the object according to given
|
||||
// size specifications, while preserving the elements as well as the
|
||||
// layout of the elements.
|
||||
prevOutput.resize(outSize, batchSize);
|
||||
cell.resize(outSize, size * batchSize);
|
||||
cellActivationError.resize(outSize, batchSize);
|
||||
outParameter.resize(outSize, (size + 1) * batchSize);
|
||||
}
|
||||
}
|
||||
// Make sure all of the matrices we use to store state are at least as large
|
||||
// as we need.
|
||||
gate.set_size(4 * outSize, rhoBatchSize);
|
||||
gateActivation.set_size(outSize * 3, rhoBatchSize);
|
||||
stateActivation.set_size(outSize, rhoBatchSize);
|
||||
cellActivation.set_size(outSize, rhoBatchSize);
|
||||
prevError.set_size(4 * outSize, batchSize);
|
||||
|
||||
// Reset stored state to zeros.
|
||||
prevOutput.zeros(outSize, batchSize);
|
||||
cell.zeros(outSize, size * batchSize);
|
||||
cellActivationError.zeros(outSize, batchSize);
|
||||
outParameter.zeros(outSize, (size + 1) * batchSize);
|
||||
}
|
||||
|
||||
template<typename InputDataType, typename OutputDataType>
|
||||
|
||||
@@ -0,0 +1,138 @@
|
||||
/**
|
||||
* @file methods/ann/layer/isrlu.hpp
|
||||
* @author Abhinav Anand
|
||||
*
|
||||
* Definition of the ISRLU activation function as described by Jonathan T. Barron.
|
||||
*
|
||||
* For more information, read the following paper.
|
||||
*
|
||||
* @code
|
||||
* @article{
|
||||
* author = {Carlile, Brad and Delamarter, Guy and Kinney, Paul and Marti,
|
||||
* Akiko and Whitney, Brian},
|
||||
* title = {Improving deep learning by inverse square root linear units (ISRLUs)},
|
||||
* year = {2017},
|
||||
* url = {https://arxiv.org/pdf/1710.09967.pdf}
|
||||
* }
|
||||
* @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_LAYER_ISRLU_HPP
|
||||
#define MLPACK_METHODS_ANN_LAYER_ISRLU_HPP
|
||||
|
||||
#include <mlpack/prereqs.hpp>
|
||||
|
||||
namespace mlpack {
|
||||
namespace ann /** Artificial Neural Network. */ {
|
||||
|
||||
/**
|
||||
* The ISRLU activation function, defined by
|
||||
*
|
||||
* @f{eqnarray*}{
|
||||
* f(x) &=& \left\{
|
||||
* \begin{array}{lr}
|
||||
* x & : x \ge 0 \\
|
||||
* x(\frac{1}{1 + \alpha x^2}) & : x < 0
|
||||
* \end{array}
|
||||
* \right. \\
|
||||
* f'(x) &=& \left\{
|
||||
* \begin{array}{lr}
|
||||
* x & : 1 \ge 0 \\
|
||||
* (\frac{1}{1 + \alpha x^2})^3 & : x < 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 ISRLU
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Create the ISRLU object using the specified parameter.
|
||||
*
|
||||
* @param alpha Scale parameter controls the value to which an ISRLU
|
||||
* saturates for negative inputs.
|
||||
*/
|
||||
ISRLU(const double alpha = 1.0);
|
||||
|
||||
/**
|
||||
* 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 f(x).
|
||||
* @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 non zero gradient.
|
||||
double const& Alpha() const { return alpha; }
|
||||
//! Modify the non zero gradient.
|
||||
double& Alpha() { return alpha; }
|
||||
|
||||
//! Get size of weights.
|
||||
size_t WeightSize() { 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;
|
||||
|
||||
//! Locally stored first derivative of the activation function.
|
||||
arma::mat derivative;
|
||||
|
||||
//! ISRLU Hyperparameter (alpha > 0).
|
||||
double alpha;
|
||||
|
||||
}; // class ISRLU
|
||||
|
||||
} // namespace ann
|
||||
} // namespace mlpack
|
||||
|
||||
// Include implementation.
|
||||
#include "isrlu_impl.hpp"
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,65 @@
|
||||
/**
|
||||
* @file methods/ann/layer/isrlu_impl.hpp
|
||||
* @author Abhinav Anand
|
||||
*
|
||||
* Implementation of the ISRLU activation function as described by Jonathan T. Barron.
|
||||
*
|
||||
* 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_ISRLU_IMPL_HPP
|
||||
#define MLPACK_METHODS_ANN_LAYER_ISRLU_IMPL_HPP
|
||||
|
||||
// In case it hasn't yet been included.
|
||||
#include "isrlu.hpp"
|
||||
|
||||
namespace mlpack {
|
||||
namespace ann /** Artificial Neural Network. */ {
|
||||
|
||||
template<typename InputDataType, typename OutputDataType>
|
||||
ISRLU<InputDataType, OutputDataType>::ISRLU(const double alpha) :
|
||||
alpha(alpha)
|
||||
{}
|
||||
|
||||
template<typename InputDataType, typename OutputDataType>
|
||||
template<typename InputType, typename OutputType>
|
||||
void ISRLU<InputDataType, OutputDataType>::Forward(
|
||||
const InputType& input, OutputType& output)
|
||||
{
|
||||
output = arma::ones<OutputDataType>(arma::size(input));
|
||||
for (size_t i = 0; i < input.n_elem; ++i)
|
||||
{
|
||||
output(i) = (input(i) >= 0) ? input(i) : input(i) *
|
||||
(1 / std::sqrt(1 + alpha * (input(i) * input(i))));
|
||||
}
|
||||
}
|
||||
|
||||
template<typename InputDataType, typename OutputDataType>
|
||||
template<typename DataType>
|
||||
void ISRLU<InputDataType, OutputDataType>::Backward(
|
||||
const DataType& input, const DataType& gy, DataType& g)
|
||||
{
|
||||
derivative.set_size(arma::size(input));
|
||||
for (size_t i = 0; i < input.n_elem; ++i)
|
||||
{
|
||||
derivative(i) = (input(i) >= 0) ? 1 :
|
||||
std::pow(1 / std::sqrt(1 + alpha * input(i) * input(i)), 3);
|
||||
}
|
||||
g = gy % derivative;
|
||||
}
|
||||
|
||||
template<typename InputDataType, typename OutputDataType>
|
||||
template<typename Archive>
|
||||
void ISRLU<InputDataType, OutputDataType>::serialize(
|
||||
Archive& ar,
|
||||
const uint32_t /* version */)
|
||||
{
|
||||
ar(CEREAL_NVP(alpha));
|
||||
}
|
||||
|
||||
} // namespace ann
|
||||
} // namespace mlpack
|
||||
|
||||
#endif
|
||||
@@ -47,6 +47,7 @@
|
||||
#include "linear3d.hpp"
|
||||
#include "log_softmax.hpp"
|
||||
#include "lookup.hpp"
|
||||
#include "lp_pooling.hpp"
|
||||
#include "lstm.hpp"
|
||||
#include "max_pooling.hpp"
|
||||
#include "mean_pooling.hpp"
|
||||
@@ -57,6 +58,7 @@
|
||||
#include "noisylinear.hpp"
|
||||
#include "padding.hpp"
|
||||
#include "parametric_relu.hpp"
|
||||
#include "pixel_shuffle.hpp"
|
||||
#include "positional_encoding.hpp"
|
||||
#include "recurrent_attention.hpp"
|
||||
#include "recurrent.hpp"
|
||||
|
||||
@@ -38,10 +38,12 @@
|
||||
#include <mlpack/methods/ann/layer/multiply_constant.hpp>
|
||||
#include <mlpack/methods/ann/layer/max_pooling.hpp>
|
||||
#include <mlpack/methods/ann/layer/mean_pooling.hpp>
|
||||
#include <mlpack/methods/ann/layer/lp_pooling.hpp>
|
||||
#include <mlpack/methods/ann/layer/noisylinear.hpp>
|
||||
#include <mlpack/methods/ann/layer/adaptive_max_pooling.hpp>
|
||||
#include <mlpack/methods/ann/layer/adaptive_mean_pooling.hpp>
|
||||
#include <mlpack/methods/ann/layer/parametric_relu.hpp>
|
||||
#include <mlpack/methods/ann/layer/pixel_shuffle.hpp>
|
||||
#include <mlpack/methods/ann/layer/positional_encoding.hpp>
|
||||
#include <mlpack/methods/ann/layer/reinforce_normal.hpp>
|
||||
#include <mlpack/methods/ann/layer/reparametrization.hpp>
|
||||
@@ -52,6 +54,7 @@
|
||||
#include <mlpack/methods/ann/layer/virtual_batch_norm.hpp>
|
||||
#include <mlpack/methods/ann/layer/hardshrink.hpp>
|
||||
#include <mlpack/methods/ann/layer/celu.hpp>
|
||||
#include <mlpack/methods/ann/layer/isrlu.hpp>
|
||||
#include <mlpack/methods/ann/layer/softshrink.hpp>
|
||||
#include <mlpack/methods/ann/layer/radial_basis_function.hpp>
|
||||
|
||||
@@ -219,6 +222,8 @@ class AdaptiveMeanPooling;
|
||||
|
||||
using MoreTypes = boost::variant<
|
||||
Linear3D<arma::mat, arma::mat, NoRegularizer>*,
|
||||
LpPooling<arma::mat, arma::mat>*,
|
||||
PixelShuffle<arma::mat, arma::mat>*,
|
||||
Glimpse<arma::mat, arma::mat>*,
|
||||
Highway<arma::mat, arma::mat>*,
|
||||
MultiheadAttention<arma::mat, arma::mat, NoRegularizer>*,
|
||||
@@ -234,7 +239,8 @@ using MoreTypes = boost::variant<
|
||||
VirtualBatchNorm<arma::mat, arma::mat>*,
|
||||
RBF<arma::mat, arma::mat, GaussianFunction>*,
|
||||
BaseLayer<GaussianFunction, arma::mat, arma::mat>*,
|
||||
PositionalEncoding<arma::mat, arma::mat>*
|
||||
PositionalEncoding<arma::mat, arma::mat>*,
|
||||
ISRLU<arma::mat, arma::mat>*
|
||||
>;
|
||||
|
||||
template <typename... CustomLayers>
|
||||
|
||||
@@ -123,6 +123,12 @@ class LinearNoBias
|
||||
//! Modify the gradient.
|
||||
OutputDataType& Gradient() { return gradient; }
|
||||
|
||||
//! Get the size of the weights.
|
||||
size_t WeightSize() const
|
||||
{
|
||||
return inSize * outSize;
|
||||
}
|
||||
|
||||
//! Get the shape of the input.
|
||||
size_t InputShape() const
|
||||
{
|
||||
|
||||
@@ -38,7 +38,7 @@ LinearNoBias<InputDataType, OutputDataType, RegularizerType>::LinearNoBias(
|
||||
outSize(outSize),
|
||||
regularizer(regularizer)
|
||||
{
|
||||
weights.set_size(outSize * inSize, 1);
|
||||
weights.set_size(WeightSize(), 1);
|
||||
}
|
||||
|
||||
template<typename InputDataType, typename OutputDataType,
|
||||
|
||||
@@ -0,0 +1,284 @@
|
||||
/**
|
||||
* @file methods/ann/layer/lp_pooling.hpp
|
||||
* @author Abhinav Anan
|
||||
*
|
||||
* Definition of the LpPooling layer 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_METHODS_ANN_LAYER_LP_POOLING_HPP
|
||||
#define MLPACK_METHODS_ANN_LAYER_LP_POOLING_HPP
|
||||
|
||||
#include <mlpack/prereqs.hpp>
|
||||
|
||||
namespace mlpack {
|
||||
namespace ann /** Artificial Neural Network. */ {
|
||||
|
||||
/**
|
||||
* Implementation of the LPPooling.
|
||||
*
|
||||
* @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 LpPooling
|
||||
{
|
||||
public:
|
||||
//! Create the LpPooling object.
|
||||
LpPooling();
|
||||
|
||||
/**
|
||||
* Create the LpPooling object using the specified number of units.
|
||||
*
|
||||
* @param normType Parameter for type of norm.
|
||||
* @param kernelWidth Width of the pooling window.
|
||||
* @param kernelHeight Height of the pooling window.
|
||||
* @param strideWidth Width of the stride operation.
|
||||
* @param strideHeight Width of the stride operation.
|
||||
* @param floor Set to true to use floor method.
|
||||
*/
|
||||
LpPooling(const size_t normType,
|
||||
const size_t kernelWidth,
|
||||
const size_t kernelHeight,
|
||||
const size_t strideWidth = 1,
|
||||
const size_t strideHeight = 1,
|
||||
const bool floor = true);
|
||||
|
||||
/**
|
||||
* 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 eT>
|
||||
void Forward(const arma::Mat<eT>& input, arma::Mat<eT>& output);
|
||||
|
||||
/**
|
||||
* Ordinary feed backward pass of a neural network, using 3rd-order tensors as
|
||||
* input, 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 eT>
|
||||
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; }
|
||||
//! 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 intput width.
|
||||
size_t const& InputWidth() const { return inputWidth; }
|
||||
//! Modify the input width.
|
||||
size_t& InputWidth() { return inputWidth; }
|
||||
|
||||
//! Get the input height.
|
||||
size_t const& InputHeight() const { return inputHeight; }
|
||||
//! Modify the input height.
|
||||
size_t& InputHeight() { return inputHeight; }
|
||||
|
||||
//! Get the output width.
|
||||
size_t const& OutputWidth() const { return outputWidth; }
|
||||
//! Modify the output width.
|
||||
size_t& OutputWidth() { return outputWidth; }
|
||||
|
||||
//! Get the output height.
|
||||
size_t const& OutputHeight() const { return outputHeight; }
|
||||
//! Modify the output height.
|
||||
size_t& OutputHeight() { return outputHeight; }
|
||||
|
||||
//! Get the input size.
|
||||
size_t InputSize() const { return inSize; }
|
||||
|
||||
//! Get the output size.
|
||||
size_t OutputSize() const { return outSize; }
|
||||
|
||||
//! Get the normType.
|
||||
size_t NormType() const { return normType; }
|
||||
//! Modify the normType.
|
||||
size_t& NormType() { return normType; }
|
||||
|
||||
//! Get the kernel width.
|
||||
size_t KernelWidth() const { return kernelWidth; }
|
||||
//! Modify the kernel width.
|
||||
size_t& KernelWidth() { return kernelWidth; }
|
||||
|
||||
//! Get the kernel height.
|
||||
size_t KernelHeight() const { return kernelHeight; }
|
||||
//! Modify the kernel height.
|
||||
size_t& KernelHeight() { return kernelHeight; }
|
||||
|
||||
//! Get the stride width.
|
||||
size_t StrideWidth() const { return strideWidth; }
|
||||
//! Modify the stride width.
|
||||
size_t& StrideWidth() { return strideWidth; }
|
||||
|
||||
//! Get the stride height.
|
||||
size_t StrideHeight() const { return strideHeight; }
|
||||
//! Modify the stride height.
|
||||
size_t& StrideHeight() { return strideHeight; }
|
||||
|
||||
//! Get the value of the rounding operation
|
||||
bool const& Floor() const { return floor; }
|
||||
//! Modify the value of the rounding operation
|
||||
bool& Floor() { return floor; }
|
||||
|
||||
//! Get the size of the weights.
|
||||
size_t WeightSize() const { return 0; }
|
||||
|
||||
/**
|
||||
* Serialize the layer.
|
||||
*/
|
||||
template<typename Archive>
|
||||
void serialize(Archive& ar, const uint32_t /* version */);
|
||||
|
||||
private:
|
||||
/**
|
||||
* Apply pooling to the input and store the results.
|
||||
*
|
||||
* @param input The input to be apply the pooling rule.
|
||||
* @param output The pooled result.
|
||||
*/
|
||||
template<typename eT>
|
||||
void Pooling(const arma::Mat<eT>& input, arma::Mat<eT>& output)
|
||||
{
|
||||
for (size_t j = 0, colidx = 0; j < output.n_cols;
|
||||
++j, colidx += strideHeight)
|
||||
{
|
||||
for (size_t i = 0, rowidx = 0; i < output.n_rows;
|
||||
++i, rowidx += strideWidth)
|
||||
{
|
||||
arma::mat subInput = input(
|
||||
arma::span(rowidx, rowidx + kernelWidth - 1 - offset),
|
||||
arma::span(colidx, colidx + kernelHeight - 1 - offset));
|
||||
|
||||
output(i, j) = pow(arma::accu(arma::pow(subInput,
|
||||
normType)), 1.0 / normType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply unpooling to the input and store the results.
|
||||
*
|
||||
* @param input The input to be apply the unpooling rule.
|
||||
* @param output The pooled result.
|
||||
*/
|
||||
template<typename eT>
|
||||
void Unpooling(const arma::Mat<eT>& input,
|
||||
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 i = 0; i < input.n_rows - rStep; i += rStep)
|
||||
{
|
||||
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)),
|
||||
(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 /= sum;
|
||||
output(arma::span(i, i + rStep - 1 - offset),
|
||||
arma::span(j, j + cStep - 1 - offset)) += unpooledError;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//! Locally-stored norm type.
|
||||
size_t normType;
|
||||
|
||||
//! Locally-stored width of the pooling window.
|
||||
size_t kernelWidth;
|
||||
|
||||
//! Locally-stored height of the pooling window.
|
||||
size_t kernelHeight;
|
||||
|
||||
//! Locally-stored width of the stride operation.
|
||||
size_t strideWidth;
|
||||
|
||||
//! Locally-stored height of the stride operation.
|
||||
size_t strideHeight;
|
||||
|
||||
//! Rounding operation used.
|
||||
bool floor;
|
||||
|
||||
//! Locally-stored number of input channels.
|
||||
size_t inSize;
|
||||
|
||||
//! Locally-stored number of output channels.
|
||||
size_t outSize;
|
||||
|
||||
//! Locally-stored input width.
|
||||
size_t inputWidth;
|
||||
|
||||
//! Locally-stored input height.
|
||||
size_t inputHeight;
|
||||
|
||||
//! Locally-stored output width.
|
||||
size_t outputWidth;
|
||||
|
||||
//! Locally-stored output height.
|
||||
size_t outputHeight;
|
||||
|
||||
//! 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;
|
||||
|
||||
//! Locally-stored output parameter.
|
||||
arma::cube outputTemp;
|
||||
|
||||
//! Locally-stored transformed input parameter.
|
||||
arma::cube inputTemp;
|
||||
|
||||
//! Locally-stored transformed output parameter.
|
||||
arma::cube gTemp;
|
||||
|
||||
//! Locally-stored delta object.
|
||||
OutputDataType delta;
|
||||
|
||||
//! Locally-stored gradient object.
|
||||
OutputDataType gradient;
|
||||
|
||||
//! Locally-stored output parameter object.
|
||||
OutputDataType outputParameter;
|
||||
}; // class LpPooling
|
||||
|
||||
|
||||
} // namespace ann
|
||||
} // namespace mlpack
|
||||
|
||||
// Include implementation.
|
||||
#include "lp_pooling_impl.hpp"
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,141 @@
|
||||
/**
|
||||
* @file methods/ann/layer/lp_pooling_impl.hpp
|
||||
* @author Marcus Edel
|
||||
* @author Nilay Jain
|
||||
*
|
||||
* Implementation of the lpPooling layer 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_METHODS_ANN_LAYER_LP_POOLING_IMPL_HPP
|
||||
#define MLPACK_METHODS_ANN_LAYER_LP_POOLING_IMPL_HPP
|
||||
|
||||
// In case it hasn't yet been included.
|
||||
#include "lp_pooling.hpp"
|
||||
|
||||
namespace mlpack {
|
||||
namespace ann /** Artificial Neural Network. */ {
|
||||
|
||||
template<typename InputDataType, typename OutputDataType>
|
||||
LpPooling<InputDataType, OutputDataType>::LpPooling()
|
||||
{
|
||||
// Nothing to do here.
|
||||
}
|
||||
|
||||
template<typename InputDataType, typename OutputDataType>
|
||||
LpPooling<InputDataType, OutputDataType>::LpPooling(
|
||||
const size_t normType,
|
||||
const size_t kernelWidth,
|
||||
const size_t kernelHeight,
|
||||
const size_t strideWidth,
|
||||
const size_t strideHeight,
|
||||
const bool floor) :
|
||||
normType(normType),
|
||||
kernelWidth(kernelWidth),
|
||||
kernelHeight(kernelHeight),
|
||||
strideWidth(strideWidth),
|
||||
strideHeight(strideHeight),
|
||||
floor(floor),
|
||||
inSize(0),
|
||||
outSize(0),
|
||||
inputWidth(0),
|
||||
inputHeight(0),
|
||||
outputWidth(0),
|
||||
outputHeight(0),
|
||||
reset(false),
|
||||
offset(0),
|
||||
batchSize(0)
|
||||
{
|
||||
// Nothing to do here.
|
||||
}
|
||||
|
||||
template<typename InputDataType, typename OutputDataType>
|
||||
template<typename eT>
|
||||
void LpPooling<InputDataType, OutputDataType>::Forward(
|
||||
const arma::Mat<eT>& input, arma::Mat<eT>& output)
|
||||
{
|
||||
batchSize = input.n_cols;
|
||||
inSize = input.n_elem / (inputWidth * inputHeight * batchSize);
|
||||
inputTemp = arma::cube(const_cast<arma::Mat<eT>&>(input).memptr(),
|
||||
inputWidth, inputHeight, batchSize * inSize, false, false);
|
||||
|
||||
if (floor)
|
||||
{
|
||||
outputWidth = std::floor((inputWidth -
|
||||
(double) kernelWidth) / (double) strideWidth + 1);
|
||||
outputHeight = std::floor((inputHeight -
|
||||
(double) kernelHeight) / (double) strideHeight + 1);
|
||||
|
||||
offset = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
outputWidth = std::ceil((inputWidth -
|
||||
(double) kernelWidth) / (double) strideWidth + 1);
|
||||
outputHeight = std::ceil((inputHeight -
|
||||
(double) kernelHeight) / (double) strideHeight + 1);
|
||||
|
||||
offset = 1;
|
||||
}
|
||||
|
||||
outputTemp = arma::zeros<arma::Cube<eT> >(outputWidth, outputHeight,
|
||||
batchSize * inSize);
|
||||
|
||||
for (size_t s = 0; s < inputTemp.n_slices; s++)
|
||||
Pooling(inputTemp.slice(s), outputTemp.slice(s));
|
||||
|
||||
output = arma::Mat<eT>(outputTemp.memptr(), outputTemp.n_elem / batchSize,
|
||||
batchSize);
|
||||
|
||||
outputWidth = outputTemp.n_rows;
|
||||
outputHeight = outputTemp.n_cols;
|
||||
outSize = batchSize * inSize;
|
||||
}
|
||||
|
||||
template<typename InputDataType, typename OutputDataType>
|
||||
template<typename eT>
|
||||
void LpPooling<InputDataType, OutputDataType>::Backward(
|
||||
const arma::Mat<eT>& /* input */,
|
||||
const arma::Mat<eT>& gy,
|
||||
arma::Mat<eT>& g)
|
||||
{
|
||||
arma::cube mappedError = arma::cube(((arma::Mat<eT>&) gy).memptr(),
|
||||
outputWidth, outputHeight, outSize, false, false);
|
||||
|
||||
gTemp = arma::zeros<arma::cube>(inputTemp.n_rows,
|
||||
inputTemp.n_cols, inputTemp.n_slices);
|
||||
|
||||
for (size_t s = 0; s < mappedError.n_slices; s++)
|
||||
{
|
||||
Unpooling(inputTemp.slice(s), mappedError.slice(s), gTemp.slice(s));
|
||||
}
|
||||
|
||||
g = arma::mat(gTemp.memptr(), gTemp.n_elem / batchSize, batchSize);
|
||||
}
|
||||
|
||||
template<typename InputDataType, typename OutputDataType>
|
||||
template<typename Archive>
|
||||
void LpPooling<InputDataType, OutputDataType>::serialize(
|
||||
Archive& ar,
|
||||
const uint32_t /* version */)
|
||||
{
|
||||
ar(CEREAL_NVP(normType));
|
||||
ar(CEREAL_NVP(kernelWidth));
|
||||
ar(CEREAL_NVP(kernelHeight));
|
||||
ar(CEREAL_NVP(strideWidth));
|
||||
ar(CEREAL_NVP(strideHeight));
|
||||
ar(CEREAL_NVP(batchSize));
|
||||
ar(CEREAL_NVP(floor));
|
||||
ar(CEREAL_NVP(inputWidth));
|
||||
ar(CEREAL_NVP(inputHeight));
|
||||
ar(CEREAL_NVP(outputWidth));
|
||||
ar(CEREAL_NVP(outputHeight));
|
||||
}
|
||||
|
||||
} // namespace ann
|
||||
} // namespace mlpack
|
||||
|
||||
#endif
|
||||
@@ -144,36 +144,25 @@ void LSTM<InputDataType, OutputDataType>::ResetCell(const size_t size)
|
||||
gradientStep = batchSize * size - 1;
|
||||
|
||||
const size_t rhoBatchSize = size * batchSize;
|
||||
if (inputGate.is_empty() || inputGate.n_cols < rhoBatchSize)
|
||||
{
|
||||
inputGate.set_size(outSize, rhoBatchSize);
|
||||
forgetGate.set_size(outSize, rhoBatchSize);
|
||||
hiddenLayer.set_size(outSize, rhoBatchSize);
|
||||
outputGate.set_size(outSize, rhoBatchSize);
|
||||
|
||||
inputGateActivation.set_size(outSize, rhoBatchSize);
|
||||
forgetGateActivation.set_size(outSize, rhoBatchSize);
|
||||
outputGateActivation.set_size(outSize, rhoBatchSize);
|
||||
hiddenLayerActivation.set_size(outSize, rhoBatchSize);
|
||||
// Make sure all of the different matrices we will use to hold parameters are
|
||||
// at least as large as we need.
|
||||
inputGate.set_size(outSize, rhoBatchSize);
|
||||
forgetGate.set_size(outSize, rhoBatchSize);
|
||||
hiddenLayer.set_size(outSize, rhoBatchSize);
|
||||
outputGate.set_size(outSize, rhoBatchSize);
|
||||
|
||||
cellActivation.set_size(outSize, rhoBatchSize);
|
||||
prevError.set_size(4 * outSize, batchSize);
|
||||
inputGateActivation.set_size(outSize, rhoBatchSize);
|
||||
forgetGateActivation.set_size(outSize, rhoBatchSize);
|
||||
outputGateActivation.set_size(outSize, rhoBatchSize);
|
||||
hiddenLayerActivation.set_size(outSize, rhoBatchSize);
|
||||
|
||||
if (cell.is_empty())
|
||||
{
|
||||
cell = arma::zeros(outSize, size * batchSize);
|
||||
outParameter = arma::zeros<OutputDataType>(
|
||||
outSize, (size + 1) * batchSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
// To preserve the leading zeros, recreate the object according to given
|
||||
// size specifications, while preserving the elements as well as the
|
||||
// layout of the elements.
|
||||
cell.resize(outSize, size * batchSize);
|
||||
outParameter.resize(outSize, (size + 1) * batchSize);
|
||||
}
|
||||
}
|
||||
cellActivation.set_size(outSize, rhoBatchSize);
|
||||
prevError.set_size(4 * outSize, batchSize);
|
||||
|
||||
// Now reset recurrent values to 0.
|
||||
cell.zeros(outSize, size * batchSize);
|
||||
outParameter.zeros(outSize, (size + 1) * batchSize);
|
||||
}
|
||||
|
||||
template<typename InputDataType, typename OutputDataType>
|
||||
|
||||
@@ -120,6 +120,9 @@ class MultiheadAttention
|
||||
const arma::Mat<eT>& error,
|
||||
arma::Mat<eT>& gradient);
|
||||
|
||||
//! Get the size of the weights.
|
||||
size_t WeightSize() const { return 4 * (embedDim + 1) * embedDim; }
|
||||
|
||||
/**
|
||||
* Serialize the layer.
|
||||
*/
|
||||
|
||||
@@ -54,7 +54,7 @@ MultiheadAttention(
|
||||
}
|
||||
|
||||
headDim = embedDim / numHeads;
|
||||
weights.set_size(4 * (embedDim + 1) * embedDim, 1);
|
||||
weights.set_size(WeightSize(), 1);
|
||||
}
|
||||
|
||||
template <typename InputDataType, typename OutputDataType,
|
||||
|
||||
@@ -39,6 +39,18 @@ class MultiplyConstant
|
||||
*/
|
||||
MultiplyConstant(const double scalar = 1.0);
|
||||
|
||||
//! Copy Constructor.
|
||||
MultiplyConstant(const MultiplyConstant& layer);
|
||||
|
||||
//! Move Constructor.
|
||||
MultiplyConstant(MultiplyConstant&& layer);
|
||||
|
||||
//! Copy assignment operator.
|
||||
MultiplyConstant& operator=(const MultiplyConstant& layer);
|
||||
|
||||
//! Move assignment operator.
|
||||
MultiplyConstant& operator=(MultiplyConstant&& layer);
|
||||
|
||||
/**
|
||||
* Ordinary feed forward pass of a neural network. Multiply the input with the
|
||||
* specified constant scalar value.
|
||||
@@ -75,6 +87,9 @@ class MultiplyConstant
|
||||
//! Modify the scalar multiplier.
|
||||
double& Scalar() { return scalar; }
|
||||
|
||||
//! Get the size of the weights.
|
||||
size_t WeightSize() const { return 0; }
|
||||
|
||||
/**
|
||||
* Serialize the layer.
|
||||
*/
|
||||
|
||||
@@ -26,6 +26,46 @@ MultiplyConstant<InputDataType, OutputDataType>::MultiplyConstant(
|
||||
// Nothing to do here.
|
||||
}
|
||||
|
||||
template<typename InputDataType, typename OutputDataType>
|
||||
MultiplyConstant<InputDataType, OutputDataType>::MultiplyConstant(
|
||||
const MultiplyConstant& layer) :
|
||||
scalar(layer.scalar)
|
||||
{
|
||||
// Nothing to do here.
|
||||
}
|
||||
|
||||
template<typename InputDataType, typename OutputDataType>
|
||||
MultiplyConstant<InputDataType, OutputDataType>::MultiplyConstant(
|
||||
MultiplyConstant&& layer) :
|
||||
scalar(std::move(layer.scalar))
|
||||
{
|
||||
// Nothing to do here.
|
||||
}
|
||||
|
||||
template<typename InputDataType, typename OutputDataType>
|
||||
MultiplyConstant<InputDataType, OutputDataType>&
|
||||
MultiplyConstant<InputDataType, OutputDataType>::operator=(
|
||||
const MultiplyConstant& layer)
|
||||
{
|
||||
if (this != &layer)
|
||||
{
|
||||
scalar = layer.scalar;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename InputDataType, typename OutputDataType>
|
||||
MultiplyConstant<InputDataType, OutputDataType>&
|
||||
MultiplyConstant<InputDataType, OutputDataType>::operator=(
|
||||
MultiplyConstant&& layer)
|
||||
{
|
||||
if (this != &layer)
|
||||
{
|
||||
scalar = std::move(layer.scalar);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename InputDataType, typename OutputDataType>
|
||||
template<typename InputType, typename OutputType>
|
||||
void MultiplyConstant<InputDataType, OutputDataType>::Forward(
|
||||
|
||||
@@ -50,6 +50,18 @@ class MultiplyMerge
|
||||
*/
|
||||
MultiplyMerge(const bool model = false, const bool run = true);
|
||||
|
||||
//! Copy Constructor.
|
||||
MultiplyMerge(const MultiplyMerge& layer);
|
||||
|
||||
//! Move Constructor.
|
||||
MultiplyMerge(MultiplyMerge&& layer);
|
||||
|
||||
//! Copy assignment operator.
|
||||
MultiplyMerge& operator=(const MultiplyMerge& layer);
|
||||
|
||||
//! Move assignment operator.
|
||||
MultiplyMerge& operator=(MultiplyMerge&& layer);
|
||||
|
||||
//! Destructor to release allocated memory.
|
||||
~MultiplyMerge();
|
||||
|
||||
@@ -135,6 +147,9 @@ class MultiplyMerge
|
||||
//! Modify the parameters.
|
||||
OutputDataType& Parameters() { return weights; }
|
||||
|
||||
//! Get the size of the weights.
|
||||
size_t WeightSize() const { return 0; }
|
||||
|
||||
/**
|
||||
* Serialize the layer.
|
||||
*/
|
||||
|
||||
@@ -32,6 +32,66 @@ MultiplyMerge<InputDataType, OutputDataType, CustomLayers...>::MultiplyMerge(
|
||||
// Nothing to do here.
|
||||
}
|
||||
|
||||
template<typename InputDataType, typename OutputDataType,
|
||||
typename... CustomLayers>
|
||||
MultiplyMerge<InputDataType, OutputDataType, CustomLayers...>::MultiplyMerge(
|
||||
const MultiplyMerge& layer) :
|
||||
model(layer.model),
|
||||
run(layer.run),
|
||||
ownsLayer(layer.ownsLayer),
|
||||
network(layer.network),
|
||||
weights(layer.weights)
|
||||
{
|
||||
// Nothing to do here.
|
||||
}
|
||||
|
||||
template<typename InputDataType, typename OutputDataType,
|
||||
typename... CustomLayers>
|
||||
MultiplyMerge<InputDataType, OutputDataType, CustomLayers...>::MultiplyMerge(
|
||||
MultiplyMerge&& layer) :
|
||||
model(std::move(layer.model)),
|
||||
run(std::move(layer.run)),
|
||||
ownsLayer(std::move(layer.ownsLayer)),
|
||||
network(std::move(layer.network)),
|
||||
weights(std::move(layer.weights))
|
||||
{
|
||||
// Nothing to do here.
|
||||
}
|
||||
|
||||
template<typename InputDataType, typename OutputDataType,
|
||||
typename... CustomLayers>
|
||||
MultiplyMerge<InputDataType, OutputDataType, CustomLayers...>&
|
||||
MultiplyMerge<InputDataType, OutputDataType, CustomLayers...>::operator=(
|
||||
const MultiplyMerge& layer)
|
||||
{
|
||||
if (this != &layer)
|
||||
{
|
||||
model = layer.model;
|
||||
run = layer.run;
|
||||
ownsLayer = layer.ownsLayer;
|
||||
network = layer.network;
|
||||
weights = layer.weights;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename InputDataType, typename OutputDataType,
|
||||
typename... CustomLayers>
|
||||
MultiplyMerge<InputDataType, OutputDataType, CustomLayers...>&
|
||||
MultiplyMerge<InputDataType, OutputDataType, CustomLayers...>::operator=(
|
||||
MultiplyMerge&& layer)
|
||||
{
|
||||
if (this != &layer)
|
||||
{
|
||||
model = std::move(layer.model);
|
||||
run = std::move(layer.run);
|
||||
ownsLayer = std::move(layer.ownsLayer);
|
||||
network = std::move(layer.network);
|
||||
weights = std::move(layer.weights);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename InputDataType, typename OutputDataType,
|
||||
typename... CustomLayers>
|
||||
MultiplyMerge<InputDataType, OutputDataType, CustomLayers...>::~MultiplyMerge()
|
||||
|
||||
@@ -0,0 +1,181 @@
|
||||
/**
|
||||
* @file methods/ann/layer/pixel_shuffle.hpp
|
||||
* @author Anjishnu Mukherjee
|
||||
* @author Abhinav Anand
|
||||
*
|
||||
* Definition of the PixelShuffle 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_METHODS_ANN_LAYER_PIXEL_SHUFFLE_HPP
|
||||
#define MLPACK_METHODS_ANN_LAYER_PIXEL_SHUFFLE_HPP
|
||||
|
||||
#include <mlpack/prereqs.hpp>
|
||||
|
||||
namespace mlpack {
|
||||
namespace ann /** Artificial Neural Network. */ {
|
||||
|
||||
/**
|
||||
* Implementation of the PixelShuffle layer.
|
||||
*
|
||||
* For more information, refer to the following paper,
|
||||
*
|
||||
* @code
|
||||
* @article{Shi16,
|
||||
* author = {Wenzhe Shi, Jose Caballero,Ferenc Huszár, Johannes Totz,
|
||||
* Andrew P. Aitken, Rob Bishop, Daniel Rueckert, Zehan Wang},
|
||||
* title = {Real-Time Single Image and Video Super-Resolution Using an
|
||||
* Efficient Sub-Pixel Convolutional Neural Network},
|
||||
* journal = {CoRR},
|
||||
* volume = {abs/1609.05158},
|
||||
* year = {2016},
|
||||
* url = {https://arxiv.org/abs/1609.05158},
|
||||
* eprint = {1609.05158},
|
||||
* }
|
||||
* @endcode
|
||||
*
|
||||
* @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 PixelShuffle
|
||||
{
|
||||
public:
|
||||
//! Create the PixelShuffle object.
|
||||
PixelShuffle();
|
||||
|
||||
/**
|
||||
* Create the PixelShuffle object using the specified parameters.
|
||||
* The number of input channels should be an integral multiple of the square
|
||||
* of the upscale factor.
|
||||
*
|
||||
* @param upscaleFactor The scaling factor for Pixel Shuffle.
|
||||
* @param height The height of each input image.
|
||||
* @param width The width of each input image.
|
||||
* @param size The number of channels of each input image.
|
||||
*/
|
||||
PixelShuffle(const size_t upscaleFactor,
|
||||
const size_t height,
|
||||
const size_t width,
|
||||
const size_t size);
|
||||
|
||||
/**
|
||||
* Ordinary feed forward pass of the PixelShuffle layer.
|
||||
*
|
||||
* @param input Input data used for evaluating the specified function.
|
||||
* @param output Resulting output activation.
|
||||
*/
|
||||
template<typename eT>
|
||||
void Forward(const arma::Mat<eT>& input, arma::Mat<eT>& output);
|
||||
|
||||
/**
|
||||
* Ordinary feed backward pass of the PixelShuffle layer.
|
||||
*
|
||||
* @param input The propagated input activation.
|
||||
* @param gy The backpropagated error.
|
||||
* @param g The calculated gradient.
|
||||
*/
|
||||
template<typename eT>
|
||||
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; }
|
||||
//! 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 upscale factor.
|
||||
size_t UpscaleFactor() const { return upscaleFactor; }
|
||||
|
||||
//! Modify the upscale factor.
|
||||
size_t& UpscaleFactor() { return upscaleFactor; }
|
||||
|
||||
//! Get the input image height.
|
||||
size_t InputHeight() const { return height; }
|
||||
|
||||
//! Modify the input image height.
|
||||
size_t& InputHeight() { return height; }
|
||||
|
||||
//! Get the input image width.
|
||||
size_t InputWidth() const { return width; }
|
||||
|
||||
//! Modify the input image width.
|
||||
size_t& InputWidth() { return width; }
|
||||
|
||||
//! Get the number of input channels.
|
||||
size_t InputChannels() const { return size; }
|
||||
|
||||
//! Modify the number of input channels.
|
||||
size_t& InputChannels() { return size; }
|
||||
|
||||
//! Get the output image height.
|
||||
size_t OutputHeight() const { return outputHeight; }
|
||||
|
||||
//! Get the output image width.
|
||||
size_t OutputWidth() const { return outputWidth; }
|
||||
|
||||
//! Get the number of output channels.
|
||||
size_t OutputChannels() const { return sizeOut; }
|
||||
|
||||
/**
|
||||
* Serialize the layer.
|
||||
*/
|
||||
template<typename Archive>
|
||||
void serialize(Archive& ar, const unsigned int /* version */);
|
||||
|
||||
private:
|
||||
//! Locally-stored delta object.
|
||||
OutputDataType delta;
|
||||
|
||||
//! Locally-stored output parameter object.
|
||||
OutputDataType outputParameter;
|
||||
|
||||
//! The scaling factor for Pixel Shuffle.
|
||||
size_t upscaleFactor;
|
||||
|
||||
//! The height of each input image.
|
||||
size_t height;
|
||||
|
||||
//! The width of each input image.
|
||||
size_t width;
|
||||
|
||||
//! The number of channels of each input image.
|
||||
size_t size;
|
||||
|
||||
//! The number of images in the batch.
|
||||
size_t batchSize;
|
||||
|
||||
//! The height of each output image.
|
||||
size_t outputHeight;
|
||||
|
||||
//! The width of each output image.
|
||||
size_t outputWidth;
|
||||
|
||||
//! The number of channels of each output image.
|
||||
size_t sizeOut;
|
||||
|
||||
//! A boolean used to do some internal calculations once initially.
|
||||
bool reset;
|
||||
}; // class PixelShuffle
|
||||
|
||||
} // namespace ann
|
||||
} // namespace mlpack
|
||||
|
||||
// Include implementation.
|
||||
#include "pixel_shuffle_impl.hpp"
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,143 @@
|
||||
/**
|
||||
* @file methods/ann/layer/pixel_shuffle_impl.hpp
|
||||
* @author Anjishnu Mukherjee
|
||||
* @author Abhinav Anand
|
||||
*
|
||||
* Implementation of the PixelShuffle 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_METHODS_ANN_LAYER_PIXEL_SHUFFLE_IMPL_HPP
|
||||
#define MLPACK_METHODS_ANN_LAYER_PIXEL_SHUFFLE_IMPL_HPP
|
||||
|
||||
// In case it hasn't yet been included.
|
||||
#include "pixel_shuffle.hpp"
|
||||
|
||||
namespace mlpack {
|
||||
namespace ann /** Artificial Neural Network. */ {
|
||||
|
||||
template<typename InputDataType, typename OutputDataType>
|
||||
PixelShuffle<InputDataType, OutputDataType>::PixelShuffle() :
|
||||
PixelShuffle(0, 0, 0, 0)
|
||||
{
|
||||
// Nothing to do here.
|
||||
}
|
||||
|
||||
template<typename InputDataType, typename OutputDataType>
|
||||
PixelShuffle<InputDataType, OutputDataType>::PixelShuffle(
|
||||
const size_t upscaleFactor,
|
||||
const size_t height,
|
||||
const size_t width,
|
||||
const size_t size) :
|
||||
upscaleFactor(upscaleFactor),
|
||||
height(height),
|
||||
width(width),
|
||||
size(size),
|
||||
batchSize(0),
|
||||
outputHeight(0),
|
||||
outputWidth(0),
|
||||
sizeOut(0),
|
||||
reset(false)
|
||||
{
|
||||
// Nothing to do here.
|
||||
}
|
||||
|
||||
template<typename InputDataType, typename OutputDataType>
|
||||
template<typename eT>
|
||||
void PixelShuffle<InputDataType, OutputDataType>::Forward(
|
||||
const arma::Mat<eT>& input, arma::Mat<eT>& output)
|
||||
{
|
||||
if (!reset)
|
||||
{
|
||||
batchSize = input.n_cols;
|
||||
sizeOut = size / std::pow(upscaleFactor, 2);
|
||||
outputHeight = height * upscaleFactor;
|
||||
outputWidth = width * upscaleFactor;
|
||||
reset = true;
|
||||
}
|
||||
|
||||
output.zeros(outputHeight * outputWidth * sizeOut, batchSize);
|
||||
for (size_t n = 0; n < batchSize; n++)
|
||||
{
|
||||
arma::cube inputTemp(const_cast<arma::mat&>(input).memptr(), height,
|
||||
width, size * batchSize, false, false);
|
||||
arma::cube outputTemp(const_cast<arma::mat&>(output).memptr(),
|
||||
outputHeight, outputWidth, sizeOut * batchSize, false, false);
|
||||
|
||||
for (size_t c = 0; c < sizeOut; c++)
|
||||
{
|
||||
for (size_t h = 0; h < outputHeight; h++)
|
||||
{
|
||||
for (size_t w = 0; w < outputWidth; w++)
|
||||
{
|
||||
size_t height_index = h / upscaleFactor;
|
||||
size_t width_index = w / upscaleFactor;
|
||||
size_t channel_index = (upscaleFactor * (h % upscaleFactor)) +
|
||||
(w % upscaleFactor) + (c * std::pow(upscaleFactor, 2));
|
||||
outputTemp(w, h, c + n * sizeOut) = inputTemp(width_index, height_index,
|
||||
channel_index + n * size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
template<typename InputDataType, typename OutputDataType>
|
||||
template<typename eT>
|
||||
void PixelShuffle<InputDataType, OutputDataType>::Backward(
|
||||
const arma::Mat<eT>& input, const arma::Mat<eT>& gy, arma::Mat<eT>& g)
|
||||
{
|
||||
g.zeros(arma::size(input));
|
||||
for (size_t n = 0; n < batchSize; n++)
|
||||
{
|
||||
arma::cube gyTemp(const_cast<arma::mat&>(gy).memptr(), outputHeight,
|
||||
outputWidth, sizeOut * batchSize, false, false);
|
||||
arma::cube gTemp(const_cast<arma::mat&>(g).memptr(), height, width,
|
||||
size * batchSize, false, false);
|
||||
|
||||
for (size_t c = 0; c < sizeOut; c++)
|
||||
{
|
||||
for (size_t h = 0; h < outputHeight; h++)
|
||||
{
|
||||
for (size_t w = 0; w < outputWidth; w++)
|
||||
{
|
||||
size_t height_index = h / upscaleFactor;
|
||||
size_t width_index = w / upscaleFactor;
|
||||
size_t channel_index = (upscaleFactor * (h % upscaleFactor)) +
|
||||
(w % upscaleFactor) + (c * std::pow(upscaleFactor, 2));
|
||||
gTemp(width_index, height_index, channel_index + n * size) = gyTemp(w, h,
|
||||
c + n * sizeOut);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
template<typename InputDataType, typename OutputDataType>
|
||||
template<typename Archive>
|
||||
void PixelShuffle<InputDataType, OutputDataType>::serialize(
|
||||
Archive& ar,
|
||||
const unsigned int /* version */)
|
||||
{
|
||||
ar(CEREAL_NVP(delta));
|
||||
ar(CEREAL_NVP(outputParameter));
|
||||
ar(CEREAL_NVP(upscaleFactor));
|
||||
ar(CEREAL_NVP(height));
|
||||
ar(CEREAL_NVP(width));
|
||||
ar(CEREAL_NVP(size));
|
||||
ar(CEREAL_NVP(batchSize));
|
||||
ar(CEREAL_NVP(outputHeight));
|
||||
ar(CEREAL_NVP(outputHeight));
|
||||
ar(CEREAL_NVP(outputWidth));
|
||||
ar(CEREAL_NVP(sizeOut));
|
||||
}
|
||||
|
||||
} // namespace ann
|
||||
} // namespace mlpack
|
||||
|
||||
#endif
|
||||
@@ -110,6 +110,12 @@ class RBF
|
||||
//! Modify the delta.
|
||||
OutputDataType& Delta() { return delta; }
|
||||
|
||||
//! Get the size of the weights.
|
||||
size_t WeightSize() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
//! Get the shape of the input.
|
||||
size_t InputShape() const
|
||||
{
|
||||
|
||||
@@ -31,7 +31,8 @@ RecurrentAttention<InputDataType, OutputDataType>::RecurrentAttention() :
|
||||
rho(0),
|
||||
forwardStep(0),
|
||||
backwardStep(0),
|
||||
deterministic(false)
|
||||
deterministic(false),
|
||||
outSize(0)
|
||||
{
|
||||
// Nothing to do.
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace ann /** Artificial Neural Network. */ {
|
||||
|
||||
template<typename InputDataType, typename OutputDataType>
|
||||
ReinforceNormal<InputDataType, OutputDataType>::ReinforceNormal(
|
||||
const double stdev) : stdev(stdev)
|
||||
const double stdev) : stdev(stdev), reward(0.0), deterministic(false)
|
||||
{
|
||||
// Nothing to do here.
|
||||
}
|
||||
@@ -34,8 +34,7 @@ void ReinforceNormal<InputDataType, OutputDataType>::Forward(
|
||||
if (!deterministic)
|
||||
{
|
||||
// Multiply by standard deviations and re-center the means to the mean.
|
||||
output = arma::randn<arma::Mat<eT> >(input.n_rows, input.n_cols) *
|
||||
stdev + input;
|
||||
output = output.randn(input.n_rows, input.n_cols) * stdev + input;
|
||||
|
||||
moduleInputParameter.push_back(input);
|
||||
}
|
||||
|
||||
@@ -126,8 +126,7 @@ TransposedConvolution<
|
||||
{
|
||||
weights.set_size(WeightSize(), 1);
|
||||
// Transform paddingType to lowercase.
|
||||
std::string paddingTypeLow = paddingType;
|
||||
util::ToLower(paddingType, paddingTypeLow);
|
||||
const std::string paddingTypeLow = util::ToLower(paddingType);
|
||||
|
||||
if (paddingTypeLow == "valid")
|
||||
{
|
||||
|
||||
@@ -206,6 +206,17 @@ class LayerNameVisitor : public boost::static_visitor<std::string>
|
||||
return "meanpooling";
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the name of the given layer of type LpPooling as a string.
|
||||
*
|
||||
* @param * Given layer of type LpPooling.
|
||||
* @return The string representation of the layer.
|
||||
*/
|
||||
std::string LayerString(LpPooling<>* /*layer*/) const
|
||||
{
|
||||
return "lppooling";
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the name of the given layer of type MultiplyConstant as a string.
|
||||
*
|
||||
|
||||
@@ -9,24 +9,32 @@ set(SOURCES
|
||||
dice_loss_impl.hpp
|
||||
earth_mover_distance.hpp
|
||||
earth_mover_distance_impl.hpp
|
||||
empty_loss.hpp
|
||||
empty_loss_impl.hpp
|
||||
huber_loss.hpp
|
||||
huber_loss_impl.hpp
|
||||
hinge_embedding_loss.hpp
|
||||
hinge_embedding_loss_impl.hpp
|
||||
hinge_loss.hpp
|
||||
hinge_loss_impl.hpp
|
||||
kl_divergence.hpp
|
||||
kl_divergence_impl.hpp
|
||||
margin_ranking_loss.hpp
|
||||
margin_ranking_loss_impl.hpp
|
||||
mean_bias_error.hpp
|
||||
mean_bias_error_impl.hpp
|
||||
l1_loss.hpp
|
||||
l1_loss_impl.hpp
|
||||
log_cosh_loss.hpp
|
||||
log_cosh_loss_impl.hpp
|
||||
margin_ranking_loss.hpp
|
||||
margin_ranking_loss_impl.hpp
|
||||
mean_absolute_percentage_error.hpp
|
||||
mean_absolute_percentage_error_impl.hpp
|
||||
mean_bias_error.hpp
|
||||
mean_bias_error_impl.hpp
|
||||
mean_squared_error.hpp
|
||||
mean_squared_error_impl.hpp
|
||||
mean_squared_logarithmic_error.hpp
|
||||
mean_squared_logarithmic_error_impl.hpp
|
||||
negative_log_likelihood.hpp
|
||||
negative_log_likelihood_impl.hpp
|
||||
log_cosh_loss.hpp
|
||||
log_cosh_loss_impl.hpp
|
||||
poisson_nll_loss.hpp
|
||||
poisson_nll_loss_impl.hpp
|
||||
reconstruction_loss.hpp
|
||||
@@ -35,12 +43,6 @@ set(SOURCES
|
||||
sigmoid_cross_entropy_error_impl.hpp
|
||||
soft_margin_loss.hpp
|
||||
soft_margin_loss_impl.hpp
|
||||
hinge_embedding_loss.hpp
|
||||
hinge_embedding_loss_impl.hpp
|
||||
empty_loss.hpp
|
||||
empty_loss_impl.hpp
|
||||
mean_absolute_percentage_error.hpp
|
||||
mean_absolute_percentage_error_impl.hpp
|
||||
triplet_margin_loss.hpp
|
||||
triplet_margin_loss_impl.hpp
|
||||
)
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
/**
|
||||
* @file methods/ann/loss_functions/hinge_loss.hpp
|
||||
* @author Anush Kini
|
||||
*
|
||||
* Definition of the Hinge Loss Function.
|
||||
*
|
||||
* mlpack is free software; you may redistribute it and/or modify it under the
|
||||
* terms of the 3-clause BSD license. You should have received a copy of the
|
||||
* 3-clause BSD license along with mlpack. If not, see
|
||||
* http://www.opensource.org/licenses/BSD-3-Clause for more information.
|
||||
*/
|
||||
|
||||
#ifndef MLPACK_METHODS_ANN_LOSS_FUNCTION_HINGE_LOSS_HPP
|
||||
#define MLPACK_METHODS_ANN_LOSS_FUNCTION_HINGE_LOSS_HPP
|
||||
|
||||
#include<mlpack/prereqs.hpp>
|
||||
|
||||
namespace mlpack {
|
||||
namespace ann /** Artificial Neural Network. */ {
|
||||
|
||||
/**
|
||||
* Computes the hinge loss between \f$y_true\f$ and \f$y_pred\f$. Expects
|
||||
* \f$y_true\f$ to be either -1 or 1. If \f$y_true\f$ is either 0 or 1, a
|
||||
* temporary conversion is made to calculate the loss.
|
||||
* The hinge loss \f$l(y_true, y_pred)\f$ is defined as
|
||||
* \f$l(y_true, y_pred) = max(0, 1 - y_true*y_pred)\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 HingeLoss
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Create HingeLoss object.
|
||||
*
|
||||
* @param reduction Specifies the reduction to apply to the output. If false,
|
||||
* 'mean' reduction is used, where sum of the output will be
|
||||
* divided by the number of elements in the output. If
|
||||
* true, 'sum' reduction is used and the output will be
|
||||
* summed. It is set to true by default.
|
||||
*/
|
||||
HingeLoss(const bool reduction = true);
|
||||
|
||||
/**
|
||||
* Computes the Hinge loss function.
|
||||
*
|
||||
* @param prediction Prediction used for evaluating the specified loss
|
||||
* function.
|
||||
* @param target Target data to compare with.
|
||||
*/
|
||||
template<typename PredictionType, typename TargetType>
|
||||
typename PredictionType::elem_type Forward(const PredictionType& prediction,
|
||||
const TargetType& target);
|
||||
|
||||
/**
|
||||
* Ordinary feed backward pass of a neural network.
|
||||
*
|
||||
* @param prediction Prediction used for evaluating the specified loss
|
||||
* function.
|
||||
* @param target The target vector.
|
||||
* @param loss The calculated error.
|
||||
*/
|
||||
template<typename PredictionType, typename TargetType, typename LossType>
|
||||
void Backward(const PredictionType& prediction,
|
||||
const TargetType& target,
|
||||
LossType& loss);
|
||||
|
||||
//! Get the output parameter.
|
||||
OutputDataType& OutputParameter() const { return outputParameter; }
|
||||
//! Modify the output parameter.
|
||||
OutputDataType& OutputParameter() { return outputParameter; }
|
||||
|
||||
//! Get the type of reduction used.
|
||||
bool Reduction() const { return reduction; }
|
||||
//! Modify the type of reduction used.
|
||||
bool& Reduction() { return reduction; }
|
||||
|
||||
/**
|
||||
* Serialize the layer.
|
||||
*/
|
||||
template<typename Archive>
|
||||
void serialize(Archive& ar, const uint32_t /* version */);
|
||||
|
||||
private:
|
||||
//! Locally-stored output parameter object.
|
||||
OutputDataType outputParameter;
|
||||
|
||||
//! The boolean value that tells if reduction is sum or mean.
|
||||
bool reduction;
|
||||
}; // class HingeLoss
|
||||
|
||||
} // namespace ann
|
||||
} // namespace mlpack
|
||||
|
||||
// include implementation
|
||||
#include "hinge_loss_impl.hpp"
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,75 @@
|
||||
/**
|
||||
* @file methods/ann/loss_functions/hinge_loss_impl.hpp
|
||||
* @author Anush Kini
|
||||
*
|
||||
* Implementation of the Hinge loss function.
|
||||
*
|
||||
* mlpack is free software; you may redistribute it and/or modify it under the
|
||||
* terms of the 3-clause BSD license. You should have received a copy of the
|
||||
* 3-clause BSD license along with mlpack. If not, see
|
||||
* http://www.opensource.org/licenses/BSD-3-Clause for more information.
|
||||
*/
|
||||
|
||||
#ifndef MLPACK_METHODS_ANN_LOSS_FUNCTION_HINGE_LOSS_IMPL_HPP
|
||||
#define MLPACK_METHODS_ANN_LOSS_FUNCTION_HINGE_LOSS_IMPL_HPP
|
||||
|
||||
// In case it hasn't yet been included.
|
||||
#include "hinge_loss.hpp"
|
||||
|
||||
namespace mlpack {
|
||||
namespace ann /** Artificial Neural Network. */ {
|
||||
|
||||
template<typename InputDataType, typename OutputDataType>
|
||||
HingeLoss<InputDataType, OutputDataType>::HingeLoss(const bool reduction):
|
||||
reduction(reduction)
|
||||
{
|
||||
// Nothing to do here.
|
||||
}
|
||||
|
||||
template<typename InputDataType, typename OutputDataType>
|
||||
template<typename PredictionType, typename TargetType>
|
||||
typename PredictionType::elem_type
|
||||
HingeLoss<InputDataType, OutputDataType>::Forward(
|
||||
const PredictionType& prediction,
|
||||
const TargetType& target)
|
||||
{
|
||||
TargetType temp = target - (target == 0);
|
||||
TargetType temp_zeros(size(target), arma::fill::zeros);
|
||||
|
||||
PredictionType loss = arma::max(temp_zeros, 1 - prediction % temp);
|
||||
|
||||
typename PredictionType::elem_type lossSum = arma::accu(loss);
|
||||
|
||||
if (reduction)
|
||||
return lossSum;
|
||||
|
||||
return lossSum / loss.n_elem;
|
||||
}
|
||||
|
||||
template<typename InputDataType, typename OutputDataType>
|
||||
template<typename PredictionType, typename TargetType, typename LossType>
|
||||
void HingeLoss<InputDataType, OutputDataType>::Backward(
|
||||
const PredictionType& prediction,
|
||||
const TargetType& target,
|
||||
LossType& loss)
|
||||
{
|
||||
TargetType temp = target - (target == 0);
|
||||
loss = (prediction < (1 / temp)) % -temp;
|
||||
|
||||
if (!reduction)
|
||||
loss /= target.n_elem;
|
||||
}
|
||||
|
||||
template<typename InputDataType, typename OutputDataType>
|
||||
template<typename Archive>
|
||||
void HingeLoss<InputDataType, OutputDataType>::serialize(
|
||||
Archive& ar,
|
||||
const uint32_t /* version */)
|
||||
{
|
||||
ar(CEREAL_NVP(reduction));
|
||||
}
|
||||
|
||||
} // namespace ann
|
||||
} // namespace mlpack
|
||||
|
||||
#endif
|
||||
@@ -35,11 +35,10 @@ NegativeLogLikelihood<InputDataType, OutputDataType>::Forward(
|
||||
ElemType output = 0;
|
||||
for (size_t i = 0; i < prediction.n_cols; ++i)
|
||||
{
|
||||
size_t currentTarget = target(i) - 1;
|
||||
Log::Assert(currentTarget < prediction.n_rows,
|
||||
Log::Assert(target(i) >= 0 && target(i) < prediction.n_rows,
|
||||
"Target class out of range.");
|
||||
|
||||
output -= prediction(currentTarget, i);
|
||||
output -= prediction(target(i), i);
|
||||
}
|
||||
|
||||
return output;
|
||||
@@ -55,11 +54,10 @@ void NegativeLogLikelihood<InputDataType, OutputDataType>::Backward(
|
||||
loss = arma::zeros<LossType>(prediction.n_rows, prediction.n_cols);
|
||||
for (size_t i = 0; i < prediction.n_cols; ++i)
|
||||
{
|
||||
size_t currentTarget = target(i) - 1;
|
||||
Log::Assert(currentTarget < prediction.n_rows,
|
||||
Log::Assert(target(i) >= 0 && target(i) < prediction.n_rows,
|
||||
"Target class out of range.");
|
||||
|
||||
loss(currentTarget, i) = -1;
|
||||
loss(target(i), i) = -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -87,10 +87,10 @@ RNN<OutputLayerType, InitializationRuleType, CustomLayers...>::RNN(
|
||||
targetSize(std::move(network.targetSize)),
|
||||
reset(std::move(network.reset)),
|
||||
single(std::move(network.single)),
|
||||
network(std::move(network.network)),
|
||||
parameter(std::move(network.parameter)),
|
||||
numFunctions(std::move(network.numFunctions)),
|
||||
deterministic(std::move(network.deterministic)),
|
||||
network(std::move(network.network))
|
||||
deterministic(std::move(network.deterministic))
|
||||
{
|
||||
// Nothing to do here.
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ set(SOURCES
|
||||
cf_impl.hpp
|
||||
cf_model.hpp
|
||||
cf_model_impl.hpp
|
||||
cf_model.cpp
|
||||
svd_wrapper.hpp
|
||||
svd_wrapper_impl.hpp
|
||||
)
|
||||
|
||||
+163
-279
@@ -194,279 +194,6 @@ PARAM_STRING_IN("interpolation", "Algorithm used for weight interpolation.",
|
||||
PARAM_STRING_IN("neighbor_search", "Algorithm used for neighbor search.",
|
||||
"S", "euclidean");
|
||||
|
||||
template <typename NeighborSearchType,
|
||||
typename InterpolationType>
|
||||
void ComputeRecommendations(CFModel* cf,
|
||||
const size_t numRecs,
|
||||
arma::Mat<size_t>& recommendations)
|
||||
{
|
||||
// Reading users.
|
||||
if (IO::HasParam("query"))
|
||||
{
|
||||
// User matrix.
|
||||
arma::Mat<size_t> users =
|
||||
std::move(IO::GetParam<arma::Mat<size_t>>("query"));
|
||||
if (users.n_rows > 1)
|
||||
users = users.t();
|
||||
if (users.n_rows > 1)
|
||||
Log::Fatal << "List of query users must be one-dimensional!"
|
||||
<< std::endl;
|
||||
|
||||
Log::Info << "Generating recommendations for "
|
||||
<< users.n_elem << " users."
|
||||
<< endl;
|
||||
|
||||
cf->GetRecommendations<NeighborSearchType, InterpolationType>
|
||||
(numRecs, recommendations, users.row(0).t());
|
||||
}
|
||||
else
|
||||
{
|
||||
Log::Info << "Generating recommendations for all users." << endl;
|
||||
cf->GetRecommendations<NeighborSearchType, InterpolationType>
|
||||
(numRecs, recommendations);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename NeighborSearchType>
|
||||
void ComputeRecommendations(CFModel* cf,
|
||||
const size_t numRecs,
|
||||
arma::Mat<size_t>& recommendations)
|
||||
{
|
||||
// Verify the Interpolation algorithms.
|
||||
RequireParamInSet<string>("interpolation", { "average",
|
||||
"regression", "similarity" }, true, "unknown interpolation algorithm");
|
||||
|
||||
// Taking Interpolation Alternatives
|
||||
const string interpolationAlgorithm = IO::GetParam<string>("interpolation");
|
||||
|
||||
// Determining the Interpolation Algorithm
|
||||
if (interpolationAlgorithm == "average")
|
||||
{
|
||||
ComputeRecommendations<NeighborSearchType, AverageInterpolation>
|
||||
(cf, numRecs, recommendations);
|
||||
}
|
||||
else if (interpolationAlgorithm == "regression")
|
||||
{
|
||||
ComputeRecommendations<NeighborSearchType, RegressionInterpolation>
|
||||
(cf, numRecs, recommendations);
|
||||
}
|
||||
else if (interpolationAlgorithm == "similarity")
|
||||
{
|
||||
ComputeRecommendations<NeighborSearchType, SimilarityInterpolation>
|
||||
(cf, numRecs, recommendations);
|
||||
}
|
||||
}
|
||||
|
||||
void ComputeRecommendations(CFModel* cf,
|
||||
const size_t numRecs,
|
||||
arma::Mat<size_t>& recommendations)
|
||||
{
|
||||
// Verifying the Neighbor Search algorithms
|
||||
RequireParamInSet<string>("neighbor_search", { "cosine",
|
||||
"euclidean", "pearson" }, true, "unknown neighbor search algorithm");
|
||||
|
||||
// Taking Neighbor Search alternatives
|
||||
const string neighborSearchAlgorithm = IO::GetParam<string>
|
||||
("neighbor_search");
|
||||
|
||||
|
||||
// Determining the Neighbor Search Algorithms
|
||||
if (neighborSearchAlgorithm == "cosine")
|
||||
{
|
||||
ComputeRecommendations<CosineSearch>(cf, numRecs, recommendations);
|
||||
}
|
||||
else if (neighborSearchAlgorithm == "euclidean")
|
||||
{
|
||||
ComputeRecommendations<EuclideanSearch>(cf, numRecs, recommendations);
|
||||
}
|
||||
else if (neighborSearchAlgorithm == "pearson")
|
||||
{
|
||||
ComputeRecommendations<PearsonSearch>(cf, numRecs, recommendations);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename NeighborSearchType,
|
||||
typename InterpolationType>
|
||||
void ComputeRMSE(CFModel* cf)
|
||||
{
|
||||
// Now, compute each test point.
|
||||
arma::mat testData = std::move(IO::GetParam<arma::mat>("test"));
|
||||
|
||||
// Assemble the combination matrix to get RMSE value.
|
||||
arma::Mat<size_t> combinations(2, testData.n_cols);
|
||||
for (size_t i = 0; i < testData.n_cols; ++i)
|
||||
{
|
||||
combinations(0, i) = size_t(testData(0, i));
|
||||
combinations(1, i) = size_t(testData(1, i));
|
||||
}
|
||||
|
||||
// Now compute the RMSE.
|
||||
arma::vec predictions;
|
||||
cf->Predict<NeighborSearchType, InterpolationType>
|
||||
(combinations, predictions);
|
||||
|
||||
// Compute the root of the sum of the squared errors, divide by the number of
|
||||
// points to get the RMSE. It turns out this is just the L2-norm divided by
|
||||
// the square root of the number of points, if we interpret the predictions
|
||||
// and the true values as vectors.
|
||||
const double rmse = arma::norm(predictions - testData.row(2).t(), 2) /
|
||||
std::sqrt((double) testData.n_cols);
|
||||
|
||||
Log::Info << "RMSE is " << rmse << "." << endl;
|
||||
}
|
||||
|
||||
template <typename NeighborSearchType>
|
||||
void ComputeRMSE(CFModel* cf)
|
||||
{
|
||||
// Verifying the Interpolation algorithms
|
||||
RequireParamInSet<string>("interpolation", { "average",
|
||||
"regression", "similarity" }, true, "unknown interpolation algorithm");
|
||||
|
||||
// Taking Interpolation Alternatives
|
||||
const string interpolationAlgorithm = IO::GetParam<string>("interpolation");
|
||||
|
||||
if (interpolationAlgorithm == "average")
|
||||
{
|
||||
ComputeRMSE<NeighborSearchType, AverageInterpolation>(cf);
|
||||
}
|
||||
else if (interpolationAlgorithm == "regression")
|
||||
{
|
||||
ComputeRMSE<NeighborSearchType, RegressionInterpolation>(cf);
|
||||
}
|
||||
else if (interpolationAlgorithm == "similarity")
|
||||
{
|
||||
ComputeRMSE<NeighborSearchType, SimilarityInterpolation>(cf);
|
||||
}
|
||||
}
|
||||
|
||||
void ComputeRMSE(CFModel* cf)
|
||||
{
|
||||
// Verifying the Neighbor Search algorithms
|
||||
RequireParamInSet<string>("neighbor_search", { "cosine",
|
||||
"euclidean", "pearson" }, true, "unknown neighbor search algorithm");
|
||||
|
||||
// Taking Neighbor Search alternatives
|
||||
const string neighborSearchAlgorithm = IO::GetParam<string>
|
||||
("neighbor_search");
|
||||
|
||||
if (neighborSearchAlgorithm == "cosine")
|
||||
{
|
||||
ComputeRMSE<CosineSearch>(cf);
|
||||
}
|
||||
else if (neighborSearchAlgorithm == "euclidean")
|
||||
{
|
||||
ComputeRMSE<EuclideanSearch>(cf);
|
||||
}
|
||||
else if (neighborSearchAlgorithm == "pearson")
|
||||
{
|
||||
ComputeRMSE<PearsonSearch>(cf);
|
||||
}
|
||||
}
|
||||
|
||||
void PerformAction(CFModel* c)
|
||||
{
|
||||
if (IO::HasParam("query") || IO::HasParam("all_user_recommendations"))
|
||||
{
|
||||
// Get parameters for generating recommendations.
|
||||
const size_t numRecs = (size_t) IO::GetParam<int>("recommendations");
|
||||
|
||||
// Get the recommendations.
|
||||
arma::Mat<size_t> recommendations;
|
||||
ComputeRecommendations(c, numRecs, recommendations);
|
||||
|
||||
// Save the output.
|
||||
IO::GetParam<arma::Mat<size_t>>("output") = recommendations;
|
||||
}
|
||||
|
||||
if (IO::HasParam("test"))
|
||||
ComputeRMSE(c);
|
||||
|
||||
IO::GetParam<CFModel*>("output_model") = c;
|
||||
}
|
||||
|
||||
template<typename DecompositionPolicy>
|
||||
void PerformAction(arma::mat& dataset,
|
||||
const size_t rank,
|
||||
const size_t maxIterations,
|
||||
const double minResidue)
|
||||
{
|
||||
const size_t neighborhood = (size_t) IO::GetParam<int>("neighborhood");
|
||||
|
||||
// Make sure the normalization strategy is valid.
|
||||
RequireParamInSet<string>("normalization", { "overall_mean", "item_mean",
|
||||
"user_mean", "z_score", "none" }, true, "unknown normalization type");
|
||||
|
||||
CFModel* c = new CFModel();
|
||||
|
||||
const string normalizationType = IO::GetParam<string>("normalization");
|
||||
|
||||
c->template Train<DecompositionPolicy>(dataset, neighborhood, rank,
|
||||
maxIterations, minResidue, IO::HasParam("iteration_only_termination"),
|
||||
normalizationType);
|
||||
|
||||
try
|
||||
{
|
||||
PerformAction(c);
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
// Clean the memory before throwing completely.
|
||||
delete c;
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
void AssembleFactorizerType(const std::string& algorithm,
|
||||
arma::mat& dataset,
|
||||
const size_t rank)
|
||||
{
|
||||
const size_t maxIterations = (size_t) IO::GetParam<int>("max_iterations");
|
||||
const double minResidue = IO::GetParam<double>("min_residue");
|
||||
|
||||
if (algorithm == "NMF")
|
||||
{
|
||||
PerformAction<NMFPolicy>(dataset, rank, maxIterations, minResidue);
|
||||
}
|
||||
else if (algorithm == "BatchSVD")
|
||||
{
|
||||
PerformAction<BatchSVDPolicy>(dataset, rank, maxIterations, minResidue);
|
||||
}
|
||||
else if (algorithm == "SVDIncompleteIncremental")
|
||||
{
|
||||
PerformAction<SVDIncompletePolicy>(dataset, rank, maxIterations,
|
||||
minResidue);
|
||||
}
|
||||
else if (algorithm == "SVDCompleteIncremental")
|
||||
{
|
||||
PerformAction<SVDCompletePolicy>(dataset, rank, maxIterations, minResidue);
|
||||
}
|
||||
else if (algorithm == "RegSVD")
|
||||
{
|
||||
ReportIgnoredParam("min_residue", "Regularized SVD terminates only "
|
||||
"when max_iterations is reached");
|
||||
PerformAction<RegSVDPolicy>(dataset, rank, maxIterations, minResidue);
|
||||
}
|
||||
else if (algorithm == "RandSVD")
|
||||
{
|
||||
ReportIgnoredParam("min_residue", "Randomized SVD terminates only "
|
||||
"when max_iterations is reached");
|
||||
PerformAction<RandomizedSVDPolicy>(dataset, rank, maxIterations,
|
||||
minResidue);
|
||||
}
|
||||
else if (algorithm == "BiasSVD")
|
||||
{
|
||||
ReportIgnoredParam("min_residue", "Bias SVD terminates only "
|
||||
"when max_iterations is reached");
|
||||
PerformAction<BiasSVDPolicy>(dataset, rank, maxIterations, minResidue);
|
||||
}
|
||||
else if (algorithm == "SVDPP")
|
||||
{
|
||||
ReportIgnoredParam("min_residue", "SVD++ terminates only "
|
||||
"when max_iterations is reached");
|
||||
PerformAction<SVDPlusPlusPolicy>(dataset, rank, maxIterations, minResidue);
|
||||
}
|
||||
}
|
||||
|
||||
static void mlpackMain()
|
||||
{
|
||||
if (IO::GetParam<int>("seed") == 0)
|
||||
@@ -496,6 +223,7 @@ static void mlpackMain()
|
||||
"recommendations must be positive");
|
||||
|
||||
// Either load from a model, or train a model.
|
||||
CFModel* cf;
|
||||
if (IO::HasParam("training"))
|
||||
{
|
||||
// Train a model.
|
||||
@@ -523,23 +251,179 @@ static void mlpackMain()
|
||||
// Get parameters.
|
||||
const size_t rank = (size_t) IO::GetParam<int>("rank");
|
||||
|
||||
cf = new CFModel();
|
||||
|
||||
// Perform decomposition to prepare for recommendations.
|
||||
Log::Info << "Performing CF matrix decomposition on dataset..." << endl;
|
||||
|
||||
const string algo = IO::GetParam<string>("algorithm");
|
||||
if (algo == "NMF")
|
||||
{
|
||||
cf->DecompositionType() = CFModel::NMF;
|
||||
}
|
||||
else if (algo == "BatchSVD")
|
||||
{
|
||||
cf->DecompositionType() = CFModel::BATCH_SVD;
|
||||
}
|
||||
else if (algo == "SVDIncompleteIncremental")
|
||||
{
|
||||
cf->DecompositionType() = CFModel::SVD_INCOMPLETE;
|
||||
}
|
||||
else if (algo == "SVDCompleteIncremental")
|
||||
{
|
||||
cf->DecompositionType() = CFModel::SVD_COMPLETE;
|
||||
}
|
||||
else if (algo == "RegSVD")
|
||||
{
|
||||
ReportIgnoredParam("min_residue", "Regularized SVD terminates only "
|
||||
"when max_iterations is reached");
|
||||
cf->DecompositionType() = CFModel::REG_SVD;
|
||||
}
|
||||
else if (algo == "RandSVD")
|
||||
{
|
||||
ReportIgnoredParam("min_residue", "Randomized SVD terminates only "
|
||||
"when max_iterations is reached");
|
||||
cf->DecompositionType() = CFModel::RANDOMIZED_SVD;
|
||||
}
|
||||
else if (algo == "BiasSVD")
|
||||
{
|
||||
ReportIgnoredParam("min_residue", "Bias SVD terminates only "
|
||||
"when max_iterations is reached");
|
||||
cf->DecompositionType() = CFModel::BIAS_SVD;
|
||||
}
|
||||
else if (algo == "SVDPP")
|
||||
{
|
||||
ReportIgnoredParam("min_residue", "SVD++ terminates only "
|
||||
"when max_iterations is reached");
|
||||
cf->DecompositionType() = CFModel::SVD_PLUS_PLUS;
|
||||
}
|
||||
|
||||
// Perform the factorization and do whatever the user wanted.
|
||||
AssembleFactorizerType(algo, dataset, rank);
|
||||
const size_t neighborhood = (size_t) IO::GetParam<int>("neighborhood");
|
||||
|
||||
// Make sure the normalization strategy is valid.
|
||||
RequireParamInSet<string>("normalization", { "overall_mean", "item_mean",
|
||||
"user_mean", "z_score", "none" }, true, "unknown normalization type");
|
||||
|
||||
const string normalizationType = IO::GetParam<string>("normalization");
|
||||
if (normalizationType == "none")
|
||||
cf->NormalizationType() = CFModel::NO_NORMALIZATION;
|
||||
else if (normalizationType == "item_mean")
|
||||
cf->NormalizationType() = CFModel::ITEM_MEAN_NORMALIZATION;
|
||||
else if (normalizationType == "user_mean")
|
||||
cf->NormalizationType() = CFModel::USER_MEAN_NORMALIZATION;
|
||||
else if (normalizationType == "overall_mean")
|
||||
cf->NormalizationType() = CFModel::OVERALL_MEAN_NORMALIZATION;
|
||||
else if (normalizationType == "z_score")
|
||||
cf->NormalizationType() = CFModel::Z_SCORE_NORMALIZATION;
|
||||
|
||||
cf->Train(dataset,
|
||||
neighborhood,
|
||||
rank,
|
||||
size_t(IO::GetParam<int>("max_iterations")),
|
||||
IO::GetParam<double>("min_residue"),
|
||||
IO::HasParam("iteration_only_termination"));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Load from a model after validating parameters.
|
||||
RequireAtLeastOnePassed({ "query", "all_user_recommendations",
|
||||
"test" }, true);
|
||||
RequireAtLeastOnePassed({ "query", "all_user_recommendations", "test" },
|
||||
true);
|
||||
|
||||
// Load an input model.
|
||||
CFModel* c = std::move(IO::GetParam<CFModel*>("input_model"));
|
||||
|
||||
PerformAction(c);
|
||||
cf = std::move(IO::GetParam<CFModel*>("input_model"));
|
||||
}
|
||||
|
||||
// Get the types of the neighbor search method and the interpolation. (These
|
||||
// may or may not be used.)
|
||||
NeighborSearchTypes nsType;
|
||||
RequireParamInSet<string>("neighbor_search", { "cosine",
|
||||
"euclidean", "pearson" }, true, "unknown neighbor search algorithm");
|
||||
if (IO::GetParam<std::string>("neighbor_search") == "cosine")
|
||||
nsType = COSINE_SEARCH;
|
||||
else if (IO::GetParam<std::string>("neighbor_search") == "euclidean")
|
||||
nsType = EUCLIDEAN_SEARCH;
|
||||
else // if (IO::GetParam<std::string>("neighbor_search") == "pearson")
|
||||
nsType = PEARSON_SEARCH;
|
||||
|
||||
InterpolationTypes interpolationType;
|
||||
RequireParamInSet<string>("interpolation", { "average",
|
||||
"regression", "similarity" }, true, "unknown interpolation algorithm");
|
||||
if (IO::GetParam<std::string>("interpolation") == "average")
|
||||
interpolationType = AVERAGE_INTERPOLATION;
|
||||
else if (IO::GetParam<std::string>("interpolation") == "regression")
|
||||
interpolationType = REGRESSION_INTERPOLATION;
|
||||
else // if (IO::GetParam<std::string>("interpolation") == "similarity")
|
||||
interpolationType = SIMILARITY_INTERPOLATION;
|
||||
|
||||
if (IO::HasParam("query") || IO::HasParam("all_user_recommendations"))
|
||||
{
|
||||
// Get parameters for generating recommendations.
|
||||
const size_t numRecs = (size_t) IO::GetParam<int>("recommendations");
|
||||
|
||||
// Get the recommendations.
|
||||
arma::Mat<size_t> recommendations;
|
||||
|
||||
// Reading users.
|
||||
if (IO::HasParam("query"))
|
||||
{
|
||||
// User matrix.
|
||||
arma::Mat<size_t> users =
|
||||
std::move(IO::GetParam<arma::Mat<size_t>>("query"));
|
||||
if (users.n_rows > 1)
|
||||
{
|
||||
users = users.t();
|
||||
}
|
||||
|
||||
if (users.n_rows > 1)
|
||||
{
|
||||
Log::Fatal << "List of query users must be one-dimensional!"
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
Log::Info << "Generating recommendations for " << users.n_elem
|
||||
<< " users." << endl;
|
||||
|
||||
cf->GetRecommendations(nsType, interpolationType, numRecs,
|
||||
recommendations, users.row(0).t());
|
||||
}
|
||||
else
|
||||
{
|
||||
Log::Info << "Generating recommendations for all users." << endl;
|
||||
cf->GetRecommendations(nsType, interpolationType, numRecs,
|
||||
recommendations);
|
||||
}
|
||||
|
||||
// Save the output.
|
||||
IO::GetParam<arma::Mat<size_t>>("output") = recommendations;
|
||||
}
|
||||
|
||||
if (IO::HasParam("test"))
|
||||
{
|
||||
// Now, compute each test point.
|
||||
arma::mat testData = std::move(IO::GetParam<arma::mat>("test"));
|
||||
|
||||
// Assemble the combination matrix to get RMSE value.
|
||||
arma::Mat<size_t> combinations(2, testData.n_cols);
|
||||
for (size_t i = 0; i < testData.n_cols; ++i)
|
||||
{
|
||||
combinations(0, i) = size_t(testData(0, i));
|
||||
combinations(1, i) = size_t(testData(1, i));
|
||||
}
|
||||
|
||||
// Now compute the RMSE.
|
||||
arma::vec predictions;
|
||||
cf->Predict(nsType, interpolationType, combinations, predictions);
|
||||
|
||||
// Compute the root of the sum of the squared errors, divide by the number
|
||||
// of points to get the RMSE. It turns out this is just the L2-norm divided
|
||||
// by the square root of the number of points, if we interpret the
|
||||
// predictions and the true values as vectors.
|
||||
const double rmse = arma::norm(predictions - testData.row(2).t(), 2) /
|
||||
std::sqrt((double) testData.n_cols);
|
||||
|
||||
Log::Info << "RMSE is " << rmse << "." << endl;
|
||||
}
|
||||
|
||||
IO::GetParam<CFModel*>("output_model") = cf;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,207 @@
|
||||
/**
|
||||
* @file methods/cf/cf_model_impl.hpp
|
||||
* @author Wenhao Huang
|
||||
*
|
||||
* A serializable CF model, used by the main program.
|
||||
*
|
||||
* mlpack is free software; you may redistribute it and/or modify it under the
|
||||
* terms of the 3-clause BSD license. You should have received a copy of the
|
||||
* 3-clause BSD license along with mlpack. If not, see
|
||||
* http://www.opensource.org/licenses/BSD-3-Clause for more information.
|
||||
*/
|
||||
#include "cf_model.hpp"
|
||||
|
||||
namespace mlpack {
|
||||
namespace cf {
|
||||
|
||||
CFModel::CFModel() :
|
||||
decompositionType(NMF),
|
||||
normalizationType(NO_NORMALIZATION),
|
||||
cf(NULL)
|
||||
{
|
||||
// Nothing else to do.
|
||||
}
|
||||
|
||||
CFModel::CFModel(const CFModel& other) :
|
||||
decompositionType(other.decompositionType),
|
||||
normalizationType(other.normalizationType),
|
||||
cf(other.cf->Clone())
|
||||
{
|
||||
// Nothing else to do.
|
||||
}
|
||||
|
||||
CFModel::CFModel(CFModel&& other) :
|
||||
decompositionType(other.decompositionType),
|
||||
normalizationType(other.normalizationType),
|
||||
cf(std::move(other.cf))
|
||||
{
|
||||
// Reset properties of the other one.
|
||||
other.decompositionType = NMF;
|
||||
other.normalizationType = NO_NORMALIZATION;
|
||||
}
|
||||
|
||||
CFModel& CFModel::operator=(const CFModel& other)
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
decompositionType = other.decompositionType;
|
||||
normalizationType = other.normalizationType;
|
||||
cf = other.cf->Clone();
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
CFModel& CFModel::operator=(CFModel&& other)
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
decompositionType = other.decompositionType;
|
||||
normalizationType = other.normalizationType;
|
||||
cf = std::move(other.cf);
|
||||
|
||||
// Reset the other object.
|
||||
other.decompositionType = NMF;
|
||||
other.normalizationType = NO_NORMALIZATION;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
CFModel::~CFModel()
|
||||
{
|
||||
delete cf;
|
||||
}
|
||||
|
||||
template<typename DecompositionPolicy>
|
||||
CFWrapperBase* TrainHelper(const DecompositionPolicy& decomposition,
|
||||
const CFModel::NormalizationTypes normalizationType,
|
||||
const arma::mat& data,
|
||||
const size_t numUsersForSimilarity,
|
||||
const size_t rank,
|
||||
const size_t maxIterations,
|
||||
const double minResidue,
|
||||
const bool mit)
|
||||
{
|
||||
switch (normalizationType)
|
||||
{
|
||||
case CFModel::NO_NORMALIZATION:
|
||||
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.
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void CFModel::Train(const arma::mat& data,
|
||||
const size_t numUsersForSimilarity,
|
||||
const size_t rank,
|
||||
const size_t maxIterations,
|
||||
const double minResidue,
|
||||
const bool mit)
|
||||
{
|
||||
// Delete the current CFType object, if there is one.
|
||||
delete cf;
|
||||
|
||||
switch (decompositionType)
|
||||
{
|
||||
case NMF:
|
||||
cf = TrainHelper(NMFPolicy(), normalizationType, data,
|
||||
numUsersForSimilarity, rank, maxIterations, minResidue, mit);
|
||||
break;
|
||||
|
||||
case BATCH_SVD:
|
||||
cf = TrainHelper(BatchSVDPolicy(), normalizationType, data,
|
||||
numUsersForSimilarity, rank, maxIterations, minResidue, mit);
|
||||
break;
|
||||
|
||||
case RANDOMIZED_SVD:
|
||||
cf = TrainHelper(RandomizedSVDPolicy(), normalizationType, data,
|
||||
numUsersForSimilarity, rank, maxIterations, minResidue, mit);
|
||||
break;
|
||||
|
||||
case REG_SVD:
|
||||
cf = TrainHelper(RegSVDPolicy(), normalizationType, data,
|
||||
numUsersForSimilarity, rank, maxIterations, minResidue, mit);
|
||||
break;
|
||||
|
||||
case SVD_COMPLETE:
|
||||
cf = TrainHelper(SVDCompletePolicy(), normalizationType, data,
|
||||
numUsersForSimilarity, rank, maxIterations, minResidue, mit);
|
||||
break;
|
||||
|
||||
case SVD_INCOMPLETE:
|
||||
cf = TrainHelper(SVDIncompletePolicy(), normalizationType, data,
|
||||
numUsersForSimilarity, rank, maxIterations, minResidue, mit);
|
||||
break;
|
||||
|
||||
case BIAS_SVD:
|
||||
cf = TrainHelper(BiasSVDPolicy(), normalizationType, data,
|
||||
numUsersForSimilarity, rank, maxIterations, minResidue, mit);
|
||||
break;
|
||||
|
||||
case SVD_PLUS_PLUS:
|
||||
cf = TrainHelper(SVDPlusPlusPolicy(), normalizationType, data,
|
||||
numUsersForSimilarity, rank, maxIterations, minResidue, mit);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//! Make predictions.
|
||||
void CFModel::Predict(const NeighborSearchTypes nsType,
|
||||
const InterpolationTypes interpolationType,
|
||||
const arma::Mat<size_t>& combinations,
|
||||
arma::vec& predictions)
|
||||
{
|
||||
cf->Predict(nsType, interpolationType, combinations, predictions);
|
||||
}
|
||||
|
||||
//! Compute recommendations for queried users.
|
||||
void CFModel::GetRecommendations(const NeighborSearchTypes nsType,
|
||||
const InterpolationTypes interpolationType,
|
||||
const size_t numRecs,
|
||||
arma::Mat<size_t>& recommendations,
|
||||
const arma::Col<size_t>& users)
|
||||
{
|
||||
cf->GetRecommendations(nsType, interpolationType, numRecs, recommendations,
|
||||
users);
|
||||
}
|
||||
|
||||
//! Compute recommendations for all users.
|
||||
void CFModel::GetRecommendations(const NeighborSearchTypes nsType,
|
||||
const InterpolationTypes interpolationType,
|
||||
const size_t numRecs,
|
||||
arma::Mat<size_t>& recommendations)
|
||||
{
|
||||
cf->GetRecommendations(nsType, interpolationType, numRecs, recommendations);
|
||||
}
|
||||
|
||||
} // namespace cf
|
||||
} // namespace mlpack
|
||||
+189
-136
@@ -14,105 +14,146 @@
|
||||
#define MLPACK_METHODS_CF_CF_MODEL_HPP
|
||||
|
||||
#include <mlpack/core.hpp>
|
||||
#include <boost/variant.hpp>
|
||||
#include "cf.hpp"
|
||||
|
||||
#include <mlpack/methods/cf/decomposition_policies/batch_svd_method.hpp>
|
||||
#include <mlpack/methods/cf/decomposition_policies/randomized_svd_method.hpp>
|
||||
#include <mlpack/methods/cf/decomposition_policies/regularized_svd_method.hpp>
|
||||
#include <mlpack/methods/cf/decomposition_policies/svd_complete_method.hpp>
|
||||
#include <mlpack/methods/cf/decomposition_policies/svd_incomplete_method.hpp>
|
||||
#include <mlpack/methods/cf/decomposition_policies/bias_svd_method.hpp>
|
||||
#include <mlpack/methods/cf/decomposition_policies/svdplusplus_method.hpp>
|
||||
|
||||
#include <mlpack/methods/cf/normalization/no_normalization.hpp>
|
||||
#include <mlpack/methods/cf/normalization/overall_mean_normalization.hpp>
|
||||
#include <mlpack/methods/cf/normalization/user_mean_normalization.hpp>
|
||||
#include <mlpack/methods/cf/normalization/item_mean_normalization.hpp>
|
||||
#include <mlpack/methods/cf/normalization/z_score_normalization.hpp>
|
||||
|
||||
namespace mlpack {
|
||||
namespace cf {
|
||||
|
||||
/**
|
||||
* DeleteVisitor deletes the CFType<> object which is pointed to by the
|
||||
* variable cf in class CFModel.
|
||||
* NeighborSearchTypes contains the set of NeighborSearchPolicy classes that are
|
||||
* usable by CFModel at prediction time.
|
||||
*/
|
||||
class DeleteVisitor : public boost::static_visitor<void>
|
||||
enum NeighborSearchTypes
|
||||
{
|
||||
public:
|
||||
//! Delete CFType object.
|
||||
template <typename DecompositionPolicy,
|
||||
typename NormalizationType = NoNormalization>
|
||||
void operator()(CFType<DecompositionPolicy, NormalizationType>* c) const;
|
||||
COSINE_SEARCH,
|
||||
EUCLIDEAN_SEARCH,
|
||||
PEARSON_SEARCH
|
||||
};
|
||||
|
||||
/**
|
||||
* GetValueVisitor returns the pointer which points to the CFType object.
|
||||
* InterpolationTypes contains the set of InterpolationPolicy classes that are
|
||||
* usable by CFModel at prediction time.
|
||||
*/
|
||||
class GetValueVisitor : public boost::static_visitor<void*>
|
||||
enum InterpolationTypes
|
||||
{
|
||||
public:
|
||||
//! Return stored pointer as void* type.
|
||||
template <typename DecompositionPolicy,
|
||||
typename NormalizationType = NoNormalization>
|
||||
void* operator()(CFType<DecompositionPolicy, NormalizationType>* c) const;
|
||||
AVERAGE_INTERPOLATION,
|
||||
REGRESSION_INTERPOLATION,
|
||||
SIMILARITY_INTERPOLATION
|
||||
};
|
||||
|
||||
/**
|
||||
* PredictVisitor uses the CFType object to make predictions on the given
|
||||
* combinations of users and items.
|
||||
* The CFWrapperBase class provides a unified interface that can be used by the
|
||||
* CFModel class to interact with all different CF types at runtime. All CF
|
||||
* wrapper types inherit from this base class.
|
||||
*/
|
||||
template <typename NeighborSearchPolicy,
|
||||
typename InterpolationPolicy>
|
||||
class PredictVisitor : public boost::static_visitor<void>
|
||||
class CFWrapperBase
|
||||
{
|
||||
private:
|
||||
//! User/item combinations to predict.
|
||||
const arma::Mat<size_t>& combinations;
|
||||
//! Predicted ratings for each user/item combination.
|
||||
arma::vec& predictions;
|
||||
|
||||
public:
|
||||
//! Predict ratings for each user-item combination.
|
||||
template <typename DecompositionPolicy,
|
||||
typename NormalizationType = NoNormalization>
|
||||
void operator()(CFType<DecompositionPolicy, NormalizationType>* c) const;
|
||||
//! Create the object. The base class has nothing to hold.
|
||||
CFWrapperBase() { }
|
||||
|
||||
//! Visitor constructor.
|
||||
PredictVisitor(const arma::Mat<size_t>& combinations,
|
||||
arma::vec& predictions);
|
||||
//! Make a copy of the object.
|
||||
virtual CFWrapperBase* Clone() const = 0;
|
||||
|
||||
//! Delete the object.
|
||||
virtual ~CFWrapperBase() { }
|
||||
|
||||
//! Compute predictions for users.
|
||||
virtual void Predict(const NeighborSearchTypes nsType,
|
||||
const InterpolationTypes interpolationType,
|
||||
const arma::Mat<size_t>& combinations,
|
||||
arma::vec& predictions) = 0;
|
||||
|
||||
//! Compute recommendations for all users.
|
||||
virtual void GetRecommendations(
|
||||
const NeighborSearchTypes nsType,
|
||||
const InterpolationTypes interpolationType,
|
||||
const size_t numRecs,
|
||||
arma::Mat<size_t>& recommendations) = 0;
|
||||
|
||||
//! Compute recommendations.
|
||||
virtual void GetRecommendations(
|
||||
const NeighborSearchTypes nsType,
|
||||
const InterpolationTypes interpolationType,
|
||||
const size_t numRecs,
|
||||
arma::Mat<size_t>& recommendations,
|
||||
const arma::Col<size_t>& users) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* RecommendationVisitor uses the CFType object to get recommendations for the
|
||||
* given users.
|
||||
* The CFWrapper class wraps the functionality of all CF types. If special
|
||||
* handling is needed for a future CF type, this class can be extended.
|
||||
*/
|
||||
template <typename NeighborSearchPolicy,
|
||||
typename InterpolationPolicy>
|
||||
class RecommendationVisitor : public boost::static_visitor<void>
|
||||
template<typename DecompositionPolicy, typename NormalizationPolicy>
|
||||
class CFWrapper : public CFWrapperBase
|
||||
{
|
||||
private:
|
||||
//! Number of Recommendations.
|
||||
const size_t numRecs;
|
||||
//! Recommendations matrix to save recommendations.
|
||||
arma::Mat<size_t>& recommendations;
|
||||
//! Users for which recommendations are to be generated.
|
||||
const arma::Col<size_t>& users;
|
||||
//! Whether users are given.
|
||||
const bool usersGiven;
|
||||
protected:
|
||||
typedef CFType<DecompositionPolicy, NormalizationPolicy> CFModelType;
|
||||
|
||||
public:
|
||||
//! Visitor constructor.
|
||||
RecommendationVisitor(const size_t numRecs,
|
||||
arma::Mat<size_t>& recommendations,
|
||||
const arma::Col<size_t>& users,
|
||||
const bool usersGiven);
|
||||
//! Create the CFWrapper object, using default parameters to initialize the
|
||||
//! held CF object.
|
||||
CFWrapper() { }
|
||||
|
||||
//! Generates the given number of recommendations.
|
||||
template <typename DecompositionPolicy,
|
||||
typename NormalizationType = NoNormalization>
|
||||
void operator()(CFType<DecompositionPolicy, NormalizationType>* c) const;
|
||||
//! Create the CFWrapper object, initializing the held CF object.
|
||||
CFWrapper(const arma::mat& data,
|
||||
const DecompositionPolicy& decomposition,
|
||||
const size_t numUsersForSimilarity,
|
||||
const size_t rank,
|
||||
const size_t maxIterations,
|
||||
const size_t minResidue,
|
||||
const bool mit) :
|
||||
cf(data,
|
||||
decomposition,
|
||||
numUsersForSimilarity,
|
||||
rank,
|
||||
maxIterations,
|
||||
minResidue,
|
||||
mit)
|
||||
{
|
||||
// Nothing else to do.
|
||||
}
|
||||
|
||||
//! Clone the CFWrapper object. This handles polymorphism correctly.
|
||||
virtual CFWrapper* Clone() const { return new CFWrapper(*this); }
|
||||
|
||||
//! Destroy the CFWrapper object.
|
||||
virtual ~CFWrapper() { }
|
||||
|
||||
//! Get the CFType object.
|
||||
CFModelType& CF() { return cf; }
|
||||
|
||||
//! Compute predictions for users.
|
||||
virtual void Predict(const NeighborSearchTypes nsType,
|
||||
const InterpolationTypes interpolationType,
|
||||
const arma::Mat<size_t>& combinations,
|
||||
arma::vec& predictions);
|
||||
|
||||
//! Compute recommendations for all users.
|
||||
virtual void GetRecommendations(
|
||||
const NeighborSearchTypes nsType,
|
||||
const InterpolationTypes interpolationType,
|
||||
const size_t numRecs,
|
||||
arma::Mat<size_t>& recommendations);
|
||||
|
||||
//! Compute recommendations.
|
||||
virtual void GetRecommendations(
|
||||
const NeighborSearchTypes nsType,
|
||||
const InterpolationTypes interpolationType,
|
||||
const size_t numRecs,
|
||||
arma::Mat<size_t>& recommendations,
|
||||
const arma::Col<size_t>& users);
|
||||
|
||||
//! Serialize the model.
|
||||
template<typename Archive>
|
||||
void serialize(Archive& ar, const uint32_t /* version */)
|
||||
{
|
||||
ar(CEREAL_NVP(cf));
|
||||
}
|
||||
|
||||
protected:
|
||||
//! This is the CF object that we are wrapping.
|
||||
CFModelType cf;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -120,98 +161,110 @@ class RecommendationVisitor : public boost::static_visitor<void>
|
||||
*/
|
||||
class CFModel
|
||||
{
|
||||
public:
|
||||
enum DecompositionTypes
|
||||
{
|
||||
NMF,
|
||||
BATCH_SVD,
|
||||
RANDOMIZED_SVD,
|
||||
REG_SVD,
|
||||
SVD_COMPLETE,
|
||||
SVD_INCOMPLETE,
|
||||
BIAS_SVD,
|
||||
SVD_PLUS_PLUS
|
||||
};
|
||||
|
||||
enum NormalizationTypes
|
||||
{
|
||||
NO_NORMALIZATION,
|
||||
ITEM_MEAN_NORMALIZATION,
|
||||
USER_MEAN_NORMALIZATION,
|
||||
OVERALL_MEAN_NORMALIZATION,
|
||||
Z_SCORE_NORMALIZATION
|
||||
};
|
||||
|
||||
private:
|
||||
//! The current decomposition policy type.
|
||||
DecompositionTypes decompositionType;
|
||||
//! The current normalization policy type.
|
||||
NormalizationTypes normalizationType;
|
||||
|
||||
/**
|
||||
* cf holds an instance of the CFType class for the current
|
||||
* decompositionPolicy and normalizationType. It is initialized every time
|
||||
* Train() is executed. We access to the contained value through the visitor
|
||||
* classes defined above.
|
||||
* Train() is executed.
|
||||
*/
|
||||
boost::variant<CFType<NMFPolicy, NoNormalization>*,
|
||||
CFType<BatchSVDPolicy, NoNormalization>*,
|
||||
CFType<RandomizedSVDPolicy, NoNormalization>*,
|
||||
CFType<RegSVDPolicy, NoNormalization>*,
|
||||
CFType<SVDCompletePolicy, NoNormalization>*,
|
||||
CFType<SVDIncompletePolicy, NoNormalization>*,
|
||||
CFType<BiasSVDPolicy, NoNormalization>*,
|
||||
CFType<SVDPlusPlusPolicy, NoNormalization>*,
|
||||
|
||||
CFType<NMFPolicy, ItemMeanNormalization>*,
|
||||
CFType<BatchSVDPolicy, ItemMeanNormalization>*,
|
||||
CFType<RandomizedSVDPolicy, ItemMeanNormalization>*,
|
||||
CFType<RegSVDPolicy, ItemMeanNormalization>*,
|
||||
CFType<SVDCompletePolicy, ItemMeanNormalization>*,
|
||||
CFType<SVDIncompletePolicy, ItemMeanNormalization>*,
|
||||
CFType<BiasSVDPolicy, ItemMeanNormalization>*,
|
||||
CFType<SVDPlusPlusPolicy, ItemMeanNormalization>*,
|
||||
|
||||
CFType<NMFPolicy, UserMeanNormalization>*,
|
||||
CFType<BatchSVDPolicy, UserMeanNormalization>*,
|
||||
CFType<RandomizedSVDPolicy, UserMeanNormalization>*,
|
||||
CFType<RegSVDPolicy, UserMeanNormalization>*,
|
||||
CFType<SVDCompletePolicy, UserMeanNormalization>*,
|
||||
CFType<SVDIncompletePolicy, UserMeanNormalization>*,
|
||||
CFType<BiasSVDPolicy, UserMeanNormalization>*,
|
||||
CFType<SVDPlusPlusPolicy, UserMeanNormalization>*,
|
||||
|
||||
CFType<NMFPolicy, OverallMeanNormalization>*,
|
||||
CFType<BatchSVDPolicy, OverallMeanNormalization>*,
|
||||
CFType<RandomizedSVDPolicy, OverallMeanNormalization>*,
|
||||
CFType<RegSVDPolicy, OverallMeanNormalization>*,
|
||||
CFType<SVDCompletePolicy, OverallMeanNormalization>*,
|
||||
CFType<SVDIncompletePolicy, OverallMeanNormalization>*,
|
||||
CFType<BiasSVDPolicy, OverallMeanNormalization>*,
|
||||
CFType<SVDPlusPlusPolicy, OverallMeanNormalization>*,
|
||||
|
||||
CFType<NMFPolicy, ZScoreNormalization>*,
|
||||
CFType<BatchSVDPolicy, ZScoreNormalization>*,
|
||||
CFType<RandomizedSVDPolicy, ZScoreNormalization>*,
|
||||
CFType<RegSVDPolicy, ZScoreNormalization>*,
|
||||
CFType<SVDCompletePolicy, ZScoreNormalization>*,
|
||||
CFType<SVDIncompletePolicy, ZScoreNormalization>*,
|
||||
CFType<BiasSVDPolicy, ZScoreNormalization>*,
|
||||
CFType<SVDPlusPlusPolicy, ZScoreNormalization>*> cf;
|
||||
CFWrapperBase* cf;
|
||||
|
||||
public:
|
||||
//! Create an empty CF model.
|
||||
CFModel() { }
|
||||
CFModel();
|
||||
|
||||
//! Create a CF model by copying the given model.
|
||||
CFModel(const CFModel& other);
|
||||
|
||||
//! Create a CF model by taking ownership of the data of the other model.
|
||||
CFModel(CFModel&& other);
|
||||
|
||||
//! Make this CF model a copy of the other model.
|
||||
CFModel& operator=(const CFModel& other);
|
||||
|
||||
//! Make this CF model take ownership of the data of the other model.
|
||||
CFModel& operator=(CFModel&& other);
|
||||
|
||||
//! Clean up memory.
|
||||
~CFModel();
|
||||
|
||||
//! Get the pointer to CFType<> object.
|
||||
template <typename DecompositionPolicy,
|
||||
typename NormalizationType = NoNormalization>
|
||||
const CFType<DecompositionPolicy, NormalizationType>* CFPtr() const;
|
||||
//! Get the CFWrapperBase object. (Be careful!)
|
||||
CFWrapperBase* CF() const { return cf; }
|
||||
|
||||
//! Get the decomposition type.
|
||||
const DecompositionTypes& DecompositionType() const
|
||||
{
|
||||
return decompositionType;
|
||||
}
|
||||
//! Set the decomposition type.
|
||||
DecompositionTypes& DecompositionType()
|
||||
{
|
||||
return decompositionType;
|
||||
}
|
||||
|
||||
//! Get the normalization type.
|
||||
const NormalizationTypes& NormalizationType() const
|
||||
{
|
||||
return normalizationType;
|
||||
}
|
||||
//! Set the normalization type.
|
||||
NormalizationTypes& NormalizationType()
|
||||
{
|
||||
return normalizationType;
|
||||
}
|
||||
|
||||
//! Train the model.
|
||||
template<typename DecompositionPolicy,
|
||||
typename MatType>
|
||||
void Train(const MatType& data,
|
||||
void Train(const arma::mat& data,
|
||||
const size_t numUsersForSimilarity,
|
||||
const size_t rank,
|
||||
const size_t maxIterations,
|
||||
const double minResidue,
|
||||
const bool mit,
|
||||
const std::string& normalizationType = "none");
|
||||
const bool mit);
|
||||
|
||||
//! Make predictions.
|
||||
template <typename NeighborSearchPolicy,
|
||||
typename InterpolationPolicy>
|
||||
void Predict(const arma::Mat<size_t>& combinations,
|
||||
void Predict(const NeighborSearchTypes nsType,
|
||||
const InterpolationTypes interpolationType,
|
||||
const arma::Mat<size_t>& combinations,
|
||||
arma::vec& predictions);
|
||||
|
||||
//! Compute recommendations for query users.
|
||||
template<typename NeighborSearchPolicy,
|
||||
typename InterpolationPolicy>
|
||||
void GetRecommendations(const size_t numRecs,
|
||||
void GetRecommendations(const NeighborSearchTypes nsType,
|
||||
const InterpolationTypes interpolationType,
|
||||
const size_t numRecs,
|
||||
arma::Mat<size_t>& recommendations,
|
||||
const arma::Col<size_t>& users);
|
||||
|
||||
//! Compute recommendations for all users.
|
||||
template<typename NeighborSearchPolicy,
|
||||
typename InterpolationPolicy>
|
||||
void GetRecommendations(const size_t numRecs,
|
||||
void GetRecommendations(const NeighborSearchTypes nsType,
|
||||
const InterpolationTypes interpolationType,
|
||||
const size_t numRecs,
|
||||
arma::Mat<size_t>& recommendations);
|
||||
|
||||
//! Serialize the model.
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user