Merge branch 'mlpack:master' into master

This commit is contained in:
Zhengshou Lai
2023-02-07 18:35:37 +08:00
committed by GitHub
50 changed files with 602 additions and 282 deletions
+13 -3
View File
@@ -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')"
+16
View File
@@ -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
View File
@@ -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>
+5
View File
@@ -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
+37 -23
View File
@@ -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) &nbsp;&emsp;>= 9.800
- [ensmallen](https://ensmallen.org) &emsp;>= 2.10.0
- [cereal](http://uscilab.github.io/cereal/) &ensp;&nbsp;&emsp;&emsp;>= 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
+3 -3
View File
@@ -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
+2 -2
View File
@@ -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++
+2 -2
View File
@@ -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)
+3 -3
View File
@@ -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
+5 -5
View File
@@ -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;
+5 -3
View File
@@ -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);
}
```
+6 -6
View File
@@ -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
View File
@@ -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>
+1 -1
View File
@@ -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
+3 -2
View File
@@ -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++
+2 -3
View File
@@ -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);
```
+2 -2
View File
@@ -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
+15 -14
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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).
+4
View File
@@ -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"
+5
View File
@@ -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")
+5
View File
@@ -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.
+1 -1
View File
@@ -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
View File
@@ -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.
+5
View File
@@ -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.
-5
View File
@@ -61,9 +61,4 @@
#include <omp.h>
#endif
// Use Armadillo's C++ version detection.
#ifdef ARMA_USE_CXX11
#define MLPACK_USE_CX11
#endif
#endif
+26 -4
View File
@@ -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)
+80 -8
View File
@@ -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]);
}
}
}
}
}
+4 -1
View File
@@ -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));
}
+33
View File
@@ -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);
}
+2 -2
View File
@@ -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);
+1 -1
View File
@@ -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);