Merge branch 'mlpack:master' into master
This commit is contained in:
+11
@@ -1,11 +1,22 @@
|
||||
### mlpack ?.?.?
|
||||
###### ????-??-??
|
||||
|
||||
* Adapt Softmin layer for new neural network API (#3437).
|
||||
|
||||
* Adapt PReLU layer for new neural network API (#3420).
|
||||
|
||||
* Add CF decomposition methods: `QUIC_SVDPolicy` and `BlockKrylovSVDPolicy` (#3413, #3404).
|
||||
|
||||
* Update outdated code in tutorials (#3398, #3401).
|
||||
|
||||
* Bugfix for non-square convolution kernels (#3376).
|
||||
|
||||
* Fix a few missing includes in `<mlpack.hpp>` (#3374).
|
||||
|
||||
* Fix DBSCAN handling of non-core points (#3346).
|
||||
|
||||
* Avoid deprecation warnings in Armadillo 11.4.4+ (#3405).
|
||||
|
||||
### mlpack 4.0.1
|
||||
###### 2022-12-23
|
||||
* Fix mapping of categorical data for Julia bindings (#3305).
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@ can redistribute the library and/or modify it under the terms of the 3-clause
|
||||
BSD license. The text of the 3-clause BSD license is contained below.
|
||||
|
||||
----
|
||||
Copyright (c) 2007-2022, mlpack contributors (see COPYRIGHT.txt)
|
||||
Copyright (c) 2007-2023, mlpack contributors (see COPYRIGHT.txt)
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use of mlpack in source and binary forms, with or without
|
||||
|
||||
@@ -279,7 +279,7 @@ add_all_bindings(program_dir program_name "category")
|
||||
In this example, this will also add a Markdown binding, which will generate
|
||||
documentation that is typically used to build the website. The `category`
|
||||
parameter should be one of the categories in
|
||||
`src/mlpack/bindings/markdown/MarkdownCategories.cmake`.
|
||||
`src/mlpack/bindings/Categories.cmake`.
|
||||
|
||||
## How to write mlpack bindings
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Alternating Matrix Factorization tutorial
|
||||
|
||||
Alternating matrix factorization decomposes a matrix `V` in the form `V ~ WH`
|
||||
where `W` is called the basis matrix and `H` is called the encoding matrix.. `V`
|
||||
where `W` is called the basis matrix and `H` is called the encoding matrix. `V`
|
||||
is taken to be of size `n x m` and the obtained `W` is `n x r` and `H` is `r x
|
||||
m`. The size `r` is called the *rank* of the factorization. Factorization is
|
||||
done by alternately calculating `W` and `H` respectively while holding the other
|
||||
|
||||
@@ -812,7 +812,7 @@ extern arma::mat dataset;
|
||||
QDAFN<> qdafn(dataset, 10, 5);
|
||||
|
||||
// Print the fifth point of the candidate set.
|
||||
std::cout << ds.CandidateSet(2).col(4).t();
|
||||
std::cout << qdafn.CandidateSet(2).col(4).t();
|
||||
```
|
||||
|
||||
### Retraining on a new reference set
|
||||
@@ -896,7 +896,7 @@ extern arma::mat querySet;
|
||||
|
||||
// Construct the object, performing the default dual-tree search with
|
||||
// approximation level epsilon = 0.05.
|
||||
KFN kfn(dataset, KFN::DUAL_TREE_MODE, 0.05);
|
||||
KFN kfn(dataset, DUAL_TREE_MODE, 0.05);
|
||||
|
||||
// Search for approximate furthest neighbors.
|
||||
arma::Mat<size_t> neighbors;
|
||||
|
||||
+14
-10
@@ -255,7 +255,7 @@ extern size_t rank;
|
||||
// Build the CF object and perform the decomposition.
|
||||
// The constructor takes a default-constructed factorizer, which, by default,
|
||||
// is of type NMFALSFactorizer.
|
||||
CF cf(data, NMFALSFactorizer(), neighborhood, rank);
|
||||
CF cf(data, NMFPolicy(), neighborhood, rank);
|
||||
|
||||
// Store the results in this object.
|
||||
arma::Mat<size_t> recommendations;
|
||||
@@ -270,12 +270,16 @@ mlpack provides a number of existing factorizers which can be used in place of
|
||||
the default `NMFALSFactorizer` (which is non-negative matrix factorization with
|
||||
alternating least squares update rules). These include:
|
||||
|
||||
- `SVDBatchFactorizer`
|
||||
- `SVDCompleteIncrementalFactorizer`
|
||||
- `SVDIncompleteIncrementalFactorizer`
|
||||
- `NMFALSFactorizer`
|
||||
- `RegularizedSVD`
|
||||
- `QUIC_SVD`
|
||||
- `BatchSVDPolicy`
|
||||
- `SVDCompletePolicy`
|
||||
- `SVDIncompletePolicy`
|
||||
- `NMFPolicy`
|
||||
- `RegSVDPolicy`
|
||||
- `QuicSVDPolicy`
|
||||
- `BiasSVDPolicy`
|
||||
- `SVDPlusPlusPolicy`
|
||||
- `RandomizedSVDPolicy`
|
||||
- `BlockKrylovSVDPolicy`
|
||||
|
||||
The `AMF` class has many other possibilities than those listed here; it is a
|
||||
framework for alternating matrix factorization techniques. See the `AMF` class
|
||||
@@ -297,7 +301,7 @@ extern size_t neighborhood;
|
||||
extern size_t rank;
|
||||
|
||||
// Build the CF object and perform the decomposition.
|
||||
CF cf(data, RegularizedSVD(), neighborhood, rank);
|
||||
CFType cf(data, RegSVDPolicy(), neighborhood, rank);
|
||||
|
||||
// Store the results in this object.
|
||||
arma::Mat<size_t> recommendations;
|
||||
@@ -330,7 +334,7 @@ extern size_t rank;
|
||||
// Build the CF object and perform the decomposition.
|
||||
// The constructor takes a default-constructed factorizer, which, by default,
|
||||
// is of type NMFALSFactorizer.
|
||||
CF cf(data, NMFALSFactorizer(), neighborhood, rank);
|
||||
CF cf(data, NMFPolicy(), neighborhood, rank);
|
||||
|
||||
const double prediction = cf.Predict(12, 50); // User 12, item 50.
|
||||
```
|
||||
@@ -356,7 +360,7 @@ extern size_t rank;
|
||||
// Build the CF object and perform the decomposition.
|
||||
// The constructor takes a default-constructed factorizer, which, by default,
|
||||
// is of type NMFALSFactorizer.
|
||||
CF cf(data, NMFALSFactorizer(), neighborhood, rank);
|
||||
CF cf(data, NMFPolicy(), neighborhood, rank);
|
||||
|
||||
// References to W and H matrices.
|
||||
const arma::mat& W = cf.W();
|
||||
|
||||
@@ -43,7 +43,7 @@ function.
|
||||
using namespace mlpack;
|
||||
|
||||
arma::mat data;
|
||||
data::DatasetMapper info;
|
||||
data::DatasetInfo info;
|
||||
data::Load("dataset.csv", data, info);
|
||||
```
|
||||
|
||||
@@ -155,8 +155,8 @@ std::cout << info.UnmapString(1, 2) << "\n";
|
||||
This will print:
|
||||
|
||||
```
|
||||
T
|
||||
F
|
||||
True
|
||||
False
|
||||
```
|
||||
|
||||
### `UnmapValue()`
|
||||
@@ -168,8 +168,8 @@ The `UnmapValue()` function has the signature `UnmapValue(const std::string
|
||||
- `dimension` is the dimension in which you want to find the mapped value
|
||||
|
||||
```c++
|
||||
std::cout << info.UnmapValue("T", 2) << "\n";
|
||||
std::cout << info.UnmapValue("F", 2) << "\n";
|
||||
std::cout << info.UnmapValue("True", 2) << "\n";
|
||||
std::cout << info.UnmapValue("False", 2) << "\n";
|
||||
```
|
||||
|
||||
will produce:
|
||||
|
||||
@@ -257,6 +257,9 @@ manually specified. Choices that mlpack provides include:
|
||||
- `HyperbolicTangentKernel`
|
||||
- `LaplacianKernel`
|
||||
- `PSpectrumStringKernel`
|
||||
- `CauchyKernal`
|
||||
- `ExampleKernal`
|
||||
- `SphericalKernal`
|
||||
|
||||
The following examples use kernels from that list. Writing your own kernel is
|
||||
detailed in the next section. Remember that when you are using the C++
|
||||
@@ -293,7 +296,7 @@ f.Search(5, indices, products);
|
||||
In this setting we have both a query and reference dataset. We search for 10
|
||||
maximum kernels.
|
||||
|
||||
```
|
||||
```c++
|
||||
#include <mlpack.hpp>
|
||||
|
||||
using namespace mlpack::fastmks;
|
||||
|
||||
@@ -103,7 +103,7 @@ bool Load(const std::vector<std::string>& files,
|
||||
```c++
|
||||
data::ImageInfo info;
|
||||
std::vector<std::string>> files{"test_image1.bmp","test_image2.bmp"};
|
||||
data::load(files, matrix, info, false, true);
|
||||
data::Load(files, matrix, info, false, true);
|
||||
```
|
||||
|
||||
## Saving
|
||||
|
||||
@@ -339,7 +339,7 @@ file.
|
||||
The class provides one method that performs computation:
|
||||
|
||||
```c++
|
||||
void Predict(const arma::mat& points, arma::vec& predictions);
|
||||
void Predict(const arma::mat& points, arma::rowvec& predictions);
|
||||
```
|
||||
|
||||
Once you have generated or loaded a model, you can call this method and pass it
|
||||
@@ -355,7 +355,7 @@ corresponding to each row of the points matrix.
|
||||
using namespace mlpack;
|
||||
|
||||
arma::mat data; // The dataset itself.
|
||||
arma::vec responses; // The responses, one row for each row in data.
|
||||
arma::rowvec responses; // The responses, one row for each row in data.
|
||||
|
||||
// Regress.
|
||||
LinearRegression lr(data, responses);
|
||||
@@ -400,11 +400,11 @@ LinearRegression lr();
|
||||
// The dataset we want to predict on; each row is a data point.
|
||||
arma::mat points;
|
||||
// This will store the predictions; one row for each point.
|
||||
arma::vec predictions;
|
||||
arma::rowvec predictions;
|
||||
|
||||
lr.Predict(points, predictions); // Predict.
|
||||
|
||||
// Now, the vector 'predictions' will contain the predicted values.
|
||||
// Now, the row vector 'predictions' will contain the predicted values.
|
||||
```
|
||||
|
||||
### Setting lambda for ridge regression
|
||||
@@ -419,7 +419,7 @@ used to set a value of lambda:
|
||||
using namespace mlpack;
|
||||
|
||||
arma::mat data; // The dataset itself.
|
||||
arma::vec responses; // The responses, one row for each row in data.
|
||||
arma::rowvec responses; // The responses, one row for each row in data.
|
||||
|
||||
// Regress, with a lambda of 0.5.
|
||||
LinearRegression lr(data, responses, 0.5);
|
||||
|
||||
@@ -290,9 +290,9 @@ if (BUILD_R_BINDINGS)
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/mlpack/")
|
||||
|
||||
file(COPY
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/mlpack/configure"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/mlpack/inst/CITATION"
|
||||
DESTINATION
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/mlpack/")
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/mlpack/inst")
|
||||
|
||||
# Do the actual build.
|
||||
add_custom_target(r_build ALL)
|
||||
|
||||
-8
@@ -1,8 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
if test `uname` = "SunOS" ;
|
||||
then
|
||||
sed '1 s/$/ -ftrack-macro-expansion=0 -pipe --param ggc-min-expand=10 --param ggc-min-heapsize=8192/' ./src/Makevars > ./src/Makevars.tmp && cat ./src/Makevars.tmp > ./src/Makevars && rm ./src/Makevars.tmp
|
||||
fi
|
||||
|
||||
exit 0
|
||||
@@ -0,0 +1,49 @@
|
||||
bibentry("Manual",
|
||||
other = unlist(citation(auto = meta), recursive = FALSE))
|
||||
|
||||
bibentry("Article",
|
||||
title = "mlpack 4: a fast, header-only C++ machine learning library",
|
||||
author = c(person("Ryan R.", "Curtin",
|
||||
comment = c(ORCID = "0000-0002-9903-8214")),
|
||||
person("Marcus", "Edel",
|
||||
comment = c(ORCID = "0000-0001-5445-7303")),
|
||||
person("Omar", "Shrit",
|
||||
comment = c(ORCID = "0000-0002-8621-3052")),
|
||||
person("Shubham", "Agrawal",
|
||||
comment = c(ORCID = "0000-0001-8713-4682")),
|
||||
person("Suryoday", "Basak",
|
||||
comment = c(ORCID = "0000-0002-1982-1787")),
|
||||
person("James J.", "Balamuta",
|
||||
comment = c(ORCID = "0000-0003-2826-8458")),
|
||||
person("Ryan", "Birmingham",
|
||||
comment = c(ORCID = "0000-0002-7943-6346")),
|
||||
person("Kartik", "Dutt",
|
||||
comment = c(ORCID = "0000-0003-3877-0142")),
|
||||
person("Dirk", "Eddelbuettel",
|
||||
comment = c(ORCID = "0000-0001-6419-907X")),
|
||||
person("Rishabh", "Garg",
|
||||
comment = c(ORCID = "0000-0003-0398-0887")),
|
||||
person("Shikhar", "Jaiswal",
|
||||
comment = c(ORCID = "0000-0002-3683-3931")),
|
||||
person("Aakash", "Kaushik",
|
||||
comment = c(ORCID = "0000-0003-1079-8338")),
|
||||
person("Sangyeon", "Kim",
|
||||
comment = c(ORCID = "0000-0003-0717-0240")),
|
||||
person("Anjishnu", "Mukherjee",
|
||||
comment = c(ORCID = "0000-0003-4012-8466")),
|
||||
person("Nanubala Gnana", "Sai",
|
||||
comment = c(ORCID = "0000-0003-0774-7994")),
|
||||
person("Nippun", "Sharma",
|
||||
comment = c(ORCID = "0000-0003-0365-2613")),
|
||||
person("Yashwant Singh", "Parihar",
|
||||
comment = c(ORCID = "0000-0003-3492-0377")),
|
||||
person("Roshan", "Swain",
|
||||
comment = c(ORCID = "0000-0002-7262-8230")),
|
||||
person("Conrad", "Sanderson",
|
||||
comment = c(ORCID = "0000-0002-0049-4501"))),
|
||||
journal = "Journal of Open Source Software",
|
||||
year = "2023",
|
||||
volume = "8",
|
||||
number = "82",
|
||||
doi = "10.21105/joss.05026"
|
||||
)
|
||||
@@ -1,3 +1,2 @@
|
||||
PKG_CXXFLAGS = -DBOOST_MATH_PROMOTE_DOUBLE_POLICY=false -I. $(SHLIB_OPENMP_CXXFLAGS)
|
||||
PKG_LIBS = $(SHLIB_OPENMP_CXXFLAGS) $(LAPACK_LIBS) $(BLAS_LIBS) $(FLIBS)
|
||||
CXX_STD = CXX14
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
PKG_CXXFLAGS = -DBOOST_MATH_PROMOTE_DOUBLE_POLICY=false -I. $(SHLIB_OPENMP_CXXFLAGS) -ftrack-macro-expansion=0 -pipe --param ggc-min-expand=10 --param ggc-min-heapsize=8192
|
||||
PKG_LIBS = $(SHLIB_OPENMP_CXXFLAGS) $(LAPACK_LIBS) $(BLAS_LIBS) $(FLIBS)
|
||||
CXX_STD = CXX14
|
||||
CXX_STD = CXX17
|
||||
|
||||
@@ -19,15 +19,15 @@
|
||||
* Print a table in markdown format that contains
|
||||
* a list of parameters.
|
||||
*
|
||||
* @param bindingName parameters corresponding to bindingName.
|
||||
* @param language parameters for a particular language.
|
||||
* @param bindingName Parameters corresponding to bindingName.
|
||||
* @param language Parameters for a particular language.
|
||||
* @param params Params object.
|
||||
* @param headers which headers to print (eg: Name, Default, etc.).
|
||||
* @param paramsSet to prevent printing a parameter more than once.
|
||||
* @param onlyHyperParams print only hyper-parameters.
|
||||
* @param onlyMatrixParams print only matrix-parameters.
|
||||
* @param onlyInputParams print only input-parameters.
|
||||
* @param onlyOutputParams print only output-parameters.
|
||||
* @param headers Which headers to print (eg: Name, Default, etc.).
|
||||
* @param paramsSet To prevent printing a parameter more than once.
|
||||
* @param onlyHyperParams If true, print only hyper-parameters.
|
||||
* @param onlyMatrixParams If true, print only matrix-parameters.
|
||||
* @param onlyInputParams If true, print only input-parameters.
|
||||
* @param onlyOutputParams If true, print only output-parameters.
|
||||
*/
|
||||
void PrintParamTable(const std::string& bindingName,
|
||||
const std::string& language,
|
||||
|
||||
@@ -64,7 +64,7 @@ void PrintWrapperPY(const std::string& category,
|
||||
}
|
||||
|
||||
// Import different mlpack programs that are to be wrapped.
|
||||
for(int i=0; i<methods.size(); i++)
|
||||
for(size_t i = 0; i < methods.size(); i++)
|
||||
{
|
||||
cout << "from mlpack." << groupName << "_" << methods[i] << " ";
|
||||
cout << "import " << groupName << "_" << methods[i] << endl;
|
||||
@@ -438,8 +438,8 @@ void PrintWrapperPY(const std::string& category,
|
||||
cout << endl;
|
||||
indent -= 2;
|
||||
}
|
||||
}
|
||||
} // PrintWrapperPY
|
||||
|
||||
} // python
|
||||
} // bindings
|
||||
} // mlpack
|
||||
} // namespace python
|
||||
} // namespace bindings
|
||||
} // namespace mlpack
|
||||
|
||||
@@ -101,10 +101,10 @@ bool Save(const std::string& filename,
|
||||
#ifdef ARMA_USE_HDF5
|
||||
// We can't save with streams for HDF5.
|
||||
const bool success = (saveType == FileType::HDF5Binary) ?
|
||||
tmp.quiet_save(filename, ToArmaFileType(saveType)) :
|
||||
tmp.quiet_save(stream, ToArmaFileType(saveType));
|
||||
tmp.save(filename, ToArmaFileType(saveType)) :
|
||||
tmp.save(stream, ToArmaFileType(saveType));
|
||||
#else
|
||||
const bool success = tmp.quiet_save(stream, ToArmaFileType(saveType));
|
||||
const bool success = tmp.save(stream, ToArmaFileType(saveType));
|
||||
#endif
|
||||
if (!success)
|
||||
{
|
||||
@@ -122,10 +122,10 @@ bool Save(const std::string& filename,
|
||||
#ifdef ARMA_USE_HDF5
|
||||
// We can't save with streams for HDF5.
|
||||
const bool success = (saveType == FileType::HDF5Binary) ?
|
||||
matrix.quiet_save(filename, ToArmaFileType(saveType)) :
|
||||
matrix.quiet_save(stream, ToArmaFileType(saveType));
|
||||
matrix.save(filename, ToArmaFileType(saveType)) :
|
||||
matrix.save(stream, ToArmaFileType(saveType));
|
||||
#else
|
||||
const bool success = matrix.quiet_save(stream, ToArmaFileType(saveType));
|
||||
const bool success = matrix.save(stream, ToArmaFileType(saveType));
|
||||
#endif
|
||||
if (!success)
|
||||
{
|
||||
@@ -236,7 +236,7 @@ bool Save(const std::string& filename,
|
||||
tmp = trans(matrix);
|
||||
}
|
||||
|
||||
const bool success = tmp.quiet_save(stream, ToArmaFileType(saveType));
|
||||
const bool success = tmp.save(stream, ToArmaFileType(saveType));
|
||||
if (!success)
|
||||
{
|
||||
Timer::Stop("saving_data");
|
||||
|
||||
@@ -42,12 +42,6 @@
|
||||
* should be present per binding. BINDING_NAME should be set before calling
|
||||
* this.
|
||||
*
|
||||
* @see mlpack::IO, PARAM_FLAG(), PARAM_INT_IN(), PARAM_DOUBLE_IN(),
|
||||
* PARAM_STRING_IN(), PARAM_VECTOR_IN(), PARAM_INT_OUT(), PARAM_DOUBLE_OUT(),
|
||||
* PARAM_VECTOR_OUT(), PARAM_INT_IN_REQ(), PARAM_DOUBLE_IN_REQ(),
|
||||
* PARAM_STRING_IN_REQ(), PARAM_VECTOR_IN_REQ(), PARAM_INT_OUT_REQ(),
|
||||
* PARAM_DOUBLE_OUT_REQ(), PARAM_VECTOR_OUT_REQ(), PARAM_STRING_OUT_REQ().
|
||||
*
|
||||
* @param NAME User-friendly name.
|
||||
*/
|
||||
#ifdef __COUNTER__
|
||||
@@ -69,12 +63,6 @@
|
||||
* should be present in your program! Therefore, use it in the main.cpp
|
||||
* (or corresponding binding) in your program.
|
||||
*
|
||||
* @see mlpack::IO, PARAM_FLAG(), PARAM_INT_IN(), PARAM_DOUBLE_IN(),
|
||||
* PARAM_STRING_IN(), PARAM_VECTOR_IN(), PARAM_INT_OUT(), PARAM_DOUBLE_OUT(),
|
||||
* PARAM_VECTOR_OUT(), PARAM_INT_IN_REQ(), PARAM_DOUBLE_IN_REQ(),
|
||||
* PARAM_STRING_IN_REQ(), PARAM_VECTOR_IN_REQ(), PARAM_INT_OUT_REQ(),
|
||||
* PARAM_DOUBLE_OUT_REQ(), PARAM_VECTOR_OUT_REQ(), PARAM_STRING_OUT_REQ().
|
||||
*
|
||||
* @param SHORT_DESC Short two-sentence description of the program; it should
|
||||
* describe what the program implements and does, and a quick overview of
|
||||
* how it can be used and what it should be used for.
|
||||
@@ -100,12 +88,6 @@
|
||||
* If you wish to "revamp" some bindings, then use the BINDING_LONG_DESC()
|
||||
* of the method that you pass first into the group_bindings() macro. For all other
|
||||
* methods, it is fine if you keep the BINDING_LONG_DESC() empty.
|
||||
*
|
||||
* @see mlpack::IO, PARAM_FLAG(), PARAM_INT_IN(), PARAM_DOUBLE_IN(),
|
||||
* PARAM_STRING_IN(), PARAM_VECTOR_IN(), PARAM_INT_OUT(), PARAM_DOUBLE_OUT(),
|
||||
* PARAM_VECTOR_OUT(), PARAM_INT_IN_REQ(), PARAM_DOUBLE_IN_REQ(),
|
||||
* PARAM_STRING_IN_REQ(), PARAM_VECTOR_IN_REQ(), PARAM_INT_OUT_REQ(),
|
||||
* PARAM_DOUBLE_OUT_REQ(), PARAM_VECTOR_OUT_REQ(), PARAM_STRING_OUT_REQ().
|
||||
*
|
||||
* @param LONG_DESC Long string describing what the program does. Newlines
|
||||
* should not be used here; this is taken care of by IO (however, you
|
||||
@@ -132,12 +114,6 @@
|
||||
* present in your program! Therefore, use it in the main.cpp
|
||||
* (or corresponding binding) in your program.
|
||||
*
|
||||
* @see mlpack::IO, PARAM_FLAG(), PARAM_INT_IN(), PARAM_DOUBLE_IN(),
|
||||
* PARAM_STRING_IN(), PARAM_VECTOR_IN(), PARAM_INT_OUT(), PARAM_DOUBLE_OUT(),
|
||||
* PARAM_VECTOR_OUT(), PARAM_INT_IN_REQ(), PARAM_DOUBLE_IN_REQ(),
|
||||
* PARAM_STRING_IN_REQ(), PARAM_VECTOR_IN_REQ(), PARAM_INT_OUT_REQ(),
|
||||
* PARAM_DOUBLE_OUT_REQ(), PARAM_VECTOR_OUT_REQ(), PARAM_STRING_OUT_REQ().
|
||||
*
|
||||
* @param EXAMPLE Long string describing a simple usage example.. Newlines
|
||||
* should not be used here; this is taken care of by IO (however, you
|
||||
* can explicitly specify newlines to denote new paragraphs). You can
|
||||
@@ -163,12 +139,6 @@
|
||||
* present in your program! Therefore, use it in the main.cpp
|
||||
* (or corresponding binding) in your program.
|
||||
*
|
||||
* @see mlpack::IO, PARAM_FLAG(), PARAM_INT_IN(), PARAM_DOUBLE_IN(),
|
||||
* PARAM_STRING_IN(), PARAM_VECTOR_IN(), PARAM_INT_OUT(), PARAM_DOUBLE_OUT(),
|
||||
* PARAM_VECTOR_OUT(), PARAM_INT_IN_REQ(), PARAM_DOUBLE_IN_REQ(),
|
||||
* PARAM_STRING_IN_REQ(), PARAM_VECTOR_IN_REQ(), PARAM_INT_OUT_REQ(),
|
||||
* PARAM_DOUBLE_OUT_REQ(), PARAM_VECTOR_OUT_REQ(), PARAM_STRING_OUT_REQ().
|
||||
*
|
||||
* Provide a link for a binding's "see also" documentation section, which is
|
||||
* primarily (but not necessarily exclusively) used by the Markdown bindings
|
||||
* This link can be specified by calling SEE_ALSO("description", "link"), where
|
||||
@@ -203,17 +173,6 @@
|
||||
* printing macros like PRINT_PARAM_STRING() or PRINT_DATASET() or others
|
||||
* here---it will cause problems.
|
||||
* @param ALIAS An alias for the parameter (one letter).
|
||||
*
|
||||
* @see mlpack::IO, BINDING_USER_NAME(), BINDING_SHORT_DESC(),
|
||||
* BINDING_LONG_DESC(), BINDING_EXAMPLE() and BINDING_SEE_ALSO().
|
||||
*
|
||||
* @bug
|
||||
* The __COUNTER__ variable is used in most cases to guarantee a unique global
|
||||
* identifier for options declared using the PARAM_*() macros. However, not all
|
||||
* compilers have this support--most notably, gcc < 4.3. In that case, the
|
||||
* __LINE__ macro is used as an attempt to get a unique global identifier, but
|
||||
* collisions are still possible, and they produce bizarre error messages. See
|
||||
* https://github.com/mlpack/mlpack/issues/100 for more information.
|
||||
*/
|
||||
#define PARAM_FLAG(ID, DESC, ALIAS) \
|
||||
PARAM_IN(bool, ID, DESC, ALIAS, false, false);
|
||||
@@ -230,18 +189,6 @@
|
||||
* here---it will cause problems.
|
||||
* @param ALIAS An alias for the parameter (one letter).
|
||||
* @param DEF Default value of the parameter.
|
||||
*
|
||||
* @see mlpack::IO, BINDING_USER_NAME(), BINDING_SHORT_DESC(),
|
||||
* BINDING_LONG_DESC(), BINDING_EXAMPLE() and BINDING_SEE_ALSO().
|
||||
*
|
||||
* @bug
|
||||
// Use a forward declaration of the class.
|
||||
* The __COUNTER__ variable is used in most cases to guarantee a unique global
|
||||
* identifier for options declared using the PARAM_*() macros. However, not all
|
||||
* compilers have this support--most notably, gcc < 4.3. In that case, the
|
||||
* __LINE__ macro is used as an attempt to get a unique global identifier, but
|
||||
* collisions are still possible, and they produce bizarre error messages. See
|
||||
* https://github.com/mlpack/mlpack/issues/100 for more information.
|
||||
*/
|
||||
#define PARAM_INT_IN(ID, DESC, ALIAS, DEF) \
|
||||
PARAM_IN(int, ID, DESC, ALIAS, DEF, false)
|
||||
@@ -262,17 +209,6 @@
|
||||
* @param DESC Quick description of the parameter (1-2 sentences). Don't use
|
||||
* printing macros like PRINT_PARAM_STRING() or PRINT_DATASET() or others
|
||||
* here---it will cause problems.
|
||||
*
|
||||
* @see mlpack::IO, BINDING_USER_NAME(), BINDING_SHORT_DESC(),
|
||||
* BINDING_LONG_DESC(), BINDING_EXAMPLE() and BINDING_SEE_ALSO().
|
||||
*
|
||||
* @bug
|
||||
* The __COUNTER__ variable is used in most cases to guarantee a unique global
|
||||
* identifier for options declared using the PARAM_*() macros. However, not all
|
||||
* compilers have this support--most notably, gcc < 4.3. In that case, the
|
||||
* __LINE__ macro is used as an attempt to get a unique global identifier, but
|
||||
* collisions are still possible, and they produce bizarre error messages. See
|
||||
* https://github.com/mlpack/mlpack/issues/100 for more information.
|
||||
*/
|
||||
#define PARAM_INT_OUT(ID, DESC) \
|
||||
PARAM_OUT(int, ID, DESC, "", 0, false)
|
||||
@@ -289,17 +225,6 @@
|
||||
* here---it will cause problems.
|
||||
* @param ALIAS An alias for the parameter (one letter).
|
||||
* @param DEF Default value of the parameter.
|
||||
*
|
||||
* @see mlpack::IO, BINDING_USER_NAME(), BINDING_SHORT_DESC(),
|
||||
* BINDING_LONG_DESC(), BINDING_EXAMPLE() and BINDING_SEE_ALSO().
|
||||
*
|
||||
* @bug
|
||||
* The __COUNTER__ variable is used in most cases to guarantee a unique global
|
||||
* identifier for options declared using the PARAM_*() macros. However, not all
|
||||
* compilers have this support--most notably, gcc < 4.3. In that case, the
|
||||
* __LINE__ macro is used as an attempt to get a unique global identifier, but
|
||||
* collisions are still possible, and they produce bizarre error messages. See
|
||||
* https://github.com/mlpack/mlpack/issues/100 for more information.
|
||||
*/
|
||||
#define PARAM_DOUBLE_IN(ID, DESC, ALIAS, DEF) \
|
||||
PARAM_IN(double, ID, DESC, ALIAS, DEF, false)
|
||||
@@ -320,17 +245,6 @@
|
||||
* @param DESC Quick description of the parameter (1-2 sentences). Don't use
|
||||
* printing macros like PRINT_PARAM_STRING() or PRINT_DATASET() or others
|
||||
* here---it will cause problems.
|
||||
*
|
||||
* @see mlpack::IO, BINDING_USER_NAME(), BINDING_SHORT_DESC(),
|
||||
* BINDING_LONG_DESC(), BINDING_EXAMPLE() and BINDING_SEE_ALSO().
|
||||
*
|
||||
* @bug
|
||||
* The __COUNTER__ variable is used in most cases to guarantee a unique global
|
||||
* identifier for options declared using the PARAM_*() macros. However, not all
|
||||
* compilers have this support--most notably, gcc < 4.3. In that case, the
|
||||
* __LINE__ macro is used as an attempt to get a unique global identifier, but
|
||||
* collisions are still possible, and they produce bizarre error messages. See
|
||||
* https://github.com/mlpack/mlpack/issues/100 for more information.
|
||||
*/
|
||||
#define PARAM_DOUBLE_OUT(ID, DESC) \
|
||||
PARAM_OUT(double, ID, DESC, "", 0.0, false)
|
||||
@@ -349,17 +263,6 @@
|
||||
* here---it will cause problems.
|
||||
* @param ALIAS An alias for the parameter (one letter).
|
||||
* @param DEF Default value of the parameter.
|
||||
*
|
||||
* @see mlpack::IO, BINDING_USER_NAME(), BINDING_SHORT_DESC(),
|
||||
* BINDING_LONG_DESC(), BINDING_EXAMPLE() and BINDING_SEE_ALSO().
|
||||
*
|
||||
* @bug
|
||||
* The __COUNTER__ variable is used in most cases to guarantee a unique global
|
||||
* identifier for options declared using the PARAM_*() macros. However, not all
|
||||
* compilers have this support--most notably, gcc < 4.3. In that case, the
|
||||
* __LINE__ macro is used as an attempt to get a unique global identifier, but
|
||||
* collisions are still possible, and they produce bizarre error messages. See
|
||||
* https://github.com/mlpack/mlpack/issues/100 for more information.
|
||||
*/
|
||||
#define PARAM_STRING_IN(ID, DESC, ALIAS, DEF) \
|
||||
PARAM_IN(std::string, ID, DESC, ALIAS, DEF, false)
|
||||
@@ -381,17 +284,6 @@
|
||||
* printing macros like PRINT_PARAM_STRING() or PRINT_DATASET() or others
|
||||
* here---it will cause problems.
|
||||
* @param ALIAS An alias for the parameter (one letter).
|
||||
*
|
||||
* @see mlpack::IO, BINDING_USER_NAME(), BINDING_SHORT_DESC(),
|
||||
* BINDING_LONG_DESC(), BINDING_EXAMPLE() and BINDING_SEE_ALSO().
|
||||
*
|
||||
* @bug
|
||||
* The __COUNTER__ variable is used in most cases to guarantee a unique global
|
||||
* identifier for options declared using the PARAM_*() macros. However, not all
|
||||
* compilers have this support--most notably, gcc < 4.3. In that case, the
|
||||
* __LINE__ macro is used as an attempt to get a unique global identifier, but
|
||||
* collisions are still possible, and they produce bizarre error messages. See
|
||||
* https://github.com/mlpack/mlpack/issues/100 for more information.
|
||||
*/
|
||||
#define PARAM_STRING_OUT(ID, DESC, ALIAS) \
|
||||
PARAM_OUT(std::string, ID, DESC, ALIAS, "", false)
|
||||
@@ -412,14 +304,6 @@
|
||||
* printing macros like PRINT_PARAM_STRING() or PRINT_DATASET() or others
|
||||
* here---it will cause problems.
|
||||
* @param ALIAS An alias for the parameter (one letter).
|
||||
*
|
||||
* @bug
|
||||
* The __COUNTER__ variable is used in most cases to guarantee a unique global
|
||||
* identifier for options declared using the PARAM_*() macros. However, not all
|
||||
* compilers have this support--most notably, gcc < 4.3. In that case, the
|
||||
* __LINE__ macro is used as an attempt to get a unique global identifier, but
|
||||
* collisions are still possible, and they produce bizarre error messages. See
|
||||
* https://github.com/mlpack/mlpack/issues/100 for more information.
|
||||
*/
|
||||
#define PARAM_MATRIX_IN(ID, DESC, ALIAS) \
|
||||
PARAM_MATRIX(ID, DESC, ALIAS, false, true, true)
|
||||
@@ -440,14 +324,6 @@
|
||||
* printing macros like PRINT_PARAM_STRING() or PRINT_DATASET() or others
|
||||
* here---it will cause problems.
|
||||
* @param ALIAS An alias for the parameter (one letter).
|
||||
*
|
||||
* @bug
|
||||
* The __COUNTER__ variable is used in most cases to guarantee a unique global
|
||||
* identifier for options declared using the PARAM_*() macros. However, not all
|
||||
* compilers have this support--most notably, gcc < 4.3. In that case, the
|
||||
* __LINE__ macro is used as an attempt to get a unique global identifier, but
|
||||
* collisions are still possible, and they produce bizarre error messages. See
|
||||
* https://github.com/mlpack/mlpack/issues/100 for more information.
|
||||
*/
|
||||
#define PARAM_MATRIX_IN_REQ(ID, DESC, ALIAS) \
|
||||
PARAM_MATRIX(ID, DESC, ALIAS, true, true, true)
|
||||
@@ -473,14 +349,6 @@
|
||||
* printing macros like PRINT_PARAM_STRING() or PRINT_DATASET() or others
|
||||
* here---it will cause problems.
|
||||
* @param ALIAS An alias for the parameter (one letter).
|
||||
*
|
||||
* @bug
|
||||
* The __COUNTER__ variable is used in most cases to guarantee a unique global
|
||||
* identifier for options declared using the PARAM_*() macros. However, not all
|
||||
* compilers have this support--most notably, gcc < 4.3. In that case, the
|
||||
* __LINE__ macro is used as an attempt to get a unique global identifier, but
|
||||
* collisions are still possible, and they produce bizarre error messages. See
|
||||
* https://github.com/mlpack/mlpack/issues/100 for more information.
|
||||
*/
|
||||
#define PARAM_MATRIX_OUT(ID, DESC, ALIAS) \
|
||||
PARAM_MATRIX(ID, DESC, ALIAS, false, true, false)
|
||||
@@ -502,14 +370,6 @@
|
||||
* printing macros like PRINT_PARAM_STRING() or PRINT_DATASET() or others
|
||||
* here---it will cause problems.
|
||||
* @param ALIAS An alias for the parameter (one letter).
|
||||
*
|
||||
* @bug
|
||||
* The __COUNTER__ variable is used in most cases to guarantee a unique global
|
||||
* identifier for options declared using the PARAM_*() macros. However, not all
|
||||
* compilers have this support--most notably, gcc < 4.3. In that case, the
|
||||
* __LINE__ macro is used as an attempt to get a unique global identifier, but
|
||||
* collisions are still possible, and they produce bizarre error messages. See
|
||||
* https://github.com/mlpack/mlpack/issues/100 for more information.
|
||||
*/
|
||||
#define PARAM_TMATRIX_IN(ID, DESC, ALIAS) \
|
||||
PARAM_MATRIX(ID, DESC, ALIAS, false, false, true)
|
||||
@@ -532,14 +392,6 @@
|
||||
* printing macros like PRINT_PARAM_STRING() or PRINT_DATASET() or others
|
||||
* here---it will cause problems.
|
||||
* @param ALIAS An alias for the parameter (one letter).
|
||||
*
|
||||
* @bug
|
||||
* The __COUNTER__ variable is used in most cases to guarantee a unique global
|
||||
* identifier for options declared using the PARAM_*() macros. However, not all
|
||||
* compilers have this support--most notably, gcc < 4.3. In that case, the
|
||||
* __LINE__ macro is used as an attempt to get a unique global identifier, but
|
||||
* collisions are still possible, and they produce bizarre error messages. See
|
||||
* https://github.com/mlpack/mlpack/issues/100 for more information.
|
||||
*/
|
||||
#define PARAM_TMATRIX_IN_REQ(ID, DESC, ALIAS) \
|
||||
PARAM_MATRIX(ID, DESC, ALIAS, true, false, true)
|
||||
@@ -567,14 +419,6 @@
|
||||
* printing macros like PRINT_PARAM_STRING() or PRINT_DATASET() or others
|
||||
* here---it will cause problems.
|
||||
* @param ALIAS An alias for the parameter (one letter).
|
||||
*
|
||||
* @bug
|
||||
* The __COUNTER__ variable is used in most cases to guarantee a unique global
|
||||
* identifier for options declared using the PARAM_*() macros. However, not all
|
||||
* compilers have this support--most notably, gcc < 4.3. In that case, the
|
||||
* __LINE__ macro is used as an attempt to get a unique global identifier, but
|
||||
* collisions are still possible, and they produce bizarre error messages. See
|
||||
* https://github.com/mlpack/mlpack/issues/100 for more information.
|
||||
*/
|
||||
#define PARAM_TMATRIX_OUT(ID, DESC, ALIAS) \
|
||||
PARAM_MATRIX(ID, DESC, ALIAS, false, false, false)
|
||||
@@ -595,14 +439,6 @@
|
||||
* printing macros like PRINT_PARAM_STRING() or PRINT_DATASET() or others
|
||||
* here---it will cause problems.
|
||||
* @param ALIAS An alias for the parameter (one letter).
|
||||
*
|
||||
* @bug
|
||||
* The __COUNTER__ variable is used in most cases to guarantee a unique global
|
||||
* identifier for options declared using the PARAM_*() macros. However, not all
|
||||
* compilers have this support--most notably, gcc < 4.3. In that case, the
|
||||
* __LINE__ macro is used as an attempt to get a unique global identifier, but
|
||||
* collisions are still possible, and they produce bizarre error messages. See
|
||||
* https://github.com/mlpack/mlpack/issues/100 for more information.
|
||||
*/
|
||||
#define PARAM_UMATRIX_IN(ID, DESC, ALIAS) \
|
||||
PARAM_UMATRIX(ID, DESC, ALIAS, false, true, true)
|
||||
@@ -624,14 +460,6 @@
|
||||
* printing macros like PRINT_PARAM_STRING() or PRINT_DATASET() or others
|
||||
* here---it will cause problems.
|
||||
* @param ALIAS An alias for the parameter (one letter).
|
||||
*
|
||||
* @bug
|
||||
* The __COUNTER__ variable is used in most cases to guarantee a unique global
|
||||
* identifier for options declared using the PARAM_*() macros. However, not all
|
||||
* compilers have this support--most notably, gcc < 4.3. In that case, the
|
||||
* __LINE__ macro is used as an attempt to get a unique global identifier, but
|
||||
* collisions are still possible, and they produce bizarre error messages. See
|
||||
* https://github.com/mlpack/mlpack/issues/100 for more information.
|
||||
*/
|
||||
#define PARAM_UMATRIX_IN_REQ(ID, DESC, ALIAS) \
|
||||
PARAM_UMATRIX(ID, DESC, ALIAS, true, true, true)
|
||||
@@ -658,14 +486,6 @@
|
||||
* printing macros like PRINT_PARAM_STRING() or PRINT_DATASET() or others
|
||||
* here---it will cause problems.
|
||||
* @param ALIAS An alias for the parameter (one letter).
|
||||
*
|
||||
* @bug
|
||||
* The __COUNTER__ variable is used in most cases to guarantee a unique global
|
||||
* identifier for options declared using the PARAM_*() macros. However, not all
|
||||
* compilers have this support--most notably, gcc < 4.3. In that case, the
|
||||
* __LINE__ macro is used as an attempt to get a unique global identifier, but
|
||||
* collisions are still possible, and they produce bizarre error messages. See
|
||||
* https://github.com/mlpack/mlpack/issues/100 for more information.
|
||||
*/
|
||||
#define PARAM_UMATRIX_OUT(ID, DESC, ALIAS) \
|
||||
PARAM_UMATRIX(ID, DESC, ALIAS, false, true, false)
|
||||
@@ -687,14 +507,6 @@
|
||||
* printing macros like PRINT_PARAM_STRING() or PRINT_DATASET() or others
|
||||
* here---it will cause problems.
|
||||
* @param ALIAS An alias for the parameter (one letter).
|
||||
*
|
||||
* @bug
|
||||
* The __COUNTER__ variable is used in most cases to guarantee a unique global
|
||||
* identifier for options declared using the PARAM_*() macros. However, not all
|
||||
* compilers have this support--most notably, gcc < 4.3. In that case, the
|
||||
* __LINE__ macro is used as an attempt to get a unique global identifier, but
|
||||
* collisions are still possible, and they produce bizarre error messages. See
|
||||
* https://github.com/mlpack/mlpack/issues/100 for more information.
|
||||
*/
|
||||
#define PARAM_COL_IN(ID, DESC, ALIAS) \
|
||||
PARAM_COL(ID, DESC, ALIAS, false, true, true)
|
||||
@@ -715,14 +527,6 @@
|
||||
* printing macros like PRINT_PARAM_STRING() or PRINT_DATASET() or others
|
||||
* here---it will cause problems.
|
||||
* @param ALIAS An alias for the parameter (one letter).
|
||||
*
|
||||
* @bug
|
||||
* The __COUNTER__ variable is used in most cases to guarantee a unique global
|
||||
* identifier for options declared using the PARAM_*() macros. However, not all
|
||||
* compilers have this support--most notably, gcc < 4.3. In that case, the
|
||||
* __LINE__ macro is used as an attempt to get a unique global identifier, but
|
||||
* collisions are still possible, and they produce bizarre error messages. See
|
||||
* https://github.com/mlpack/mlpack/issues/100 for more information.
|
||||
*/
|
||||
#define PARAM_COL_IN_REQ(ID, DESC, ALIAS) \
|
||||
PARAM_COL(ID, DESC, ALIAS, true, true, true)
|
||||
@@ -743,14 +547,6 @@
|
||||
* printing macros like PRINT_PARAM_STRING() or PRINT_DATASET() or others
|
||||
* here---it will cause problems.
|
||||
* @param ALIAS An alias for the parameter (one letter).
|
||||
*
|
||||
* @bug
|
||||
* The __COUNTER__ variable is used in most cases to guarantee a unique global
|
||||
* identifier for options declared using the PARAM_*() macros. However, not all
|
||||
* compilers have this support--most notably, gcc < 4.3. In that case, the
|
||||
* __LINE__ macro is used as an attempt to get a unique global identifier, but
|
||||
* collisions are still possible, and they produce bizarre error messages. See
|
||||
* https://github.com/mlpack/mlpack/issues/100 for more information.
|
||||
*/
|
||||
#define PARAM_ROW_IN(ID, DESC, ALIAS) \
|
||||
PARAM_ROW(ID, DESC, ALIAS, false, true, true)
|
||||
@@ -771,14 +567,6 @@
|
||||
* printing macros like PRINT_PARAM_STRING() or PRINT_DATASET() or others
|
||||
* here---it will cause problems.
|
||||
* @param ALIAS An alias for the parameter (one letter).
|
||||
*
|
||||
* @bug
|
||||
* The __COUNTER__ variable is used in most cases to guarantee a unique global
|
||||
* identifier for options declared using the PARAM_*() macros. However, not all
|
||||
* compilers have this support--most notably, gcc < 4.3. In that case, the
|
||||
* __LINE__ macro is used as an attempt to get a unique global identifier, but
|
||||
* collisions are still possible, and they produce bizarre error messages. See
|
||||
* https://github.com/mlpack/mlpack/issues/100 for more information.
|
||||
*/
|
||||
#define PARAM_UCOL_IN(ID, DESC, ALIAS) \
|
||||
PARAM_UCOL(ID, DESC, ALIAS, false, true, true)
|
||||
@@ -800,14 +588,6 @@
|
||||
* printing macros like PRINT_PARAM_STRING() or PRINT_DATASET() or others
|
||||
* here---it will cause problems.
|
||||
* @param ALIAS An alias for the parameter (one letter).
|
||||
*
|
||||
* @bug
|
||||
* The __COUNTER__ variable is used in most cases to guarantee a unique global
|
||||
* identifier for options declared using the PARAM_*() macros. However, not all
|
||||
* compilers have this support--most notably, gcc < 4.3. In that case, the
|
||||
* __LINE__ macro is used as an attempt to get a unique global identifier, but
|
||||
* collisions are still possible, and they produce bizarre error messages. See
|
||||
* https://github.com/mlpack/mlpack/issues/100 for more information.
|
||||
*/
|
||||
#define PARAM_UROW_IN(ID, DESC, ALIAS) \
|
||||
PARAM_UROW(ID, DESC, ALIAS, false, true, true)
|
||||
@@ -833,14 +613,6 @@
|
||||
* printing macros like PRINT_PARAM_STRING() or PRINT_DATASET() or others
|
||||
* here---it will cause problems.
|
||||
* @param ALIAS An alias for the parameter (one letter).
|
||||
*
|
||||
* @bug
|
||||
* The __COUNTER__ variable is used in most cases to guarantee a unique global
|
||||
* identifier for options declared using the PARAM_*() macros. However, not all
|
||||
* compilers have this support--most notably, gcc < 4.3. In that case, the
|
||||
* __LINE__ macro is used as an attempt to get a unique global identifier, but
|
||||
* collisions are still possible, and they produce bizarre error messages. See
|
||||
* https://github.com/mlpack/mlpack/issues/100 for more information.
|
||||
*/
|
||||
#define PARAM_COL_OUT(ID, DESC, ALIAS) \
|
||||
PARAM_COL(ID, DESC, ALIAS, false, true, false)
|
||||
@@ -866,14 +638,6 @@
|
||||
* printing macros like PRINT_PARAM_STRING() or PRINT_DATASET() or others
|
||||
* here---it will cause problems.
|
||||
* @param ALIAS An alias for the parameter (one letter).
|
||||
*
|
||||
* @bug
|
||||
* The __COUNTER__ variable is used in most cases to guarantee a unique global
|
||||
* identifier for options declared using the PARAM_*() macros. However, not all
|
||||
* compilers have this support--most notably, gcc < 4.3. In that case, the
|
||||
* __LINE__ macro is used as an attempt to get a unique global identifier, but
|
||||
* collisions are still possible, and they produce bizarre error messages. See
|
||||
* https://github.com/mlpack/mlpack/issues/100 for more information.
|
||||
*/
|
||||
#define PARAM_ROW_OUT(ID, DESC, ALIAS) \
|
||||
PARAM_ROW(ID, DESC, ALIAS, false, true, false)
|
||||
@@ -899,14 +663,6 @@
|
||||
* printing macros like PRINT_PARAM_STRING() or PRINT_DATASET() or others
|
||||
* here---it will cause problems.
|
||||
* @param ALIAS An alias for the parameter (one letter).
|
||||
*
|
||||
* @bug
|
||||
* The __COUNTER__ variable is used in most cases to guarantee a unique global
|
||||
* identifier for options declared using the PARAM_*() macros. However, not all
|
||||
* compilers have this support--most notably, gcc < 4.3. In that case, the
|
||||
* __LINE__ macro is used as an attempt to get a unique global identifier, but
|
||||
* collisions are still possible, and they produce bizarre error messages. See
|
||||
* https://github.com/mlpack/mlpack/issues/100 for more information.
|
||||
*/
|
||||
#define PARAM_UCOL_OUT(ID, DESC, ALIAS) \
|
||||
PARAM_UCOL(ID, DESC, ALIAS, false, true, false)
|
||||
@@ -932,14 +688,6 @@
|
||||
* printing macros like PRINT_PARAM_STRING() or PRINT_DATASET() or others
|
||||
* here---it will cause problems.
|
||||
* @param ALIAS An alias for the parameter (one letter).
|
||||
*
|
||||
* @bug
|
||||
* The __COUNTER__ variable is used in most cases to guarantee a unique global
|
||||
* identifier for options declared using the PARAM_*() macros. However, not all
|
||||
* compilers have this support--most notably, gcc < 4.3. In that case, the
|
||||
* __LINE__ macro is used as an attempt to get a unique global identifier, but
|
||||
* collisions are still possible, and they produce bizarre error messages. See
|
||||
* https://github.com/mlpack/mlpack/issues/100 for more information.
|
||||
*/
|
||||
#define PARAM_UROW_OUT(ID, DESC, ALIAS) \
|
||||
PARAM_UROW(ID, DESC, ALIAS, false, true, false)
|
||||
@@ -956,17 +704,6 @@
|
||||
* printing macros like PRINT_PARAM_STRING() or PRINT_DATASET() or others
|
||||
* here---it will cause problems.
|
||||
* @param ALIAS An alias for the parameter (one letter).
|
||||
*
|
||||
* @see mlpack::IO, BINDING_USER_NAME(), BINDING_SHORT_DESC(),
|
||||
* BINDING_LONG_DESC(), BINDING_EXAMPLE() and BINDING_SEE_ALSO().
|
||||
*
|
||||
* @bug
|
||||
* The __COUNTER__ variable is used in most cases to guarantee a unique global
|
||||
* identifier for options declared using the PARAM_*() macros. However, not all
|
||||
* compilers have this support--most notably, gcc < 4.3. In that case, the
|
||||
* __LINE__ macro is used as an attempt to get a unique global identifier, but
|
||||
* collisions are still possible, and they produce bizarre error messages. See
|
||||
* https://github.com/mlpack/mlpack/issues/100 for more information.
|
||||
*/
|
||||
#define PARAM_VECTOR_IN(T, ID, DESC, ALIAS) \
|
||||
PARAM_IN(std::vector<T>, ID, DESC, ALIAS, std::vector<T>(), false)
|
||||
@@ -990,17 +727,6 @@
|
||||
* printing macros like PRINT_PARAM_STRING() or PRINT_DATASET() or others
|
||||
* here---it will cause problems.
|
||||
* @param ALIAS An alias for the parameter (one letter).
|
||||
*
|
||||
* @see mlpack::IO, BINDING_USER_NAME(), BINDING_SHORT_DESC(),
|
||||
* BINDING_LONG_DESC(), BINDING_EXAMPLE() and BINDING_SEE_ALSO().
|
||||
*
|
||||
* @bug
|
||||
* The __COUNTER__ variable is used in most cases to guarantee a unique global
|
||||
* identifier for options declared using the PARAM_*() macros. However, not all
|
||||
* compilers have this support--most notably, gcc < 4.3. In that case, the
|
||||
* __LINE__ macro is used as an attempt to get a unique global identifier, but
|
||||
* collisions are still possible, and they produce bizarre error messages. See
|
||||
* https://github.com/mlpack/mlpack/issues/100 for more information.
|
||||
*/
|
||||
#define PARAM_VECTOR_OUT(T, ID, DESC, ALIAS) \
|
||||
PARAM_OUT(std::vector<T>, ID, DESC, ALIAS, std::vector<T>(), false)
|
||||
@@ -1030,17 +756,6 @@
|
||||
* printing macros like PRINT_PARAM_STRING() or PRINT_DATASET() or others
|
||||
* here---it will cause problems.
|
||||
* @param ALIAS One-character string representing the alias of the parameter.
|
||||
*
|
||||
* @see mlpack::IO, BINDING_USER_NAME(), BINDING_SHORT_DESC(),
|
||||
* BINDING_LONG_DESC(), BINDING_EXAMPLE() and BINDING_SEE_ALSO().
|
||||
*
|
||||
* @bug
|
||||
* The __COUNTER__ variable is used in most cases to guarantee a unique global
|
||||
* identifier for options declared using the PARAM_*() macros. However, not all
|
||||
* compilers have this support--most notably, gcc < 4.3. In that case, the
|
||||
* __LINE__ macro is used as an attempt to get a unique global identifier, but
|
||||
* collisions are still possible, and they produce bizarre error messages. See
|
||||
* https://github.com/mlpack/mlpack/issues/100 for more information.
|
||||
*/
|
||||
#define TUPLE_TYPE std::tuple<mlpack::data::DatasetInfo, arma::mat>
|
||||
#define PARAM_MATRIX_AND_INFO_IN(ID, DESC, ALIAS) \
|
||||
@@ -1145,17 +860,6 @@
|
||||
* printing macros like PRINT_PARAM_STRING() or PRINT_DATASET() or others
|
||||
* here---it will cause problems.
|
||||
* @param ALIAS An alias for the parameter (one letter).
|
||||
*
|
||||
* @see mlpack::IO, BINDING_USER_NAME(), BINDING_SHORT_DESC(),
|
||||
* BINDING_LONG_DESC(), BINDING_EXAMPLE() and BINDING_SEE_ALSO().
|
||||
*
|
||||
* @bug
|
||||
* The __COUNTER__ variable is used in most cases to guarantee a unique global
|
||||
* identifier for options declared using the PARAM_*() macros. However, not all
|
||||
* compilers have this support--most notably, gcc < 4.3. In that case, the
|
||||
* __LINE__ macro is used as an attempt to get a unique global identifier, but
|
||||
* collisions are still possible, and they produce bizarre error messages. See
|
||||
* https://github.com/mlpack/mlpack/issues/100 for more information.
|
||||
*/
|
||||
#define PARAM_INT_IN_REQ(ID, DESC, ALIAS) \
|
||||
PARAM_IN(int, ID, DESC, ALIAS, 0, true)
|
||||
@@ -1170,17 +874,6 @@
|
||||
* printing macros like PRINT_PARAM_STRING() or PRINT_DATASET() or others
|
||||
* here---it will cause problems.
|
||||
* @param ALIAS An alias for the parameter (one letter).
|
||||
*
|
||||
* @see mlpack::IO, BINDING_USER_NAME(), BINDING_SHORT_DESC(),
|
||||
* BINDING_LONG_DESC(), BINDING_EXAMPLE() and BINDING_SEE_ALSO().
|
||||
*
|
||||
* @bug
|
||||
* The __COUNTER__ variable is used in most cases to guarantee a unique global
|
||||
* identifier for options declared using the PARAM_*() macros. However, not all
|
||||
* compilers have this support--most notably, gcc < 4.3. In that case, the
|
||||
* __LINE__ macro is used as an attempt to get a unique global identifier, but
|
||||
* collisions are still possible, and they produce bizarre error messages. See
|
||||
* https://github.com/mlpack/mlpack/issues/100 for more information.
|
||||
*/
|
||||
#define PARAM_DOUBLE_IN_REQ(ID, DESC, ALIAS) \
|
||||
PARAM_IN(double, ID, DESC, ALIAS, 0.0, true)
|
||||
@@ -1195,17 +888,6 @@
|
||||
* printing macros like PRINT_PARAM_STRING() or PRINT_DATASET() or others
|
||||
* here---it will cause problems.
|
||||
* @param ALIAS An alias for the parameter (one letter).
|
||||
*
|
||||
* @see mlpack::IO, BINDING_USER_NAME(), BINDING_SHORT_DESC(),
|
||||
* BINDING_LONG_DESC(), BINDING_EXAMPLE() and BINDING_SEE_ALSO().
|
||||
*
|
||||
* @bug
|
||||
* The __COUNTER__ variable is used in most cases to guarantee a unique global
|
||||
* identifier for options declared using the PARAM_*() macros. However, not all
|
||||
* compilers have this support--most notably, gcc < 4.3. In that case, the
|
||||
* __LINE__ macro is used as an attempt to get a unique global identifier, but
|
||||
* collisions are still possible, and they produce bizarre error messages. See
|
||||
* https://github.com/mlpack/mlpack/issues/100 for more information.
|
||||
*/
|
||||
#define PARAM_STRING_IN_REQ(ID, DESC, ALIAS) \
|
||||
PARAM_IN(std::string, ID, DESC, ALIAS, "", true)
|
||||
@@ -1222,17 +904,6 @@
|
||||
* printing macros like PRINT_PARAM_STRING() or PRINT_DATASET() or others
|
||||
* here---it will cause problems.
|
||||
* @param ALIAS An alias for the parameter (one letter).
|
||||
*
|
||||
* @see mlpack::IO, BINDING_USER_NAME(), BINDING_SHORT_DESC(),
|
||||
* BINDING_LONG_DESC(), BINDING_EXAMPLE() and BINDING_SEE_ALSO().
|
||||
*
|
||||
* @bug
|
||||
* The __COUNTER__ variable is used in most cases to guarantee a unique global
|
||||
* identifier for options declared using the PARAM_*() macros. However, not all
|
||||
* compilers have this support--most notably, gcc < 4.3. In that case, the
|
||||
* __LINE__ macro is used as an attempt to get a unique global identifier, but
|
||||
* collisions are still possible, and they produce bizarre error messages. See
|
||||
* https://github.com/mlpack/mlpack/issues/100 for more information.
|
||||
*/
|
||||
#define PARAM_VECTOR_IN_REQ(T, ID, DESC, ALIAS) \
|
||||
PARAM_IN(std::vector<T>, ID, DESC, ALIAS, std::vector<T>(), true);
|
||||
|
||||
@@ -45,7 +45,7 @@ inline Params::Params()
|
||||
/**
|
||||
* Return `true` if the specified parameter was given.
|
||||
*
|
||||
* @param identifier The name of the parameter in question.
|
||||
* @param key The name of the parameter in question.
|
||||
*/
|
||||
inline bool Params::Has(const std::string& key) const
|
||||
{
|
||||
|
||||
@@ -43,8 +43,10 @@
|
||||
#include <mlpack/methods/ann/layer/mean_pooling.hpp>
|
||||
#include <mlpack/methods/ann/layer/noisylinear.hpp>
|
||||
#include <mlpack/methods/ann/layer/padding.hpp>
|
||||
#include <mlpack/methods/ann/layer/parametric_relu.hpp>
|
||||
#include <mlpack/methods/ann/layer/radial_basis_function.hpp>
|
||||
#include <mlpack/methods/ann/layer/softmax.hpp>
|
||||
#include <mlpack/methods/ann/layer/softmin.hpp>
|
||||
|
||||
// Convolution modes.
|
||||
#include <mlpack/methods/ann/convolution_rules/border_modes.hpp>
|
||||
|
||||
@@ -1,88 +0,0 @@
|
||||
/**
|
||||
* @file methods/ann/layer/parametric_relu_impl.hpp
|
||||
* @author Prasanna Patil
|
||||
*
|
||||
* Definition of PReLU layer first introduced in the,
|
||||
* Kaiming He, Xiangyu Zhang, Shaoqing, Ren Jian Sun,
|
||||
* "Delving Deep into Rectifiers:
|
||||
* Surpassing Human-Level Performance on ImageNet Classification", 2014
|
||||
*
|
||||
* mlpack is free software; you may redistribute it and/or modify it under the
|
||||
* terms of the 3-clause BSD license. You should have received a copy of the
|
||||
* 3-clause BSD license along with mlpack. If not, see
|
||||
* http://www.opensource.org/licenses/BSD-3-Clause for more information.
|
||||
*/
|
||||
#ifndef MLPACK_METHODS_ANN_LAYER_PRELU_IMPL_HPP
|
||||
#define MLPACK_METHODS_ANN_LAYER_PRELU_IMPL_HPP
|
||||
|
||||
// In case it hasn't yet been included.
|
||||
#include "parametric_relu.hpp"
|
||||
|
||||
namespace mlpack {
|
||||
|
||||
template<typename InputType, typename OutputType>
|
||||
PReLUType<InputType, OutputType>::PReLUType(
|
||||
const double userAlpha) : userAlpha(userAlpha)
|
||||
{
|
||||
alpha.set_size(WeightSize(), 1);
|
||||
alpha(0) = userAlpha;
|
||||
}
|
||||
|
||||
template<typename InputType, typename OutputType>
|
||||
void PReLUType<InputType, OutputType>::SetWeights(
|
||||
typename OutputType::elem_type* weightsPtr)
|
||||
{
|
||||
alpha = arma::mat(weightsPtr, 1, 1, false, false);
|
||||
|
||||
//! Set value of alpha to the one given by user.
|
||||
// TODO: this doesn't even make any sense. is it trainable or not?
|
||||
// why is there userAlpha? is that for initialization only?
|
||||
alpha(0) = userAlpha;
|
||||
}
|
||||
|
||||
template<typename InputType, typename OutputType>
|
||||
void PReLUType<InputType, OutputType>::Forward(
|
||||
const InputType& input, OutputType& output)
|
||||
{
|
||||
// TODO: use transform()?
|
||||
output = input;
|
||||
arma::uvec negative = arma::find(input < 0);
|
||||
output(negative) = input(negative) * alpha(0);
|
||||
}
|
||||
|
||||
template<typename InputType, typename OutputType>
|
||||
void PReLUType<InputType, OutputType>::Backward(
|
||||
const InputType& input, const OutputType& gy, OutputType& g)
|
||||
{
|
||||
OutputType derivative;
|
||||
derivative.set_size(arma::size(input));
|
||||
for (size_t i = 0; i < input.n_elem; ++i)
|
||||
derivative(i) = (input(i) >= 0) ? 1 : alpha(0);
|
||||
|
||||
g = gy % derivative;
|
||||
}
|
||||
|
||||
template<typename InputType, typename OutputType>
|
||||
void PReLUType<InputType, OutputType>::Gradient(
|
||||
const InputType& input,
|
||||
const OutputType& error,
|
||||
OutputType& gradient)
|
||||
{
|
||||
OutputType zeros = arma::zeros<OutputType>(input.n_rows, input.n_cols);
|
||||
gradient(0) = arma::accu(error % arma::min(zeros, input)) / input.n_cols;
|
||||
}
|
||||
|
||||
template<typename InputType, typename OutputType>
|
||||
template<typename Archive>
|
||||
void PReLUType<InputType, OutputType>::serialize(
|
||||
Archive& ar,
|
||||
const uint32_t /* version */)
|
||||
{
|
||||
ar(cereal::base_class<Layer<InputType, OutputType>>(this));
|
||||
|
||||
ar(CEREAL_NVP(alpha));
|
||||
}
|
||||
|
||||
} // namespace mlpack
|
||||
|
||||
#endif
|
||||
@@ -1,56 +0,0 @@
|
||||
/**
|
||||
* @file methods/ann/layer/softmin_impl.hpp
|
||||
* @author Aakash Kaushik
|
||||
*
|
||||
* Implementation of the Softmin class.
|
||||
*
|
||||
* mlpack is free software; you may redistribute it and/or modify it under the
|
||||
* terms of the 3-clause BSD license. You should have received a copy of the
|
||||
* 3-clause BSD license along with mlpack. If not, see
|
||||
* http://www.opensource.org/licenses/BSD-3-Clause for more information.
|
||||
*/
|
||||
#ifndef MLPACK_METHODS_ANN_LAYER_SOFTMIN_IMPL_HPP
|
||||
#define MLPACK_METHODS_ANN_LAYER_SOFTMIN_IMPL_HPP
|
||||
|
||||
// In case it hasn't yet been included.
|
||||
#include "softmin.hpp"
|
||||
|
||||
namespace mlpack {
|
||||
|
||||
template<typename InputType, typename OutputType>
|
||||
SoftminType<InputType, OutputType>::SoftminType()
|
||||
{
|
||||
// Nothing to do here.
|
||||
}
|
||||
|
||||
template<typename InputType, typename OutputType>
|
||||
void SoftminType<InputType, OutputType>::Forward(
|
||||
const InputType& input,
|
||||
OutputType& output)
|
||||
{
|
||||
InputType softminInput = arma::exp(-(input.each_row() -
|
||||
arma::min(input, 0)));
|
||||
output = softminInput.each_row() / sum(softminInput, 0);
|
||||
}
|
||||
|
||||
template<typename InputType, typename OutputType>
|
||||
void SoftminType<InputType, OutputType>::Backward(
|
||||
const InputType& input,
|
||||
const OutputType& gy,
|
||||
OutputType& g)
|
||||
{
|
||||
g = input % (gy - arma::repmat(arma::sum(gy % input), input.n_rows, 1));
|
||||
}
|
||||
|
||||
template<typename InputType, typename OutputType>
|
||||
template<typename Archive>
|
||||
void SoftminType<InputType, OutputType>::serialize(
|
||||
Archive& ar,
|
||||
const uint32_t /* version */)
|
||||
{
|
||||
ar(cereal::base_class<Layer<InputType, OutputType>>(this));
|
||||
}
|
||||
|
||||
} // namespace mlpack
|
||||
|
||||
#endif
|
||||
+39
-19
@@ -12,8 +12,8 @@
|
||||
* 3-clause BSD license along with mlpack. If not, see
|
||||
* http://www.opensource.org/licenses/BSD-3-Clause for more information.
|
||||
*/
|
||||
#ifndef MLPACK_METHODS_ANN_LAYER_PReLU_HPP
|
||||
#define MLPACK_METHODS_ANN_LAYER_PReLU_HPP
|
||||
#ifndef MLPACK_METHODS_ANN_LAYER_PRELU_HPP
|
||||
#define MLPACK_METHODS_ANN_LAYER_PRELU_HPP
|
||||
|
||||
#include <mlpack/prereqs.hpp>
|
||||
|
||||
@@ -34,14 +34,12 @@ namespace mlpack {
|
||||
* \right.
|
||||
* @f}
|
||||
*
|
||||
* @tparam InputType The type of the layer's inputs. The layer automatically
|
||||
* cast inputs to this type (Default: arma::mat).
|
||||
* @tparam OutputType The type of the computation which also causes the output
|
||||
* to also be in this type. The type also allows the computation and weight
|
||||
* type to differ from the input type (Default: arma::mat).
|
||||
* @tparam MatType Matrix representation to accept as input and allows the
|
||||
* computation and weight type to differ from the input type
|
||||
* (Default: arma::mat).
|
||||
*/
|
||||
template<typename InputType = arma::mat, typename OutputType = arma::mat>
|
||||
class PReLUType : public Layer<InputType, OutputType>
|
||||
template<typename MatType = arma::mat>
|
||||
class PReLUType : public Layer<MatType>
|
||||
{
|
||||
public:
|
||||
/**
|
||||
@@ -57,8 +55,30 @@ class PReLUType : public Layer<InputType, OutputType>
|
||||
//! Clone the PReLUType object. This handles polymorphism correctly.
|
||||
PReLUType* Clone() const { return new PReLUType(*this); }
|
||||
|
||||
// Virtual destructor.
|
||||
virtual ~PReLUType() { }
|
||||
|
||||
//! Copy the given PReLUType.
|
||||
PReLUType(const PReLUType& other);
|
||||
//! Take ownership of the given PReLUType.
|
||||
PReLUType(PReLUType&& other);
|
||||
//! Copy the given PReLUType.
|
||||
PReLUType& operator=(const PReLUType& other);
|
||||
//! Take ownership of the given PReLUType.
|
||||
PReLUType& operator=(PReLUType&& other);
|
||||
|
||||
//! Reset the layer parameter.
|
||||
void SetWeights(typename OutputType::elem_type* weightsPtr);
|
||||
void SetWeights(typename MatType::elem_type* weightsPtr);
|
||||
|
||||
/**
|
||||
* Initialize the weight matrix of the layer.
|
||||
*
|
||||
* @param W Weight matrix to initialize.
|
||||
* @param elements Number of elements.
|
||||
*/
|
||||
void CustomInitialize(
|
||||
MatType& W,
|
||||
const size_t elements);
|
||||
|
||||
/**
|
||||
* Ordinary feed forward pass of a neural network, evaluating the function
|
||||
@@ -67,7 +87,7 @@ class PReLUType : public Layer<InputType, OutputType>
|
||||
* @param input Input data used for evaluating the specified function.
|
||||
* @param output Resulting output activation.
|
||||
*/
|
||||
void Forward(const InputType& input, OutputType& output);
|
||||
void Forward(const MatType& input, MatType& output);
|
||||
|
||||
/**
|
||||
* Ordinary feed backward pass of a neural network, calculating the function
|
||||
@@ -78,7 +98,7 @@ class PReLUType : public Layer<InputType, OutputType>
|
||||
* @param gy The backpropagated error.
|
||||
* @param g The calculated gradient.
|
||||
*/
|
||||
void Backward(const InputType& input, const OutputType& gy, OutputType& g);
|
||||
void Backward(const MatType& input, const MatType& gy, MatType& g);
|
||||
|
||||
/**
|
||||
* Calculate the gradient using the output delta and the input activation.
|
||||
@@ -87,14 +107,14 @@ class PReLUType : public Layer<InputType, OutputType>
|
||||
* @param error The calculated error.
|
||||
* @param gradient The calculated gradient.
|
||||
*/
|
||||
void Gradient(const InputType& input,
|
||||
const OutputType& error,
|
||||
OutputType& gradient);
|
||||
void Gradient(const MatType& input,
|
||||
const MatType& error,
|
||||
MatType& gradient);
|
||||
|
||||
//! Get the parameters.
|
||||
OutputType const& Parameters() const { return alpha; }
|
||||
MatType const& Parameters() const { return alpha; }
|
||||
//! Modify the parameters.
|
||||
OutputType& Parameters() { return alpha; }
|
||||
MatType& Parameters() { return alpha; }
|
||||
|
||||
//! Get the non zero gradient.
|
||||
double const& Alpha() const { return alpha(0); }
|
||||
@@ -112,7 +132,7 @@ class PReLUType : public Layer<InputType, OutputType>
|
||||
|
||||
private:
|
||||
//! Leakyness Parameter object.
|
||||
OutputType alpha;
|
||||
MatType alpha;
|
||||
|
||||
//! Leakyness Parameter given by user in the range 0 < alpha < 1.
|
||||
double userAlpha;
|
||||
@@ -121,7 +141,7 @@ class PReLUType : public Layer<InputType, OutputType>
|
||||
// Convenience typedefs.
|
||||
|
||||
// Standard PReLU layer.
|
||||
typedef PReLUType<arma::mat, arma::mat> PReLU;
|
||||
typedef PReLUType<arma::mat> PReLU;
|
||||
|
||||
} // namespace mlpack
|
||||
|
||||
@@ -0,0 +1,146 @@
|
||||
/**
|
||||
* @file methods/ann/layer/parametric_relu_impl.hpp
|
||||
* @author Prasanna Patil
|
||||
*
|
||||
* Definition of PReLU layer first introduced in the,
|
||||
* Kaiming He, Xiangyu Zhang, Shaoqing, Ren Jian Sun,
|
||||
* "Delving Deep into Rectifiers:
|
||||
* Surpassing Human-Level Performance on ImageNet Classification", 2014
|
||||
*
|
||||
* mlpack is free software; you may redistribute it and/or modify it under the
|
||||
* terms of the 3-clause BSD license. You should have received a copy of the
|
||||
* 3-clause BSD license along with mlpack. If not, see
|
||||
* http://www.opensource.org/licenses/BSD-3-Clause for more information.
|
||||
*/
|
||||
#ifndef MLPACK_METHODS_ANN_LAYER_PRELU_IMPL_HPP
|
||||
#define MLPACK_METHODS_ANN_LAYER_PRELU_IMPL_HPP
|
||||
|
||||
// In case it hasn't yet been included.
|
||||
#include "parametric_relu.hpp"
|
||||
|
||||
namespace mlpack {
|
||||
|
||||
template<typename MatType>
|
||||
PReLUType<MatType>::PReLUType(const double userAlpha) :
|
||||
Layer<MatType>(),
|
||||
userAlpha(userAlpha)
|
||||
{
|
||||
// Nothing to do here.
|
||||
}
|
||||
|
||||
template<typename MatType>
|
||||
PReLUType<MatType>::PReLUType(
|
||||
const PReLUType& other) :
|
||||
Layer<MatType>(other),
|
||||
userAlpha(other.userAlpha)
|
||||
{
|
||||
// Nothing to do here.
|
||||
}
|
||||
|
||||
template<typename MatType>
|
||||
PReLUType<MatType>::PReLUType(
|
||||
PReLUType&& other) :
|
||||
Layer<MatType>(std::move(other)),
|
||||
userAlpha(std::move(other.userAlpha))
|
||||
{
|
||||
// Nothing to do here.
|
||||
}
|
||||
|
||||
template<typename MatType>
|
||||
PReLUType<MatType>&
|
||||
PReLUType<MatType>::operator=(const PReLUType& other)
|
||||
{
|
||||
if (&other != this)
|
||||
{
|
||||
Layer<MatType>::operator=(other);
|
||||
userAlpha = other.userAlpha;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename MatType>
|
||||
PReLUType<MatType>&
|
||||
PReLUType<MatType>::operator=(PReLUType&& other)
|
||||
{
|
||||
if (&other != this)
|
||||
{
|
||||
Layer<MatType>::operator=(std::move(other));
|
||||
userAlpha = std::move(other.userAlpha);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename MatType>
|
||||
void PReLUType<MatType>::SetWeights(
|
||||
typename MatType::elem_type* weightsPtr)
|
||||
{
|
||||
MakeAlias(alpha, weightsPtr, 1, 1);
|
||||
}
|
||||
|
||||
template<typename MatType>
|
||||
void PReLUType<MatType>::CustomInitialize(
|
||||
MatType& W,
|
||||
const size_t elements)
|
||||
{
|
||||
if (elements != 1)
|
||||
{
|
||||
throw std::invalid_argument("PReLUType::CustomInitialize(): wrong "
|
||||
"elements size!");
|
||||
}
|
||||
|
||||
W(0) = userAlpha;
|
||||
}
|
||||
|
||||
template<typename MatType>
|
||||
void PReLUType<MatType>::Forward(
|
||||
const MatType& input, MatType& output)
|
||||
{
|
||||
output = input;
|
||||
if (this->training)
|
||||
{
|
||||
#pragma omp for
|
||||
for (size_t i = 0; i < input.n_elem; ++i)
|
||||
output(i) *= (input(i) >= 0) ? 1 : alpha(0);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename MatType>
|
||||
void PReLUType<MatType>::Backward(
|
||||
const MatType& input, const MatType& gy, MatType& g)
|
||||
{
|
||||
MatType derivative;
|
||||
derivative.set_size(arma::size(input));
|
||||
#pragma omp for
|
||||
for (size_t i = 0; i < input.n_elem; ++i)
|
||||
derivative(i) = (input(i) >= 0) ? 1 : alpha(0);
|
||||
|
||||
g = gy % derivative;
|
||||
}
|
||||
|
||||
template<typename MatType>
|
||||
void PReLUType<MatType>::Gradient(
|
||||
const MatType& input,
|
||||
const MatType& error,
|
||||
MatType& gradient)
|
||||
{
|
||||
MatType zeros = arma::zeros<MatType>(input.n_rows, input.n_cols);
|
||||
gradient.set_size(1, 1);
|
||||
gradient(0) = arma::accu(error % arma::min(zeros, input)) / input.n_cols;
|
||||
}
|
||||
|
||||
template<typename MatType>
|
||||
template<typename Archive>
|
||||
void PReLUType<MatType>::serialize(
|
||||
Archive& ar,
|
||||
const uint32_t /* version */)
|
||||
{
|
||||
ar(cereal::base_class<Layer<MatType>>(this));
|
||||
|
||||
ar(CEREAL_NVP(userAlpha));
|
||||
}
|
||||
|
||||
} // namespace mlpack
|
||||
|
||||
#endif
|
||||
@@ -65,8 +65,10 @@
|
||||
CEREAL_REGISTER_TYPE(mlpack::MeanPoolingType<__VA_ARGS__>); \
|
||||
CEREAL_REGISTER_TYPE(mlpack::NoisyLinearType<__VA_ARGS__>); \
|
||||
CEREAL_REGISTER_TYPE(mlpack::PaddingType<__VA_ARGS__>); \
|
||||
CEREAL_REGISTER_TYPE(mlpack::PReLUType<__VA_ARGS__>); \
|
||||
CEREAL_REGISTER_TYPE(mlpack::RBFType<__VA_ARGS__>); \
|
||||
CEREAL_REGISTER_TYPE(mlpack::SoftmaxType<__VA_ARGS__>); \
|
||||
CEREAL_REGISTER_TYPE(mlpack::SoftminType<__VA_ARGS__>); \
|
||||
|
||||
CEREAL_REGISTER_MLPACK_LAYERS(arma::mat);
|
||||
|
||||
|
||||
+19
-10
@@ -24,14 +24,11 @@ namespace mlpack {
|
||||
* a vector of K real numbers, rescaling them so that the elements of the
|
||||
* K-dimensional output vector lie in the range [0, 1] and sum to 1.
|
||||
*
|
||||
* @tparam InputType The type of the layer's inputs. The layer automatically
|
||||
* cast inputs to this type (Default: arma::mat).
|
||||
* @tparam OutputType The type of the computation which also causes the output
|
||||
* to also be in this type. The type also allows the computation and weight
|
||||
* type to differ from the input type (Default: arma::mat).
|
||||
* @tparam MatType Matrix representation to accept as input and use for
|
||||
* computation.
|
||||
*/
|
||||
template<typename InputType = arma::mat, typename OutputType = arma::mat>
|
||||
class SoftminType : public Layer<InputType, OutputType>
|
||||
template<typename MatType = arma::mat>
|
||||
class SoftminType : public Layer<MatType>
|
||||
{
|
||||
public:
|
||||
//! Create the Softmin object.
|
||||
@@ -40,6 +37,18 @@ class SoftminType : public Layer<InputType, OutputType>
|
||||
//! Clone the SoftminType object. This handles polymorphism correctly.
|
||||
SoftminType* Clone() const { return new SoftminType(*this); }
|
||||
|
||||
//! Virtual destructor.
|
||||
virtual ~SoftminType() { }
|
||||
|
||||
//! Copy the given SoftminType.
|
||||
SoftminType(const SoftminType& other);
|
||||
//! Take ownership of the given SoftminType.
|
||||
SoftminType(SoftminType&& other);
|
||||
//! Copy the given SoftminType.
|
||||
SoftminType& operator=(const SoftminType& other);
|
||||
//! Take ownership of the given SoftminType.
|
||||
SoftminType& operator=(SoftminType&& other);
|
||||
|
||||
/**
|
||||
* Ordinary feed forward pass of a neural network, evaluating the function
|
||||
* f(x) by propagating the activity forward through f.
|
||||
@@ -47,7 +56,7 @@ class SoftminType : public Layer<InputType, OutputType>
|
||||
* @param input Input data used for evaluating the specified function.
|
||||
* @param output Resulting output activation.
|
||||
*/
|
||||
void Forward(const InputType& input, OutputType& output);
|
||||
void Forward(const MatType& input, MatType& output);
|
||||
|
||||
/**
|
||||
* Ordinary feed backward pass of a neural network, calculating the function
|
||||
@@ -58,7 +67,7 @@ class SoftminType : public Layer<InputType, OutputType>
|
||||
* @param gy The backpropagated error.
|
||||
* @param g The calculated gradient.
|
||||
*/
|
||||
void Backward(const InputType& input, const OutputType& gy, OutputType& g);
|
||||
void Backward(const MatType& input, const MatType& gy, MatType& g);
|
||||
|
||||
//! Serialize the layer.
|
||||
template<typename Archive>
|
||||
@@ -68,7 +77,7 @@ class SoftminType : public Layer<InputType, OutputType>
|
||||
// Convenience typedefs.
|
||||
|
||||
// Standard Softmin layer using no regularization.
|
||||
typedef SoftminType<arma::mat, arma::mat> Softmin;
|
||||
typedef SoftminType<arma::mat> Softmin;
|
||||
|
||||
|
||||
} // namespace mlpack
|
||||
@@ -0,0 +1,90 @@
|
||||
/**
|
||||
* @file methods/ann/layer/softmin_impl.hpp
|
||||
* @author Aakash Kaushik
|
||||
*
|
||||
* Implementation of the Softmin class.
|
||||
*
|
||||
* mlpack is free software; you may redistribute it and/or modify it under the
|
||||
* terms of the 3-clause BSD license. You should have received a copy of the
|
||||
* 3-clause BSD license along with mlpack. If not, see
|
||||
* http://www.opensource.org/licenses/BSD-3-Clause for more information.
|
||||
*/
|
||||
#ifndef MLPACK_METHODS_ANN_LAYER_SOFTMIN_IMPL_HPP
|
||||
#define MLPACK_METHODS_ANN_LAYER_SOFTMIN_IMPL_HPP
|
||||
|
||||
// In case it hasn't yet been included.
|
||||
#include "softmin.hpp"
|
||||
|
||||
namespace mlpack {
|
||||
|
||||
template<typename MatType>
|
||||
SoftminType<MatType>::SoftminType()
|
||||
{
|
||||
// Nothing to do here.
|
||||
}
|
||||
|
||||
template<typename MatType>
|
||||
SoftminType<MatType>::SoftminType(const SoftminType& other) :
|
||||
Layer<MatType>(other)
|
||||
{
|
||||
// Nothing to do here.
|
||||
}
|
||||
|
||||
template<typename MatType>
|
||||
SoftminType<MatType>::SoftminType(SoftminType&& other) :
|
||||
Layer<MatType>(std::move(other))
|
||||
{
|
||||
// Nothing to do here.
|
||||
}
|
||||
|
||||
template<typename MatType>
|
||||
SoftminType<MatType>&
|
||||
SoftminType<MatType>::operator=(const SoftminType& other)
|
||||
{
|
||||
if (this != &other)
|
||||
Layer<MatType>::operator=(other);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename MatType>
|
||||
SoftminType<MatType>&
|
||||
SoftminType<MatType>::operator=(SoftminType&& other)
|
||||
{
|
||||
if (this != &other)
|
||||
Layer<MatType>::operator=(std::move(other));
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename MatType>
|
||||
void SoftminType<MatType>::Forward(
|
||||
const MatType& input,
|
||||
MatType& output)
|
||||
{
|
||||
MatType softminInput = arma::exp(-(input.each_row() -
|
||||
arma::min(input, 0)));
|
||||
output = softminInput.each_row() / sum(softminInput, 0);
|
||||
}
|
||||
|
||||
template<typename MatType>
|
||||
void SoftminType<MatType>::Backward(
|
||||
const MatType& input,
|
||||
const MatType& gy,
|
||||
MatType& g)
|
||||
{
|
||||
g = input % (gy - arma::repmat(arma::sum(gy % input), input.n_rows, 1));
|
||||
}
|
||||
|
||||
template<typename MatType>
|
||||
template<typename Archive>
|
||||
void SoftminType<MatType>::serialize(
|
||||
Archive& ar,
|
||||
const uint32_t /* version */)
|
||||
{
|
||||
ar(cereal::base_class<Layer<MatType>>(this));
|
||||
}
|
||||
|
||||
} // namespace mlpack
|
||||
|
||||
#endif
|
||||
@@ -283,6 +283,8 @@ class CFType
|
||||
};
|
||||
}; // class CFType
|
||||
|
||||
typedef CFType<> CF;
|
||||
|
||||
} // namespace mlpack
|
||||
|
||||
// Include implementation of templated functions.
|
||||
|
||||
@@ -72,6 +72,9 @@ BINDING_LONG_DESC(
|
||||
" - 'SVDCompleteIncremental' -- SVD complete incremental learning\n"
|
||||
" - 'BiasSVD' -- Bias SVD using a SGD optimizer\n"
|
||||
" - 'SVDPP' -- SVD++ using a SGD optimizer\n"
|
||||
" - 'RandSVD' -- RandomizedSVD learning\n"
|
||||
" - 'QSVD' -- QuicSVD learning\n"
|
||||
" - 'BKSVD' -- Block Krylov SVD learning\n"
|
||||
"\n\n"
|
||||
"The following neighbor search algorithms can be specified via" +
|
||||
" the " + PRINT_PARAM_STRING("neighbor_search") + " parameter:"
|
||||
@@ -196,7 +199,7 @@ void BINDING_FUNCTION(util::Params& params, util::Timers& timers)
|
||||
|
||||
RequireParamInSet<string>(params, "algorithm", { "NMF", "BatchSVD",
|
||||
"SVDIncompleteIncremental", "SVDCompleteIncremental", "RegSVD",
|
||||
"RandSVD", "BiasSVD", "SVDPP" }, true, "unknown algorithm");
|
||||
"RandSVD", "BiasSVD", "SVDPP", "QSVD", "BKSVD" }, true, "unknown algorithm");
|
||||
|
||||
ReportIgnoredParam(params, {{ "iteration_only_termination", true }},
|
||||
"min_residue");
|
||||
@@ -282,6 +285,18 @@ void BINDING_FUNCTION(util::Params& params, util::Timers& timers)
|
||||
"when max_iterations is reached");
|
||||
cf->DecompositionType() = CFModel::SVD_PLUS_PLUS;
|
||||
}
|
||||
else if (algo == "QSVD")
|
||||
{
|
||||
ReportIgnoredParam(params, "min_residue", "QSVD terminates only "
|
||||
"when max_iterations is reached");
|
||||
cf->DecompositionType() = CFModel::QUIC_SVD;
|
||||
}
|
||||
else if (algo == "BKSVD")
|
||||
{
|
||||
ReportIgnoredParam(params, "min_residue", "BKSVD terminates only "
|
||||
"when max_iterations is reached");
|
||||
cf->DecompositionType() = CFModel::BLOCK_KRYLOV_SVD;
|
||||
}
|
||||
|
||||
// Perform the factorization and do whatever the user wanted.
|
||||
const size_t neighborhood = (size_t) params.Get<int>("neighborhood");
|
||||
|
||||
@@ -170,7 +170,9 @@ class CFModel
|
||||
SVD_COMPLETE,
|
||||
SVD_INCOMPLETE,
|
||||
BIAS_SVD,
|
||||
SVD_PLUS_PLUS
|
||||
SVD_PLUS_PLUS,
|
||||
QUIC_SVD,
|
||||
BLOCK_KRYLOV_SVD
|
||||
};
|
||||
|
||||
enum NormalizationTypes
|
||||
|
||||
@@ -14,29 +14,6 @@
|
||||
|
||||
#include "cf_model.hpp"
|
||||
|
||||
#include "interpolation_policies/average_interpolation.hpp"
|
||||
#include "interpolation_policies/regression_interpolation.hpp"
|
||||
#include "interpolation_policies/similarity_interpolation.hpp"
|
||||
|
||||
#include "neighbor_search_policies/cosine_search.hpp"
|
||||
#include "neighbor_search_policies/lmetric_search.hpp"
|
||||
#include "neighbor_search_policies/pearson_search.hpp"
|
||||
|
||||
#include "decomposition_policies/batch_svd_method.hpp"
|
||||
#include "decomposition_policies/bias_svd_method.hpp"
|
||||
#include "decomposition_policies/nmf_method.hpp"
|
||||
#include "decomposition_policies/randomized_svd_method.hpp"
|
||||
#include "decomposition_policies/regularized_svd_method.hpp"
|
||||
#include "decomposition_policies/svd_complete_method.hpp"
|
||||
#include "decomposition_policies/svd_incomplete_method.hpp"
|
||||
#include "decomposition_policies/svdplusplus_method.hpp"
|
||||
|
||||
#include "normalization/no_normalization.hpp"
|
||||
#include "normalization/overall_mean_normalization.hpp"
|
||||
#include "normalization/user_mean_normalization.hpp"
|
||||
#include "normalization/item_mean_normalization.hpp"
|
||||
#include "normalization/z_score_normalization.hpp"
|
||||
|
||||
namespace mlpack {
|
||||
|
||||
inline CFModel::CFModel() :
|
||||
@@ -361,6 +338,12 @@ inline CFWrapperBase* InitializeModel(
|
||||
|
||||
case CFModel::SVD_PLUS_PLUS:
|
||||
return InitializeModelHelper<SVDPlusPlusPolicy>(normalizationType);
|
||||
|
||||
case CFModel::QUIC_SVD:
|
||||
return InitializeModelHelper<QUIC_SVDPolicy>(normalizationType);
|
||||
|
||||
case CFModel::BLOCK_KRYLOV_SVD:
|
||||
return InitializeModelHelper<BlockKrylovSVDPolicy>(normalizationType);
|
||||
}
|
||||
|
||||
// This shouldn't ever happen.
|
||||
@@ -473,6 +456,16 @@ inline void CFModel::Train(
|
||||
cf = TrainHelper(SVDPlusPlusPolicy(), normalizationType, data,
|
||||
numUsersForSimilarity, rank, maxIterations, minResidue, mit);
|
||||
break;
|
||||
|
||||
case QUIC_SVD:
|
||||
cf = TrainHelper(QUIC_SVDPolicy(), normalizationType, data,
|
||||
numUsersForSimilarity, rank, maxIterations, minResidue, mit);
|
||||
break;
|
||||
|
||||
case BLOCK_KRYLOV_SVD:
|
||||
cf = TrainHelper(BlockKrylovSVDPolicy(), normalizationType, data,
|
||||
numUsersForSimilarity, rank, maxIterations, minResidue, mit);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -555,6 +548,14 @@ void CFModel::serialize(Archive& ar, const uint32_t /* version */)
|
||||
case SVD_PLUS_PLUS:
|
||||
SerializeHelper<SVDPlusPlusPolicy>(ar, cf, normalizationType);
|
||||
break;
|
||||
|
||||
case QUIC_SVD:
|
||||
SerializeHelper<QUIC_SVDPolicy>(ar, cf, normalizationType);
|
||||
break;
|
||||
|
||||
case BLOCK_KRYLOV_SVD:
|
||||
SerializeHelper<BlockKrylovSVDPolicy>(ar, cf, normalizationType);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,173 @@
|
||||
/**
|
||||
* @file methods/cf/decomposition_policies/block_krylov_svd_method.hpp
|
||||
* @author Adarsh Santoria
|
||||
*
|
||||
* Implementation of the block krylov svd method for use in
|
||||
* Collaborative Fitlering.
|
||||
*
|
||||
* 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_CF_DECOMPOSITION_POLICIES_BLOCK_KRYLOV_SVD_METHOD_HPP
|
||||
#define MLPACK_METHODS_CF_DECOMPOSITION_POLICIES_BLOCK_KRYLOV_SVD_METHOD_HPP
|
||||
|
||||
#include <mlpack/prereqs.hpp>
|
||||
#include <mlpack/methods/block_krylov_svd/block_krylov_svd.hpp>
|
||||
|
||||
namespace mlpack {
|
||||
|
||||
/**
|
||||
* Implementation of the Block Krylov SVD policy to act as a wrapper when
|
||||
* using Block Krylov SVD for the decomposition type of CF.
|
||||
*
|
||||
* An example of how to use BlockKrylovSVDPolicy in CF is shown below:
|
||||
*
|
||||
* @code
|
||||
* extern arma::mat data; // data is a (user, item, rating) table.
|
||||
* // Users for whom recommendations are generated.
|
||||
* extern arma::Col<size_t> users;
|
||||
* arma::Mat<size_t> recommendations; // Resulting recommendations.
|
||||
*
|
||||
* CFType<BlockKrylovSVDPolicy> cf(data);
|
||||
*
|
||||
* // Generate 10 recommendations for all users.
|
||||
* cf.GetRecommendations(10, recommendations);
|
||||
* @endcode
|
||||
*/
|
||||
class BlockKrylovSVDPolicy
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Create block krylov SVD object to use for collaborative filtering.
|
||||
*/
|
||||
BlockKrylovSVDPolicy()
|
||||
{
|
||||
/* Nothing to do here */
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply Collaborative Filtering to the provided data set using the
|
||||
* block krylov SVD.
|
||||
*
|
||||
* @param * (data) Data matrix: dense matrix (coordinate lists)
|
||||
* or sparse matrix(cleaned).
|
||||
* @param cleanedData item user table in form of sparse matrix.
|
||||
* @param rank Rank parameter for matrix factorization.
|
||||
* @param * (maxIterations) Maximum number of iterations.
|
||||
* @param * (minResidue) Residue required to terminate.
|
||||
* @param * (mit) Whether to terminate only when maxIterations is reached.
|
||||
*/
|
||||
template<typename MatType>
|
||||
void Apply(const MatType& /* data */,
|
||||
const arma::sp_mat& cleanedData,
|
||||
const size_t rank,
|
||||
const size_t /* maxIterations */,
|
||||
const double /* minResidue */,
|
||||
const bool /* mit */)
|
||||
{
|
||||
arma::vec sigma;
|
||||
|
||||
// Preprocessed data converted to mat format
|
||||
arma::mat data(cleanedData);
|
||||
|
||||
// Do singular value decomposition using the block krylov SVD algorithm.
|
||||
RandomizedBlockKrylovSVD blockkrylovsvd;
|
||||
blockkrylovsvd.Apply(data, w, sigma, h, rank);
|
||||
|
||||
// Sigma matrix is multiplied to w.
|
||||
w = w * arma::diagmat(sigma);
|
||||
|
||||
// Take transpose of the matrix h as required by CF class.
|
||||
h = arma::trans(h);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return predicted rating given user ID and item ID.
|
||||
*
|
||||
* @param user User ID.
|
||||
* @param item Item ID.
|
||||
*/
|
||||
double GetRating(const size_t user, const size_t item) const
|
||||
{
|
||||
double rating = arma::as_scalar(w.row(item) * h.col(user));
|
||||
return rating;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get predicted ratings for a user.
|
||||
*
|
||||
* @param user User ID.
|
||||
* @param rating Resulting rating vector.
|
||||
*/
|
||||
void GetRatingOfUser(const size_t user, arma::vec& rating) const
|
||||
{
|
||||
rating = w * h.col(user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the neighborhood and corresponding similarities for a set of users.
|
||||
*
|
||||
* @tparam NeighborSearchPolicy The policy to perform neighbor search.
|
||||
*
|
||||
* @param users Users whose neighborhood is to be computed.
|
||||
* @param numUsersForSimilarity The number of neighbors returned for
|
||||
* each user.
|
||||
* @param neighborhood Neighbors represented by user IDs.
|
||||
* @param similarities Similarity between each user and each of its
|
||||
* neighbors.
|
||||
*/
|
||||
template<typename NeighborSearchPolicy>
|
||||
void GetNeighborhood(const arma::Col<size_t>& users,
|
||||
const size_t numUsersForSimilarity,
|
||||
arma::Mat<size_t>& neighborhood,
|
||||
arma::mat& similarities) const
|
||||
{
|
||||
// We want to avoid calculating the full rating matrix, so we will do
|
||||
// nearest neighbor search only on the H matrix, using the observation that
|
||||
// if the rating matrix X = W*H, then d(X.col(i), X.col(j)) = d(W H.col(i),
|
||||
// W H.col(j)). This can be seen as nearest neighbor search on the H
|
||||
// matrix with the Mahalanobis distance where M^{-1} = W^T W. So, we'll
|
||||
// decompose M^{-1} = L L^T (the Cholesky decomposition), and then multiply
|
||||
// H by L^T. Then we can perform nearest neighbor search.
|
||||
arma::mat l = arma::chol(w.t() * w);
|
||||
arma::mat stretchedH = l * h; // Due to the Armadillo API, l is L^T.
|
||||
|
||||
// Temporarily store feature vector of queried users.
|
||||
arma::mat query(stretchedH.n_rows, users.n_elem);
|
||||
// Select feature vectors of queried users.
|
||||
for (size_t i = 0; i < users.n_elem; ++i)
|
||||
query.col(i) = stretchedH.col(users(i));
|
||||
|
||||
NeighborSearchPolicy neighborSearch(stretchedH);
|
||||
neighborSearch.Search(
|
||||
query, numUsersForSimilarity, neighborhood, similarities);
|
||||
}
|
||||
|
||||
//! Get the Item Matrix.
|
||||
const arma::mat& W() const { return w; }
|
||||
//! Get the User Matrix.
|
||||
const arma::mat& H() const { return h; }
|
||||
|
||||
/**
|
||||
* Serialization.
|
||||
*/
|
||||
template<typename Archive>
|
||||
void serialize(Archive& ar, const uint32_t /* version */)
|
||||
{
|
||||
ar(CEREAL_NVP(w));
|
||||
ar(CEREAL_NVP(h));
|
||||
}
|
||||
|
||||
private:
|
||||
//! Item matrix.
|
||||
arma::mat w;
|
||||
//! User matrix.
|
||||
arma::mat h;
|
||||
};
|
||||
|
||||
} // namespace mlpack
|
||||
|
||||
#endif
|
||||
@@ -20,5 +20,7 @@
|
||||
#include "svd_complete_method.hpp"
|
||||
#include "svd_incomplete_method.hpp"
|
||||
#include "svdplusplus_method.hpp"
|
||||
#include "quic_svd_method.hpp"
|
||||
#include "block_krylov_svd_method.hpp"
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,173 @@
|
||||
/**
|
||||
* @file methods/cf/decomposition_policies/quic_svd_method.hpp
|
||||
* @author Adarsh Santoria
|
||||
*
|
||||
* Implementation of the quic svd method for use in
|
||||
* Collaborative Fitlering.
|
||||
*
|
||||
* 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_CF_DECOMPOSITION_POLICIES_QUIC_SVD_METHOD_HPP
|
||||
#define MLPACK_METHODS_CF_DECOMPOSITION_POLICIES_QUIC_SVD_METHOD_HPP
|
||||
|
||||
#include <mlpack/prereqs.hpp>
|
||||
#include <mlpack/methods/quic_svd/quic_svd.hpp>
|
||||
|
||||
namespace mlpack {
|
||||
|
||||
/**
|
||||
* Implementation of the QUIC-SVD policy to act as a wrapper when
|
||||
* accessing Quic SVD from within CFType.
|
||||
*
|
||||
* An example of how to use QUIC_SVDPolicy in CF is shown below:
|
||||
*
|
||||
* @code
|
||||
* extern arma::mat data; // data is a (user, item, rating) table.
|
||||
* // Users for whom recommendations are generated.
|
||||
* extern arma::Col<size_t> users;
|
||||
* arma::Mat<size_t> recommendations; // Resulting recommendations.
|
||||
*
|
||||
* CFType<QUIC_SVDPolicy> cf(data);
|
||||
*
|
||||
* // Generate 10 recommendations for all users.
|
||||
* cf.GetRecommendations(10, recommendations);
|
||||
* @endcode
|
||||
*/
|
||||
class QUIC_SVDPolicy
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Use quic SVD method to perform collaborative filtering
|
||||
*/
|
||||
QUIC_SVDPolicy()
|
||||
{
|
||||
/* Nothing to do here */
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply Collaborative Filtering to the provided data set using the
|
||||
* quic SVD.
|
||||
*
|
||||
* @param * (data) Data matrix: dense matrix (coordinate lists)
|
||||
* or sparse matrix(cleaned).
|
||||
* @param cleanedData item user table in form of sparse matrix.
|
||||
* @param * (rank) Rank parameter for matrix factorization.
|
||||
* @param * (maxIterations) Maximum number of iterations.
|
||||
* @param * (minResidue) Residue required to terminate.
|
||||
* @param * (mit) Whether to terminate only when maxIterations is reached.
|
||||
*/
|
||||
template<typename MatType>
|
||||
void Apply(const MatType& /* data */,
|
||||
const arma::sp_mat& cleanedData,
|
||||
const size_t /* rank */,
|
||||
const size_t /* maxIterations */,
|
||||
const double /* minResidue */,
|
||||
const bool /* mit */)
|
||||
{
|
||||
arma::mat sigma;
|
||||
|
||||
// Preprocessed data converted to mat format
|
||||
arma::mat data(cleanedData);
|
||||
|
||||
// Do singular value decomposition using the quic SVD algorithm.
|
||||
QUIC_SVD quicsvd;
|
||||
quicsvd.Apply(data, w, h, sigma);
|
||||
|
||||
// Sigma matrix is multiplied to w.
|
||||
w = w * sigma;
|
||||
|
||||
// Take transpose of the matrix h as required by CF class.
|
||||
h = arma::trans(h);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return predicted rating given user ID and item ID.
|
||||
*
|
||||
* @param user User ID.
|
||||
* @param item Item ID.
|
||||
*/
|
||||
double GetRating(const size_t user, const size_t item) const
|
||||
{
|
||||
double rating = arma::as_scalar(w.row(item) * h.col(user));
|
||||
return rating;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get predicted ratings for a user.
|
||||
*
|
||||
* @param user User ID.
|
||||
* @param rating Resulting rating vector.
|
||||
*/
|
||||
void GetRatingOfUser(const size_t user, arma::vec& rating) const
|
||||
{
|
||||
rating = w * h.col(user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the neighborhood and corresponding similarities for a set of users.
|
||||
*
|
||||
* @tparam NeighborSearchPolicy The policy to perform neighbor search.
|
||||
*
|
||||
* @param users Users whose neighborhood is to be computed.
|
||||
* @param numUsersForSimilarity The number of neighbors returned for
|
||||
* each user.
|
||||
* @param neighborhood Neighbors represented by user IDs.
|
||||
* @param similarities Similarity between each user and each of its
|
||||
* neighbors.
|
||||
*/
|
||||
template<typename NeighborSearchPolicy>
|
||||
void GetNeighborhood(const arma::Col<size_t>& users,
|
||||
const size_t numUsersForSimilarity,
|
||||
arma::Mat<size_t>& neighborhood,
|
||||
arma::mat& similarities) const
|
||||
{
|
||||
// We want to avoid calculating the full rating matrix, so we will do
|
||||
// nearest neighbor search only on the H matrix, using the observation that
|
||||
// if the rating matrix X = W*H, then d(X.col(i), X.col(j)) = d(W H.col(i),
|
||||
// W H.col(j)). This can be seen as nearest neighbor search on the H
|
||||
// matrix with the Mahalanobis distance where M^{-1} = W^T W. So, we'll
|
||||
// decompose M^{-1} = L L^T (the Cholesky decomposition), and then multiply
|
||||
// H by L^T. Then we can perform nearest neighbor search.
|
||||
arma::mat l = arma::chol(w.t() * w);
|
||||
arma::mat stretchedH = l * h; // Due to the Armadillo API, l is L^T.
|
||||
|
||||
// Temporarily store feature vector of queried users.
|
||||
arma::mat query(stretchedH.n_rows, users.n_elem);
|
||||
// Select feature vectors of queried users.
|
||||
for (size_t i = 0; i < users.n_elem; ++i)
|
||||
query.col(i) = stretchedH.col(users(i));
|
||||
|
||||
NeighborSearchPolicy neighborSearch(stretchedH);
|
||||
neighborSearch.Search(
|
||||
query, numUsersForSimilarity, neighborhood, similarities);
|
||||
}
|
||||
|
||||
//! Get the Item Matrix.
|
||||
const arma::mat& W() const { return w; }
|
||||
//! Get the User Matrix.
|
||||
const arma::mat& H() const { return h; }
|
||||
|
||||
/**
|
||||
* Serialization.
|
||||
*/
|
||||
template<typename Archive>
|
||||
void serialize(Archive& ar, const uint32_t /* version */)
|
||||
{
|
||||
ar(CEREAL_NVP(w));
|
||||
ar(CEREAL_NVP(h));
|
||||
}
|
||||
|
||||
private:
|
||||
//! Item matrix.
|
||||
arma::mat w;
|
||||
//! User matrix.
|
||||
arma::mat h;
|
||||
};
|
||||
|
||||
} // namespace mlpack
|
||||
|
||||
#endif
|
||||
@@ -42,21 +42,20 @@ namespace mlpack {
|
||||
* const double epsilon = 0.01; // Relative error limit of data in subspace.
|
||||
* const double delta = 0.1 // Lower error bound for Monte Carlo estimate.
|
||||
*
|
||||
* // Make a QuicSVD object.
|
||||
* QUIC_SVD qSVD();
|
||||
*
|
||||
* arma::mat u, v, sigma; // Matrices for the factors. data = u * sigma * v.t()
|
||||
*
|
||||
* // Get the factorization in the constructor.
|
||||
* QUIC_SVD(data, u, v, sigma, epsilon, delta);
|
||||
* // Use the Apply() method to get a factorization.
|
||||
* qSVD.Apply(data, u, v, sigma, epsilon, delta);
|
||||
* @endcode
|
||||
*/
|
||||
class QUIC_SVD
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor which implements the QUIC-SVD algorithm. The function calls the
|
||||
* CosineTree constructor to create a subspace basis, where the original
|
||||
* matrix's projection has minimum reconstruction error. The constructor then
|
||||
* uses the ExtractSVD() function to calculate the SVD of the original dataset
|
||||
* in that subspace.
|
||||
* Create object for the randomized SVD method.
|
||||
*
|
||||
* @param dataset Matrix for which SVD is calculated.
|
||||
* @param u First unitary matrix.
|
||||
@@ -72,6 +71,35 @@ class QUIC_SVD
|
||||
const double epsilon = 0.03,
|
||||
const double delta = 0.1);
|
||||
|
||||
/**
|
||||
* Create object for the QUIC-SVD method.
|
||||
*
|
||||
* @param epsilon Error tolerance fraction for calculated subspace.
|
||||
* @param delta Cumulative probability for Monte Carlo error lower bound.
|
||||
*/
|
||||
QUIC_SVD(const double epsilon = 0.03,
|
||||
const double delta = 0.1);
|
||||
|
||||
/**
|
||||
* The function calls the CosineTree constructor to create a subspace basis,
|
||||
* where the original matrix's projection has minimum reconstruction error.
|
||||
* The constructor then uses the ExtractSVD() function to calculate the SVD
|
||||
* of the original dataset in that subspace.
|
||||
*
|
||||
* @param dataset Matrix for which SVD is calculated.
|
||||
* @param u First unitary matrix.
|
||||
* @param v Second unitary matrix.
|
||||
* @param sigma Diagonal matrix of singular values.
|
||||
* @param epsilon Error tolerance fraction for calculated subspace.
|
||||
* @param delta Cumulative probability for Monte Carlo error lower bound.
|
||||
*/
|
||||
void Apply(const arma::mat& dataset,
|
||||
arma::mat& u,
|
||||
arma::mat& v,
|
||||
arma::mat& sigma,
|
||||
const double epsilon = 0.03,
|
||||
const double delta = 0.1);
|
||||
|
||||
/**
|
||||
* This function uses the vector subspace created using a cosine tree to
|
||||
* calculate an approximate SVD of the original matrix.
|
||||
@@ -80,11 +108,12 @@ class QUIC_SVD
|
||||
* @param v Second unitary matrix.
|
||||
* @param sigma Diagonal matrix of singular values.
|
||||
*/
|
||||
void ExtractSVD(arma::mat& u, arma::mat& v, arma::mat& sigma);
|
||||
void ExtractSVD(const arma::mat& dataset,
|
||||
arma::mat& u,
|
||||
arma::mat& v,
|
||||
arma::mat& sigma);
|
||||
|
||||
private:
|
||||
//! Matrix for which cosine tree is constructed.
|
||||
const arma::mat& dataset;
|
||||
//! Subspace basis of the input dataset.
|
||||
arma::mat basis;
|
||||
};
|
||||
|
||||
@@ -23,8 +23,25 @@ inline QUIC_SVD::QUIC_SVD(
|
||||
arma::mat& v,
|
||||
arma::mat& sigma,
|
||||
const double epsilon,
|
||||
const double delta) :
|
||||
dataset(dataset)
|
||||
const double delta)
|
||||
{
|
||||
Apply(dataset, u, v, sigma, epsilon, delta);
|
||||
}
|
||||
|
||||
inline QUIC_SVD::QUIC_SVD(
|
||||
const double epsilon,
|
||||
const double delta)
|
||||
{
|
||||
/* Nothing to do here */
|
||||
}
|
||||
|
||||
inline void QUIC_SVD::Apply(
|
||||
const arma::mat& dataset,
|
||||
arma::mat& u,
|
||||
arma::mat& v,
|
||||
arma::mat& sigma,
|
||||
const double epsilon,
|
||||
const double delta)
|
||||
{
|
||||
// Since columns are sample in the implementation, the matrix is transposed if
|
||||
// necessary for maximum speedup.
|
||||
@@ -42,10 +59,11 @@ inline QUIC_SVD::QUIC_SVD(
|
||||
|
||||
// Use the ExtractSVD algorithm mentioned in the paper to extract the SVD of
|
||||
// the original dataset in the obtained subspace.
|
||||
ExtractSVD(u, v, sigma);
|
||||
ExtractSVD(dataset, u, v, sigma);
|
||||
}
|
||||
|
||||
inline void QUIC_SVD::ExtractSVD(arma::mat& u,
|
||||
inline void QUIC_SVD::ExtractSVD(const arma::mat& dataset,
|
||||
arma::mat& u,
|
||||
arma::mat& v,
|
||||
arma::mat& sigma)
|
||||
{
|
||||
|
||||
@@ -152,83 +152,7 @@ class RandomizedSVD
|
||||
arma::vec& s,
|
||||
arma::mat& v,
|
||||
const size_t rank,
|
||||
MatType rowMean)
|
||||
{
|
||||
if (iteratedPower == 0)
|
||||
iteratedPower = rank + 2;
|
||||
|
||||
arma::mat R, Q, Qdata;
|
||||
|
||||
// Apply the centered data matrix to a random matrix, obtaining Q.
|
||||
if (data.n_cols >= data.n_rows)
|
||||
{
|
||||
R = arma::randn<arma::mat>(data.n_rows, iteratedPower);
|
||||
Q = (data.t() * R) - arma::repmat(arma::trans(R.t() * rowMean),
|
||||
data.n_cols, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
R = arma::randn<arma::mat>(data.n_cols, iteratedPower);
|
||||
Q = (data * R) - (rowMean * (arma::ones(1, data.n_cols) * R));
|
||||
}
|
||||
|
||||
// Form a matrix Q whose columns constitute a
|
||||
// well-conditioned basis for the columns of the earlier Q.
|
||||
if (maxIterations == 0)
|
||||
{
|
||||
arma::qr_econ(Q, v, Q);
|
||||
}
|
||||
else
|
||||
{
|
||||
arma::lu(Q, v, Q);
|
||||
}
|
||||
|
||||
// Perform normalized power iterations.
|
||||
for (size_t i = 0; i < maxIterations; ++i)
|
||||
{
|
||||
if (data.n_cols >= data.n_rows)
|
||||
{
|
||||
Q = (data * Q) - rowMean * (arma::ones(1, data.n_cols) * Q);
|
||||
arma::lu(Q, v, Q);
|
||||
Q = (data.t() * Q) - arma::repmat(rowMean.t() * Q, data.n_cols, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
Q = (data.t() * Q) - arma::repmat(rowMean.t() * Q, data.n_cols, 1);
|
||||
arma::lu(Q, v, Q);
|
||||
Q = (data * Q) - (rowMean * (arma::ones(1, data.n_cols) * Q));
|
||||
}
|
||||
|
||||
// Computing the LU decomposition is more efficient than computing the QR
|
||||
// decomposition, so we only use it in the last iteration, a pivoted QR
|
||||
// decomposition which renormalizes Q, ensuring that the columns of Q are
|
||||
// orthonormal.
|
||||
if (i < (maxIterations - 1))
|
||||
{
|
||||
arma::lu(Q, v, Q);
|
||||
}
|
||||
else
|
||||
{
|
||||
arma::qr_econ(Q, v, Q);
|
||||
}
|
||||
}
|
||||
|
||||
// Do economical singular value decomposition and compute only the
|
||||
// approximations of the left singular vectors by using the centered data
|
||||
// applied to Q.
|
||||
if (data.n_cols >= data.n_rows)
|
||||
{
|
||||
Qdata = (data * Q) - rowMean * (arma::ones(1, data.n_cols) * Q);
|
||||
arma::svd_econ(u, s, v, Qdata);
|
||||
v = Q * v;
|
||||
}
|
||||
else
|
||||
{
|
||||
Qdata = (Q.t() * data) - arma::repmat(Q.t() * rowMean, 1, data.n_cols);
|
||||
arma::svd_econ(u, s, v, Qdata);
|
||||
u = Q * u;
|
||||
}
|
||||
}
|
||||
MatType rowMean);
|
||||
|
||||
//! Get the size of the normalized power iterations.
|
||||
size_t IteratedPower() const { return iteratedPower; }
|
||||
|
||||
@@ -51,7 +51,6 @@ inline RandomizedSVD::RandomizedSVD(
|
||||
/* Nothing to do here */
|
||||
}
|
||||
|
||||
|
||||
inline void RandomizedSVD::Apply(const arma::sp_mat& data,
|
||||
arma::mat& u,
|
||||
arma::vec& s,
|
||||
@@ -76,6 +75,90 @@ inline void RandomizedSVD::Apply(const arma::mat& data,
|
||||
Apply(data, u, s, v, rank, rowMean);
|
||||
}
|
||||
|
||||
template<typename MatType>
|
||||
inline void RandomizedSVD::Apply(const MatType& data,
|
||||
arma::mat& u,
|
||||
arma::vec& s,
|
||||
arma::mat& v,
|
||||
const size_t rank,
|
||||
MatType rowMean)
|
||||
{
|
||||
if (iteratedPower == 0)
|
||||
iteratedPower = rank + 2;
|
||||
|
||||
arma::mat R, Q, Qdata;
|
||||
|
||||
// Apply the centered data matrix to a random matrix, obtaining Q.
|
||||
if (data.n_cols >= data.n_rows)
|
||||
{
|
||||
R = arma::randn<arma::mat>(data.n_rows, iteratedPower);
|
||||
Q = (data.t() * R) - arma::repmat(arma::trans(R.t() * rowMean),
|
||||
data.n_cols, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
R = arma::randn<arma::mat>(data.n_cols, iteratedPower);
|
||||
Q = (data * R) - (rowMean * (arma::ones(1, data.n_cols) * R));
|
||||
}
|
||||
|
||||
// Form a matrix Q whose columns constitute a
|
||||
// well-conditioned basis for the columns of the earlier Q.
|
||||
if (maxIterations == 0)
|
||||
{
|
||||
arma::qr_econ(Q, v, Q);
|
||||
}
|
||||
else
|
||||
{
|
||||
arma::lu(Q, v, Q);
|
||||
}
|
||||
|
||||
// Perform normalized power iterations.
|
||||
for (size_t i = 0; i < maxIterations; ++i)
|
||||
{
|
||||
if (data.n_cols >= data.n_rows)
|
||||
{
|
||||
Q = (data * Q) - rowMean * (arma::ones(1, data.n_cols) * Q);
|
||||
arma::lu(Q, v, Q);
|
||||
Q = (data.t() * Q) - arma::repmat(rowMean.t() * Q, data.n_cols, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
Q = (data.t() * Q) - arma::repmat(rowMean.t() * Q, data.n_cols, 1);
|
||||
arma::lu(Q, v, Q);
|
||||
Q = (data * Q) - (rowMean * (arma::ones(1, data.n_cols) * Q));
|
||||
}
|
||||
|
||||
// Computing the LU decomposition is more efficient than computing the QR
|
||||
// decomposition, so we only use it in the last iteration, a pivoted QR
|
||||
// decomposition which renormalizes Q, ensuring that the columns of Q are
|
||||
// orthonormal.
|
||||
if (i < (maxIterations - 1))
|
||||
{
|
||||
arma::lu(Q, v, Q);
|
||||
}
|
||||
else
|
||||
{
|
||||
arma::qr_econ(Q, v, Q);
|
||||
}
|
||||
}
|
||||
|
||||
// Do economical singular value decomposition and compute only the
|
||||
// approximations of the left singular vectors by using the centered data
|
||||
// applied to Q.
|
||||
if (data.n_cols >= data.n_rows)
|
||||
{
|
||||
Qdata = (data * Q) - rowMean * (arma::ones(1, data.n_cols) * Q);
|
||||
arma::svd_econ(u, s, v, Qdata);
|
||||
v = Q * v;
|
||||
}
|
||||
else
|
||||
{
|
||||
Qdata = (Q.t() * data) - arma::repmat(Q.t() * rowMean, 1, data.n_cols);
|
||||
arma::svd_econ(u, s, v, Qdata);
|
||||
u = Q * u;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace mlpack
|
||||
|
||||
#endif
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
namespace mlpack {
|
||||
|
||||
/**
|
||||
* SVD++ is a matrix decomposition tenique used in collaborative filtering.
|
||||
* SVD++ is a matrix decomposition technique used in collaborative filtering.
|
||||
* SVD++ is similar to BiasSVD, but it is a more expressive model because
|
||||
* SVD++ also models implicit feedback. SVD++ outputs user/item latent
|
||||
* vectors, user/item bias, and item vectors with regard to implicit feedback.
|
||||
|
||||
@@ -0,0 +1,227 @@
|
||||
/**
|
||||
* @file tests/ann/layer/concat.cpp
|
||||
* @author Marcus Edel
|
||||
* @author Praveen Ch
|
||||
*
|
||||
* Tests the ann layer modules.
|
||||
*
|
||||
* 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 <mlpack/methods/ann.hpp>
|
||||
|
||||
#include "../../test_catch_tools.hpp"
|
||||
#include "../../catch.hpp"
|
||||
#include "../../serialization.hpp"
|
||||
#include "../ann_test_tools.hpp"
|
||||
|
||||
using namespace mlpack;
|
||||
|
||||
/**
|
||||
* Simple concat module test.
|
||||
*/
|
||||
TEST_CASE("SimpleConcatLayerTest", "[ANNLayerTest]")
|
||||
{
|
||||
arma::mat output, input, delta, error;
|
||||
|
||||
Linear* moduleA = new Linear(10);
|
||||
moduleA->InputDimensions() = std::vector<size_t>({ 10 });
|
||||
moduleA->ComputeOutputDimensions();
|
||||
arma::mat weightsA(moduleA->WeightSize(), 1);
|
||||
moduleA->SetWeights((double*) weightsA.memptr());
|
||||
moduleA->Parameters().randu();
|
||||
|
||||
Linear* moduleB = new Linear(10);
|
||||
moduleB->InputDimensions() = std::vector<size_t>({ 10 });
|
||||
moduleB->ComputeOutputDimensions();
|
||||
arma::mat weightsB(moduleB->WeightSize(), 1);
|
||||
moduleB->SetWeights((double*) weightsB.memptr());
|
||||
moduleB->Parameters().randu();
|
||||
|
||||
Concat module;
|
||||
module.Add(moduleA);
|
||||
module.Add(moduleB);
|
||||
module.InputDimensions() = std::vector<size_t>({ 10 });
|
||||
module.ComputeOutputDimensions();
|
||||
|
||||
// Test the Forward function.
|
||||
input = arma::zeros(10, 1);
|
||||
output.set_size(module.OutputSize(), 1);
|
||||
module.Forward(input, output);
|
||||
|
||||
const double sumModuleA = arma::accu(
|
||||
moduleA->Parameters().submat(
|
||||
100, 0, moduleA->Parameters().n_elem - 1, 0));
|
||||
const double sumModuleB = arma::accu(
|
||||
moduleB->Parameters().submat(
|
||||
100, 0, moduleB->Parameters().n_elem - 1, 0));
|
||||
REQUIRE(sumModuleA + sumModuleB ==
|
||||
Approx(arma::accu(output.col(0))).epsilon(1e-5));
|
||||
|
||||
// Test the Backward function.
|
||||
error = arma::zeros(20, 1);
|
||||
delta.set_size(input.n_rows, input.n_cols);
|
||||
module.Backward(input, error, delta);
|
||||
REQUIRE(arma::accu(delta) == 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test to check Concat layer along different axes.
|
||||
*/
|
||||
TEST_CASE("ConcatAlongAxisTest", "[ANNLayerTest]")
|
||||
{
|
||||
arma::mat output, input, error, outputA, outputB;
|
||||
size_t inputWidth = 4, inputHeight = 4, inputChannel = 2;
|
||||
size_t outputWidth, outputHeight, outputChannel = 2;
|
||||
size_t kW = 3, kH = 3;
|
||||
size_t batch = 1;
|
||||
|
||||
// Using Convolution<> layer as inout to Concat<> layer.
|
||||
// Compute the output shape of convolution layer.
|
||||
outputWidth = (inputWidth - kW) + 1;
|
||||
outputHeight = (inputHeight - kH) + 1;
|
||||
|
||||
input = arma::ones(inputWidth * inputHeight * inputChannel, batch);
|
||||
|
||||
Convolution* moduleA = new Convolution(outputChannel, kW, kH, 1, 1, 0, 0);
|
||||
Convolution* moduleB = new Convolution(outputChannel, kW, kH, 1, 1, 0, 0);
|
||||
|
||||
moduleA->InputDimensions() = std::vector<size_t>({ inputWidth, inputHeight });
|
||||
moduleA->ComputeOutputDimensions();
|
||||
arma::mat weightsA(moduleA->WeightSize(), 1);
|
||||
moduleA->SetWeights((double*) weightsA.memptr());
|
||||
moduleA->Parameters().randu();
|
||||
|
||||
moduleB->InputDimensions() = std::vector<size_t>({ inputWidth, inputHeight });
|
||||
moduleB->ComputeOutputDimensions();
|
||||
arma::mat weightsB(moduleB->WeightSize(), 1);
|
||||
moduleB->SetWeights((double*) weightsB.memptr());
|
||||
moduleB->Parameters().randu();
|
||||
|
||||
// Compute output of each layer.
|
||||
outputA.set_size(moduleA->OutputSize(), 1);
|
||||
outputB.set_size(moduleB->OutputSize(), 1);
|
||||
moduleA->Forward(input, outputA);
|
||||
moduleB->Forward(input, outputB);
|
||||
|
||||
arma::cube A(outputA.memptr(), outputWidth, outputHeight, outputChannel);
|
||||
arma::cube B(outputB.memptr(), outputWidth, outputHeight, outputChannel);
|
||||
|
||||
error = arma::ones(outputWidth * outputHeight * outputChannel * 2, 1);
|
||||
|
||||
for (size_t axis = 0; axis < 3; ++axis)
|
||||
{
|
||||
size_t x = 1, y = 1, z = 1;
|
||||
arma::cube calculatedOut;
|
||||
if (axis == 0)
|
||||
{
|
||||
calculatedOut.set_size(2 * outputWidth, outputHeight, outputChannel);
|
||||
for (size_t i = 0; i < A.n_slices; ++i)
|
||||
{
|
||||
arma::mat aMat = A.slice(i);
|
||||
arma::mat bMat = B.slice(i);
|
||||
calculatedOut.slice(i) = arma::join_cols(aMat, bMat);
|
||||
}
|
||||
x = 2;
|
||||
}
|
||||
if (axis == 1)
|
||||
{
|
||||
calculatedOut.set_size(outputWidth, 2 * outputHeight, outputChannel);
|
||||
for (size_t i = 0; i < A.n_slices; ++i)
|
||||
{
|
||||
arma::mat aMat = A.slice(i);
|
||||
arma::mat bMat = B.slice(i);
|
||||
calculatedOut.slice(i) = arma::join_rows(aMat, bMat);
|
||||
}
|
||||
y = 2;
|
||||
}
|
||||
if (axis == 2)
|
||||
{
|
||||
calculatedOut = arma::join_slices(A, B);
|
||||
z = 2;
|
||||
}
|
||||
|
||||
// Compute output of Concat<> layer.
|
||||
Concat module(axis);
|
||||
module.Add(moduleA);
|
||||
module.Add(moduleB);
|
||||
module.InputDimensions() = std::vector<size_t>({ inputWidth, inputHeight });
|
||||
module.ComputeOutputDimensions();
|
||||
output.set_size(module.OutputSize(), 1);
|
||||
module.Forward(input, output);
|
||||
arma::cube concatOut(output.memptr(), x * outputWidth,
|
||||
y * outputHeight, z * outputChannel);
|
||||
|
||||
// Verify if the output reshaped to cubes are similar.
|
||||
CheckMatrices(concatOut, calculatedOut, 1e-12);
|
||||
|
||||
// Ensure that the child layers don't get deleted when `module` is
|
||||
// deallocated.
|
||||
module.Network().clear();
|
||||
}
|
||||
|
||||
delete moduleA;
|
||||
delete moduleB;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that the function that can access the axis parameter of the
|
||||
* Concat layer works.
|
||||
*/
|
||||
TEST_CASE("ConcatLayerParametersTest", "[ANNLayerTest]")
|
||||
{
|
||||
Concat layer(2);
|
||||
|
||||
// Make sure we can get the parameters successfully.
|
||||
REQUIRE(layer.Axis() == 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Concat layer numerical gradient test.
|
||||
*/
|
||||
TEST_CASE("GradientConcatLayerTest", "[ANNLayerTest]")
|
||||
{
|
||||
// Concat function gradient instantiation.
|
||||
struct GradientFunction
|
||||
{
|
||||
GradientFunction() :
|
||||
input(arma::randu(10, 1)),
|
||||
target(arma::mat("0"))
|
||||
{
|
||||
model = new FFN<NegativeLogLikelihood, NguyenWidrowInitialization>();
|
||||
model->ResetData(input, target);
|
||||
model->Add<Linear>(10);
|
||||
|
||||
concat = new Concat();
|
||||
concat->Add<Linear>(5);
|
||||
concat->Add<Linear>(5);
|
||||
model->Add(concat);
|
||||
model->Add<Linear>(2);
|
||||
|
||||
model->Add<LogSoftMax>();
|
||||
}
|
||||
|
||||
~GradientFunction()
|
||||
{
|
||||
delete model;
|
||||
}
|
||||
|
||||
double Gradient(arma::mat& gradient) const
|
||||
{
|
||||
double error = model->Evaluate(model->Parameters(), 0, 1);
|
||||
model->Gradient(model->Parameters(), 0, gradient, 1);
|
||||
return error;
|
||||
}
|
||||
|
||||
arma::mat& Parameters() { return model->Parameters(); }
|
||||
|
||||
FFN<NegativeLogLikelihood, NguyenWidrowInitialization>* model;
|
||||
Concat* concat;
|
||||
arma::mat input, target;
|
||||
} function;
|
||||
|
||||
REQUIRE(CheckGradient(function) <= 1e-4);
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
/**
|
||||
* @file tests/ann/layer/concatenate.cpp
|
||||
* @author Marcus Edel
|
||||
* @author Praveen Ch
|
||||
*
|
||||
* Tests the ann layer modules.
|
||||
*
|
||||
* 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 <mlpack/methods/ann.hpp>
|
||||
|
||||
#include "../../test_catch_tools.hpp"
|
||||
#include "../../catch.hpp"
|
||||
#include "../../serialization.hpp"
|
||||
#include "../ann_test_tools.hpp"
|
||||
|
||||
using namespace mlpack;
|
||||
|
||||
|
||||
/**
|
||||
* Simple concatenate module test.
|
||||
*/
|
||||
TEST_CASE("SimpleConcatenateLayerTest", "[ANNLayerTest]")
|
||||
{
|
||||
arma::mat input = arma::ones(5, 1);
|
||||
arma::mat output, delta;
|
||||
|
||||
Concatenate module;
|
||||
module.Concat() = arma::ones(5, 1) * 0.5;
|
||||
module.InputDimensions() = std::vector<size_t>({ 5 });
|
||||
module.ComputeOutputDimensions();
|
||||
|
||||
// Test the Forward function.
|
||||
output.set_size(module.OutputSize(), 1);
|
||||
module.Forward(input, output);
|
||||
|
||||
REQUIRE(arma::accu(output) == 7.5);
|
||||
|
||||
// Test the Backward function.
|
||||
delta.set_size(5, 1);
|
||||
module.Backward(input, output, delta);
|
||||
REQUIRE(arma::accu(delta) == 5);
|
||||
}
|
||||
|
||||
/**
|
||||
* Concatenate layer numerical gradient test.
|
||||
*/
|
||||
TEST_CASE("GradientConcatenateLayerTest", "[ANNLayerTest]")
|
||||
{
|
||||
// Concatenate function gradient instantiation.
|
||||
struct GradientFunction
|
||||
{
|
||||
GradientFunction() :
|
||||
input(arma::randu(10, 1)),
|
||||
target(arma::mat("0"))
|
||||
{
|
||||
model = new FFN<NegativeLogLikelihood, NguyenWidrowInitialization>();
|
||||
model->ResetData(input, target);
|
||||
model->Add<Linear>(5);
|
||||
|
||||
arma::mat concat = arma::ones(5, 1);
|
||||
// concatenate = new Concatenate();
|
||||
// concatenate->Concat() = concat;
|
||||
// model->Add(concatenate);
|
||||
model->Add<Concatenate>(concat);
|
||||
|
||||
model->Add<Linear>(5);
|
||||
model->Add<LogSoftMax>();
|
||||
}
|
||||
|
||||
~GradientFunction()
|
||||
{
|
||||
delete model;
|
||||
}
|
||||
|
||||
double Gradient(arma::mat& gradient) const
|
||||
{
|
||||
double error = model->Evaluate(model->Parameters(), 0, 1);
|
||||
model->Gradient(model->Parameters(), 0, gradient, 1);
|
||||
return error;
|
||||
}
|
||||
|
||||
arma::mat& Parameters() { return model->Parameters(); }
|
||||
|
||||
FFN<NegativeLogLikelihood, NguyenWidrowInitialization>* model;
|
||||
Concatenate* concatenate;
|
||||
arma::mat input, target;
|
||||
} function;
|
||||
|
||||
REQUIRE(CheckGradient(function) <= 1e-4);
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
/**
|
||||
* @file tests/ann/layer/parametric_relu.cpp
|
||||
* @author Adarsh Santoria
|
||||
*
|
||||
* Tests the parametric relu layer modules.
|
||||
*
|
||||
* 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 <mlpack/methods/ann.hpp>
|
||||
|
||||
#include "../../test_catch_tools.hpp"
|
||||
#include "../../catch.hpp"
|
||||
#include "../../serialization.hpp"
|
||||
#include "../ann_test_tools.hpp"
|
||||
|
||||
using namespace mlpack;
|
||||
|
||||
/**
|
||||
* PReLU FORWARD Test.
|
||||
*/
|
||||
TEST_CASE("PReLUFORWARDTest", "[ANNLayerTest]")
|
||||
{
|
||||
arma::mat input = {{0.5, 1.2, 3.1},
|
||||
{-2.2, -1.5, 0.8},
|
||||
{5.5, -4.7, 2.1},
|
||||
{0.2, 0.1, -0.5}};
|
||||
PReLU module(0.01);
|
||||
module.Training() = true;
|
||||
arma::mat moduleParams(module.WeightSize(), 1);
|
||||
module.CustomInitialize(moduleParams, module.WeightSize());
|
||||
module.SetWeights((double*) moduleParams.memptr());
|
||||
arma::mat predOutput;
|
||||
module.Forward(input, predOutput);
|
||||
arma::mat actualOutput = {{0.5, 1.2, 3.1},
|
||||
{-0.022, -0.015, 0.8},
|
||||
{5.5, -0.047, 2.1},
|
||||
{0.2, 0.1, -0.005}};
|
||||
REQUIRE(arma::accu(arma::abs(actualOutput - predOutput)) ==
|
||||
Approx(0.0).margin(1e-4));
|
||||
}
|
||||
|
||||
/**
|
||||
* PReLU BACKWARD Test.
|
||||
*/
|
||||
TEST_CASE("PReLUBACKWARDTest", "[ANNLayerTest]")
|
||||
{
|
||||
arma::mat input = {{0.5, 1.2, 3.1},
|
||||
{-2.2, -1.5, 0.8},
|
||||
{5.5, -4.7, 2.1},
|
||||
{0.2, 0.1, -0.5}};
|
||||
PReLU module(0.01);
|
||||
arma::mat moduleParams(module.WeightSize(), 1);
|
||||
module.CustomInitialize(moduleParams, module.WeightSize());
|
||||
module.SetWeights((double*) moduleParams.memptr());
|
||||
arma::mat gy = {{0.2, -0.5, 0.8},
|
||||
{1.5, -0.6, 0.1},
|
||||
{-0.3, 0.2, -0.5},
|
||||
{0.1, -0.1, 0.3}};
|
||||
arma::mat predG;
|
||||
module.Backward(input, gy, predG);
|
||||
arma::mat actualG = {{0.2, -0.5, 0.8},
|
||||
{0.015, -0.006, 0.1},
|
||||
{-0.3, 0.002, -0.5},
|
||||
{0.1, -0.1, 0.0030}};
|
||||
|
||||
REQUIRE(arma::accu(arma::abs(actualG - predG)) ==
|
||||
Approx(0.0).margin(1e-4));
|
||||
}
|
||||
|
||||
/**
|
||||
* PReLU GRADIENT Test.
|
||||
*/
|
||||
TEST_CASE("PReLUGRADIENTTest", "[ANNLayerTest]")
|
||||
{
|
||||
arma::mat input = {{0.5, 1.2, 3.1},
|
||||
{-2.2, -1.5, 0.8},
|
||||
{5.5, -4.7, 2.1},
|
||||
{0.2, 0.1, -0.5}};
|
||||
PReLU module(0.01);
|
||||
arma::mat moduleParams(module.WeightSize(), 1);
|
||||
module.CustomInitialize(moduleParams, module.WeightSize());
|
||||
module.SetWeights((double*) moduleParams.memptr());
|
||||
arma::mat error = {{0.2, -0.5, 0.8},
|
||||
{-0.015, -0.006, 0.001},
|
||||
{-0.3, 0.002, -0.005},
|
||||
{0.1, -0.1, 0.0035}};
|
||||
arma::mat predGradient;
|
||||
module.Gradient(input, error, predGradient);
|
||||
|
||||
REQUIRE(0.0103 - arma::accu(predGradient) ==
|
||||
Approx(0.0).margin(1e-4));
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/**
|
||||
* @file tests/ann/layer/softmin.cpp
|
||||
* @author Aditya Raj
|
||||
*
|
||||
* Tests the ann layer modules.
|
||||
*
|
||||
* 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 <mlpack/methods/ann.hpp>
|
||||
|
||||
#include "../../test_catch_tools.hpp"
|
||||
#include "../../catch.hpp"
|
||||
#include "../../serialization.hpp"
|
||||
#include "../ann_test_tools.hpp"
|
||||
|
||||
using namespace mlpack;
|
||||
using namespace std;
|
||||
|
||||
/**
|
||||
* Simple Softmin module test.
|
||||
*/
|
||||
TEST_CASE("SimpleSoftminLayerTest", "[ANNLayerTest]")
|
||||
{
|
||||
arma::mat input, output, gy, g;
|
||||
Softmin module;
|
||||
|
||||
// Test the forward function.
|
||||
input = {{0.0, 0.1, 0.2},
|
||||
{1.0, 1.1, 1.2},
|
||||
{2.0, 2.1, 2.2},
|
||||
{2.9, 2.8, 2.5}};
|
||||
arma::mat actualOutput = {{0.641750, 0.636772, 0.623646},
|
||||
{0.236086, 0.234255, 0.229426},
|
||||
{0.086851, 0.086177, 0.084401},
|
||||
{0.035311, 0.042794, 0.062526}};
|
||||
|
||||
module.Forward(input, output);
|
||||
REQUIRE(arma::accu(arma::abs(actualOutput - output)) ==
|
||||
Approx(0.0).margin(1e-4));
|
||||
|
||||
// Test the backward function.
|
||||
gy = arma::zeros(input.n_rows, input.n_cols);
|
||||
gy(1) = 1;
|
||||
module.Backward(output, gy, g);
|
||||
arma::mat calculatedGradient = {{-0.1515, 0, 0},
|
||||
{0.1803, 0, 0},
|
||||
{-0.0205, 0, 0},
|
||||
{-0.0083, 0, 0}};
|
||||
|
||||
REQUIRE(arma::accu(arma::abs(calculatedGradient - g)) ==
|
||||
Approx(0.0).margin(1e-04));
|
||||
|
||||
}
|
||||
@@ -22,6 +22,8 @@
|
||||
#include "layer/alpha_dropout.cpp"
|
||||
#include "layer/batch_norm.cpp"
|
||||
#include "layer/convolution.cpp"
|
||||
#include "layer/concat.cpp"
|
||||
#include "layer/concatenate.cpp"
|
||||
#include "layer/dropout.cpp"
|
||||
#include "layer/grouped_convolution.cpp"
|
||||
#include "layer/identity.cpp"
|
||||
@@ -31,4 +33,6 @@
|
||||
#include "layer/max_pooling.cpp"
|
||||
#include "layer/mean_pooling.cpp"
|
||||
#include "layer/padding.cpp"
|
||||
#include "layer/parametric_relu.cpp"
|
||||
#include "layer/softmax.cpp"
|
||||
#include "layer/softmin.cpp"
|
||||
|
||||
@@ -1251,3 +1251,24 @@ TEST_CASE("NegativeLogLikelihoodLossTest", "[LossFunctionsTest]")
|
||||
REQUIRE(output.n_cols == input.n_cols);
|
||||
CheckMatrices(output, expectedOutput, 0.1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Jacobian negative log likelihood module test.
|
||||
*/
|
||||
TEST_CASE("JacobianNegativeLogLikelihoodLayerTest", "[LossFunctionsTest]")
|
||||
{
|
||||
for (size_t i = 0; i < 5; ++i)
|
||||
{
|
||||
NegativeLogLikelihood module;
|
||||
const size_t inputElements = RandInt(5, 100);
|
||||
arma::mat input;
|
||||
RandomInitialization init(0, 1);
|
||||
init.Initialize(input, inputElements, 1);
|
||||
|
||||
arma::mat target(1, 1);
|
||||
target(0) = RandInt(0, inputElements - 2);
|
||||
|
||||
double error = JacobianPerformanceTest(module, input, target);
|
||||
REQUIRE(error <= 1e-5);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,79 +87,6 @@ void CheckHardTanHDerivativeCorrect(const arma::colvec input,
|
||||
}
|
||||
}*/
|
||||
|
||||
/**
|
||||
* Implementation of the PReLU activation function test. The function
|
||||
* is implemented as PReLU layer in the file parametric_relu.hpp.
|
||||
*
|
||||
* @param input Input data used for evaluating the PReLU activation
|
||||
* function.
|
||||
* @param target Target data used to evaluate the PReLU activation.
|
||||
*
|
||||
void CheckPReLUActivationCorrect(const arma::colvec input,
|
||||
const arma::colvec target)
|
||||
{
|
||||
PReLU<> prelu;
|
||||
|
||||
// Test the activation function using the entire vector as input.
|
||||
arma::colvec activations;
|
||||
prelu.Forward(input, activations);
|
||||
for (size_t i = 0; i < activations.n_elem; ++i)
|
||||
{
|
||||
REQUIRE(activations.at(i) == Approx(target.at(i)).epsilon(1e-5));
|
||||
}
|
||||
}*/
|
||||
|
||||
/**
|
||||
* Implementation of the PReLU activation function derivative test.
|
||||
* The function is implemented as PReLU layer in the file
|
||||
* parametric_relu.hpp
|
||||
*
|
||||
* @param input Input data used for evaluating the PReLU activation
|
||||
* function.
|
||||
* @param target Target data used to evaluate the PReLU activation.
|
||||
*
|
||||
void CheckPReLUDerivativeCorrect(const arma::colvec input,
|
||||
const arma::colvec target)
|
||||
{
|
||||
PReLU<> prelu;
|
||||
|
||||
// Test the calculation of the derivatives using the entire vector as input.
|
||||
arma::colvec derivatives;
|
||||
|
||||
// This error vector will be set to 1 to get the derivatives.
|
||||
arma::colvec error = arma::ones<arma::colvec>(input.n_elem);
|
||||
prelu.Backward(input, error, derivatives);
|
||||
for (size_t i = 0; i < derivatives.n_elem; ++i)
|
||||
{
|
||||
REQUIRE(derivatives.at(i) == Approx(target.at(i)).epsilon(1e-5));
|
||||
}
|
||||
}*/
|
||||
|
||||
/**
|
||||
* Implementation of the PReLU activation function gradient test.
|
||||
* The function is implemented as PReLU layer in the file
|
||||
* parametric_relu.hpp
|
||||
*
|
||||
* @param input Input data used for evaluating the PReLU activation
|
||||
* function.
|
||||
* @param target Target data used to evaluate the PReLU gradient.
|
||||
*
|
||||
void CheckPReLUGradientCorrect(const arma::colvec input,
|
||||
const arma::colvec target)
|
||||
{
|
||||
PReLU<> prelu;
|
||||
|
||||
// Test the calculation of the derivatives using the entire vector as input.
|
||||
arma::colvec gradient;
|
||||
|
||||
// This error vector will be set to 1 to get the gradient.
|
||||
arma::colvec error = arma::ones<arma::colvec>(input.n_elem);
|
||||
prelu.Gradient(input, error, gradient);
|
||||
REQUIRE(gradient.n_rows == 1);
|
||||
REQUIRE(gradient.n_cols == 1);
|
||||
REQUIRE(gradient(0) == Approx(target(0)).epsilon(1e-5));
|
||||
}*/
|
||||
|
||||
/**
|
||||
* Implementation of the Hard Shrink activation function test. The function is
|
||||
* implemented as Hard Shrink layer in the file hardshrink.hpp
|
||||
@@ -460,23 +387,6 @@ TEST_CASE("HardTanHFunctionTest", "[ActivationFunctionsTest]")
|
||||
CheckHardTanHDerivativeCorrect(activationData, desiredDerivatives);
|
||||
}*/
|
||||
|
||||
/**
|
||||
* Basic test of the PReLU function.
|
||||
*
|
||||
TEST_CASE("PReLUFunctionTest", "[ActivationFunctionsTest]")
|
||||
{
|
||||
const arma::colvec desiredActivations("-0.06 3.2 4.5 -3.006 \
|
||||
1 -0.03 2 0");
|
||||
|
||||
const arma::colvec desiredDerivatives("0.03 1 1 0.03 \
|
||||
1 0.03 1 1");
|
||||
const arma::colvec desiredGradient("-103.2");
|
||||
|
||||
CheckPReLUActivationCorrect(activationData, desiredActivations);
|
||||
CheckPReLUDerivativeCorrect(desiredActivations, desiredDerivatives);
|
||||
CheckPReLUGradientCorrect(activationData, desiredGradient);
|
||||
}*/
|
||||
|
||||
/**
|
||||
* Basic test of the CReLU function.
|
||||
*
|
||||
|
||||
@@ -386,27 +386,6 @@ TEST_CASE("ConstantLayerParametersTest", "[ANNLayerTest]")
|
||||
// REQUIRE(CheckGradient(function) <= 1e-4);
|
||||
// }
|
||||
|
||||
// /**
|
||||
// * Jacobian negative log likelihood module test.
|
||||
// */
|
||||
// TEST_CASE("JacobianNegativeLogLikelihoodLayerTest", "[ANNLayerTest]")
|
||||
// {
|
||||
// for (size_t i = 0; i < 5; ++i)
|
||||
// {
|
||||
// NegativeLogLikelihood module;
|
||||
// const size_t inputElements = RandInt(5, 100);
|
||||
// arma::mat input;
|
||||
// RandomInitialization init(0, 1);
|
||||
// init.Initialize(input, inputElements, 1);
|
||||
|
||||
// arma::mat target(1, 1);
|
||||
// target(0) = RandInt(0, inputElements - 2);
|
||||
|
||||
// double error = JacobianPerformanceTest(module, input, target);
|
||||
// REQUIRE(error <= 1e-5);
|
||||
// }
|
||||
// }
|
||||
|
||||
/**
|
||||
* Jacobian LeakyReLU module test.
|
||||
*
|
||||
@@ -1848,285 +1827,6 @@ TEST_CASE("SimpleJoinLayerTest", "[ANNLayerTest]")
|
||||
// boost::apply_visitor(DeleteVisitor(), layer);
|
||||
// }
|
||||
|
||||
/**
|
||||
* Simple concat module test.
|
||||
*/
|
||||
TEST_CASE("SimpleConcatLayerTest", "[ANNLayerTest]")
|
||||
{
|
||||
arma::mat output, input, delta, error;
|
||||
|
||||
Linear* moduleA = new Linear(10);
|
||||
moduleA->InputDimensions() = std::vector<size_t>({ 10 });
|
||||
moduleA->ComputeOutputDimensions();
|
||||
arma::mat weightsA(moduleA->WeightSize(), 1);
|
||||
moduleA->SetWeights((double*) weightsA.memptr());
|
||||
moduleA->Parameters().randu();
|
||||
|
||||
Linear* moduleB = new Linear(10);
|
||||
moduleB->InputDimensions() = std::vector<size_t>({ 10 });
|
||||
moduleB->ComputeOutputDimensions();
|
||||
arma::mat weightsB(moduleB->WeightSize(), 1);
|
||||
moduleB->SetWeights((double*) weightsB.memptr());
|
||||
moduleB->Parameters().randu();
|
||||
|
||||
Concat module;
|
||||
module.Add(moduleA);
|
||||
module.Add(moduleB);
|
||||
module.InputDimensions() = std::vector<size_t>({ 10 });
|
||||
module.ComputeOutputDimensions();
|
||||
|
||||
// Test the Forward function.
|
||||
input = arma::zeros(10, 1);
|
||||
output.set_size(module.OutputSize(), 1);
|
||||
module.Forward(input, output);
|
||||
|
||||
const double sumModuleA = arma::accu(
|
||||
moduleA->Parameters().submat(
|
||||
100, 0, moduleA->Parameters().n_elem - 1, 0));
|
||||
const double sumModuleB = arma::accu(
|
||||
moduleB->Parameters().submat(
|
||||
100, 0, moduleB->Parameters().n_elem - 1, 0));
|
||||
REQUIRE(sumModuleA + sumModuleB ==
|
||||
Approx(arma::accu(output.col(0))).epsilon(1e-5));
|
||||
|
||||
// Test the Backward function.
|
||||
error = arma::zeros(20, 1);
|
||||
delta.set_size(input.n_rows, input.n_cols);
|
||||
module.Backward(input, error, delta);
|
||||
REQUIRE(arma::accu(delta) == 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test to check Concat layer along different axes.
|
||||
*/
|
||||
TEST_CASE("ConcatAlongAxisTest", "[ANNLayerTest]")
|
||||
{
|
||||
arma::mat output, input, error, outputA, outputB;
|
||||
size_t inputWidth = 4, inputHeight = 4, inputChannel = 2;
|
||||
size_t outputWidth, outputHeight, outputChannel = 2;
|
||||
size_t kW = 3, kH = 3;
|
||||
size_t batch = 1;
|
||||
|
||||
// Using Convolution<> layer as inout to Concat<> layer.
|
||||
// Compute the output shape of convolution layer.
|
||||
outputWidth = (inputWidth - kW) + 1;
|
||||
outputHeight = (inputHeight - kH) + 1;
|
||||
|
||||
input = arma::ones(inputWidth * inputHeight * inputChannel, batch);
|
||||
|
||||
Convolution* moduleA = new Convolution(outputChannel, kW, kH, 1, 1, 0, 0);
|
||||
Convolution* moduleB = new Convolution(outputChannel, kW, kH, 1, 1, 0, 0);
|
||||
|
||||
moduleA->InputDimensions() = std::vector<size_t>({ inputWidth, inputHeight });
|
||||
moduleA->ComputeOutputDimensions();
|
||||
arma::mat weightsA(moduleA->WeightSize(), 1);
|
||||
moduleA->SetWeights((double*) weightsA.memptr());
|
||||
moduleA->Parameters().randu();
|
||||
|
||||
moduleB->InputDimensions() = std::vector<size_t>({ inputWidth, inputHeight });
|
||||
moduleB->ComputeOutputDimensions();
|
||||
arma::mat weightsB(moduleB->WeightSize(), 1);
|
||||
moduleB->SetWeights((double*) weightsB.memptr());
|
||||
moduleB->Parameters().randu();
|
||||
|
||||
// Compute output of each layer.
|
||||
outputA.set_size(moduleA->OutputSize(), 1);
|
||||
outputB.set_size(moduleB->OutputSize(), 1);
|
||||
moduleA->Forward(input, outputA);
|
||||
moduleB->Forward(input, outputB);
|
||||
|
||||
arma::cube A(outputA.memptr(), outputWidth, outputHeight, outputChannel);
|
||||
arma::cube B(outputB.memptr(), outputWidth, outputHeight, outputChannel);
|
||||
|
||||
error = arma::ones(outputWidth * outputHeight * outputChannel * 2, 1);
|
||||
|
||||
for (size_t axis = 0; axis < 3; ++axis)
|
||||
{
|
||||
size_t x = 1, y = 1, z = 1;
|
||||
arma::cube calculatedOut;
|
||||
if (axis == 0)
|
||||
{
|
||||
calculatedOut.set_size(2 * outputWidth, outputHeight, outputChannel);
|
||||
for (size_t i = 0; i < A.n_slices; ++i)
|
||||
{
|
||||
arma::mat aMat = A.slice(i);
|
||||
arma::mat bMat = B.slice(i);
|
||||
calculatedOut.slice(i) = arma::join_cols(aMat, bMat);
|
||||
}
|
||||
x = 2;
|
||||
}
|
||||
if (axis == 1)
|
||||
{
|
||||
calculatedOut.set_size(outputWidth, 2 * outputHeight, outputChannel);
|
||||
for (size_t i = 0; i < A.n_slices; ++i)
|
||||
{
|
||||
arma::mat aMat = A.slice(i);
|
||||
arma::mat bMat = B.slice(i);
|
||||
calculatedOut.slice(i) = arma::join_rows(aMat, bMat);
|
||||
}
|
||||
y = 2;
|
||||
}
|
||||
if (axis == 2)
|
||||
{
|
||||
calculatedOut = arma::join_slices(A, B);
|
||||
z = 2;
|
||||
}
|
||||
|
||||
// Compute output of Concat<> layer.
|
||||
Concat module(axis);
|
||||
module.Add(moduleA);
|
||||
module.Add(moduleB);
|
||||
module.InputDimensions() = std::vector<size_t>({ inputWidth, inputHeight });
|
||||
module.ComputeOutputDimensions();
|
||||
output.set_size(module.OutputSize(), 1);
|
||||
module.Forward(input, output);
|
||||
arma::cube concatOut(output.memptr(), x * outputWidth,
|
||||
y * outputHeight, z * outputChannel);
|
||||
|
||||
// Verify if the output reshaped to cubes are similar.
|
||||
CheckMatrices(concatOut, calculatedOut, 1e-12);
|
||||
|
||||
// Ensure that the child layers don't get deleted when `module` is
|
||||
// deallocated.
|
||||
module.Network().clear();
|
||||
}
|
||||
|
||||
delete moduleA;
|
||||
delete moduleB;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that the function that can access the axis parameter of the
|
||||
* Concat layer works.
|
||||
*/
|
||||
TEST_CASE("ConcatLayerParametersTest", "[ANNLayerTest]")
|
||||
{
|
||||
Concat layer(2);
|
||||
|
||||
// Make sure we can get the parameters successfully.
|
||||
REQUIRE(layer.Axis() == 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Concat layer numerical gradient test.
|
||||
*/
|
||||
TEST_CASE("GradientConcatLayerTest", "[ANNLayerTest]")
|
||||
{
|
||||
// Concat function gradient instantiation.
|
||||
struct GradientFunction
|
||||
{
|
||||
GradientFunction() :
|
||||
input(arma::randu(10, 1)),
|
||||
target(arma::mat("0"))
|
||||
{
|
||||
model = new FFN<NegativeLogLikelihood, NguyenWidrowInitialization>();
|
||||
model->ResetData(input, target);
|
||||
model->Add<Linear>(10);
|
||||
|
||||
concat = new Concat();
|
||||
concat->Add<Linear>(5);
|
||||
concat->Add<Linear>(5);
|
||||
model->Add(concat);
|
||||
model->Add<Linear>(2);
|
||||
|
||||
model->Add<LogSoftMax>();
|
||||
}
|
||||
|
||||
~GradientFunction()
|
||||
{
|
||||
delete model;
|
||||
}
|
||||
|
||||
double Gradient(arma::mat& gradient) const
|
||||
{
|
||||
double error = model->Evaluate(model->Parameters(), 0, 1);
|
||||
model->Gradient(model->Parameters(), 0, gradient, 1);
|
||||
return error;
|
||||
}
|
||||
|
||||
arma::mat& Parameters() { return model->Parameters(); }
|
||||
|
||||
FFN<NegativeLogLikelihood, NguyenWidrowInitialization>* model;
|
||||
Concat* concat;
|
||||
arma::mat input, target;
|
||||
} function;
|
||||
|
||||
REQUIRE(CheckGradient(function) <= 1e-4);
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple concatenate module test.
|
||||
*/
|
||||
TEST_CASE("SimpleConcatenateLayerTest", "[ANNLayerTest]")
|
||||
{
|
||||
arma::mat input = arma::ones(5, 1);
|
||||
arma::mat output, delta;
|
||||
|
||||
Concatenate module;
|
||||
module.Concat() = arma::ones(5, 1) * 0.5;
|
||||
module.InputDimensions() = std::vector<size_t>({ 5 });
|
||||
module.ComputeOutputDimensions();
|
||||
|
||||
// Test the Forward function.
|
||||
output.set_size(module.OutputSize(), 1);
|
||||
module.Forward(input, output);
|
||||
|
||||
REQUIRE(arma::accu(output) == 7.5);
|
||||
|
||||
// Test the Backward function.
|
||||
delta.set_size(5, 1);
|
||||
module.Backward(input, output, delta);
|
||||
REQUIRE(arma::accu(delta) == 5);
|
||||
}
|
||||
|
||||
/**
|
||||
* Concatenate layer numerical gradient test.
|
||||
*/
|
||||
TEST_CASE("GradientConcatenateLayerTest", "[ANNLayerTest]")
|
||||
{
|
||||
// Concatenate function gradient instantiation.
|
||||
struct GradientFunction
|
||||
{
|
||||
GradientFunction() :
|
||||
input(arma::randu(10, 1)),
|
||||
target(arma::mat("0"))
|
||||
{
|
||||
model = new FFN<NegativeLogLikelihood, NguyenWidrowInitialization>();
|
||||
model->ResetData(input, target);
|
||||
model->Add<Linear>(5);
|
||||
|
||||
arma::mat concat = arma::ones(5, 1);
|
||||
// concatenate = new Concatenate();
|
||||
// concatenate->Concat() = concat;
|
||||
// model->Add(concatenate);
|
||||
model->Add<Concatenate>(concat);
|
||||
|
||||
model->Add<Linear>(5);
|
||||
model->Add<LogSoftMax>();
|
||||
}
|
||||
|
||||
~GradientFunction()
|
||||
{
|
||||
delete model;
|
||||
}
|
||||
|
||||
double Gradient(arma::mat& gradient) const
|
||||
{
|
||||
double error = model->Evaluate(model->Parameters(), 0, 1);
|
||||
model->Gradient(model->Parameters(), 0, gradient, 1);
|
||||
return error;
|
||||
}
|
||||
|
||||
arma::mat& Parameters() { return model->Parameters(); }
|
||||
|
||||
FFN<NegativeLogLikelihood, NguyenWidrowInitialization>* model;
|
||||
Concatenate* concatenate;
|
||||
arma::mat input, target;
|
||||
} function;
|
||||
|
||||
REQUIRE(CheckGradient(function) <= 1e-4);
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple lookup module test.
|
||||
*
|
||||
@@ -2239,69 +1939,6 @@ TEST_CASE("LookupLayerParametersTest", "[ANNLayerTest]")
|
||||
}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Simple Softmax module test.
|
||||
*/
|
||||
TEST_CASE("SimpleSoftmaxLayerTest", "[ANNLayerTest]")
|
||||
{
|
||||
arma::mat input, output, gy, g;
|
||||
Softmax module;
|
||||
|
||||
// Test the forward function.
|
||||
input = arma::mat("1.7; 3.6");
|
||||
module.Forward(input, output);
|
||||
REQUIRE(arma::accu(arma::abs(arma::mat("0.130108; 0.869892") - output)) ==
|
||||
Approx(0.0).margin(1e-4));
|
||||
|
||||
// Test the backward function.
|
||||
gy = arma::zeros(input.n_rows, input.n_cols);
|
||||
gy(0) = 1;
|
||||
module.Backward(output, gy, g);
|
||||
REQUIRE(arma::accu(arma::abs(arma::mat("0.11318; -0.11318") - g)) ==
|
||||
Approx(0.0).margin(1e-04));
|
||||
}
|
||||
|
||||
/**
|
||||
* Softmax layer numerical gradient test.
|
||||
*/
|
||||
TEST_CASE("GradientSoftmaxTest", "[ANNLayerTest]")
|
||||
{
|
||||
// Softmax function gradient instantiation.
|
||||
struct GradientFunction
|
||||
{
|
||||
GradientFunction() :
|
||||
input(arma::randu(10, 1)),
|
||||
target(arma::mat("1; 0"))
|
||||
{
|
||||
model = new FFN<MeanSquaredError, RandomInitialization>;
|
||||
model->ResetData(input, target);
|
||||
model->Add<Linear>(10);
|
||||
model->Add<ReLU>();
|
||||
model->Add<Linear>(2);
|
||||
model->Add<Softmax>();
|
||||
}
|
||||
|
||||
~GradientFunction()
|
||||
{
|
||||
delete model;
|
||||
}
|
||||
|
||||
double Gradient(arma::mat& gradient) const
|
||||
{
|
||||
double error = model->Evaluate(model->Parameters(), 0, 1);
|
||||
model->Gradient(model->Parameters(), 0, gradient, 1);
|
||||
return error;
|
||||
}
|
||||
|
||||
arma::mat& Parameters() { return model->Parameters(); }
|
||||
|
||||
FFN<MeanSquaredError>* model;
|
||||
arma::mat input, target;
|
||||
} function;
|
||||
|
||||
REQUIRE(CheckGradient(function) <= 1e-4);
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple test for the NearestInterpolation layer
|
||||
*
|
||||
@@ -4058,155 +3695,6 @@ TEST_CASE("TransposedConvolutionLayerPaddingTest", "[ANNLayerTest]")
|
||||
// REQUIRE(output.n_elem == 4);
|
||||
// }
|
||||
|
||||
/**
|
||||
* Simple test for AddMerge layer.
|
||||
*/
|
||||
TEST_CASE("AddMergeTestCase", "[ANNLayerTest]")
|
||||
{
|
||||
// For rectangular input to pooling layers.
|
||||
arma::mat input = arma::mat(28, 1);
|
||||
input.zeros();
|
||||
input(0) = input(16) = 1;
|
||||
input(1) = input(17) = 2;
|
||||
input(2) = input(18) = 3;
|
||||
input(3) = input(19) = 4;
|
||||
input(4) = input(20) = 5;
|
||||
input(5) = input(23) = 6;
|
||||
input(6) = input(24) = 7;
|
||||
input(14) = input(25) = 8;
|
||||
input(15) = input(26) = 9;
|
||||
|
||||
AddMerge module1;
|
||||
module1.Add<MeanPooling>(2, 2, 2, 2, false);
|
||||
module1.Add<MeanPooling>(2, 2, 2, 2, false);
|
||||
|
||||
AddMerge module2;
|
||||
module2.Add<MeanPooling>(2, 2, 2, 2, true);
|
||||
module2.Add<MeanPooling>(2, 2, 2, 2, true);
|
||||
|
||||
module1.InputDimensions() = std::vector<size_t>({ 7, 4 });
|
||||
module1.ComputeOutputDimensions();
|
||||
module2.InputDimensions() = std::vector<size_t>({ 7, 4 });
|
||||
module2.ComputeOutputDimensions();
|
||||
|
||||
// Calculated using torch.nn.MeanPool2d().
|
||||
arma::mat result1, result2;
|
||||
result1 << 1.5000 << 8.5000 << arma::endr
|
||||
<< 3.5000 << 8.0000 << arma::endr
|
||||
<< 5.5000 << 12.0000 << arma::endr
|
||||
<< 7.0000 << 5.0000 << arma::endr;
|
||||
|
||||
result2 << 1.5000 << 8.5000 << arma::endr
|
||||
<< 3.5000 << 8.0000 << arma::endr
|
||||
<< 5.5000 << 12.0000 << arma::endr;
|
||||
|
||||
arma::mat output1, output2;
|
||||
output1.set_size(8, 1);
|
||||
output2.set_size(6, 1);
|
||||
module1.Forward(input, output1);
|
||||
REQUIRE(arma::accu(output1) == 51.0);
|
||||
module2.Forward(input, output2);
|
||||
REQUIRE(arma::accu(output2) == 39.0);
|
||||
output1.reshape(4, 2);
|
||||
output2.reshape(3, 2);
|
||||
CheckMatrices(output1, result1, 1e-1);
|
||||
CheckMatrices(output2, result2, 1e-1);
|
||||
|
||||
arma::mat prevDelta1, prevDelta2;
|
||||
prevDelta1 << 3.6000 << -0.9000 << arma::endr
|
||||
<< 3.6000 << -0.9000 << arma::endr
|
||||
<< 3.6000 << -0.9000 << arma::endr
|
||||
<< 3.6000 << -0.9000 << arma::endr;
|
||||
|
||||
prevDelta2 << 3.6000 << -0.9000 << arma::endr
|
||||
<< 3.6000 << -0.9000 << arma::endr
|
||||
<< 3.6000 << -0.9000 << arma::endr;
|
||||
arma::mat delta1, delta2;
|
||||
delta1.set_size(28, 1);
|
||||
delta2.set_size(28, 1);
|
||||
prevDelta1.reshape(8, 1);
|
||||
prevDelta2.reshape(6, 1);
|
||||
module1.Backward(input, prevDelta1, delta1);
|
||||
REQUIRE(arma::accu(delta1) == Approx(21.6).epsilon(1e-3));
|
||||
module2.Backward(input, prevDelta2, delta2);
|
||||
REQUIRE(arma::accu(delta2) == Approx(16.2).epsilon(1e-3));
|
||||
}
|
||||
|
||||
/**
|
||||
* Complex test for AddMerge layer.
|
||||
* This test includes:
|
||||
* 1. AddMerge layer inside the AddMerge layer.
|
||||
* 2. Batch Size > 1.
|
||||
* 3. AddMerge layer with single child layer.
|
||||
*/
|
||||
TEST_CASE("AddMergeAdvanceTestCase", "[ANNLayerTest]")
|
||||
{
|
||||
AddMerge r;
|
||||
AddMerge* r2 = new AddMerge();
|
||||
r2->Add<Linear>(5);
|
||||
r.Add<Linear>(5);
|
||||
r.Add(r2);
|
||||
r.InputDimensions() = std::vector<size_t>({ 5 });
|
||||
r.ComputeOutputDimensions();
|
||||
arma::mat rParams(r.WeightSize(), 1);
|
||||
r.SetWeights((double*) rParams.memptr());
|
||||
r.Network()[0]->Parameters().fill(2.0);
|
||||
((AddMerge*) r.Network()[1])->Network()[0]->Parameters().fill(-1.0);
|
||||
|
||||
Linear l(5);
|
||||
l.InputDimensions() = std::vector<size_t>({ 5 });
|
||||
l.ComputeOutputDimensions();
|
||||
arma::mat lParams(l.WeightSize(), 1);
|
||||
l.SetWeights((double*) lParams.memptr());
|
||||
l.Parameters().fill(1.0);
|
||||
|
||||
arma::mat input(arma::randn(5, 10));
|
||||
arma::mat output1, output2;
|
||||
output1.set_size(5, 10);
|
||||
output2.set_size(5, 10);
|
||||
|
||||
r.Forward(input, output1);
|
||||
l.Forward(input, output2);
|
||||
|
||||
CheckMatrices(output1, output2, 1e-3);
|
||||
|
||||
arma::mat delta1, delta2;
|
||||
delta1.set_size(5, 10);
|
||||
delta2.set_size(5, 10);
|
||||
r.Backward(input, output1, delta1);
|
||||
l.Backward(input, output2, delta2);
|
||||
|
||||
CheckMatrices(output1, output2, 1e-3);
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple test for Identity layer.
|
||||
*/
|
||||
TEST_CASE("IdentityTestCase", "[ANNLayerTest]")
|
||||
{
|
||||
// For rectangular input to pooling layers.
|
||||
arma::mat input = arma::mat(12, 1, arma::fill::randn);
|
||||
arma::mat output;
|
||||
// Output-Size should be 4 x 3.
|
||||
output.set_size(12, 1);
|
||||
|
||||
Identity module1;
|
||||
module1.InputDimensions() = std::vector<size_t>({ 4, 3 });
|
||||
module1.ComputeOutputDimensions();
|
||||
module1.Forward(input, output);
|
||||
CheckMatrices(output, input, 1e-1);
|
||||
REQUIRE(output.n_elem == 12);
|
||||
REQUIRE(output.n_cols == 1);
|
||||
REQUIRE(input.memptr() != output.memptr());
|
||||
|
||||
arma::mat prevDelta = arma::mat(12, 1, arma::fill::randn);
|
||||
arma::mat delta;
|
||||
delta.set_size(12, 1);
|
||||
module1.Backward(input, prevDelta, delta);
|
||||
CheckMatrices(delta, prevDelta, 1e-1);
|
||||
REQUIRE(delta.memptr() != prevDelta.memptr());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that the functions that can modify and access the parameters of the
|
||||
* Glimpse layer work.
|
||||
|
||||
+81
-575
@@ -496,212 +496,38 @@ void Serialization()
|
||||
|
||||
/**
|
||||
* Make sure that correct number of recommendations are generated when query
|
||||
* set for randomized SVD.
|
||||
* set for all methods.
|
||||
*/
|
||||
TEST_CASE("CFGetRecommendationsAllUsersRandSVDTest", "[CFTest]")
|
||||
TEMPLATE_TEST_CASE("CFGetRecommendationsAllUsersTest", "[CFTest]",
|
||||
RandomizedSVDPolicy, RegSVDPolicy, BatchSVDPolicy, NMFPolicy,
|
||||
SVDCompletePolicy, SVDIncompletePolicy, BiasSVDPolicy, SVDPlusPlusPolicy,
|
||||
QUIC_SVDPolicy, BlockKrylovSVDPolicy)
|
||||
{
|
||||
GetRecommendationsAllUsers<RandomizedSVDPolicy>();
|
||||
GetRecommendationsAllUsers<TestType>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure that correct number of recommendations are generated when query
|
||||
* set for regularized SVD.
|
||||
* Make sure that the recommendations are generated for queried users
|
||||
* for all methods.
|
||||
*/
|
||||
TEST_CASE("CFGetRecommendationsAllUsersRegSVDTest", "[CFTest]")
|
||||
TEMPLATE_TEST_CASE("CFGetRecommendationsQueriedUsersTest", "[CFTest]",
|
||||
RandomizedSVDPolicy, RegSVDPolicy, BatchSVDPolicy, NMFPolicy,
|
||||
SVDCompletePolicy, SVDIncompletePolicy, BiasSVDPolicy, SVDPlusPlusPolicy,
|
||||
QUIC_SVDPolicy, BlockKrylovSVDPolicy)
|
||||
{
|
||||
GetRecommendationsAllUsers<RegSVDPolicy>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure that correct number of recommendations are generated when query
|
||||
* set for Batch SVD.
|
||||
*/
|
||||
|
||||
TEST_CASE("CFGetRecommendationsAllUsersBatchSVDTest", "[CFTest]")
|
||||
{
|
||||
GetRecommendationsAllUsers<BatchSVDPolicy>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure that correct number of recommendations are generated when query
|
||||
* set for NMF.
|
||||
*/
|
||||
TEST_CASE("CFGetRecommendationsAllUsersNMFTest", "[CFTest]")
|
||||
{
|
||||
GetRecommendationsAllUsers<NMFPolicy>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure that correct number of recommendations are generated when query
|
||||
* set for SVD Complete Incremental method.
|
||||
*/
|
||||
TEST_CASE("CFGetRecommendationsAllUsersSVDCompleteTest", "[CFTest]")
|
||||
{
|
||||
GetRecommendationsAllUsers<SVDCompletePolicy>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure that correct number of recommendations are generated when query
|
||||
* set for SVD Incomplete Incremental method.
|
||||
*/
|
||||
TEST_CASE("CFGetRecommendationsAllUsersSVDIncompleteTest", "[CFTest]")
|
||||
{
|
||||
GetRecommendationsAllUsers<SVDIncompletePolicy>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure that correct number of recommendations are generated when query
|
||||
* set for Bias SVD method.
|
||||
*/
|
||||
TEST_CASE("CFGetRecommendationsAllUsersBiasSVDTest", "[CFTest]")
|
||||
{
|
||||
GetRecommendationsAllUsers<BiasSVDPolicy>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure that correct number of recommendations are generated when query
|
||||
* set for SVDPlusPlus method.
|
||||
*/
|
||||
TEST_CASE("CFGetRecommendationsAllUsersSVDPPTest", "[CFTest]")
|
||||
{
|
||||
GetRecommendationsAllUsers<SVDPlusPlusPolicy>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure that the recommendations are generated for queried users only
|
||||
* for randomized SVD.
|
||||
*/
|
||||
TEST_CASE("CFGetRecommendationsQueriedUserRandSVDTest", "[CFTest]")
|
||||
{
|
||||
GetRecommendationsQueriedUser<RandomizedSVDPolicy>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure that the recommendations are generated for queried users only
|
||||
* for regularized SVD.
|
||||
*/
|
||||
TEST_CASE("CFGetRecommendationsQueriedUserRegSVDTest", "[CFTest]")
|
||||
{
|
||||
GetRecommendationsQueriedUser<RegSVDPolicy>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure that the recommendations are generated for queried users only
|
||||
* for batch SVD.
|
||||
*/
|
||||
TEST_CASE("CFGetRecommendationsQueriedUserBatchSVDTest", "[CFTest]")
|
||||
{
|
||||
GetRecommendationsQueriedUser<BatchSVDPolicy>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure that the recommendations are generated for queried users only
|
||||
* for NMF.
|
||||
*/
|
||||
TEST_CASE("CFGetRecommendationsQueriedUserNMFTest", "[CFTest]")
|
||||
{
|
||||
GetRecommendationsQueriedUser<NMFPolicy>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure that the recommendations are generated for queried users only
|
||||
* for SVD Complete Incremental method.
|
||||
*/
|
||||
TEST_CASE("CFGetRecommendationsQueriedUserSVDCompleteTest", "[CFTest]")
|
||||
{
|
||||
GetRecommendationsQueriedUser<SVDCompletePolicy>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure that the recommendations are generated for queried users only
|
||||
* for SVD Incomplete Incremental method.
|
||||
*/
|
||||
TEST_CASE("CFGetRecommendationsQueriedUserSVDIncompleteTest", "[CFTest]")
|
||||
{
|
||||
GetRecommendationsQueriedUser<SVDIncompletePolicy>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure that the recommendations are generated for queried users only
|
||||
* for Bias SVD method.
|
||||
*/
|
||||
TEST_CASE("CFGetRecommendationsQueriedUserBiasSVDTest", "[CFTest]")
|
||||
{
|
||||
GetRecommendationsQueriedUser<BiasSVDPolicy>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure that the recommendations are generated for queried users only
|
||||
* for SVDPlusPlus method.
|
||||
*/
|
||||
TEST_CASE("CFGetRecommendationsQueriedUserSVDPPTest", "[CFTest]")
|
||||
{
|
||||
GetRecommendationsQueriedUser<SVDPlusPlusPolicy>();
|
||||
GetRecommendationsQueriedUser<TestType>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure recommendations that are generated are reasonably accurate
|
||||
* for randomized SVD.
|
||||
* for all methods except SVDPlusPlus method.
|
||||
*/
|
||||
TEST_CASE("RecommendationAccuracyRandSVDTest", "[CFTest]")
|
||||
TEMPLATE_TEST_CASE("RecommendationAccuracyTest", "[CFTest]",
|
||||
RandomizedSVDPolicy, RegSVDPolicy, BatchSVDPolicy, NMFPolicy,
|
||||
SVDCompletePolicy, SVDIncompletePolicy, BiasSVDPolicy, QUIC_SVDPolicy,
|
||||
BlockKrylovSVDPolicy)
|
||||
{
|
||||
RecommendationAccuracy<RandomizedSVDPolicy>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure recommendations that are generated are reasonably accurate
|
||||
* for regularized SVD.
|
||||
*/
|
||||
TEST_CASE("RecommendationAccuracyRegSVDTest", "[CFTest]")
|
||||
{
|
||||
RecommendationAccuracy<RegSVDPolicy>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure recommendations that are generated are reasonably accurate
|
||||
* for batch SVD.
|
||||
*/
|
||||
TEST_CASE("RecommendationAccuracyBatchSVDTest", "[CFTest]")
|
||||
{
|
||||
RecommendationAccuracy<BatchSVDPolicy>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure recommendations that are generated are reasonably accurate
|
||||
* for NMF.
|
||||
*/
|
||||
TEST_CASE("RecommendationAccuracyNMFTest", "[CFTest]")
|
||||
{
|
||||
RecommendationAccuracy<NMFPolicy>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure recommendations that are generated are reasonably accurate
|
||||
* for SVD Complete Incremental method.
|
||||
*/
|
||||
TEST_CASE("RecommendationAccuracySVDCompleteTest", "[CFTest]")
|
||||
{
|
||||
RecommendationAccuracy<SVDCompletePolicy>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure recommendations that are generated are reasonably accurate
|
||||
* for SVD Incomplete Incremental method.
|
||||
*/
|
||||
TEST_CASE("RecommendationAccuracySVDIncompleteTest", "[CFTest]")
|
||||
{
|
||||
RecommendationAccuracy<SVDIncompletePolicy>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure recommendations that are generated are reasonably accurate
|
||||
* for Bias SVD method.
|
||||
*/
|
||||
TEST_CASE("RecommendationAccuracyBiasSVDTest", "[CFTest]")
|
||||
{
|
||||
// This algorithm seems to be far less effective than others.
|
||||
// We therefore allow failures on 44% of the runs.
|
||||
RecommendationAccuracy<BiasSVDPolicy>(22);
|
||||
RecommendationAccuracy<TestType>();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -715,326 +541,82 @@ TEST_CASE("RecommendationAccuracyBiasSVDTest", "[CFTest]")
|
||||
// RecommendationAccuracy<SVDPlusPlusPolicy>();
|
||||
// }
|
||||
|
||||
// Make sure that Predict() is returning reasonable results for randomized SVD.
|
||||
TEST_CASE("CFPredictRandSVDTest", "[CFTest]")
|
||||
/**
|
||||
* Make sure that Predict() is returning reasonable results for all methods.
|
||||
*/
|
||||
TEMPLATE_TEST_CASE("CFPredictTest", "[CFTest]",
|
||||
RandomizedSVDPolicy, RegSVDPolicy, BatchSVDPolicy, NMFPolicy,
|
||||
SVDCompletePolicy, SVDIncompletePolicy, BiasSVDPolicy, SVDPlusPlusPolicy,
|
||||
QUIC_SVDPolicy, BlockKrylovSVDPolicy)
|
||||
{
|
||||
CFPredict<RandomizedSVDPolicy>();
|
||||
}
|
||||
|
||||
// Make sure that Predict() is returning reasonable results for regularized SVD.
|
||||
TEST_CASE("CFPredictRegSVDTest", "[CFTest]")
|
||||
{
|
||||
CFPredict<RegSVDPolicy>();
|
||||
}
|
||||
|
||||
// Make sure that Predict() is returning reasonable results for batch SVD.
|
||||
TEST_CASE("CFPredictBatchSVDTest", "[CFTest]")
|
||||
{
|
||||
CFPredict<BatchSVDPolicy>();
|
||||
}
|
||||
|
||||
// Make sure that Predict() is returning reasonable results for NMF.
|
||||
TEST_CASE("CFPredictNMFTest", "[CFTest]")
|
||||
{
|
||||
CFPredict<NMFPolicy>();
|
||||
CFPredict<TestType>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure that Predict() is returning reasonable results for SVD Complete
|
||||
* Incremental method.
|
||||
* Compare batch Predict() and individual Predict() for all methods.
|
||||
*/
|
||||
TEST_CASE("CFPredictSVDCompleteTest", "[CFTest]")
|
||||
TEMPLATE_TEST_CASE("CFBatchPredictTest", "[CFTest]",
|
||||
RandomizedSVDPolicy, RegSVDPolicy, BatchSVDPolicy, NMFPolicy,
|
||||
SVDCompletePolicy, SVDIncompletePolicy, BiasSVDPolicy, SVDPlusPlusPolicy,
|
||||
QUIC_SVDPolicy, BlockKrylovSVDPolicy)
|
||||
{
|
||||
CFPredict<SVDCompletePolicy>();
|
||||
BatchPredict<TestType>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure that Predict() is returning reasonable results for SVD Incomplete
|
||||
* Incremental method.
|
||||
* Make sure we can train an already-trained model and it works okay for
|
||||
* some methods
|
||||
*/
|
||||
TEST_CASE("CFPredictSVDIncompleteTest", "[CFTest]")
|
||||
TEMPLATE_TEST_CASE("TrainTest_1", "[CFTest]",
|
||||
RandomizedSVDPolicy, BatchSVDPolicy, NMFPolicy, SVDCompletePolicy,
|
||||
SVDIncompletePolicy, QUIC_SVDPolicy, BlockKrylovSVDPolicy)
|
||||
{
|
||||
CFPredict<SVDIncompletePolicy>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure that Predict() is returning reasonable results for Bias SVD
|
||||
* method.
|
||||
*/
|
||||
TEST_CASE("CFPredictBiasSVDTest", "[CFTest]")
|
||||
{
|
||||
CFPredict<BiasSVDPolicy>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure that Predict() is returning reasonable results for SVDPlusPlus
|
||||
* method.
|
||||
*/
|
||||
TEST_CASE("CFPredictSVDPPTest", "[CFTest]")
|
||||
{
|
||||
CFPredict<SVDPlusPlusPolicy>();
|
||||
}
|
||||
|
||||
// Compare batch Predict() and individual Predict() for randomized SVD.
|
||||
TEST_CASE("CFBatchPredictRandSVDTest", "[CFTest]")
|
||||
{
|
||||
BatchPredict<RandomizedSVDPolicy>();
|
||||
}
|
||||
|
||||
// Compare batch Predict() and individual Predict() for regularized SVD.
|
||||
TEST_CASE("CFBatchPredictRegSVDTest", "[CFTest]")
|
||||
{
|
||||
BatchPredict<RegSVDPolicy>();
|
||||
}
|
||||
|
||||
// Compare batch Predict() and individual Predict() for batch SVD.
|
||||
TEST_CASE("CFBatchPredictBatchSVDTest", "[CFTest]")
|
||||
{
|
||||
BatchPredict<BatchSVDPolicy>();
|
||||
}
|
||||
|
||||
// Compare batch Predict() and individual Predict() for NMF.
|
||||
TEST_CASE("CFBatchPredictNMFTest", "[CFTest]")
|
||||
{
|
||||
BatchPredict<NMFPolicy>();
|
||||
}
|
||||
|
||||
// Compare batch Predict() and individual Predict() for
|
||||
// SVD Complete Incremental method.
|
||||
TEST_CASE("CFBatchPredictSVDCompleteTest", "[CFTest]")
|
||||
{
|
||||
BatchPredict<SVDCompletePolicy>();
|
||||
}
|
||||
|
||||
// Compare batch Predict() and individual Predict() for
|
||||
// SVD Incomplete Incremental method.
|
||||
TEST_CASE("CFBatchPredictSVDIncompleteTest", "[CFTest]")
|
||||
{
|
||||
BatchPredict<SVDIncompletePolicy>();
|
||||
}
|
||||
|
||||
// Compare batch Predict() and individual Predict() for
|
||||
// Bias SVD method.
|
||||
TEST_CASE("CFBatchPredictBiasSVDTest", "[CFTest]")
|
||||
{
|
||||
BatchPredict<BiasSVDPolicy>();
|
||||
}
|
||||
|
||||
// Compare batch Predict() and individual Predict() for
|
||||
// SVDPlusPlus method.
|
||||
TEST_CASE("CFBatchPredictSVDPPTest", "[CFTest]")
|
||||
{
|
||||
BatchPredict<SVDPlusPlusPolicy>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure we can train an already-trained model and it works okay for
|
||||
* randomized SVD.
|
||||
*/
|
||||
TEST_CASE("TrainRandSVDTest", "[CFTest]")
|
||||
{
|
||||
RandomizedSVDPolicy decomposition;
|
||||
TestType decomposition;
|
||||
Train(decomposition);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure we can train an already-trained model and it works okay for
|
||||
* regularized SVD.
|
||||
* Make sure we can train an already-trained model and it works okay for
|
||||
* some methods
|
||||
*/
|
||||
TEST_CASE("TrainRegSVDTest", "[CFTest]")
|
||||
TEMPLATE_TEST_CASE("TrainTest_2", "[CFTest]",
|
||||
RegSVDPolicy, BiasSVDPolicy, SVDPlusPlusPolicy)
|
||||
{
|
||||
RegSVDPolicy decomposition;
|
||||
TrainWithCoordinateList(decomposition);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure we can train an already-trained model and it works okay for
|
||||
* batch SVD.
|
||||
*/
|
||||
TEST_CASE("TrainBatchSVDTest", "[CFTest]")
|
||||
{
|
||||
BatchSVDPolicy decomposition;
|
||||
Train(decomposition);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure we can train an already-trained model and it works okay for
|
||||
* NMF.
|
||||
*/
|
||||
TEST_CASE("TrainNMFTest", "[CFTest]")
|
||||
{
|
||||
NMFPolicy decomposition;
|
||||
Train(decomposition);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure we can train an already-trained model and it works okay for
|
||||
* SVD Complete Incremental method.
|
||||
*/
|
||||
TEST_CASE("TrainSVDCompleteTest", "[CFTest]")
|
||||
{
|
||||
SVDCompletePolicy decomposition;
|
||||
Train(decomposition);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure we can train an already-trained model and it works okay for
|
||||
* SVD Incomplete Incremental method.
|
||||
*/
|
||||
TEST_CASE("TrainSVDIncompleteTest", "[CFTest]")
|
||||
{
|
||||
SVDIncompletePolicy decomposition;
|
||||
Train(decomposition);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure we can train an already-trained model and it works okay for
|
||||
* BiasSVD method.
|
||||
*/
|
||||
TEST_CASE("TrainBiasSVDTest", "[CFTest]")
|
||||
{
|
||||
BiasSVDPolicy decomposition;
|
||||
TrainWithCoordinateList(decomposition);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure we can train an already-trained model and it works okay for
|
||||
* SVDPlusPlus method.
|
||||
*/
|
||||
TEST_CASE("TrainSVDPPTest", "[CFTest]")
|
||||
{
|
||||
SVDPlusPlusPolicy decomposition;
|
||||
TestType decomposition;
|
||||
TrainWithCoordinateList(decomposition);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure we can train a model after using the empty constructor when
|
||||
* using randomized SVD.
|
||||
* using any of the method.
|
||||
*/
|
||||
TEST_CASE("EmptyConstructorTrainRandSVDTest", "[CFTest]")
|
||||
TEMPLATE_TEST_CASE("EmptyConstructorTrainTest", "[CFTest]",
|
||||
RandomizedSVDPolicy, RegSVDPolicy, BatchSVDPolicy, NMFPolicy,
|
||||
SVDCompletePolicy, SVDIncompletePolicy, BiasSVDPolicy, QUIC_SVDPolicy,
|
||||
BlockKrylovSVDPolicy)
|
||||
{
|
||||
EmptyConstructorTrain<RandomizedSVDPolicy>();
|
||||
EmptyConstructorTrain<TestType>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure we can train a model after using the empty constructor when
|
||||
* using regularized SVD.
|
||||
* Ensure we can load and save the CF model using any of the method.
|
||||
*/
|
||||
TEST_CASE("EmptyConstructorTrainRegSVDTest", "[CFTest]")
|
||||
TEMPLATE_TEST_CASE("SerializationTest", "[CFTest]",
|
||||
RandomizedSVDPolicy, BatchSVDPolicy, NMFPolicy, SVDCompletePolicy,
|
||||
SVDIncompletePolicy, QUIC_SVDPolicy, BlockKrylovSVDPolicy)
|
||||
{
|
||||
EmptyConstructorTrain<RegSVDPolicy>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure we can train a model after using the empty constructor when
|
||||
* using batch SVD.
|
||||
*/
|
||||
TEST_CASE("EmptyConstructorTrainBatchSVDTest", "[CFTest]")
|
||||
{
|
||||
EmptyConstructorTrain<BatchSVDPolicy>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure we can train a model after using the empty constructor when
|
||||
* using NMF.
|
||||
*/
|
||||
TEST_CASE("EmptyConstructorTrainNMFTest", "[CFTest]")
|
||||
{
|
||||
EmptyConstructorTrain<NMFPolicy>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure we can train a model after using the empty constructor when
|
||||
* using SVD Complete Incremental method.
|
||||
*/
|
||||
TEST_CASE("EmptyConstructorTrainSVDCompleteTest", "[CFTest]")
|
||||
{
|
||||
EmptyConstructorTrain<SVDCompletePolicy>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure we can train a model after using the empty constructor when
|
||||
* using SVD Incomplete Incremental method.
|
||||
*/
|
||||
TEST_CASE("EmptyConstructorTrainSVDIncompleteTest", "[CFTest]")
|
||||
{
|
||||
EmptyConstructorTrain<SVDIncompletePolicy>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure we can load and save the CF model using randomized SVD policy.
|
||||
*/
|
||||
TEST_CASE("SerializationRandSVDTest", "[CFTest]")
|
||||
{
|
||||
Serialization<RandomizedSVDPolicy>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure we can load and save the CF model using batch SVD policy.
|
||||
*/
|
||||
TEST_CASE("SerializationBatchSVDTest", "[CFTest]")
|
||||
{
|
||||
Serialization<BatchSVDPolicy>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure we can load and save the CF model using NMF policy.
|
||||
*/
|
||||
TEST_CASE("SerializationNMFTest", "[CFTest]")
|
||||
{
|
||||
Serialization<NMFPolicy>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure we can load and save the CF model using SVD Complete Incremental.
|
||||
*/
|
||||
TEST_CASE("SerializationSVDCompleteTest", "[CFTest]")
|
||||
{
|
||||
Serialization<SVDCompletePolicy>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure we can load and save the CF model using SVD Incomplete Incremental.
|
||||
*/
|
||||
TEST_CASE("SerializationSVDIncompleteTest", "[CFTest]")
|
||||
{
|
||||
Serialization<SVDIncompletePolicy>();
|
||||
Serialization<TestType>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure that Predict() is returning reasonable results for NMF and
|
||||
* OverallMeanNormalization.
|
||||
* all types of Normalization except default.
|
||||
*/
|
||||
TEST_CASE("CFPredictOverallMeanNormalization", "[CFTest]")
|
||||
TEMPLATE_TEST_CASE("CFPredictNormalization", "[CFTest]",
|
||||
OverallMeanNormalization, UserMeanNormalization, ItemMeanNormalization,
|
||||
ZScoreNormalization)
|
||||
{
|
||||
CFPredict<NMFPolicy, OverallMeanNormalization>(2.0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure that Predict() is returning reasonable results for NMF and
|
||||
* UserMeanNormalization.
|
||||
*/
|
||||
TEST_CASE("CFPredictUserMeanNormalization", "[CFTest]")
|
||||
{
|
||||
CFPredict<NMFPolicy, UserMeanNormalization>(2.0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure that Predict() is returning reasonable results for NMF and
|
||||
* ItemMeanNormalization.
|
||||
*/
|
||||
TEST_CASE("CFPredictItemMeanNormalization", "[CFTest]")
|
||||
{
|
||||
CFPredict<NMFPolicy, ItemMeanNormalization>(2.0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure that Predict() is returning reasonable results for NMF and
|
||||
* ZScoreNormalization.
|
||||
*/
|
||||
TEST_CASE("CFPredictZScoreNormalization", "[CFTest]")
|
||||
{
|
||||
CFPredict<NMFPolicy, ZScoreNormalization>(2.0);
|
||||
CFPredict<NMFPolicy, TestType>(2.0);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1061,38 +643,13 @@ TEST_CASE("CFPredictNoNormalization", "[CFTest]")
|
||||
|
||||
/**
|
||||
* Make sure recommendations that are generated are reasonably accurate
|
||||
* for OverallMeanNormalization.
|
||||
* for all types of Normalization except default.
|
||||
*/
|
||||
TEST_CASE("RecommendationAccuracyOverallMeanNormalizationTest", "[CFTest]")
|
||||
TEMPLATE_TEST_CASE("RecommendationAccuracyNormalizationTest", "[CFTest]",
|
||||
OverallMeanNormalization, UserMeanNormalization, ItemMeanNormalization,
|
||||
ZScoreNormalization)
|
||||
{
|
||||
RecommendationAccuracy<NMFPolicy, OverallMeanNormalization>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure recommendations that are generated are reasonably accurate
|
||||
* for UserMeanNormalization.
|
||||
*/
|
||||
TEST_CASE("RecommendationAccuracyUserMeanNormalizationTest", "[CFTest]")
|
||||
{
|
||||
RecommendationAccuracy<NMFPolicy, UserMeanNormalization>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure recommendations that are generated are reasonably accurate
|
||||
* for ItemMeanNormalization.
|
||||
*/
|
||||
TEST_CASE("RecommendationAccuracyItemMeanNormalizationTest", "[CFTest]")
|
||||
{
|
||||
RecommendationAccuracy<NMFPolicy, ItemMeanNormalization>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure recommendations that are generated are reasonably accurate
|
||||
* for ZScoreNormalization.
|
||||
*/
|
||||
TEST_CASE("RecommendationAccuracyZScoreNormalizationTest", "[CFTest]")
|
||||
{
|
||||
RecommendationAccuracy<NMFPolicy, ZScoreNormalization>();
|
||||
RecommendationAccuracy<NMFPolicy, TestType>();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1109,35 +666,14 @@ TEST_CASE("RecommendationAccuracyCombinedNormalizationTest", "[CFTest]")
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure we can load and save the CF model using OverallMeanNormalization.
|
||||
* Ensure we can load and save the CF model using any type of Normalization
|
||||
* except default.
|
||||
*/
|
||||
TEST_CASE("SerializationOverallMeanNormalizationTest", "[CFTest]")
|
||||
TEMPLATE_TEST_CASE("SerializationNormalizationTest", "[CFTest]",
|
||||
OverallMeanNormalization, UserMeanNormalization, ItemMeanNormalization,
|
||||
ZScoreNormalization)
|
||||
{
|
||||
Serialization<NMFPolicy, OverallMeanNormalization>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure we can load and save the CF model using UserMeanNormalization.
|
||||
*/
|
||||
TEST_CASE("SerializationUserMeanNormalizationTest", "[CFTest]")
|
||||
{
|
||||
Serialization<NMFPolicy, UserMeanNormalization>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure we can load and save the CF model using ItemMeanNormalization.
|
||||
*/
|
||||
TEST_CASE("SerializationItemMeanNormalizationTest", "[CFTest]")
|
||||
{
|
||||
Serialization<NMFPolicy, ItemMeanNormalization>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure we can load and save the CF model using ZScoreMeanNormalization.
|
||||
*/
|
||||
TEST_CASE("SerializationZScoreNormalizationTest", "[CFTest]")
|
||||
{
|
||||
Serialization<NMFPolicy, ZScoreNormalization>();
|
||||
Serialization<NMFPolicy, TestType>();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1153,54 +689,24 @@ TEST_CASE("SerializationCombinedNormalizationTest", "[CFTest]")
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure that Predict() is returning reasonable results for
|
||||
* EuclideanSearch.
|
||||
* Make sure that Predict() is returning reasonable results for all search
|
||||
* except default.
|
||||
*/
|
||||
TEST_CASE("CFPredictEuclideanSearch", "[CFTest]")
|
||||
TEMPLATE_TEST_CASE("CFPredictSearch", "[CFTest]",
|
||||
EuclideanSearch, CosineSearch, PearsonSearch)
|
||||
{
|
||||
CFPredict<NMFPolicy, OverallMeanNormalization, EuclideanSearch>(2.0);
|
||||
CFPredict<NMFPolicy, OverallMeanNormalization, TestType>(2.0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure that Predict() is returning reasonable results for
|
||||
* CosineSearch.
|
||||
* some Interpolations.
|
||||
*/
|
||||
TEST_CASE("CFPredictCosineSearch", "[CFTest]")
|
||||
TEMPLATE_TEST_CASE("CFPredictAverageInterpolation", "[CFTest]",
|
||||
AverageInterpolation, SimilarityInterpolation)
|
||||
{
|
||||
CFPredict<NMFPolicy, OverallMeanNormalization, CosineSearch>(2.0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure that Predict() is returning reasonable results for
|
||||
* PearsonSearch.
|
||||
*/
|
||||
TEST_CASE("CFPredictPearsonSearch", "[CFTest]")
|
||||
{
|
||||
CFPredict<NMFPolicy, OverallMeanNormalization, PearsonSearch>(2.0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure that Predict() is returning reasonable results for
|
||||
* AverageInterpolation.
|
||||
*/
|
||||
TEST_CASE("CFPredictAverageInterpolation", "[CFTest]")
|
||||
{
|
||||
CFPredict<NMFPolicy,
|
||||
OverallMeanNormalization,
|
||||
EuclideanSearch,
|
||||
AverageInterpolation>(2.0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure that Predict() is returning reasonable results for
|
||||
* SimilarityInterpolation.
|
||||
*/
|
||||
TEST_CASE("CFPredictSimilarityInterpolation", "[CFTest]")
|
||||
{
|
||||
CFPredict<NMFPolicy,
|
||||
OverallMeanNormalization,
|
||||
EuclideanSearch,
|
||||
SimilarityInterpolation>(2.0);
|
||||
CFPredict<NMFPolicy, OverallMeanNormalization, EuclideanSearch,
|
||||
TestType>(2.0);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -58,7 +58,7 @@ TEST_CASE("WrongExtensionWrongLoad", "[LoadSaveTest]")
|
||||
"4 8;";
|
||||
|
||||
arma::mat testTrans = trans(test);
|
||||
REQUIRE(testTrans.quiet_save("test_file.csv", arma::arma_binary) == true);
|
||||
REQUIRE(testTrans.save("test_file.csv", arma::arma_binary) == true);
|
||||
|
||||
// Now reload through our interface.
|
||||
REQUIRE(data::Load("test_file.csv", test) == false);
|
||||
@@ -79,7 +79,7 @@ TEST_CASE("WrongExtensionCorrectLoad", "[LoadSaveTest]")
|
||||
"4 8;";
|
||||
|
||||
arma::mat testTrans = trans(test);
|
||||
REQUIRE(testTrans.quiet_save("test_file.csv", arma::arma_binary) == true);
|
||||
REQUIRE(testTrans.save("test_file.csv", arma::arma_binary) == true);
|
||||
|
||||
// Now reload through our interface.
|
||||
REQUIRE(
|
||||
@@ -924,7 +924,7 @@ TEST_CASE("LoadArmaBinaryTest", "[LoadSaveTest]")
|
||||
"4 8;";
|
||||
|
||||
arma::mat testTrans = trans(test);
|
||||
REQUIRE(testTrans.quiet_save("test_file.bin", arma::arma_binary)
|
||||
REQUIRE(testTrans.save("test_file.bin", arma::arma_binary)
|
||||
== true);
|
||||
|
||||
// Now reload through our interface.
|
||||
@@ -1001,7 +1001,7 @@ TEST_CASE("LoadRawBinaryTest", "[LoadSaveTest]")
|
||||
"7 8;";
|
||||
|
||||
arma::mat testTrans = trans(test);
|
||||
REQUIRE(testTrans.quiet_save("test_file.bin", arma::raw_binary)
|
||||
REQUIRE(testTrans.save("test_file.bin", arma::raw_binary)
|
||||
== true);
|
||||
|
||||
// Now reload through our interface.
|
||||
@@ -1028,7 +1028,7 @@ TEST_CASE("LoadPGMBinaryTest", "[LoadSaveTest]")
|
||||
"4 8;";
|
||||
|
||||
arma::mat testTrans = trans(test);
|
||||
REQUIRE(testTrans.quiet_save("test_file.pgm", arma::pgm_binary)
|
||||
REQUIRE(testTrans.save("test_file.pgm", arma::pgm_binary)
|
||||
== true);
|
||||
|
||||
// Now reload through our interface.
|
||||
@@ -1080,13 +1080,13 @@ TEST_CASE("LoadHDF5Test", "[LoadSaveTest]")
|
||||
"3 7;"
|
||||
"4 8;";
|
||||
arma::mat testTrans = trans(test);
|
||||
REQUIRE(testTrans.quiet_save("test_file.h5", arma::hdf5_binary)
|
||||
REQUIRE(testTrans.save("test_file.h5", arma::hdf5_binary)
|
||||
== true);
|
||||
REQUIRE(testTrans.quiet_save("test_file.hdf5", arma::hdf5_binary)
|
||||
REQUIRE(testTrans.save("test_file.hdf5", arma::hdf5_binary)
|
||||
== true);
|
||||
REQUIRE(testTrans.quiet_save("test_file.hdf", arma::hdf5_binary)
|
||||
REQUIRE(testTrans.save("test_file.hdf", arma::hdf5_binary)
|
||||
== true);
|
||||
REQUIRE(testTrans.quiet_save("test_file.he5", arma::hdf5_binary)
|
||||
REQUIRE(testTrans.save("test_file.he5", arma::hdf5_binary)
|
||||
== true);
|
||||
|
||||
// Now reload through our interface.
|
||||
|
||||
Reference in New Issue
Block a user