Merge branch 'mlpack:master' into master
This commit is contained in:
@@ -57,7 +57,17 @@ jobs:
|
||||
- name: Install Build Dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y --allow-unauthenticated libopenblas-dev liblapack-dev g++ libcereal-dev libensmallen-dev libhdf5-dev libarmadillo-dev libcurl4-openssl-dev
|
||||
# We don't install cereal via apt, because the Debian packagers
|
||||
# split the rapidjson dependency into a separate package. We will
|
||||
# bundle the cereal sources with the R package, so we want them to
|
||||
# be exactly the upstream sources (with rapidjson included).
|
||||
sudo apt-get install -y --allow-unauthenticated libopenblas-dev liblapack-dev g++ libensmallen-dev libhdf5-dev libarmadillo-dev libcurl4-openssl-dev
|
||||
wget https://github.com/USCiLab/cereal/archive/refs/tags/v1.3.2.tar.gz
|
||||
tar -xvzpf v1.3.2.tar.gz
|
||||
# These directives cause warnings on CRAN:
|
||||
# https://github.com/USCiLab/cereal/blob/master/include/cereal/external/base64.hpp#L28-L31
|
||||
# The command below comments them out.
|
||||
sed -i 's|#pragma|// #pragma|' cereal-1.3.2/include/cereal/external/base64.hpp
|
||||
|
||||
- name: Install R-bindings dependencies
|
||||
run: |
|
||||
@@ -69,7 +79,7 @@ jobs:
|
||||
- name: CMake
|
||||
run: |
|
||||
mkdir build
|
||||
cd build && cmake -DDEBUG=OFF -DPROFILE=OFF -DBUILD_CLI_EXECUTABLES=OFF -DBUILD_PYTHON_BINDINGS=OFF -DBUILD_JULIA_BINDINGS=OFF -DBUILD_GO_BINDINGS=OFF -DBUILD_R_BINDINGS=ON -DDOWNLOAD_DEPENDENCIES=ON -DBUILD_TESTS=ON ..
|
||||
cd build && cmake -DDEBUG=OFF -DPROFILE=OFF -DBUILD_CLI_EXECUTABLES=OFF -DBUILD_PYTHON_BINDINGS=OFF -DBUILD_JULIA_BINDINGS=OFF -DBUILD_GO_BINDINGS=OFF -DBUILD_R_BINDINGS=ON -DDOWNLOAD_DEPENDENCIES=ON -DBUILD_TESTS=ON -DCEREAL_INCLUDE_DIR=../cereal-1.3.2/include/ ..
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
@@ -121,7 +131,7 @@ jobs:
|
||||
r-version: ${{ matrix.config.r }}
|
||||
http-user-agent: ${{ matrix.config.http-user-agent }}
|
||||
use-public-rspm: true
|
||||
|
||||
|
||||
- name: Query dependencies
|
||||
run: Rscript -e "install.packages('remotes')" -e "saveRDS(remotes::dev_package_deps('${{ needs.jobR.outputs.r_bindings }}', dependencies = TRUE), 'depends.Rds')"
|
||||
|
||||
|
||||
@@ -94,6 +94,22 @@ if(NOT _ARMA_USE_WRAPPER OR MSVC)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# On Linux, when statically linking against OpenBLAS, we must also manually
|
||||
# link against -lgfortran and -lquadmath. See
|
||||
# https://gitlab.kitware.com/cmake/cmake/-/issues/23693 for more
|
||||
# information. When that issue is fixed, we may be able to remove this
|
||||
# section.
|
||||
if (NOT BUILD_SHARED_LIBS AND
|
||||
${CMAKE_SYSTEM_NAME} MATCHES "Linux" AND
|
||||
NOT CMAKE_CROSSCOMPILING)
|
||||
string(TOLOWER "${LAPACK_LIBRARIES}" _lower_lapack_libs)
|
||||
string(FIND "${_lower_lapack_libs}" "openblas" _openblas_found_index)
|
||||
if (${_openblas_found_index} GREATER_EQUAL 0)
|
||||
message(STATUS "Using static OpenBLAS on Linux; adding -lgfortran and -lquadmath...")
|
||||
set(LAPACK_LIBRARIES "${LAPACK_LIBRARIES};gfortran;quadmath")
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
if(LAPACK_FOUND)
|
||||
set(_ARMA_SUPPORT_LIBRARIES "${_ARMA_SUPPORT_LIBRARIES}" "${LAPACK_LIBRARIES}")
|
||||
endif()
|
||||
|
||||
+12
-7
@@ -7,7 +7,7 @@ Source:
|
||||
|
||||
Files: *
|
||||
Copyright:
|
||||
Copyright 2008-2022, Ryan Curtin <ryan@ratml.org>
|
||||
Copyright 2008-2023, Ryan Curtin <ryan@ratml.org>
|
||||
Copyright 2008-2013, Bill March <march@gatech.edu>
|
||||
Copyright 2008-2012, Dongryeol Lee <dongryel@cc.gatech.edu>
|
||||
Copyright 2008-2013, Nishant Mehta <niche@cc.gatech.edu>
|
||||
@@ -26,7 +26,7 @@ Copyright:
|
||||
Copyright 2013, Mudit Raj Gupta <mudit.raaj.gupta@gmail.com>
|
||||
Copyright 2013-2018, Sumedh Ghaisas <sumedhghaisas@gmail.com>
|
||||
Copyright 2014, Michael Fox <michaelfox99@gmail.com>
|
||||
Copyright 2014,2020 Ryan Birmingham <birm@gatech.edu>
|
||||
Copyright 2014,2020, Ryan Birmingham <birm@gatech.edu>
|
||||
Copyright 2014, Siddharth Agrawal <siddharth.950@gmail.com>
|
||||
Copyright 2014, Saheb Motiani <saheb210692@gmail.com>
|
||||
Copyright 2014, Yash Vadalia <yashdv@gmail.com>
|
||||
@@ -83,15 +83,16 @@ Copyright:
|
||||
Copyright 2017, Samikshya Chand <samikshya289@gmail.com>
|
||||
Copyright 2017, N Rajiv Vaidyanathan <rajivvaidyanathan4@gmail.com>
|
||||
Copyright 2017, Kartik Nighania <kartiknighania@gmail.com>
|
||||
Copyright 2017-2023, Dirk Eddelbuettel <edd@debian.org>
|
||||
Copyright 2017-2018, Eugene Freyman <evg.freyman@gmail.com>
|
||||
Copyright 2017-2019, Manish Kumar <manish887kr@gmail.com>
|
||||
Copyright 2017-2018, Haritha Sreedharan Nair <haritha1313@gmail.com>
|
||||
Copyright 2017-2018, Sourabh Varshney <sourabhvarshney111@gmail.com>
|
||||
Copyright 2018, Projyal Dev <projyal@gmail.com>
|
||||
Copyright 2018, Nikhil Goel <nikhilgoel199797@gmail.com>
|
||||
Copyright 2018-2020 Shikhar Jaiswal <jaiswalshikhar87@gmail.com>
|
||||
Copyright 2018-2020, Shikhar Jaiswal <jaiswalshikhar87@gmail.com>
|
||||
Copyright 2018, B Kartheek Reddy <bkartheekreddy@gmail.com>
|
||||
Copyright 2018-2019 Atharva Khandait <akhandait45@gmail.com>
|
||||
Copyright 2018-2019, Atharva Khandait <akhandait45@gmail.com>
|
||||
Copyright 2018, Wenhao Huang <wenhao.huang.work@gmail.com>
|
||||
Copyright 2018-2019, Roberto Hueso <robertohueso96@gmail.com>
|
||||
Copyright 2018, Prabhat Sharma <prabhatsharma7298@gmail.com>
|
||||
@@ -114,9 +115,9 @@ Copyright:
|
||||
Copyright 2019, Miguel Canteras <mcanteras@gmail.com>
|
||||
Copyright 2019, Bishwa Karki <karkeebishwa1@gmail.com>
|
||||
Copyright 2019, Mehul Kumar Nirala <mehulkumarnirala@gmail.com>
|
||||
Copyright 2019-2020 Yashwant Singh Parihar <yashwantsingh.sngh@gmail.com>
|
||||
Copyright 2019-2020, Yashwant Singh Parihar <yashwantsingh.sngh@gmail.com>
|
||||
Copyright 2019, Heet Sankesara <heetsankesara3@gmail.com>
|
||||
Copyright 2019-2020 Jeffin Sam <sam.jeffin@gmail.com>
|
||||
Copyright 2019-2020, Jeffin Sam <sam.jeffin@gmail.com>
|
||||
Copyright 2019, Vikas S Shetty <shettyvikas209@gmail.com>
|
||||
Copyright 2019, Khizir Siddiqui <khizirsiddiqui@gmail.com>
|
||||
Copyright 2019, Tejasvi Tomar <tstomar@outlook.com>
|
||||
@@ -124,7 +125,8 @@ Copyright:
|
||||
Copyright 2019, Ziyang Jiang <zij004@alumni.stanford.edu>
|
||||
Copyright 2019, Rohit Kartik <rohit.audrey@gmail.com>
|
||||
Copyright 2019, Aditya Viki <adityaviki01@gmail.com>
|
||||
Copyright 2019-2020 Kartik Dutt <kartikdutt@live.in>
|
||||
Copyright 2019-2020, Kartik Dutt <kartikdutt@live.in>
|
||||
Copyright 2019, Suryoday Basak <suryodaybasak@gmail.com>
|
||||
Copyright 2020, Sriram S K <sriramsk1999@gmail.com>
|
||||
Copyright 2020, Manoranjan Kumar Bharti ( Nakul Bharti ) <knakul853@gmail.com>
|
||||
Copyright 2020, Saraansh Tandon <saraanshtandon1999@gmail.com>
|
||||
@@ -141,12 +143,15 @@ Copyright:
|
||||
Copyright 2020, Alex Nguyen <alexvn.edu@gmail.com>
|
||||
Copyright 2020, Gaurav Ghati <gauravghatii@gmail.com>
|
||||
Copyright 2020, Anmolpreet Singh <anmol323c@gmail.com>
|
||||
Copyright 2020, Anjishnu Mukherjee <amukher6@gmu.edu>
|
||||
Copyright 2020-2023, Omar Shrit <omar@shrit.me>
|
||||
Copyright 2021, Tru Hoang <trugiahoang@gmail.com>
|
||||
Copyright 2021, Mark Fischinger <markfischinger@gmail.com>
|
||||
Copyright 2021, Muhammad Fawwaz Mayda <maydafawwaz@gmail.com>
|
||||
Copyright 2021, Roshan Nrusing Swain <swainroshan001@gmail.com>
|
||||
Copyright 2021, Suvarsha Chennareddy <suvarshachennareddy@gmail.com>
|
||||
Copyright 2021, Shubham Agrawal <shubham.agra1206@gmail.com>
|
||||
Copyright 2020-2022, James Joseph Balamuta <balamut2@illinois.edu>
|
||||
Copyright 2022, Sri Madhan M <srimadhan11@gmail.com>
|
||||
Copyright 2022, Zhuojin Liu <zhuojinliu.cs@gmail.com>
|
||||
Copyright 2022, Richèl Bilderbeek <richel@richelbilderbeek.nl>
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
### mlpack ?.?.?
|
||||
###### ????-??-??
|
||||
* Bugfix for non-square convolution kernels (#3376).
|
||||
|
||||
* Fix a few missing includes in `<mlpack.hpp>` (#3374).
|
||||
|
||||
* Fix DBSCAN handling of non-core points (#3346).
|
||||
|
||||
### mlpack 4.0.1
|
||||
###### 2022-12-23
|
||||
|
||||
@@ -85,29 +85,33 @@ variety of other needs.
|
||||
If you use mlpack in your research or software, please cite mlpack using the
|
||||
citation below (given in BibTeX format):
|
||||
|
||||
@article{mlpack2018,
|
||||
title = {mlpack 3: a fast, flexible machine learning library},
|
||||
author = {Curtin, Ryan R. and Edel, Marcus and Lozhnikov, Mikhail and
|
||||
Mentekidis, Yannis and Ghaisas, Sumedh and Zhang,
|
||||
Shangtong},
|
||||
@article{mlpack2023,
|
||||
title = {mlpack 4: a fast, header-only C++ machine learning library},
|
||||
author = {Ryan R. Curtin and Marcus Edel and Omar Shrit and
|
||||
Shubham Agrawal and Suryoday Basak and James J. Balamuta and
|
||||
Ryan Birmingham and Kartik Dutt and Dirk Eddelbuettel and
|
||||
Rishabh Garg and Shikhar Jaiswal and Aakash Kaushik and
|
||||
Sangyeon Kim and Anjishnu Mukherjee and Nanubala Gnana Sai and
|
||||
Nippun Sharma and Yashwant Singh Parihar and Roshan Swain and
|
||||
Conrad Sanderson},
|
||||
journal = {Journal of Open Source Software},
|
||||
volume = {3},
|
||||
issue = {26},
|
||||
pages = {726},
|
||||
year = {2018},
|
||||
doi = {10.21105/joss.00726},
|
||||
url = {https://doi.org/10.21105/joss.00726}
|
||||
volume = {8},
|
||||
number = {82},
|
||||
pages = {5026},
|
||||
year = {2023},
|
||||
doi = {10.21105/joss.05026},
|
||||
url = {https://doi.org/10.21105/joss.05026}
|
||||
}
|
||||
|
||||
Citations are beneficial for the growth and improvement of mlpack.
|
||||
|
||||
## 2. Dependencies
|
||||
|
||||
mlpack requires a C++14 compiler and has the following additional dependencies:
|
||||
|
||||
- Armadillo >= 9.800
|
||||
- ensmallen >= 2.10.0
|
||||
- cereal >= 1.1.2
|
||||
**mlpack** requires the following additional dependencies:
|
||||
- C++14 compiler
|
||||
- [Armadillo](https://arma.sourceforge.net)  >= 9.800
|
||||
- [ensmallen](https://ensmallen.org)  >= 2.10.0
|
||||
- [cereal](http://uscilab.github.io/cereal/)     >= 1.1.2
|
||||
|
||||
If the STB library headers are available, image loading support will be
|
||||
available.
|
||||
@@ -119,31 +123,41 @@ If you are compiling Armadillo by hand, ensure that LAPACK and BLAS are enabled.
|
||||
*See also the [C++ quickstart](doc/quickstart/cpp.md).*
|
||||
|
||||
Since mlpack is a header-only library, installing just the headers for use in a
|
||||
C++ application is trivial. From the root of the sources, configure and install
|
||||
C++ application is trivial.
|
||||
|
||||
From the root of the sources, configure and install
|
||||
in the standard CMake way:
|
||||
|
||||
```sh
|
||||
mkdir build && cd build/
|
||||
cmake ../
|
||||
cmake ..
|
||||
sudo make install
|
||||
```
|
||||
|
||||
Note: Since CMake v3.14.0 the `cmake` command can create the build folder itself.
|
||||
The above commands can be rewritten as follows:
|
||||
If the `cmake ..` command fails due to unavailable dependencies, consider either using the
|
||||
`-DDOWNLOAD_DEPENDENCIES=ON` option as detailed in
|
||||
[the following subsection](#31-additional-build-options), or ensure that mlpack's dependencies
|
||||
are installed, e.g. using the system package manager. For example, on Debian and Ubuntu,
|
||||
all relevant dependencies can be installed with `sudo apt-get install libarmadillo-dev libensmallen-dev libcereal-dev g++ cmake`.
|
||||
|
||||
Alternatively, since CMake v3.14.0 the `cmake` command can create the build folder itself,
|
||||
the above commands can be rewritten as follows:
|
||||
|
||||
```sh
|
||||
cmake -S . -B build
|
||||
sudo cmake --build build --target install
|
||||
```
|
||||
|
||||
### 3.1. Additional build options
|
||||
|
||||
You can add a few arguments to the `cmake` command to control the behavior of
|
||||
the configuration and build process. Simply add these to the `cmake` command.
|
||||
Some options are given below:
|
||||
|
||||
- `-DCMAKE_INSTALL_PREFIX=/install/root/` will set the root of the install
|
||||
directory to `/install/root` when `make install` is run.
|
||||
- `-DDOWNLOAD_DEPENDENCIES=ON` will automatically download mlpack's
|
||||
dependencies (ensmallen, Armadillo, and cereal).
|
||||
- `-DCMAKE_INSTALL_PREFIX=/install/root/` will set the root of the install
|
||||
directory to `/install/root` when `make install` is run.
|
||||
- `-DDEBUG=ON` will enable debugging symbols in any compiled bindings or tests.
|
||||
|
||||
There are also options to enable building bindings to each language that mlpack
|
||||
@@ -171,7 +185,7 @@ See the [C++ quickstart](doc/quickstart/cpp.md) and the
|
||||
[examples](https://github.com/mlpack/examples) repository for some examples of
|
||||
mlpack applications in C++, with corresponding `Makefile`s.
|
||||
|
||||
### 3.1. Including mlpack and improving compile time
|
||||
### 3.2. Reducing compile time
|
||||
|
||||
mlpack is a template-heavy library, and if care is not used, compilation time of
|
||||
a project can be increased greatly. Fortunately, there are a number of ways to
|
||||
|
||||
@@ -254,7 +254,7 @@ links above for further documentation.
|
||||
In order to write a new binding, then, you simply must define `BINDING_NAME`,
|
||||
then write `BINDING_USER_NAME()`, `BINDING_SHORT_DESC()`, `BINDING_LONG_DESC()`,
|
||||
`BINDING_EXAMPLE()` and `BINDING_SEE_ALSO()` definitions of the program with
|
||||
some docuentation, define the input and output parameters as `PARAM` macros, and
|
||||
some documentation, define the input and output parameters as `PARAM` macros, and
|
||||
then write a `BINDING_FUNCTION()` function that actually performs the
|
||||
functionality of the binding.
|
||||
|
||||
@@ -695,7 +695,7 @@ There are numerous different macros that can be used:
|
||||
- `PARAM_TMATRIX_OUT()` - transposed double-valued matrix (`arma::mat`) output
|
||||
parameter
|
||||
- `PARAM_MATRIX_AND_INFO_IN()` - matrix with categoricals input parameter
|
||||
(`std::tuple<data::DatasetInfo, arma::mat`)
|
||||
(`std::tuple<data::DatasetInfo, arma::mat>`)
|
||||
- `PARAM_COL_IN()` - double-valued column vector (`arma::vec`) input parameter
|
||||
- `PARAM_COL_OUT()` - double-valued column vector (`arma::vec`) output
|
||||
parameter
|
||||
@@ -1322,7 +1322,7 @@ If this is the route that is desired, a large amount of CMake boilerplate may be
|
||||
necessary. The Python CMake configuration can be referred to as an example, but
|
||||
probably a large amount of adaptation to other languages will be necessary.
|
||||
|
||||
Lastly, when adding a new language, be sure to make sure it works with the
|
||||
Lastly, when adding a new language, make sure it works with the
|
||||
Markdown documentation generator. In order to make this happen, you will need
|
||||
to modify all of the `add_markdown_docs()` calls in
|
||||
`src/mlpack/methods/CMakeLists.txt` to contain the name of the language you have
|
||||
|
||||
@@ -16,7 +16,7 @@ including
|
||||
|
||||
mlpack implements a number of kernel methods and, accordingly, each of these
|
||||
methods allows arbitrary kernels to be used via the `KernelType` template
|
||||
parameter. Like the [MetricType policy](metrictype.md), the requirements are
|
||||
parameter. Like the [MetricType policy](metrics.md), the requirements are
|
||||
quite simple: a class implementing the `KernelType` policy must have
|
||||
|
||||
- an `Evaluate()` function
|
||||
@@ -42,7 +42,7 @@ Note that for kernels that do not hold any state, the `Evaluate()` method can be
|
||||
marked as `static`.
|
||||
|
||||
Overall, the `KernelType` template policy is quite simple (much like the
|
||||
[MetricType policy](metrictype.md)). Below is an example kernel class, which
|
||||
[MetricType policy](metrics.md)). Below is an example kernel class, which
|
||||
outputs `1` if the vectors are close and `0` otherwise.
|
||||
|
||||
```c++
|
||||
|
||||
@@ -35,7 +35,7 @@ Note that for metrics that do not hold any state, the `Evaluate()` method can
|
||||
be marked as `static`.
|
||||
|
||||
Overall, the `MetricType` template policy is quite simple (much like the
|
||||
[KernelType policy](kerneltype.md)). Below is an example metric class, which
|
||||
[KernelType policy](kernels.md)). Below is an example metric class, which
|
||||
implements the L2 distance:
|
||||
|
||||
```c++
|
||||
@@ -105,4 +105,4 @@ policy:
|
||||
- `ChebyshevDistance`
|
||||
- `MahalanobisDistance`
|
||||
- `LMetric` (for arbitrary L-metrics)
|
||||
- `IPMetric` (requires a [KernelType](kerneltype.md) parameter)
|
||||
- `IPMetric` (requires a [KernelType](kernels.md) parameter)
|
||||
|
||||
@@ -86,11 +86,11 @@ restatement of the fourth part of the definition).
|
||||
|
||||
Most everything in mlpack is decomposed into a series of configurable template
|
||||
parameters, and trees are no exception. In order to ease usage of high-level
|
||||
mlpack algorithms, each \c TreeType itself must be a template class taking three
|
||||
mlpack algorithms, each `TreeType` itself must be a template class taking three
|
||||
parameters:
|
||||
|
||||
- `MetricType` -- the underlying metric that the tree will be built on (see
|
||||
[the MetricType policy documentation](metrictype.md))
|
||||
[the MetricType policy documentation](metrics.md))
|
||||
- `StatisticType` -- holds any auxiliary information that individual
|
||||
algorithms may need
|
||||
- `MatType` -- the type of the matrix used to represent the data
|
||||
@@ -424,7 +424,7 @@ This constructor should be called with `(*this)` after the node is constructed
|
||||
The last template parameter is the `MatType` parameter. This is generally
|
||||
`arma::mat` or `arma::sp_mat`, but could be any Armadillo type, including
|
||||
matrices that hold data points of different precisions (such as `float` or even
|
||||
`int`). It generally suffices to write \c MatType assuming that `arma::mat`
|
||||
`int`). It generally suffices to write `MatType` assuming that `arma::mat`
|
||||
will be used, since the vast majority of the time this will be what is used.
|
||||
|
||||
### Constructors and destructors
|
||||
|
||||
@@ -105,11 +105,11 @@ int main()
|
||||
testLabels, 0.3);
|
||||
|
||||
// Create the RandomForest object and train it on the training data.
|
||||
RandomForest r(trainDataset,
|
||||
trainLabels,
|
||||
7 /* number of classes */,
|
||||
10 /* number of trees */,
|
||||
3 /* minimum leaf size */);
|
||||
RandomForest<> r(trainDataset,
|
||||
trainLabels,
|
||||
7 /* number of classes */,
|
||||
10 /* number of trees */,
|
||||
3 /* minimum leaf size */);
|
||||
|
||||
// Compute and print the training error.
|
||||
Row<size_t> trainPredictions;
|
||||
|
||||
@@ -137,7 +137,8 @@ int main()
|
||||
NMFALSFactorizer nmf;
|
||||
mat W, H;
|
||||
mat V = randu<mat>(100, 100);
|
||||
double residue = nmf.Apply(V, W, H);
|
||||
size_t r = 10;
|
||||
double residue = nmf.Apply(V, r, W, H);
|
||||
}
|
||||
```
|
||||
|
||||
@@ -169,11 +170,12 @@ using namespace mlpack;
|
||||
|
||||
int main()
|
||||
{
|
||||
sp_mat V = randu<sp_mat>(100,100);
|
||||
sp_mat V = sprandu<sp_mat>(100,100,0.1);
|
||||
size_t r = 10;
|
||||
mat W, H;
|
||||
|
||||
SVDBatchFactorizer<sp_mat> svd;
|
||||
double residue = svd.Apply(V, W, H);
|
||||
double residue = svd.Apply(V, r, W, H);
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@@ -80,7 +80,7 @@ In order to solve this problem, mlpack provides a number of interfaces.
|
||||
|
||||
- two simple command-line executables to calculate approximate furthest
|
||||
neighbors
|
||||
- a simple C++ class for QDAFN"
|
||||
- a simple C++ class for QDAFN
|
||||
- a simple C++ class for DrusillaSelect
|
||||
- a simple C++ class for tree-based and brute-force search
|
||||
|
||||
@@ -114,8 +114,8 @@ search:
|
||||
|
||||
These two programs allow a large number of algorithms to be used to find
|
||||
approximate furthest neighbors. Note that the `mlpack_kfn` program is also
|
||||
documented in the [KNN tutorial](knn.md) page, as it shares options with the
|
||||
`mlpack_knn` program.
|
||||
documented in the [KNN tutorial](neighbor_search.md) page, as it shares options
|
||||
with the `mlpack_knn` program.
|
||||
|
||||
Below are several examples of how the `mlpack_approx_kfn` and `mlpack_kfn`
|
||||
programs might be used. The first examples focus on the `mlpack_approx_kfn`
|
||||
@@ -682,7 +682,7 @@ std::cout << ds.CandidateSet().col(4).t();
|
||||
|
||||
It is possible to retrain a `DrusillaSelect` model with new parameters or with a
|
||||
new reference set. This is functionally equivalent to creating a new model.
|
||||
The example code below creates a first \c DrusillaSelect model using 3 tables
|
||||
The example code below creates a first `DrusillaSelect` model using 3 tables
|
||||
and 10 projections, and then retrains this with the same reference set using 10
|
||||
tables and 3 projections.
|
||||
|
||||
@@ -869,7 +869,7 @@ qdafn.Search(querySet, 3, neighbors, distances);
|
||||
The extensive `NeighborSearch` class also provides a way to search for
|
||||
approximate furthest neighbors using a different, tree-based technique. For
|
||||
full documentation on this class, see the [NeighborSearch
|
||||
tutorial](nstutorial.md). The `KFN` class is a convenient typedef of the
|
||||
tutorial](neighbor_search.md). The `KFN` class is a convenient typedef of the
|
||||
`NeighborSearch` class that can be used to perform the furthest neighbors task
|
||||
with `kd`-trees.
|
||||
|
||||
@@ -982,6 +982,6 @@ kfn.Search(querySet, 2, neighbors, distances);
|
||||
## Further documentation
|
||||
|
||||
For further documentation on the approximate furthest neighbor facilities
|
||||
offered by mlpack, see also [the NeighborSearch tutorial](nstutorial.md). Also,
|
||||
offered by mlpack, see also [the NeighborSearch tutorial](neighbor_search.md). Also,
|
||||
each class (`QDAFN`, `DrusillaSelect`, `NeighborSelect`) are well-documented,
|
||||
and more details can be found in the source code documentation.
|
||||
|
||||
+2
-2
@@ -389,8 +389,8 @@ number of rows equal to the number of items and the number of columns equal to
|
||||
the number of users, and each nonzero element in the matrix corresponds to a
|
||||
non-missing rating.
|
||||
|
||||
The method that the factorizer implements is specified via the \c
|
||||
FactorizerTraits class, which is a template metaprogramming traits class:
|
||||
The method that the factorizer implements is specified via the
|
||||
`FactorizerTraits` class, which is a template metaprogramming traits class:
|
||||
|
||||
```c++
|
||||
template<typename FactorizerType>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
Image datasets are becoming increasingly popular in deep learning.
|
||||
|
||||
mlpack's image saving/loading functionality is based on [stb/](https://github.com/nothings/stb).
|
||||
mlpack's image saving/loading functionality is based on [stb](https://github.com/nothings/stb).
|
||||
|
||||
## Model API
|
||||
|
||||
|
||||
@@ -445,11 +445,12 @@ how to modify them.
|
||||
|
||||
Most machine learning algorithms in mlpack support modifying the distance
|
||||
metric, and `KMeans<>` is no exception. Similar to `NeighborSearch` (see the
|
||||
section in the [NeighborSearch tutorial](neighbor_search.md)), any of mlpack's
|
||||
"MetricType policy class" section in the
|
||||
[NeighborSearch tutorial](neighbor_search.md)), any of mlpack's
|
||||
metric classes (found in `mlpack/core/metrics/`) can be given as an argument.
|
||||
The `LMetric` class is a good example implementation.
|
||||
|
||||
A class fulfilling the [MetricType policy](../developer/metrictype.md) must
|
||||
A class fulfilling the [MetricType policy](../developer/metrics.md) must
|
||||
provide the following two functions:
|
||||
|
||||
```c++
|
||||
|
||||
@@ -363,7 +363,7 @@ covariance matrix). Therefore, you can write a non-static MetricType class and
|
||||
use it seamlessly with `NeighborSearch`.
|
||||
|
||||
For more information on the `MetricType` policy, see the [documentation for
|
||||
`MetricType`s](../developer/metrics.md).
|
||||
`MetricType`](../developer/metrics.md).
|
||||
|
||||
### `MatType` policy class
|
||||
|
||||
@@ -418,8 +418,7 @@ The `RuleType` class provides the following functions for use in the traverser:
|
||||
// Evaluate the base case between two points.
|
||||
double BaseCase(const size_t queryIndex, const size_t referenceIndex);
|
||||
|
||||
// Score the two nodes to see if they can be pruned, returning DBL_MAX if they
|
||||
// can be pruned.
|
||||
// Score the two nodes to see if they can be pruned, returning DBL_MAX if so.
|
||||
double Score(TreeType& queryNode, TreeType& referenceNode);
|
||||
```
|
||||
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
Range search is a simple machine learning task which aims to find all the
|
||||
neighbors of a point that fall into a certain range of distances. In this
|
||||
setting, we have a *query* and a *reference* dataset. Given a certain range,
|
||||
for each point in the *query* dataset, we wish to know all points in the \b
|
||||
reference dataset which have distances within that given range to the given
|
||||
for each point in the *query* dataset, we wish to know all points in the
|
||||
*reference* dataset which have distances within that given range to the given
|
||||
query point.
|
||||
|
||||
Alternately, if the query and reference datasets are the same, the problem can
|
||||
|
||||
@@ -143,13 +143,13 @@ can't pass mlpack's `FFN` network directly. Instead, we have to wrap it into
|
||||
int main()
|
||||
{
|
||||
// Set up the network.
|
||||
FFN<MeanSquaredError<>, GaussianInitialization> network(MeanSquaredError<>(),
|
||||
FFN<MeanSquaredError, GaussianInitialization> network(MeanSquaredError(),
|
||||
GaussianInitialization(0, 0.001));
|
||||
network.Add<Linear<>>(4, 128);
|
||||
network.Add<ReLULayer<>>();
|
||||
network.Add<Linear<>>(128, 128);
|
||||
network.Add<ReLULayer<>>();
|
||||
network.Add<Linear<>>(128, 2);
|
||||
network.Add<Linear>(128);
|
||||
network.Add<ReLU>();
|
||||
network.Add<Linear>(128);
|
||||
network.Add<ReLU>();
|
||||
network.Add<Linear>(2);
|
||||
|
||||
SimpleDQN<> model(network);
|
||||
|
||||
@@ -159,7 +159,7 @@ The next step would be to setup the other components of the Q-learning agent,
|
||||
namely its policy, replay method and hyperparameters.
|
||||
|
||||
```c++
|
||||
// Set up the policy and replay method.
|
||||
// Set up the policy and replay method.
|
||||
GreedyPolicy<CartPole> policy(1.0, 1000, 0.1, 0.99);
|
||||
RandomReplay<CartPole> replayMethod(10, 10000);
|
||||
|
||||
@@ -314,6 +314,7 @@ auto measure = [&returns, &position, &episode](double episodeReturn)
|
||||
std::cout << "Episode No.: " << episode
|
||||
<< "; Episode Return: " << episodeReturn
|
||||
<< "; Average Return: " << arma::mean(returns) << std::endl;
|
||||
return false;
|
||||
};
|
||||
```
|
||||
|
||||
@@ -328,17 +329,16 @@ Here is the full code to try this right away:
|
||||
#include <mlpack.hpp>
|
||||
|
||||
using namespace mlpack;
|
||||
using namespace mlpack::rl;
|
||||
|
||||
int main()
|
||||
{
|
||||
// Set up the network.
|
||||
FFN<MeanSquaredError<>, GaussianInitialization> model(MeanSquaredError<>(), GaussianInitialization(0, 0.001));
|
||||
model.Add<Linear<>>(4, 128);
|
||||
model.Add<ReLULayer<>>();
|
||||
model.Add<Linear<>>(128, 128);
|
||||
model.Add<ReLULayer<>>();
|
||||
model.Add<Linear<>>(128, 2);
|
||||
FFN<MeanSquaredError, GaussianInitialization> model(MeanSquaredError(), GaussianInitialization(0, 0.001));
|
||||
model.Add<Linear>(128);
|
||||
model.Add<ReLU>();
|
||||
model.Add<Linear>(128);
|
||||
model.Add<ReLU>();
|
||||
model.Add<Linear>(2);
|
||||
|
||||
AggregatedPolicy<GreedyPolicy<CartPole>> policy({GreedyPolicy<CartPole>(0.7, 5000, 0.1),
|
||||
GreedyPolicy<CartPole>(0.7, 5000, 0.01),
|
||||
@@ -371,6 +371,7 @@ int main()
|
||||
std::cout << "Episode No.: " << episode
|
||||
<< "; Episode Return: " << episodeReturn
|
||||
<< "; Average Return: " << arma::mean(returns) << std::endl;
|
||||
return false;
|
||||
};
|
||||
|
||||
for (int i = 0; i < 100; i++)
|
||||
|
||||
+1
-1
@@ -70,7 +70,7 @@ SoftmaxRegression(const arma::mat& data,
|
||||
```
|
||||
|
||||
which has the parameter `lambda` after three conventional arguments (`data`,
|
||||
\c labels and \c numClasses). We can skip passing `fitIntercept` and
|
||||
`labels` and `numClasses`). We can skip passing `fitIntercept` and
|
||||
`optimizer` since there are the default values. (Technically, we don't even
|
||||
need to pass `lambda` since there is a default value.)
|
||||
|
||||
|
||||
+2
-2
@@ -177,8 +177,8 @@ matrix = matrix.t(); // We must transpose after load!
|
||||
The transposition after loading is necessary if the coordinate list is in
|
||||
row-major format (that is, if each row in the matrix represents a point and each
|
||||
column represents a feature). Be sure that the matrix you use with mlpack
|
||||
methods has points as columns and features as rows! See \ref matrices for more
|
||||
information.
|
||||
methods has points as columns and features as rows! See [matrices](matrices.md)
|
||||
for more information.
|
||||
|
||||
## Categorical features and command line programs
|
||||
|
||||
|
||||
+2
-2
@@ -179,7 +179,7 @@ HyperParameterTuner<LinearRegression, MSE, SimpleCV> hpt(0.2, dataset,
|
||||
```
|
||||
|
||||
Next, we must set up the hyperparameters to be optimized. If we are doing a
|
||||
grid search with the \c ens::GridSearch optimizer (the
|
||||
grid search with the `ens::GridSearch` optimizer (the
|
||||
default), then we only need to pass a `std::vector` (for non-numeric
|
||||
hyperparameters) or an `arma::vec` (for numeric hyperparameters) containing all
|
||||
of the possible choices that we wish to search over.
|
||||
@@ -216,6 +216,6 @@ Optimization" section for more details.
|
||||
|
||||
## Further documentation
|
||||
|
||||
For more information on the `HyperParameterTuner` class, see the source code fro
|
||||
For more information on the `HyperParameterTuner` class, see the source code of
|
||||
the `HyperParameterTuner` class (it is very well commented!), and the
|
||||
[cross-validation tutorial](cv.md).
|
||||
|
||||
@@ -48,6 +48,7 @@
|
||||
#include "mlpack/methods/kmeans.hpp"
|
||||
#include "mlpack/methods/lars.hpp"
|
||||
#include "mlpack/methods/linear_regression.hpp"
|
||||
#include "mlpack/methods/linear_svm.hpp"
|
||||
#include "mlpack/methods/lmnn.hpp"
|
||||
#include "mlpack/methods/local_coordinate_coding.hpp"
|
||||
#include "mlpack/methods/logistic_regression.hpp"
|
||||
@@ -57,8 +58,11 @@
|
||||
#include "mlpack/methods/naive_bayes.hpp"
|
||||
#include "mlpack/methods/nca.hpp"
|
||||
#include "mlpack/methods/neighbor_search.hpp"
|
||||
#include "mlpack/methods/nmf.hpp"
|
||||
#include "mlpack/methods/nystroem_method.hpp"
|
||||
#include "mlpack/methods/pca.hpp"
|
||||
#include "mlpack/methods/perceptron.hpp"
|
||||
#include "mlpack/methods/preprocess.hpp"
|
||||
#include "mlpack/methods/quic_svd.hpp"
|
||||
#include "mlpack/methods/radical.hpp"
|
||||
#include "mlpack/methods/random_forest.hpp"
|
||||
|
||||
@@ -83,6 +83,11 @@ if (BUILD_R_BINDINGS)
|
||||
"\\1" MLPACK_VERSION_PATCH "${VERSION_HPP_CONTENTS}")
|
||||
set(PACKAGE_VERSION
|
||||
"${MLPACK_VERSION_MAJOR}.${MLPACK_VERSION_MINOR}.${MLPACK_VERSION_PATCH}")
|
||||
if (USING_GIT)
|
||||
set(PACKAGE_DOC_VERSION "git")
|
||||
else ()
|
||||
set(PACKAGE_DOC_VERSION "${PACKAGE_VERSION}")
|
||||
endif ()
|
||||
|
||||
string(TIMESTAMP PACKAGE_DATE "%Y-%m-%d")
|
||||
|
||||
|
||||
@@ -3,6 +3,11 @@
|
||||
* @author Yashwant Singh Parihar
|
||||
*
|
||||
* This is a template file to call the PrintR() function for a given binding.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#define BINDING_TYPE BINDING_TYPE_R
|
||||
// Disable debug output.
|
||||
|
||||
@@ -15,7 +15,7 @@ LinkingTo: Rcpp,
|
||||
RcppArmadillo (>= @RcppArmadillo_Version@),
|
||||
RcppEnsmallen (>= @RcppEnsmallen_Version@)
|
||||
Suggests: testthat (>= 2.1.0)
|
||||
URL: https://www.mlpack.org/doc/mlpack-@PACKAGE_VERSION@/r_documentation.html,
|
||||
URL: https://www.mlpack.org/doc/mlpack-@PACKAGE_DOC_VERSION@/r_documentation.html,
|
||||
https://github.com/mlpack/mlpack
|
||||
BugReports: https://github.com/mlpack/mlpack/issues
|
||||
RoxygenNote: 7.1.0
|
||||
|
||||
@@ -121,11 +121,11 @@ void BINDING_FUNCTION(util::Params& params, util::Timers& /* timers */)
|
||||
// the 3rd row will be multiplied by two.
|
||||
if (params.Has("matrix_in"))
|
||||
{
|
||||
arma::mat out = move(params.Get<arma::mat>("matrix_in"));
|
||||
arma::mat out = std::move(params.Get<arma::mat>("matrix_in"));
|
||||
out.shed_row(4);
|
||||
out.row(2) *= 2.0;
|
||||
|
||||
params.Get<arma::mat>("matrix_out") = move(out);
|
||||
params.Get<arma::mat>("matrix_out") = std::move(out);
|
||||
}
|
||||
|
||||
// Input matrices should be at least 5 rows; the 5th row will be dropped and
|
||||
@@ -133,70 +133,70 @@ void BINDING_FUNCTION(util::Params& params, util::Timers& /* timers */)
|
||||
if (params.Has("umatrix_in"))
|
||||
{
|
||||
arma::Mat<size_t> out =
|
||||
move(params.Get<arma::Mat<size_t>>("umatrix_in"));
|
||||
std::move(params.Get<arma::Mat<size_t>>("umatrix_in"));
|
||||
out.shed_row(4);
|
||||
out.row(2) *= 2;
|
||||
|
||||
params.Get<arma::Mat<size_t>>("umatrix_out") = move(out);
|
||||
params.Get<arma::Mat<size_t>>("umatrix_out") = std::move(out);
|
||||
}
|
||||
|
||||
// An input column or row should have all elements multiplied by two.
|
||||
if (params.Has("col_in"))
|
||||
{
|
||||
arma::vec out = move(params.Get<arma::vec>("col_in"));
|
||||
arma::vec out = std::move(params.Get<arma::vec>("col_in"));
|
||||
out *= 2.0;
|
||||
|
||||
params.Get<arma::vec>("col_out") = move(out);
|
||||
params.Get<arma::vec>("col_out") = std::move(out);
|
||||
}
|
||||
|
||||
if (params.Has("ucol_in"))
|
||||
{
|
||||
arma::Col<size_t> out =
|
||||
move(params.Get<arma::Col<size_t>>("ucol_in"));
|
||||
std::move(params.Get<arma::Col<size_t>>("ucol_in"));
|
||||
out += 1;
|
||||
|
||||
params.Get<arma::Col<size_t>>("ucol_out") = move(out);
|
||||
params.Get<arma::Col<size_t>>("ucol_out") = std::move(out);
|
||||
}
|
||||
|
||||
if (params.Has("row_in"))
|
||||
{
|
||||
arma::rowvec out = move(params.Get<arma::rowvec>("row_in"));
|
||||
arma::rowvec out = std::move(params.Get<arma::rowvec>("row_in"));
|
||||
out *= 2.0;
|
||||
|
||||
params.Get<arma::rowvec>("row_out") = move(out);
|
||||
params.Get<arma::rowvec>("row_out") = std::move(out);
|
||||
}
|
||||
|
||||
if (params.Has("urow_in"))
|
||||
{
|
||||
arma::Row<size_t> out =
|
||||
move(params.Get<arma::Row<size_t>>("urow_in"));
|
||||
std::move(params.Get<arma::Row<size_t>>("urow_in"));
|
||||
out += 1;
|
||||
|
||||
params.Get<arma::Row<size_t>>("urow_out") = move(out);
|
||||
params.Get<arma::Row<size_t>>("urow_out") = std::move(out);
|
||||
}
|
||||
|
||||
// Vector arguments should have the last element removed.
|
||||
if (params.Has("vector_in"))
|
||||
{
|
||||
vector<int> out = move(params.Get<vector<int>>("vector_in"));
|
||||
vector<int> out = std::move(params.Get<vector<int>>("vector_in"));
|
||||
out.pop_back();
|
||||
|
||||
params.Get<vector<int>>("vector_out") = move(out);
|
||||
params.Get<vector<int>>("vector_out") = std::move(out);
|
||||
}
|
||||
|
||||
if (params.Has("str_vector_in"))
|
||||
{
|
||||
vector<string> out = move(params.Get<vector<string>>("str_vector_in"));
|
||||
vector<string> out = std::move(params.Get<vector<string>>("str_vector_in"));
|
||||
out.pop_back();
|
||||
|
||||
params.Get<vector<string>>("str_vector_out") = move(out);
|
||||
params.Get<vector<string>>("str_vector_out") = std::move(out);
|
||||
}
|
||||
|
||||
// All numeric elements should be multiplied by 3.
|
||||
if (params.Has("matrix_and_info_in"))
|
||||
{
|
||||
typedef tuple<data::DatasetInfo, arma::mat> TupleType;
|
||||
TupleType tuple = move(params.Get<TupleType>("matrix_and_info_in"));
|
||||
TupleType tuple = std::move(params.Get<TupleType>("matrix_and_info_in"));
|
||||
|
||||
const data::DatasetInfo& di = std::get<0>(tuple);
|
||||
arma::mat& m = std::get<1>(tuple);
|
||||
@@ -222,7 +222,7 @@ void BINDING_FUNCTION(util::Params& params, util::Timers& /* timers */)
|
||||
}
|
||||
}
|
||||
|
||||
params.Get<arma::mat>("matrix_and_info_out") = move(m);
|
||||
params.Get<arma::mat>("matrix_and_info_out") = std::move(m);
|
||||
}
|
||||
|
||||
// If we got a request to build a model, then build it.
|
||||
|
||||
+119
-70
@@ -1,11 +1,11 @@
|
||||
// CLI11: Version 2.3.1
|
||||
// CLI11: Version 2.3.2
|
||||
// Originally designed by Henry Schreiner
|
||||
// https://github.com/CLIUtils/CLI11
|
||||
//
|
||||
// This is a standalone header file generated by MakeSingleHeader.py in CLI11/scripts
|
||||
// from: v2.3.1
|
||||
// from: v2.3.2
|
||||
//
|
||||
// CLI11 2.3.1 Copyright (c) 2017-2022 University of Cincinnati, developed by Henry
|
||||
// CLI11 2.3.2 Copyright (c) 2017-2022 University of Cincinnati, developed by Henry
|
||||
// Schreiner under NSF AWARD 1414736. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms of CLI11, with or without
|
||||
@@ -34,34 +34,34 @@
|
||||
#pragma once
|
||||
|
||||
// Standard combined includes:
|
||||
#include <functional>
|
||||
#include <locale>
|
||||
#include <cstdint>
|
||||
#include <iomanip>
|
||||
#include <memory>
|
||||
#include <exception>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <iterator>
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
#include <cmath>
|
||||
#include <type_traits>
|
||||
#include <limits>
|
||||
#include <set>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
#include <map>
|
||||
#include <stdexcept>
|
||||
#include <locale>
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <iterator>
|
||||
#include <exception>
|
||||
#include <numeric>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <tuple>
|
||||
#include <map>
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <sstream>
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
|
||||
|
||||
#define CLI11_VERSION_MAJOR 2
|
||||
#define CLI11_VERSION_MINOR 3
|
||||
#define CLI11_VERSION_PATCH 1
|
||||
#define CLI11_VERSION "2.3.1"
|
||||
#define CLI11_VERSION_PATCH 2
|
||||
#define CLI11_VERSION "2.3.2"
|
||||
|
||||
|
||||
|
||||
@@ -972,7 +972,9 @@ constexpr enabler dummy = {};
|
||||
template <bool B, class T = void> using enable_if_t = typename std::enable_if<B, T>::type;
|
||||
|
||||
/// A copy of std::void_t from C++17 (helper for C++11 and C++14)
|
||||
template <typename... Ts> struct make_void { using type = void; };
|
||||
template <typename... Ts> struct make_void {
|
||||
using type = void;
|
||||
};
|
||||
|
||||
/// A copy of std::void_t from C++17 - same reasoning as enable_if_t, it does not hurt to redefine
|
||||
template <typename... Ts> using void_t = typename make_void<Ts...>::type;
|
||||
@@ -1001,10 +1003,14 @@ template <typename T> struct is_copyable_ptr {
|
||||
};
|
||||
|
||||
/// This can be specialized to override the type deduction for IsMember.
|
||||
template <typename T> struct IsMemberType { using type = T; };
|
||||
template <typename T> struct IsMemberType {
|
||||
using type = T;
|
||||
};
|
||||
|
||||
/// The main custom type needed here is const char * should be a string.
|
||||
template <> struct IsMemberType<const char *> { using type = std::string; };
|
||||
template <> struct IsMemberType<const char *> {
|
||||
using type = std::string;
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
|
||||
@@ -1014,7 +1020,9 @@ namespace detail {
|
||||
/// pointer_traits<T> be valid.
|
||||
|
||||
/// not a pointer
|
||||
template <typename T, typename Enable = void> struct element_type { using type = T; };
|
||||
template <typename T, typename Enable = void> struct element_type {
|
||||
using type = T;
|
||||
};
|
||||
|
||||
template <typename T> struct element_type<T, typename std::enable_if<is_copyable_ptr<T>::value>::type> {
|
||||
using type = typename std::pointer_traits<T>::element_type;
|
||||
@@ -1022,7 +1030,9 @@ template <typename T> struct element_type<T, typename std::enable_if<is_copyable
|
||||
|
||||
/// Combination of the element type and value type - remove pointer (including smart pointers) and get the value_type of
|
||||
/// the container
|
||||
template <typename T> struct element_value_type { using type = typename element_type<T>::type::value_type; };
|
||||
template <typename T> struct element_value_type {
|
||||
using type = typename element_type<T>::type::value_type;
|
||||
};
|
||||
|
||||
/// Adaptor for set-like structure: This just wraps a normal container in a few utilities that do almost nothing.
|
||||
template <typename T, typename _ = void> struct pair_adaptor : std::false_type {
|
||||
@@ -1283,7 +1293,9 @@ auto value_string(const T &value) -> decltype(to_string(value)) {
|
||||
}
|
||||
|
||||
/// template to get the underlying value type if it exists or use a default
|
||||
template <typename T, typename def, typename Enable = void> struct wrapped_type { using type = def; };
|
||||
template <typename T, typename def, typename Enable = void> struct wrapped_type {
|
||||
using type = def;
|
||||
};
|
||||
|
||||
/// Type size for regular object types that do not look like a tuple
|
||||
template <typename T, typename def> struct wrapped_type<T, def, typename std::enable_if<is_wrapper<T>::value>::type> {
|
||||
@@ -1291,7 +1303,9 @@ template <typename T, typename def> struct wrapped_type<T, def, typename std::en
|
||||
};
|
||||
|
||||
/// This will only trigger for actual void type
|
||||
template <typename T, typename Enable = void> struct type_count_base { static const int value{0}; };
|
||||
template <typename T, typename Enable = void> struct type_count_base {
|
||||
static const int value{0};
|
||||
};
|
||||
|
||||
/// Type size for regular object types that do not look like a tuple
|
||||
template <typename T>
|
||||
@@ -1321,7 +1335,9 @@ template <typename T> struct subtype_count;
|
||||
template <typename T> struct subtype_count_min;
|
||||
|
||||
/// This will only trigger for actual void type
|
||||
template <typename T, typename Enable = void> struct type_count { static const int value{0}; };
|
||||
template <typename T, typename Enable = void> struct type_count {
|
||||
static const int value{0};
|
||||
};
|
||||
|
||||
/// Type size for regular object types that do not look like a tuple
|
||||
template <typename T>
|
||||
@@ -1372,7 +1388,9 @@ template <typename T> struct subtype_count {
|
||||
};
|
||||
|
||||
/// This will only trigger for actual void type
|
||||
template <typename T, typename Enable = void> struct type_count_min { static const int value{0}; };
|
||||
template <typename T, typename Enable = void> struct type_count_min {
|
||||
static const int value{0};
|
||||
};
|
||||
|
||||
/// Type size for regular object types that do not look like a tuple
|
||||
template <typename T>
|
||||
@@ -1421,7 +1439,9 @@ template <typename T> struct subtype_count_min {
|
||||
};
|
||||
|
||||
/// This will only trigger for actual void type
|
||||
template <typename T, typename Enable = void> struct expected_count { static const int value{0}; };
|
||||
template <typename T, typename Enable = void> struct expected_count {
|
||||
static const int value{0};
|
||||
};
|
||||
|
||||
/// For most types the number of expected items is 1
|
||||
template <typename T>
|
||||
@@ -1725,11 +1745,15 @@ inline std::string type_name() {
|
||||
/// Convert to an unsigned integral
|
||||
template <typename T, enable_if_t<std::is_unsigned<T>::value, detail::enabler> = detail::dummy>
|
||||
bool integral_conversion(const std::string &input, T &output) noexcept {
|
||||
if(input.empty()) {
|
||||
if(input.empty() || input.front() == '-') {
|
||||
return false;
|
||||
}
|
||||
char *val = nullptr;
|
||||
errno = 0;
|
||||
std::uint64_t output_ll = std::strtoull(input.c_str(), &val, 0);
|
||||
if(errno == ERANGE) {
|
||||
return false;
|
||||
}
|
||||
output = static_cast<T>(output_ll);
|
||||
if(val == (input.c_str() + input.size()) && static_cast<std::uint64_t>(output) == output_ll) {
|
||||
return true;
|
||||
@@ -1750,7 +1774,11 @@ bool integral_conversion(const std::string &input, T &output) noexcept {
|
||||
return false;
|
||||
}
|
||||
char *val = nullptr;
|
||||
errno = 0;
|
||||
std::int64_t output_ll = std::strtoll(input.c_str(), &val, 0);
|
||||
if(errno == ERANGE) {
|
||||
return false;
|
||||
}
|
||||
output = static_cast<T>(output_ll);
|
||||
if(val == (input.c_str() + input.size()) && static_cast<std::int64_t>(output) == output_ll) {
|
||||
return true;
|
||||
@@ -1867,18 +1895,18 @@ bool lexical_cast(const std::string &input, T &output) {
|
||||
bool worked = false;
|
||||
auto nloc = str1.find_last_of("+-");
|
||||
if(nloc != std::string::npos && nloc > 0) {
|
||||
worked = detail::lexical_cast(str1.substr(0, nloc), x);
|
||||
worked = lexical_cast(str1.substr(0, nloc), x);
|
||||
str1 = str1.substr(nloc);
|
||||
if(str1.back() == 'i' || str1.back() == 'j')
|
||||
str1.pop_back();
|
||||
worked = worked && detail::lexical_cast(str1, y);
|
||||
worked = worked && lexical_cast(str1, y);
|
||||
} else {
|
||||
if(str1.back() == 'i' || str1.back() == 'j') {
|
||||
str1.pop_back();
|
||||
worked = detail::lexical_cast(str1, y);
|
||||
worked = lexical_cast(str1, y);
|
||||
x = XC{0};
|
||||
} else {
|
||||
worked = detail::lexical_cast(str1, x);
|
||||
worked = lexical_cast(str1, x);
|
||||
y = XC{0};
|
||||
}
|
||||
}
|
||||
@@ -2099,7 +2127,7 @@ template <typename AssignTo,
|
||||
detail::enabler> = detail::dummy>
|
||||
bool lexical_assign(const std::string &input, AssignTo &output) {
|
||||
ConvertTo val{};
|
||||
bool parse_result = (!input.empty()) ? lexical_cast<ConvertTo>(input, val) : true;
|
||||
bool parse_result = (!input.empty()) ? lexical_cast(input, val) : true;
|
||||
if(parse_result) {
|
||||
output = val;
|
||||
}
|
||||
@@ -2115,7 +2143,7 @@ template <
|
||||
detail::enabler> = detail::dummy>
|
||||
bool lexical_assign(const std::string &input, AssignTo &output) {
|
||||
ConvertTo val{};
|
||||
bool parse_result = input.empty() ? true : lexical_cast<ConvertTo>(input, val);
|
||||
bool parse_result = input.empty() ? true : lexical_cast(input, val);
|
||||
if(parse_result) {
|
||||
output = AssignTo(val); // use () form of constructor to allow some implicit conversions
|
||||
}
|
||||
@@ -2193,7 +2221,7 @@ bool lexical_conversion(const std::vector<std::string> &strings, AssignTo &outpu
|
||||
if(str1.back() == 'i' || str1.back() == 'j') {
|
||||
str1.pop_back();
|
||||
}
|
||||
auto worked = detail::lexical_cast(strings[0], x) && detail::lexical_cast(str1, y);
|
||||
auto worked = lexical_cast(strings[0], x) && lexical_cast(str1, y);
|
||||
if(worked) {
|
||||
output = ConvertTo{x, y};
|
||||
}
|
||||
@@ -2457,7 +2485,7 @@ inline std::string sum_string_vector(const std::vector<std::string> &values) {
|
||||
std::string output;
|
||||
for(const auto &arg : values) {
|
||||
double tv{0.0};
|
||||
auto comp = detail::lexical_cast<double>(arg, tv);
|
||||
auto comp = lexical_cast(arg, tv);
|
||||
if(!comp) {
|
||||
try {
|
||||
tv = static_cast<double>(detail::to_flag_value(arg));
|
||||
@@ -2475,8 +2503,7 @@ inline std::string sum_string_vector(const std::vector<std::string> &values) {
|
||||
} else {
|
||||
if(val <= static_cast<double>((std::numeric_limits<std::int64_t>::min)()) ||
|
||||
val >= static_cast<double>((std::numeric_limits<std::int64_t>::max)()) ||
|
||||
// NOLINTNEXTLINE(clang-diagnostic-float-equal,bugprone-narrowing-conversions)
|
||||
val == static_cast<std::int64_t>(val)) {
|
||||
std::ceil(val) == std::floor(val)) {
|
||||
output = detail::value_string(static_cast<int64_t>(val));
|
||||
} else {
|
||||
output = detail::value_string(val);
|
||||
@@ -2998,8 +3025,9 @@ template <typename DesiredType> class TypeValidator : public Validator {
|
||||
public:
|
||||
explicit TypeValidator(const std::string &validator_name)
|
||||
: Validator(validator_name, [](std::string &input_string) {
|
||||
using CLI::detail::lexical_cast;
|
||||
auto val = DesiredType();
|
||||
if(!detail::lexical_cast(input_string, val)) {
|
||||
if(!lexical_cast(input_string, val)) {
|
||||
return std::string("Failed parsing ") + input_string + " as a " + detail::type_name<DesiredType>();
|
||||
}
|
||||
return std::string();
|
||||
@@ -3033,8 +3061,9 @@ class Range : public Validator {
|
||||
}
|
||||
|
||||
func_ = [min_val, max_val](std::string &input) {
|
||||
using CLI::detail::lexical_cast;
|
||||
T val;
|
||||
bool converted = detail::lexical_cast(input, val);
|
||||
bool converted = lexical_cast(input, val);
|
||||
if((!converted) || (val < min_val || val > max_val)) {
|
||||
std::stringstream out;
|
||||
out << "Value " << input << " not in range [";
|
||||
@@ -3070,8 +3099,9 @@ class Bound : public Validator {
|
||||
description(out.str());
|
||||
|
||||
func_ = [min_val, max_val](std::string &input) {
|
||||
using CLI::detail::lexical_cast;
|
||||
T val;
|
||||
bool converted = detail::lexical_cast(input, val);
|
||||
bool converted = lexical_cast(input, val);
|
||||
if(!converted) {
|
||||
return std::string("Value ") + input + " could not be converted";
|
||||
}
|
||||
@@ -3262,8 +3292,9 @@ class IsMember : public Validator {
|
||||
// This is the function that validates
|
||||
// It stores a copy of the set pointer-like, so shared_ptr will stay alive
|
||||
func_ = [set, filter_fn](std::string &input) {
|
||||
using CLI::detail::lexical_cast;
|
||||
local_item_t b;
|
||||
if(!detail::lexical_cast(input, b)) {
|
||||
if(!lexical_cast(input, b)) {
|
||||
throw ValidationError(input); // name is added later
|
||||
}
|
||||
if(filter_fn) {
|
||||
@@ -3330,8 +3361,9 @@ class Transformer : public Validator {
|
||||
desc_function_ = [mapping]() { return detail::generate_map(detail::smart_deref(mapping)); };
|
||||
|
||||
func_ = [mapping, filter_fn](std::string &input) {
|
||||
using CLI::detail::lexical_cast;
|
||||
local_item_t b;
|
||||
if(!detail::lexical_cast(input, b)) {
|
||||
if(!lexical_cast(input, b)) {
|
||||
return std::string();
|
||||
// there is no possible way we can match anything in the mapping if we can't convert so just return
|
||||
}
|
||||
@@ -3399,8 +3431,9 @@ class CheckedTransformer : public Validator {
|
||||
desc_function_ = tfunc;
|
||||
|
||||
func_ = [mapping, tfunc, filter_fn](std::string &input) {
|
||||
using CLI::detail::lexical_cast;
|
||||
local_item_t b;
|
||||
bool converted = detail::lexical_cast(input, b);
|
||||
bool converted = lexical_cast(input, b);
|
||||
if(converted) {
|
||||
if(filter_fn) {
|
||||
b = filter_fn(b);
|
||||
@@ -3502,7 +3535,8 @@ class AsNumberWithUnit : public Validator {
|
||||
unit = detail::to_lower(unit);
|
||||
}
|
||||
if(unit.empty()) {
|
||||
if(!detail::lexical_cast(input, num)) {
|
||||
using CLI::detail::lexical_cast;
|
||||
if(!lexical_cast(input, num)) {
|
||||
throw ValidationError(std::string("Value ") + input + " could not be converted to " +
|
||||
detail::type_name<Number>());
|
||||
}
|
||||
@@ -3520,7 +3554,8 @@ class AsNumberWithUnit : public Validator {
|
||||
}
|
||||
|
||||
if(!input.empty()) {
|
||||
bool converted = detail::lexical_cast(input, num);
|
||||
using CLI::detail::lexical_cast;
|
||||
bool converted = lexical_cast(input, num);
|
||||
if(!converted) {
|
||||
throw ValidationError(std::string("Value ") + input + " could not be converted to " +
|
||||
detail::type_name<Number>());
|
||||
@@ -3829,7 +3864,8 @@ CLI11_INLINE IPV4Validator::IPV4Validator() : Validator("IPV4") {
|
||||
}
|
||||
int num = 0;
|
||||
for(const auto &var : result) {
|
||||
bool retval = detail::lexical_cast(var, num);
|
||||
using CLI::detail::lexical_cast;
|
||||
bool retval = lexical_cast(var, num);
|
||||
if(!retval) {
|
||||
return std::string("Failed parsing number (") + var + ')';
|
||||
}
|
||||
@@ -5548,8 +5584,11 @@ struct AppFriend;
|
||||
} // namespace detail
|
||||
|
||||
namespace FailureMessage {
|
||||
std::string simple(const App *app, const Error &e);
|
||||
std::string help(const App *app, const Error &e);
|
||||
/// Printout a clean, simple message on error (the default in CLI11 1.5+)
|
||||
CLI11_INLINE std::string simple(const App *app, const Error &e);
|
||||
|
||||
/// Printout the full help string on error (if this fn is set, the old default for CLI11)
|
||||
CLI11_INLINE std::string help(const App *app, const Error &e);
|
||||
} // namespace FailureMessage
|
||||
|
||||
/// enumeration of modes of how to deal with extras in config files
|
||||
@@ -6122,7 +6161,8 @@ class App {
|
||||
std::string flag_description = "") {
|
||||
|
||||
CLI::callback_t fun = [&flag_result](const CLI::results_t &res) {
|
||||
return CLI::detail::lexical_cast(res[0], flag_result);
|
||||
using CLI::detail::lexical_cast;
|
||||
return lexical_cast(res[0], flag_result);
|
||||
};
|
||||
auto *opt = _add_flag_internal(flag_name, std::move(fun), std::move(flag_description));
|
||||
return detail::default_flag_modifiers<T>(opt);
|
||||
@@ -6138,8 +6178,9 @@ class App {
|
||||
CLI::callback_t fun = [&flag_results](const CLI::results_t &res) {
|
||||
bool retval = true;
|
||||
for(const auto &elem : res) {
|
||||
using CLI::detail::lexical_cast;
|
||||
flag_results.emplace_back();
|
||||
retval &= detail::lexical_cast(elem, flag_results.back());
|
||||
retval &= lexical_cast(elem, flag_results.back());
|
||||
}
|
||||
return retval;
|
||||
};
|
||||
@@ -6851,16 +6892,6 @@ CLI11_INLINE void retire_option(App *app, const std::string &option_name);
|
||||
/// Helper function to mark an option as retired
|
||||
CLI11_INLINE void retire_option(App &app, const std::string &option_name);
|
||||
|
||||
namespace FailureMessage {
|
||||
|
||||
/// Printout a clean, simple message on error (the default in CLI11 1.5+)
|
||||
CLI11_INLINE std::string simple(const App *app, const Error &e);
|
||||
|
||||
/// Printout the full help string on error (if this fn is set, the old default for CLI11)
|
||||
CLI11_INLINE std::string help(const App *app, const Error &e);
|
||||
|
||||
} // namespace FailureMessage
|
||||
|
||||
namespace detail {
|
||||
/// This class is simply to allow tests access to App's protected functions
|
||||
struct AppFriend {
|
||||
@@ -7143,8 +7174,9 @@ CLI11_INLINE Option *App::add_flag_callback(std::string flag_name,
|
||||
std::string flag_description) {
|
||||
|
||||
CLI::callback_t fun = [function](const CLI::results_t &res) {
|
||||
using CLI::detail::lexical_cast;
|
||||
bool trigger{false};
|
||||
auto result = CLI::detail::lexical_cast(res[0], trigger);
|
||||
auto result = lexical_cast(res[0], trigger);
|
||||
if(result && trigger) {
|
||||
function();
|
||||
}
|
||||
@@ -7159,8 +7191,9 @@ App::add_flag_function(std::string flag_name,
|
||||
std::string flag_description) {
|
||||
|
||||
CLI::callback_t fun = [function](const CLI::results_t &res) {
|
||||
using CLI::detail::lexical_cast;
|
||||
std::int64_t flag_count{0};
|
||||
CLI::detail::lexical_cast(res[0], flag_count);
|
||||
lexical_cast(res[0], flag_count);
|
||||
function(flag_count);
|
||||
return true;
|
||||
};
|
||||
@@ -7544,7 +7577,7 @@ CLI11_NODISCARD CLI11_INLINE std::string App::help(std::string prev, AppFormatMo
|
||||
// Delegate to subcommand if needed
|
||||
auto selected_subcommands = get_subcommands();
|
||||
if(!selected_subcommands.empty()) {
|
||||
return selected_subcommands.at(0)->help(prev, mode);
|
||||
return selected_subcommands.back()->help(prev, mode);
|
||||
}
|
||||
return formatter_->make_help(this, prev, mode);
|
||||
}
|
||||
@@ -8274,7 +8307,22 @@ CLI11_INLINE bool App::_parse_single_config(const ConfigItem &item, std::size_t
|
||||
if(item.inputs.size() <= 1) {
|
||||
// Flag parsing
|
||||
auto res = config_formatter_->to_flag(item);
|
||||
res = op->get_flag_value(item.name, res);
|
||||
bool converted{false};
|
||||
if(op->get_disable_flag_override()) {
|
||||
|
||||
try {
|
||||
auto val = detail::to_flag_value(res);
|
||||
if(val == 1) {
|
||||
res = op->get_flag_value(item.name, "{}");
|
||||
converted = true;
|
||||
}
|
||||
} catch(...) {
|
||||
}
|
||||
}
|
||||
|
||||
if(!converted) {
|
||||
res = op->get_flag_value(item.name, res);
|
||||
}
|
||||
|
||||
op->add_result(res);
|
||||
return true;
|
||||
@@ -8998,8 +9046,9 @@ CLI11_INLINE std::string convert_arg_for_ini(const std::string &arg, char string
|
||||
}
|
||||
// floating point conversion can convert some hex codes, but don't try that here
|
||||
if(arg.compare(0, 2, "0x") != 0 && arg.compare(0, 2, "0X") != 0) {
|
||||
using CLI::detail::lexical_cast;
|
||||
double val = 0.0;
|
||||
if(detail::lexical_cast(arg, val)) {
|
||||
if(lexical_cast(arg, val)) {
|
||||
return arg;
|
||||
}
|
||||
}
|
||||
@@ -9420,7 +9469,7 @@ CLI11_INLINE std::string Formatter::make_description(const App *app) const {
|
||||
if(min_options == 1) {
|
||||
desc += " \n[Exactly 1 of the following options is required]";
|
||||
} else {
|
||||
desc += " \n[Exactly " + std::to_string(min_options) + "options from the following list are required]";
|
||||
desc += " \n[Exactly " + std::to_string(min_options) + " options from the following list are required]";
|
||||
}
|
||||
} else if(max_options > 0) {
|
||||
if(min_options > 0) {
|
||||
|
||||
@@ -117,11 +117,11 @@ void BINDING_FUNCTION(util::Params& params, util::Timers& /* timer */)
|
||||
// the 3rd row will be multiplied by two.
|
||||
if (params.Has("matrix_in"))
|
||||
{
|
||||
arma::mat out = move(params.Get<arma::mat>("matrix_in"));
|
||||
arma::mat out = std::move(params.Get<arma::mat>("matrix_in"));
|
||||
out.shed_row(4);
|
||||
out.row(2) *= 2.0;
|
||||
|
||||
params.Get<arma::mat>("matrix_out") = move(out);
|
||||
params.Get<arma::mat>("matrix_out") = std::move(out);
|
||||
}
|
||||
|
||||
// Input matrices should be at least 5 rows; the 5th row will be dropped and
|
||||
@@ -129,70 +129,70 @@ void BINDING_FUNCTION(util::Params& params, util::Timers& /* timer */)
|
||||
if (params.Has("umatrix_in"))
|
||||
{
|
||||
arma::Mat<size_t> out =
|
||||
move(params.Get<arma::Mat<size_t>>("umatrix_in"));
|
||||
std::move(params.Get<arma::Mat<size_t>>("umatrix_in"));
|
||||
out.shed_row(4);
|
||||
out.row(2) *= 2;
|
||||
|
||||
params.Get<arma::Mat<size_t>>("umatrix_out") = move(out);
|
||||
params.Get<arma::Mat<size_t>>("umatrix_out") = std::move(out);
|
||||
}
|
||||
|
||||
// An input column or row should have all elements multiplied by two.
|
||||
if (params.Has("col_in"))
|
||||
{
|
||||
arma::vec out = move(params.Get<arma::vec>("col_in"));
|
||||
arma::vec out = std::move(params.Get<arma::vec>("col_in"));
|
||||
out *= 2.0;
|
||||
|
||||
params.Get<arma::vec>("col_out") = move(out);
|
||||
params.Get<arma::vec>("col_out") = std::move(out);
|
||||
}
|
||||
|
||||
if (params.Has("ucol_in"))
|
||||
{
|
||||
arma::Col<size_t> out =
|
||||
move(params.Get<arma::Col<size_t>>("ucol_in"));
|
||||
std::move(params.Get<arma::Col<size_t>>("ucol_in"));
|
||||
out *= 2;
|
||||
|
||||
params.Get<arma::Col<size_t>>("ucol_out") = move(out);
|
||||
params.Get<arma::Col<size_t>>("ucol_out") = std::move(out);
|
||||
}
|
||||
|
||||
if (params.Has("row_in"))
|
||||
{
|
||||
arma::rowvec out = move(params.Get<arma::rowvec>("row_in"));
|
||||
arma::rowvec out = std::move(params.Get<arma::rowvec>("row_in"));
|
||||
out *= 2.0;
|
||||
|
||||
params.Get<arma::rowvec>("row_out") = move(out);
|
||||
params.Get<arma::rowvec>("row_out") = std::move(out);
|
||||
}
|
||||
|
||||
if (params.Has("urow_in"))
|
||||
{
|
||||
arma::Row<size_t> out =
|
||||
move(params.Get<arma::Row<size_t>>("urow_in"));
|
||||
std::move(params.Get<arma::Row<size_t>>("urow_in"));
|
||||
out *= 2;
|
||||
|
||||
params.Get<arma::Row<size_t>>("urow_out") = move(out);
|
||||
params.Get<arma::Row<size_t>>("urow_out") = std::move(out);
|
||||
}
|
||||
|
||||
// Vector arguments should have the last element removed.
|
||||
if (params.Has("vector_in"))
|
||||
{
|
||||
vector<int> out = move(params.Get<vector<int>>("vector_in"));
|
||||
vector<int> out = std::move(params.Get<vector<int>>("vector_in"));
|
||||
out.pop_back();
|
||||
|
||||
params.Get<vector<int>>("vector_out") = move(out);
|
||||
params.Get<vector<int>>("vector_out") = std::move(out);
|
||||
}
|
||||
|
||||
if (params.Has("str_vector_in"))
|
||||
{
|
||||
vector<string> out = move(params.Get<vector<string>>("str_vector_in"));
|
||||
vector<string> out = std::move(params.Get<vector<string>>("str_vector_in"));
|
||||
out.pop_back();
|
||||
|
||||
params.Get<vector<string>>("str_vector_out") = move(out);
|
||||
params.Get<vector<string>>("str_vector_out") = std::move(out);
|
||||
}
|
||||
|
||||
// All numeric elements should be multiplied by 3.
|
||||
if (params.Has("matrix_and_info_in"))
|
||||
{
|
||||
typedef tuple<data::DatasetInfo, arma::mat> TupleType;
|
||||
TupleType tuple = move(params.Get<TupleType>("matrix_and_info_in"));
|
||||
TupleType tuple = std::move(params.Get<TupleType>("matrix_and_info_in"));
|
||||
|
||||
const data::DatasetInfo& di = std::get<0>(tuple);
|
||||
arma::mat& m = std::get<1>(tuple);
|
||||
@@ -218,7 +218,7 @@ void BINDING_FUNCTION(util::Params& params, util::Timers& /* timer */)
|
||||
}
|
||||
}
|
||||
|
||||
params.Get<arma::mat>("matrix_and_info_out") = move(m);
|
||||
params.Get<arma::mat>("matrix_and_info_out") = std::move(m);
|
||||
}
|
||||
|
||||
// If we got a request to build a model, then build it.
|
||||
|
||||
@@ -3,6 +3,11 @@
|
||||
* @author Ryan Curtin
|
||||
*
|
||||
* This is a template file to call the PrintJL() function for a given binding.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#define BINDING_TYPE BINDING_TYPE_JL
|
||||
// Disable debug output.
|
||||
|
||||
@@ -4,6 +4,11 @@
|
||||
*
|
||||
* Some utility functions in C that can be called from Julia with ccall() in
|
||||
* order to interact with the IO interface.
|
||||
*
|
||||
* 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_BINDINGS_JULIA_JULIA_UTIL_H
|
||||
#define MLPACK_BINDINGS_JULIA_JULIA_UTIL_H
|
||||
|
||||
@@ -2,6 +2,12 @@
|
||||
# @author Ryan Curtin
|
||||
#
|
||||
# Tests for the Julia bindings.
|
||||
|
||||
# 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.
|
||||
|
||||
using Pkg
|
||||
Pkg.activate(".")
|
||||
using Test
|
||||
|
||||
@@ -119,11 +119,11 @@ void BINDING_FUNCTION(util::Params& params, util::Timers& /* timers */)
|
||||
// the 3rd row will be multiplied by two.
|
||||
if (params.Has("matrix_in"))
|
||||
{
|
||||
arma::mat out = move(params.Get<arma::mat>("matrix_in"));
|
||||
arma::mat out = std::move(params.Get<arma::mat>("matrix_in"));
|
||||
out.shed_row(4);
|
||||
out.row(2) *= 2.0;
|
||||
|
||||
params.Get<arma::mat>("matrix_out") = move(out);
|
||||
params.Get<arma::mat>("matrix_out") = std::move(out);
|
||||
}
|
||||
|
||||
// Input matrices should be at least 5 rows; the 5th row will be dropped and
|
||||
@@ -131,70 +131,70 @@ void BINDING_FUNCTION(util::Params& params, util::Timers& /* timers */)
|
||||
if (params.Has("umatrix_in"))
|
||||
{
|
||||
arma::Mat<size_t> out =
|
||||
move(params.Get<arma::Mat<size_t>>("umatrix_in"));
|
||||
std::move(params.Get<arma::Mat<size_t>>("umatrix_in"));
|
||||
out.shed_row(4);
|
||||
out.row(2) *= 2;
|
||||
|
||||
params.Get<arma::Mat<size_t>>("umatrix_out") = move(out);
|
||||
params.Get<arma::Mat<size_t>>("umatrix_out") = std::move(out);
|
||||
}
|
||||
|
||||
// An input column or row should have all elements multiplied by two.
|
||||
if (params.Has("col_in"))
|
||||
{
|
||||
arma::vec out = move(params.Get<arma::vec>("col_in"));
|
||||
arma::vec out = std::move(params.Get<arma::vec>("col_in"));
|
||||
out *= 2.0;
|
||||
|
||||
params.Get<arma::vec>("col_out") = move(out);
|
||||
params.Get<arma::vec>("col_out") = std::move(out);
|
||||
}
|
||||
|
||||
if (params.Has("ucol_in"))
|
||||
{
|
||||
arma::Col<size_t> out =
|
||||
move(params.Get<arma::Col<size_t>>("ucol_in"));
|
||||
std::move(params.Get<arma::Col<size_t>>("ucol_in"));
|
||||
out *= 2;
|
||||
|
||||
params.Get<arma::Col<size_t>>("ucol_out") = move(out);
|
||||
params.Get<arma::Col<size_t>>("ucol_out") = std::move(out);
|
||||
}
|
||||
|
||||
if (params.Has("row_in"))
|
||||
{
|
||||
arma::rowvec out = move(params.Get<arma::rowvec>("row_in"));
|
||||
arma::rowvec out = std::move(params.Get<arma::rowvec>("row_in"));
|
||||
out *= 2.0;
|
||||
|
||||
params.Get<arma::rowvec>("row_out") = move(out);
|
||||
params.Get<arma::rowvec>("row_out") = std::move(out);
|
||||
}
|
||||
|
||||
if (params.Has("urow_in"))
|
||||
{
|
||||
arma::Row<size_t> out =
|
||||
move(params.Get<arma::Row<size_t>>("urow_in"));
|
||||
std::move(params.Get<arma::Row<size_t>>("urow_in"));
|
||||
out *= 2;
|
||||
|
||||
params.Get<arma::Row<size_t>>("urow_out") = move(out);
|
||||
params.Get<arma::Row<size_t>>("urow_out") = std::move(out);
|
||||
}
|
||||
|
||||
// Vector arguments should have the last element removed.
|
||||
if (params.Has("vector_in"))
|
||||
{
|
||||
vector<int> out = move(params.Get<vector<int>>("vector_in"));
|
||||
vector<int> out = std::move(params.Get<vector<int>>("vector_in"));
|
||||
out.pop_back();
|
||||
|
||||
params.Get<vector<int>>("vector_out") = move(out);
|
||||
params.Get<vector<int>>("vector_out") = std::move(out);
|
||||
}
|
||||
|
||||
if (params.Has("str_vector_in"))
|
||||
{
|
||||
vector<string> out = move(params.Get<vector<string>>("str_vector_in"));
|
||||
vector<string> out = std::move(params.Get<vector<string>>("str_vector_in"));
|
||||
out.pop_back();
|
||||
|
||||
params.Get<vector<string>>("str_vector_out") = move(out);
|
||||
params.Get<vector<string>>("str_vector_out") = std::move(out);
|
||||
}
|
||||
|
||||
// All numeric elements should be multiplied by 3.
|
||||
if (params.Has("matrix_and_info_in"))
|
||||
{
|
||||
typedef tuple<data::DatasetInfo, arma::mat> TupleType;
|
||||
TupleType tuple = move(params.Get<TupleType>("matrix_and_info_in"));
|
||||
TupleType tuple = std::move(params.Get<TupleType>("matrix_and_info_in"));
|
||||
|
||||
const data::DatasetInfo& di = std::get<0>(tuple);
|
||||
arma::mat& m = std::get<1>(tuple);
|
||||
@@ -224,7 +224,7 @@ void BINDING_FUNCTION(util::Params& params, util::Timers& /* timers */)
|
||||
}
|
||||
}
|
||||
|
||||
params.Get<arma::mat>("matrix_and_info_out") = move(m);
|
||||
params.Get<arma::mat>("matrix_and_info_out") = std::move(m);
|
||||
}
|
||||
|
||||
// If we got a request to build a model, then build it.
|
||||
|
||||
@@ -4,6 +4,11 @@
|
||||
*
|
||||
* This file is configured by CMake to generate all of the Markdown required by
|
||||
* the project.
|
||||
*
|
||||
* mlpack is free software; you may redistribute it and/or modify it under the
|
||||
* terms of the 3-clause BSD license. You should have received a copy of the
|
||||
* 3-clause BSD license along with mlpack. If not, see
|
||||
* http://www.opensource.org/licenses/BSD-3-Clause for more information.
|
||||
*/
|
||||
#include <mlpack/core.hpp>
|
||||
#include "binding_info.hpp"
|
||||
|
||||
@@ -4,6 +4,11 @@ serialization.pxd: serialization functions for mlpack classes.
|
||||
|
||||
This simply makes the utility serialization functions from serialization.hpp
|
||||
available from Python.
|
||||
|
||||
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.
|
||||
"""
|
||||
cimport cython
|
||||
|
||||
|
||||
@@ -140,11 +140,11 @@ void BINDING_FUNCTION(util::Params& params, util::Timers& /* timer */)
|
||||
// the 3rd row will be multiplied by two.
|
||||
if (params.Has("matrix_in"))
|
||||
{
|
||||
arma::mat out = move(params.Get<arma::mat>("matrix_in"));
|
||||
arma::mat out = std::move(params.Get<arma::mat>("matrix_in"));
|
||||
out.shed_row(4);
|
||||
out.row(2) *= 2.0;
|
||||
|
||||
params.Get<arma::mat>("matrix_out") = move(out);
|
||||
params.Get<arma::mat>("matrix_out") = std::move(out);
|
||||
}
|
||||
|
||||
// Input matrices should be at least 5 rows; the 5th row will be dropped and
|
||||
@@ -152,89 +152,89 @@ void BINDING_FUNCTION(util::Params& params, util::Timers& /* timer */)
|
||||
if (params.Has("umatrix_in"))
|
||||
{
|
||||
arma::Mat<size_t> out =
|
||||
move(params.Get<arma::Mat<size_t>>("umatrix_in"));
|
||||
std::move(params.Get<arma::Mat<size_t>>("umatrix_in"));
|
||||
out.shed_row(4);
|
||||
out.row(2) *= 2;
|
||||
|
||||
params.Get<arma::Mat<size_t>>("umatrix_out") = move(out);
|
||||
params.Get<arma::Mat<size_t>>("umatrix_out") = std::move(out);
|
||||
}
|
||||
|
||||
// An input matrix (pandas.Series) should have all elements multiplied by two.
|
||||
if (params.Has("smatrix_in"))
|
||||
{
|
||||
arma::mat out = move(params.Get<arma::mat>("smatrix_in"));
|
||||
arma::mat out = std::move(params.Get<arma::mat>("smatrix_in"));
|
||||
out *= 2.0;
|
||||
|
||||
params.Get<arma::mat>("smatrix_out") = move(out);
|
||||
params.Get<arma::mat>("smatrix_out") = std::move(out);
|
||||
}
|
||||
|
||||
// An input matrix (pandas.Series) should have all elements multiplied by two.
|
||||
if (params.Has("s_umatrix_in"))
|
||||
{
|
||||
arma::Mat<size_t> out =
|
||||
move(params.Get<arma::Mat<size_t>>("s_umatrix_in"));
|
||||
std::move(params.Get<arma::Mat<size_t>>("s_umatrix_in"));
|
||||
out *= 2;
|
||||
|
||||
params.Get<arma::Mat<size_t>>("s_umatrix_out") = move(out);
|
||||
params.Get<arma::Mat<size_t>>("s_umatrix_out") = std::move(out);
|
||||
}
|
||||
|
||||
// An input column or row should have all elements multiplied by two.
|
||||
if (params.Has("col_in"))
|
||||
{
|
||||
arma::vec out = move(params.Get<arma::vec>("col_in"));
|
||||
arma::vec out = std::move(params.Get<arma::vec>("col_in"));
|
||||
out *= 2.0;
|
||||
|
||||
params.Get<arma::vec>("col_out") = move(out);
|
||||
params.Get<arma::vec>("col_out") = std::move(out);
|
||||
}
|
||||
|
||||
if (params.Has("ucol_in"))
|
||||
{
|
||||
arma::Col<size_t> out =
|
||||
move(params.Get<arma::Col<size_t>>("ucol_in"));
|
||||
std::move(params.Get<arma::Col<size_t>>("ucol_in"));
|
||||
out *= 2;
|
||||
|
||||
params.Get<arma::Col<size_t>>("ucol_out") = move(out);
|
||||
params.Get<arma::Col<size_t>>("ucol_out") = std::move(out);
|
||||
}
|
||||
|
||||
if (params.Has("row_in"))
|
||||
{
|
||||
arma::rowvec out = move(params.Get<arma::rowvec>("row_in"));
|
||||
arma::rowvec out = std::move(params.Get<arma::rowvec>("row_in"));
|
||||
out *= 2.0;
|
||||
|
||||
params.Get<arma::rowvec>("row_out") = move(out);
|
||||
params.Get<arma::rowvec>("row_out") = std::move(out);
|
||||
}
|
||||
|
||||
if (params.Has("urow_in"))
|
||||
{
|
||||
arma::Row<size_t> out =
|
||||
move(params.Get<arma::Row<size_t>>("urow_in"));
|
||||
std::move(params.Get<arma::Row<size_t>>("urow_in"));
|
||||
out *= 2;
|
||||
|
||||
params.Get<arma::Row<size_t>>("urow_out") = move(out);
|
||||
params.Get<arma::Row<size_t>>("urow_out") = std::move(out);
|
||||
}
|
||||
|
||||
// Vector arguments should have the last element removed.
|
||||
if (params.Has("vector_in"))
|
||||
{
|
||||
vector<int> out = move(params.Get<vector<int>>("vector_in"));
|
||||
vector<int> out = std::move(params.Get<vector<int>>("vector_in"));
|
||||
out.pop_back();
|
||||
|
||||
params.Get<vector<int>>("vector_out") = move(out);
|
||||
params.Get<vector<int>>("vector_out") = std::move(out);
|
||||
}
|
||||
|
||||
if (params.Has("str_vector_in"))
|
||||
{
|
||||
vector<string> out = move(params.Get<vector<string>>("str_vector_in"));
|
||||
vector<string> out = std::move(params.Get<vector<string>>("str_vector_in"));
|
||||
out.pop_back();
|
||||
|
||||
params.Get<vector<string>>("str_vector_out") = move(out);
|
||||
params.Get<vector<string>>("str_vector_out") = std::move(out);
|
||||
}
|
||||
|
||||
// All numeric elements should be multiplied by 3.
|
||||
if (params.Has("matrix_and_info_in"))
|
||||
{
|
||||
typedef tuple<data::DatasetInfo, arma::mat> TupleType;
|
||||
TupleType tuple = move(params.Get<TupleType>("matrix_and_info_in"));
|
||||
TupleType tuple = std::move(params.Get<TupleType>("matrix_and_info_in"));
|
||||
|
||||
const data::DatasetInfo& di = std::get<0>(tuple);
|
||||
arma::mat& m = std::get<1>(tuple);
|
||||
@@ -260,7 +260,7 @@ void BINDING_FUNCTION(util::Params& params, util::Timers& /* timer */)
|
||||
}
|
||||
}
|
||||
|
||||
params.Get<arma::mat>("matrix_and_info_out") = move(m);
|
||||
params.Get<arma::mat>("matrix_and_info_out") = std::move(m);
|
||||
}
|
||||
|
||||
// If we got a request to build a model, then build it.
|
||||
|
||||
@@ -61,9 +61,4 @@
|
||||
#include <omp.h>
|
||||
#endif
|
||||
|
||||
// Use Armadillo's C++ version detection.
|
||||
#ifdef ARMA_USE_CXX11
|
||||
#define MLPACK_USE_CX11
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -14,8 +14,31 @@
|
||||
|
||||
#include "load_csv.hpp"
|
||||
|
||||
namespace mlpack{
|
||||
namespace data{
|
||||
namespace mlpack {
|
||||
namespace data {
|
||||
|
||||
/**
|
||||
* A safe function to get negative or positive infinity, which avoids unary
|
||||
* minus on an unsigned type. This works around a Visual Studio warning.
|
||||
*/
|
||||
template<typename eT>
|
||||
inline eT SafeNegInf(
|
||||
const bool neg,
|
||||
const typename std::enable_if<std::is_unsigned<eT>::value>::type* = 0)
|
||||
{
|
||||
// For an unsigned type, we cannot return negative infinity, so instead return
|
||||
// 0.
|
||||
return neg ? 0 : std::numeric_limits<eT>::infinity();
|
||||
}
|
||||
|
||||
template<typename eT>
|
||||
inline eT SafeNegInf(
|
||||
const bool neg,
|
||||
const typename std::enable_if<!std::is_unsigned<eT>::value>::type* = 0)
|
||||
{
|
||||
return neg ? -(std::numeric_limits<eT>::infinity()) :
|
||||
std::numeric_limits<eT>::infinity();
|
||||
}
|
||||
|
||||
template<typename eT>
|
||||
bool LoadCSV::ConvertToken(eT& val,
|
||||
@@ -49,8 +72,7 @@ bool LoadCSV::ConvertToken(eT& val,
|
||||
((sigB == 'n') || (sigB == 'N')) &&
|
||||
((sigC == 'f') || (sigC == 'F')))
|
||||
{
|
||||
val = neg ? -(std::numeric_limits<eT>
|
||||
::infinity()) : std::numeric_limits<eT>::infinity();
|
||||
val = SafeNegInf<eT>(neg);
|
||||
return true;
|
||||
}
|
||||
else if (((sigA == 'n') || (sigA == 'N')) &&
|
||||
|
||||
@@ -30,10 +30,6 @@ namespace mlpack {
|
||||
* observation is passed (i.e. observation > numObservations), a crash will
|
||||
* probably occur.
|
||||
*
|
||||
* This distribution only supports one-dimensional observations, so when
|
||||
* passing an arma::vec as an observation, it should only have one dimension
|
||||
* (vec.n_rows == 1). Any additional dimensions will simply be ignored.
|
||||
*
|
||||
* @note
|
||||
* This class, like every other class in mlpack, uses arma::vec to represent
|
||||
* observations. While a discrete distribution only has positive integers
|
||||
|
||||
@@ -384,8 +384,8 @@ void ConvolutionType<
|
||||
(padWLeft != 0 || padWRight != 0 || padHTop != 0 || padHBottom != 0);
|
||||
|
||||
// To perform the backward pass, we need to rotate all the filters.
|
||||
arma::Cube<typename MatType::elem_type> rotatedFilters(weight.n_cols,
|
||||
weight.n_rows, weight.n_slices);
|
||||
arma::Cube<typename MatType::elem_type> rotatedFilters(weight.n_rows,
|
||||
weight.n_cols, weight.n_slices);
|
||||
|
||||
// To perform the backward pass, we need to dilate all the mappedError.
|
||||
arma::Cube<typename MatType::elem_type> dilatedMappedError;
|
||||
|
||||
@@ -402,8 +402,8 @@ void GroupedConvolutionType<
|
||||
(padWLeft != 0 || padWRight != 0 || padHTop != 0 || padHBottom != 0);
|
||||
|
||||
// To perform the backward pass, we need to rotate all the filters.
|
||||
arma::Cube<typename MatType::elem_type> rotatedFilters(weight.n_cols,
|
||||
weight.n_rows, weight.n_slices);
|
||||
arma::Cube<typename MatType::elem_type> rotatedFilters(weight.n_rows,
|
||||
weight.n_cols, weight.n_slices);
|
||||
|
||||
#pragma omp parallel for
|
||||
for (size_t map = 0; map < ((maps * inMaps) / groups); ++map)
|
||||
|
||||
@@ -154,18 +154,68 @@ void DBSCAN<RangeSearchType, PointSelectionPolicy>::PointwiseCluster(
|
||||
std::vector<std::vector<size_t>> neighbors;
|
||||
std::vector<std::vector<double>> distances;
|
||||
|
||||
// Note that the strategy here is somewhat different from the original DBSCAN
|
||||
// paper. The original DBSCAN paper grows each cluster individually to its
|
||||
// fullest extent; here, we use a UnionFind structure to grow each point into
|
||||
// a local cluster (if it has enough points), and we combine with other local
|
||||
// clusters. The end result is the same.
|
||||
//
|
||||
// Define points as being either core points, or non-core points. Core points
|
||||
// have more than `minPoints` neighbors. Non-core points are included into
|
||||
// the first core point cluster that encounters them; if they are not included
|
||||
// by anything, they are labeled as noise.
|
||||
//
|
||||
// We maintain a list of non-core points so that we can handle that logic
|
||||
// correctly.
|
||||
|
||||
std::vector<bool> visited(data.n_cols, false);
|
||||
std::vector<bool> nonCorePoints(data.n_cols, false);
|
||||
|
||||
for (size_t i = 0; i < data.n_cols; ++i)
|
||||
{
|
||||
if (i % 10000 == 0 && i > 0)
|
||||
Log::Info << "DBSCAN clustering on point " << i << "..." << std::endl;
|
||||
|
||||
// Get the next index.
|
||||
const size_t index = pointSelector.Select(i, data);
|
||||
visited[index] = true;
|
||||
|
||||
// Do the range search for only this point.
|
||||
rangeSearch.Search(data.col(i), Range(0.0, epsilon), neighbors,
|
||||
rangeSearch.Search(data.col(index), Range(0.0, epsilon), neighbors,
|
||||
distances);
|
||||
|
||||
// Union to all neighbors.
|
||||
for (size_t j = 0; j < neighbors[0].size(); ++j)
|
||||
uf.Union(i, neighbors[0][j]);
|
||||
// Union to all neighbors if the point is not noise.
|
||||
//
|
||||
// If the point is noise, we leave its label as undefined (i.e. we do no
|
||||
// unioning).
|
||||
if (neighbors[0].size() >= minPoints)
|
||||
{
|
||||
for (size_t j = 0; j < neighbors[0].size(); ++j)
|
||||
{
|
||||
// Union to all neighbors that either do not have a label, or are core
|
||||
// points of other clusters. (When we union to another core point, we
|
||||
// are merging clusters.)
|
||||
if (uf.Find(neighbors[0][j]) == neighbors[0][j])
|
||||
{
|
||||
// This unions unlabeled points.
|
||||
uf.Union(index, neighbors[0][j]);
|
||||
}
|
||||
else if (!nonCorePoints[neighbors[0][j]] && visited[neighbors[0][j]])
|
||||
{
|
||||
// This unions core points of other clusters. Note that we only union
|
||||
// with other clusters that have already been visited---this is
|
||||
// because we do not know whether unvisited points are core or
|
||||
// non-core points. (If an unvisited point is a core point, it'll
|
||||
// merge with us later.)
|
||||
uf.Union(index, neighbors[0][j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// This is not a core point---it does not have enough neighbors.
|
||||
nonCorePoints[index] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -180,21 +230,43 @@ void DBSCAN<RangeSearchType, PointSelectionPolicy>::BatchCluster(
|
||||
const MatType& data,
|
||||
UnionFind& uf)
|
||||
{
|
||||
// For each point, find the points in epsilon-nighborhood and their distances.
|
||||
// For each point, find the points in epsilon-neighborhood and their distances.
|
||||
std::vector<std::vector<size_t>> neighbors;
|
||||
std::vector<std::vector<double>> distances;
|
||||
Log::Info << "Performing range search." << std::endl;
|
||||
rangeSearch.Train(data);
|
||||
rangeSearch.Search(data, Range(0.0, epsilon), neighbors, distances);
|
||||
rangeSearch.Search(Range(0.0, epsilon), neighbors, distances);
|
||||
Log::Info << "Range search complete." << std::endl;
|
||||
|
||||
// See the description of the algorithm in `PointwiseCluster()`. The strategy
|
||||
// is the same here, but we have cached all range search results already.
|
||||
// That means we already have computed whether each point is or is not a core
|
||||
// point, just based on the size of its neighbors; so we don't need an
|
||||
// auxiliary std::vector<bool> for that.
|
||||
|
||||
// Now loop over all points.
|
||||
for (size_t i = 0; i < data.n_cols; ++i)
|
||||
{
|
||||
// Get the next index.
|
||||
const size_t index = pointSelector.Select(i, data);
|
||||
for (size_t j = 0; j < neighbors[index].size(); ++j)
|
||||
uf.Union(index, neighbors[index][j]);
|
||||
// Monochromatic dual-tree range search does not return the point as its own
|
||||
// neighbor, so we are looking for `minPoints - 1` instead.
|
||||
if (neighbors[index].size() >= minPoints - 1)
|
||||
{
|
||||
for (size_t j = 0; j < neighbors[index].size(); ++j)
|
||||
{
|
||||
if (uf.Find(neighbors[index][j]) == neighbors[index][j])
|
||||
{
|
||||
// This unions unlabeled points.
|
||||
uf.Union(index, neighbors[index][j]);
|
||||
}
|
||||
else if (neighbors[neighbors[index][j]].size() >= (minPoints - 1))
|
||||
{
|
||||
// This unions core points of other clusters.
|
||||
uf.Union(index, neighbors[index][j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -88,7 +88,10 @@ class HMM
|
||||
* the given default distribution for emissions. The dimensionality of the
|
||||
* observations is taken from the emissions variable, so it is important that
|
||||
* the given default emission distribution is set with the correct
|
||||
* dimensionality. Alternately, set the dimensionality with Dimensionality().
|
||||
* dimensionality. Alternately, set the dimensionality with Dimensionality(),
|
||||
* and then use Emission() to access and set the dimensionality of each
|
||||
* individual distribution correctly.
|
||||
*
|
||||
* Optionally, the tolerance for convergence of the Baum-Welch algorithm can
|
||||
* be set.
|
||||
*
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
/**
|
||||
* @file methods/preprocess/preprocess.hpp
|
||||
* @author Ryan Curtin
|
||||
*
|
||||
* Convenience include for preprocessing utilities.
|
||||
*
|
||||
* 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_PREPROCESSING_PREPROCESSING_HPP
|
||||
#define MLPACK_METHODS_PREPROCESSING_PREPROCESSING_HPP
|
||||
|
||||
#include "scaling_model.hpp"
|
||||
|
||||
#endif
|
||||
@@ -19,9 +19,9 @@
|
||||
namespace mlpack {
|
||||
namespace data {
|
||||
|
||||
ScalingModel::ScalingModel(const int minvalue,
|
||||
const int maxvalue,
|
||||
double epsilonvalue) :
|
||||
inline ScalingModel::ScalingModel(const int minvalue,
|
||||
const int maxvalue,
|
||||
double epsilonvalue) :
|
||||
scalerType(0),
|
||||
minmaxscale(NULL),
|
||||
maxabsscale(NULL),
|
||||
@@ -37,7 +37,7 @@ ScalingModel::ScalingModel(const int minvalue,
|
||||
}
|
||||
|
||||
//! Copy constructor.
|
||||
ScalingModel::ScalingModel(const ScalingModel& other) :
|
||||
inline ScalingModel::ScalingModel(const ScalingModel& other) :
|
||||
scalerType(other.scalerType),
|
||||
minmaxscale(other.minmaxscale == NULL ? NULL :
|
||||
new data::MinMaxScaler(*other.minmaxscale)),
|
||||
@@ -59,7 +59,7 @@ ScalingModel::ScalingModel(const ScalingModel& other) :
|
||||
}
|
||||
|
||||
//! Move constructor.
|
||||
ScalingModel::ScalingModel(ScalingModel&& other) :
|
||||
inline ScalingModel::ScalingModel(ScalingModel&& other) :
|
||||
scalerType(other.scalerType),
|
||||
minmaxscale(other.minmaxscale),
|
||||
maxabsscale(other.maxabsscale),
|
||||
@@ -84,7 +84,7 @@ ScalingModel::ScalingModel(ScalingModel&& other) :
|
||||
}
|
||||
|
||||
//! Copy assignment operator.
|
||||
ScalingModel& ScalingModel::operator=(const ScalingModel& other)
|
||||
inline ScalingModel& ScalingModel::operator=(const ScalingModel& other)
|
||||
{
|
||||
if (this == &other)
|
||||
{
|
||||
@@ -124,7 +124,7 @@ ScalingModel& ScalingModel::operator=(const ScalingModel& other)
|
||||
}
|
||||
|
||||
//! Move assignment operator.
|
||||
ScalingModel& ScalingModel::operator=(ScalingModel&& other)
|
||||
inline ScalingModel& ScalingModel::operator=(ScalingModel&& other)
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
@@ -153,7 +153,7 @@ ScalingModel& ScalingModel::operator=(ScalingModel&& other)
|
||||
return *this;
|
||||
}
|
||||
|
||||
ScalingModel::~ScalingModel()
|
||||
inline ScalingModel::~ScalingModel()
|
||||
{
|
||||
delete minmaxscale;
|
||||
delete maxabsscale;
|
||||
|
||||
@@ -441,3 +441,23 @@ TEST_CASE("AdvancedConvolutionLayerWithStrideTest", "[ANNLayerTest]")
|
||||
layer.Backward(input, output, delta);
|
||||
REQUIRE(arma::accu(delta) == Approx(115.3515701294).epsilon(1e-5));
|
||||
}
|
||||
|
||||
// Make a simple convolutional layer with non-square filters, and make sure the
|
||||
// forward and backward and gradient passes all return a result. (This checks
|
||||
// that we don't have any shape errors.)
|
||||
TEST_CASE("NonSquareConvolutionTest", "[ANNLayerTest]")
|
||||
{
|
||||
Convolution module1(1, 5, 3);
|
||||
module1.InputDimensions() = std::vector<size_t>({ 7, 7 });
|
||||
module1.ComputeOutputDimensions();
|
||||
arma::mat weights1(module1.WeightSize(), 1);
|
||||
module1.SetWeights(weights1.memptr());
|
||||
|
||||
arma::mat data(49, 10, arma::fill::randu);
|
||||
arma::mat forwardResult(module1.OutputSize(), 10, arma::fill::zeros);
|
||||
REQUIRE_NOTHROW(module1.Forward(data, forwardResult));
|
||||
arma::mat backwardResult(49, 10);
|
||||
REQUIRE_NOTHROW(module1.Backward(data, forwardResult, backwardResult));
|
||||
arma::mat gradientResult(module1.WeightSize(), 1);
|
||||
REQUIRE_NOTHROW(module1.Gradient(data, backwardResult, gradientResult));
|
||||
}
|
||||
|
||||
@@ -202,3 +202,23 @@ TEST_CASE("GradientGroupedConvolutionLayerTest", "[ANNLayerTest]")
|
||||
|
||||
REQUIRE(CheckGradient(function) < 1e-1);
|
||||
}
|
||||
|
||||
// Make a simple grouped convolutional layer with non-square filters, and make
|
||||
// sure the forward and backward and gradient passes all return a result. (This
|
||||
// checks that we don't have any shape errors.)
|
||||
TEST_CASE("NonSquareGroupedConvolutionTest", "[ANNLayerTest]")
|
||||
{
|
||||
GroupedConvolution module1(1, 5, 3, 1);
|
||||
module1.InputDimensions() = std::vector<size_t>({ 7, 7 });
|
||||
module1.ComputeOutputDimensions();
|
||||
arma::mat weights1(module1.WeightSize(), 1);
|
||||
module1.SetWeights(weights1.memptr());
|
||||
|
||||
arma::mat data(49, 10, arma::fill::randu);
|
||||
arma::mat forwardResult(module1.OutputSize(), 10, arma::fill::zeros);
|
||||
REQUIRE_NOTHROW(module1.Forward(data, forwardResult));
|
||||
arma::mat backwardResult(49, 10);
|
||||
REQUIRE_NOTHROW(module1.Backward(data, forwardResult, backwardResult));
|
||||
arma::mat gradientResult(module1.WeightSize(), 1);
|
||||
REQUIRE_NOTHROW(module1.Gradient(data, backwardResult, gradientResult));
|
||||
}
|
||||
|
||||
@@ -302,3 +302,36 @@ TEST_CASE("RandomPointSelectionTest", "[DBSCANTest]")
|
||||
// The number of assignments returned should be the same as points.
|
||||
REQUIRE(assignments.n_elem == points.n_cols);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that noise points do not accidentally connect clusters.
|
||||
* See issue #3339. (Thanks @iad-ABDUL-RAOUF!)
|
||||
*/
|
||||
TEST_CASE("NoiseConnectionTest", "[DBSCANTest]")
|
||||
{
|
||||
arma::mat dataset({
|
||||
// cluster 1 cluster 2 noise
|
||||
{ 0.0, 0.5, 0.5, 1.0, 3.0, 3.5, 3.5, 4.0, 2.0 },
|
||||
{ 0.0, 0.5, -0.5, 0.0, 0.0, 0.5, -0.5, 0.0, 0.0 }});
|
||||
|
||||
// Now perform clustering.
|
||||
const double epsilon = 1.1;
|
||||
size_t minPts = 4;
|
||||
|
||||
DBSCAN<> dbscan(epsilon, minPts, false);
|
||||
|
||||
arma::Row<size_t> labels;
|
||||
arma::mat centroids;
|
||||
|
||||
size_t numClusters = dbscan.Cluster(dataset, labels, centroids);
|
||||
|
||||
// The noisy element should not link the two clusters together, since it has
|
||||
// less than minPts neighbors.
|
||||
REQUIRE(numClusters == 2);
|
||||
|
||||
// Now make sure the same is true with batch clustering.
|
||||
dbscan = DBSCAN<>(epsilon, minPts, true);
|
||||
numClusters = dbscan.Cluster(dataset, labels, centroids);
|
||||
|
||||
REQUIRE(numClusters == 2);
|
||||
}
|
||||
|
||||
@@ -1100,8 +1100,8 @@ TEST_CASE("MatrixAndDatasetInfoTest", "[IOTest]")
|
||||
"MatrixAndDatasetInfoTest");
|
||||
|
||||
// Get the dataset and info.
|
||||
DatasetInfo info = move(get<0>(p.Get<TupleType>("dataset")));
|
||||
arma::mat dataset = move(get<1>(p.Get<TupleType>("dataset")));
|
||||
DatasetInfo info = std::move(get<0>(p.Get<TupleType>("dataset")));
|
||||
arma::mat dataset = std::move(get<1>(p.Get<TupleType>("dataset")));
|
||||
|
||||
REQUIRE(info.Dimensionality() == 3);
|
||||
|
||||
|
||||
@@ -86,7 +86,7 @@ TEST_CASE_METHOD(DETTestFixture, "DETParamBoundTest",
|
||||
|
||||
// Test for folds.
|
||||
|
||||
SetInputParam("training", move(trainingData));
|
||||
SetInputParam("training", std::move(trainingData));
|
||||
SetInputParam("folds", (int) -1);
|
||||
|
||||
REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error);
|
||||
|
||||
@@ -57,7 +57,7 @@ TEST_CASE_METHOD(RangeSearchTestFixture, "RangeSearchInputModelNoQuery",
|
||||
if (!data::Load("iris.csv", inputData))
|
||||
FAIL("Unable to load dataset iris.csv!");
|
||||
|
||||
SetInputParam("reference", move(inputData));
|
||||
SetInputParam("reference", std::move(inputData));
|
||||
SetInputParam("min", minVal);
|
||||
SetInputParam("max", maxVal);
|
||||
SetInputParam("distances_file", distanceFile);
|
||||
@@ -96,7 +96,7 @@ TEST_CASE_METHOD(RangeSearchTestFixture, "RangeSearchDifferentTree",
|
||||
if (!data::Load("iris.csv", inputData))
|
||||
FAIL("Unable to load dataset iris.csv!");
|
||||
|
||||
SetInputParam("reference", move(inputData));
|
||||
SetInputParam("reference", std::move(inputData));
|
||||
SetInputParam("min", minVal);
|
||||
SetInputParam("max", maxVal);
|
||||
SetInputParam("distances_file", distanceFile);
|
||||
@@ -125,7 +125,7 @@ TEST_CASE_METHOD(RangeSearchTestFixture, "RangeSearchBothReferenceAndModel",
|
||||
if (!data::Load("iris_test.csv", queryData))
|
||||
FAIL("Unable to load dataset iris_test.csv!");
|
||||
|
||||
SetInputParam("reference", move(inputData));
|
||||
SetInputParam("reference", std::move(inputData));
|
||||
SetInputParam("min", minVal);
|
||||
SetInputParam("max", maxVal);
|
||||
SetInputParam("distances_file", distanceFile);
|
||||
@@ -134,8 +134,8 @@ TEST_CASE_METHOD(RangeSearchTestFixture, "RangeSearchBothReferenceAndModel",
|
||||
|
||||
RUN_BINDING();
|
||||
|
||||
SetInputParam("input_model", move(params.Get<RSModel*>("output_model")));
|
||||
SetInputParam("query", move(queryData));
|
||||
SetInputParam("input_model", std::move(params.Get<RSModel*>("output_model")));
|
||||
SetInputParam("query", std::move(queryData));
|
||||
|
||||
REQUIRE_THROWS_AS(RUN_BINDING(), std::runtime_error);
|
||||
|
||||
@@ -174,7 +174,7 @@ TEST_CASE_METHOD(RangeSearchTestFixture, "RangeSearchTest",
|
||||
vector<vector<size_t>> neighbors;
|
||||
vector<vector<double>> distances;
|
||||
|
||||
SetInputParam("reference", move(x));
|
||||
SetInputParam("reference", std::move(x));
|
||||
SetInputParam("min", minVal);
|
||||
SetInputParam("max", maxVal);
|
||||
SetInputParam("distances_file", distanceFile);
|
||||
@@ -219,7 +219,7 @@ TEST_CASE_METHOD(RangeSearchTestFixture, "RangeSeachTestwithQuery",
|
||||
double minVal = 0, maxVal = 5;
|
||||
|
||||
SetInputParam("query", queryData);
|
||||
SetInputParam("reference", move(x));
|
||||
SetInputParam("reference", std::move(x));
|
||||
SetInputParam("min", minVal);
|
||||
SetInputParam("max", maxVal);
|
||||
SetInputParam("distances_file", distanceFile);
|
||||
@@ -256,7 +256,7 @@ TEST_CASE_METHOD(RangeSearchTestFixture, "ModelCheck",
|
||||
if (!data::Load("iris_test.csv", queryData))
|
||||
FAIL("Unable to load dataset iris_test.csv!");
|
||||
|
||||
SetInputParam("reference", move(inputData));
|
||||
SetInputParam("reference", std::move(inputData));
|
||||
SetInputParam("min", minVal);
|
||||
SetInputParam("max", maxVal);
|
||||
SetInputParam("distances_file", distanceFile);
|
||||
@@ -275,7 +275,7 @@ TEST_CASE_METHOD(RangeSearchTestFixture, "ModelCheck",
|
||||
ResetSettings();
|
||||
|
||||
SetInputParam("input_model", outputModel);
|
||||
SetInputParam("query", move(queryData));
|
||||
SetInputParam("query", std::move(queryData));
|
||||
|
||||
RUN_BINDING();
|
||||
|
||||
@@ -455,7 +455,7 @@ TEST_CASE_METHOD(RangeSearchTestFixture, "RandomBasisTesting",
|
||||
|
||||
RUN_BINDING();
|
||||
|
||||
RSModel* outputModel = move(params.Get<RSModel*>("output_model"));
|
||||
RSModel* outputModel = std::move(params.Get<RSModel*>("output_model"));
|
||||
|
||||
SetInputParam("min", minVal);
|
||||
SetInputParam("max", maxVal);
|
||||
@@ -504,7 +504,7 @@ TEST_CASE_METHOD(RangeSearchTestFixture, "NaiveModeTest",
|
||||
|
||||
neighbors = ReadData<size_t>(neighborsFile);
|
||||
distances = ReadData<double>(distanceFile);
|
||||
RSModel* outputModel = move(params.Get<RSModel*>("output_model"));
|
||||
RSModel* outputModel = std::move(params.Get<RSModel*>("output_model"));
|
||||
|
||||
SetInputParam("min", minVal);
|
||||
SetInputParam("max", maxVal);
|
||||
@@ -559,7 +559,7 @@ TEST_CASE_METHOD(RangeSearchTestFixture, "SingleModeTest",
|
||||
|
||||
neighbors = ReadData<size_t>(neighborsFile);
|
||||
distances = ReadData<double>(distanceFile);
|
||||
RSModel* outputModel = move(params.Get<RSModel*>("output_model"));
|
||||
RSModel* outputModel = std::move(params.Get<RSModel*>("output_model"));
|
||||
|
||||
SetInputParam("min", minVal);
|
||||
SetInputParam("max", maxVal);
|
||||
|
||||
Reference in New Issue
Block a user