Merge remote-tracking branch 'origin/master' into julia-bindings

This commit is contained in:
Ryan Curtin
2019-11-27 13:16:41 -05:00
277 changed files with 18411 additions and 2502 deletions
+19 -13
View File
@@ -11,9 +11,8 @@ environment:
boost_serialization-vc140.1.60.0.0/lib/native/address-model-64/lib/*.*"
BOOST_UNIT_TEST : "C:/projects/mlpack/\
boost_unit_test_framework-vc140.1.60.0.0/lib/native/address-model-64/lib/*.*"
ARMADILLO_DOWNLOAD : "http://sourceforge.net/projects/arma/files/\
armadillo-7.800.2.tar.xz"
ARMADILLO_LIBRARY : "C:/projects/mlpack/armadillo-7.800.2/\
ARMADILLO_DOWNLOAD : "http://ftp.fau.de/macports/distfiles/armadillo/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"
@@ -25,8 +24,15 @@ environment:
matrix:
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
VSVER: Visual Studio 14 2015 Win64
MSBUILD: C:\Program Files (x86)\MSBuild\14.0\bin\MSBuild.exe
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
VSVER: Visual Studio 15 2017 Win64
MSBUILD: C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin\MSBuild.exe
# Currently, the VS2019 build seems to always time out. This seems to be an
# AppVeyor issue.
# - 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
configuration: Release
@@ -62,28 +68,26 @@ build_script:
- ps: cp ${env:BOOST_UNIT_TEST} C:\projects\mlpack\boost_libs\
- echo TEST_ARMA is %ARMADILLO_DOWNLOAD%
- >
if not exist armadillo.tar.xz
appveyor DownloadFile %ARMADILLO_DOWNLOAD%
-FileName armadillo.tar.xz
- 7z x armadillo.tar.xz -so | 7z x -si -ttar > nul
- cd armadillo-7.800.2 && mkdir build && cd build
- 7z x armadillo.tar.xz -so -txz | 7z x -si -ttar > nul
- cd armadillo-8.400.0 && mkdir build && cd build
- >
cmake -G "Visual Studio 14 2015 Win64"
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 ..
- >
"C:\Program Files (x86)\MSBuild\14.0\Bin\MSBuild.exe"
"C:\projects\mlpack\armadillo-7.800.2\build\armadillo.sln"
"%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 "Visual Studio 14 2015 Win64"
cmake -G "%VSVER%"
-DBLAS_LIBRARY:FILEPATH=%BLAS_LIBRARY%
-DLAPACK_LIBRARY:FILEPATH=%BLAS_LIBRARY%
-DARMADILLO_INCLUDE_DIR="C:/projects/mlpack/armadillo-7.800.2/include"
-DARMADILLO_INCLUDE_DIR="C:/projects/mlpack/armadillo-8.400.0/include"
-DARMADILLO_LIBRARY:FILEPATH=%ARMADILLO_LIBRARY%
-DBOOST_INCLUDEDIR:PATH=%BOOST_INCLUDE%
-DBOOST_LIBRARYDIR:PATH="C:/projects/mlpack/boost_libs"
@@ -92,8 +96,7 @@ build_script:
-DBUILD_PYTHON_BINDINGS=OFF
-DCMAKE_BUILD_TYPE=Release ..
- >
"C:\Program Files (x86)\MSBuild\14.0\Bin\MSBuild.exe"
"C:\projects\mlpack\build\mlpack.sln"
"%MSBUILD%" "C:\projects\mlpack\build\mlpack.sln"
/m /verbosity:minimal /nologo /p:BuildInParallel=true
/p:Configuration=Release;Platform=x64
@@ -143,6 +146,9 @@ build_script:
- 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: >
+96
View File
@@ -0,0 +1,96 @@
jobs:
- job: Linux
timeoutInMinutes: 360
pool:
vmImage: ubuntu-16.04
strategy:
matrix:
Plain:
CMakeArgs: '-DDEBUG=ON -DPROFILE=OFF -DBUILD_PYTHON_BINDINGS=OFF'
python.version: '2.7'
Python27:
python.version: '2.7'
CMakeArgs: '-DDEBUG=OFF -DPROFILE=OFF -DPYTHON_EXECUTABLE=/usr/bin/python'
Python37:
python.version: '3.7'
CMakeArgs: '-DDEBUG=OFF -DPROFILE=OFF -DPYTHON_EXECUTABLE=/usr/bin/python3'
Markdown:
python.version: '2.7'
CMakeArgs: '-DDEBUG=OFF -DPROFILE=OFF -DBUILD_MARKDOWN_BINDINGS=ON -DBUILD_PYTHON_BINDINGS=OFF'
steps:
- template: linux-steps.yaml
- job: macOS
timeoutInMinutes: 360
pool:
vmImage: macOS-10.13
strategy:
matrix:
Plain:
CMakeArgs: '-DDEBUG=ON -DPROFILE=OFF -DBUILD_PYTHON_BINDINGS=OFF'
python.version: '2.7'
Python27:
python.version: '2.7'
CMakeArgs: '-DDEBUG=OFF -DPROFILE=OFF'
Python37:
python.version: '3.7'
CMakeArgs: '-DDEBUG=OFF -DPROFILE=OFF'
steps:
- template: macos-steps.yaml
- job: WindowsVS14
timeoutInMinutes: 360
displayName: Windows VS14
pool:
vmImage: vs2015-win2012r2
strategy:
matrix:
Plain:
CMakeArgs: '-DDEBUG=ON -DPROFILE=OFF -DBUILD_PYTHON_BINDINGS=OFF'
CMakeGenerator: '-G "Visual Studio 14 2015 Win64"'
MSBuildVersion: '14.0'
ArchiveNoLibs: 'mlpack-windows-vs14-no-libs.zip'
ArchiveLibs: 'mlpack-windows-vs14.zip'
ArchiveTests: 'mlpack_test-vs14.xml'
steps:
- template: windows-steps.yaml
- job: WindowsVS15
timeoutInMinutes: 360
displayName: Windows VS15
pool:
vmImage: vs2017-win2016
strategy:
matrix:
Plain:
CMakeArgs: '-DDEBUG=ON -DPROFILE=OFF -DBUILD_PYTHON_BINDINGS=OFF'
python.version: '2.7'
CMakeGenerator: '-G "Visual Studio 15 2017 Win64"'
MSBuildVersion: '15.0'
ArchiveNoLibs: 'mlpack-windows-vs15-no-libs.zip'
ArchiveLibs: 'mlpack-windows-vs15.zip'
ArchiveTests: 'mlpack_test-vs15.xml'
steps:
- template: windows-steps.yaml
- job: WindowsVS16
timeoutInMinutes: 360
displayName: Windows VS16
pool:
vmImage: windows-2019
strategy:
matrix:
Plain:
CMakeArgs: '-DDEBUG=ON -DPROFILE=OFF -DBUILD_PYTHON_BINDINGS=OFF'
python.version: '2.7'
CMakeGenerator: '-G "Visual Studio 16 2019"'
MSBuildVersion: '16.0'
ArchiveNoLibs: 'mlpack-windows-vs16-no-libs.zip'
ArchiveLibs: 'mlpack-windows-vs16.zip'
ArchiveTests: 'mlpack_test-vs16.xml'
steps:
- template: windows-steps.yaml
+73
View File
@@ -0,0 +1,73 @@
steps:
# Checkout repository
- checkout: self
clean: true
fetchDepth: 1
# Set python version
- task: UsePythonVersion@0
inputs:
versionSpec: '$(python.version)'
# Install build dependencies
- script: |
git clone --depth 1 https://github.com/mlpack/jenkins-conf.git conf
sudo add-apt-repository ppa:mhier/libboost-latest
sudo apt-get update
# Remove BOOST_ROOT from the environment to prevent attempting to use a
# boost which is incompatible with the compiler.
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
if [ '$(python.version)' == '2.7' ]; then
sudo apt-get install -y --allow-unauthenticated python-pip cython python-numpy python-pandas
sudo pip install --upgrade --ignore-installed setuptools cython
fi
if [ '$(python.version)' == '3.7' ]; then
sudo apt-get install -y --allow-unauthenticated python3-pip cython3 python3-numpy
sudo pip3 install --upgrade --ignore-installed setuptools cython pandas
fi
# Install armadillo.
curl https://ftp.fau.de/macports/distfiles/armadillo/armadillo-8.400.0.tar.xz | tar -xvJ && cd armadillo*
cmake . && make && sudo make install && cd ..
sudo cp .travis/config.hpp /usr/include/armadillo_bits/config.hpp
displayName: 'Install Build Dependencies'
# Configure mlpack (CMake)
- script: unset BOOST_ROOT && mkdir build && cd build && cmake $(CMakeArgs) ..
displayName: 'CMake'
# Build mlpack
- script: cd build && make -j2
displayName: 'Build'
# Run tests
- script: cd build && bin/mlpack_test --result_code=no --report_level=detailed --log_level=test_suite --log_format=HRF --log_sink=res.txt
displayName: 'Run tests'
# Process test results
- bash: |
python conf/ci/convert.py > mlpack_test.xml
displayName: 'Process test results'
# Publish test results to Azure Pipelines
- task: PublishTestResults@2
inputs:
testResultsFormat: JUnit
testResultsFiles: 'mlpack_test.xml'
failTaskOnFailedTests: true
displayName: 'Publish tests'
# Publish build artifacts to Azure Pipelines
- task: PublishBuildArtifacts@1
inputs:
pathtoPublish: 'mlpack_test.xml'
artifactName: 'mlpack_test_linux.xml'
displayName: 'Publish artifacts test results'
+58
View File
@@ -0,0 +1,58 @@
steps:
# Checkout repository
- checkout: self
clean: true
fetchDepth: 1
# Set python version.
- task: UsePythonVersion@0
inputs:
versionSpec: '$(python.version)'
# Install Build Dependencies
- script: |
set -e
sudo xcode-select --switch /Applications/Xcode_10.1.app/Contents/Developer
unset BOOST_ROOT
pip install cython numpy pandas
brew install openblas armadillo boost
git clone --depth 1 https://github.com/mlpack/jenkins-conf.git conf
displayName: 'Install Build Dependencies'
# Configure mlpack (CMake)
- script: |
unset BOOST_ROOT
mkdir build && cd build
export PYPATH=$(which python)
cmake $(CMakeArgs) -DPYTHON_EXECUTABLE=$PYPATH ..
displayName: 'CMake'
# Build mlpack
- script: cd build && make -j2
displayName: 'Build'
# Run tests
- script: cd build && bin/mlpack_test --result_code=no --report_level=detailed --log_level=test_suite --log_format=HRF --log_sink=res.txt
displayName: 'Run tests'
# Process test results
- bash: |
python conf/ci/convert.py > mlpack_test.xml
displayName: 'Process test results'
# Publish test results to Azure Pipelines
- task: PublishTestResults@2
inputs:
testResultsFormat: JUnit
testResultsFiles: 'mlpack_test.xml'
failTaskOnFailedTests: true
displayName: 'Publish tests'
# Publish build artifacts to Azure Pipelines
- task: PublishBuildArtifacts@1
inputs:
pathtoPublish: 'mlpack_test.xml'
artifactName: 'mlpack_test_macos.xml'
displayName: 'Publish artifacts test results'
+151
View File
@@ -0,0 +1,151 @@
steps:
- checkout: self
clean: true
fetchDepth: 1
- task: NuGetToolInstaller@0
inputs:
versionSpec: '5.3.0'
# Fetch build dependencies
- powershell: |
nuget install OpenBLAS -o $(Agent.ToolsDirectory)
nuget install boost -o $(Agent.ToolsDirectory) -Version 1.60.0
nuget install boost_unit_test_framework-vc140 -o $(Agent.ToolsDirectory) -Version 1.60.0
nuget install boost_program_options-vc140 -o $(Agent.ToolsDirectory) -Version 1.60.0
nuget install boost_random-vc140 -o $(Agent.ToolsDirectory) -Version 1.60.0
nuget install boost_serialization-vc140 -o $(Agent.ToolsDirectory) -Version 1.60.0
nuget install boost_math_c99-vc140 -o $(Agent.ToolsDirectory) -Version 1.60.0
nuget install OpenBLAS -o $(Agent.ToolsDirectory)
mkdir -p $(Agent.ToolsDirectory)/boost_libs
cp $(Agent.ToolsDirectory)/boost_program_options-vc140.1.60.0.0/lib/native/address-model-64/lib/*.* $(Agent.ToolsDirectory)/boost_libs
cp $(Agent.ToolsDirectory)/boost_math_c99-vc140.1.60.0.0/lib/native/address-model-64/lib/*.* $(Agent.ToolsDirectory)/boost_libs
cp $(Agent.ToolsDirectory)/boost_random-vc140.1.60.0.0/lib/native/address-model-64/lib/*.* $(Agent.ToolsDirectory)/boost_libs
cp $(Agent.ToolsDirectory)/boost_serialization-vc140.1.60.0.0/lib/native/address-model-64/lib/*.* $(Agent.ToolsDirectory)/boost_libs
cp $(Agent.ToolsDirectory)/boost_unit_test_framework-vc140.1.60.0.0/lib/native/address-model-64/lib/*.* $(Agent.ToolsDirectory)/boost_libs
displayName: 'Fetch build dependencies'
# Configure armadillo
- bash: |
git clone --depth 1 https://github.com/mlpack/jenkins-conf.git conf
curl http://masterblaster.mlpack.org:5005/armadillo-8.400.0.tar.gz | tar xvz
cd armadillo-8.400.0/ && cmake $(CMakeGenerator) \
-DBLAS_LIBRARY:FILEPATH=$(Agent.ToolsDirectory)/OpenBLAS.0.2.14.1/lib/native/lib/x64/libopenblas.dll.a \
-DLAPACK_LIBRARY:FILEPATH=$(Agent.ToolsDirectory)/OpenBLAS.0.2.14.1/lib/native/lib/x64/libopenblas.dll.a \
-DCMAKE_PREFIX:FILEPATH=../../armadillo \
-DBUILD_SHARED_LIBS=OFF \
-DCMAKE_BUILD_TYPE=Release .
displayName: 'Configure armadillo'
# Build armadillo
- task: MSBuild@1
inputs:
solution: 'armadillo-8.400.0/*.sln'
msbuildLocationMethod: 'location'
msbuildVersion: $(MSBuildVersion)
configuration: 'Release'
msbuildArchitecture: 'x64'
msbuildArguments: /m /p:BuildInParallel=true
clean: false
maximumCpuCount: false
displayName: 'Build armadillo'
# Configure mlpack
- powershell: |
mkdir build
cd build
cmake $(CMakeGenerator) `
$(CMakeArgs) `
-DBLAS_LIBRARY:FILEPATH=$(Agent.ToolsDirectory)\OpenBLAS.0.2.14.1\lib\native\lib\x64\libopenblas.dll.a `
-DLAPACK_LIBRARY:FILEPATH=$(Agent.ToolsDirectory)\OpenBLAS.0.2.14.1\lib\native\lib\x64\libopenblas.dll.a `
-DARMADILLO_INCLUDE_DIR="..\armadillo-8.400.0\include" `
-DARMADILLO_LIBRARY="..\armadillo-8.400.0\Release\armadillo.lib" `
-DBOOST_INCLUDEDIR=$(Agent.ToolsDirectory)\boost.1.60.0.0\lib\native\include `
-DBOOST_LIBRARYDIR=$(Agent.ToolsDirectory)\boost_libs `
-DCMAKE_BUILD_TYPE=Release ..
displayName: 'Configure mlpack'
# Build mlpack
- task: MSBuild@1
inputs:
solution: 'build/*.sln'
msbuildLocationMethod: 'location'
msbuildVersion: $(MSBuildVersion)
configuration: 'Release'
msbuildArchitecture: 'x64'
msbuildArguments: /m /p:BuildInParallel=true
maximumCpuCount: false
clean: false
displayName: 'Build mlpack'
# Configure mlpack
- powershell: |
cp $(Agent.ToolsDirectory)\boost_libs\*.* build\Release\
cp $(Agent.ToolsDirectory)\OpenBLAS.0.2.14.1\lib\native\lib\x64\*.* build\Release\
cp $(Agent.ToolsDirectory)\OpenBLAS.0.2.14.1\lib\native\bin\x64\*.* build\Release\
displayName: 'Configure mlpack'
# Run tests
- bash: |
cd build
ls
Release/mlpack_test.exe --result_code=no --report_level=detailed --log_level=test_suite --log_format=HRF --log_sink=res.txt
displayName: 'Run tests'
# Process test results
- bash: |
python conf/ci/convert.py > mlpack_test.xml
displayName: 'Process test results'
# Copy artifacts
- powershell: |
mkdir exe-archive
cp build\Release\*.exe exe-archive\
displayName: 'Copy artifacts'
# Build artifacts archive
- task: ArchiveFiles@2
inputs:
rootFolderOrFile: 'exe-archive\'
includeRootFolder: false
archiveType: 'zip'
archiveFile: $(ArchiveNoLibs)
replaceExistingArchive: true
displayName: 'Build artifacts'
- task: ArchiveFiles@2
inputs:
rootFolderOrFile: 'build\Release\'
includeRootFolder: false
archiveType: 'zip'
archiveFile: $(ArchiveLibs)
replaceExistingArchive: true
displayName: 'Build artifacts'
# Publish artifacts to Azure Pipelines
- task: PublishBuildArtifacts@1
inputs:
pathtoPublish: $(ArchiveNoLibs)
artifactName: $(ArchiveNoLibs)
displayName: 'Publish artifacts no-libs'
- task: PublishBuildArtifacts@1
inputs:
pathtoPublish: $(ArchiveLibs)
artifactName: $(ArchiveLibs)
displayName: 'Publish artifacts complete'
- task: PublishBuildArtifacts@1
inputs:
pathtoPublish: 'mlpack_test.xml'
artifactName: $(ArchiveTests)
displayName: 'Publish artifacts test results'
# Publish test results to Azure Pipelines
- task: PublishTestResults@2
inputs:
testResultsFormat: JUnit
testResultsFiles: 'mlpack_test.xml'
failTaskOnFailedTests: true
displayName: 'Publish tests'
+2
View File
@@ -0,0 +1,2 @@
github: [numfocus]
custom: https://numfocus.org/donate-to-mlpack
+1
View File
@@ -6,3 +6,4 @@ src/mlpack/core/util/arma_config.hpp
.idea
cmake-build-*
*.pyc
Testing/
+7 -8
View File
@@ -1,4 +1,3 @@
sudo: required
language: cpp
matrix:
@@ -8,9 +7,9 @@ matrix:
env: CMAKE_OPTIONS="-DDEBUG=OFF -DPROFILE=OFF -DPYTHON_EXECUTABLE=/usr/bin/python"
before_install:
- sudo apt-get update
- sudo apt-get install -y --allow-unauthenticated libopenblas-dev liblapack-dev g++ libboost-all-dev python-pip cython python-numpy python-pandas
- sudo apt-get install -y --allow-unauthenticated libopenblas-dev liblapack-dev g++ libboost-all-dev python-pip cython python-numpy python-pandas xz-utils
- sudo pip install --upgrade --ignore-installed setuptools cython
- curl https://ftp.fau.de/macports/distfiles/armadillo/armadillo-6.500.5.tar.gz | tar xvz && cd armadillo*
- curl https://ftp.fau.de/macports/distfiles/armadillo/armadillo-8.400.0.tar.xz | tar -xvJ && cd armadillo*
- cmake . && make && sudo make install && cd ..
- sudo cp .travis/config.hpp /usr/include/armadillo_bits/config.hpp
@@ -19,9 +18,9 @@ matrix:
env: CMAKE_OPTIONS="-DDEBUG=OFF -DPROFILE=OFF -DPYTHON_EXECUTABLE=/usr/bin/python3"
before_install:
- sudo apt-get update
- sudo apt-get install -y --allow-unauthenticated libopenblas-dev liblapack-dev g++ libboost-all-dev python3-pip cython3 python3-numpy
- sudo apt-get install -y --allow-unauthenticated libopenblas-dev liblapack-dev g++ libboost-all-dev python3-pip cython3 python3-numpy xz-utils
- sudo pip3 install --upgrade --ignore-installed setuptools cython pandas
- curl https://ftp.fau.de/macports/distfiles/armadillo/armadillo-6.500.5.tar.gz | tar xvz && cd armadillo*
- curl https://ftp.fau.de/macports/distfiles/armadillo/armadillo-8.400.0.tar.xz | tar -xvJ && cd armadillo*
- cmake . && make && sudo make install && cd ..
- sudo cp .travis/config.hpp /usr/include/armadillo_bits/config.hpp
@@ -30,8 +29,8 @@ matrix:
env: CMAKE_OPTIONS="-DDEBUG=ON -DPROFILE=OFF -DBUILD_PYTHON_BINDINGS=OFF"
before_install:
- sudo apt-get update
- sudo apt-get install -y --allow-unauthenticated libopenblas-dev liblapack-dev g++ libboost-all-dev
- curl https://ftp.fau.de/macports/distfiles/armadillo/armadillo-6.500.5.tar.gz | tar xvz && cd armadillo*
- sudo apt-get install -y --allow-unauthenticated libopenblas-dev liblapack-dev g++ libboost-all-dev xz-utils
- curl https://ftp.fau.de/macports/distfiles/armadillo/armadillo-8.400.0.tar.xz | tar -xvJ && cd armadillo*
- cmake . && make && sudo make install && cd ..
- sudo cp .travis/config.hpp /usr/include/armadillo_bits/config.hpp
@@ -54,7 +53,7 @@ matrix:
- brew install openblas armadillo || brew install openblas armadillo
install:
- mkdir build && cd build && cmake $CMAKE_OPTIONS .. && travis_wait 60 make -j2
- mkdir build && cd build && cmake $CMAKE_OPTIONS .. && travis_wait 75 make -j2
script:
- CTEST_OUTPUT_ON_FAILURE=1 travis_wait 30 ctest -j2
+177 -49
View File
@@ -1,35 +1,65 @@
// Copyright (C) 2008-2012 NICTA (www.nicta.com.au)
// Copyright (C) 2008-2012 Conrad Sanderson
//
// This file is part of the Armadillo C++ library.
// It is provided without any warranty of fitness
// for any purpose. You can redistribute this file
// and/or modify it under the terms of the GNU
// Lesser General Public License (LGPL) as published
// by the Free Software Foundation, either version 3
// of the License or (at your option) any later version.
// (see http://www.opensource.org/licenses for more info)
// Copyright 2008-2016 Conrad Sanderson (http://conradsanderson.id.au)
// Copyright 2008-2016 National ICT Australia (NICTA)
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ------------------------------------------------------------------------
#if !defined(ARMA_USE_LAPACK)
#define ARMA_USE_LAPACK
//// Uncomment the above line if you have LAPACK or a high-speed replacement for LAPACK,
//// such as Intel's MKL, AMD's ACML, or the Accelerate framework.
//// Comment out the above line if you don't have LAPACK or a high-speed replacement for LAPACK,
//// such as Intel MKL, AMD ACML, or the Accelerate framework.
//// LAPACK is required for matrix decompositions (eg. SVD) and matrix inverse.
#endif
#if !defined(ARMA_USE_BLAS)
#define ARMA_USE_BLAS
//// Uncomment the above line if you have BLAS or a high-speed replacement for BLAS,
//// such as GotoBLAS, Intel's MKL, AMD's ACML, or the Accelerate framework.
//// Comment out the above line if you don't have BLAS or a high-speed replacement for BLAS,
//// such as OpenBLAS, GotoBLAS, Intel MKL, AMD ACML, or the Accelerate framework.
//// BLAS is used for matrix multiplication.
//// Without BLAS, matrix multiplication will still work, but might be slower.
#endif
#if !defined(ARMA_USE_NEWARP)
#define ARMA_USE_NEWARP
//// Uncomment the above line to enable the built-in partial emulation of ARPACK.
//// This is used for eigen decompositions of real (non-complex) sparse matrices, eg. eigs_sym(), svds()
#endif
#if !defined(ARMA_USE_ARPACK)
// #define ARMA_USE_ARPACK
//// Uncomment the above line if you have ARPACK or a high-speed replacement for ARPACK.
//// ARPACK is required for eigen decompositions of complex sparse matrices
#endif
#if !defined(ARMA_USE_SUPERLU)
// #define ARMA_USE_SUPERLU
//// Uncomment the above line if you have SuperLU.
//// SuperLU is used for solving sparse linear systems via spsolve()
//// Caveat: only SuperLU version 5.2 can be used!
#endif
#if !defined(ARMA_SUPERLU_INCLUDE_DIR)
// #define ARMA_SUPERLU_INCLUDE_DIR /usr/include/
//// If you're using SuperLU and want to explicitly include the SuperLU headers,
//// uncomment the above define and specify the appropriate include directory.
//// Make sure the directory has a trailing /
#endif
#define ARMA_USE_WRAPPER
//// Comment out the above line if you prefer to directly link with LAPACK and/or BLAS (eg. -llapack -lblas)
//// instead of linking indirectly with LAPACK and/or BLAS via Armadillo's run-time wrapper library.
//// Comment out the above line if you're getting linking errors when compiling your programs,
//// or if you prefer to directly link with LAPACK, BLAS + etc instead of the Armadillo runtime library.
//// You will then need to link your programs directly with -llapack -lblas instead of -larmadillo
// #define ARMA_BLAS_CAPITALS
//// Uncomment the above line if your BLAS and LAPACK libraries have capitalised function names (eg. ACML on 64-bit Windows)
@@ -45,31 +75,49 @@
//// Uncomment the above line if your BLAS and LAPACK libraries use "long long" instead of "int"
// #define ARMA_USE_TBB_ALLOC
//// Uncomment the above line if you want to use Intel TBB scalable_malloc() and scalable_free() instead of standard new[] and delete[]
//// Uncomment the above line if you want to use Intel TBB scalable_malloc() and scalable_free() instead of standard malloc() and free()
// #define ARMA_USE_MKL_ALLOC
//// Uncomment the above line if you want to use Intel MKL mkl_malloc() and mkl_free() instead of standard new[] and delete[]
//// Uncomment the above line if you want to use Intel MKL mkl_malloc() and mkl_free() instead of standard malloc() and free()
/* #undef ARMA_USE_ATLAS */
#define ARMA_ATLAS_INCLUDE_DIR /
// #define ARMA_USE_ATLAS
// #define ARMA_ATLAS_INCLUDE_DIR /usr/include/
//// If you're using ATLAS and the compiler can't find cblas.h and/or clapack.h
//// uncomment the above define and specify the appropriate include directory.
//// Make sure the directory has a trailing /
#define ARMA_64BIT_WORD
//// Uncomment the above line if you require matrices/vectors capable of holding more than 4 billion elements.
//// Your machine and compiler must have support for 64 bit integers (eg. via "long" or "long long")
#if !defined(ARMA_USE_CXX11)
#define ARMA_USE_CXX11
//// Uncomment the above line if you have a C++ compiler that supports the C++11 standard
//// This will enable additional features, such as use of initialiser lists
//// Uncomment the above line to forcefully enable use of C++11 features (eg. initialiser lists).
//// Note that ARMA_USE_CXX11 is automatically enabled when a C++11 compiler is detected.
#endif
#if !defined(ARMA_USE_OPENMP)
// #define ARMA_USE_OPENMP
//// Uncomment the above line to forcefully enable use of OpenMP for parallelisation.
//// Note that ARMA_USE_OPENMP is automatically enabled when a compiler supporting OpenMP 3.1 is detected.
#endif
#if !defined(ARMA_64BIT_WORD)
#define ARMA_64BIT_WORD
//// Uncomment the above line if you require matrices/vectors capable of holding more than 4 billion elements.
//// Your machine and compiler must have support for 64 bit integers (eg. via "long" or "long long").
//// Note that ARMA_64BIT_WORD is automatically enabled when a C++11 compiler is detected.
#endif
#if !defined(ARMA_USE_HDF5)
/* #undef ARMA_USE_HDF5 */
//// Uncomment the above line if you want the ability to save and load matrices stored in the HDF5 format;
//// the hdf5.h header file must be available on your system and you will need to link with the hdf5 library (eg. -lhdf5)
// #define ARMA_USE_HDF5
//// Uncomment the above line to allow the ability to save and load matrices stored in HDF5 format;
//// the hdf5.h header file must be available on your system,
//// and you will need to link with the hdf5 library (eg. -lhdf5)
#endif
// #define ARMA_USE_HDF5_ALT
#if defined(ARMA_USE_HDF5_ALT) && defined(ARMA_USE_WRAPPER)
#undef ARMA_USE_HDF5
#define ARMA_USE_HDF5
// #define ARMA_HDF5_INCLUDE_DIR /usr/include/
#endif
#if !defined(ARMA_MAT_PREALLOC)
@@ -80,6 +128,18 @@
//// If you mainly use lots of very small vectors (eg. <= 4 elements),
//// change the number to the size of your vectors.
#if !defined(ARMA_OPENMP_THRESHOLD)
#define ARMA_OPENMP_THRESHOLD 320
#endif
//// The minimum number of elements in a matrix to allow OpenMP based parallelisation;
//// it must be an integer that is at least 1.
#if !defined(ARMA_OPENMP_THREADS)
#define ARMA_OPENMP_THREADS 10
#endif
//// The maximum number of threads to use for OpenMP based parallelisation;
//// it must be an integer that is at least 1.
#if !defined(ARMA_SPMAT_CHUNKSIZE)
#define ARMA_SPMAT_CHUNKSIZE 256
#endif
@@ -99,27 +159,39 @@
//// This is mainly useful for debugging of the library.
// #define ARMA_USE_BOOST
// #define ARMA_USE_BOOST_DATE
#if !defined(ARMA_DEFAULT_OSTREAM)
#define ARMA_DEFAULT_OSTREAM std::cout
#if defined(ARMA_DEFAULT_OSTREAM)
#pragma message ("WARNING: support for ARMA_DEFAULT_OSTREAM is deprecated and will be removed;")
#pragma message ("WARNING: use ARMA_COUT_STREAM and ARMA_CERR_STREAM instead")
#endif
#define ARMA_PRINT_LOGIC_ERRORS
#define ARMA_PRINT_RUNTIME_ERRORS
//#define ARMA_PRINT_HDF5_ERRORS
#define ARMA_HAVE_STD_ISFINITE
#define ARMA_HAVE_STD_ISINF
#define ARMA_HAVE_STD_ISNAN
#define ARMA_HAVE_STD_SNPRINTF
#if !defined(ARMA_COUT_STREAM)
#if defined(ARMA_DEFAULT_OSTREAM)
// for compatibility with earlier versions of Armadillo
#define ARMA_COUT_STREAM ARMA_DEFAULT_OSTREAM
#else
#define ARMA_COUT_STREAM std::cout
#endif
#endif
#define ARMA_HAVE_LOG1P
#define ARMA_HAVE_GETTIMEOFDAY
#if !defined(ARMA_CERR_STREAM)
#if defined(ARMA_DEFAULT_OSTREAM)
// for compatibility with earlier versions of Armadillo
#define ARMA_CERR_STREAM ARMA_DEFAULT_OSTREAM
#else
#define ARMA_CERR_STREAM std::cerr
#endif
#endif
#if !defined(ARMA_PRINT_ERRORS)
#define ARMA_PRINT_ERRORS
//// Comment out the above line if you don't want errors and warnings printed (eg. failed decompositions)
#endif
#if !defined(ARMA_PRINT_HDF5_ERRORS)
// #define ARMA_PRINT_HDF5_ERRORS
#endif
#if defined(ARMA_DONT_USE_LAPACK)
#undef ARMA_USE_LAPACK
@@ -129,15 +201,71 @@
#undef ARMA_USE_BLAS
#endif
#if defined(ARMA_DONT_USE_NEWARP) || !defined(ARMA_USE_LAPACK)
#undef ARMA_USE_NEWARP
#endif
#if defined(ARMA_DONT_USE_ARPACK)
#undef ARMA_USE_ARPACK
#endif
#if defined(ARMA_DONT_USE_SUPERLU)
#undef ARMA_USE_SUPERLU
#undef ARMA_SUPERLU_INCLUDE_DIR
#endif
#if defined(ARMA_DONT_USE_ATLAS)
#undef ARMA_USE_ATLAS
#undef ARMA_ATLAS_INCLUDE_DIR
#endif
#if defined(ARMA_DONT_PRINT_LOGIC_ERRORS)
#undef ARMA_PRINT_LOGIC_ERRORS
#if defined(ARMA_DONT_USE_WRAPPER)
#undef ARMA_USE_WRAPPER
#undef ARMA_USE_HDF5_ALT
#endif
#if defined(ARMA_DONT_PRINT_RUNTIME_ERRORS)
#undef ARMA_PRINT_RUNTIME_ERRORS
#if defined(ARMA_DONT_USE_CXX11)
#undef ARMA_USE_CXX11
#undef ARMA_USE_EXTERN_CXX11_RNG
#endif
#if defined(ARMA_DONT_USE_OPENMP)
#undef ARMA_USE_OPENMP
#endif
#if defined(ARMA_USE_WRAPPER)
#if defined(ARMA_USE_CXX11)
#if !defined(ARMA_USE_EXTERN_CXX11_RNG)
// #define ARMA_USE_EXTERN_CXX11_RNG
#endif
#endif
#endif
#if defined(ARMA_DONT_USE_EXTERN_CXX11_RNG)
#undef ARMA_USE_EXTERN_CXX11_RNG
#endif
#if defined(ARMA_32BIT_WORD)
#undef ARMA_64BIT_WORD
#endif
#if defined(ARMA_DONT_USE_HDF5)
#undef ARMA_USE_HDF5
#undef ARMA_USE_HDF5_ALT
#endif
#if defined(ARMA_DONT_PRINT_ERRORS)
#undef ARMA_PRINT_ERRORS
#endif
#if defined(ARMA_DONT_PRINT_HDF5_ERRORS)
#undef ARMA_PRINT_HDF5_ERRORS
#endif
// if Armadillo was installed on this system via CMake and ARMA_USE_WRAPPER is not defined,
// ARMA_AUX_LIBS lists the libraries required by Armadillo on this system, and
// ARMA_AUX_INCDIRS lists the include directories required by Armadillo on this system.
// Do not use these unless you know what you are doing.
#define ARMA_AUX_LIBS
#define ARMA_AUX_INCDIRS
+35
View File
@@ -0,0 +1,35 @@
# Validate md5 hash given md5file url and the file directory.
# This module does the following on hash failure:
# Set HASH_CHECK_FAIL to 1.
# Remove the downloaded files.
macro (check_hash MD5_URL DIR HASH_CHECK_FAIL)
set(HASH_CHECK_FAIL 0)
file(DOWNLOAD ${MD5_URL}
"${DIR}/hash.md5"
STATUS MD5_DOWNLOAD_STATUS_LIST)
list(GET MD5_DOWNLOAD_STATUS_LIST 0 MD5_DOWNLOAD_STATUS)
if (MD5_DOWNLOAD_STATUS EQUAL 0)
file(STRINGS "${DIR}/hash.md5" HASH_DATA NEWLINE_CONSUME)
string(REGEX REPLACE "\n" ";" HASH_LIST "${HASH_DATA}")
foreach(item ${HASH_LIST})
string(SUBSTRING ${item} 0 32 EXPECTED_HASH)
string(SUBSTRING ${item} 34 -1 FILE_NAME)
file(MD5 "${DIR}/${FILE_NAME}" LOCAL_HASH)
if (NOT LOCAL_HASH STREQUAL EXPECTED_HASH)
set(HASH_CHECK_FAIL 1)
file(REMOVE_RECURSE ${DIR})
message(WARNING
"md5sum verification error for ${item}! Got ${LOCAL_HASH}, expected ${EXPECTED_HASH}.")
break()
endif()
endforeach()
else ()
set(HASH_CHECK_FAIL 1)
file(REMOVE_RECURSE ${DIR})
list(GET MD5_DOWNLOAD_STATUS_LIST 1 MD5_DOWNLOAD_ERROR)
message(WARNING
"Could not download the md5 for hash verification! Error code ${MD5_DOWNLOAD_STATUS}: ${MD5_DOWNLOAD_ERROR}!")
endif ()
endmacro (check_hash)
+1 -1
View File
@@ -52,7 +52,7 @@ endif ()
# Checks 'REQUIRED', 'QUIET' and versions.
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(ensmallen
find_package_handle_standard_args(Ensmallen
REQUIRED_VARS ENSMALLEN_INCLUDE_DIR
VERSION_VAR ENSMALLEN_VERSION_STRING)
+23
View File
@@ -0,0 +1,23 @@
# - Find STB_IMAGE
# Find the STB_IMAGE C++ library
#
# This module sets the following variables:
# STB_IMAGE_FOUND - set to true if the library is found
# STB_IMAGE_INCLUDE_DIR - list of required include directories
file(GLOB STB_IMAGE_SEARCH_PATHS
${CMAKE_BINARY_DIR}/deps/stb)
find_path(STB_IMAGE_INCLUDE_DIR
NAMES stb_image.h stb_image_write.h
PATHS ${STB_IMAGE_SEARCH_PATHS})
if(STB_IMAGE_INCLUDE_DIR)
set(STB_IMAGE_FOUND YES)
endif ()
# Checks 'REQUIRED'.
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(STB_IMAGE
REQUIRED_VARS STB_IMAGE_INCLUDE_DIR)
mark_as_advanced(STB_IMAGE_INCLUDE_DIR)
+6 -1
View File
@@ -5,4 +5,9 @@
#
# PROGRAM: the program to run to.
# OUTPUT_FILE: the file to store the output in.
execute_process(COMMAND ${PROGRAM} OUTPUT_FILE ${OUTPUT_FILE})
execute_process(COMMAND ${PROGRAM} OUTPUT_FILE ${OUTPUT_FILE}
ERROR_VARIABLE err)
if (err)
message(FATAL_ERROR "Fatal error running ${PROGRAM}: ${err}!")
endif ()
+113 -18
View File
@@ -2,6 +2,7 @@ cmake_minimum_required(VERSION 3.3.2)
project(mlpack C CXX)
include(CMake/cotire.cmake)
include(CMake/CheckHash.cmake)
# First, define all the compilation options.
# We default to debugging mode for developers.
@@ -13,16 +14,16 @@ option(TEST_VERBOSE "Run test cases with verbose output." OFF)
option(BUILD_TESTS "Build tests." ON)
option(BUILD_CLI_EXECUTABLES "Build command-line executables." ON)
option(DOWNLOAD_ENSMALLEN "If ensmallen is not found, download it." ON)
option(DOWNLOAD_STB_IMAGE "Download stb_image for image loading." ON)
option(BUILD_PYTHON_BINDINGS "Build Python bindings." ON)
# Currently Python bindings aren't known to build successfully on Windows, so
# set BUILD_PYTHON_BINDINGS to OFF when the platform is Windows.
if (WIN32)
option(BUILD_PYTHON_BINDINGS "Build Python bindings." OFF)
option(BUILD_SHARED_LIBS
"Compile shared libraries (if OFF, static libraries are compiled)." OFF)
message(WARNING "By default Python bindings are not compiled for Windows because they are not known to work. Set BUILD_PYTHON_BINDINGS to ON if you want them built.")
set(DLL_COPY_DIRS "" CACHE STRING "List of directories (separated by ';') containing DLLs to copy for runtime.")
set(DLL_COPY_LIBS "" CACHE STRING "List of DLLs (separated by ';') that should be copied for runtime.")
else ()
option(BUILD_PYTHON_BINDINGS "Build Python bindings." ON)
option(BUILD_SHARED_LIBS
"Compile shared libraries (if OFF, static libraries are compiled)." ON)
endif()
@@ -84,6 +85,10 @@ if(CMAKE_COMPILER_IS_GNUCC OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -ftemplate-depth=1000")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra")
# To remove unused functions warnings.
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-function")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-unused-function")
endif()
# These support libraries are used if we need to link against something
@@ -148,7 +153,7 @@ endif()
# Setup build for test coverage
if(BUILD_WITH_COVERAGE)
# Currently coverage only works with GNU g++
# Currently coverage only works with GNU g++.
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
# Find gcov and lcov
find_program(GCOV gcov)
@@ -160,6 +165,7 @@ if(BUILD_WITH_COVERAGE)
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
@@ -242,7 +248,7 @@ endif()
# ENSMALLEN_INCLUDE_DIR - include directory for ensmallen
# MATHJAX_ROOT - root of MathJax installation
find_package(Armadillo 6.500.0 REQUIRED)
find_package(Armadillo 8.400.0 REQUIRED)
# If Armadillo was compiled without ARMA_64BIT_WORD and we are on a 64-bit
# system (where size_t will be 64 bits), suggest to the user that they should
@@ -312,22 +318,93 @@ if (WIN32)
# Piggyback LAPACK and BLAS linking into Armadillo link.
set(ARMADILLO_LIBRARIES
${ARMADILLO_LIBRARIES} ${BLAS_LIBRARY} ${LAPACK_LIBRARY})
${ARMADILLO_LIBRARIES} ${BLAS_LIBRARY} ${LAPACK_LIBRARY})
# Ensure that the libraries are added to the MSVC IDE runtime path.
get_filename_component(BLAS_DIR ${BLAS_LIBRARY} DIRECTORY)
get_filename_component(LAPACK_DIR ${LAPACK_LIBRARY} DIRECTORY)
# Sometimes, especially with an OpenBLAS install via nuget, the DLLs are
# actually in ../../bin/x64/. Automatically add these.
if (EXISTS "${BLAS_DIR}/../../bin/x64/")
get_filename_component(BLAS_DLL_DIR "${BLAS_DIR}/../../bin/x64" ABSOLUTE)
set(DLL_COPY_DIRS ${DLL_COPY_DIRS} "${BLAS_DLL_DIR}")
endif ()
if (EXISTS "${LAPACK_DIR}/../../bin/x64/")
get_filename_component(LAPACK_DLL_DIR "${LAPACK_DIR}/../../bin/x64" ABSOLUTE)
set(DLL_COPY_DIRS ${DLL_COPY_DIRS} "${BLAS_DLL_DIR}")
endif ()
endif ()
# Include directories for the previous dependencies.
set(MLPACK_INCLUDE_DIRS ${MLPACK_INCLUDE_DIRS} ${ARMADILLO_INCLUDE_DIRS})
set(MLPACK_LIBRARIES ${MLPACK_LIBRARIES} ${ARMADILLO_LIBRARIES})
# Find stb_image.h and stb_image_write.h.
find_package(StbImage)
# Download stb_image for image loading.
if (NOT STB_IMAGE_FOUND)
if (DOWNLOAD_STB_IMAGE)
set(STB_DIR "stb")
install(DIRECTORY DESTINATION "${CMAKE_BINARY_DIR}/deps/${STB_DIR}")
file(DOWNLOAD http://mlpack.org/files/stb-2.22/stb_image.h
"${CMAKE_BINARY_DIR}/deps/${STB_DIR}/stb_image.h"
STATUS STB_IMAGE_DOWNLOAD_STATUS_LIST LOG STB_IMAGE_DOWNLOAD_LOG
SHOW_PROGRESS)
list(GET STB_IMAGE_DOWNLOAD_STATUS_LIST 0 STB_IMAGE_DOWNLOAD_STATUS)
file(DOWNLOAD http://mlpack.org/files/stb-1.13/stb_image_write.h
"${CMAKE_BINARY_DIR}/deps/${STB_DIR}/stb_image_write.h"
STATUS STB_IMAGE_WRITE_DOWNLOAD_STATUS_LIST
LOG STB_IMAGE_WRITE_DOWNLOAD_LOG
SHOW_PROGRESS)
list(GET STB_IMAGE_WRITE_DOWNLOAD_STATUS_LIST 0
STB_IMAGE_WRITE_DOWNLOAD_STATUS)
if (STB_IMAGE_DOWNLOAD_STATUS EQUAL 0 AND
STB_IMAGE_WRITE_DOWNLOAD_STATUS EQUAL 0)
check_hash (http://mlpack.org/files/stb/hash.md5 "${CMAKE_BINARY_DIR}/deps/${STB_DIR}"
HASH_CHECK_FAIL)
if (HASH_CHECK_FAIL EQUAL 0)
set(MLPACK_INCLUDE_DIRS ${MLPACK_INCLUDE_DIRS}
"${CMAKE_BINARY_DIR}/deps/${STB_DIR}/")
message(STATUS
"Successfully downloaded stb into ${CMAKE_BINARY_DIR}/deps/${STB_DIR}/")
# Now we have to also ensure these header files get installed.
install(FILES "${CMAKE_BINARY_DIR}/deps/${STB_DIR}/stb_image.h" DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}")
install(FILES "${CMAKE_BINARY_DIR}/deps/${STB_DIR}/stb_image_write.h" DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}")
add_definitions(-DHAS_STB)
else ()
message(WARNING
"stb/stb_image.h is not installed. Image utilities will not be available!")
endif ()
else ()
file(REMOVE_RECURSE "${CMAKE_BINARY_DIR}/deps/${STB_DIR}/")
list(GET STB_IMAGE_DOWNLOAD_STATUS_LIST 1 STB_DOWNLOAD_ERROR)
message(WARNING
"Could not download stb! Error code ${STB_DOWNLOAD_STATUS}: ${STB_DOWNLOAD_ERROR}! Error log: ${STB_DOWNLOAD_LOG}")
message(WARNING
"stb/stb_image.h is not installed. Image utilities will not be available!")
endif ()
else ()
message(WARNING
"stb/stb_image.h is not installed. Image utilities will not be available!")
endif ()
else ()
# Already has STB installed.
add_definitions(-DHAS_STB)
set(MLPACK_INCLUDE_DIRS ${MLPACK_INCLUDE_DIRS} ${STB_IMAGE_INCLUDE_DIR})
endif ()
# Find ensmallen.
# Once ensmallen is readily available in package repos, the automatic downloader
# here can be removed.
find_package(Ensmallen 1.10.0)
find_package(Ensmallen 2.10.0)
if (NOT ENSMALLEN_FOUND)
if (DOWNLOAD_ENSMALLEN)
file(DOWNLOAD http://www.ensmallen.org/files/ensmallen-latest.tar.gz
"${CMAKE_BINARY_DIR}/deps/ensmallen-latest.tar.gz"
STATUS ENS_DOWNLOAD_STATUS_LIST LOG ENS_DOWBLOAD_LOG
STATUS ENS_DOWNLOAD_STATUS_LIST LOG ENS_DOWNLOAD_LOG
SHOW_PROGRESS)
list(GET ENS_DOWNLOAD_STATUS_LIST 0 ENS_DOWNLOAD_STATUS)
if (ENS_DOWNLOAD_STATUS EQUAL 0)
@@ -338,6 +415,7 @@ if (NOT ENSMALLEN_FOUND)
# Get the name of the directory.
file (GLOB ENS_DIRECTORIES RELATIVE "${CMAKE_BINARY_DIR}/deps/"
"${CMAKE_BINARY_DIR}/deps/ensmallen-[0-9]*.[0-9]*.[0-9]*")
list(FILTER ENS_DIRECTORIES EXCLUDE REGEX "ensmallen-.*\.tar\.gz")
list(LENGTH ENS_DIRECTORIES ENS_DIRECTORIES_LEN)
if (ENS_DIRECTORIES_LEN EQUAL 1)
list(GET ENS_DIRECTORIES 0 ENSMALLEN_INCLUDE_DIR)
@@ -347,8 +425,8 @@ if (NOT ENSMALLEN_FOUND)
"Successfully downloaded ensmallen into ${CMAKE_BINARY_DIR}/deps/${ENSMALLEN_INCLUDE_DIR}/")
# Now we have to also ensure these header files get installed.
install(DIRECTORY ${CMAKE_BINARY_DIR}/deps/${ENSMALLEN_INCLUDE_DIR}/include/ensmallen_bits/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/ensmallen_bits)
install(FILES ${CMAKE_BINARY_DIR}/deps/${ENSMALLEN_INCLUDE_DIR}/include/ensmallen.hpp DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
install(DIRECTORY "${CMAKE_BINARY_DIR}/deps/${ENSMALLEN_INCLUDE_DIR}/include/ensmallen_bits/" DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/ensmallen_bits")
install(FILES "${CMAKE_BINARY_DIR}/deps/${ENSMALLEN_INCLUDE_DIR}/include/ensmallen.hpp" DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}")
else ()
message(FATAL_ERROR "Problem unpacking ensmallen! Expected only one directory ensmallen-x.y.z/; found ${ENS_DIRECTORIES}. Try removing the directory ${CMAKE_BINARY_DIR}/deps and reconfiguring.")
endif ()
@@ -411,6 +489,8 @@ link_directories(${Boost_LIBRARY_DIRS})
# handle it.
if (MSVC)
link_directories(${Boost_LIBRARY_DIRS})
set(CMAKE_MSVCIDE_RUN_PATH ${CMAKE_MSVCIDE_RUN_PATH} ${Boost_LIBRARY_DIRS})
message("boost lib dirs ${Boost_LIBRARY_DIRS}")
set(Boost_LIBRARIES "")
endif ()
@@ -463,6 +543,21 @@ if (WIN32)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
# Copy all necessary DLLs for runtime to the build directory.
# This is a little hackish, but I can't figure out clear ways to make CMake
# consistently link everything 100% statically across platforms or set the
# runtime path right always, so this is the best I know how to do for now.
foreach(dir ${DLL_COPY_DIRS})
file(GLOB dir_dll_list "${dir}/*.dll")
file(COPY ${dir_dll_list} DESTINATION ${CMAKE_BINARY_DIR}/Release/)
file(COPY ${dir_dll_list} DESTINATION ${CMAKE_BINARY_DIR}/Debug/)
endforeach ()
foreach(file ${DLL_COPY_LIBS})
file(COPY ${file} DESTINATION ${CMAKE_BINARY_DIR}/Release/)
file(COPY ${file} DESTINATION ${CMAKE_BINARY_DIR}/Debug/)
endforeach()
else ()
# If not on Windows, put them under more standard UNIX-like places. This is
# necessary, otherwise they would all end up in
@@ -536,8 +631,8 @@ if (BUILD_CLI_EXECUTABLES AND UNIX)
)
# Set the rules to install the documentation.
install(DIRECTORY ${CMAKE_BINARY_DIR}/share/man/
DESTINATION ${CMAKE_INSTALL_MANDIR})
install(DIRECTORY "${CMAKE_BINARY_DIR}/share/man/"
DESTINATION "${CMAKE_INSTALL_MANDIR}")
endif ()
endif ()
@@ -588,8 +683,8 @@ if (DOXYGEN_FOUND)
COMMENT "Generating API documentation with Doxygen"
)
install(DIRECTORY ${CMAKE_BINARY_DIR}/doc/html
DESTINATION ${CMAKE_INSTALL_DOCDIR}
install(DIRECTORY "${CMAKE_BINARY_DIR}/doc/html"
DESTINATION "${CMAKE_INSTALL_DOCDIR}"
COMPONENT doc
OPTIONAL
)
@@ -668,6 +763,6 @@ if (PKG_CONFIG_FOUND)
DEPENDS mlpack_headers
COMMENT "Generating mlpack.pc (pkg-config) file.")
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/lib/pkgconfig/mlpack.pc
DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig/)
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/lib/pkgconfig/mlpack.pc"
DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig/")
endif ()
+6
View File
@@ -113,7 +113,13 @@ Copyright:
Copyright 2019, Dan Timson
Copyright 2019, Miguel Canteras <mcanteras@gmail.com>
Copyright 2019, Bishwa Karki <karkeebishwa1@gmail.com>
Copyright 2019, Mehul Kumar Nirala <mehulkumarnirala@gmail.com>
Copyright 2019, Yashwant Singh Parihar <yashwantsingh.sngh@gmail.com>
Copyright 2019, Heet Sankesara <heetsankesara3@gmail.com>
Copyright 2019, Jeffin Sam <sam.jeffin@gmail.com>
Copyright 2019, Vikas S Shetty <shettyvikas209@gmail.com>
Copyright 2019, Tejasvi Tomar <tstomar@outlook.com>
Copyright 2019, Jai Agarwal <jai.bhageria@gmail.com>
License: BSD-3-clause
All rights reserved.
+112
View File
@@ -0,0 +1,112 @@
# mlpack governance structure (DRAFT)
Revised Oct. 21st, 2019.
## Introduction
mlpack has grown much since its initial inception as a small project out of a
university research lab. Now that there are over 150 contributors, it's
important that we have a clearly defined process for making our decisions and
organizing ourselves.
This document aims to clarify the governance of mlpack. This is a living
document: it may change over time. The process for making these changes is
detailed in the "Governance Changes" section.
## Code of Conduct
mlpack aims to be an open and welcoming environment, and as such, we have a
code of conduct that helps foster this environment. See
(here)[https://github.com/mlpack/mlpack/blob/master/CODE_OF_CONDUCT.md] for
more information.
## Teams & Roles
To keep overhead minimal, mlpack's teams and roles are simple: there is only
the [Committers](https://github.com/orgs/mlpack/teams/contributors) team, and
the [NumFOCUS leadership team](TODO:link).
Members of the Committers team have commit access to all mlpack repositories
and help guide the development directions and goals of mlpack. Committers
should be familiar with the [contribution
process](https://github.com/mlpack/mlpack/blob/master/CONTRIBUTING.md) and
follow it when merging code and reviewing pull requests; this is important for
the continued stability and quality of mlpack's codebase. Responsibilities and
activities of Committers team members can include:
* Welcoming new members to the community: helping support users and point
potential contributors in the correct direction.
* Reviewing pull requests and approving them when they are ready.
* Merging pull requests after they have been approved by others for merge.
* Communicating and coordinating with contributors to help get code merged and
improve the software.
* Helping map out mlpack's development directions and processes.
* Maintaining mlpack infrastructure (build systems, continuous integration,
etc.).
Membership on the Committers team does not expire. Contributors who have
repeatedly shown that their code quality is high, demonstrated adherence to the
code of conduct, and shown that they have a strong interest in the project can
be added to the Committers team using the organizational decision process in
the next section.
The NumFOCUS leadership team is a subset of the Committers team whose
additional responsibilities are to coordinate with NumFOCUS and maintain this
governance document. Membership in the NumFOCUS leadership team is limited to
five people, and does not confer any special voting power or decision rights.
## Voting and Organizational Decisions
Historically, mlpack organizational decisions have not been controversial and
this has allowed efficient decision making. Therefore, a vote on a proposal is
not required unless there is any explicit disagreement or concern with the
proposal. The topics of a proposal might be:
* Adding/removing a new member to/from the Committers team.
* Participating in a program such as Google Summer of Code or Outreachy.
* A change to some part of the mlpack infrastructure or contribution process.
* Refactoring or change of an important public part of the API.
* Use of funds for a particular project.
That list is not inclusive. Introducing a proposal or idea can be done
informally in a public place, such as the mlpack mailing list or on Github as
an issue. It's a good idea (but not mandatory) to make the proposal discussion
fully public so that people who are not on the Committers team can also comment
and provide opinions---after all, this is a community-led project so we should
be sure to include the *entire* community whenever possible.
If there is any disagreement or concern with the proposal, the person who
introduced the proposal should work to try and find a resolution or compromise
if possible. If that is not possible, then the proposal can be brought to a
vote.
For a proposal to pass, a simple majority vote suffices. Each Committer has
one equal vote, and they may choose to abstain from voting if they do prefer.
Since some Committers may be inactive or busy, it is not required for every
Committer to participate in every vote; instead, someone who has a proposal
should make a good-faith effort to post the proposal in a public location so
that interested and active Committers can respond. Voting for any proposal
should be open for at least five days to allow sufficient time.
If a proposal passes despite votes against it, it is generally a good idea for
the Committer who introduced the proposal to spend some time considering and
understanding the arguments that were presented against the proposal, or if
appropriate, for the Committer to try and find an acceptable compromise or
alternate strategy that addresses the given feedback.
## Governance Changes
The NumFOCUS leadership team is responsible for this governance document, and
thus any changes to this document, NumFOCUS membership, or the NumFOCUS
leadership team must be approved by that team, also by a simple majority vote.
Because every member of the NumFOCUS leadership team should be an active
Committer, any proposal requires votes (or abstentions) by all five members.
+63 -6
View File
@@ -1,20 +1,77 @@
### mlpack 4.0.0
### mlpack ?.?.?
###### ????-??-??
* Add Multiple Pole Balancing Environment (#1901).
* Add `valid` and `same` padding option in `Convolution` and `Atrous
Convolution` layer (#1988).
* Add Model() to the FFN class to access individual layers (#2043).
* Update documentation for pip and conda installation packages (#2044).
* Add bindings for linear SVM (#1935); `mlpack_linear_svm` from the
command-line, `linear_svm()` from Python.
* Add support to return the layer name as `std::string` (#1987).
* Speed and memory improvements for the Transposed Convolution layer (#1493).
* Fix Windows Python build configuration (#1885).
* Validate md5 of STB library after download (#2087).
* Add `__version__` to `__init__.py` (#2092).
### mlpack 3.2.1
###### 2019-10-01
* Enforce CMake version check for ensmallen (#2032).
* Fix CMake check for Armadillo version (#2029).
* Better handling of when STB is not installed (#2033).
* Fix Naive Bayes classifier computations in high dimensions (#2022).
### mlpack 3.2.0
###### 2019-09-25
* Fix some potential infinity errors in Naive Bayes Classifier (#2022).
* Fix occasionally-failing RADICAL test (#1924).
* Fix gcc 9 OpenMP compilation issue (#1970).
* Added support for loading and saving of images (#1903).
* Add Multiple Pole Balancing Environment (#1901, #1951).
* Added functionality for scaling of data (#1876); see the command-line
binding `mlpack_preprocess_scale` or Python binding `preprocess_scale()`.
* Add new parameter `maximum_depth` to decision tree and random forest
bindings (#1916).
* Fix prediction output of softmax regression when test set accuracy is
calculated (#1922).
* Action struct in continuous RL environments now stores the action as a
`double` instead of `double[1]` (#1941, #1931).
* Pendulum environment now checks for termination. All RL environments now
have an option to terminate after a set number of time steps (no limit
by default) (#1941).
* Add support for probabilistic KDE (kernel density estimation) error bounds
when using the Gaussian kernel (#1934).
* Fix negative distances for cover tree computation (#1979).
* Fix cover tree building when all pairwise distances are 0 (#1986).
* Improve KDE pruning by reclaiming not used error tolerance (#1954, #1984).
* Optimizations for sparse matrix accesses in z-score normalization for CF
(#1989).
* Add `kmeans_max_iterations` option to GMM training binding `gmm_train_main`.
* Bump minimum Armadillo version to 8.400.0 due to ensmallen dependency
requirement (#2015).
### mlpack 3.1.1
###### 2019-05-26
* Fix random forest bug for numerical-only data (#1887).
+4
View File
@@ -12,6 +12,10 @@ licensed under the Boost Software License, version 1.0. This code is found in
src/mlpack/core/boost_backport/ and more details on the licensing are available
there.
mlpack may contain some usage of the source code of stb, which is licensed
under the MIT License and the Public Domain (www.unlicense.org). This code
is used in src/mlpack/core/data/load_image.hpp.
----
Copyright (c) 2007-2018, mlpack contributors (see COPYRIGHT.txt)
All rights reserved.
+38 -19
View File
@@ -23,7 +23,7 @@ src="https://cdn.rawgit.com/mlpack/mlpack.org/e7d36ed8/mlpack-black.svg" style="
<p align="center">
<em>
Download:
<a href="https://www.mlpack.org/files/mlpack-3.1.1.tar.gz">current stable version (3.1.1)</a>
<a href="https://www.mlpack.org/files/mlpack-3.2.2.tar.gz">current stable version (3.2.2)</a>
</em>
</p>
@@ -34,6 +34,21 @@ functions as a "swiss army knife" for machine learning researchers. In addition
to its powerful C++ interface, mlpack also provides command-line programs and
Python bindings.
mlpack uses an [open governance model](./GOVERNANCE.md) and is fiscally
sponsored by [NumFOCUS](https://numfocus.org/). Consider making a
[tax-deductible donation](https://numfocus.org/donate-to-mlpack) to help the
project pay for developer time, professional services, travel, workshops, and a
variety of other needs.
<div align="center">
<a href="https://numfocus.org/donate-to-mlpack">
<img height="60px"
src="https://raw.githubusercontent.com/numfocus/templates/master/images/numfocus-logo.png"
align="center">
</a>
</div>
<br>
### 0. Contents
1. [Introduction](#1-introduction)
@@ -83,10 +98,11 @@ Citations are beneficial for the growth and improvement of mlpack.
mlpack has the following dependencies:
Armadillo >= 6.500.0
Armadillo >= 8.400.0
Boost (program_options, math_c99, unit_test_framework, serialization,
spirit)
CMake >= 3.3.2
ensmallen >= 2.10.0
All of those should be available in your distribution's package manager. If
not, you will have to compile each of them by hand. See the documentation for
@@ -100,12 +116,15 @@ following Python packages are installed:
numpy
pandas >= 0.15.0
If the STB library headers are available, image loading support will be
compiled.
If you are compiling Armadillo by hand, ensure that LAPACK and BLAS are enabled.
### 4. Building mlpack from source
This section discusses how to build mlpack from source. However, mlpack is in
the repositories of many Linux distributions and so it may be easier to use the
the repositories of many Linux distributions, so it may be easier to use the
package manager for your system. For example, on Ubuntu, you can install mlpack
with the following command:
@@ -116,13 +135,13 @@ available---for instance, at the time of this writing, Ubuntu 16.04 only has
mlpack 2.0.1 available. Options include upgrading your Ubuntu version, finding
a PPA or other non-official sources, or installing with a manual build.
There are some other useful pages to consult in addition to this section:
There are some useful pages to consult in addition to this section:
- [Building mlpack From Source](https://www.mlpack.org/doc/mlpack-git/doxygen/build.html)
- [Building mlpack From Source on Windows](https://www.mlpack.org/doc/mlpack-git/doxygen/build_windows.html)
mlpack uses CMake as a build system and allows several flexible build
configuration options. One can consult any of numerous CMake tutorials for
configuration options. You can consult any of the CMake tutorials for
further documentation, but this tutorial should be enough to get mlpack built
and installed.
@@ -132,21 +151,20 @@ use mlpack-x.y.z where x.y.z is the version.
$ tar -xzf mlpack-x.y.z.tar.gz
$ cd mlpack-x.y.z
Then, make a build directory. The directory can have any name, not just
'build', but 'build' is sufficient.
Then, make a build directory. The directory can have any name, but 'build' is
sufficient.
$ mkdir build
$ cd build
The next step is to run CMake to configure the project. Running CMake is the
equivalent to running `./configure` with autotools. If you run CMake with no
options, it will configure the project to build with no debugging symbols and no
profiling information:
options, it will configure the project to build with no debugging symbols and
no profiling information:
$ cmake ../
You can specify options to compile with debugging information and profiling
information:
Options can be specified to compile with debugging information and profiling information:
$ cmake -D DEBUG=ON -D PROFILE=ON ../
@@ -160,10 +178,12 @@ Options are specified with the -D flag. The allowed options include:
ARMADILLO_LIBRARY=(/path/to/armadillo/libarmadillo.so): Armadillo library
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
BUILD_TESTS=(ON/OFF): whether or not to build tests
BUILD_SHARED_LIBS=(ON/OFF): compile shared libraries as opposed to
static libraries
DOWNLOAD_ENSMALLEN=(ON/OFF): If ensmallen is not found, download it
DOWNLOAD_STB_IMAGE=(ON/OFF): If STB is not found, download it
ENSMALLEN_INCLUDE_DIR=(/path/to/ensmallen/include): path to include directory
for ensmallen
USE_OPENMP=(ON/OFF): whether or not to use OpenMP if available
@@ -181,22 +201,21 @@ Once CMake is configured, building the library is as simple as typing 'make'.
This will build all library components as well as 'mlpack_test'.
$ make
You can specify individual components which you want to build, if you do not
want to build everything in the library:
If you do not want to build everything in the library, individual components
of the build can be specified:
$ make mlpack_pca mlpack_knn mlpack_kfn
If the build fails and you cannot figure out why, register an account on Github
and submit an issue; the mlpack developers will quickly help you figure it out:
and submit an issue. The mlpack developers will quickly help you figure it out:
[mlpack on Github](https://www.github.com/mlpack/mlpack/)
Alternately, mlpack help can be found in IRC at `#mlpack` on irc.freenode.net.
If you wish to install mlpack to `/usr/local/include/mlpack/` and `/usr/local/lib/`
and `/usr/local/bin/`, once it has built, make sure you have root privileges (or
write permissions to those three directories), and simply type
If you wish to install mlpack to `/usr/local/include/mlpack/`, `/usr/local/lib/`,
and `/usr/local/bin/`, make sure you have root privileges (or write permissions
to those three directories), and simply type
$ make install
@@ -204,7 +223,7 @@ You can now run the executables by name; you can link against mlpack with
`-lmlpack`
and the mlpack headers are found in
`/usr/local/include/mlpack/`
and if Python bindings were built, they will be accessible with the `mlpack`
and if Python bindings were built, you can access them with the `mlpack`
package in Python.
If running the programs (i.e. `$ mlpack_knn -h`) gives an error of the form
@@ -104,16 +104,16 @@
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>false</ConformanceMode>
<AdditionalIncludeDirectories>C:\boost\boost_1_66_0;C:\mlpack\armadillo-8.500.1\include;C:\mlpack\mlpack-3.1.1\build\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>C:\boost\boost_1_66_0;C:\mlpack\armadillo-8.500.1\include;C:\mlpack\mlpack-3.2.1\build\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>C:\mlpack\mlpack-3.1.1\build\Debug\mlpack.lib;C:\boost\boost_1_66_0\lib64-msvc-14.1\libboost_serialization-vc141-mt-gd-x64-1_66.lib;C:\boost\boost_1_66_0\lib64-msvc-14.1\libboost_program_options-vc141-mt-gd-x64-1_66.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>C:\mlpack\mlpack-3.2.1\build\Debug\mlpack.lib;C:\boost\boost_1_66_0\lib64-msvc-14.1\libboost_serialization-vc141-mt-gd-x64-1_66.lib;C:\boost\boost_1_66_0\lib64-msvc-14.1\libboost_program_options-vc141-mt-gd-x64-1_66.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<PostBuildEvent>
<Command>xcopy /y "C:\mlpack\mlpack-3.1.1\build\Debug\mlpack.dll" $(OutDir)
xcopy /y "C:\mlpack\mlpack-3.1.1\packages\OpenBLAS.0.2.14.1\lib\native\bin\x64\*.dll" $(OutDir)
<Command>xcopy /y "C:\mlpack\mlpack-3.2.1\build\Debug\mlpack.dll" $(OutDir)
xcopy /y "C:\mlpack\mlpack-3.2.1\packages\OpenBLAS.0.2.14.1\lib\native\bin\x64\*.dll" $(OutDir)
xcopy /y "$(ProjectDir)..\..\..\..\src\mlpack\tests\data\german.csv" "$(ProjectDir)data\german.csv*"</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
+20 -10
View File
@@ -29,7 +29,7 @@ to build mlpack on Windows, see \ref build_windows (alternatively, you can read
is based on older versions).
You can download the latest mlpack release from here:
<a href="https://www.mlpack.org/files/mlpack-3.1.1.tar.gz">mlpack-3.1.1</a>
<a href="https://www.mlpack.org/files/mlpack-3.2.1.tar.gz">mlpack-3.2.1</a>
@section build_simple Simple Linux build instructions
@@ -37,9 +37,9 @@ Assuming all dependencies are installed in the system, you can run the commands
below directly to build and install mlpack.
@code
$ wget https://www.mlpack.org/files/mlpack-3.1.1.tar.gz
$ tar -xvzpf mlpack-3.1.1.tar.gz
$ mkdir mlpack-3.1.1/build && cd mlpack-3.1.1/build
$ wget https://www.mlpack.org/files/mlpack-3.2.1.tar.gz
$ tar -xvzpf mlpack-3.2.1.tar.gz
$ mkdir mlpack-3.2.1/build && cd mlpack-3.2.1/build
$ cmake ../
$ make -j4 # The -j is the number of cores you want to use for a build.
$ sudo make install
@@ -64,8 +64,8 @@ configure mlpack.
First we should unpack the mlpack source and create a build directory.
@code
$ tar -xvzpf mlpack-3.1.1.tar.gz
$ cd mlpack-3.1.1
$ tar -xvzpf mlpack-3.2.1.tar.gz
$ cd mlpack-3.2.1
$ mkdir build
@endcode
@@ -76,9 +76,15 @@ The directory can have any name, not just 'build', but 'build' is sufficient.
mlpack depends on the following libraries, which need to be installed on the
system and have headers present:
- Armadillo >= 6.500.0 (with LAPACK support)
- Armadillo >= 8.400.0 (with LAPACK support)
- Boost (math_c99, program_options, serialization, unit_test_framework, heap,
spirit) >= 1.49
- ensmallen >= 2.10.0 (will be downloaded if not found)
In addition, mlpack has the following optional dependencies:
- STB: this will allow loading of images; the library is downloaded if not
found and the CMake variable DOWNLOAD_STB_IMAGE is set to ON (the default)
For Python bindings, the following packages are required:
@@ -93,7 +99,8 @@ In Ubuntu and Debian, you can get all of these dependencies through apt:
@code
# apt-get install libboost-math-dev libboost-program-options-dev
libboost-test-dev libboost-serialization-dev libarmadillo-dev binutils-dev
python-pandas python-numpy cython python-setuptools
python-pandas python-numpy cython python-setuptools libensmallen-dev
libstb-dev
@endcode
On Fedora, Red Hat, or CentOS, these same dependencies can be obtained via dnf:
@@ -101,11 +108,12 @@ On Fedora, Red Hat, or CentOS, these same dependencies can be obtained via dnf:
@code
# dnf install boost-devel boost-test boost-program-options boost-math
armadillo-devel binutils-devel python2-Cython python2-setuptools
python2-numpy python2-pandas
python2-numpy python2-pandas ensmallen-devel stbi-devel
@endcode
(It's also possible to use python3 packages from the package manager---mlpack
will work with either.)
will work with either. Also, the ensmallen-devel package is only available in
Fedora 29 or RHEL7 or newer.)
@section build_config Configuring CMake
@@ -146,8 +154,10 @@ The full list of options mlpack allows:
(default OFF)
- 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
- BUILD_MARKDOWN_BINDINGS=(ON/OFF): Build Markdown bindings for website
documentation (default OFF)
- MATHJAX=(ON/OFF): use MathJax for generated Doxygen documentation (default
+5 -5
View File
@@ -17,11 +17,11 @@ Installing the mlpack bindings for Python is straightforward. It's easy to use
conda or pip to do this:
@code{.sh}
pip install mlpack3
pip install mlpack
@endcode
@code{.sh}
conda install -c mlpack mlpack
conda install -c conda-forge mlpack
@endcode
Otherwise, we can build the Python bindings from scratch, as follows. First we
@@ -31,9 +31,9 @@ build and install mlpack. You can copy-paste the commands into your shell.
@code{.sh}
sudo apt-get install libboost-all-dev g++ cmake libarmadillo-dev python-pip wget
sudo pip install cython setuptools distutils numpy pandas
wget https://www.mlpack.org/files/mlpack-3.1.1.tar.gz
tar -xvzpf mlpack-3.1.1.tar.gz
mkdir -p mlpack-3.1.1/build/ && cd mlpack-3.1.1/build/
wget https://www.mlpack.org/files/mlpack-3.2.1.tar.gz
tar -xvzpf mlpack-3.2.1.tar.gz
mkdir -p mlpack-3.2.1/build/ && cd mlpack-3.2.1/build/
cmake ../ && make -j4 && sudo make install
@endcode
+4 -4
View File
@@ -29,18 +29,18 @@ mlpack and dependencies in Release Mode).
@code
- C:\boost\boost_1_66_0
- C:\mlpack\armadillo-8.500.1\include
- C:\mlpack\mlpack-3.1.1\build\include
- C:\mlpack\mlpack-3.2.1\build\include
@endcode
- Under Linker > Input > Additional Dependencies add:
@code
- C:\mlpack\mlpack-3.1.1\build\Debug\mlpack.lib
- C:\mlpack\mlpack-3.2.1\build\Debug\mlpack.lib
- C:\boost\boost_1_66_0\lib64-msvc-14.1\libboost_serialization-vc141-mt-gd-x64-1_66.lib
- C:\boost\boost_1_66_0\lib64-msvc-14.1\libboost_program_options-vc141-mt-gd-x64-1_66.lib
@endcode
- Under Build Events > Post-Build Event > Command Line add:
@code
- xcopy /y "C:\mlpack\mlpack-3.1.1\build\Debug\mlpack.dll" $(OutDir)
- xcopy /y "C:\mlpack\mlpack-3.1.1\packages\OpenBLAS.0.2.14.1\lib\native\bin\x64\*.dll" $(OutDir)
- xcopy /y "C:\mlpack\mlpack-3.2.1\build\Debug\mlpack.dll" $(OutDir)
- xcopy /y "C:\mlpack\mlpack-3.2.1\packages\OpenBLAS.0.2.14.1\lib\native\bin\x64\*.dll" $(OutDir)
@endcode
@note Recent versions of Visual Studio set "Conformance Mode" enabled by default. This causes some issues with
+185
View File
@@ -0,0 +1,185 @@
/*!
@file image.txt
@author Mehul Kumar Nirala
@brief Tutorial for how to load and save images in mlpack.
@page imagetutorial Image Utilities tutorial
@section intro_imagetut Introduction
Image datasets are becoming increasingly popular in deep learning.
mlpack's image saving/loading functionality is based on [stb/](https://github.com/nothings/stb).
@section toc_imagetut Table of Contents
This tutorial is split into the following sections:
- \ref intro_imagetut
- \ref toc_imagetut
- \ref model_api_imagetut
- \ref imageinfo_api_imagetut
- \ref load_api_imagetut
- \ref save_api_imagetut
@section model_api_imagetut Model API
Image utilities supports loading and saving of images.
It supports filetypes "jpg", "png", "tga","bmp", "psd", "gif", "hdr", "pic", "pnm" for loading and "jpg", "png", "tga", "bmp", "hdr" for saving.
The datatype associated is unsigned char to support RGB values in the range 1-255. To feed data into the network typecast of `arma::Mat` may be required. Images are stored in matrix as (width * height * channels, NumberOfImages). Therefore imageMatrix.col(0) would be the first image if images are loaded in imageMatrix.
@section imageinfo_api_imagetut ImageInfo
ImageInfo class contains the metadata of the images.
@code
/**
* Instantiate the ImageInfo object with the image width, height, channels.
*
* @param width Image width.
* @param height Image height.
* @param channels number of channels in the image.
*/
ImageInfo(const size_t width,
const size_t height,
const size_t channels);
@endcode
Other public memebers include:
- flipVertical Flip the image vertical upon loading.
- quality Compression of the image if saved as jpg (0-100).
@section load_api_imagetut Load
Standalone loading of images.
@code
/**
* Load the image file into the given matrix.
*
* @param filename Name of the image file.
* @param matrix Matrix to load the image into.
* @param info An object of ImageInfo class.
* @param fatal If an error should be reported as fatal (default false).
* @param transpose If true, transpose the matrix after loading.
* @return Boolean value indicating success or failure of load.
*/
template<typename eT>
bool Load(const std::string& filename,
arma::Mat<eT>& matrix,
ImageInfo& info,
const bool fatal,
const bool transpose);
@endcode
Loading a test image. It also fills up the ImageInfo class object.
@code
data::ImageInfo info;
data::Load("test_image.png", matrix, info, false, true);
@endcode
ImageInfo requires height, width, number of channels of the image.
@code
size_t height = 64, width = 64, channels = 1;
data::ImageInfo info(width, height, channels);
@endcode
More than one image can be loaded into the same matrix.
Loading multiple images:
@code
/**
* Load the image file into the given matrix.
*
* @param files A vector consisting of filenames.
* @param matrix Matrix to save the image from.
* @param info An object of ImageInfo class.
* @param fatal If an error should be reported as fatal (default false).
* @param transpose If true, transpose the matrix after loading.
* @return Boolean value indicating success or failure of load.
*/
template<typename eT>
bool Load(const std::vector<std::string>& files,
arma::Mat<eT>& matrix,
ImageInfo& info,
const bool fatal,
const bool transpose);
@endcode
@code
data::ImageInfo info;
std::vector<std::string>> files{"test_image1.bmp","test_image2.bmp"};
data::load(files, matrix, info, false, true);
@endcode
@section save_api_imagetut Save
Save images expects a matrix of type unsigned char in the form (width * height * channels, NumberOfImages).
Just like load it can be used to save one image or multiple images. Besides image data it also expects the shape of the image as input (width, height, channels).
Saving one image:
@code
/**
* Save the image file from the given matrix.
*
* @param filename Name of the image file.
* @param matrix Matrix to save the image from.
* @param info An object of ImageInfo class.
* @param fatal If an error should be reported as fatal (default false).
* @param transpose If true, transpose the matrix after loading.
* @return Boolean value indicating success or failure of load.
*/
template<typename eT>
bool Save(const std::string& filename,
arma::Mat<eT>& matrix,
ImageInfo& info,
const bool fatal,
const bool transpose);
@endcode
@code
data::ImageInfo info;
info.width = info.height = 25;
info.channels = 3;
info.quality = 90;
data::Save("test_image.bmp", matrix, info, false, true);
@endcode
If the matrix contains more than one image, only the first one is saved.
Saving multiple images:
@code
/**
* Save the image file from the given matrix.
*
* @param files A vector consisting of filenames.
* @param matrix Matrix to save the image from.
* @param info An object of ImageInfo class.
* @param fatal If an error should be reported as fatal (default false).
* @param transpose If true, transpose the matrix after loading.
* @return Boolean value indicating success or failure of load.
*/
template<typename eT>
bool Save(const std::vector<std::string>& files,
arma::Mat<eT>& matrix,
ImageInfo& info,
const bool fatal,
const bool transpose);
@endcode
@code
data::ImageInfo info;
info.width = info.height = 25;
info.channels = 3;
info.quality = 90;
std::vector<std::string>> files{"test_image1.bmp", "test_image2.bmp"};
data::Save(files, matrix, info, false, true);
@endcode
Multiple images are saved according to the vector of filenames specified.
*/
+31 -9
View File
@@ -44,7 +44,7 @@ target_link_libraries(mlpack ${MLPACK_LIBRARIES})
set_target_properties(mlpack
PROPERTIES
VERSION 3.1
VERSION 3.2
SOVERSION 3
)
@@ -90,21 +90,21 @@ endforeach()
# At install time, we simply install that directory of header files we
# collected to include/.
install(DIRECTORY ${CMAKE_BINARY_DIR}/include/mlpack DESTINATION
${CMAKE_INSTALL_INCLUDEDIR})
install(DIRECTORY "${CMAKE_BINARY_DIR}/include/mlpack" DESTINATION
"${CMAKE_INSTALL_INCLUDEDIR}")
# Set generated executables to be installed. Unfortunately they must manually
# be entered...
install(TARGETS mlpack
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}"
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}")
add_dependencies(mlpack mlpack_headers)
# If we are building Python bindings, we have to configure setup.py but only
# after we've recursed into methods/.
if (BUILD_PYTHON_BINDINGS)
if (BUILDING_PYTHON_BINDINGS)
# Extract the version number.
file(READ "${CMAKE_SOURCE_DIR}/src/mlpack/core/util/version.hpp"
VERSION_HPP_CONTENTS)
@@ -120,8 +120,30 @@ if (BUILD_PYTHON_BINDINGS)
get_property(CYTHON_INCLUDE_DIRECTORIES DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
PROPERTY INCLUDE_DIRECTORIES)
configure_file(${CMAKE_SOURCE_DIR}/src/mlpack/bindings/python/setup.py.in
${CMAKE_BINARY_DIR}/src/mlpack/bindings/python/setup.py)
add_custom_target(python_configure
COMMAND ${CMAKE_COMMAND}
-D SETUP_PY_IN="${CMAKE_SOURCE_DIR}/src/mlpack/bindings/python/setup.py.in"
-D SETUP_PY_OUT="${CMAKE_BINARY_DIR}/src/mlpack/bindings/python/setup.py"
-D PACKAGE_VERSION="${PACKAGE_VERSION}"
-D Boost_SERIALIZATION_LIBRARY="${Boost_SERIALIZATION_LIBRARY_RELEASE}"
-D Boost_LIBRARY_DIRS="${Boost_LIBRARY_DIRS}"
-D ARMADILLO_LIBRARIES="${ARMADILLO_LIBRARIES}"
-D MLPACK_LIBRARY="$<TARGET_LINKER_FILE:mlpack>"
-D MLPACK_LIBDIR="$<TARGET_LINKER_FILE_DIR:mlpack>"
-D MLPACK_PYXS="${MLPACK_PYXS}"
-D OpenMP_CXX_FLAGS="${OpenMP_CXX_FLAGS}"
-D DISABLE_CFLAGS="${DISABLE_CFLAGS}"
-D CYTHON_INCLUDE_DIRECTORIES="${CYTHON_INCLUDE_DIRECTORIES}"
-D OUTPUT_DIR="${CMAKE_BINARY_DIR}"
-P "${CMAKE_SOURCE_DIR}/src/mlpack/bindings/python/ConfigureSetup.cmake"
BYPRODUCTS "${CMAKE_BINARY_DIR}/src/mlpack/bindings/python/setup.py"
COMMENT "Configuring setup.py...")
add_dependencies(python_configure python_copy)
add_dependencies(python_configured python_configure)
# Append the package version to __init__.py after all the imports are loaded.
file(APPEND ${CMAKE_BINARY_DIR}/src/mlpack/bindings/python/mlpack/__init__.py
"__version__='${PACKAGE_VERSION}'\n")
endif ()
# If we are building Julia bindings, we have to end the 'module' declaration in
+1
View File
@@ -15,3 +15,4 @@ set(MARKDOWN_CATEGORIES ${MARKDOWN_CATEGORIES} PARENT_SCOPE)
set(MLPACK_SRCS ${MLPACK_SRCS} PARENT_SCOPE)
set(MLPACK_PYXS ${MLPACK_PYXS} PARENT_SCOPE)
set(DISABLE_CFLAGS ${DISABLE_CFLAGS} PARENT_SCOPE)
set(BUILDING_PYTHON_BINDINGS ${BUILDING_PYTHON_BINDINGS} PARENT_SCOPE)
+1 -1
View File
@@ -59,7 +59,7 @@ if (BUILD_CLI_EXECUTABLES)
# compiled with the correct int main() call.
set_target_properties(mlpack_${name} PROPERTIES COMPILE_FLAGS
-DBINDING_TYPE=BINDING_TYPE_CLI)
install(TARGETS mlpack_${name} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
install(TARGETS mlpack_${name} RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}")
# If man documentation is being generated, make sure this is a dependency.
if (TXT2MAN)
+29 -5
View File
@@ -40,6 +40,8 @@ if (NOT PY_PANDAS)
not_found_return("pandas not found; not building Python bindings.")
endif ()
set(BUILDING_PYTHON_BINDINGS ON PARENT_SCOPE)
# Nothing in this directory will be compiled into mlpack.
set(BINDING_SOURCES
default_param.hpp
@@ -105,6 +107,8 @@ endif ()
add_custom_target(python ALL DEPENDS mlpack)
add_custom_target(python_copy ALL DEPENDS mlpack)
# The python_configure target is added later; this is a dummy target.
add_custom_target(python_configured ALL)
# Copy necessary files after making the mlpack/ directory.
add_custom_command(TARGET python_copy PRE_BUILD
@@ -137,7 +141,7 @@ if (BUILD_TESTS)
endif ()
# Install any dependencies via setuptools automatically.
add_custom_command(TARGET python_copy POST_BUILD
add_custom_command(TARGET python_configured POST_BUILD
COMMAND ${CMAKE_COMMAND} -E env NO_BUILD=1 ${PYTHON_EXECUTABLE}
${CMAKE_BINARY_DIR}/src/mlpack/bindings/python/setup.py build
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/src/mlpack/bindings/python/)
@@ -162,7 +166,7 @@ add_custom_command(TARGET python POST_BUILD
${CMAKE_BINARY_DIR}/src/mlpack/bindings/python/copy_artifacts.py
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/src/mlpack/bindings/python/)
add_dependencies(python python_copy)
add_dependencies(python python_configured)
# Configure installation script file.
execute_process(COMMAND ${PYTHON_EXECUTABLE}
@@ -174,12 +178,32 @@ 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 "execute_process(COMMAND mkdir -p $ENV{DESTDIR}${CMAKE_PYTHON_PATH})")
install(SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/PythonInstall.cmake)
install(SCRIPT "${CMAKE_CURRENT_SOURCE_DIR}/PythonInstall.cmake")
# Prepare __init__.py for having all of the convenience imports appended to it.
file(COPY mlpack/__init__.py DESTINATION
${CMAKE_BINARY_DIR}/src/mlpack/bindings/python/mlpack/)
if (WIN32)
# Copy all necessary DLLs to the Python build directory.
foreach (dir ${DLL_COPY_DIRS})
file(GLOB dll_dir_files "${dir}/*.dll")
file(COPY ${dll_dir_files} DESTINATION ${CMAKE_BINARY_DIR}/src/mlpack/bindings/python/mlpack/)
endforeach ()
foreach (dll ${DLL_COPY_LIBS})
file(COPY ${dll} DESTINATION ${CMAKE_BINARY_DIR}/src/mlpack/bindings/python/mlpack/)
endforeach ()
# We also need to copy the boost DLLs over.
file(GLOB boost_ser_dll_files "${Boost_LIBRARY_DIRS}/*serialization*.dll")
file(COPY ${boost_ser_dll_files} DESTINATION ${CMAKE_BINARY_DIR}/src/mlpack/bindings/python/mlpack/)
file(GLOB boost_po_dll_files "${Boost_LIBRARY_DIRS}/*program*options*.dll")
file(COPY ${boost_po_dll_files} DESTINATION ${CMAKE_BINARY_DIR}/src/mlpack/bindings/python/mlpack/)
file(GLOB boost_utf_dll_files "${Boost_LIBRARY_DIRS}/*unit*test*framework*.dll")
file(COPY ${boost_utf_dll_files} DESTINATION ${CMAKE_BINARY_DIR}/src/mlpack/bindings/python/mlpack/)
endif ()
# Add a macro to build a python binding.
macro (add_python_binding name)
if (BUILD_PYTHON_BINDINGS)
@@ -204,7 +228,7 @@ if (BUILD_PYTHON_BINDINGS)
-DBINDING_TYPE=BINDING_TYPE_PYX)
add_custom_command(TARGET generate_pyx_${name} POST_BUILD
COMMAND ${CMAKE_COMMAND}
-DPROGRAM=${CMAKE_BINARY_DIR}/bin/generate_pyx_${name}
-DPROGRAM=$<TARGET_FILE:generate_pyx_${name}>
-DOUTPUT_FILE=${CMAKE_BINARY_DIR}/src/mlpack/bindings/python/mlpack/${name}.pyx
-P ${CMAKE_SOURCE_DIR}/CMake/RunProgram.cmake)
@@ -221,7 +245,7 @@ if (BUILD_PYTHON_BINDINGS)
add_dependencies(python build_pyx_${name})
add_dependencies(build_pyx_${name} generate_pyx_${name})
add_dependencies(generate_pyx_${name} python_copy)
add_dependencies(generate_pyx_${name} python_configured)
# Add the convenience import to __init__.py. Note that this happens during
# configuration.
@@ -0,0 +1,46 @@
# ConfigureSetup.cmake: generate the setup.py file given several environment
# variables.
#
# This file depends on the following variables being set:
#
# - SETUP_PY_IN: location of input file
# - SETUP_PY_OUT: location of output file
# - PACKAGE_VERSION: version of package
# - Boost_SERIALIZATION_LIBRARY: location of Boost serialization library
# - Boost_LIBRARY_DIRS: paths to boost libraries
# - ARMADILLO_LIBRARIES: space-separated list of Armadillo dependencies
# - MLPACK_LIBRARY: location of mlpack library
# - MLPACK_PYXS: list of pyx files
# - OpenMP_CXX_FLAGS: OpenMP C++ compilation flags
# - DISABLE_CFLAGS: list of CFLAGS or CXXFLAGS to be disabled
# - CYTHON_INCLUDE_DIRECTORIES: include directories for Cython
# - MLPACK_LIBDIR: path to mlpack libraries
# - OUTPUT_DIR: binary output directory for CMake
# It's possible that the FindBoost CMake script may have returned a Boost
# library with "lib" improperly prepended to it. So we need to see if the file
# exists, and if it doesn't, but it has a "lib" in it, then we will try
# stripping the "lib" off the front.
message(STATUS "Run with ${Boost_SERIALIZATION_LIBRARY}.")
if (NOT EXISTS "${Boost_SERIALIZATION_LIBRARY}")
message(STATUS "Did not find serialization library ${Boost_SERIALIZATION_LIBRARY}!")
# Split the filename to see if it starts with lib.
set(Boost_SERIALIZATION_LIBRARY_ORIG "${Boost_SERIALIZATION_LIBRARY}")
get_filename_component(SER_LIB_DIRECTORY "${Boost_SERIALIZATION_LIBRARY}"
DIRECTORY)
get_filename_component(SER_LIB_FILENAME "${Boost_SERIALIZATION_LIBRARY}" NAME)
message(STATUS "Name component is ${SER_LIB_FILENAME}, and directory is ${SER_LIB_DIRECTORY}.")
# Strip any preceding "lib/".
string(REGEX REPLACE "^lib" "" STRIPPED_FILENAME "${SER_LIB_FILENAME}")
message(STATUS "Regex gave us ${STRIPPED_FILENAME}.")
set(Boost_SERIALIZATION_LIBRARY "${SER_LIB_DIRECTORY}/${STRIPPED_FILENAME}")
message(STATUS "New library ${Boost_SERIALIZATION_LIBRARY}.")
if (NOT EXISTS "${Boost_SERIALIZATION_LIBRARY}")
# We didn't find it, so for ease of debugging just revert to the original.
set (Boost_SERIALIZATION_LIBRARY "${Boost_SERIALIZATION_LIBRARY_ORIG}")
endif ()
endif ()
configure_file("${SETUP_PY_IN}" "${SETUP_PY_OUT}")
@@ -5,7 +5,7 @@
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=${CMAKE_INSTALL_PREFIX} --root=$ENV{DESTDIR}
WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/src/mlpack/bindings/python/"
RESULT_VARIABLE setup_res)
else ()
@@ -26,6 +26,9 @@ numpy.import_array()
cimport arma
from libcpp cimport bool
import platform
isWin = (platform.system() == "Windows")
cdef extern from "numpy/arrayobject.h":
void PyArray_ENABLEFLAGS(numpy.ndarray arr, int flags)
void PyArray_CLEARFLAGS(numpy.ndarray arr, int flags)
@@ -45,16 +48,16 @@ cdef arma.Mat[double]* numpy_to_mat_d(numpy.ndarray[numpy.double_t, ndim=2] X, \
"""
Convert a numpy ndarray to a matrix. The memory will still be owned by numpy.
"""
if not (X.flags.c_contiguous or X.flags.owndata):
if not X.flags.c_contiguous or (not X.flags.owndata and not isWin):
# If needed, make a copy where we own the memory.
X = X.copy(order="C")
takeOwnership = True
cdef arma.Mat[double]* m = new arma.Mat[double](<double*> X.data, X.shape[1],\
X.shape[0], False, False)
X.shape[0], isWin, False)
# Take ownership of the memory, if we need to.
if takeOwnership:
# Take ownership of the memory, if we need to and we are not on Windows.
if takeOwnership and not isWin:
PyArray_CLEARFLAGS(X, numpy.NPY_OWNDATA)
SetMemState[arma.Mat[double]](m[0], 0)
@@ -65,16 +68,17 @@ cdef arma.Mat[size_t]* numpy_to_mat_s(numpy.ndarray[numpy.npy_intp, ndim=2] X, \
"""
Convert a numpy ndarray to a matrix. The memory will still be owned by numpy.
"""
if not (X.flags.c_contiguous or X.flags.owndata):
# If needed, make a copy where we own the memory.
if not X.flags.c_contiguous or (not X.flags.owndata and not isWin):
# If needed, make a copy where we own the memory, except on Windows where
# we never copy.
X = X.copy(order="C")
takeOwnership = True
cdef arma.Mat[size_t]* m = new arma.Mat[size_t](<size_t*> X.data, X.shape[1],
X.shape[0], False, False)
X.shape[0], isWin, False)
# Take ownership of the memory, if we need to.
if takeOwnership:
if takeOwnership and not isWin:
PyArray_CLEARFLAGS(X, numpy.NPY_OWNDATA)
SetMemState[arma.Mat[size_t]](m[0], 0)
@@ -91,9 +95,11 @@ cdef numpy.ndarray[numpy.double_t, ndim=2] mat_to_numpy_d(arma.Mat[double]& X) \
dims[1] = <numpy.npy_intp> X.n_rows
cdef numpy.ndarray[numpy.double_t, ndim=2] output = \
numpy.PyArray_SimpleNewFromData(2, &dims[0], numpy.NPY_DOUBLE, GetMemory(X))
if isWin:
output = output.copy(order="C")
# Transfer memory ownership, if needed.
if GetMemState[arma.Mat[double]](X) == 0:
if GetMemState[arma.Mat[double]](X) == 0 and not isWin:
SetMemState[arma.Mat[double]](X, 1)
PyArray_ENABLEFLAGS(output, numpy.NPY_OWNDATA)
@@ -110,9 +116,11 @@ cdef numpy.ndarray[numpy.npy_intp, ndim=2] mat_to_numpy_s(arma.Mat[size_t]& X) \
dims[1] = <numpy.npy_intp> X.n_rows
cdef numpy.ndarray[numpy.npy_intp, ndim=2] output = \
numpy.PyArray_SimpleNewFromData(2, &dims[0], numpy.NPY_INTP, GetMemory(X))
if isWin:
output = output.copy(order="C")
# Transfer memory ownership, if needed.
if GetMemState[arma.Mat[size_t]](X) == 0:
if GetMemState[arma.Mat[size_t]](X) == 0 and not isWin:
SetMemState[arma.Mat[size_t]](X, 1)
PyArray_ENABLEFLAGS(output, numpy.NPY_OWNDATA)
@@ -124,16 +132,17 @@ cdef arma.Row[double]* numpy_to_row_d(numpy.ndarray[numpy.double_t, ndim=1] X, \
Convert a numpy one-dimensional ndarray to a row. The memory will still be
owned by numpy.
"""
if not (X.flags.c_contiguous or X.flags.owndata):
# If needed, make a copy where we own the memory.
if not X.flags.c_contiguous or (not X.flags.owndata and not isWin):
# If needed, make a copy where we own the memory, except on Windows where
# we never copy.
X = X.copy(order="C")
takeOwnership = True
cdef arma.Row[double]* m = new arma.Row[double](<double*> X.data, X.shape[0],
False, False)
isWin, False)
# Transfer memory ownership, if needed.
if takeOwnership:
if takeOwnership and not isWin:
PyArray_CLEARFLAGS(X, numpy.NPY_OWNDATA)
SetMemState[arma.Row[double]](m[0], 0)
@@ -145,16 +154,17 @@ cdef arma.Row[size_t]* numpy_to_row_s(numpy.ndarray[numpy.npy_intp, ndim=1] X, \
Convert a numpy one-dimensional ndarray to a row. The memory will still be
owned by numpy.
"""
if not (X.flags.c_contiguous or X.flags.owndata):
# If needed, make a copy where we own the memory.
if not X.flags.c_contiguous or (not X.flags.owndata and not isWin):
# If needed, make a copy where we own the memory, except on Windows where
# we never copy.
X = X.copy(order="C")
takeOwnership = True
cdef arma.Row[size_t]* m = new arma.Row[size_t](<size_t*> X.data, X.shape[0],
False, False)
isWin, False)
# Transfer memory ownership, if needed.
if takeOwnership:
if takeOwnership and not isWin:
PyArray_CLEARFLAGS(X, numpy.NPY_OWNDATA)
SetMemState[arma.Row[size_t]](m[0], 0)
@@ -169,9 +179,11 @@ cdef numpy.ndarray[numpy.double_t, ndim=1] row_to_numpy_d(arma.Row[double]& X) \
cdef numpy.npy_intp dim = <numpy.npy_intp> X.n_elem
cdef numpy.ndarray[numpy.double_t, ndim=1] output = \
numpy.PyArray_SimpleNewFromData(1, &dim, numpy.NPY_DOUBLE, GetMemory(X))
if isWin:
output = output.copy(order="C")
# Transfer memory ownership, if needed.
if GetMemState[arma.Row[double]](X) == 0:
if GetMemState[arma.Row[double]](X) == 0 and not isWin:
SetMemState[arma.Row[double]](X, 1)
PyArray_ENABLEFLAGS(output, numpy.NPY_OWNDATA)
@@ -182,13 +194,16 @@ cdef numpy.ndarray[numpy.npy_intp, ndim=1] row_to_numpy_s(arma.Row[size_t]& X) \
"""
Convert an Armadillo row vector to a one-dimensional numpy ndarray.
"""
# print("called row_to_numpy_s()\n")
# Extract dimensions.
cdef numpy.npy_intp dim = <numpy.npy_intp> X.n_elem
cdef numpy.ndarray[numpy.npy_intp, ndim=1] output = \
numpy.PyArray_SimpleNewFromData(1, &dim, numpy.NPY_INTP, GetMemory(X))
if isWin:
output = output.copy(order="C")
# Transfer memory ownership, if needed.
if GetMemState[arma.Row[size_t]](X) == 0:
if GetMemState[arma.Row[size_t]](X) == 0 and not isWin:
SetMemState[arma.Row[size_t]](X, 1)
PyArray_ENABLEFLAGS(output, numpy.NPY_OWNDATA)
@@ -200,16 +215,17 @@ cdef arma.Col[double]* numpy_to_col_d(numpy.ndarray[numpy.double_t, ndim=1] X, \
Convert a numpy one-dimensional ndarray to a column vector. The memory will
still be owned by numpy.
"""
if not (X.flags.c_contiguous or X.flags.owndata):
# If needed, make a copy where we own the memory.
if not X.flags.c_contiguous or (not X.flags.owndata and not isWin):
# If needed, make a copy where we own the memory, except on Windows where
# we never copy.
X = X.copy(order="C")
takeOwnership = True
cdef arma.Col[double]* m = new arma.Col[double](<double*> X.data, X.shape[0],
False, True)
isWin, False)
# Transfer memory ownership, if needed.
if takeOwnership:
if takeOwnership and not isWin:
PyArray_CLEARFLAGS(X, numpy.NPY_OWNDATA)
SetMemState[arma.Col[double]](m[0], 0)
@@ -221,15 +237,17 @@ cdef arma.Col[size_t]* numpy_to_col_s(numpy.ndarray[numpy.npy_intp, ndim=1] X, \
Convert a numpy one-dimensional ndarray to a column vector. The memory will
still be owned by numpy.
"""
if not (X.flags.c_contiguous or X.flags.owndata):
# If needed, make a copy where we own the memory.
if not X.flags.c_contiguous or (not X.flags.owndata and not isWin):
# If needed, make a copy where we own the memory, except on Windows where
# we never copy.
X = X.copy(order="C")
takeOwnership = True
cdef arma.Col[size_t]* m = new arma.Col[size_t](<size_t*> X.data, X.shape[0],
False, False)
isWin, False)
# Transfer memory ownership, if needed.
if takeOwnership:
if takeOwnership and not isWin:
PyArray_CLEARFLAGS(X, numpy.NPY_OWNDATA)
SetMemState[arma.Col[size_t]](m[0], 0)
@@ -244,9 +262,11 @@ cdef numpy.ndarray[numpy.double_t, ndim=1] col_to_numpy_d(arma.Col[double]& X) \
cdef numpy.npy_intp dim = <numpy.npy_intp> X.n_elem
cdef numpy.ndarray[numpy.double_t, ndim=1] output = \
numpy.PyArray_SimpleNewFromData(1, &dim, numpy.NPY_DOUBLE, GetMemory(X))
if isWin:
output = output.copy(order="C")
# Transfer memory ownership, if needed.
if GetMemState[arma.Col[double]](X) == 0:
if GetMemState[arma.Col[double]](X) == 0 and not isWin:
SetMemState[arma.Col[double]](X, 1)
PyArray_ENABLEFLAGS(output, numpy.NPY_OWNDATA)
@@ -261,9 +281,11 @@ cdef numpy.ndarray[numpy.npy_intp, ndim=1] col_to_numpy_s(arma.Col[size_t]& X) \
cdef numpy.npy_intp dim = <numpy.npy_intp> X.n_elem
cdef numpy.ndarray[numpy.npy_intp, ndim=1] output = \
numpy.PyArray_SimpleNewFromData(1, &dim, numpy.NPY_INTP, GetMemory(X))
if isWin:
output = output.copy(order="C")
# Transfer memory ownership, if needed.
if GetMemState[arma.Col[size_t]](X) == 0:
if GetMemState[arma.Col[size_t]](X) == 0 and not isWin:
SetMemState[arma.Col[size_t]](X, 1)
PyArray_ENABLEFLAGS(output, numpy.NPY_OWNDATA)
+41 -18
View File
@@ -11,6 +11,7 @@ import os
import sys
import numpy as np
import re
import platform
# Process input argument --module={name} first if needed.
module = None
@@ -22,57 +23,79 @@ from setuptools import setup
from setuptools.extension import Extension
from Cython.Distutils import build_ext
pyxs='${MLPACK_PYXS}'.split(';')
pyxs='${MLPACK_PYXS}'.split(' ')
if not '${OpenMP_CXX_FLAGS}':
extra_link_args=[]
else:
extra_link_args=['${OpenMP_CXX_FLAGS}']
# Get list of library dirs.
library_dirs = list(filter(None, ['${MLPACK_LIBDIR}'] +
'${Boost_LIBRARY_DIRS}'.split(' ')))
# We'll link with the exact paths to each library using extra_objects, instead
# of linking with 'libraries' and 'library_dirs', because of differences in
# Windows and Linux linking behavior.
libraries = ['${MLPACK_LIBRARY}',
'${Boost_SERIALIZATION_LIBRARY}'] + \
'${ARMADILLO_LIBRARIES}'.split(' ')
# Potentially faulty assumption: we can always link against libraries directly
# by just specifying the full path to them on the command line.
extra_link_args += libraries
# Only build the extensions if we are asked to.
if os.getenv('NO_BUILD') == '1':
modules = []
else:
cxx_flags = '${CMAKE_CXX_FLAGS}'.strip()
cxx_flags = re.sub(' +', ' ', cxx_flags)
extra_args = ['-DBINDING_TYPE=BINDING_TYPE_PYX',
'-std=c++11'] + cxx_flags.split(' ')
if cxx_flags:
extra_args = ['-DBINDING_TYPE=BINDING_TYPE_PYX',
'-std=c++11',
'${OpenMP_CXX_FLAGS}'] + cxx_flags.split(' ')
else:
extra_args = ['-DBINDING_TYPE=BINDING_TYPE_PYX',
'-std=c++11',
'${OpenMP_CXX_FLAGS}']
# Extra options for MSVC compiler.
if platform.system() == 'Windows':
extra_args = extra_args + ['/MD', '/O2', '/Ob2', '/DNDEBUG']
# This is used for parallel builds; CMake will set PYX_TO_BUILD accordingly.
if module is not None:
modules=[\
Extension('mlpack.' + name.split('.')[0],
['${CMAKE_BINARY_DIR}/src/mlpack/bindings/python/mlpack/' +
name],
['mlpack/' + name],
language='c++',
include_dirs=[ \
np.get_include(), \
'${CMAKE_BINARY_DIR}/src/mlpack/bindings/python/'] +
'${CYTHON_INCLUDE_DIRECTORIES}'.split(';'),
libraries=['mlpack', 'boost_serialization'],
library_dirs=['${CMAKE_BINARY_DIR}/lib/'],
'${OUTPUT_DIR}/src/mlpack/bindings/python/'] +
'${CYTHON_INCLUDE_DIRECTORIES}'.split(' '),
library_dirs=library_dirs,
# CMAKE_CXX_FLAGS seems to have an extra space.
extra_compile_args=extra_args,
extra_link_args=extra_link_args,
undef_macros=[] if len("${DISABLE_CFLAGS}") == 0 \
else '${DISABLE_CFLAGS}'.split(';')) \
else '${DISABLE_CFLAGS}'.split(' ')) \
for name in pyxs if name == module]
else:
modules=[\
Extension('mlpack.' + name.split('.')[0],
['${CMAKE_BINARY_DIR}/src/mlpack/bindings/python/mlpack/' +
name],
['mlpack/' + name],
language='c++',
include_dirs=[ \
np.get_include(), \
'${CMAKE_BINARY_DIR}/src/mlpack/bindings/python/'] +
'${CYTHON_INCLUDE_DIRECTORIES}'.split(';'),
libraries=['mlpack', 'boost_serialization'],
library_dirs=['${CMAKE_BINARY_DIR}/lib/'],
'${OUTPUT_DIR}/src/mlpack/bindings/python/'] +
'${CYTHON_INCLUDE_DIRECTORIES}'.split(' '),
library_dirs=library_dirs,
# CMAKE_CXX_FLAGS seems to have an extra space.
extra_compile_args=extra_args,
extra_link_args=extra_link_args,
undef_macros=[] if len("${DISABLE_CFLAGS}") == 0 \
else '${DISABLE_CFLAGS}'.split(';')) \
else '${DISABLE_CFLAGS}'.split(' ')) \
for name in pyxs]
setup(name='mlpack',
@@ -103,7 +126,7 @@ setup(name='mlpack',
'Source': 'https://github.com/mlpack/mlpack/',
'Tracker': 'https://github.com/mlpack/mlpack/issues'},
install_requires=['cython>=0.24', 'numpy', 'pandas'],
package_dir={ '': '${CMAKE_BINARY_DIR}/src/mlpack/bindings/python/' },
package_dir={ '': '.' }, # Might be superfluous.
packages=['mlpack'],
cmdclass={ 'build_ext': build_ext },
ext_modules = modules,
@@ -60,7 +60,8 @@ class TestToMatrix(unittest.TestCase):
"""
d = pd.DataFrame({'a': range(50)})
d['b'] = np.random.randn(50, 1)
self.assertEqual(d['a'].dtype, int)
self.assertTrue((d['a'].dtype == np.dtype('int32')) or
(d['a'].dtype == np.dtype('int64')))
self.assertEqual(d['b'].dtype, np.dtype(np.double))
m, _ = to_matrix(d)
@@ -190,7 +191,8 @@ class TestToMatrixWithInfo(unittest.TestCase):
"""
d = pd.DataFrame({'a': range(50)})
d['b'] = np.random.randn(50, 1)
self.assertEqual(d['a'].dtype, int)
self.assertTrue((d['a'].dtype == np.dtype('int32')) or
(d['a'].dtype == np.dtype('int64')))
self.assertEqual(d['b'].dtype, np.dtype(np.double))
m, _, dims = to_matrix_with_info(d, np.double)
@@ -263,7 +263,7 @@ class TestPythonBinding(unittest.TestCase):
s_umatrix_in=z)
self.assertEqual(output['s_umatrix_out'].shape[0], 100)
self.assertEqual(output['s_umatrix_out'].dtype, np.long)
self.assertEqual(output['s_umatrix_out'].dtype, np.dtype('intp'))
for i in range(100):
self.assertEqual(output['s_umatrix_out'][i, 0], x.iloc[i] * 2)
@@ -284,7 +284,7 @@ class TestPythonBinding(unittest.TestCase):
copy_all_inputs=True)
self.assertEqual(output['s_umatrix_out'].shape[0], 100)
self.assertEqual(output['s_umatrix_out'].dtype, np.long)
self.assertEqual(output['s_umatrix_out'].dtype, np.dtype('intp'))
for i in range(100):
self.assertEqual(output['s_umatrix_out'][i, 0], x.iloc[i] * 2)
@@ -460,7 +460,7 @@ class TestPythonBinding(unittest.TestCase):
self.assertEqual(output['umatrix_out'].shape[0], 100)
self.assertEqual(output['umatrix_out'].shape[1], 4)
self.assertEqual(output['umatrix_out'].dtype, np.long)
self.assertEqual(output['umatrix_out'].dtype, np.dtype('intp'))
for i in [0, 1, 3]:
for j in range(100):
self.assertEqual(x[j, i], output['umatrix_out'][j, i])
@@ -484,7 +484,7 @@ class TestPythonBinding(unittest.TestCase):
self.assertEqual(output['umatrix_out'].shape[0], 100)
self.assertEqual(output['umatrix_out'].shape[1], 4)
self.assertEqual(output['umatrix_out'].dtype, np.long)
self.assertEqual(output['umatrix_out'].dtype, np.dtype('intp'))
for i in [0, 1, 3]:
for j in range(100):
self.assertEqual(x[j, i], output['umatrix_out'][j, i])
@@ -509,7 +509,7 @@ class TestPythonBinding(unittest.TestCase):
self.assertEqual(output['umatrix_out'].shape[0], 3)
self.assertEqual(output['umatrix_out'].shape[1], 4)
self.assertEqual(output['umatrix_out'].dtype, np.long)
self.assertEqual(output['umatrix_out'].dtype, np.dtype('intp'))
self.assertEqual(output['umatrix_out'][0, 0], 1)
self.assertEqual(output['umatrix_out'][0, 1], 2)
self.assertEqual(output['umatrix_out'][0, 2], 6)
@@ -543,7 +543,7 @@ class TestPythonBinding(unittest.TestCase):
self.assertEqual(output['umatrix_out'].shape[1], 4)
self.assertEqual(len(x), 3)
self.assertEqual(len(x[0]), 5)
self.assertEqual(output['umatrix_out'].dtype, np.long)
self.assertEqual(output['umatrix_out'].dtype, np.dtype('intp'))
self.assertEqual(output['umatrix_out'][0, 0], 1)
self.assertEqual(output['umatrix_out'][0, 1], 2)
self.assertEqual(output['umatrix_out'][0, 2], 6)
@@ -612,7 +612,7 @@ class TestPythonBinding(unittest.TestCase):
ucol_in=z)
self.assertEqual(output['ucol_out'].shape[0], 100)
self.assertEqual(output['ucol_out'].dtype, np.long)
self.assertEqual(output['ucol_out'].dtype, np.dtype('intp'))
for i in range(100):
self.assertEqual(output['ucol_out'][i], x[i] * 2)
@@ -631,7 +631,7 @@ class TestPythonBinding(unittest.TestCase):
copy_all_inputs=True)
self.assertEqual(output['ucol_out'].shape[0], 100)
self.assertEqual(output['ucol_out'].dtype, np.long)
self.assertEqual(output['ucol_out'].dtype, np.dtype('intp'))
for i in range(100):
self.assertEqual(output['ucol_out'][i], x[i] * 2)
@@ -690,7 +690,7 @@ class TestPythonBinding(unittest.TestCase):
urow_in=z)
self.assertEqual(output['urow_out'].shape[0], 100)
self.assertEqual(output['urow_out'].dtype, np.long)
self.assertEqual(output['urow_out'].dtype, np.dtype('intp'))
for i in range(100):
self.assertEqual(output['urow_out'][i], x[i] * 2)
@@ -710,7 +710,7 @@ class TestPythonBinding(unittest.TestCase):
copy_all_inputs=True)
self.assertEqual(output['urow_out'].shape[0], 100)
self.assertEqual(output['urow_out'].dtype, np.long)
self.assertEqual(output['urow_out'].dtype, np.dtype('intp'))
for i in range(100):
self.assertEqual(output['urow_out'][i], x[i] * 2)
@@ -923,7 +923,7 @@ class TestPythonBinding(unittest.TestCase):
s_umatrix_in=z)
self.assertEqual(output['s_umatrix_out'].shape[0], 100)
self.assertEqual(output['s_umatrix_out'].dtype, np.long)
self.assertEqual(output['s_umatrix_out'].dtype, np.dtype('intp'))
for i in range(100):
self.assertEqual(output['s_umatrix_out'][i, 0], x[i] * 2)
@@ -943,7 +943,7 @@ class TestPythonBinding(unittest.TestCase):
copy_all_inputs=True)
self.assertEqual(output['s_umatrix_out'].shape[0], 100)
self.assertEqual(output['s_umatrix_out'].dtype, np.long)
self.assertEqual(output['s_umatrix_out'].dtype, np.dtype('intp'))
for i in range(100):
self.assertEqual(output['s_umatrix_out'][i, 0], x[i] * 2)
@@ -1003,7 +1003,7 @@ class TestPythonBinding(unittest.TestCase):
ucol_in=z)
self.assertEqual(output['ucol_out'].shape[0], 100)
self.assertEqual(output['ucol_out'].dtype, np.long)
self.assertEqual(output['ucol_out'].dtype, np.dtype('intp'))
for i in range(100):
self.assertEqual(output['ucol_out'][i], x[i] * 2)
@@ -1022,7 +1022,7 @@ class TestPythonBinding(unittest.TestCase):
copy_all_inputs=True)
self.assertEqual(output['ucol_out'].shape[0], 100)
self.assertEqual(output['ucol_out'].dtype, np.long)
self.assertEqual(output['ucol_out'].dtype, np.dtype('intp'))
for i in range(100):
self.assertEqual(output['ucol_out'][i], x[i] * 2)
@@ -1081,7 +1081,7 @@ class TestPythonBinding(unittest.TestCase):
urow_in=z)
self.assertEqual(output['urow_out'].shape[0], 100)
self.assertEqual(output['urow_out'].dtype, np.long)
self.assertEqual(output['urow_out'].dtype, np.dtype('intp'))
for i in range(100):
self.assertEqual(output['urow_out'][i], x[i] * 2)
@@ -1101,7 +1101,7 @@ class TestPythonBinding(unittest.TestCase):
copy_all_inputs=True)
self.assertEqual(output['urow_out'].shape[0], 101)
self.assertEqual(output['urow_out'].dtype, np.long)
self.assertEqual(output['urow_out'].dtype, np.dtype('intp'))
for i in range(101):
self.assertEqual(output['urow_out'][i], x[0][i] * 2)
@@ -2,8 +2,6 @@
# Anything not in this list will not be compiled into mlpack.
set(SOURCES
arma_extend.hpp
fn_inplace_reshape.hpp
hdf5_misc.hpp
SpMat_extra_bones.hpp
SpMat_extra_meat.hpp
Mat_extra_bones.hpp
@@ -36,11 +36,6 @@
#endif
#endif
// Make sure that U64 and S64 support is enabled.
#ifndef ARMA_USE_U64S64
#define ARMA_USE_U64S64
#endif
// Include everything we'll need for serialize().
#include <boost/serialization/serialization.hpp>
#include <boost/serialization/nvp.hpp>
@@ -48,13 +43,4 @@
#include <armadillo>
namespace arma {
// u64/s64
#include "hdf5_misc.hpp"
// inplace_reshape()
#include "fn_inplace_reshape.hpp"
};
#endif
@@ -1,33 +0,0 @@
//! \addtogroup fn_inplace_reshape
//! @{
/**
* This does not handle column vectors or row vectors entirely correctly. You
* should be able to do multiplication or other basic operations with the
* resulting matrix, but it may have other problems. So if you are using this
* on vectors (arma::Col<> or arma::Row<>), be careful, and be warned that
* bizarre behavior may occur.
*/
template<typename eT>
inline
Mat<eT>&
inplace_reshape(Mat<eT>& X,
const uword new_n_rows,
const uword new_n_cols)
{
arma_extra_debug_sigprint();
arma_debug_check((new_n_rows * new_n_cols) != X.n_elem,
"inplace_reshape(): cannot add or remove elements");
access::rw(X.n_rows) = new_n_rows;
access::rw(X.n_cols) = new_n_cols;
return X;
}
//! @}
-38
View File
@@ -1,38 +0,0 @@
// Copyright (C) 2012-2013 National ICT Australia (NICTA)
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
// -------------------------------------------------------------------
//
// Written by Conrad Sanderson - http://conradsanderson.id.au
// Written by Ryan Curtin
// Written by Szabolcs Horvat
// To hack in u64/s64 support to Armadillo when it is not compiled with
// ARMA_64BIT_WORD.
namespace hdf5_misc {
#if defined(ARMA_USE_HDF5)
#if !(defined(ARMA_64BIT_WORD) || defined(ARMA_USE_U64S64))
#if defined(ULLONG_MAX)
template<>
inline
hid_t
get_hdf5_type< long long >()
{
return H5Tcopy(H5T_NATIVE_LLONG);
}
template<>
inline
hid_t
get_hdf5_type< unsigned long long >()
{
return H5Tcopy(H5T_NATIVE_ULLONG);
}
#endif
#endif
#endif
} // namespace hdf5_misc
+2
View File
@@ -10,6 +10,7 @@ set(SOURCES
load_csv.hpp
load_csv.cpp
load.hpp
load_image_impl.hpp
load_model_impl.hpp
load_vec_impl.hpp
load_impl.hpp
@@ -38,6 +39,7 @@ endforeach()
# Add subdirectories.
add_subdirectory(imputation_methods)
add_subdirectory(map_policies)
add_subdirectory(scaler_methods)
# Append sources (with directory name) to list of all mlpack sources (used at
# parent scope).
+110
View File
@@ -0,0 +1,110 @@
/**
* @file image_info.hpp
* @author Mehul Kumar Nirala
*
* An image information holder.
*
* mlpack is free software; you may redistribute it and/or modify it under the
* terms of the 3-clause BSD license. You should have received a copy of the
* 3-clause BSD license along with mlpack. If not, see
* http://www.opensource.org/licenses/BSD-3-Clause for more information.
*/
#ifndef MLPACK_CORE_DATA_IMAGE_INFO_HPP
#define MLPACK_CORE_DATA_IMAGE_INFO_HPP
#include <mlpack/prereqs.hpp>
#include "extension.hpp"
#ifdef HAS_STB // Compile this only if stb is present.
#define STB_IMAGE_STATIC
#define STB_IMAGE_IMPLEMENTATION
#include <stb_image.h>
#define STB_IMAGE_WRITE_STATIC
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include <stb_image_write.h>
#endif
namespace mlpack {
namespace data {
#ifdef HAS_STB // Compile this only if stb is present.
/**
* Checks if the given image filename is supported.
*
* @param filename Name of the image file.
* @return Boolean value indicating success if it is an image.
*/
inline bool ImageFormatSupported(const std::string& fileName,
const bool save = false);
#endif
/**
* Implements meta-data of images required by data::Load and
* data::Save for loading and saving images into arma::Mat.
*/
class ImageInfo
{
public:
/**
* Instantiate the ImageInfo object with the given image width, height,
* number of channels and quality parameter.
*
* @param width Image width.
* @param height Image height.
* @param channels Number of channels in the image.
* @param quality Compression of the image if saved as jpg (0 - 100).
*/
ImageInfo(const size_t width = 0,
const size_t height = 0,
const size_t channels = 3,
const size_t quality = 90);
//! Get the image width.
const size_t& Width() const { return width; }
//! Modify the image width.
size_t& Width() { return width; }
//! Get the image height.
const size_t& Height() const { return height; }
//! Modify the image height.
size_t& Height() { return height; }
//! Get the image channels.
const size_t& Channels() const { return channels; }
//! Modify the image channels.
size_t& Channels() { return channels; }
//! Get the image quality.
const size_t& Quality() const { return quality; }
//! Modify the image quality.
size_t& Quality() { return quality; }
private:
// To store the image width.
size_t width;
// To store the image height.
size_t height;
// To store the number of channels in the image.
size_t channels;
// Compression of the image if saved as jpg (0 - 100).
size_t quality;
};
} // namespace data
} // namespace mlpack
// Include implementation of Image.
#include "image_info_impl.hpp"
#endif
+77
View File
@@ -0,0 +1,77 @@
/**
* @file image_info_impl.hpp
* @author Mehul Kumar Nirala
*
* An image information holder implementation.
*
* mlpack is free software; you may redistribute it and/or modify it under the
* terms of the 3-clause BSD license. You should have received a copy of the
* 3-clause BSD license along with mlpack. If not, see
* http://www.opensource.org/licenses/BSD-3-Clause for more information.
*/
#ifndef MLPACK_CORE_DATA_IMAGE_INFO_IMPL_HPP
#define MLPACK_CORE_DATA_IMAGE_INFO_IMPL_HPP
#ifdef HAS_STB // Compile this only if stb is present.
// In case it hasn't been included yet.
#include "image_info.hpp"
namespace mlpack {
namespace data {
static const std::vector<std::string> loadFileTypes({"jpg", "png", "tga",
"bmp", "psd", "gif", "hdr", "pic", "pnm", "jpeg"});
static const std::vector<std::string> saveFileTypes({"jpg", "png", "tga",
"bmp", "hdr"});
inline bool ImageFormatSupported(const std::string& fileName, const bool save)
{
if (save)
{
// Iterate over all supported file types that can be saved.
for (auto extension : saveFileTypes)
{
if (extension == Extension(fileName))
return true;
}
}
else
{
// Iterate over all supported file types that can be loaded.
for (auto extension : loadFileTypes)
{
if (extension == Extension(fileName))
return true;
}
}
return false;
}
} // namespace data
} // namespace mlpack
#endif // HAS_STB.
namespace mlpack {
namespace data {
inline ImageInfo::ImageInfo(const size_t width,
const size_t height,
const size_t channels,
const size_t quality) :
width(width),
height(height),
channels(channels),
quality(quality)
{
// Do nothing.
}
} // namespace data
} // namespace mlpack
#endif
+44
View File
@@ -20,6 +20,7 @@
#include "format.hpp"
#include "dataset_mapper.hpp"
#include "image_info.hpp"
namespace mlpack {
namespace data /** Functions to load and save matrices and models. */ {
@@ -287,6 +288,47 @@ bool Load(const std::string& filename,
const bool fatal = false,
format f = format::autodetect);
/**
* Image load/save interfaces.
*/
#ifdef HAS_STB
/**
* Load the image file into the given matrix.
*
* @param filename Name of the image file.
* @param matrix Matrix to load the image into.
* @param info An object of ImageInfo class.
* @param fatal If an error should be reported as fatal (default false).
* @param transpose If true, transpose the matrix after loading.
* @return Boolean value indicating success or failure of load.
*/
template<typename eT>
bool Load(const std::string& filename,
arma::Mat<eT>& matrix,
ImageInfo& info,
const bool fatal = false,
const bool transpose = true);
/**
* Load the image file into the given matrix.
*
* @param files A vector consisting of filenames.
* @param matrix Matrix to save the image from.
* @param info An object of ImageInfo class.
* @param fatal If an error should be reported as fatal (default false).
* @param transpose If true, transpose the matrix after loading.
* @return Boolean value indicating success or failure of load.
*/
template<typename eT>
bool Load(const std::vector<std::string>& files,
arma::Mat<eT>& matrix,
ImageInfo& info,
const bool fatal = false,
const bool transpose = true);
#endif // HAS_STB.
} // namespace data
} // namespace mlpack
@@ -294,5 +336,7 @@ bool Load(const std::string& filename,
#include "load_model_impl.hpp"
// Include implementation of Load() for vectors.
#include "load_vec_impl.hpp"
// Include implementation of Load() for images.
#include "load_image_impl.hpp"
#endif
+148
View File
@@ -0,0 +1,148 @@
/**
* @file load_image_impl.hpp
* @author Mehul Kumar Nirala
*
* An image loading utility implementation.
*
* mlpack is free software; you may redistribute it and/or modify it under the
* terms of the 3-clause BSD license. You should have received a copy of the
* 3-clause BSD license along with mlpack. If not, see
* http://www.opensource.org/licenses/BSD-3-Clause for more information.
*/
#ifndef MLPACK_CORE_DATA_LOAD_IMAGE_IMPL_HPP
#define MLPACK_CORE_DATA_LOAD_IMAGE_IMPL_HPP
// In case it hasn't been included yet.
#include "load.hpp"
namespace mlpack {
namespace data {
#ifdef HAS_STB // Compile this only if stb is present.
// Image loading API.
template<typename eT>
bool Load(const std::string& filename,
arma::Mat<eT>& matrix,
ImageInfo& info,
const bool /* fatal */,
const bool transpose)
{
Timer::Start("loading_image");
unsigned char* image;
if (!ImageFormatSupported(filename))
{
std::ostringstream oss;
oss << "File type " << Extension(filename) << " not supported.\n";
oss << "Currently it supports ";
for (auto extension : loadFileTypes)
oss << " " << extension;
oss << std::endl;
throw std::runtime_error(oss.str());
return false;
}
stbi_set_flip_vertically_on_load(transpose);
// Temporary variables needed as stb_image.h supports int parameters.
int tempWidth, tempHeight, tempChannels;
// For grayscale images.
if (info.Channels() == 1)
{
image = stbi_load(filename.c_str(), &tempWidth, &tempHeight, &tempChannels,
STBI_grey);
}
else
{
image = stbi_load(filename.c_str(), &tempWidth, &tempHeight, &tempChannels,
STBI_rgb);
}
if (tempWidth <= 0 || tempHeight <= 0)
{
std::ostringstream oss;
oss << "Image '" << filename << "' not found." << std::endl;
free(image);
throw std::runtime_error(oss.str());
return false;
}
info.Width() = tempWidth;
info.Height() = tempHeight;
info.Channels() = tempChannels;
// Copy image into armadillo Mat.
matrix = arma::Mat<unsigned char>(image, info.Width() * info.Height() *
info.Channels(), 1, true, true);
// Free the image pointer.
free(image);
Timer::Stop("loading_image");
return true;
}
// Image loading API for multiple files.
template<typename eT>
bool Load(const std::vector<std::string>& files,
arma::Mat<eT>& matrix,
ImageInfo& info,
const bool fatal,
const bool transpose)
{
if (files.size() == 0)
{
std::ostringstream oss;
oss << "Files vector is empty." << std::endl;
throw std::runtime_error(oss.str());
return false;
}
arma::Mat<unsigned char> img;
bool status = Load(files[0], img, info, fatal, transpose);
// Decide matrix dimension using the image height and width.
matrix.set_size(info.Width() * info.Height() * info.Channels(), files.size());
matrix.col(0) = img;
for (size_t i = 1; i < files.size() ; i++)
{
arma::Mat<unsigned char> colImg(matrix.colptr(i), matrix.n_rows, 1,
false, true);
status &= Load(files[i], colImg, info, fatal, transpose);
}
return status;
}
#else // No STB.
template<typename eT>
bool Load(const std::string& filename,
arma::Mat<eT>& matrix,
ImageInfo& info,
const bool fatal = false,
const bool transpose = true)
{
throw std::runtime_error("Load(): HAS_STB is not defined, "
"so STB is not available and images cannot be loaded!");
}
template<typename eT>
bool Load(const std::vector<std::string>& files,
arma::Mat<eT>& matrix,
ImageInfo& info,
const bool fatal = false,
const bool transpose = true)
{
throw std::runtime_error("Load(): HAS_STB is not defined, "
"so STB is not available and images cannot be loaded!");
}
#endif // HAS_STB.
} // namespace data
} // namespace mlpack
#endif
+39
View File
@@ -19,6 +19,7 @@
#include <string>
#include "format.hpp"
#include "image_info.hpp"
namespace mlpack {
namespace data /** Functions to load and save matrices. */ {
@@ -90,6 +91,44 @@ bool Save(const std::string& filename,
const bool fatal = false,
format f = format::autodetect);
#ifdef HAS_STB
/**
* Save the image file from the given matrix.
*
* @param filename Name of the image file.
* @param matrix Matrix to save the image from.
* @param info An object of ImageInfo class.
* @param fatal If an error should be reported as fatal (default false).
* @param transpose If true, transpose the matrix after loading.
* @return Boolean value indicating success or failure of load.
*/
template<typename eT>
bool Save(const std::string& filename,
arma::Mat<eT>& matrix,
ImageInfo& info,
const bool fatal = false,
const bool transpose = true);
/**
* Save the image file from the given matrix.
*
* @param files A vector consisting of filenames.
* @param matrix Matrix to save the image from.
* @param info An object of ImageInfo class.
* @param fatal If an error should be reported as fatal (default false).
* @param transpose If true, transpose the matrix after loading.
* @return Boolean value indicating success or failure of load.
*/
template<typename eT>
bool Save(const std::vector<std::string>& files,
arma::Mat<eT>& matrix,
ImageInfo& info,
const bool fatal = false,
const bool transpose = true);
#endif // HAS_STB.
} // namespace data
} // namespace mlpack
+141
View File
@@ -283,6 +283,147 @@ bool Save(const std::string& filename,
}
}
#ifdef HAS_STB
// Image saving API.
template<typename eT>
bool Save(const std::string& filename,
arma::Mat<eT>& matrix,
ImageInfo& info,
const bool fatal,
const bool transpose)
{
Timer::Start("saving_image");
// We transpose by default. So, un-transpose if necessary.
if (!transpose)
matrix = arma::trans(matrix);
int tempWidth, tempHeight, tempChannels, tempQuality;
tempWidth = info.Width();
tempHeight = info.Height();
tempChannels = info.Channels();
tempQuality = info.Quality();
if (!ImageFormatSupported(filename, true))
{
std::ostringstream oss;
oss << "File type " << Extension(filename) << " not supported.\n";
oss << "Currently it supports ";
for (auto extension : saveFileTypes)
oss << ", " << extension;
oss << std::endl;
throw std::runtime_error(oss.str());
return false;
}
if (matrix.n_cols > 1)
{
std::cout << "Input Matrix contains more than 1 image." << std::endl;
std::cout << "Only the firstimage will be saved!" << std::endl;
}
stbi_flip_vertically_on_write(transpose);
bool status = false;
try
{
unsigned char* image = matrix.memptr();
if ("png" == Extension(filename))
{
status = stbi_write_png(filename.c_str(), tempWidth, tempHeight,
tempChannels, image, tempWidth * tempChannels);
}
else if ("bmp" == Extension(filename))
{
status = stbi_write_bmp(filename.c_str(), tempWidth, tempHeight,
tempChannels, image);
}
else if ("tga" == Extension(filename))
{
status = stbi_write_tga(filename.c_str(), tempWidth, tempHeight,
tempChannels, image);
}
else if ("hdr" == Extension(filename))
{
status = stbi_write_hdr(filename.c_str(), tempWidth, tempHeight,
tempChannels, reinterpret_cast<float*>(image));
}
else if ("jpg" == Extension(filename))
{
status = stbi_write_jpg(filename.c_str(), tempWidth, tempHeight,
tempChannels, image, tempQuality);
}
}
catch (std::exception& e)
{
Timer::Stop("saving_image");
if (fatal)
Log::Fatal << e.what() << std::endl;
Log::Warn << e.what() << std::endl;
return false;
}
Timer::Stop("saving_image");
return status;
}
// Image saving API for multiple files.
template<typename eT>
bool Save(const std::vector<std::string>& files,
arma::Mat<eT>& matrix,
ImageInfo& info,
const bool fatal,
const bool transpose)
{
if (files.size() == 0)
{
std::ostringstream oss;
oss << "Files vector is empty." << std::endl;
throw std::runtime_error(oss.str());
return false;
}
// We transpose by default. So, un-transpose if necessary.
if (!transpose)
matrix = arma::trans(matrix);
arma::Mat<unsigned char> img;
bool status = Save(files[0], img, info, fatal, transpose);
// Decide matrix dimension using the image height and width.
matrix.set_size(info.Width() * info.Height() * info.Channels(), files.size());
matrix.col(0) = img;
for (size_t i = 1; i < files.size() ; i++)
{
arma::Mat<unsigned char> colImg(matrix.colptr(i), matrix.n_rows, 1,
false, true);
status &= Save(files[i], colImg, info, fatal, transpose);
}
return status;
}
#else
template<typename eT>
bool Save(const std::string& filename,
arma::Mat<eT>& matrix,
ImageInfo& info,
const bool fatal = false,
const bool transpose = true)
{
throw std::runtime_error("Save(): HAS_STB is not defined, "
"so STB is not available and images cannot be saved!");
}
template<typename eT>
bool Save(const std::vector<std::string>& files,
arma::Mat<eT>& matrix,
ImageInfo& info,
const bool fatal = false,
const bool transpose = true)
{
throw std::runtime_error("Save(): HAS_STB is not defined, "
"so STB is not available and images cannot be saved!");
}
#endif // HAS_STB.
} // namespace data
} // namespace mlpack
@@ -0,0 +1,19 @@
# Define the files we need to compile
# Anything not in this list will not be compiled into mlpack.
set(SOURCES
min_max_scaler.hpp
max_abs_scaler.hpp
standard_scaler.hpp
mean_normalization.hpp
pca_whitening.hpp
zca_whitening.hpp
)
# Add directory name to sources.
set(DIR_SRCS)
foreach(file ${SOURCES})
set(DIR_SRCS ${DIR_SRCS} ${CMAKE_CURRENT_SOURCE_DIR}/${file})
endforeach()
# Append sources (with directory name) to list of all mlpack sources (used at
# the parent scope).
set(MLPACK_SRCS ${MLPACK_SRCS} ${DIR_SRCS} PARENT_SCOPE)
@@ -0,0 +1,122 @@
/**
* @file max_abs_scaler.hpp
* @author Jeffin Sam
*
* MaxAbsScaler class to scale features.
*
* mlpack is free software; you may redistribute it and/or modify it under the
* terms of the 3-clause BSD license. You should have received a copy of the
* 3-clause BSD license along with mlpack. If not, see
* http://www.opensource.org/licenses/BSD-3-Clause for more information.
*/
#ifndef MLPACK_CORE_DATA_MAX_ABS_SCALE_HPP
#define MLPACK_CORE_DATA_MAX_ABS_SCALE_HPP
#include <mlpack/prereqs.hpp>
namespace mlpack {
namespace data {
/**
* A simple MaxAbs Scaler class.
*
* Given an input dataset this class helps you to scale each
* feature by its maximum absolute value.
*
* \[z = x / max(abs(x))\]
*
* where max(abs(x)) is maximum absolute value of feature.
*
* @code
* arma::mat input;
* Load("train.csv", input);
* arma::mat output;
*
* // Fit the features.
* MaxAbsScaler scale;
* scale.Fit(input)
*
* // Scale the features.
* scale.Transform(input, output);
*
* // Retransform the input.
* scale.InverseTransform(output, input);
* @endcode
*/
class MaxAbsScaler
{
public:
/**
* Function to fit features, to find out the min max and scale.
*
* @param input Dataset to fit.
*/
template<typename MatType>
void Fit(const MatType& input)
{
itemMin = arma::min(input, 1);
itemMax = arma::max(input, 1);
scale = arma::max(arma::abs(itemMin), arma::abs(itemMax));
// Handling zeros in scale vector.
scale.for_each([](arma::vec::elem_type& val) { val =
(val == 0) ? 1 : val; });
}
/**
* Function to scale features.
*
* @param input Dataset to scale features.
* @param output Output matrix with scaled features.
*/
template<typename MatType>
void Transform(const MatType& input, MatType& output)
{
if (scale.is_empty())
{
throw std::runtime_error("Call Fit() before Transform(), please"
" refer to the documentation.");
}
output.copy_size(input);
output = input.each_col() / scale;
}
/**
* Function to retrieve original dataset.
*
* @param input Scaled dataset.
* @param output Output matrix with original Dataset.
*/
template<typename MatType>
void InverseTransform(const MatType& input, MatType& output)
{
output.copy_size(input);
output = input.each_col() % scale;
}
//! Get the Min row vector.
const arma::vec& ItemMin() const { return itemMin; }
//! Get the Max row vector.
const arma::vec& ItemMax() const { return itemMax; }
//! Get the Scale row vector.
const arma::vec& Scale() const { return scale; }
template<typename Archive>
void serialize(Archive& ar, const unsigned int /* version */)
{
ar & BOOST_SERIALIZATION_NVP(itemMin);
ar & BOOST_SERIALIZATION_NVP(itemMax);
ar & BOOST_SERIALIZATION_NVP(scale);
}
private:
// Vector which holds minimum of each feature.
arma::vec itemMin;
// Vector which holds maximum of each feature.
arma::vec itemMax;
// Vector which is used to scale up each feature.
arma::vec scale;
}; // class MaxAbsScaler
} // namespace data
} // namespace mlpack
#endif
@@ -0,0 +1,129 @@
/**
* @file mean_normalization.hpp
* @author Jeffin Sam
*
* MeanNormalization class to scale features.
*
* mlpack is free software; you may redistribute it and/or modify it under the
* terms of the 3-clause BSD license. You should have received a copy of the
* 3-clause BSD license along with mlpack. If not, see
* http://www.opensource.org/licenses/BSD-3-Clause for more information.
*/
#ifndef MLPACK_CORE_DATA_MEAN_NORMALIZATION_HPP
#define MLPACK_CORE_DATA_MEAN_NORMALIZATION_HPP
#include <mlpack/prereqs.hpp>
namespace mlpack {
namespace data {
/**
* A simple Mean Normalization class
*
* Given an input dataset this class helps you to normalize each
* feature.
*
* \[z = x - average(x) / (max(x) - min(x))\]
*
* where x is an original value,z is the normalized value.
*
* @code
* arma::mat input;
* Load("train.csv", input);
* arma::mat output;
*
* // Fit the features.
* MeanNormalization scale;
* scale.Fit(input)
*
* // Scale the features.
* scale.Transform(input, output);
*
* // Retransform the input.
* scale.InverseTransform(output, input);
* @endcode
*/
class MeanNormalization
{
public:
/**
* Function to fit features, to find out the min max and scale.
*
* @param input Dataset to fit.
*/
template<typename MatType>
void Fit(const MatType& input)
{
itemMean = arma::mean(input, 1);
itemMin = arma::min(input, 1);
itemMax = arma::max(input, 1);
scale = itemMax - itemMin;
// Handling zeros in scale vector.
scale.for_each([](arma::vec::elem_type& val) { val =
(val == 0) ? 1 : val; });
}
/**
* Function to scale features.
*
* @param input Dataset to scale features.
* @param output Output matrix with scaled features.
*/
template<typename MatType>
void Transform(const MatType& input, MatType& output)
{
if (itemMean.is_empty() || scale.is_empty())
{
throw std::runtime_error("Call Fit() before Transform(), please"
" refer to the documentation.");
}
output.copy_size(input);
output = (input.each_col() - itemMean).each_col() / scale;
}
/**
* Function to retrieve original dataset.
*
* @param input Scaled dataset.
* @param output Output matrix with original Dataset.
*/
template<typename MatType>
void InverseTransform(const MatType& input, MatType& output)
{
output.copy_size(input);
output = (input.each_col() % scale).each_col() + itemMean;
}
//! Get the Mean row vector.
const arma::vec& ItemMean() const { return itemMean; }
//! Get the Min row vector.
const arma::vec& ItemMin() const { return itemMin; }
//! Get the Max row vector.
const arma::vec& ItemMax() const { return itemMax; }
//! Get the Scale row vector.
const arma::vec& Scale() const { return scale; }
template<typename Archive>
void serialize(Archive& ar, const unsigned int /* version */)
{
ar & BOOST_SERIALIZATION_NVP(itemMin);
ar & BOOST_SERIALIZATION_NVP(itemMax);
ar & BOOST_SERIALIZATION_NVP(scale);
ar & BOOST_SERIALIZATION_NVP(itemMean);
}
private:
// Vector which holds mean of each feature.
arma::vec itemMean;
// Vector which holds minimum of each feature.
arma::vec itemMin;
// Vector which holds maximum of each feature.
arma::vec itemMax;
// Vector which is used to scale up each feature.
arma::vec scale;
}; // class MeanNormalization
} // namespace data
} // namespace mlpack
#endif
@@ -0,0 +1,159 @@
/**
* @file min_max_scaler.hpp
* @author Jeffin Sam
*
* MinMaxScaler class to scale features.
*
* mlpack is free software; you may redistribute it and/or modify it under the
* terms of the 3-clause BSD license. You should have received a copy of the
* 3-clause BSD license along with mlpack. If not, see
* http://www.opensource.org/licenses/BSD-3-Clause for more information.
*/
#ifndef MLPACK_CORE_DATA_SCALE_HPP
#define MLPACK_CORE_DATA_SCALE_HPP
#include <mlpack/prereqs.hpp>
namespace mlpack {
namespace data {
/**
* A simple MinMax Scaler class
*
* Given an input dataset this class helps you to scale each
* feature to a given range.
*
* \[z = scale * x + scaleMin - min(x) * scale\]
* \[scale = (scaleMax - scaleMin) / (max(x) - min(x))\]
*
* where scaleMin, scaleMax = feature_range and min(x), max(x)
* are the minimum and maximum value of x respectively.
*
* @code
* arma::mat input;
* Load("train.csv", input);
* arma::mat output;
*
* // Fit the features.
* MinMaxScaler scale;
* scale.Fit(input)
*
* // Scale the features.
* scale.Transform(input, output);
*
* // Retransform the input.
* scale.InverseTransform(output, input);
* @endcode
*/
class MinMaxScaler
{
public:
/**
* Default constructor
*
* @param min Lower range of scaling.
* @param max Upper range of scaling.
*/
MinMaxScaler(const double min = 0, const double max = 1)
{
scaleMin = min;
scaleMax = max;
// Ensure scaleMin is smaller than scaleMax.
if (scaleMin > scaleMax)
{
throw std::runtime_error("Range is not appropriate");
}
}
/**
* Function to fit features, to find out the min max and scale.
*
* @param input Dataset to fit.
*/
template<typename MatType>
void Fit(const MatType& input)
{
itemMin = arma::min(input, 1);
itemMax = arma::max(input, 1);
scale = itemMax - itemMin;
// Handle zeros in scale vector.
scale.for_each([](arma::vec::elem_type& val) { val =
(val == 0) ? 1 : val; });
scale = (scaleMax - scaleMin) / scale;
scalerowmin.copy_size(itemMin);
scalerowmin.fill(scaleMin);
scalerowmin = scalerowmin - itemMin % scale;
}
/**
* Function to scale features.
*
* @param input Dataset to scale features.
* @param output Output matrix with scaled features.
*/
template<typename MatType>
void Transform(const MatType& input, MatType& output)
{
if (scalerowmin.is_empty() || scale.is_empty())
{
throw std::runtime_error("Call Fit() before Transform(), please"
" refer to the documentation.");
}
output.copy_size(input);
output = (input.each_col() % scale).each_col() + scalerowmin;
}
/**
* Function to retrieve original dataset.
*
* @param input Scaled dataset.
* @param output Output matrix with original Dataset.
*/
template<typename MatType>
void InverseTransform(const MatType& input, MatType& output)
{
output.copy_size(input);
output = (input.each_col() - scalerowmin).each_col() / scale;
}
//! Get the Min row vector.
const arma::vec& ItemMin() const { return itemMin; }
//! Get the Max row vector.
const arma::vec& ItemMax() const { return itemMax; }
//! Get the Scale row vector.
const arma::vec& Scale() const { return scale; }
//! Get the upper range parameter.
double ScaleMax() const { return scaleMax; }
//! Get the lower range parameter.
double ScaleMin() const { return scaleMin; }
template<typename Archive>
void serialize(Archive& ar, const unsigned int /* version */)
{
ar & BOOST_SERIALIZATION_NVP(itemMin);
ar & BOOST_SERIALIZATION_NVP(itemMax);
ar & BOOST_SERIALIZATION_NVP(scale);
ar & BOOST_SERIALIZATION_NVP(scaleMin);
ar & BOOST_SERIALIZATION_NVP(scaleMax);
ar & BOOST_SERIALIZATION_NVP(scalerowmin);
}
private:
// Vector which holds minimum of each feature.
arma::vec itemMin;
// Vector which holds maximum of each feature.
arma::vec itemMax;
// Scale vector which is used to scale up each feature.
arma::vec scale;
// Lower value for range.
double scaleMin;
// Upper value for range.
double scaleMax;
// Column vector of scalemin
arma::vec scalerowmin;
}; // class MinMaxScaler
} // namespace data
} // namespace mlpack
#endif
@@ -0,0 +1,145 @@
/**
* @file pca_whitening.hpp
* @author Jeffin Sam
*
* Whitening scaling to scale features, Using PCA Whitening.
*
* mlpack is free software; you may redistribute it and/or modify it under the
* terms of the 3-clause BSD license. You should have received a copy of the
* 3-clause BSD license along with mlpack. If not, see
* http://www.opensource.org/licenses/BSD-3-Clause for more information.
*/
#ifndef MLPACK_CORE_DATA_PCA_WHITENING_SCALE_HPP
#define MLPACK_CORE_DATA_PCA_WHITENING_SCALE_HPP
#include <mlpack/prereqs.hpp>
#include <mlpack/core/math/lin_alg.hpp>
namespace mlpack {
namespace data {
/**
* A simple PCAWhitening class.
*
* Whitens a matrix using the eigendecomposition of the covariance matrix.
* Whitening means the covariance matrix of the result is the identity matrix.
*
* For whitening related formula and more info, check the link below.
* http://ufldl.stanford.edu/tutorial/unsupervised/PCAWhitening/
*
* @code
* arma::mat input;
* Load("train.csv", input);
* arma::mat output;
*
* // Fit the features.
* PCAWhitening scale;
* scale.Fit(input)
*
* // Scale the features.
* scale.Transform(input, output);
*
* // Retransform the input.
* scale.InverseTransform(output, input);
* @endcode
*/
class PCAWhitening
{
public:
/**
* A constructor to set the regularization parameter.
*
* @param eps Regularization parameter.
*/
PCAWhitening(double eps = 0.00005)
{
epsilon = eps;
// Ensure scaleMin is smaller than scaleMax.
if (epsilon < 0)
{
throw std::runtime_error("Regularization parameter is not correct");
}
}
/**
* Function to fit features, to find out the min max and scale.
*
* @param input Dataset to fit.
*/
template<typename MatType>
void Fit(const MatType& input)
{
itemMean = arma::mean(input, 1);
// Get eigenvectors and eigenvalues of covariance of input matrix.
eig_sym(eigenValues, eigenVectors, mlpack::math::ColumnCovariance(
input.each_col() - itemMean));
eigenValues += epsilon;
}
/**
* Function for PCA whitening.
*
* @param input Dataset to scale features.
* @param output Output matrix with whitened features.
*/
template<typename MatType>
void Transform(const MatType& input, MatType& output)
{
if (eigenValues.is_empty() || eigenVectors.is_empty())
{
throw std::runtime_error("Call Fit() before Transform(), please"
" refer to the documentation.");
}
output.copy_size(input);
output = (input.each_col() - itemMean);
output = arma::diagmat(1.0 / (arma::sqrt(eigenValues))) * eigenVectors.t()
* output;
}
/**
* Function to retrieve original dataset.
*
* @param input Scaled dataset.
* @param output Output matrix with original Dataset.
*/
template<typename MatType>
void InverseTransform(const MatType& input, MatType& output)
{
output = arma::diagmat(arma::sqrt(eigenValues)) * inv(eigenVectors.t())
* input;
output = (output.each_col() + itemMean);
}
//! Get the mean row vector.
const arma::vec& ItemMean() const { return itemMean; }
//! Get the eigenvalues vector.
const arma::vec& EigenValues() const { return eigenValues; }
//! Get the eigenvector.
const arma::mat& EigenVectors() const { return eigenVectors; }
//! Get the regularization parameter.
const double& Epsilon() const { return epsilon; }
template<typename Archive>
void serialize(Archive& ar, const unsigned int /* version */)
{
ar & BOOST_SERIALIZATION_NVP(eigenValues);
ar & BOOST_SERIALIZATION_NVP(eigenVectors);
ar & BOOST_SERIALIZATION_NVP(itemMean);
ar & BOOST_SERIALIZATION_NVP(epsilon);
}
private:
// Vector which holds mean of each feature.
arma::vec itemMean;
// Mat which hold the eigenvectors.
arma::mat eigenVectors;
// Regularization Paramter.
double epsilon;
// Vector which hold the eigenvalues.
arma::vec eigenValues;
}; // class PCAWhitening
} // namespace data
} // namespace mlpack
#endif
@@ -0,0 +1,118 @@
/**
* @file standard_scaler.hpp
* @author Jeffin Sam
*
* StandardScaler class to scale features.
*
* mlpack is free software; you may redistribute it and/or modify it under the
* terms of the 3-clause BSD license. You should have received a copy of the
* 3-clause BSD license along with mlpack. If not, see
* http://www.opensource.org/licenses/BSD-3-Clause for more information.
*/
#ifndef MLPACK_CORE_DATA_STANDARD_SCALE_HPP
#define MLPACK_CORE_DATA_STANDARD_SCALE_HPP
#include <mlpack/prereqs.hpp>
namespace mlpack {
namespace data {
/**
* A simple Standard Scaler class
*
* Given an input dataset this class helps you to Standardize features
* by removing the mean and scaling to unit variance.
*
* \[z = (x - u) / s\]
*
* where u is the mean of the training samples and s is the standard deviation
* of the training samples.
*
* @code
* arma::mat input;
* Load("train.csv", input);
* arma::mat output;
*
* // Fit the features.
* StandardScaler scale;
* scale.Fit(input)
*
* // Scale the features.
* scale.Transform(input, output);
*
* // Retransform the input.
* scale.InverseTransform(output, input);
* @endcode
*/
class StandardScaler
{
public:
/**
* Function to fit features, to find out the min max and scale.
*
* @param input Dataset to fit.
*/
template<typename MatType>
void Fit(const MatType& input)
{
itemMean = arma::mean(input, 1);
itemStdDev = arma::stddev(input, 1, 1);
// Handle zeros in scale vector.
itemStdDev.for_each([](arma::vec::elem_type& val) { val =
(val == 0) ? 1 : val; });
}
/**
* Function to scale features.
*
* @param input Dataset to scale features.
* @param output Output matrix with scaled features.
*/
template<typename MatType>
void Transform(const MatType& input, MatType& output)
{
if (itemMean.is_empty() || itemStdDev.is_empty())
{
throw std::runtime_error("Call Fit() before Transform(), please"
" refer to the documentation.");
}
output.copy_size(input);
output = (input.each_col() - itemMean).each_col() / itemStdDev;
}
/**
* Function to retrieve original dataset.
*
* @param input Scaled dataset.
* @param output Output matrix with original Dataset.
*/
template<typename MatType>
void InverseTransform(const MatType& input, MatType& output)
{
output.copy_size(input);
output = (input.each_col() % itemStdDev).each_col() + itemMean;
}
//! Get the mean row vector.
const arma::vec& ItemMean() const { return itemMean; }
//! Get the standard deviation row vector.
const arma::vec& ItemStdDev() const { return itemStdDev; }
template<typename Archive>
void serialize(Archive& ar, const unsigned int /* version */)
{
ar & BOOST_SERIALIZATION_NVP(itemMean);
ar & BOOST_SERIALIZATION_NVP(itemStdDev);
}
private:
// Vector which holds mean of each feature.
arma::vec itemMean;
// Vector which holds standard devation of each feature.
arma::vec itemStdDev;
}; // class StandardScaler
} // namespace data
} // namespace mlpack
#endif
@@ -0,0 +1,121 @@
/**
* @file zca_whitening.hpp
* @author Jeffin Sam
*
* Whitening scaling to scale features, Using ZCA Whitening.
*
* mlpack is free software; you may redistribute it and/or modify it under the
* terms of the 3-clause BSD license. You should have received a copy of the
* 3-clause BSD license along with mlpack. If not, see
* http://www.opensource.org/licenses/BSD-3-Clause for more information.
*/
#ifndef MLPACK_CORE_DATA_ZCA_WHITENING_SCALE_HPP
#define MLPACK_CORE_DATA_ZCA_WHITENING_SCALE_HPP
#include <mlpack/prereqs.hpp>
#include <mlpack/core/math/lin_alg.hpp>
#include <mlpack/core/data/scaler_methods/pca_whitening.hpp>
namespace mlpack {
namespace data {
/**
* A simple ZCAWhitening class.
*
* Whitens a matrix using the eigendecomposition of the covariance matrix.
* Whitening means the covariance matrix of the result is the identity matrix.
*
* For whitening related formula and more info, check the link below.
* http://ufldl.stanford.edu/tutorial/unsupervised/PCAWhitening/
*
* @code
* arma::mat input;
* Load("train.csv", input);
* arma::mat output;
*
* // Fit the features.
* ZCAWhitening scale;
* scale.Fit(input)
*
* // Scale the features.
* scale.Transform(input, output);
*
* // Retransform the input.
* scale.InverseTransform(output, input);
* @endcode
*/
class ZCAWhitening
{
public:
/**
* A constructor to set the regularization parameter.
*
* @param eps Regularization parameter.
*/
ZCAWhitening(double eps = 0.00005)
{
pca = new data::PCAWhitening(eps);
}
/**
* Function to fit features, to find out the min max and scale.
*
* @param input Dataset to fit.
*/
template<typename MatType>
void Fit(const MatType& input)
{
pca->Fit(input);
}
/**
* Function for ZCA whitening.
*
* @param input Dataset to scale features.
* @param output Output matrix with whitened features.
*/
template<typename MatType>
void Transform(const MatType& input, MatType& output)
{
pca->Transform(input, output);
output = pca->EigenVectors() * output;
}
/**
* Function to retrieve original dataset.
*
* @param input Scaled dataset.
* @param output Output matrix with original Dataset.
*/
template<typename MatType>
void InverseTransform(const MatType& input, MatType& output)
{
output = inv(pca->EigenVectors()) * arma::diagmat(arma::sqrt(
pca->EigenValues())) * inv(pca->EigenVectors().t()) * input;
output = (output.each_col() + pca->ItemMean());
}
//! Get the mean row vector.
const arma::vec& ItemMean() const { return pca->ItemMean(); }
//! Get the eigenvalues vector.
const arma::vec& EigenValues() const { return pca->EigenValues(); }
//! Get the eigenvector.
const arma::mat& EigenVectors() const { return pca->EigenVectors(); }
//! Get the regularization parameter.
double Epsilon() const { return pca->Epsilon(); }
template<typename Archive>
void serialize(Archive& ar, const unsigned int /* version */)
{
ar & BOOST_SERIALIZATION_NVP(pca);
}
private:
// A pointer to PcaWhitening Class.
PCAWhitening* pca;
}; // class ZCAWhitening
} // namespace data
} // namespace mlpack
#endif
@@ -168,6 +168,12 @@ class GaussianDistribution
void Covariance(arma::mat&& covariance);
//! Return the invCov.
const arma::mat& InvCov() const { return invCov; }
//! Return the logDetCov.
double LogDetCov() const { return logDetCov; }
/**
* Serialize the distribution.
*/
+7
View File
@@ -63,6 +63,13 @@ inline void FixedRandomSeed()
srand((unsigned int) seed);
arma::arma_rng::set_seed(seed);
}
inline void CustomRandomSeed(const size_t seed)
{
randGen.seed((uint32_t) seed);
srand((unsigned int) seed);
arma::arma_rng::set_seed(seed);
}
#endif
/**
+1 -1
View File
@@ -61,7 +61,7 @@ typename VecTypeA::elem_type LMetric<2, true>::Evaluate(
const VecTypeA& a,
const VecTypeB& b)
{
return sqrt(arma::accu(square(a - b)));
return arma::norm(a - b, 2);
}
template<>
@@ -56,6 +56,18 @@ DualTreeTraverser<RuleType>::Traverse(
// Store the current traversal info.
traversalInfo = rule.TraversalInfo();
// If both nodes are root nodes, just score them.
if (queryNode.Parent() == NULL && referenceNode.Parent() == NULL)
{
const double rootScore = rule.Score(queryNode, referenceNode);
// If root score is DBL_MAX, don't recurse.
if (rootScore == DBL_MAX)
{
++numPrunes;
return;
}
}
// If both are leaves, we must evaluate the base case.
if (queryNode.IsLeaf() && referenceNode.IsLeaf())
{
@@ -57,6 +57,18 @@ SingleTreeTraverser<RuleType>::Traverse(
}
else
{
// If it's the root node, just score it.
if (referenceNode.Parent() == NULL)
{
const double rootScore = rule.Score(queryIndex, referenceNode);
// If root score is DBL_MAX, don't recurse into that node.
if (rootScore == DBL_MAX)
{
++numPrunes;
return;
}
}
// If either score is DBL_MAX, we do not recurse into that node.
double leftScore = rule.Score(queryIndex, *referenceNode.Left());
double rightScore = rule.Score(queryIndex, *referenceNode.Right());
@@ -238,6 +238,20 @@ class CoverTree
*/
CoverTree(CoverTree&& other);
/**
* Copy the given Cover Tree.
*
* @param other The tree to be copied.
*/
CoverTree& operator=(const CoverTree& other);
/**
* Take ownership of the given Cover Tree.
*
* @param other The tree to take ownership of.
*/
CoverTree& operator=(CoverTree&& other);
/**
* Create a cover tree from a boost::serialization archive.
*/
@@ -21,6 +21,18 @@
namespace mlpack {
namespace tree {
// Build the statistics, bottom-up.
template<typename TreeType, typename StatisticType>
void BuildStatistics(TreeType* node)
{
// Recurse first.
for (size_t i = 0; i < node->NumChildren(); ++i)
BuildStatistics<TreeType, StatisticType>(&node->Child(i));
// Now build the statistic.
node->Stat() = StatisticType(*node);
}
// Create the cover tree.
template<
typename MetricType,
@@ -88,9 +100,8 @@ CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::CoverTree(
{
children.push_back(&(old->Child(i)));
// Set its parent correctly, and rebuild the statistic.
// Set its parent correctly.
old->Child(i).Parent() = this;
old->Child(i).Stat() = StatisticType(old->Child(i));
}
// Remove all the children so they don't get erased.
@@ -104,14 +115,19 @@ CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::CoverTree(
}
// Use the furthest descendant distance to determine the scale of the root
// node.
if (furthestDescendantDistance == 0.0)
// node. Note that if the root is a leaf, we can have scale INT_MIN, but if
// it *isn't* a leaf, we need to mark the scale as one higher than INT_MIN, so
// that the recursions don't fail.
if (furthestDescendantDistance == 0.0 && dataset.n_cols == 1)
scale = INT_MIN;
else if (furthestDescendantDistance == 0.0)
scale = INT_MIN + 1;
else
scale = (int) ceil(log(furthestDescendantDistance) / log(base));
// Initialize statistic.
stat = StatisticType(*this);
// Initialize statistics recursively after the entire tree construction is
// complete.
BuildStatistics<CoverTree, StatisticType>(this);
Log::Info << distanceComps << " distance computations during tree "
<< "construction." << std::endl;
@@ -181,8 +197,6 @@ CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::CoverTree(
// Set its parent correctly.
old->Child(i).Parent() = this;
// Rebuild the statistic.
old->Child(i).Stat() = StatisticType(old->Child(i));
}
// Remove all the children so they don't get erased.
@@ -196,14 +210,19 @@ CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::CoverTree(
}
// Use the furthest descendant distance to determine the scale of the root
// node.
if (furthestDescendantDistance == 0.0)
// node. Note that if the root is a leaf, we can have scale INT_MIN, but if
// it *isn't* a leaf, we need to mark the scale as one higher than INT_MIN, so
// that the recursions don't fail.
if (furthestDescendantDistance == 0.0 && dataset.n_cols == 1)
scale = INT_MIN;
else if (furthestDescendantDistance == 0.0)
scale = INT_MIN + 1;
else
scale = (int) ceil(log(furthestDescendantDistance) / log(base));
// Initialize statistic.
stat = StatisticType(*this);
// Initialize statistics recursively after the entire tree construction is
// complete.
BuildStatistics<CoverTree, StatisticType>(this);
Log::Info << distanceComps << " distance computations during tree "
<< "construction." << std::endl;
@@ -272,9 +291,8 @@ CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::CoverTree(
{
children.push_back(&(old->Child(i)));
// Set its parent correctly, and rebuild the statistic.
// Set its parent correctly.
old->Child(i).Parent() = this;
old->Child(i).Stat() = StatisticType(old->Child(i));
}
// Remove all the children so they don't get erased.
@@ -288,14 +306,19 @@ CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::CoverTree(
}
// Use the furthest descendant distance to determine the scale of the root
// node.
if (furthestDescendantDistance == 0.0)
// node. Note that if the root is a leaf, we can have scale INT_MIN, but if
// it *isn't* a leaf, we need to mark the scale as one higher than INT_MIN, so
// that the recursions don't fail.
if (furthestDescendantDistance == 0.0 && dataset->n_cols == 1)
scale = INT_MIN;
else if (furthestDescendantDistance == 0.0)
scale = INT_MIN + 1;
else
scale = (int) ceil(log(furthestDescendantDistance) / log(base));
// Initialize statistic.
stat = StatisticType(*this);
// Initialize statistics recursively after the entire tree construction is
// complete.
BuildStatistics<CoverTree, StatisticType>(this);
Log::Info << distanceComps << " distance computations during tree "
<< "construction." << std::endl;
@@ -363,9 +386,8 @@ CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::CoverTree(
{
children.push_back(&(old->Child(i)));
// Set its parent correctly, and rebuild the statistic.
// Set its parent correctly.
old->Child(i).Parent() = this;
old->Child(i).Stat() = StatisticType(old->Child(i));
}
// Remove all the children so they don't get erased.
@@ -379,14 +401,19 @@ CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::CoverTree(
}
// Use the furthest descendant distance to determine the scale of the root
// node.
if (furthestDescendantDistance == 0.0)
// node. Note that if the root is a leaf, we can have scale INT_MIN, but if
// it *isn't* a leaf, we need to mark the scale as one higher than INT_MIN, so
// that the recursions don't fail.
if (furthestDescendantDistance == 0.0 && dataset->n_cols == 1)
scale = INT_MIN;
else if (furthestDescendantDistance == 0.0)
scale = INT_MIN + 1;
else
scale = (int) ceil(log(furthestDescendantDistance) / log(base));
// Initialize statistic.
stat = StatisticType(*this);
// Initialize statistics recursively after the entire tree construction is
// complete.
BuildStatistics<CoverTree, StatisticType>(this);
Log::Info << distanceComps << " distance computations during tree "
<< "construction." << std::endl;
@@ -429,15 +456,11 @@ CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::CoverTree(
{
this->scale = INT_MIN;
numDescendants = 1;
stat = StatisticType(*this);
return;
}
// Otherwise, create the children.
CreateChildren(indices, distances, nearSetSize, farSetSize, usedSetSize);
// Initialize statistic.
stat = StatisticType(*this);
}
// Manually create a cover tree node.
@@ -472,11 +495,9 @@ CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::CoverTree(
// If necessary, create a local metric.
if (localMetric)
this->metric = new MetricType();
// Initialize the statistic.
stat = StatisticType(*this);
}
// Copy Constructor.
template<
typename MetricType,
typename StatisticType,
@@ -495,9 +516,9 @@ CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::CoverTree(
parent(other.parent),
parentDistance(other.parentDistance),
furthestDescendantDistance(other.furthestDescendantDistance),
localMetric(false),
localMetric(other.localMetric),
localDataset(other.parent == NULL && other.localDataset),
metric(other.metric),
metric((other.localMetric ? new MetricType() : other.metric)),
distanceComps(0)
{
// Copy each child by hand.
@@ -527,6 +548,76 @@ CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::CoverTree(
}
}
// Copy Assignment.
template<
typename MetricType,
typename StatisticType,
typename MatType,
typename RootPointPolicy
>
CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>&
CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::
operator=(const CoverTree& other)
{
if (this == &other)
return *this;
// Freeing memory that will not be used anymore.
if (localDataset)
delete dataset;
if (localMetric)
delete metric;
for (size_t i = 0; i < children.size(); ++i)
delete children[i];
children.clear();
dataset = ((other.parent == NULL && other.localDataset) ?
new MatType(*other.dataset) : other.dataset);
point = other.point;
scale = other.scale;
base = other.base;
stat = other.stat;
numDescendants = other.numDescendants;
parent = other.parent;
parentDistance = other.parentDistance;
furthestDescendantDistance = other.furthestDescendantDistance;
localMetric = other.localMetric;
localDataset = (other.parent == NULL && other.localDataset);
metric = (other.localMetric ? new MetricType() : other.metric);
distanceComps = 0;
// Copy each child by hand.
for (size_t i = 0; i < other.NumChildren(); ++i)
{
children.push_back(new CoverTree(other.Child(i)));
children[i]->Parent() = this;
}
// Propagate matrix, but only if we are the root.
if (parent == NULL && localDataset)
{
std::queue<CoverTree*> queue;
for (size_t i = 0; i < NumChildren(); ++i)
queue.push(children[i]);
while (!queue.empty())
{
CoverTree* node = queue.front();
queue.pop();
node->dataset = dataset;
for (size_t i = 0; i < node->NumChildren(); ++i)
queue.push(node->children[i]);
}
}
return *this;
}
// Move Constructor.
template<
typename MetricType,
typename StatisticType,
@@ -567,6 +658,64 @@ CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::CoverTree(
other.metric = NULL;
}
// Move Assignment.
template<
typename MetricType,
typename StatisticType,
typename MatType,
typename RootPointPolicy
>
CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>&
CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::
operator=(CoverTree&& other)
{
if (this == &other)
return *this;
// Freeing memory that will not be used anymore.
if (localDataset)
delete dataset;
if (localMetric)
delete metric;
for (size_t i = 0; i < children.size(); ++i)
delete children[i];
dataset = other.dataset;
point = other.point;
children = std::move(other.children);
scale = other.scale;
base = other.base;
stat = std::move(other.stat);
numDescendants = other.numDescendants;
parent = other.parent;
parentDistance = other.parentDistance;
furthestDescendantDistance = other.furthestDescendantDistance;
localMetric = other.localMetric;
localDataset = other.localDataset;
metric = other.metric;
distanceComps = other.distanceComps;
// Set proper parent pointer.
for (size_t i = 0; i < children.size(); ++i)
children[i]->Parent() = this;
other.dataset = NULL;
other.point = 0;
other.scale = INT_MIN;
other.base = 0;
other.numDescendants = 0;
other.parent = NULL;
other.parentDistance = 0;
other.furthestDescendantDistance = 0;
other.localMetric = false;
other.localDataset = false;
other.metric = NULL;
return *this;
}
// Construct from a boost::serialization archive.
template<
typename MetricType,
@@ -907,8 +1056,8 @@ CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::
other.Dataset().col(other.Point()));
math::RangeType<ElemType> result;
result.Lo() = distance - furthestDescendantDistance -
other.FurthestDescendantDistance();
result.Lo() = std::max(distance - furthestDescendantDistance -
other.FurthestDescendantDistance(), 0.0);
result.Hi() = distance + furthestDescendantDistance +
other.FurthestDescendantDistance();
@@ -930,8 +1079,8 @@ CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::
const ElemType distance) const
{
math::RangeType<ElemType> result;
result.Lo() = distance - furthestDescendantDistance -
other.FurthestDescendantDistance();
result.Lo() = std::max(distance - furthestDescendantDistance -
other.FurthestDescendantDistance(), 0.0);
result.Hi() = distance + furthestDescendantDistance +
other.FurthestDescendantDistance();
@@ -952,8 +1101,9 @@ CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::
{
const ElemType distance = metric->Evaluate(dataset->col(point), other);
return math::RangeType<ElemType>(distance - furthestDescendantDistance,
distance + furthestDescendantDistance);
return math::RangeType<ElemType>(
std::max(distance - furthestDescendantDistance, 0.0),
distance + furthestDescendantDistance);
}
//! Return the minimum and maximum distance to another point given that the
@@ -970,8 +1120,9 @@ CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::
RangeDistance(const arma::vec& /* other */,
const ElemType distance) const
{
return math::RangeType<ElemType>(distance - furthestDescendantDistance,
distance + furthestDescendantDistance);
return math::RangeType<ElemType>(
std::max(distance - furthestDescendantDistance, 0.0),
distance + furthestDescendantDistance);
}
//! For a newly initialized node, create children using the near and far set.
@@ -1526,11 +1677,10 @@ inline void CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::
// Now take its child.
children.push_back(&(old->Child(0)));
// Set its parent and parameters correctly, and rebuild the statistic.
// Set its parent and parameters correctly.
old->Child(0).Parent() = this;
old->Child(0).ParentDistance() = old->ParentDistance();
old->Child(0).DistanceComps() = old->DistanceComps();
old->Child(0).Stat() = StatisticType(old->Child(0));
// Remove its child (so it doesn't delete it).
old->Children().erase(old->Children().begin() + old->Children().size() - 1);
@@ -42,6 +42,18 @@ void Octree<MetricType, StatisticType, MatType>::DualTreeTraverser<RuleType>::
// Store the current traversal info.
traversalInfo = rule.TraversalInfo();
// If both nodes are root nodes, just score them.
if (queryNode.Parent() == NULL && referenceNode.Parent() == NULL)
{
const double rootScore = rule.Score(queryNode, referenceNode);
// If root score is DBL_MAX, don't recurse.
if (rootScore == DBL_MAX)
{
++numPrunes;
return;
}
}
if (queryNode.IsLeaf() && referenceNode.IsLeaf())
{
const size_t begin = queryNode.Point(0);
@@ -22,7 +22,8 @@ template<typename MetricType, typename StatisticType, typename MatType>
template<typename RuleType>
Octree<MetricType, StatisticType, MatType>::SingleTreeTraverser<RuleType>::
SingleTreeTraverser(RuleType& rule) :
rule(rule)
rule(rule),
numPrunes(0)
{
// Nothing to do.
}
@@ -42,6 +43,18 @@ void Octree<MetricType, StatisticType, MatType>::SingleTreeTraverser<RuleType>::
}
else
{
// If it's the root node, just score it.
if (referenceNode.Parent() == NULL)
{
const double rootScore = rule.Score(queryIndex, referenceNode);
// If root score is DBL_MAX, don't recurse into that node.
if (rootScore == DBL_MAX)
{
++numPrunes;
return;
}
}
// Do a prioritized recursion, by scoring all candidates and then sorting
// them.
arma::vec scores(referenceNode.NumChildren());
@@ -181,10 +181,24 @@ class RectangleTree
/**
* Create a rectangle tree by moving the other tree.
*
* @param other The tree to be copied.
* @param other The tree to be moved.
*/
RectangleTree(RectangleTree&& other);
/**
* Copy the given rectangle tree.
*
* @param other The tree to be copied.
*/
RectangleTree& operator=(const RectangleTree& other);
/**
* Take ownership of the given rectangle tree.
*
* @param other The tree to take ownership of.
*/
RectangleTree& operator=(RectangleTree&& other);
/**
* Construct the tree from a boost::serialization archive.
*/
@@ -542,6 +556,13 @@ class RectangleTree
*/
void SplitNode(std::vector<bool>& relevels);
/**
* Builds statistics for a node and all its descendants in a bottom-up way.
*
* @param node Node for which statistics will be built.
*/
void BuildStatistics(RectangleTree* node);
protected:
/**
* A default constructor. This is meant to only be used with
@@ -21,6 +21,25 @@
namespace mlpack {
namespace tree {
// Build the statistics, bottom-up.
template<typename MetricType,
typename StatisticType,
typename MatType,
typename SplitType,
typename DescentType,
template<typename> class AuxiliaryInformationType>
void RectangleTree<MetricType, StatisticType, MatType, SplitType, DescentType,
AuxiliaryInformationType>::
BuildStatistics(RectangleTree* node)
{
// Recurse first.
for (size_t i = 0; i < node->NumChildren(); ++i)
BuildStatistics(&node->Child(i));
// Now build the statistic.
node->Stat() = StatisticType(*node);
}
template<typename MetricType,
typename StatisticType,
typename MatType,
@@ -52,13 +71,14 @@ RectangleTree(const MatType& data,
points(maxLeafSize + 1), // Add one to make splitting the node simpler.
auxiliaryInfo(this)
{
stat = StatisticType(*this);
// For now, just insert the points in order.
RectangleTree* root = this;
for (size_t i = firstDataIndex; i < data.n_cols; i++)
root->InsertPoint(i);
// Initialize statistic recursively after tree construction is complete.
BuildStatistics(this);
}
template<typename MetricType,
@@ -92,13 +112,14 @@ RectangleTree(MatType&& data,
points(maxLeafSize + 1), // Add one to make splitting the node simpler.
auxiliaryInfo(this)
{
stat = StatisticType(*this);
// For now, just insert the points in order.
RectangleTree* root = this;
for (size_t i = firstDataIndex; i < dataset->n_cols; i++)
root->InsertPoint(i);
// Initialize statistic recursively after tree construction is complete.
BuildStatistics(this);
}
template<typename MetricType,
@@ -131,7 +152,8 @@ RectangleTree(
points(maxLeafSize + 1), // Add one to make splitting the node simpler.
auxiliaryInfo(this)
{
stat = StatisticType(*this);
// Initialize statistic.
BuildStatistics(this);
}
/**
@@ -234,6 +256,96 @@ RectangleTree(RectangleTree&& other) :
other.ownsDataset = false;
}
template<typename MetricType,
typename StatisticType,
typename MatType,
typename SplitType,
typename DescentType,
template<typename> class AuxiliaryInformationType>
RectangleTree<MetricType, StatisticType, MatType, SplitType, DescentType,
AuxiliaryInformationType>&
RectangleTree<MetricType, StatisticType, MatType, SplitType, DescentType,
AuxiliaryInformationType>::
operator=(const RectangleTree& other)
{
// Return if it's the same tree.
if (this == &other)
return *this;
for (size_t i = 0; i < numChildren; i++)
delete children[i];
if (ownsDataset)
delete dataset;
maxNumChildren = other.MaxNumChildren();
minNumChildren = other.MinNumChildren();
numChildren = other.NumChildren();
children.resize(maxNumChildren + 1, NULL);
parent = NULL;
begin = other.Begin();
count = other.Count();
numDescendants = other.numDescendants;
maxLeafSize = other.MaxLeafSize();
minLeafSize = other.MinLeafSize();
bound = other.bound;
parentDistance = other.ParentDistance();
dataset = new MatType(*other.dataset);
ownsDataset = true;
points = other.points;
auxiliaryInfo = AuxiliaryInfoType(other.auxiliaryInfo, this, true);
if (numChildren > 0)
{
for (size_t i = 0; i < numChildren; i++)
children[i] = new RectangleTree(other.Child(i), true, this);
}
return *this;
}
template<typename MetricType,
typename StatisticType,
typename MatType,
typename SplitType,
typename DescentType,
template<typename> class AuxiliaryInformationType>
RectangleTree<MetricType, StatisticType, MatType, SplitType, DescentType,
AuxiliaryInformationType>&
RectangleTree<MetricType, StatisticType, MatType, SplitType, DescentType,
AuxiliaryInformationType>::
operator=(RectangleTree&& other)
{
// Return if it's the same tree.
if (this == &other)
return *this;
for (size_t i = 0; i < numChildren; i++)
delete children[i];
if (ownsDataset)
delete dataset;
maxNumChildren = other.MaxNumChildren();
minNumChildren = other.MinNumChildren();
numChildren = other.NumChildren();
children = std::move(other.children);
parent = other.Parent();
begin = other.Begin();
count = other.Count();
numDescendants = other.numDescendants;
maxLeafSize = other.MaxLeafSize();
minLeafSize = other.MinLeafSize();
bound = std::move(other.bound);
parentDistance = other.ParentDistance();
dataset = other.dataset;
ownsDataset = other.ownsDataset;
points = std::move(other.points);
auxiliaryInfo = std::move(other.auxiliaryInfo);
return *this;
}
/**
* Construct the tree from a boost::serialization archive.
*/
@@ -209,6 +209,20 @@ class SpillTree
*/
SpillTree(SpillTree&& other);
/**
* Copy the given Spill Tree.
*
* @param other The tree to be copied.
*/
SpillTree& operator=(const SpillTree& other);
/**
* Take ownership of the given Spill Tree.
*
* @param other The tree to take ownership of.
*/
SpillTree& operator=(SpillTree&& other);
/**
* Initialize the tree from a boost::serialization archive.
*
@@ -192,6 +192,88 @@ SpillTree(const SpillTree& other) :
}
}
/**
* Copy Assignment.
*/
template<typename MetricType,
typename StatisticType,
typename MatType,
template<typename HyperplaneMetricType> class HyperplaneType,
template<typename SplitMetricType, typename SplitMatType>
class SplitType>
SpillTree<MetricType, StatisticType, MatType, HyperplaneType, SplitType>&
SpillTree<MetricType, StatisticType, MatType, HyperplaneType, SplitType>::
operator=(const SpillTree& other)
{
if (this == &other)
return *this;
// Freeing memory that will not be used anymore.
if (localDataset)
delete dataset;
delete pointsIndex;
delete left;
delete right;
left = NULL;
right = NULL;
parent = other.parent;
count = other.count;
pointsIndex = NULL;
overlappingNode = other.overlappingNode;
hyperplane = other.hyperplane;
bound = other.bound;
stat = other.stat;
parentDistance = other.parentDistance;
furthestDescendantDistance = other.furthestDescendantDistance;
// Copy matrix, but only if we are the root and the other tree has its own
// copy of the dataset.
dataset = (other.parent == NULL && other.localDataset) ?
new MatType(*other.dataset) : other.dataset;
localDataset = other.parent == NULL && other.localDataset;
// Create left and right children (if any).
if (other.Left())
{
left = new SpillTree(*other.Left());
left->Parent() = this; // Set parent to this, not other tree.
}
if (other.Right())
{
right = new SpillTree(*other.Right());
right->Parent() = this; // Set parent to this, not other tree.
}
// If vector of indexes, copy it.
if (other.pointsIndex)
pointsIndex = new arma::Col<size_t>(*other.pointsIndex);
// Propagate matrix, but only if we are the root.
if (parent == NULL && localDataset)
{
std::queue<SpillTree*> queue;
if (left)
queue.push(left);
if (right)
queue.push(right);
while (!queue.empty())
{
SpillTree* node = queue.front();
queue.pop();
node->dataset = dataset;
if (node->left)
queue.push(node->left);
if (node->right)
queue.push(node->right);
}
}
return *this;
}
/**
* Move constructor.
*/
@@ -237,6 +319,66 @@ SpillTree(SpillTree&& other) :
right->parent = this;
}
/**
* Move Assignment.
*/
template<typename MetricType,
typename StatisticType,
typename MatType,
template<typename HyperplaneMetricType> class HyperplaneType,
template<typename SplitMetricType, typename SplitMatType>
class SplitType>
SpillTree<MetricType, StatisticType, MatType, HyperplaneType, SplitType>&
SpillTree<MetricType, StatisticType, MatType, HyperplaneType, SplitType>::
operator=(SpillTree&& other)
{
if (this == &other)
return *this;
// Freeing memory that will not be used anymore.
if (localDataset)
delete dataset;
delete pointsIndex;
delete left;
delete right;
left = other.left;
right = other.right;
parent = other.parent;
count = other.count;
pointsIndex = other.pointsIndex;
overlappingNode = other.overlappingNode;
hyperplane = other.hyperplane;
bound = std::move(other.bound);
stat = std::move(other.stat);
parentDistance = other.parentDistance;
furthestDescendantDistance = other.furthestDescendantDistance;
minimumBoundDistance = other.minimumBoundDistance;
dataset = other.dataset;
localDataset = other.localDataset;
// Now we are a clone of the other tree. But we must also clear the other
// tree's contents, so it doesn't delete anything when it is destructed.
other.left = NULL;
other.right = NULL;
other.count = 0;
other.pointsIndex = NULL;
other.parentDistance = 0.0;
other.furthestDescendantDistance = 0.0;
other.minimumBoundDistance = 0.0;
other.dataset = NULL;
other.localDataset = false;
// Set new parent.
if (left)
left->parent = this;
if (right)
right->parent = this;
return *this;
}
/**
* Initialize the tree from an archive.
*/
+8 -14
View File
@@ -36,28 +36,22 @@ ARMA_64BIT_WORD disabled."
#endif
#endif
// Check if OpenMP was enabled when mlpack was built. This only matters for
// Armadillo 8.300.1 and newer.
#if (ARMA_VERSION_MAJOR > 8) || \
((ARMA_VERSION_MAJOR == 8) && (ARMA_VERSION_MINOR > 300)) || \
((ARMA_VERSION_MAJOR == 8) && (ARMA_VERSION_MINOR == 300) && \
(ARMA_VERSION_PATCH >= 1))
#ifdef ARMA_USE_OPENMP
#ifdef MLPACK_ARMA_DONT_USE_OPENMP
#pragma message "mlpack was compiled without OpenMP support, but you are \
// Check if OpenMP was enabled when mlpack was built.
#ifdef ARMA_USE_OPENMP
#ifdef MLPACK_ARMA_DONT_USE_OPENMP
#pragma message "mlpack was compiled without OpenMP support, but you are \
compiling with OpenMP support (either -fopenmp or another option). This will \
almost certainly cause irreparable disaster. Either compile your application \
*without* OpenMP support (i.e. remove -fopenmp or another flag), or, recompile \
mlpack with OpenMP support."
#endif
#else
#ifdef MLPACK_ARMA_USE_OPENMP
#pragma message "mlpack was compiled with OpenMP support, but you are \
#endif
#else
#ifdef MLPACK_ARMA_USE_OPENMP
#pragma message "mlpack was compiled with OpenMP support, but you are \
compiling without OpenMP support. This will almost certainly cause \
irreparable disaster. Either enable OpenMP support in your application (e.g., \
add -fopenmp to your compiler command line), or, recompile mlpack *without* \
OpenMP support."
#endif
#endif
#endif
+109
View File
@@ -37,11 +37,43 @@
#include <mlpack/bindings/cli/cli_option.hpp>
#include <mlpack/bindings/cli/print_doc_functions.hpp>
/**
* PRINT_PARAM_STRING() returns a string that contains the correct
* language-specific representation of a parameter's name.
*/
#define PRINT_PARAM_STRING mlpack::bindings::cli::ParamString
/**
* PRINT_PARAM_VALUE() returns a string that contains a correct
* language-specific representation of a parameter's value.
*/
#define PRINT_PARAM_VALUE mlpack::bindings::cli::PrintValue
/**
* PRINT_CALL() returns a string that contains the full language-specific
* representation of a call to an mlpack binding. The first argument should be
* the name of the binding, and all other arguments should be names of
* parameters followed by values (in the case where the preceding parameter is
* not a flag).
*/
#define PRINT_CALL mlpack::bindings::cli::ProgramCall
/**
* PRINT_DATASET() returns a string that contains a correct language-specific
* representation of a dataset name.
*/
#define PRINT_DATASET mlpack::bindings::cli::PrintDataset
/**
* PRINT_MODEL() returns a string that contains a correct language-specific
* representation of an mlpack model name.
*/
#define PRINT_MODEL mlpack::bindings::cli::PrintModel
/**
* BINDING_IGNORE_CHECK() is an internally-used macro to determine whether or
* not a specific parameter check should be ignored.
*/
#define BINDING_IGNORE_CHECK mlpack::bindings::cli::IgnoreCheck
namespace mlpack {
@@ -91,7 +123,20 @@ int main(int argc, char** argv)
#define PRINT_PARAM_VALUE(A, B) std::string(" ")
#define PRINT_DATASET(A) std::string(" ")
#define PRINT_MODEL(A) std::string(" ")
/**
* PRINT_CALL() returns a string that contains the full language-specific
* representation of a call to an mlpack binding. The first argument should be
* the name of the binding, and all other arguments should be names of
* parameters followed by values (in the case where the preceding parameter is
* not a flag).
*/
#define PRINT_CALL(...) std::string(" ")
/**
* BINDING_IGNORE_CHECK() is an internally-used macro to determine whether or
* not a specific parameter check should be ignored.
*/
#define BINDING_IGNORE_CHECK mlpack::bindings::tests::IgnoreCheck
namespace mlpack {
@@ -120,11 +165,43 @@ using Option = mlpack::bindings::tests::TestOption<T>;
#include <mlpack/bindings/python/py_option.hpp>
#include <mlpack/bindings/python/print_doc_functions.hpp>
/**
* PRINT_PARAM_STRING() returns a string that contains the correct
* language-specific representation of a parameter's name.
*/
#define PRINT_PARAM_STRING mlpack::bindings::python::ParamString
/**
* PRINT_PARAM_VALUE() returns a string that contains a correct
* language-specific representation of a parameter's value.
*/
#define PRINT_PARAM_VALUE mlpack::bindings::python::PrintValue
/**
* PRINT_DATASET() returns a string that contains a correct language-specific
* representation of a dataset name.
*/
#define PRINT_DATASET mlpack::bindings::python::PrintDataset
/**
* PRINT_MODEL() returns a string that contains a correct language-specific
* representation of an mlpack model name.
*/
#define PRINT_MODEL mlpack::bindings::python::PrintModel
/**
* PRINT_CALL() returns a string that contains the full language-specific
* representation of a call to an mlpack binding. The first argument should be
* the name of the binding, and all other arguments should be names of
* parameters followed by values (in the case where the preceding parameter is
* not a flag).
*/
#define PRINT_CALL mlpack::bindings::python::ProgramCall
/**
* BINDING_IGNORE_CHECK() is an internally-used macro to determine whether or
* not a specific parameter check should be ignored.
*/
#define BINDING_IGNORE_CHECK mlpack::bindings::python::IgnoreCheck
namespace mlpack {
@@ -217,11 +294,43 @@ PARAM_FLAG("verbose", "Display informational messages and the full list of "
#include <mlpack/bindings/markdown/md_option.hpp>
#include <mlpack/bindings/markdown/print_doc_functions.hpp>
/**
* PRINT_PARAM_STRING() returns a string that contains the correct
* language-specific representation of a parameter's name.
*/
#define PRINT_PARAM_STRING mlpack::bindings::markdown::ParamString
/**
* PRINT_PARAM_VALUE() returns a string that contains a correct
* language-specific representation of a parameter's value.
*/
#define PRINT_PARAM_VALUE mlpack::bindings::markdown::PrintValue
/**
* PRINT_DATASET() returns a string that contains a correct language-specific
* representation of a dataset name.
*/
#define PRINT_DATASET mlpack::bindings::markdown::PrintDataset
/**
* PRINT_MODEL() returns a string that contains a correct language-specific
* representation of an mlpack model name.
*/
#define PRINT_MODEL mlpack::bindings::markdown::PrintModel
/**
* PRINT_CALL() returns a string that contains the full language-specific
* representation of a call to an mlpack binding. The first argument should be
* the name of the binding, and all other arguments should be names of
* parameters followed by values (in the case where the preceding parameter is
* not a flag).
*/
#define PRINT_CALL mlpack::bindings::markdown::ProgramCall
/**
* BINDING_IGNORE_CHECK() is an internally-used macro to determine whether or
* not a specific parameter check should be ignored.
*/
#define BINDING_IGNORE_CHECK mlpack::bindings::markdown::IgnoreCheck
// This doesn't actually matter for this binding type.
+108 -36
View File
@@ -77,7 +77,9 @@ using DatasetInfo = DatasetMapper<IncrementPolicy, std::string>;
* Define a flag parameter.
*
* @param ID Name of the parameter.
* @param DESC Quick description of the parameter (1-2 sentences).
* @param DESC Quick description of the parameter (1-2 sentences). Don't use
* printing macros like PRINT_PARAM_STRING() or PRINT_DATASET() or others
* here---it will cause problems.
* @param ALIAS An alias for the parameter (one letter).
*
* @see mlpack::CLI, PROGRAM_INFO()
@@ -100,7 +102,9 @@ using DatasetInfo = DatasetMapper<IncrementPolicy, std::string>;
* --ID=value.
*
* @param ID Name of the parameter.
* @param DESC Quick description of the parameter (1-2 sentences).
* @param DESC Quick description of the parameter (1-2 sentences). Don't use
* printing macros like PRINT_PARAM_STRING() or PRINT_DATASET() or others
* here---it will cause problems.
* @param ALIAS An alias for the parameter (one letter).
* @param DEF Default value of the parameter.
*
@@ -131,7 +135,9 @@ using DatasetInfo = DatasetMapper<IncrementPolicy, std::string>;
* will be issued.
*
* @param ID Name of the parameter.
* @param DESC Quick description of the parameter (1-2 sentences).
* @param DESC Quick description of the parameter (1-2 sentences). Don't use
* printing macros like PRINT_PARAM_STRING() or PRINT_DATASET() or others
* here---it will cause problems.
*
* @see mlpack::CLI, PROGRAM_INFO()
*
@@ -153,7 +159,9 @@ using DatasetInfo = DatasetMapper<IncrementPolicy, std::string>;
* --ID=value.
*
* @param ID Name of the parameter.
* @param DESC Quick description of the parameter (1-2 sentences).
* @param DESC Quick description of the parameter (1-2 sentences). Don't use
* printing macros like PRINT_PARAM_STRING() or PRINT_DATASET() or others
* here---it will cause problems.
* @param ALIAS An alias for the parameter (one letter).
* @param DEF Default value of the parameter.
*
@@ -183,7 +191,9 @@ using DatasetInfo = DatasetMapper<IncrementPolicy, std::string>;
* will be issued.
*
* @param ID Name of the parameter.
* @param DESC Quick description of the parameter (1-2 sentences).
* @param DESC Quick description of the parameter (1-2 sentences). Don't use
* printing macros like PRINT_PARAM_STRING() or PRINT_DATASET() or others
* here---it will cause problems.
*
* @see mlpack::CLI, PROGRAM_INFO()
*
@@ -206,7 +216,9 @@ using DatasetInfo = DatasetMapper<IncrementPolicy, std::string>;
* PROGRAM_INFO() macro), the parameter can be specified with just --ID=value.
*
* @param ID Name of the parameter.
* @param DESC Quick description of the parameter (1-2 sentences).
* @param DESC Quick description of the parameter (1-2 sentences). Don't use
* printing macros like PRINT_PARAM_STRING() or PRINT_DATASET() or others
* here---it will cause problems.
* @param ALIAS An alias for the parameter (one letter).
* @param DEF Default value of the parameter.
*
@@ -236,7 +248,9 @@ using DatasetInfo = DatasetMapper<IncrementPolicy, std::string>;
* @endcode
*
* @param ID Name of the parameter.
* @param DESC Quick description of the parameter (1-2 sentences).
* @param DESC Quick description of the parameter (1-2 sentences). Don't use
* printing macros like PRINT_PARAM_STRING() or PRINT_DATASET() or others
* here---it will cause problems.
* @param ALIAS An alias for the parameter (one letter).
*
* @see mlpack::CLI, PROGRAM_INFO()
@@ -264,7 +278,9 @@ using DatasetInfo = DatasetMapper<IncrementPolicy, std::string>;
* @endcode
*
* @param ID Name of the parameter.
* @param DESC Description of the parameter (1-2 sentences).
* @param DESC Description of the parameter (1-2 sentences). Don't use
* printing macros like PRINT_PARAM_STRING() or PRINT_DATASET() or others
* here---it will cause problems.
* @param ALIAS An alias for the parameter (one letter).
*
* @bug
@@ -290,7 +306,9 @@ using DatasetInfo = DatasetMapper<IncrementPolicy, std::string>;
* @endcode
*
* @param ID Name of the parameter.
* @param DESC Description of the parameter (1-2 sentences).
* @param DESC Description of the parameter (1-2 sentences). Don't use
* printing macros like PRINT_PARAM_STRING() or PRINT_DATASET() or others
* here---it will cause problems.
* @param ALIAS An alias for the parameter (one letter).
*
* @bug
@@ -321,7 +339,9 @@ using DatasetInfo = DatasetMapper<IncrementPolicy, std::string>;
* types.
*
* @param ID Name of the parameter.
* @param DESC Description of the parameter (1-2 sentences).
* @param DESC Description of the parameter (1-2 sentences). Don't use
* printing macros like PRINT_PARAM_STRING() or PRINT_DATASET() or others
* here---it will cause problems.
* @param ALIAS An alias for the parameter (one letter).
*
* @bug
@@ -348,7 +368,9 @@ using DatasetInfo = DatasetMapper<IncrementPolicy, std::string>;
* @endcode
*
* @param ID Name of the parameter.
* @param DESC Description of the parameter (1-2 sentences).
* @param DESC Description of the parameter (1-2 sentences). Don't use
* printing macros like PRINT_PARAM_STRING() or PRINT_DATASET() or others
* here---it will cause problems.
* @param ALIAS An alias for the parameter (one letter).
*
* @bug
@@ -376,7 +398,9 @@ using DatasetInfo = DatasetMapper<IncrementPolicy, std::string>;
* @endcode
*
* @param ID Name of the parameter.
* @param DESC Description of the parameter (1-2 sentences).
* @param DESC Description of the parameter (1-2 sentences). Don't use
* printing macros like PRINT_PARAM_STRING() or PRINT_DATASET() or others
* here---it will cause problems.
* @param ALIAS An alias for the parameter (one letter).
*
* @bug
@@ -409,7 +433,9 @@ using DatasetInfo = DatasetMapper<IncrementPolicy, std::string>;
* types.
*
* @param ID Name of the parameter.
* @param DESC Description of the parameter (1-2 sentences).
* @param DESC Description of the parameter (1-2 sentences). Don't use
* printing macros like PRINT_PARAM_STRING() or PRINT_DATASET() or others
* here---it will cause problems.
* @param ALIAS An alias for the parameter (one letter).
*
* @bug
@@ -435,7 +461,9 @@ using DatasetInfo = DatasetMapper<IncrementPolicy, std::string>;
* @endcode
*
* @param ID Name of the parameter.
* @param DESC Description of the parameter (1-2 sentences).
* @param DESC Description of the parameter (1-2 sentences). Don't use
* printing macros like PRINT_PARAM_STRING() or PRINT_DATASET() or others
* here---it will cause problems.
* @param ALIAS An alias for the parameter (one letter).
*
* @bug
@@ -462,7 +490,9 @@ using DatasetInfo = DatasetMapper<IncrementPolicy, std::string>;
* @endcode
*
* @param ID Name of the parameter.
* @param DESC Description of the parameter (1-2 sentences).
* @param DESC Description of the parameter (1-2 sentences). Don't use
* printing macros like PRINT_PARAM_STRING() or PRINT_DATASET() or others
* here---it will cause problems.
* @param ALIAS An alias for the parameter (one letter).
*
* @bug
@@ -494,7 +524,9 @@ using DatasetInfo = DatasetMapper<IncrementPolicy, std::string>;
* types.
*
* @param ID Name of the parameter.
* @param DESC Description of the parameter (1-2 sentences).
* @param DESC Description of the parameter (1-2 sentences). Don't use
* printing macros like PRINT_PARAM_STRING() or PRINT_DATASET() or others
* here---it will cause problems.
* @param ALIAS An alias for the parameter (one letter).
*
* @bug
@@ -521,7 +553,9 @@ using DatasetInfo = DatasetMapper<IncrementPolicy, std::string>;
* @endcode
*
* @param ID Name of the parameter.
* @param DESC Description of the parameter (1-2 sentences).
* @param DESC Description of the parameter (1-2 sentences). Don't use
* printing macros like PRINT_PARAM_STRING() or PRINT_DATASET() or others
* here---it will cause problems.
* @param ALIAS An alias for the parameter (one letter).
*
* @bug
@@ -547,7 +581,9 @@ using DatasetInfo = DatasetMapper<IncrementPolicy, std::string>;
* @endcode
*
* @param ID Name of the parameter.
* @param DESC Description of the parameter (1-2 sentences).
* @param DESC Description of the parameter (1-2 sentences). Don't use
* printing macros like PRINT_PARAM_STRING() or PRINT_DATASET() or others
* here---it will cause problems.
* @param ALIAS An alias for the parameter (one letter).
*
* @bug
@@ -573,7 +609,9 @@ using DatasetInfo = DatasetMapper<IncrementPolicy, std::string>;
* @endcode
*
* @param ID Name of the parameter.
* @param DESC Description of the parameter (1-2 sentences).
* @param DESC Description of the parameter (1-2 sentences). Don't use
* printing macros like PRINT_PARAM_STRING() or PRINT_DATASET() or others
* here---it will cause problems.
* @param ALIAS An alias for the parameter (one letter).
*
* @bug
@@ -599,7 +637,9 @@ using DatasetInfo = DatasetMapper<IncrementPolicy, std::string>;
* @endcode
*
* @param ID Name of the parameter.
* @param DESC Description of the parameter (1-2 sentences).
* @param DESC Description of the parameter (1-2 sentences). Don't use
* printing macros like PRINT_PARAM_STRING() or PRINT_DATASET() or others
* here---it will cause problems.
* @param ALIAS An alias for the parameter (one letter).
*
* @bug
@@ -626,7 +666,9 @@ using DatasetInfo = DatasetMapper<IncrementPolicy, std::string>;
* @endcode
*
* @param ID Name of the parameter.
* @param DESC Description of the parameter (1-2 sentences).
* @param DESC Description of the parameter (1-2 sentences). Don't use
* printing macros like PRINT_PARAM_STRING() or PRINT_DATASET() or others
* here---it will cause problems.
* @param ALIAS An alias for the parameter (one letter).
*
* @bug
@@ -657,7 +699,9 @@ using DatasetInfo = DatasetMapper<IncrementPolicy, std::string>;
* types.
*
* @param ID Name of the parameter.
* @param DESC Description of the parameter (1-2 sentences).
* @param DESC Description of the parameter (1-2 sentences). Don't use
* printing macros like PRINT_PARAM_STRING() or PRINT_DATASET() or others
* here---it will cause problems.
* @param ALIAS An alias for the parameter (one letter).
*
* @bug
@@ -688,7 +732,9 @@ using DatasetInfo = DatasetMapper<IncrementPolicy, std::string>;
* types.
*
* @param ID Name of the parameter.
* @param DESC Description of the parameter (1-2 sentences).
* @param DESC Description of the parameter (1-2 sentences). Don't use
* printing macros like PRINT_PARAM_STRING() or PRINT_DATASET() or others
* here---it will cause problems.
* @param ALIAS An alias for the parameter (one letter).
*
* @bug
@@ -719,7 +765,9 @@ using DatasetInfo = DatasetMapper<IncrementPolicy, std::string>;
* types.
*
* @param ID Name of the parameter.
* @param DESC Description of the parameter (1-2 sentences).
* @param DESC Description of the parameter (1-2 sentences). Don't use
* printing macros like PRINT_PARAM_STRING() or PRINT_DATASET() or others
* here---it will cause problems.
* @param ALIAS An alias for the parameter (one letter).
*
* @bug
@@ -750,7 +798,9 @@ using DatasetInfo = DatasetMapper<IncrementPolicy, std::string>;
* types.
*
* @param ID Name of the parameter.
* @param DESC Description of the parameter (1-2 sentences).
* @param DESC Description of the parameter (1-2 sentences). Don't use
* printing macros like PRINT_PARAM_STRING() or PRINT_DATASET() or others
* here---it will cause problems.
* @param ALIAS An alias for the parameter (one letter).
*
* @bug
@@ -771,7 +821,9 @@ using DatasetInfo = DatasetMapper<IncrementPolicy, std::string>;
* --ID=value1,value2,value3.
*
* @param ID Name of the parameter.
* @param DESC Quick description of the parameter (1-2 sentences).
* @param DESC Quick description of the parameter (1-2 sentences). Don't use
* printing macros like PRINT_PARAM_STRING() or PRINT_DATASET() or others
* here---it will cause problems.
* @param ALIAS An alias for the parameter (one letter).
* @param DEF Default value of the parameter.
*
@@ -802,7 +854,9 @@ using DatasetInfo = DatasetMapper<IncrementPolicy, std::string>;
* will be issued.
*
* @param ID Name of the parameter.
* @param DESC Quick description of the parameter (1-2 sentences).
* @param DESC Quick description of the parameter (1-2 sentences). Don't use
* printing macros like PRINT_PARAM_STRING() or PRINT_DATASET() or others
* here---it will cause problems.
*
* @see mlpack::CLI, PROGRAM_INFO()
*
@@ -838,7 +892,9 @@ using DatasetInfo = DatasetMapper<IncrementPolicy, std::string>;
* @endcode
*
* @param ID Name of the parameter.
* @param DESC Quick description of the parameter (1-2 sentences).
* @param DESC Quick description of the parameter (1-2 sentences). Don't use
* printing macros like PRINT_PARAM_STRING() or PRINT_DATASET() or others
* here---it will cause problems.
* @param ALIAS One-character string representing the alias of the parameter.
*
* @see mlpack::CLI, PROGRAM_INFO()
@@ -881,7 +937,9 @@ using DatasetInfo = DatasetMapper<IncrementPolicy, std::string>;
*
* @param TYPE Type of the model to be loaded.
* @param ID Name of the parameter.
* @param DESC Description of the parameter.
* @param DESC Description of the parameter. Don't use
* printing macros like PRINT_PARAM_STRING() or PRINT_DATASET() or others
* here---it will cause problems.
* @param ALIAS An alias for the parameter (one letter).
*/
#define PARAM_MODEL_IN(TYPE, ID, DESC, ALIAS) \
@@ -913,7 +971,9 @@ using DatasetInfo = DatasetMapper<IncrementPolicy, std::string>;
*
* @param TYPE Type of the model to be loaded.
* @param ID Name of the parameter.
* @param DESC Description of the parameter.
* @param DESC Description of the parameter. Don't use
* printing macros like PRINT_PARAM_STRING() or PRINT_DATASET() or others
* here---it will cause problems.
* @param ALIAS An alias for the parameter (one letter).
*/
#define PARAM_MODEL_IN_REQ(TYPE, ID, DESC, ALIAS) \
@@ -936,7 +996,9 @@ using DatasetInfo = DatasetMapper<IncrementPolicy, std::string>;
*
* @param TYPE Type of the model to be saved.
* @param ID Name of the parameter.
* @param DESC Description of the parameter.
* @param DESC Description of the parameter. Don't use
* printing macros like PRINT_PARAM_STRING() or PRINT_DATASET() or others
* here---it will cause problems.
* @param ALIAS An alias for the parameter (one letter).
*/
#define PARAM_MODEL_OUT(TYPE, ID, DESC, ALIAS) \
@@ -948,7 +1010,9 @@ using DatasetInfo = DatasetMapper<IncrementPolicy, std::string>;
* The parameter must then be specified on the command line with --ID=value.
*
* @param ID Name of the parameter.
* @param DESC Quick description of the parameter (1-2 sentences).
* @param DESC Quick description of the parameter (1-2 sentences). Don't use
* printing macros like PRINT_PARAM_STRING() or PRINT_DATASET() or others
* here---it will cause problems.
* @param ALIAS An alias for the parameter (one letter).
*
* @see mlpack::CLI, PROGRAM_INFO()
@@ -970,7 +1034,9 @@ using DatasetInfo = DatasetMapper<IncrementPolicy, std::string>;
* The parameter must then be specified on the command line with --ID=value.
*
* @param ID Name of the parameter.
* @param DESC Quick description of the parameter (1-2 sentences).
* @param DESC Quick description of the parameter (1-2 sentences). Don't use
* printing macros like PRINT_PARAM_STRING() or PRINT_DATASET() or others
* here---it will cause problems.
* @param ALIAS An alias for the parameter (one letter).
*
* @see mlpack::CLI, PROGRAM_INFO()
@@ -992,7 +1058,9 @@ using DatasetInfo = DatasetMapper<IncrementPolicy, std::string>;
* The parameter must then be specified on the command line with --ID=value.
*
* @param ID Name of the parameter.
* @param DESC Quick description of the parameter (1-2 sentences).
* @param DESC Quick description of the parameter (1-2 sentences). Don't use
* printing macros like PRINT_PARAM_STRING() or PRINT_DATASET() or others
* here---it will cause problems.
* @param ALIAS An alias for the parameter (one letter).
*
* @see mlpack::CLI, PROGRAM_INFO()
@@ -1015,7 +1083,9 @@ using DatasetInfo = DatasetMapper<IncrementPolicy, std::string>;
* --ID=value1,value2,value3.
*
* @param ID Name of the parameter.
* @param DESC Quick description of the parameter (1-2 sentences).
* @param DESC Quick description of the parameter (1-2 sentences). Don't use
* printing macros like PRINT_PARAM_STRING() or PRINT_DATASET() or others
* here---it will cause problems.
* @param ALIAS An alias for the parameter (one letter).
*
* @see mlpack::CLI, PROGRAM_INFO()
@@ -1052,7 +1122,9 @@ using DatasetInfo = DatasetMapper<IncrementPolicy, std::string>;
*
* @param T Type of the parameter.
* @param ID Name of the parameter.
* @param DESC Description of the parameter (1-2 sentences).
* @param DESC Description of the parameter (1-2 sentences). Don't use
* printing macros like PRINT_PARAM_STRING() or PRINT_DATASET() or others
* here---it will cause problems.
* @param ALIAS Alias for this parameter (one letter).
* @param DEF Default value of the parameter.
* @param REQ Whether or not parameter is required (boolean value).
+4 -4
View File
@@ -220,7 +220,7 @@ struct NAME \
#define SINGLE_ARG(...) __VA_ARGS__
/**
* HAS_METHOD_FORM generates a template that allows to check at compile time
* HAS_METHOD_FORM generates a template that allows a compile time check for
* whether a given class has a method of the requested form. For example, for
* the following class
*
@@ -254,8 +254,8 @@ struct NAME \
HAS_METHOD_FORM_BASE(SINGLE_ARG(METHOD), SINGLE_ARG(NAME), 7)
/**
* HAS_EXACT_METHOD_FORM generates a template that allows to check at compile
* time whether a given class has a method of the requested form. For example,
* HAS_EXACT_METHOD_FORM generates a template that allows a compile time check
* whether a given class has a method of the requested form. For example,
* for the following class
*
* class A
@@ -291,7 +291,7 @@ struct NAME \
* A version of HAS_METHOD_FORM() where the maximum number of extra arguments is
* set to the default of 7.
*
* HAS_METHOD_FORM generates a template that allows to check at compile time
* HAS_METHOD_FORM generates a template that allows a compile time check as to
* whether a given class has a method of the requested form. For example, for
* the following class
*
+1 -1
View File
@@ -17,7 +17,7 @@
// The version of mlpack. If this is a git repository, this will be a version
// with higher number than the most recent release.
#define MLPACK_VERSION_MAJOR 3
#define MLPACK_VERSION_MINOR 1
#define MLPACK_VERSION_MINOR 2
#define MLPACK_VERSION_PATCH 2
// The name of the version (for use by --version).
+2
View File
@@ -7,6 +7,7 @@ set(SOURCES
rnn_impl.hpp
brnn.hpp
brnn_impl.hpp
layer_names.hpp
)
add_subdirectory(visitor)
@@ -18,6 +19,7 @@ add_subdirectory(convolution_rules)
add_subdirectory(gan)
add_subdirectory(rbm)
add_subdirectory(augmented)
add_subdirectory(regularizer)
# Add directory name to sources.
set(DIR_SRCS)
+21 -4
View File
@@ -94,15 +94,19 @@ class FFN
* object, be sure to use std::move to avoid unnecessary copy.
*
* @tparam OptimizerType Type of optimizer to use to train the model.
* @tparam CallbackTypes Types of Callback Functions.
* @param predictors Input training variables.
* @param responses Outputs results from input training variables.
* @param optimizer Instantiated optimizer used to train the model.
* @param callbacks Callback function for ensmallen optimizer `OptimizerType`.
* See https://www.ensmallen.org/docs.html#callback-documentation.
* @return The final objective of the trained model (NaN or Inf on error).
*/
template<typename OptimizerType>
template<typename OptimizerType, typename... CallbackTypes>
double Train(arma::mat predictors,
arma::mat responses,
OptimizerType& optimizer);
OptimizerType& optimizer,
CallbackTypes&&... callbacks);
/**
* Train the feedforward network on the given input data. By default, the
@@ -118,11 +122,16 @@ class FFN
*
* @tparam OptimizerType Type of optimizer to use to train the model.
* @param predictors Input training variables.
* @tparam CallbackTypes Types of Callback Functions.
* @param responses Outputs results from input training variables.
* @param callbacks Callback function for ensmallen optimizer `OptimizerType`.
* See https://www.ensmallen.org/docs.html#callback-documentation.
* @return The final objective of the trained model (NaN or Inf on error).
*/
template<typename OptimizerType = ens::RMSProp>
double Train(arma::mat predictors, arma::mat responses);
template<typename OptimizerType = ens::RMSProp, typename... CallbackTypes>
double Train(arma::mat predictors,
arma::mat responses,
CallbackTypes&&... callbacks);
/**
* Predict the responses to a given set of predictors. The responses will
@@ -257,6 +266,14 @@ class FFN
*/
void Add(LayerTypes<CustomLayers...> layer) { network.push_back(layer); }
//! Get the network model.
const std::vector<LayerTypes<CustomLayers...> >& Model() const
{
return network;
}
//! Modify the network model.
std::vector<LayerTypes<CustomLayers...> >& Model() { return network; }
//! Return the number of separable functions (the number of predictor points).
size_t NumFunctions() const { return numFunctions; }
+9 -6
View File
@@ -69,17 +69,18 @@ void FFN<OutputLayerType, InitializationRuleType, CustomLayers...>::ResetData(
template<typename OutputLayerType, typename InitializationRuleType,
typename... CustomLayers>
template<typename OptimizerType>
template<typename OptimizerType, typename... CallbackTypes>
double FFN<OutputLayerType, InitializationRuleType, CustomLayers...>::Train(
arma::mat predictors,
arma::mat responses,
OptimizerType& optimizer)
OptimizerType& optimizer,
CallbackTypes&&... callbacks)
{
ResetData(std::move(predictors), std::move(responses));
// Train the model.
Timer::Start("ffn_optimization");
const double out = optimizer.Optimize(*this, parameter);
const double out = optimizer.Optimize(*this, parameter, callbacks...);
Timer::Stop("ffn_optimization");
Log::Info << "FFN::FFN(): final objective of trained model is " << out
@@ -89,9 +90,11 @@ double FFN<OutputLayerType, InitializationRuleType, CustomLayers...>::Train(
template<typename OutputLayerType, typename InitializationRuleType,
typename... CustomLayers>
template<typename OptimizerType>
template<typename OptimizerType, typename... CallbackTypes>
double FFN<OutputLayerType, InitializationRuleType, CustomLayers...>::Train(
arma::mat predictors, arma::mat responses)
arma::mat predictors,
arma::mat responses,
CallbackTypes&&... callbacks)
{
ResetData(std::move(predictors), std::move(responses));
@@ -99,7 +102,7 @@ double FFN<OutputLayerType, InitializationRuleType, CustomLayers...>::Train(
// Train the model.
Timer::Start("ffn_optimization");
const double out = optimizer.Optimize(*this, parameter);
const double out = optimizer.Optimize(*this, parameter, callbacks...);
Timer::Stop("ffn_optimization");
Log::Info << "FFN::FFN(): final objective of trained model is " << out
@@ -8,6 +8,8 @@ set(SOURCES
wgangp_impl.hpp
)
add_subdirectory(metrics)
# Add directory name to sources.
set(DIR_SRCS)
foreach(file ${SOURCES})
+39 -13
View File
@@ -19,6 +19,7 @@
#include <mlpack/methods/ann/visitor/reset_visitor.hpp>
#include <mlpack/methods/ann/visitor/weight_size_visitor.hpp>
#include <mlpack/methods/ann/visitor/weight_set_visitor.hpp>
#include "metrics/inception_score.hpp"
namespace mlpack {
@@ -65,9 +66,12 @@ class GAN
/**
* Constructor for GAN class.
*
* @param trainData The real data.
* @param generator Generator network.
* @param discriminator Discriminator network.
* @param initializeRule Initialization rule to use for initializing
* parameters.
* @param noiseFunction Function to be used for generating noise.
* @param noiseDim Dimension of noise vector to be created.
* @param batchSize Batch size to be used for training.
* @param generatorUpdateStep Number of steps to train Discriminator
* before updating Generator.
@@ -76,8 +80,7 @@ class GAN
* @param clippingParameter Weight range for enforcing Lipschitz constraint.
* @param lambda Parameter for setting the gradient penalty.
*/
GAN(arma::mat& trainData,
Model generator,
GAN(Model generator,
Model discriminator,
InitializationRuleType& initializeRule,
Noise& noiseFunction,
@@ -95,16 +98,32 @@ class GAN
//! Move constructor.
GAN(GAN&&);
/**
* Initialize the generator, discriminator and weights of the model for
* training. This function won't actually trigger training process.
*
* @param trainData The data points of real distribution.
*/
void ResetData(arma::mat trainData);
// Reset function.
void Reset();
/**
* Train function.
*
*
* @tparam OptimizerType Type of optimizer to use to train the model.
* @tparam CallbackTypes Types of Callback functions.
* @param trainData The data points of real distribution.
* @param optimizer Instantiated optimizer used to train the model.
* @param callbacks Callback function for ensmallen optimizer `OptimizerType`.
* See https://www.ensmallen.org/docs.html#callback-documentation.
* @return The final objective of the trained model (NaN or Inf on error).
*/
template<typename OptimizerType>
double Train(OptimizerType& Optimizer);
template<typename OptimizerType, typename... CallbackTypes>
double Train(arma::mat trainData,
OptimizerType& Optimizer,
CallbackTypes&&... callbacks);
/**
* Evaluate function for the Standard GAN and DCGAN.
@@ -275,11 +294,10 @@ class GAN
/**
* This function predicts the output of the network on the given input.
*
* @param input The input the Discriminator network.
* @param input The input of the Generator network.
* @param output Result of the Discriminator network.
*/
void Predict(arma::mat&& input,
arma::mat& output);
void Predict(arma::mat input, arma::mat& output);
//! Return the parameters of the network.
const arma::mat& Parameters() const { return parameter; }
@@ -313,6 +331,12 @@ class GAN
void serialize(Archive& ar, const unsigned int /* version */);
private:
/**
* Reset the module status by setting the current deterministic parameter
* for the discriminator and generator networks and their respective layers.
*/
void ResetDeterministic();
//! Locally stored parameter for training data + noise data.
arma::mat predictors;
//! Locally stored parameters of the network.
@@ -331,8 +355,6 @@ class GAN
size_t numFunctions;
//! Locally stored batch size parameter.
size_t batchSize;
//! Locally stored number of iterations that have been completed.
size_t counter;
//! Locally stored batch number which is being processed.
size_t currentBatch;
//! Locally stored number of training step before Generator is trained.
@@ -373,8 +395,12 @@ class GAN
arma::mat noise;
//! Locally stored gradient for Generator.
arma::mat gradientGenerator;
//! Locally stored output of the Generator network.
arma::mat ganOutput;
//! The current evaluation mode (training or testing).
bool deterministic;
//! To keep track of number of generator weights in total weights.
size_t genWeights;
//! To keep track of number of discriminator weights in total weights.
size_t discWeights;
};
} // namespace ann
+145 -50
View File
@@ -30,7 +30,6 @@ template<
typename PolicyType
>
GAN<Model, InitializationRuleType, Noise, PolicyType>::GAN(
arma::mat& predictors,
Model generator,
Model discriminator,
InitializationRuleType& initializeRule,
@@ -47,41 +46,23 @@ GAN<Model, InitializationRuleType, Noise, PolicyType>::GAN(
initializeRule(initializeRule),
noiseFunction(noiseFunction),
noiseDim(noiseDim),
numFunctions(0),
batchSize(batchSize),
currentBatch(0),
generatorUpdateStep(generatorUpdateStep),
preTrainSize(preTrainSize),
multiplier(multiplier),
clippingParameter(clippingParameter),
lambda(lambda),
reset(false)
reset(false),
deterministic(false),
genWeights(0),
discWeights(0)
{
// Insert IdentityLayer for joining the Generator and Discriminator.
this->discriminator.network.insert(
this->discriminator.network.begin(),
new IdentityLayer<>());
counter = 0;
currentBatch = 0;
this->discriminator.deterministic = this->generator.deterministic = true;
this->predictors.set_size(predictors.n_rows, predictors.n_cols + batchSize);
this->predictors.cols(0, predictors.n_cols - 1) = predictors;
this->discriminator.predictors = arma::mat(this->predictors.memptr(),
this->predictors.n_rows, this->predictors.n_cols, false, false);
responses.ones(1, predictors.n_cols + batchSize);
responses.cols(predictors.n_cols,
predictors.n_cols + batchSize - 1) = arma::zeros(1, batchSize);
this->discriminator.responses = arma::mat(this->responses.memptr(),
this->responses.n_rows, this->responses.n_cols, false, false);
numFunctions = predictors.n_cols;
noise.set_size(noiseDim, batchSize);
this->generator.predictors.set_size(noiseDim, batchSize);
this->generator.responses.set_size(predictors.n_rows, batchSize);
}
template<
@@ -106,11 +87,13 @@ GAN<Model, InitializationRuleType, Noise, PolicyType>::GAN(
clippingParameter(network.clippingParameter),
lambda(network.lambda),
reset(network.reset),
counter(network.counter),
currentBatch(network.currentBatch),
parameter(network.parameter),
numFunctions(network.numFunctions),
noise(network.noise)
noise(network.noise),
deterministic(network.deterministic),
genWeights(network.genWeights),
discWeights(network.discWeights)
{
/* Nothing to do here */
}
@@ -137,15 +120,59 @@ GAN<Model, InitializationRuleType, Noise, PolicyType>::GAN(
clippingParameter(network.clippingParameter),
lambda(network.lambda),
reset(network.reset),
counter(network.counter),
currentBatch(network.currentBatch),
parameter(std::move(network.parameter)),
numFunctions(network.numFunctions),
noise(std::move(network.noise))
noise(std::move(network.noise)),
deterministic(network.deterministic),
genWeights(network.genWeights),
discWeights(network.discWeights)
{
/* Nothing to do here */
}
template<
typename Model,
typename InitializationRuleType,
typename Noise,
typename PolicyType
>
void GAN<Model, InitializationRuleType, Noise, PolicyType>::ResetData(
arma::mat trainData)
{
currentBatch = 0;
numFunctions = trainData.n_cols;
noise.set_size(noiseDim, batchSize);
deterministic = true;
ResetDeterministic();
/**
* These predictors are shared by the discriminator network. The additional
* batch size predictors are taken from the generator network while training.
* For more details please look in EvaluateWithGradient() function.
*/
this->predictors.set_size(trainData.n_rows, numFunctions + batchSize);
this->predictors.cols(0, numFunctions - 1) = std::move(trainData);
this->discriminator.predictors = arma::mat(this->predictors.memptr(),
this->predictors.n_rows, this->predictors.n_cols, false, false);
responses.ones(1, numFunctions + batchSize);
responses.cols(numFunctions, numFunctions + batchSize - 1) =
arma::zeros(1, batchSize);
this->discriminator.responses = arma::mat(this->responses.memptr(),
this->responses.n_rows, this->responses.n_cols, false, false);
this->generator.predictors.set_size(noiseDim, batchSize);
this->generator.responses.set_size(predictors.n_rows, batchSize);
if (!reset)
{
Reset();
}
}
template<
typename Model,
typename InitializationRuleType,
@@ -154,8 +181,8 @@ template<
>
void GAN<Model, InitializationRuleType, Noise, PolicyType>::Reset()
{
size_t genWeights = 0;
size_t discWeights = 0;
genWeights = 0;
discWeights = 0;
NetworkInitialization<InitializationRuleType> networkInit(initializeRule);
@@ -190,13 +217,15 @@ template<
typename Noise,
typename PolicyType
>
template<typename OptimizerType>
template<typename OptimizerType, typename... CallbackTypes>
double GAN<Model, InitializationRuleType, Noise, PolicyType>::Train(
OptimizerType& Optimizer)
arma::mat trainData,
OptimizerType& Optimizer,
CallbackTypes&&... callbacks)
{
if (!reset)
Reset();
return Optimizer.Optimize(*this, parameter);
ResetData(std::move(trainData));
return Optimizer.Optimize(*this, parameter, callbacks...);
}
template<
@@ -213,8 +242,16 @@ GAN<Model, InitializationRuleType, Noise, PolicyType>::Evaluate(
const size_t i,
const size_t /* batchSize */)
{
if (!reset)
if (parameter.is_empty())
{
Reset();
}
if (!deterministic)
{
deterministic = true;
ResetDeterministic();
}
currentInput = arma::mat(predictors.memptr() + (i * predictors.n_rows),
predictors.n_rows, batchSize, false, false);
@@ -262,8 +299,10 @@ EvaluateWithGradient(const arma::mat& /* parameters */,
GradType& gradient,
const size_t /* batchSize */)
{
if (!reset)
if (parameter.is_empty())
{
Reset();
}
if (gradient.is_empty())
{
@@ -274,6 +313,12 @@ EvaluateWithGradient(const arma::mat& /* parameters */,
else
gradient.zeros();
if (this->deterministic)
{
this->deterministic = false;
ResetDeterministic();
}
if (noiseGradientDiscriminator.is_empty())
{
noiseGradientDiscriminator = arma::zeros<arma::mat>(
@@ -325,14 +370,8 @@ EvaluateWithGradient(const arma::mat& /* parameters */,
gradientGenerator *= multiplier;
}
counter++;
currentBatch++;
// Revert the counter to zero, if the total dataset get's covered.
if (counter * batchSize >= numFunctions)
{
counter = 0;
}
if (preTrainSize > 0)
{
@@ -382,12 +421,13 @@ template<
void GAN<Model, InitializationRuleType, Noise, PolicyType>::Forward(
arma::mat&& input)
{
if (!reset)
if (parameter.is_empty())
{
Reset();
}
generator.Forward(std::move(input));
ganOutput = boost::apply_visitor(
outputParameterVisitor,
arma::mat ganOutput = boost::apply_visitor(outputParameterVisitor,
generator.network.back());
discriminator.Forward(std::move(ganOutput));
@@ -400,10 +440,18 @@ template<
typename PolicyType
>
void GAN<Model, InitializationRuleType, Noise, PolicyType>::
Predict(arma::mat&& input, arma::mat& output)
Predict(arma::mat input, arma::mat& output)
{
if (!reset)
if (parameter.is_empty())
{
Reset();
}
if (!deterministic)
{
deterministic = true;
ResetDeterministic();
}
Forward(std::move(input));
@@ -411,6 +459,21 @@ Predict(arma::mat&& input, arma::mat& output)
discriminator.network.back());
}
template<
typename Model,
typename InitializationRuleType,
typename Noise,
typename PolicyType
>
void GAN<Model, InitializationRuleType, Noise, PolicyType>::
ResetDeterministic()
{
this->discriminator.deterministic = deterministic;
this->generator.deterministic = deterministic;
this->discriminator.ResetDeterministic();
this->generator.ResetDeterministic();
}
template<
typename Model,
typename InitializationRuleType,
@@ -424,7 +487,39 @@ serialize(Archive& ar, const unsigned int /* version */)
ar & BOOST_SERIALIZATION_NVP(parameter);
ar & BOOST_SERIALIZATION_NVP(generator);
ar & BOOST_SERIALIZATION_NVP(discriminator);
ar & BOOST_SERIALIZATION_NVP(noiseFunction);
ar & BOOST_SERIALIZATION_NVP(reset);
ar & BOOST_SERIALIZATION_NVP(genWeights);
ar & BOOST_SERIALIZATION_NVP(discWeights);
if (Archive::is_loading::value)
{
// Share the parameters between the network.
generator.Parameters() = arma::mat(parameter.memptr(), genWeights, 1, false,
false);
discriminator.Parameters() = arma::mat(parameter.memptr() + genWeights,
discWeights, 1, false, false);
size_t offset = 0;
for (size_t i = 0; i < generator.network.size(); ++i)
{
offset += boost::apply_visitor(WeightSetVisitor(std::move(
generator.parameter), offset), generator.network[i]);
boost::apply_visitor(resetVisitor, generator.network[i]);
}
offset = 0;
for (size_t i = 0; i < discriminator.network.size(); ++i)
{
offset += boost::apply_visitor(WeightSetVisitor(std::move(
discriminator.parameter), offset), discriminator.network[i]);
boost::apply_visitor(resetVisitor, discriminator.network[i]);
}
deterministic = true;
ResetDeterministic();
}
}
} // namespace ann
@@ -0,0 +1,15 @@
# Define the files we need to compile.
# Anything not in this list will not be compiled into mlpack.
set(SOURCES
inception_score
inception_score_impl
)
# Add directory name to sources.
set(DIR_SRCS)
foreach(file ${SOURCES})
set(DIR_SRCS ${DIR_SRCS} ${CMAKE_CURRENT_SOURCE_DIR}/${file})
endforeach()
# Append sources (with directory name) to list of all mlpack sources (used at
# the parent scope).
set(MLPACK_SRCS ${MLPACK_SRCS} ${DIR_SRCS} PARENT_SCOPE)
@@ -0,0 +1,49 @@
/**
* @file inception_score.hpp
* @author Saksham Bansal
*
* Definition of Inception Score for Generative Adversarial Networks.
*
* 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_METRICS_INCEPTION_SCORE_HPP
#define MLPACK_METHODS_METRICS_INCEPTION_SCORE_HPP
#include <mlpack/prereqs.hpp>
namespace mlpack {
namespace ann /* Artificial Neural Network */ {
/**
* Function that computes Inception Score for a set of images produced by a GAN.
* For more information, see the following.
*
* @code
* @article{Goodfellow2016,
* author = {Tim Salimans, Ian Goodfellow, Wojciech Zaremba, Vicki Cheung,
* Alec Radford, Xi Chen},
* title = {Improved Techniques for Training GANs},
* year = {2016},
* url = {https://arxiv.org/abs/1606.03498},
* }
* @endcode
*
* @param Model Model for evaluating the quality of images.
* @param images Images generated by GAN.
*/
template<typename ModelType>
double InceptionScore(ModelType Model,
arma::mat images,
size_t splits = 1);
} // namespace ann
} // namespace mlpack
#include "inception_score_impl.hpp"
#endif
@@ -0,0 +1,59 @@
/**
* @file inception_score_impl.hpp
* @author Saksham Bansal
*
* Definition of Inception Score for Generative Adversarial Networks.
*
* 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_METRICS_INCEPTION_SCORE_IMPL_HPP
#define MLPACK_METHODS_METRICS_INCEPTION_SCORE_IMPL_HPP
// In case it hasn't been included yet.
#include "inception_score.hpp"
namespace mlpack {
namespace ann /* Artificial Neural Network */ {
template <typename ModelType>
double InceptionScore(ModelType model,
arma::mat images,
size_t splits)
{
size_t samples = images.n_cols;
size_t splitSize = samples / splits;
size_t remainder = samples % splits;
arma::mat preds;
model.Predict(images, preds);
size_t index = 0;
arma::vec scores = arma::vec(splits);
for (int i = 0; i < splits; i++)
{
size_t curSize = splitSize;
if (remainder)
{
curSize++;
remainder--;
}
arma::mat curPreds =
arma::mat(preds.colptr(index), preds.n_rows, curSize, false, true);
arma::colvec c = arma::log(arma::mean(curPreds, 1));
arma::mat temp = arma::log(curPreds);
temp.each_col() -= c;
curPreds %= temp;
scores(i) = exp(arma::as_scalar(arma::mean(arma::sum(curPreds, 0))));
index += curSize;
}
return arma::mean(scores);
}
} // namespace ann
} // namespace mlpack
#endif
+18 -9
View File
@@ -34,8 +34,16 @@ GAN<Model, InitializationRuleType, Noise, PolicyType>::Evaluate(
const size_t i,
const size_t /* batchSize */)
{
if (!reset)
if (parameter.is_empty())
{
Reset();
}
if (!deterministic)
{
deterministic = true;
ResetDeterministic();
}
currentInput = arma::mat(predictors.memptr() + (i * predictors.n_rows),
predictors.n_rows, batchSize, false, false);
@@ -82,8 +90,10 @@ EvaluateWithGradient(const arma::mat& /* parameters */,
GradType& gradient,
const size_t /* batchSize */)
{
if (!reset)
if (parameter.is_empty())
{
Reset();
}
if (gradient.is_empty())
{
@@ -94,6 +104,12 @@ EvaluateWithGradient(const arma::mat& /* parameters */,
else
gradient.zeros();
if (this->deterministic)
{
this->deterministic = false;
ResetDeterministic();
}
if (noiseGradientDiscriminator.is_empty())
{
noiseGradientDiscriminator = arma::zeros<arma::mat>(
@@ -147,15 +163,8 @@ EvaluateWithGradient(const arma::mat& /* parameters */,
gradientGenerator *= multiplier;
}
counter++;
currentBatch++;
// Revert the counter to zero, if the total dataset get's covered.
if (counter * batchSize >= numFunctions)
{
counter = 0;
}
if (preTrainSize > 0)
{
preTrainSize--;
+18 -9
View File
@@ -35,8 +35,16 @@ GAN<Model, InitializationRuleType, Noise, PolicyType>::Evaluate(
const size_t i,
const size_t /* batchSize */)
{
if (!reset)
if ((parameter.is_empty()))
{
Reset();
}
if (!deterministic)
{
deterministic = true;
ResetDeterministic();
}
currentInput = arma::mat(predictors.memptr() + (i * predictors.n_rows),
predictors.n_rows, batchSize, false, false);
@@ -96,8 +104,10 @@ EvaluateWithGradient(const arma::mat& /* parameters */,
GradType& gradient,
const size_t /* batchSize */)
{
if (!reset)
if (parameter.is_empty())
{
Reset();
}
if (gradient.is_empty())
{
@@ -108,6 +118,12 @@ EvaluateWithGradient(const arma::mat& /* parameters */,
else
gradient.zeros();
if (this->deterministic)
{
this->deterministic = false;
ResetDeterministic();
}
if (noiseGradientDiscriminator.is_empty())
{
noiseGradientDiscriminator = arma::zeros<arma::mat>(
@@ -171,15 +187,8 @@ EvaluateWithGradient(const arma::mat& /* parameters */,
gradientGenerator *= multiplier;
}
counter++;
currentBatch++;
// Revert the counter to zero, if the total dataset get's covered.
if (counter * batchSize >= numFunctions)
{
counter = 0;
}
if (preTrainSize > 0)
{
preTrainSize--;
@@ -40,6 +40,8 @@ set(SOURCES
gru_impl.hpp
hard_tanh.hpp
hard_tanh_impl.hpp
highway.hpp
highway_impl.hpp
join.hpp
join_impl.hpp
layer.hpp
@@ -63,6 +65,8 @@ set(SOURCES
max_pooling_impl.hpp
mean_pooling.hpp
mean_pooling_impl.hpp
minibatch_discrimination.hpp
minibatch_discrimination_impl.hpp
multiply_constant.hpp
multiply_constant_impl.hpp
multiply_merge.hpp
@@ -88,6 +92,8 @@ set(SOURCES
vr_class_reward_impl.hpp
c_relu.hpp
c_relu_impl.hpp
weight_norm.hpp
weight_norm_impl.hpp
)
# Add directory name to sources.
@@ -37,7 +37,6 @@ namespace ann /** Artificial Neural Network. */ {
* journal = {Advances in Neural Information Processing Systems},
* year = {2017}
* }
* }
* @endcode
*
* @tparam InputDataType Type of the input data (arma::colvec, arma::mat,
@@ -21,6 +21,7 @@
#include <mlpack/methods/ann/convolution_rules/svd_convolution.hpp>
#include "layer_types.hpp"
#include "padding.hpp"
namespace mlpack{
namespace ann /** Artificial Neural Network. */ {
@@ -70,6 +71,7 @@ class AtrousConvolution
* @param inputHeight The height of the input data.
* @param dilationW The space between the cells of filters in x direction.
* @param dilationH The space between the cells of filters in y direction.
* @param paddingType The type of padding (Valid or Same). Defaults to None.
*/
AtrousConvolution(const size_t inSize,
const size_t outSize,
@@ -82,7 +84,45 @@ class AtrousConvolution
const size_t inputWidth = 0,
const size_t inputHeight = 0,
const size_t dilationW = 1,
const size_t dilationH = 1);
const size_t dilationH = 1,
const std::string paddingType = "None");
/**
* Create the AtrousConvolution object using the specified number of
* input maps, output maps, filter size, stride, dilation and
* padding parameter.
*
* @param inSize The number of input maps.
* @param outSize The number of output maps.
* @param kW Width of the filter/kernel.
* @param kH Height of the filter/kernel.
* @param dW Stride of filter application in the x direction.
* @param dH Stride of filter application in the y direction.
* @param padW A two-value tuple indicating padding widths of the input.
* First value is padding at left side. Second value is padding on
* right side.
* @param padH A two-value tuple indicating padding heights of the input.
* First value is padding at top. Second value is padding on
* bottom.
* @param inputWidth The widht of the input data.
* @param inputHeight The height of the input data.
* @param dilationW The space between the cells of filters in x direction.
* @param dilationH The space between the cells of filters in y direction.
* @param paddingType The type of padding (Valid or Same). Defaults to None.
*/
AtrousConvolution(const size_t inSize,
const size_t outSize,
const size_t kW,
const size_t kH,
const size_t dW,
const size_t dH,
const std::tuple<size_t, size_t> padW,
const std::tuple<size_t, size_t> padH,
const size_t inputWidth = 0,
const size_t inputHeight = 0,
const size_t dilationW = 1,
const size_t dilationH = 1,
const std::string paddingType = "None");
/*
* Set the weight and bias term.
@@ -165,6 +205,9 @@ class AtrousConvolution
//! Modify the output height.
size_t& OutputHeight() { return outputHeight; }
//! Modify the bias weights of the layer.
arma::mat& Bias() { return bias; }
/**
* Serialize the layer
*/
@@ -178,19 +221,26 @@ class AtrousConvolution
* @param size The size of the input (row or column).
* @param k The size of the filter (width or height).
* @param s The stride size (x or y direction).
* @param p The size of the padding (width or height).
* @param pSideOne The size of the padding (width or height) on one side.
* @param pSideTwo The size of the padding (width or height) on another side.
* @param d The dilation size.
* @return The convolution output size.
*/
size_t ConvOutSize(const size_t size,
const size_t k,
const size_t s,
const size_t p,
const size_t d)
const size_t k,
const size_t s,
const size_t pSideOne,
const size_t pSideTwo,
const size_t d)
{
return std::floor(size + p * 2 - d * (k - 1) - 1) / s + 1;
return std::floor(size + pSideOne + pSideTwo - d * (k - 1) - 1) / s + 1;
}
/*
* Function to assign padding such that output size is same as input size.
*/
void InitializeSamePadding();
/*
* Rotates a 3rd-order tensor counterclockwise by 180 degrees.
*
@@ -220,53 +270,6 @@ class AtrousConvolution
output = arma::fliplr(arma::flipud(input));
}
/*
* Pad the given input data.
*
* @param input The input to be padded.
* @param wPad Padding width of the input.
* @param hPad Padding height of the input.
* @param output The padded output data.
*/
template<typename eT>
void Pad(const arma::Mat<eT>& input,
size_t wPad,
size_t hPad,
arma::Mat<eT>& output)
{
if (output.n_rows != input.n_rows + wPad * 2 ||
output.n_cols != input.n_cols + hPad * 2)
{
output = arma::zeros(input.n_rows + wPad * 2, input.n_cols + hPad * 2);
}
output.submat(wPad, hPad, wPad + input.n_rows - 1,
hPad + input.n_cols - 1) = input;
}
/*
* Pad the given input data.
*
* @param input The input to be padded.
* @param wPad Padding width of the input.
* @param hPad Padding height of the input.
* @param output The padded output data.
*/
template<typename eT>
void Pad(const arma::Cube<eT>& input,
size_t wPad,
size_t hPad,
arma::Cube<eT>& output)
{
output = arma::zeros(input.n_rows + wPad * 2,
input.n_cols + hPad * 2, input.n_slices);
for (size_t i = 0; i < input.n_slices; ++i)
{
Pad<double>(input.slice(i), wPad, hPad, output.slice(i));
}
}
//! Locally-stored number of input channels.
size_t inSize;
@@ -288,11 +291,17 @@ class AtrousConvolution
//! Locally-stored stride of the filter in y-direction.
size_t dH;
//! Locally-stored padding width.
size_t padW;
//! Locally-stored left-side padding width.
size_t padWLeft;
//! Locally-stored padding height.
size_t padH;
//! Locally-stored right-side padding width.
size_t padWRight;
//! Locally-stored bottom padding height.
size_t padHBottom;
//! Locally-stored top padding height.
size_t padHTop;
//! Locally-stored weight object.
OutputDataType weights;
@@ -336,6 +345,9 @@ class AtrousConvolution
//! Locally-stored transformed gradient parameter.
arma::cube gradientTemp;
//! Locally-stored padding layer.
Padding<>* padding;
//! Locally-stored delta object.
OutputDataType delta;
@@ -349,6 +361,28 @@ class AtrousConvolution
} // namespace ann
} // namespace mlpack
//! Set the serialization version of the AtrousConvolution class.
namespace boost {
namespace serialization {
template<
typename ForwardConvolutionRule,
typename BackwardConvolutionRule,
typename GradientConvolutionRule,
typename InputDataType,
typename OutputDataType
>
struct version<
mlpack::ann::AtrousConvolution<ForwardConvolutionRule,
BackwardConvolutionRule, GradientConvolutionRule, InputDataType,
OutputDataType> >
{
BOOST_STATIC_CONSTANT(int, value = 1);
};
} // namespace serialization
} // namespace boost
// Include implementation
#include "atrous_convolution_impl.hpp"
@@ -62,15 +62,18 @@ AtrousConvolution<
const size_t inputWidth,
const size_t inputHeight,
const size_t dilationW,
const size_t dilationH) :
const size_t dilationH,
const std::string paddingType) :
inSize(inSize),
outSize(outSize),
kW(kW),
kH(kH),
dW(dW),
dH(dH),
padW(padW),
padH(padH),
padWLeft(padW),
padWRight(padW),
padHBottom(padH),
padHTop(padH),
inputWidth(inputWidth),
inputHeight(inputHeight),
outputWidth(0),
@@ -79,6 +82,91 @@ AtrousConvolution<
dilationH(dilationH)
{
weights.set_size((outSize * inSize * kW * kH) + outSize, 1);
// Transform paddingType to lowercase.
std::string paddingTypeLow = paddingType;
std::transform(paddingType.begin(), paddingType.end(), paddingTypeLow.begin(),
[](unsigned char c){ return std::tolower(c); });
if (paddingTypeLow == "valid")
{
padWLeft = 0;
padWRight = 0;
padHTop = 0;
padHBottom = 0;
}
else if (paddingTypeLow == "same")
{
InitializeSamePadding();
}
padding = new Padding<>(padWLeft, padWRight, padHTop, padHBottom);
}
template<
typename ForwardConvolutionRule,
typename BackwardConvolutionRule,
typename GradientConvolutionRule,
typename InputDataType,
typename OutputDataType
>
AtrousConvolution<
ForwardConvolutionRule,
BackwardConvolutionRule,
GradientConvolutionRule,
InputDataType,
OutputDataType
>::AtrousConvolution(
const size_t inSize,
const size_t outSize,
const size_t kW,
const size_t kH,
const size_t dW,
const size_t dH,
const std::tuple<size_t, size_t> padW,
const std::tuple<size_t, size_t> padH,
const size_t inputWidth,
const size_t inputHeight,
const size_t dilationW,
const size_t dilationH,
const std::string paddingType) :
inSize(inSize),
outSize(outSize),
kW(kW),
kH(kH),
dW(dW),
dH(dH),
padWLeft(std::get<0>(padW)),
padWRight(std::get<1>(padW)),
padHBottom(std::get<1>(padH)),
padHTop(std::get<0>(padH)),
inputWidth(inputWidth),
inputHeight(inputHeight),
outputWidth(0),
outputHeight(0),
dilationW(dilationW),
dilationH(dilationH)
{
weights.set_size((outSize * inSize * kW * kH) + outSize, 1);
// Transform paddingType to lowercase.
std::string paddingTypeLow = paddingType;
std::transform(paddingType.begin(), paddingType.end(), paddingTypeLow.begin(),
[](unsigned char c){ return std::tolower(c); });
if (paddingTypeLow == "valid")
{
padWLeft = 0;
padWRight = 0;
padHTop = 0;
padHBottom = 0;
}
else if (paddingTypeLow == "same")
{
InitializeSamePadding();
}
padding = new Padding<>(padWLeft, padWRight, padHTop, padHBottom);
}
template<
@@ -122,13 +210,22 @@ void AtrousConvolution<
inputTemp = arma::cube(const_cast<arma::Mat<eT>&&>(input).memptr(),
inputWidth, inputHeight, inSize * batchSize, false, false);
if (padW != 0 || padH != 0)
if (padWLeft != 0 || padWRight != 0 || padHTop != 0 || padHBottom != 0)
{
Pad(inputTemp, padW, padH, inputPaddedTemp);
inputPaddedTemp.set_size(inputTemp.n_rows + padWLeft + padWRight,
inputTemp.n_cols + padHTop + padHBottom, inputTemp.n_slices);
for (size_t i = 0; i < inputTemp.n_slices; ++i)
{
padding->Forward(std::move(inputTemp.slice(i)),
std::move(inputPaddedTemp.slice(i)));
}
}
size_t wConv = ConvOutSize(inputWidth, kW, dW, padW, dilationW);
size_t hConv = ConvOutSize(inputHeight, kH, dH, padH, dilationH);
size_t wConv = ConvOutSize(inputWidth, kW, dW, padWLeft, padWRight,
dilationW);
size_t hConv = ConvOutSize(inputHeight, kH, dH, padHTop, padHBottom,
dilationH);
output.set_size(wConv * hConv * outSize, batchSize);
outputTemp = arma::Cube<eT>(output.memptr(), wConv, hConv,
@@ -148,7 +245,7 @@ void AtrousConvolution<
{
arma::Mat<eT> convOutput;
if (padW != 0 || padH != 0)
if (padWLeft != 0 || padWRight != 0 || padHTop != 0 || padHBottom != 0)
{
ForwardConvolutionRule::Convolution(inputPaddedTemp.slice(inMap +
batchCount * inSize), weight.slice(outMapIdx), convOutput, dW, dH,
@@ -213,11 +310,10 @@ void AtrousConvolution<
BackwardConvolutionRule::Convolution(mappedError.slice(outMap),
rotatedFilter, output, dW, dH, dilationW, dilationH);
if (padW != 0 || padH != 0)
if (padWLeft != 0 || padWRight != 0 || padHTop != 0 || padHBottom != 0)
{
gTemp.slice(inMap + batchCount * inSize) += output.submat(padW, padH,
padW + gTemp.n_rows - 1,
padH + gTemp.n_cols - 1);
gTemp.slice(inMap + batchCount * inSize) += output.submat(padWLeft,
padHTop, padWLeft + gTemp.n_rows - 1, padHTop + gTemp.n_cols - 1);
}
else
{
@@ -266,7 +362,7 @@ void AtrousConvolution<
for (size_t inMap = 0; inMap < inSize; inMap++, outMapIdx++)
{
arma::Mat<eT> inputSlice;
if (padW != 0 || padH != 0)
if (padWLeft != 0 || padWRight != 0 || padHTop != 0 || padHBottom != 0)
{
inputSlice = inputPaddedTemp.slice(inMap + batchCount * inSize);
}
@@ -331,8 +427,7 @@ void AtrousConvolution<
GradientConvolutionRule,
InputDataType,
OutputDataType
>::serialize(
Archive& ar, const unsigned int /* version */)
>::serialize(Archive& ar, const unsigned int version)
{
ar & BOOST_SERIALIZATION_NVP(inSize);
ar & BOOST_SERIALIZATION_NVP(outSize);
@@ -341,8 +436,10 @@ void AtrousConvolution<
ar & BOOST_SERIALIZATION_NVP(kH);
ar & BOOST_SERIALIZATION_NVP(dW);
ar & BOOST_SERIALIZATION_NVP(dH);
ar & BOOST_SERIALIZATION_NVP(padW);
ar & BOOST_SERIALIZATION_NVP(padH);
ar & BOOST_SERIALIZATION_NVP(padWLeft);
ar & BOOST_SERIALIZATION_NVP(padWRight);
ar & BOOST_SERIALIZATION_NVP(padHBottom);
ar & BOOST_SERIALIZATION_NVP(padHTop);
ar & BOOST_SERIALIZATION_NVP(inputWidth);
ar & BOOST_SERIALIZATION_NVP(inputHeight);
ar & BOOST_SERIALIZATION_NVP(outputWidth);
@@ -350,10 +447,42 @@ void AtrousConvolution<
ar & BOOST_SERIALIZATION_NVP(dilationW);
ar & BOOST_SERIALIZATION_NVP(dilationH);
if (version > 0)
ar & BOOST_SERIALIZATION_NVP(padding);
if (Archive::is_loading::value)
weights.set_size((outSize * inSize * kW * kH) + outSize, 1);
}
template<
typename ForwardConvolutionRule,
typename BackwardConvolutionRule,
typename GradientConvolutionRule,
typename InputDataType,
typename OutputDataType
>
void AtrousConvolution<
ForwardConvolutionRule,
BackwardConvolutionRule,
GradientConvolutionRule,
InputDataType,
OutputDataType
>::InitializeSamePadding()
{
/*
* Using O = (W - F + 2P) / s + 1;
*/
size_t totalVerticalPadding = (dW - 1) * inputWidth + kW - dW + (dilationW -
1) * (kW - 1);
size_t totalHorizontalPadding = (dH - 1) * inputHeight + kH - dH + (dilationH
- 1) * (kH - 1);
padWLeft = totalVerticalPadding / 2;
padWRight = totalVerticalPadding - totalVerticalPadding / 2;
padHTop = totalHorizontalPadding / 2;
padHBottom = totalHorizontalPadding - totalHorizontalPadding / 2;
}
} // namespace ann
} // namespace mlpack
+1 -1
View File
@@ -151,7 +151,7 @@ class BatchNorm
//! Locally-stored epsilon value.
double eps;
//! Whether we are in loading or saving mode.
//! Variable to keep track of whether we are in loading or saving mode.
bool loading;
//! Locally-stored scale parameter.
@@ -110,7 +110,7 @@ void BatchNorm<InputDataType, OutputDataType>::Backward(
{
const arma::mat stdInv = 1.0 / arma::sqrt(variance + eps);
// Step 1: dl / dxhat
// Step 1: dl / dxhat.
const arma::mat norm = gy.each_col() % gamma;
// Step 2: sum dl / dxhat * (x - mu) * -0.5 * stdInv^3.
+83 -55
View File
@@ -20,6 +20,7 @@
#include <mlpack/methods/ann/convolution_rules/svd_convolution.hpp>
#include "layer_types.hpp"
#include "padding.hpp"
namespace mlpack {
namespace ann /** Artificial Neural Network. */ {
@@ -63,6 +64,7 @@ class Convolution
* @param padH Padding height of the input.
* @param inputWidth The width of the input data.
* @param inputHeight The height of the input data.
* @param paddingType The type of padding (Valid or Same). Defaults to None.
*/
Convolution(const size_t inSize,
const size_t outSize,
@@ -73,7 +75,40 @@ class Convolution
const size_t padW = 0,
const size_t padH = 0,
const size_t inputWidth = 0,
const size_t inputHeight = 0);
const size_t inputHeight = 0,
const std::string paddingType = "None");
/**
* Create the Convolution object using the specified number of input maps,
* output maps, filter size, stride and padding parameter.
*
* @param inSize The number of input maps.
* @param outSize The number of output maps.
* @param kW Width of the filter/kernel.
* @param kH Height of the filter/kernel.
* @param dW Stride of filter application in the x direction.
* @param dH Stride of filter application in the y direction.
* @param padW A two-value tuple indicating padding widths of the input.
* First value is padding at left side. Second value is padding on
* right side.
* @param padH A two-value tuple indicating padding heights of the input.
* First value is padding at top. Second value is padding on
* bottom.
* @param inputWidth The width of the input data.
* @param inputHeight The height of the input data.
* @param paddingType The type of padding (Valid or Same). Defaults to None.
*/
Convolution(const size_t inSize,
const size_t outSize,
const size_t kW,
const size_t kH,
const size_t dW,
const size_t dH,
const std::tuple<size_t, size_t> padW,
const std::tuple<size_t, size_t> padH,
const size_t inputWidth = 0,
const size_t inputHeight = 0,
const std::string paddingType = "None");
/*
* Set the weight and bias term.
@@ -161,6 +196,9 @@ class Convolution
//! Modify the output height.
size_t& OutputHeight() { return outputHeight; }
//! Modify the bias weights of the layer.
arma::mat& Bias() { return bias; }
/**
* Serialize the layer
*/
@@ -174,17 +212,24 @@ class Convolution
* @param size The size of the input (row or column).
* @param k The size of the filter (width or height).
* @param s The stride size (x or y direction).
* @param p The size of the padding (width or height).
* @param pSideOne The size of the padding (width or height) on one side.
* @param pSideTwo The size of the padding (width or height) on another side.
* @return The convolution output size.
*/
size_t ConvOutSize(const size_t size,
const size_t k,
const size_t s,
const size_t p)
const size_t pSideOne,
const size_t pSideTwo)
{
return std::floor(size + p * 2 - k) / s + 1;
return std::floor(size + pSideOne + pSideTwo - k) / s + 1;
}
/*
* Function to assign padding such that output size is same as input size.
*/
void InitializeSamePadding();
/*
* Rotates a 3rd-order tensor counterclockwise by 180 degrees.
*
@@ -214,53 +259,6 @@ class Convolution
output = arma::fliplr(arma::flipud(input));
}
/*
* Pad the given input data.
*
* @param input The input to be padded.
* @param wPad Padding width of the input.
* @param hPad Padding height of the input.
* @param output The padded output data.
*/
template<typename eT>
void Pad(const arma::Mat<eT>& input,
size_t wPad,
size_t hPad,
arma::Mat<eT>& output)
{
if (output.n_rows != input.n_rows + wPad * 2 ||
output.n_cols != input.n_cols + hPad * 2)
{
output = arma::zeros(input.n_rows + wPad * 2, input.n_cols + hPad * 2);
}
output.submat(wPad, hPad, wPad + input.n_rows - 1,
hPad + input.n_cols - 1) = input;
}
/*
* Pad the given input data.
*
* @param input The input to be padded.
* @param wPad Padding width of the input.
* @param hPad Padding height of the input.
* @param output The padded output data.
*/
template<typename eT>
void Pad(const arma::Cube<eT>& input,
size_t wPad,
size_t hPad,
arma::Cube<eT>& output)
{
output = arma::zeros(input.n_rows + wPad * 2,
input.n_cols + hPad * 2, input.n_slices);
for (size_t i = 0; i < input.n_slices; ++i)
{
Pad<eT>(input.slice(i), wPad, hPad, output.slice(i));
}
}
//! Locally-stored number of input channels.
size_t inSize;
@@ -282,11 +280,17 @@ class Convolution
//! Locally-stored stride of the filter in y-direction.
size_t dH;
//! Locally-stored padding width.
size_t padW;
//! Locally-stored left-side padding width.
size_t padWLeft;
//! Locally-stored padding height.
size_t padH;
//! Locally-stored right-side padding width.
size_t padWRight;
//! Locally-stored bottom padding height.
size_t padHBottom;
//! Locally-stored top padding height.
size_t padHTop;
//! Locally-stored weight object.
OutputDataType weights;
@@ -324,6 +328,9 @@ class Convolution
//! Locally-stored transformed gradient parameter.
arma::cube gradientTemp;
//! Locally-stored padding layer.
Padding<>* padding;
//! Locally-stored delta object.
OutputDataType delta;
@@ -340,6 +347,27 @@ class Convolution
} // namespace ann
} // namespace mlpack
//! Set the serialization version of the Convolution class.
namespace boost {
namespace serialization {
template<
typename ForwardConvolutionRule,
typename BackwardConvolutionRule,
typename GradientConvolutionRule,
typename InputDataType,
typename OutputDataType
>
struct version<
mlpack::ann::Convolution<ForwardConvolutionRule, BackwardConvolutionRule,
GradientConvolutionRule, InputDataType, OutputDataType> >
{
BOOST_STATIC_CONSTANT(int, value = 1);
};
} // namespace serialization
} // namespace boost
// Include implementation.
#include "convolution_impl.hpp"
+138 -17
View File
@@ -59,21 +59,105 @@ Convolution<
const size_t padW,
const size_t padH,
const size_t inputWidth,
const size_t inputHeight) :
const size_t inputHeight,
const std::string paddingType) :
inSize(inSize),
outSize(outSize),
kW(kW),
kH(kH),
dW(dW),
dH(dH),
padW(padW),
padH(padH),
padWLeft(padW),
padWRight(padW),
padHBottom(padH),
padHTop(padH),
inputWidth(inputWidth),
inputHeight(inputHeight),
outputWidth(0),
outputHeight(0)
{
weights.set_size((outSize * inSize * kW * kH) + outSize, 1);
// Transform paddingType to lowercase.
std::string paddingTypeLow = paddingType;
std::transform(paddingType.begin(), paddingType.end(), paddingTypeLow.begin(),
[](unsigned char c){ return std::tolower(c); });
if (paddingTypeLow == "valid")
{
padWLeft = 0;
padWRight = 0;
padHTop = 0;
padHBottom = 0;
}
else if (paddingTypeLow == "same")
{
InitializeSamePadding();
}
padding = new Padding<>(padWLeft, padWRight, padHTop, padHBottom);
}
template<
typename ForwardConvolutionRule,
typename BackwardConvolutionRule,
typename GradientConvolutionRule,
typename InputDataType,
typename OutputDataType
>
Convolution<
ForwardConvolutionRule,
BackwardConvolutionRule,
GradientConvolutionRule,
InputDataType,
OutputDataType
>::Convolution(
const size_t inSize,
const size_t outSize,
const size_t kW,
const size_t kH,
const size_t dW,
const size_t dH,
const std::tuple<size_t, size_t> padW,
const std::tuple<size_t, size_t> padH,
const size_t inputWidth,
const size_t inputHeight,
const std::string paddingType) :
inSize(inSize),
outSize(outSize),
kW(kW),
kH(kH),
dW(dW),
dH(dH),
padWLeft(std::get<0>(padW)),
padWRight(std::get<1>(padW)),
padHBottom(std::get<1>(padH)),
padHTop(std::get<0>(padH)),
inputWidth(inputWidth),
inputHeight(inputHeight),
outputWidth(0),
outputHeight(0)
{
weights.set_size((outSize * inSize * kW * kH) + outSize, 1);
// Transform paddingType to lowercase.
std::string paddingTypeLow = paddingType;
std::transform(paddingType.begin(), paddingType.end(), paddingTypeLow.begin(),
[](unsigned char c){ return std::tolower(c); });
if (paddingTypeLow == "valid")
{
padWLeft = 0;
padWRight = 0;
padHTop = 0;
padHBottom = 0;
}
else if (paddingTypeLow == "same")
{
InitializeSamePadding();
}
padding = new Padding<>(padWLeft, padWRight, padHTop, padHBottom);
}
template<
@@ -117,13 +201,20 @@ void Convolution<
inputTemp = arma::cube(const_cast<arma::Mat<eT>&&>(input).memptr(),
inputWidth, inputHeight, inSize * batchSize, false, false);
if (padW != 0 || padH != 0)
if (padWLeft != 0 || padWRight != 0 || padHTop != 0 || padHBottom != 0)
{
Pad(inputTemp, padW, padH, inputPaddedTemp);
inputPaddedTemp.set_size(inputTemp.n_rows + padWLeft + padWRight,
inputTemp.n_cols + padHTop + padHBottom, inputTemp.n_slices);
for (size_t i = 0; i < inputTemp.n_slices; ++i)
{
padding->Forward(std::move(inputTemp.slice(i)),
std::move(inputPaddedTemp.slice(i)));
}
}
size_t wConv = ConvOutSize(inputWidth, kW, dW, padW);
size_t hConv = ConvOutSize(inputHeight, kH, dH, padH);
size_t wConv = ConvOutSize(inputWidth, kW, dW, padWLeft, padWRight);
size_t hConv = ConvOutSize(inputHeight, kH, dH, padHTop, padHBottom);
output.set_size(wConv * hConv * outSize, batchSize);
outputTemp = arma::Cube<eT>(output.memptr(), wConv, hConv,
@@ -143,7 +234,7 @@ void Convolution<
{
arma::Mat<eT> convOutput;
if (padW != 0 || padH != 0)
if (padWLeft != 0 || padWRight != 0 || padHTop != 0 || padHBottom != 0)
{
ForwardConvolutionRule::Convolution(inputPaddedTemp.slice(inMap +
batchCount * inSize), weight.slice(outMapIdx), convOutput, dW, dH);
@@ -206,11 +297,10 @@ void Convolution<
BackwardConvolutionRule::Convolution(mappedError.slice(outMap),
rotatedFilter, output, dW, dH);
if (padW != 0 || padH != 0)
if (padWLeft != 0 || padWRight != 0 || padHTop != 0 || padHBottom != 0)
{
gTemp.slice(inMap + batchCount * inSize) += output.submat(padW, padH,
padW + gTemp.n_rows - 1,
padH + gTemp.n_cols - 1);
gTemp.slice(inMap + batchCount * inSize) += output.submat(padWLeft,
padHTop, padWLeft + gTemp.n_rows - 1, padHTop + gTemp.n_cols - 1);
}
else
{
@@ -259,7 +349,7 @@ void Convolution<
for (size_t inMap = 0; inMap < inSize; inMap++, outMapIdx++)
{
arma::Mat<eT> inputSlice;
if (padW != 0 || padH != 0)
if (padWLeft != 0 || padWRight != 0 || padHTop != 0 || padHBottom != 0)
{
inputSlice = inputPaddedTemp.slice(inMap + batchCount * inSize);
}
@@ -311,8 +401,7 @@ void Convolution<
GradientConvolutionRule,
InputDataType,
OutputDataType
>::serialize(
Archive& ar, const unsigned int /* version */)
>::serialize(Archive& ar, const unsigned int version)
{
ar & BOOST_SERIALIZATION_NVP(inSize);
ar & BOOST_SERIALIZATION_NVP(outSize);
@@ -321,17 +410,49 @@ void Convolution<
ar & BOOST_SERIALIZATION_NVP(kH);
ar & BOOST_SERIALIZATION_NVP(dW);
ar & BOOST_SERIALIZATION_NVP(dH);
ar & BOOST_SERIALIZATION_NVP(padW);
ar & BOOST_SERIALIZATION_NVP(padH);
ar & BOOST_SERIALIZATION_NVP(padWLeft);
ar & BOOST_SERIALIZATION_NVP(padWRight);
ar & BOOST_SERIALIZATION_NVP(padHBottom);
ar & BOOST_SERIALIZATION_NVP(padHTop);
ar & BOOST_SERIALIZATION_NVP(inputWidth);
ar & BOOST_SERIALIZATION_NVP(inputHeight);
ar & BOOST_SERIALIZATION_NVP(outputWidth);
ar & BOOST_SERIALIZATION_NVP(outputHeight);
if (version > 0)
ar & BOOST_SERIALIZATION_NVP(padding);
if (Archive::is_loading::value)
weights.set_size((outSize * inSize * kW * kH) + outSize, 1);
}
template<
typename ForwardConvolutionRule,
typename BackwardConvolutionRule,
typename GradientConvolutionRule,
typename InputDataType,
typename OutputDataType
>
void Convolution<
ForwardConvolutionRule,
BackwardConvolutionRule,
GradientConvolutionRule,
InputDataType,
OutputDataType
>::InitializeSamePadding()
{
/*
* Using O = (W - F + 2P) / s + 1;
*/
size_t totalVerticalPadding = (dW - 1) * inputWidth + kW - dW;
size_t totalHorizontalPadding = (dH - 1) * inputHeight + kH - dH;
padWLeft = totalVerticalPadding / 2;
padWRight = totalVerticalPadding - totalVerticalPadding / 2;
padHTop = totalHorizontalPadding / 2;
padHBottom = totalHorizontalPadding - totalHorizontalPadding / 2;
}
} // namespace ann
} // namespace mlpack
@@ -36,6 +36,10 @@ namespace ann /** Artificial Neural Network. */ {
* Note that FastLSTM network layer does not use peephole connections between
* the cell and gates.
*
* Note also that if a FastLSTM layer is desired as the first layer of a neural
* network, an IdentityLayer should be added to the network as the first layer,
* and then the FastLSTM layer should be added.
*
* For more information, see the following.
*
* @code
+257
View File
@@ -0,0 +1,257 @@
/**
* @file highway.hpp
* @author Konstantin Sidorov
* @author Saksham Bansal
*
* Definition of the Highway layer.
*
* 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_HIGHWAY_HPP
#define MLPACK_METHODS_ANN_LAYER_HIGHWAY_HPP
#include <mlpack/prereqs.hpp>
#include <boost/ptr_container/ptr_vector.hpp>
#include "../visitor/delete_visitor.hpp"
#include "../visitor/delta_visitor.hpp"
#include "../visitor/output_height_visitor.hpp"
#include "../visitor/output_parameter_visitor.hpp"
#include "../visitor/output_width_visitor.hpp"
#include "layer_types.hpp"
#include "add_merge.hpp"
namespace mlpack {
namespace ann /** Artificial Neural Network. */ {
/**
* Implementation of the Highway layer. The Highway class can vary its behavior
* between that of feed-forward fully connected network container and that
* of a layer which simply passes its inputs through depending on the transform
* gate. Note that the size of the input and output matrices of this class
* should be equal.
*
* For more information, refer the following paper.
*
* @code
* @article{Srivastava2015,
* author = {Rupesh Kumar Srivastava, Klaus Greff, Jurgen Schmidhuber},
* title = {Training Very Deep Networks},
* journal = {Advances in Neural Information Processing Systems},
* year = {2015},
* url = {https://arxiv.org/abs/1507.06228},
* }
* @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,
typename... CustomLayers>
class Highway
{
public:
//! Create the Highway object.
Highway();
/**
* Create the Highway object.
*
* @param inSize The number of input units.
* @param model Expose all the network modules.
*/
Highway(const size_t inSize, const bool model = true);
//! Destroy the Highway object.
~Highway();
/**
* Destroy all the modules added to the Highway object.
*/
void DeleteModules();
/**
* Reset the layer parameter.
*/
void Reset();
/**
* 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(arma::Mat<eT>&& input, arma::Mat<eT>&& output);
/**
* Ordinary feed-backward pass of a neural network, calculating the function
* f(x) by propagating x backwards through f. Using the results from the
* feed-forward pass.
*
* @param input The propagated input activation.
* @param gy The backpropagated error.
* @param g The calculated gradient.
*/
template<typename eT>
void Backward(const arma::Mat<eT>&& /* input */,
arma::Mat<eT>&& gy,
arma::Mat<eT>&& g);
/**
* Calculate the gradient using the output delta and the input activation.
*
* @param input The input parameter used for calculating the gradient.
* @param error The calculated error.
* @param gradient The calculated gradient.
*/
template<typename eT>
void Gradient(arma::Mat<eT>&& input,
arma::Mat<eT>&& error,
arma::Mat<eT>&& gradient);
/**
* Add a new module to the model.
*
* @param args The layer parameter.
*/
template <class LayerType, class... Args>
void Add(Args... args) { network.push_back(new LayerType(args...)); }
/**
* Add a new module to the model.
*
* @param layer The Layer to be added to the model.
*/
void Add(LayerTypes<CustomLayers...> layer) { network.push_back(layer); }
//! Return the modules of the model.
std::vector<LayerTypes<CustomLayers...> >& Model()
{
if (model)
{
return network;
}
return empty;
}
//! Get the parameters.
OutputDataType const& Parameters() const { return weights; }
//! Modify the parameters.
OutputDataType& Parameters() { return weights; }
//! Get the input parameter.
InputDataType const& InputParameter() const { return inputParameter; }
//! Modify the input parameter.
InputDataType& InputParameter() { return inputParameter; }
//! 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 gradient.
OutputDataType const& Gradient() const { return gradient; }
//! Modify the gradient.
OutputDataType& Gradient() { return gradient; }
/**
* Serialize the layer.
*/
template<typename Archive>
void serialize(Archive& ar, const unsigned int /* version */);
private:
//! Locally-stored number of input units.
size_t inSize;
//! Parameter which indicates if the modules should be exposed.
bool model;
//! Indicator if we already initialized the model.
bool reset;
//! Locally-stored network modules.
std::vector<LayerTypes<CustomLayers...> > network;
//! Locally-stored empty list of modules.
std::vector<LayerTypes<CustomLayers...> > empty;
//! Locally-stored weight object.
OutputDataType weights;
//! Locally-stored delta object.
OutputDataType delta;
//! Locally-stored gradient object.
OutputDataType gradient;
//! Weights for transformation of output.
OutputDataType transformWeight;
//! Bias for transformation of output.
OutputDataType transformBias;
//! Locally-stored transform gate parameters.
OutputDataType transformGate;
//! Locally-stored transform gate activation.
OutputDataType transformGateActivation;
//! Locally-stored transform gate error.
OutputDataType transformGateError;
//! Locally-stored input parameter object.
InputDataType inputParameter;
//! Locally-stored output parameter object.
OutputDataType outputParameter;
//! The input width.
size_t width;
//! The input height.
size_t height;
//! The normal output without highway network.
OutputDataType networkOutput;
//! Locally-stored delta visitor.
DeltaVisitor deltaVisitor;
//! Locally-stored output parameter visitor.
OutputParameterVisitor outputParameterVisitor;
//! Locally-stored delete visitor.
DeleteVisitor deleteVisitor;
//! Locally-stored output width visitor.
OutputWidthVisitor outputWidthVisitor;
//! Locally-stored output height visitor.
OutputHeightVisitor outputHeightVisitor;
}; // class Highway
} // namespace ann
} // namespace mlpack
// Include implementation.
#include "highway_impl.hpp"
#endif
@@ -0,0 +1,249 @@
/**
* @file highway_impl.hpp
* @author Konstantin Sidorov
* @author Saksham Bansal
*
* Implementation of Highway layer.
*
* 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_HIGHWAY_IMPL_HPP
#define MLPACK_METHODS_ANN_LAYER_HIGHWAY_IMPL_HPP
// In case it hasn't yet been included.
#include "highway.hpp"
#include "../visitor/forward_visitor.hpp"
#include "../visitor/backward_visitor.hpp"
#include "../visitor/gradient_visitor.hpp"
#include "../visitor/set_input_height_visitor.hpp"
#include "../visitor/set_input_width_visitor.hpp"
namespace mlpack {
namespace ann /** Artificial Neural Network. */ {
template<typename InputDataType, typename OutputDataType,
typename... CustomLayers>
Highway<InputDataType, OutputDataType, CustomLayers...>::Highway() :
inSize(0),
model(true),
reset(false),
width(0),
height(0)
{
// Nothing to do here.
}
template<
typename InputDataType, typename OutputDataType, typename... CustomLayers>
Highway<InputDataType, OutputDataType, CustomLayers...>::Highway(
const size_t inSize,
const bool model) :
inSize(inSize),
model(model),
reset(false),
width(0),
height(0)
{
weights.set_size(inSize * inSize + inSize, 1);
}
template<typename InputDataType, typename OutputDataType,
typename... CustomLayers>
Highway<InputDataType, OutputDataType, CustomLayers...>::~Highway()
{
if (!model)
{
for (LayerTypes<CustomLayers...>& layer : network)
{
boost::apply_visitor(deleteVisitor, layer);
}
}
}
template<typename InputDataType, typename OutputDataType,
typename... CustomLayers>
void Highway<
InputDataType, OutputDataType, CustomLayers...>::DeleteModules()
{
if (model)
{
for (LayerTypes<CustomLayers...>& layer : network)
{
boost::apply_visitor(deleteVisitor, layer);
}
}
}
template<typename InputDataType, typename OutputDataType,
typename... CustomLayers>
void Highway<InputDataType, OutputDataType, CustomLayers...>::Reset()
{
transformWeight = arma::mat(weights.memptr(), inSize, inSize, false, false);
transformBias = arma::mat(weights.memptr() + transformWeight.n_elem,
inSize, 1, false, false);
}
template<typename InputDataType, typename OutputDataType,
typename... CustomLayers>
template<typename eT>
void Highway<InputDataType, OutputDataType, CustomLayers...>::Forward(
arma::Mat<eT>&& input, arma::Mat<eT>&& output)
{
boost::apply_visitor(ForwardVisitor(std::move(input), std::move(
boost::apply_visitor(outputParameterVisitor, network.front()))),
network.front());
if (!reset)
{
if (boost::apply_visitor(outputWidthVisitor, network.front()) != 0)
{
width = boost::apply_visitor(outputWidthVisitor, network.front());
}
if (boost::apply_visitor(outputHeightVisitor, network.front()) != 0)
{
height = boost::apply_visitor(outputHeightVisitor, network.front());
}
}
for (size_t i = 1; i < network.size(); ++i)
{
if (!reset)
{
// Set the input width.
boost::apply_visitor(SetInputWidthVisitor(width), network[i]);
// Set the input height.
boost::apply_visitor(SetInputHeightVisitor(height), network[i]);
}
boost::apply_visitor(ForwardVisitor(std::move(boost::apply_visitor(
outputParameterVisitor, network[i - 1])), std::move(
boost::apply_visitor(outputParameterVisitor, network[i]))),
network[i]);
if (!reset)
{
// Get the output width.
if (boost::apply_visitor(outputWidthVisitor, network[i]) != 0)
{
width = boost::apply_visitor(outputWidthVisitor, network[i]);
}
// Get the output height.
if (boost::apply_visitor(outputHeightVisitor, network[i]) != 0)
{
height = boost::apply_visitor(outputHeightVisitor, network[i]);
}
}
}
if (!reset)
{
reset = true;
}
output = boost::apply_visitor(outputParameterVisitor, network.back());
if (arma::size(output) != arma::size(input))
{
Log::Fatal << "The sizes of the output and input matrices of the Highway"
<< " network should be equal. Please examine the network layers.";
}
transformGate = transformWeight * input;
transformGate.each_col() += transformBias;
transformGateActivation = 1.0 /(1 + arma::exp(-transformGate));
inputParameter = input;
networkOutput = output;
output = (output % transformGateActivation) +
(input % (1 - transformGateActivation));
}
template<typename InputDataType, typename OutputDataType,
typename... CustomLayers>
template<typename eT>
void Highway<InputDataType, OutputDataType, CustomLayers...>::Backward(
const arma::Mat<eT>&& /* input */,
arma::Mat<eT>&& gy,
arma::Mat<eT>&& g)
{
boost::apply_visitor(BackwardVisitor(std::move(boost::apply_visitor(
outputParameterVisitor, network.back())),
std::move(gy % transformGateActivation),
std::move(boost::apply_visitor(deltaVisitor, network.back()))),
network.back());
for (size_t i = 2; i < network.size() + 1; ++i)
{
boost::apply_visitor(BackwardVisitor(std::move(boost::apply_visitor(
outputParameterVisitor, network[network.size() - i])), std::move(
boost::apply_visitor(deltaVisitor, network[network.size() - i + 1])),
std::move(boost::apply_visitor(deltaVisitor,
network[network.size() - i]))), network[network.size() - i]);
}
g = boost::apply_visitor(deltaVisitor, network.front());
transformGateError = gy % (networkOutput - inputParameter) %
transformGateActivation % (1.0 - transformGateActivation);
g += transformWeight.t() * transformGateError;
g += gy % (1 - transformGateActivation);
}
template<typename InputDataType, typename OutputDataType,
typename... CustomLayers>
template<typename eT>
void Highway<InputDataType, OutputDataType, CustomLayers...>::Gradient(
arma::Mat<eT>&& input,
arma::Mat<eT>&& error,
arma::Mat<eT>&& gradient)
{
boost::apply_visitor(GradientVisitor(std::move(boost::apply_visitor(
outputParameterVisitor, network[network.size() - 2])),
std::move(error % transformGateActivation)), network.back());
for (size_t i = 2; i < network.size(); ++i)
{
boost::apply_visitor(GradientVisitor(std::move(boost::apply_visitor(
outputParameterVisitor, network[network.size() - i - 1])), std::move(
boost::apply_visitor(deltaVisitor, network[network.size() - i + 1]))),
network[network.size() - i]);
}
boost::apply_visitor(GradientVisitor(std::move(input), std::move(
boost::apply_visitor(deltaVisitor, network[1]))), network.front());
gradient.submat(0, 0, transformWeight.n_elem - 1, 0) = arma::vectorise(
transformGateError * input.t());
gradient.submat(transformWeight.n_elem, 0, gradient.n_elem - 1, 0) =
arma::sum(transformGateError, 1);
}
template<typename InputDataType, typename OutputDataType,
typename... CustomLayers>
template<typename Archive>
void Highway<InputDataType, OutputDataType, CustomLayers...>::serialize(
Archive& ar, const unsigned int /* version */)
{
// If loading, delete the old layers and set size for weights.
if (Archive::is_loading::value)
{
for (LayerTypes<CustomLayers...>& layer : network)
{
boost::apply_visitor(deleteVisitor, layer);
}
weights.set_size(inSize * inSize + inSize, 1);
}
ar & BOOST_SERIALIZATION_NVP(model);
ar & BOOST_SERIALIZATION_NVP(network);
}
} // namespace ann
} // namespace mlpack
#endif
+4
View File
@@ -19,12 +19,15 @@
#include "convolution.hpp"
#include "dropconnect.hpp"
#include "glimpse.hpp"
#include "highway.hpp"
#include "layer_norm.hpp"
#include "layer_types.hpp"
#include "linear.hpp"
#include "linear_no_bias.hpp"
#include "lstm.hpp"
#include "minibatch_discrimination.hpp"
#include "multiply_merge.hpp"
#include "padding.hpp"
#include "gru.hpp"
#include "fast_lstm.hpp"
#include "recurrent.hpp"
@@ -35,5 +38,6 @@
#include "concat.hpp"
#include "vr_class_reward.hpp"
#include "transposed_convolution.hpp"
#include "weight_norm.hpp"
#endif
+1 -1
View File
@@ -155,7 +155,7 @@ class LayerNorm
//! Locally-stored epsilon value.
double eps;
//! Whether we are in loading or saving mode.
//! Variable to keep track of whether we are in loading or saving mode.
bool loading;
//! Locally-stored scale parameter.
@@ -82,7 +82,7 @@ void LayerNorm<InputDataType, OutputDataType>::Backward(
{
const arma::mat stdInv = 1.0 / arma::sqrt(variance + eps);
// dl / dxhat
// dl / dxhat.
const arma::mat norm = gy.each_col() % gamma;
// sum dl / dxhat * (x - mu) * -0.5 * stdInv^3.
@@ -112,6 +112,10 @@ HAS_MEM_FUNC(Loss, HasLoss);
// can use with SFINAE to catch when a type has a Run() function.
HAS_MEM_FUNC(Run, HasRunCheck);
// This gives us a HasBiasCheck<T, U> type (where U is a function pointer) we
// can use with SFINAE to catch when a type has a Bias() function.
HAS_MEM_FUNC(Bias, HasBiasCheck);
} // namespace ann
} // namespace mlpack
+58 -14
View File
@@ -40,12 +40,16 @@
#include <mlpack/methods/ann/layer/reparametrization.hpp>
#include <mlpack/methods/ann/layer/select.hpp>
#include <mlpack/methods/ann/layer/subview.hpp>
#include <mlpack/methods/ann/layer/virtual_batch_norm.hpp>
// Convolution modules.
#include <mlpack/methods/ann/convolution_rules/border_modes.hpp>
#include <mlpack/methods/ann/convolution_rules/naive_convolution.hpp>
#include <mlpack/methods/ann/convolution_rules/fft_convolution.hpp>
// Regularizers.
#include <mlpack/methods/ann/regularizer/no_regularizer.hpp>
// Loss function modules.
#include <mlpack/methods/ann/loss_functions/negative_log_likelihood.hpp>
@@ -56,13 +60,32 @@ template<typename InputDataType, typename OutputDataType> class BatchNorm;
template<typename InputDataType, typename OutputDataType> class DropConnect;
template<typename InputDataType, typename OutputDataType> class Glimpse;
template<typename InputDataType, typename OutputDataType> class LayerNorm;
template<typename InputDataType, typename OutputDataType> class Linear;
template<typename InputDataType, typename OutputDataType> class LinearNoBias;
template<typename InputDataType, typename OutputDataType> class LSTM;
template<typename InputDataType, typename OutputDataType> class GRU;
template<typename InputDataType, typename OutputDataType> class FastLSTM;
template<typename InputDataType, typename OutputDataType> class VRClassReward;
template<typename InputDataType, typename OutputDataType> class Concatenate;
template<typename InputDataType, typename OutputDataType> class Padding;
template<typename InputDataType,
typename OutputDataType,
typename RegularizerType>
class Linear;
template<typename InputDataType,
typename OutputDataType,
typename RegularizerType>
class LinearNoBias;
template<typename InputDataType,
typename OutputDataType
>
class VirtualBatchNorm;
template<typename InputDataType,
typename OutputDataType
>
class MiniBatchDiscrimination;
template<typename InputDataType,
typename OutputDataType
@@ -82,6 +105,12 @@ template<typename InputDataType,
>
class Sequential;
template<typename InputDataType,
typename OutputDataType,
typename... CustomLayers
>
class Highway;
template<typename InputDataType,
typename OutputDataType,
typename... CustomLayers
@@ -140,6 +169,25 @@ template<typename InputDataType,
>
class MultiplyMerge;
template <typename InputDataType,
typename OutputDataType,
typename... CustomLayers
>
class WeightNorm;
using MoreTypes = boost::variant<
Recurrent<arma::mat, arma::mat>*,
RecurrentAttention<arma::mat, arma::mat>*,
ReinforceNormal<arma::mat, arma::mat>*,
Reparametrization<arma::mat, arma::mat>*,
Select<arma::mat, arma::mat>*,
Sequential<arma::mat, arma::mat, false>*,
Sequential<arma::mat, arma::mat, true>*,
Subview<arma::mat, arma::mat>*,
VRClassReward<arma::mat, arma::mat>*,
VirtualBatchNorm<arma::mat, arma::mat>*
>;
template <typename... CustomLayers>
using LayerTypes = boost::variant<
Add<arma::mat, arma::mat>*,
@@ -164,7 +212,7 @@ using LayerTypes = boost::variant<
NaiveConvolution<FullConvolution>,
NaiveConvolution<ValidConvolution>, arma::mat, arma::mat>*,
TransposedConvolution<NaiveConvolution<ValidConvolution>,
NaiveConvolution<FullConvolution>,
NaiveConvolution<ValidConvolution>,
NaiveConvolution<ValidConvolution>, arma::mat, arma::mat>*,
DropConnect<arma::mat, arma::mat>*,
Dropout<arma::mat, arma::mat>*,
@@ -173,12 +221,13 @@ using LayerTypes = boost::variant<
FlexibleReLU<arma::mat, arma::mat>*,
Glimpse<arma::mat, arma::mat>*,
HardTanH<arma::mat, arma::mat>*,
Highway<arma::mat, arma::mat>*,
Join<arma::mat, arma::mat>*,
LayerNorm<arma::mat, arma::mat>*,
LeakyReLU<arma::mat, arma::mat>*,
CReLU<arma::mat, arma::mat>*,
Linear<arma::mat, arma::mat>*,
LinearNoBias<arma::mat, arma::mat>*,
Linear<arma::mat, arma::mat, NoRegularizer>*,
LinearNoBias<arma::mat, arma::mat, NoRegularizer>*,
LogSoftMax<arma::mat, arma::mat>*,
Lookup<arma::mat, arma::mat>*,
LSTM<arma::mat, arma::mat>*,
@@ -186,19 +235,14 @@ using LayerTypes = boost::variant<
FastLSTM<arma::mat, arma::mat>*,
MaxPooling<arma::mat, arma::mat>*,
MeanPooling<arma::mat, arma::mat>*,
MiniBatchDiscrimination<arma::mat, arma::mat>*,
MultiplyConstant<arma::mat, arma::mat>*,
MultiplyMerge<arma::mat, arma::mat>*,
NegativeLogLikelihood<arma::mat, arma::mat>*,
Padding<arma::mat, arma::mat>*,
PReLU<arma::mat, arma::mat>*,
Recurrent<arma::mat, arma::mat>*,
RecurrentAttention<arma::mat, arma::mat>*,
ReinforceNormal<arma::mat, arma::mat>*,
Reparametrization<arma::mat, arma::mat>*,
Select<arma::mat, arma::mat>*,
Sequential<arma::mat, arma::mat, false>*,
Sequential<arma::mat, arma::mat, true>*,
Subview<arma::mat, arma::mat>*,
VRClassReward<arma::mat, arma::mat>*,
WeightNorm<arma::mat, arma::mat>*,
MoreTypes,
CustomLayers*...
>;
+12 -2
View File
@@ -14,6 +14,7 @@
#define MLPACK_METHODS_ANN_LAYER_LINEAR_HPP
#include <mlpack/prereqs.hpp>
#include <mlpack/methods/ann/regularizer/no_regularizer.hpp>
#include "layer_types.hpp"
@@ -31,7 +32,8 @@ namespace ann /** Artificial Neural Network. */ {
*/
template <
typename InputDataType = arma::mat,
typename OutputDataType = arma::mat
typename OutputDataType = arma::mat,
typename RegularizerType = NoRegularizer
>
class Linear
{
@@ -45,7 +47,9 @@ class Linear
* @param inSize The number of input units.
* @param outSize The number of output units.
*/
Linear(const size_t inSize, const size_t outSize);
Linear(const size_t inSize,
const size_t outSize,
RegularizerType regularizer = RegularizerType());
/*
* Reset the layer parameter.
@@ -113,6 +117,9 @@ class Linear
//! Modify the gradient.
OutputDataType& Gradient() { return gradient; }
//! Modify the bias weights of the layer.
arma::mat& Bias() { return bias; }
/**
* Serialize the layer
*/
@@ -146,6 +153,9 @@ class Linear
//! Locally-stored output parameter object.
OutputDataType outputParameter;
//! Locally-stored regularizer object.
RegularizerType regularizer;
}; // class Linear
} // namespace ann
+28 -16
View File
@@ -19,50 +19,60 @@
namespace mlpack {
namespace ann /** Artificial Neural Network. */ {
template<typename InputDataType, typename OutputDataType>
Linear<InputDataType, OutputDataType>::Linear()
template<typename InputDataType, typename OutputDataType,
typename RegularizerType>
Linear<InputDataType, OutputDataType, RegularizerType>::Linear() :
inSize(0),
outSize(0)
{
// Nothing to do here.
}
template <typename InputDataType, typename OutputDataType>
Linear<InputDataType, OutputDataType>::Linear(
template<typename InputDataType, typename OutputDataType,
typename RegularizerType>
Linear<InputDataType, OutputDataType, RegularizerType>::Linear(
const size_t inSize,
const size_t outSize) :
const size_t outSize,
RegularizerType regularizer) :
inSize(inSize),
outSize(outSize)
outSize(outSize),
regularizer(regularizer)
{
weights.set_size(outSize * inSize + outSize, 1);
}
template<typename InputDataType, typename OutputDataType>
void Linear<InputDataType, OutputDataType>::Reset()
template<typename InputDataType, typename OutputDataType,
typename RegularizerType>
void Linear<InputDataType, OutputDataType, RegularizerType>::Reset()
{
weight = arma::mat(weights.memptr(), outSize, inSize, false, false);
bias = arma::mat(weights.memptr() + weight.n_elem,
outSize, 1, false, false);
}
template<typename InputDataType, typename OutputDataType>
template<typename InputDataType, typename OutputDataType,
typename RegularizerType>
template<typename eT>
void Linear<InputDataType, OutputDataType>::Forward(
void Linear<InputDataType, OutputDataType, RegularizerType>::Forward(
const arma::Mat<eT>&& input, arma::Mat<eT>&& output)
{
output = weight * input;
output.each_col() += bias;
}
template<typename InputDataType, typename OutputDataType>
template<typename InputDataType, typename OutputDataType,
typename RegularizerType>
template<typename eT>
void Linear<InputDataType, OutputDataType>::Backward(
void Linear<InputDataType, OutputDataType, RegularizerType>::Backward(
const arma::Mat<eT>&& /* input */, arma::Mat<eT>&& gy, arma::Mat<eT>&& g)
{
g = weight.t() * gy;
}
template<typename InputDataType, typename OutputDataType>
template<typename InputDataType, typename OutputDataType,
typename RegularizerType>
template<typename eT>
void Linear<InputDataType, OutputDataType>::Gradient(
void Linear<InputDataType, OutputDataType, RegularizerType>::Gradient(
const arma::Mat<eT>&& input,
arma::Mat<eT>&& error,
arma::Mat<eT>&& gradient)
@@ -71,11 +81,13 @@ void Linear<InputDataType, OutputDataType>::Gradient(
error * input.t());
gradient.submat(weight.n_elem, 0, gradient.n_elem - 1, 0) =
arma::sum(error, 1);
regularizer.Evaluate(weights, gradient);
}
template<typename InputDataType, typename OutputDataType>
template<typename InputDataType, typename OutputDataType,
typename RegularizerType>
template<typename Archive>
void Linear<InputDataType, OutputDataType>::serialize(
void Linear<InputDataType, OutputDataType, RegularizerType>::serialize(
Archive& ar, const unsigned int /* version */)
{
ar & BOOST_SERIALIZATION_NVP(inSize);
@@ -14,6 +14,7 @@
#define MLPACK_METHODS_ANN_LAYER_LINEAR_NO_BIAS_HPP
#include <mlpack/prereqs.hpp>
#include <mlpack/methods/ann/regularizer/no_regularizer.hpp>
#include "layer_types.hpp"
@@ -31,7 +32,8 @@ namespace ann /** Artificial Neural Network. */ {
*/
template <
typename InputDataType = arma::mat,
typename OutputDataType = arma::mat
typename OutputDataType = arma::mat,
typename RegularizerType = NoRegularizer
>
class LinearNoBias
{
@@ -44,7 +46,9 @@ class LinearNoBias
* @param inSize The number of input units.
* @param outSize The number of output units.
*/
LinearNoBias(const size_t inSize, const size_t outSize);
LinearNoBias(const size_t inSize,
const size_t outSize,
RegularizerType regularizer = RegularizerType());
/*
* Reset the layer parameter.
@@ -142,6 +146,9 @@ class LinearNoBias
//! Locally-stored output parameter object.
OutputDataType outputParameter;
//! Locally-stored regularizer object.
RegularizerType regularizer;
}; // class LinearNoBias
} // namespace ann

Some files were not shown because too many files have changed in this diff Show More