Merge branch 'mlpack:master' into master

This commit is contained in:
2023-03-28 09:27:14 +08:00
committed by GitHub
50 changed files with 1546 additions and 1866 deletions
+11
View File
@@ -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
View File
@@ -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
+1 -1
View File
@@ -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 -1
View File
@@ -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
+2 -2
View File
@@ -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
View File
@@ -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();
+5 -5
View File
@@ -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:
+4 -1
View File
@@ -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;
+1 -1
View File
@@ -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
+5 -5
View File
@@ -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);
+2 -2
View File
@@ -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
View File
@@ -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
+7 -7
View File
@@ -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");
-329
View File
@@ -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);
+1 -1
View File
@@ -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
@@ -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);
@@ -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
+2
View File
@@ -283,6 +283,8 @@ class CFType
};
}; // class CFType
typedef CFType<> CF;
} // namespace mlpack
// Include implementation of templated functions.
+16 -1
View File
@@ -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");
+3 -1
View File
@@ -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
+24 -23
View File
@@ -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
+39 -10
View File
@@ -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;
};
+22 -4
View File
@@ -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.
+227
View File
@@ -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));
}
+57
View File
@@ -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));
}
+4
View File
@@ -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
View File
@@ -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);
}
/**
+9 -9
View File
@@ -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.