Merge branch 'master' into msle
This commit is contained in:
@@ -15,6 +15,7 @@ steps:
|
||||
sudo xcode-select --switch /Applications/Xcode_10.1.app/Contents/Developer
|
||||
unset BOOST_ROOT
|
||||
pip install cython numpy pandas zipp
|
||||
brew update
|
||||
brew install openblas armadillo boost
|
||||
|
||||
if [ "a$(julia.version)" != "a" ]; then
|
||||
|
||||
@@ -125,6 +125,8 @@ Copyright:
|
||||
Copyright 2019, Rohit Kartik <rohit.audrey@gmail.com>
|
||||
Copyright 2019, Aditya Viki <adityaviki01@gmail.com>
|
||||
Copyright 2019, Kartik Dutt <kartikdutt@live.in>
|
||||
Copyright 2020, Sriram S K <sriramsk1999@gmail.com>
|
||||
Copyright 2020, Manoranjan Kumar Bharti ( Nakul Bharti ) <knakul853@gmail.com>
|
||||
|
||||
License: BSD-3-clause
|
||||
All rights reserved.
|
||||
|
||||
+10
-1
@@ -2,7 +2,9 @@
|
||||
###### ????-??-??
|
||||
* Added `mean squared logarithmic error` loss function for neural networks
|
||||
(#2210).
|
||||
|
||||
|
||||
* Added `mean bias loss function` for neural networks (#2210).
|
||||
|
||||
* The DecisionStump class has been marked deprecated; use the `DecisionTree`
|
||||
class with `NoRecursion=true` or use `ID3DecisionStump` instead (#2099).
|
||||
|
||||
@@ -33,10 +35,17 @@
|
||||
|
||||
* Add Mish activation function (#2158).
|
||||
|
||||
* Update `init_rules` in AMF to allow users to merge two initialization
|
||||
rules (#2151).
|
||||
|
||||
* Add GELU activation function (#2183).
|
||||
|
||||
* Better error handling of eigendecompositions and Cholesky decompositions
|
||||
(#2088, #1840).
|
||||
|
||||
* Add LiSHT activation function (#2182).
|
||||
|
||||
* Add Valid and Same Padding for Transposed Convolution layer (#2163).
|
||||
|
||||
### mlpack 3.2.2
|
||||
###### 2019-11-26
|
||||
|
||||
@@ -27,20 +27,20 @@ mlpack and dependencies in Release Mode).
|
||||
- Right click on the project and select Properties, select the x64 Debug profile
|
||||
- Under C/C++ > General > Additional Include Directories add:
|
||||
@code
|
||||
- C:\boost\boost_1_66_0
|
||||
- C:\mlpack\armadillo-8.500.1\include
|
||||
- C:\mlpack\mlpack-3.2.1\build\include
|
||||
- C:\boost\boost_1_71_0\lib\native\include
|
||||
- C:\mlpack\armadillo-9.800.3\include
|
||||
- C:\mlpack\mlpack-3.2.2\build\include
|
||||
@endcode
|
||||
- Under Linker > Input > Additional Dependencies add:
|
||||
@code
|
||||
- C:\mlpack\mlpack-3.2.1\build\Debug\mlpack.lib
|
||||
- C:\boost\boost_1_66_0\lib64-msvc-14.1\libboost_serialization-vc141-mt-gd-x64-1_66.lib
|
||||
- C:\boost\boost_1_66_0\lib64-msvc-14.1\libboost_program_options-vc141-mt-gd-x64-1_66.lib
|
||||
- C:\mlpack\mlpack-3.2.2\build\Debug\mlpack.lib
|
||||
- C:\boost\boost_1_71_0\lib64-msvc-14.2\libboost_serialization-vc142-mt-gd-x64-1_71.lib
|
||||
- C:\boost\boost_1_71_0\lib64-msvc-14.2\libboost_program_options-vc142-mt-gd-x64-1_71.lib
|
||||
@endcode
|
||||
- Under Build Events > Post-Build Event > Command Line add:
|
||||
@code
|
||||
- xcopy /y "C:\mlpack\mlpack-3.2.1\build\Debug\mlpack.dll" $(OutDir)
|
||||
- xcopy /y "C:\mlpack\mlpack-3.2.1\packages\OpenBLAS.0.2.14.1\lib\native\bin\x64\*.dll" $(OutDir)
|
||||
- xcopy /y "C:\mlpack\mlpack-3.2.2\build\Debug\mlpack.dll" $(OutDir)
|
||||
- xcopy /y "C:\mlpack\mlpack-3.2.2\packages\OpenBLAS.0.2.14.1\lib\native\bin\x64\*.dll" $(OutDir)
|
||||
@endcode
|
||||
|
||||
@note Recent versions of Visual Studio set "Conformance Mode" enabled by default. This causes some issues with
|
||||
|
||||
@@ -273,7 +273,7 @@ class BinarySpaceTree
|
||||
* Create a binary space tree by copying the other tree. Be careful! This
|
||||
* can take a long time and use a lot of memory.
|
||||
*
|
||||
* @param other Tree to be replicated.
|
||||
* @param other Tree to be copied.
|
||||
*/
|
||||
BinarySpaceTree(const BinarySpaceTree& other);
|
||||
|
||||
@@ -283,6 +283,20 @@ class BinarySpaceTree
|
||||
*/
|
||||
BinarySpaceTree(BinarySpaceTree&& other);
|
||||
|
||||
/**
|
||||
* Copy the given BinarySaceTree.
|
||||
*
|
||||
* @param other The tree to be copied.
|
||||
*/
|
||||
BinarySpaceTree& operator=(const BinarySpaceTree& other);
|
||||
|
||||
/**
|
||||
* Take ownership of the given BinarySpaceTree.
|
||||
*
|
||||
* @param other The tree to take ownership of.
|
||||
*/
|
||||
BinarySpaceTree& operator=(BinarySpaceTree&& other);
|
||||
|
||||
/**
|
||||
* Initialize the tree from a boost::serialization archive.
|
||||
*
|
||||
|
||||
@@ -341,6 +341,7 @@ BinarySpaceTree(
|
||||
stat(other.stat),
|
||||
parentDistance(other.parentDistance),
|
||||
furthestDescendantDistance(other.furthestDescendantDistance),
|
||||
minimumBoundDistance(other.minimumBoundDistance),
|
||||
// Copy matrix, but only if we are the root.
|
||||
dataset((other.parent == NULL) ? new MatType(*other.dataset) : NULL)
|
||||
{
|
||||
@@ -379,6 +380,126 @@ BinarySpaceTree(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy assignment operator: copy the given other tree.
|
||||
*/
|
||||
template<typename MetricType,
|
||||
typename StatisticType,
|
||||
typename MatType,
|
||||
template<typename BoundMetricType, typename...> class BoundType,
|
||||
template<typename SplitBoundType, typename SplitMatType>
|
||||
class SplitType>
|
||||
BinarySpaceTree<MetricType, StatisticType, MatType, BoundType, SplitType>&
|
||||
BinarySpaceTree<MetricType, StatisticType, MatType, BoundType, SplitType>::
|
||||
operator=(const BinarySpaceTree& other)
|
||||
{
|
||||
// Return if it's the same tree.
|
||||
if (this == &other)
|
||||
return *this;
|
||||
|
||||
// Freeing memory that will not be used anymore.
|
||||
delete dataset;
|
||||
delete left;
|
||||
delete right;
|
||||
|
||||
left = NULL;
|
||||
right = NULL;
|
||||
parent = other.Parent();
|
||||
begin = other.Begin();
|
||||
count = other.Count();
|
||||
bound = other.bound;
|
||||
stat = other.stat;
|
||||
parentDistance = other.ParentDistance();
|
||||
furthestDescendantDistance = other.FurthestDescendantDistance();
|
||||
minimumBoundDistance = other.MinimumBoundDistance();
|
||||
// Copy matrix, but only if we are the root.
|
||||
dataset = ((other.parent == NULL) ? new MatType(*other.dataset) : NULL);
|
||||
|
||||
// Create left and right children (if any).
|
||||
if (other.Left())
|
||||
{
|
||||
left = new BinarySpaceTree(*other.Left());
|
||||
left->Parent() = this; // Set parent to this, not other tree.
|
||||
}
|
||||
|
||||
if (other.Right())
|
||||
{
|
||||
right = new BinarySpaceTree(*other.Right());
|
||||
right->Parent() = this; // Set parent to this, not other tree.
|
||||
}
|
||||
|
||||
// Propagate matrix, but only if we are the root.
|
||||
if (parent == NULL)
|
||||
{
|
||||
std::queue<BinarySpaceTree*> queue;
|
||||
if (left)
|
||||
queue.push(left);
|
||||
if (right)
|
||||
queue.push(right);
|
||||
while (!queue.empty())
|
||||
{
|
||||
BinarySpaceTree* node = queue.front();
|
||||
queue.pop();
|
||||
|
||||
node->dataset = dataset;
|
||||
if (node->left)
|
||||
queue.push(node->left);
|
||||
if (node->right)
|
||||
queue.push(node->right);
|
||||
}
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Move assignment operator: take ownership of the given tree.
|
||||
*/
|
||||
template<typename MetricType,
|
||||
typename StatisticType,
|
||||
typename MatType,
|
||||
template<typename BoundMetricType, typename...> class BoundType,
|
||||
template<typename SplitBoundType, typename SplitMatType>
|
||||
class SplitType>
|
||||
BinarySpaceTree<MetricType, StatisticType, MatType, BoundType, SplitType>&
|
||||
BinarySpaceTree<MetricType, StatisticType, MatType, BoundType, SplitType>::
|
||||
operator=(BinarySpaceTree&& other)
|
||||
{
|
||||
// Return if it's the same tree.
|
||||
if (this == &other)
|
||||
return *this;
|
||||
|
||||
// Freeing memory that will not be used anymore.
|
||||
delete dataset;
|
||||
delete left;
|
||||
delete right;
|
||||
|
||||
parent = other.Parent();
|
||||
left = other.Left();
|
||||
right = other.Right();
|
||||
begin = other.Begin();
|
||||
count = other.Count();
|
||||
bound = std::move(other.bound);
|
||||
stat = std::move(other.stat);
|
||||
parentDistance = other.ParentDistance();
|
||||
furthestDescendantDistance = other.FurthestDescendantDistance();
|
||||
minimumBoundDistance = other.MinimumBoundDistance();
|
||||
dataset = other.dataset;
|
||||
|
||||
other.left = NULL;
|
||||
other.right = NULL;
|
||||
other.parent = NULL;
|
||||
other.begin = 0;
|
||||
other.count = 0;
|
||||
other.parentDistance = 0.0;
|
||||
other.furthestDescendantDistance = 0.0;
|
||||
other.minimumBoundDistance = 0.0;
|
||||
other.dataset = NULL;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Move constructor.
|
||||
*/
|
||||
@@ -406,6 +527,7 @@ BinarySpaceTree(BinarySpaceTree&& other) :
|
||||
// tree's contents, so it doesn't delete anything when it is destructed.
|
||||
other.left = NULL;
|
||||
other.right = NULL;
|
||||
other.parent = NULL;
|
||||
other.begin = 0;
|
||||
other.count = 0;
|
||||
other.parentDistance = 0.0;
|
||||
|
||||
@@ -18,11 +18,12 @@ namespace mlpack {
|
||||
namespace tree {
|
||||
|
||||
CosineTree::CosineTree(const arma::mat& dataset) :
|
||||
dataset(dataset),
|
||||
dataset(&dataset),
|
||||
parent(NULL),
|
||||
left(NULL),
|
||||
right(NULL),
|
||||
numColumns(dataset.n_cols)
|
||||
numColumns(dataset.n_cols),
|
||||
localDataset(false)
|
||||
{
|
||||
// Initialize sizes of column indices and l2 norms.
|
||||
indices.resize(numColumns);
|
||||
@@ -47,11 +48,12 @@ CosineTree::CosineTree(const arma::mat& dataset) :
|
||||
|
||||
CosineTree::CosineTree(CosineTree& parentNode,
|
||||
const std::vector<size_t>& subIndices) :
|
||||
dataset(parentNode.GetDataset()),
|
||||
dataset(&parentNode.GetDataset()),
|
||||
parent(&parentNode),
|
||||
left(NULL),
|
||||
right(NULL),
|
||||
numColumns(subIndices.size())
|
||||
numColumns(subIndices.size()),
|
||||
localDataset(false)
|
||||
{
|
||||
// Initialize sizes of column indices and l2 norms.
|
||||
indices.resize(numColumns);
|
||||
@@ -76,10 +78,11 @@ CosineTree::CosineTree(CosineTree& parentNode,
|
||||
CosineTree::CosineTree(const arma::mat& dataset,
|
||||
const double epsilon,
|
||||
const double delta) :
|
||||
dataset(dataset),
|
||||
dataset(&dataset),
|
||||
delta(delta),
|
||||
left(NULL),
|
||||
right(NULL)
|
||||
right(NULL),
|
||||
localDataset(false)
|
||||
{
|
||||
// Declare the cosine tree priority queue.
|
||||
CosineNodeQueue treeQueue;
|
||||
@@ -150,8 +153,214 @@ CosineTree::CosineTree(const arma::mat& dataset,
|
||||
ConstructBasis(treeQueue);
|
||||
}
|
||||
|
||||
//! Copy the given tree.
|
||||
CosineTree::CosineTree(const CosineTree& other) :
|
||||
// Copy matrix, but only if we are the root.
|
||||
dataset((other.parent == NULL) ? new arma::mat(*other.dataset) : NULL),
|
||||
delta(other.delta),
|
||||
parent(NULL),
|
||||
left(NULL),
|
||||
right(NULL),
|
||||
indices(other.indices),
|
||||
l2NormsSquared(other.l2NormsSquared),
|
||||
centroid(other.centroid),
|
||||
basisVector(other.basisVector),
|
||||
splitPointIndex(other.SplitPointIndex()),
|
||||
numColumns(other.NumColumns()),
|
||||
l2Error(other.L2Error()),
|
||||
frobNormSquared(other.FrobNormSquared()),
|
||||
localDataset(other.parent == NULL)
|
||||
{
|
||||
// Create left and right children (if any).
|
||||
if (other.Left())
|
||||
{
|
||||
left = new CosineTree(*other.Left());
|
||||
left->Parent() = this; // Set parent to this, not other tree.
|
||||
}
|
||||
|
||||
if (other.Right())
|
||||
{
|
||||
right = new CosineTree(*other.Right());
|
||||
right->Parent() = this; // Set parent to this, not other tree.
|
||||
}
|
||||
|
||||
// Propagate matrix, but only if we are the root.
|
||||
if (parent == NULL && localDataset)
|
||||
{
|
||||
std::queue<CosineTree*> queue;
|
||||
if (left)
|
||||
queue.push(left);
|
||||
if (right)
|
||||
queue.push(right);
|
||||
while (!queue.empty())
|
||||
{
|
||||
CosineTree* node = queue.front();
|
||||
queue.pop();
|
||||
|
||||
node->dataset = dataset;
|
||||
if (node->left)
|
||||
queue.push(node->left);
|
||||
if (node->right)
|
||||
queue.push(node->right);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//! Copy assignment operator: copy the given other tree.
|
||||
CosineTree& CosineTree::operator=(const CosineTree& other)
|
||||
{
|
||||
// Return if it's the same tree.
|
||||
if (this == &other)
|
||||
return *this;
|
||||
|
||||
// Freeing memory that will not be used anymore.
|
||||
if (localDataset)
|
||||
delete dataset;
|
||||
|
||||
delete left;
|
||||
delete right;
|
||||
|
||||
// Performing a deep copy of the dataset.
|
||||
dataset = (other.parent == NULL) ? new arma::mat(*other.dataset) : NULL;
|
||||
|
||||
delta = other.delta;
|
||||
parent = other.Parent();
|
||||
left = other.Left();
|
||||
right = other.Right();
|
||||
indices = other.indices;
|
||||
l2NormsSquared = other.l2NormsSquared;
|
||||
centroid = other.centroid;
|
||||
basisVector = other.basisVector;
|
||||
splitPointIndex = other.SplitPointIndex();
|
||||
numColumns = other.NumColumns();
|
||||
l2Error = other.L2Error();
|
||||
localDataset = (other.parent == NULL) ? true : false;
|
||||
frobNormSquared = other.FrobNormSquared();
|
||||
|
||||
// Create left and right children (if any).
|
||||
if (other.Left())
|
||||
{
|
||||
left = new CosineTree(*other.Left());
|
||||
left->Parent() = this; // Set parent to this, not other tree.
|
||||
}
|
||||
|
||||
if (other.Right())
|
||||
{
|
||||
right = new CosineTree(*other.Right());
|
||||
right->Parent() = this; // Set parent to this, not other tree.
|
||||
}
|
||||
|
||||
// Propagate matrix, but only if we are the root.
|
||||
if (parent == NULL && localDataset)
|
||||
{
|
||||
std::queue<CosineTree*> queue;
|
||||
if (left)
|
||||
queue.push(left);
|
||||
if (right)
|
||||
queue.push(right);
|
||||
while (!queue.empty())
|
||||
{
|
||||
CosineTree* node = queue.front();
|
||||
queue.pop();
|
||||
|
||||
node->dataset = dataset;
|
||||
if (node->left)
|
||||
queue.push(node->left);
|
||||
if (node->right)
|
||||
queue.push(node->right);
|
||||
}
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
//! Move the given tree.
|
||||
CosineTree::CosineTree(CosineTree&& other) :
|
||||
dataset(other.dataset),
|
||||
delta(std::move(other.delta)),
|
||||
parent(other.parent),
|
||||
left(other.left),
|
||||
right(other.right),
|
||||
indices(std::move(other.indices)),
|
||||
l2NormsSquared(std::move(other.l2NormsSquared)),
|
||||
centroid(std::move(other.centroid)),
|
||||
basisVector(std::move(other.basisVector)),
|
||||
splitPointIndex(other.splitPointIndex),
|
||||
numColumns(other.numColumns),
|
||||
l2Error(other.l2Error),
|
||||
frobNormSquared(other.frobNormSquared),
|
||||
localDataset(other.localDataset)
|
||||
{
|
||||
// Now we are a clone of the other tree. But we must also clear the other
|
||||
// tree's contents, so it doesn't delete anything when it is destructed.
|
||||
other.dataset = NULL;
|
||||
other.parent = NULL;
|
||||
other.left = NULL;
|
||||
other.right = NULL;
|
||||
other.splitPointIndex = 0;
|
||||
other.numColumns = 0;
|
||||
other.l2Error = -1;
|
||||
other.localDataset = false;
|
||||
other.frobNormSquared = 0;
|
||||
// Set new parent.
|
||||
if (left)
|
||||
left->parent = this;
|
||||
if (right)
|
||||
right->parent = this;
|
||||
}
|
||||
|
||||
//! Move assignment operator: take ownership of the given tree.
|
||||
CosineTree& CosineTree::operator=(CosineTree&& other)
|
||||
{
|
||||
// Return if it's the same tree.
|
||||
if (this == &other)
|
||||
return *this;
|
||||
|
||||
// Freeing memory that will not be used anymore.
|
||||
if (localDataset)
|
||||
delete dataset;
|
||||
delete left;
|
||||
delete right;
|
||||
|
||||
dataset = other.dataset;
|
||||
delta = std::move(other.delta);
|
||||
parent = other.Parent();
|
||||
left = other.Left();
|
||||
right = other.Right();
|
||||
indices = std::move(other.indices);
|
||||
l2NormsSquared = std::move(other.l2NormsSquared);
|
||||
centroid = std::move(other.centroid);
|
||||
basisVector = std::move(other.basisVector);
|
||||
splitPointIndex = other.SplitPointIndex();
|
||||
numColumns = other.NumColumns();
|
||||
l2Error = other.L2Error();
|
||||
localDataset = other.localDataset;
|
||||
frobNormSquared = other.FrobNormSquared();
|
||||
|
||||
// Now we are a clone of the other tree. But we must also clear the other
|
||||
// tree's contents, so it doesn't delete anything when it is destructed.
|
||||
other.dataset = NULL;
|
||||
other.parent = NULL;
|
||||
other.left = NULL;
|
||||
other.right = NULL;
|
||||
other.splitPointIndex = 0;
|
||||
other.numColumns = 0;
|
||||
other.l2Error = -1;
|
||||
other.localDataset = false;
|
||||
other.frobNormSquared = 0;
|
||||
// Set new parent.
|
||||
if (left)
|
||||
left->parent = this;
|
||||
if (right)
|
||||
right->parent = this;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
CosineTree::~CosineTree()
|
||||
{
|
||||
if (localDataset)
|
||||
delete dataset;
|
||||
if (left)
|
||||
delete left;
|
||||
if (right)
|
||||
@@ -206,7 +415,7 @@ double CosineTree::MonteCarloError(CosineTree* node,
|
||||
node->ColumnSamplesLS(sampledIndices, probabilities, numSamples);
|
||||
|
||||
// Get pointer to the original dataset.
|
||||
arma::mat dataset = node->GetDataset();
|
||||
const arma::mat& dataset = node->GetDataset();
|
||||
|
||||
// Initialize weighted projection magnitudes as zeros.
|
||||
arma::vec weightedMagnitudes;
|
||||
@@ -280,7 +489,7 @@ double CosineTree::MonteCarloError(CosineTree* node,
|
||||
void CosineTree::ConstructBasis(CosineNodeQueue& treeQueue)
|
||||
{
|
||||
// Initialize basis as matrix of zeros.
|
||||
basis.zeros(dataset.n_rows, treeQueue.size());
|
||||
basis.zeros(dataset->n_rows, treeQueue.size());
|
||||
|
||||
// Variables for iterating through the priority queue.
|
||||
CosineTree *currentNode;
|
||||
@@ -435,8 +644,8 @@ void CosineTree::CalculateCosines(arma::vec& cosines)
|
||||
else
|
||||
{
|
||||
cosines(i) =
|
||||
std::abs(arma::norm_dot(dataset.col(indices[splitPointIndex]),
|
||||
dataset.col(indices[i])));
|
||||
std::abs(arma::norm_dot(dataset->col(indices[splitPointIndex]),
|
||||
dataset->col(indices[i])));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -444,12 +653,12 @@ void CosineTree::CalculateCosines(arma::vec& cosines)
|
||||
void CosineTree::CalculateCentroid()
|
||||
{
|
||||
// Initialize centroid as vector of zeros.
|
||||
centroid.zeros(dataset.n_rows);
|
||||
centroid.zeros(dataset->n_rows);
|
||||
|
||||
// Calculate centroid of columns in the node.
|
||||
for (size_t i = 0; i < numColumns; i++)
|
||||
{
|
||||
centroid += dataset.col(indices[i]);
|
||||
centroid += dataset->col(indices[i]);
|
||||
}
|
||||
centroid /= numColumns;
|
||||
}
|
||||
|
||||
@@ -68,6 +68,35 @@ class CosineTree
|
||||
const double epsilon,
|
||||
const double delta);
|
||||
|
||||
/**
|
||||
* Copy the given tree. Be careful! This may use a lot of memory.
|
||||
*
|
||||
* @param other Tree to copy from.
|
||||
*/
|
||||
CosineTree(const CosineTree& other);
|
||||
|
||||
/**
|
||||
* Move the given tree. The tree passed as a parameter will be emptied and
|
||||
* will not be usable after this call.
|
||||
*
|
||||
* @param other Tree to move.
|
||||
*/
|
||||
CosineTree(CosineTree&& other);
|
||||
|
||||
/**
|
||||
* Copy the given Cosine Tree.
|
||||
*
|
||||
* @param other The tree to be copied.
|
||||
*/
|
||||
CosineTree& operator=(const CosineTree& other);
|
||||
|
||||
/**
|
||||
* Take ownership of the given Cosine Tree.
|
||||
*
|
||||
* @param other The tree to take ownership of.
|
||||
*/
|
||||
CosineTree& operator=(CosineTree&& other);
|
||||
|
||||
/**
|
||||
* Clean up the CosineTree: release allocated memory (including children).
|
||||
*/
|
||||
@@ -169,7 +198,7 @@ class CosineTree
|
||||
void GetFinalBasis(arma::mat& finalBasis) { finalBasis = basis; }
|
||||
|
||||
//! Get pointer to the dataset matrix.
|
||||
const arma::mat& GetDataset() const { return dataset; }
|
||||
const arma::mat& GetDataset() const { return *dataset; }
|
||||
|
||||
//! Get the indices of columns in the node.
|
||||
std::vector<size_t>& VectorIndices() { return indices; }
|
||||
@@ -214,7 +243,7 @@ class CosineTree
|
||||
|
||||
private:
|
||||
//! Matrix for which cosine tree is constructed.
|
||||
const arma::mat& dataset;
|
||||
const arma::mat* dataset;
|
||||
//! Cumulative probability for Monte Carlo error lower bound.
|
||||
double delta;
|
||||
//! Subspace basis of the input dataset.
|
||||
@@ -241,6 +270,8 @@ class CosineTree
|
||||
double l2Error;
|
||||
//! Frobenius norm squared of columns in the node.
|
||||
double frobNormSquared;
|
||||
//! If true, we own the dataset and need to destroy it in the destructor.
|
||||
bool localDataset;
|
||||
};
|
||||
|
||||
class CompareCosineNode
|
||||
|
||||
@@ -548,7 +548,7 @@ CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::CoverTree(
|
||||
}
|
||||
}
|
||||
|
||||
// Copy Assignment.
|
||||
// Copy assignment operator: copy the given other tree.
|
||||
template<
|
||||
typename MetricType,
|
||||
typename StatisticType,
|
||||
@@ -658,7 +658,7 @@ CoverTree<MetricType, StatisticType, MatType, RootPointPolicy>::CoverTree(
|
||||
other.metric = NULL;
|
||||
}
|
||||
|
||||
// Move Assignment.
|
||||
// Move assignment operator: take ownership of the given tree.
|
||||
template<
|
||||
typename MetricType,
|
||||
typename StatisticType,
|
||||
|
||||
@@ -220,6 +220,20 @@ class Octree
|
||||
*/
|
||||
Octree(Octree&& other);
|
||||
|
||||
/**
|
||||
* Copy the given Octree.
|
||||
*
|
||||
* @param other The tree to be copied.
|
||||
*/
|
||||
Octree& operator=(const Octree& other);
|
||||
|
||||
/**
|
||||
* Take ownership of the given Octree.
|
||||
*
|
||||
* @param other The tree to take ownership of.
|
||||
*/
|
||||
Octree& operator=(Octree&& other);
|
||||
|
||||
/**
|
||||
* Initialize the tree from a boost::serialization archive.
|
||||
*
|
||||
|
||||
@@ -363,6 +363,43 @@ Octree<MetricType, StatisticType, MatType>::Octree(const Octree& other) :
|
||||
}
|
||||
}
|
||||
|
||||
//! Copy assignment operator: copy the given other tree.
|
||||
template<typename MetricType, typename StatisticType, typename MatType>
|
||||
Octree<MetricType, StatisticType, MatType>&
|
||||
Octree<MetricType, StatisticType, MatType>::
|
||||
operator=(const Octree& other)
|
||||
{
|
||||
// Return if it's the same tree.
|
||||
if (this == &other)
|
||||
return *this;
|
||||
|
||||
// Freeing memory that will not be used anymore.
|
||||
delete dataset;
|
||||
for (size_t i = 0; i < children.size(); ++i)
|
||||
delete children[i];
|
||||
children.clear();
|
||||
|
||||
begin = other.Begin();
|
||||
count = other.Count();
|
||||
bound = other.bound;
|
||||
dataset = ((other.parent == NULL) ? new MatType(*other.dataset) : NULL);
|
||||
parent = NULL;
|
||||
stat = other.stat;
|
||||
parentDistance = other.ParentDistance();
|
||||
furthestDescendantDistance = other.FurthestDescendantDistance();
|
||||
metric = other.metric;
|
||||
|
||||
// If we have any children, we need to create them, and then ensure that their
|
||||
// parent links are set right.
|
||||
for (size_t i = 0; i < other.NumChildren(); ++i)
|
||||
{
|
||||
children.push_back(new Octree(other.Child(i)));
|
||||
children[i]->parent = this;
|
||||
children[i]->dataset = this->dataset;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
//! Move the given tree.
|
||||
template<typename MetricType, typename StatisticType, typename MatType>
|
||||
Octree<MetricType, StatisticType, MatType>::Octree(Octree&& other) :
|
||||
@@ -389,6 +426,48 @@ Octree<MetricType, StatisticType, MatType>::Octree(Octree&& other) :
|
||||
other.parent = NULL;
|
||||
}
|
||||
|
||||
//! Move assignment operator: take ownership of the given tree.
|
||||
template<typename MetricType, typename StatisticType, typename MatType>
|
||||
Octree<MetricType, StatisticType, MatType>&
|
||||
Octree<MetricType, StatisticType, MatType>::
|
||||
operator=(Octree&& other)
|
||||
{
|
||||
// Return if it's the same tree.
|
||||
if (this == &other)
|
||||
return *this;
|
||||
|
||||
// Freeing memory that will not be used anymore.
|
||||
delete dataset;
|
||||
for (size_t i = 0; i < children.size(); ++i)
|
||||
delete children[i];
|
||||
children.clear();
|
||||
|
||||
children = std::move(other.children);
|
||||
begin = other.Begin();
|
||||
count = other.Count();
|
||||
bound = std::move(other.bound);
|
||||
dataset = other.dataset;
|
||||
parent = other.Parent();
|
||||
stat = std::move(other.stat);
|
||||
parentDistance = other.ParentDistance();
|
||||
furthestDescendantDistance = other.furthestDescendantDistance();
|
||||
metric = std::move(other.metric);
|
||||
|
||||
// Update the parent pointers of the direct children.
|
||||
for (size_t i = 0; i < children.size(); ++i)
|
||||
children[i]->parent = this;
|
||||
|
||||
other.begin = 0;
|
||||
other.count = 0;
|
||||
other.dataset = new MatType();
|
||||
other.parentDistance = 0.0;
|
||||
other.numDescendants = 0;
|
||||
other.furthestDescendantDistance = 0.0;
|
||||
other.parent = NULL;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename MetricType, typename StatisticType, typename MatType>
|
||||
Octree<MetricType, StatisticType, MatType>::Octree() :
|
||||
begin(0),
|
||||
|
||||
@@ -183,6 +183,7 @@ RectangleTree(
|
||||
maxLeafSize(other.MaxLeafSize()),
|
||||
minLeafSize(other.MinLeafSize()),
|
||||
bound(other.bound),
|
||||
stat(other.stat),
|
||||
parentDistance(other.ParentDistance()),
|
||||
dataset(deepCopy ?
|
||||
(parent ? parent->dataset : new MatType(*other.dataset)) :
|
||||
@@ -203,6 +204,9 @@ RectangleTree(
|
||||
children = other.children;
|
||||
}
|
||||
|
||||
/**
|
||||
* Move constructor.
|
||||
*/
|
||||
template<typename MetricType,
|
||||
typename StatisticType,
|
||||
typename MatType,
|
||||
@@ -223,6 +227,7 @@ RectangleTree(RectangleTree&& other) :
|
||||
maxLeafSize(other.MaxLeafSize()),
|
||||
minLeafSize(other.MinLeafSize()),
|
||||
bound(std::move(other.bound)),
|
||||
stat(std::move(other.stat)),
|
||||
parentDistance(other.ParentDistance()),
|
||||
dataset(other.dataset),
|
||||
ownsDataset(other.ownsDataset),
|
||||
@@ -242,6 +247,8 @@ RectangleTree(RectangleTree&& other) :
|
||||
for (size_t i = 0; i < numChildren; i++)
|
||||
children[i]->parent = this;
|
||||
}
|
||||
// Now we are a clone of the other tree. But we must also clear the other
|
||||
// tree's contents, so it doesn't delete anything when it is destructed.
|
||||
other.maxNumChildren = 0;
|
||||
other.minNumChildren = 0;
|
||||
other.numChildren = 0;
|
||||
@@ -256,6 +263,9 @@ RectangleTree(RectangleTree&& other) :
|
||||
other.ownsDataset = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy assignment operator: copy the given other tree.
|
||||
*/
|
||||
template<typename MetricType,
|
||||
typename StatisticType,
|
||||
typename MatType,
|
||||
@@ -272,6 +282,7 @@ operator=(const RectangleTree& other)
|
||||
if (this == &other)
|
||||
return *this;
|
||||
|
||||
// Freeing memory that will not be used anymore.
|
||||
for (size_t i = 0; i < numChildren; i++)
|
||||
delete children[i];
|
||||
|
||||
@@ -289,6 +300,7 @@ operator=(const RectangleTree& other)
|
||||
maxLeafSize = other.MaxLeafSize();
|
||||
minLeafSize = other.MinLeafSize();
|
||||
bound = other.bound;
|
||||
stat = other.stat;
|
||||
parentDistance = other.ParentDistance();
|
||||
dataset = new MatType(*other.dataset);
|
||||
ownsDataset = true;
|
||||
@@ -304,6 +316,9 @@ operator=(const RectangleTree& other)
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Move assignment operator: take ownership of the given tree.
|
||||
*/
|
||||
template<typename MetricType,
|
||||
typename StatisticType,
|
||||
typename MatType,
|
||||
@@ -320,6 +335,7 @@ operator=(RectangleTree&& other)
|
||||
if (this == &other)
|
||||
return *this;
|
||||
|
||||
// Freeing memory that will not be used anymore.
|
||||
for (size_t i = 0; i < numChildren; i++)
|
||||
delete children[i];
|
||||
|
||||
@@ -337,12 +353,28 @@ operator=(RectangleTree&& other)
|
||||
maxLeafSize = other.MaxLeafSize();
|
||||
minLeafSize = other.MinLeafSize();
|
||||
bound = std::move(other.bound);
|
||||
stat = std::move(other.stat);
|
||||
parentDistance = other.ParentDistance();
|
||||
dataset = other.dataset;
|
||||
ownsDataset = other.ownsDataset;
|
||||
points = std::move(other.points);
|
||||
auxiliaryInfo = std::move(other.auxiliaryInfo);
|
||||
|
||||
// Now we are a clone of the other tree. But we must also clear the other
|
||||
// tree's contents, so it doesn't delete anything when it is destructed.
|
||||
other.maxNumChildren = 0;
|
||||
other.minNumChildren = 0;
|
||||
other.numChildren = 0;
|
||||
other.parent = NULL;
|
||||
other.begin = 0;
|
||||
other.count = 0;
|
||||
other.numDescendants = 0;
|
||||
other.maxLeafSize = 0;
|
||||
other.minLeafSize = 0;
|
||||
other.parentDistance = 0;
|
||||
other.dataset = NULL;
|
||||
other.ownsDataset = false;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
@@ -193,7 +193,7 @@ SpillTree(const SpillTree& other) :
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy Assignment.
|
||||
* Copy assignment operator: copy the given other tree.
|
||||
*/
|
||||
template<typename MetricType,
|
||||
typename StatisticType,
|
||||
@@ -320,7 +320,7 @@ SpillTree(SpillTree&& other) :
|
||||
}
|
||||
|
||||
/**
|
||||
* Move Assignment.
|
||||
* Move assignment operator: take ownership of the given tree.
|
||||
*/
|
||||
template<typename MetricType,
|
||||
typename StatisticType,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @file averge_init.hpp
|
||||
* @file average_init.hpp
|
||||
* @author Sumedh Ghaisas
|
||||
*
|
||||
* Initialization rule for Alternating Matrix Factorization.
|
||||
@@ -49,7 +49,6 @@ class AverageInitialization
|
||||
const size_t m = V.n_cols;
|
||||
|
||||
double avgV = 0;
|
||||
size_t count = 0;
|
||||
double min = DBL_MAX;
|
||||
|
||||
// Iterate over all elements in the matrix (for sparse matrices, this only
|
||||
@@ -57,7 +56,6 @@ class AverageInitialization
|
||||
for (typename MatType::const_row_col_iterator it = V.begin();
|
||||
it != V.end(); ++it)
|
||||
{
|
||||
++count;
|
||||
avgV += *it;
|
||||
// Track the minimum value.
|
||||
if (*it < min)
|
||||
@@ -70,8 +68,53 @@ class AverageInitialization
|
||||
W.randu(n, r);
|
||||
H.randu(r, m);
|
||||
|
||||
W = W + avgV;
|
||||
H = H + avgV;
|
||||
W += avgV;
|
||||
H += + avgV;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the matrix W or H to the average value of V with uniform
|
||||
* random noise added.
|
||||
*
|
||||
* @param V Input matrix.
|
||||
* @param r Rank of matrix.
|
||||
* @param M W or H matrix, to be initialized to the average value of V
|
||||
* with uniform random noise added.
|
||||
* @param whichMatrix If true, initialize W. Otherwise, initialize H.
|
||||
*/
|
||||
template<typename MatType>
|
||||
inline static void InitializeOne(const MatType& V,
|
||||
const size_t r,
|
||||
arma::mat& M,
|
||||
const bool whichMatrix = true)
|
||||
{
|
||||
const size_t n = V.n_rows;
|
||||
const size_t m = V.n_cols;
|
||||
|
||||
double avgV = 0;
|
||||
double min = DBL_MAX;
|
||||
|
||||
// Iterate over all elements in the matrix (for sparse matrices, this only
|
||||
// iterates over nonzeros).
|
||||
for (typename MatType::const_row_col_iterator it = V.begin();
|
||||
it != V.end(); ++it)
|
||||
{
|
||||
avgV += *it;
|
||||
// Track the minimum value.
|
||||
if (*it < min)
|
||||
min = *it;
|
||||
}
|
||||
if (whichMatrix)
|
||||
{
|
||||
// Initialize W to random values
|
||||
M.randu(n, r);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Initialize H to random values
|
||||
M.randu(r, m);
|
||||
}
|
||||
M += sqrt(((avgV / (n * m)) - min) / r);
|
||||
}
|
||||
|
||||
//! Serialize the object (in this case, there is nothing to do).
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @file given_initialization.hpp
|
||||
* @file given_init.hpp
|
||||
* @author Ryan Curtin
|
||||
*
|
||||
* Initialization rule for alternating matrix factorization (AMF). This simple
|
||||
@@ -28,25 +28,62 @@ class GivenInitialization
|
||||
{
|
||||
public:
|
||||
// Empty constructor required for the InitializeRule template.
|
||||
GivenInitialization() { }
|
||||
GivenInitialization() : wIsGiven(false), hIsGiven(false) { }
|
||||
|
||||
// Initialize the GivenInitialization object with the given matrices.
|
||||
GivenInitialization(const arma::mat& w, const arma::mat& h) : w(w), h(h) { }
|
||||
GivenInitialization(const arma::mat& w, const arma::mat& h) :
|
||||
w(w), h(h), wIsGiven(true), hIsGiven(true) { }
|
||||
|
||||
// Initialize the GivenInitialization object, taking control of the given
|
||||
// matrices.
|
||||
GivenInitialization(const arma::mat&& w, const arma::mat&& h) :
|
||||
w(std::move(w)),
|
||||
h(std::move(h))
|
||||
h(std::move(h)),
|
||||
wIsGiven(true),
|
||||
hIsGiven(true)
|
||||
{ }
|
||||
|
||||
// Initialize either H or W with the given matrix.
|
||||
GivenInitialization(const arma::mat& m, const bool whichMatrix = true)
|
||||
{
|
||||
if (whichMatrix)
|
||||
{
|
||||
w = m;
|
||||
wIsGiven = true;
|
||||
hIsGiven = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
h = m;
|
||||
wIsGiven = false;
|
||||
hIsGiven = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize either H or W, taking control of the given matrix.
|
||||
GivenInitialization(const arma::mat&& m, const bool whichMatrix = true)
|
||||
{
|
||||
if (whichMatrix)
|
||||
{
|
||||
w = std::move(m);
|
||||
wIsGiven = true;
|
||||
hIsGiven = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
h = std::move(m);
|
||||
wIsGiven = false;
|
||||
hIsGiven = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fill W and H with random uniform noise.
|
||||
* Fill W and H with given matrices.
|
||||
*
|
||||
* @param V Input matrix.
|
||||
* @param r Rank of decomposition.
|
||||
* @param W W matrix, to be filled with random noise.
|
||||
* @param H H matrix, to be filled with random noise.
|
||||
* @param W W matrix, to be initialized to given matrix.
|
||||
* @param H H matrix, to be initialized to given matrix.
|
||||
*/
|
||||
template<typename MatType>
|
||||
inline void Initialize(const MatType& V,
|
||||
@@ -54,6 +91,16 @@ class GivenInitialization
|
||||
arma::mat& W,
|
||||
arma::mat& H)
|
||||
{
|
||||
// Make sure the initial W, H matrices are given
|
||||
if (!wIsGiven)
|
||||
{
|
||||
Log::Fatal << "Initial W matrix is not given!" << std::endl;
|
||||
}
|
||||
if (!hIsGiven)
|
||||
{
|
||||
Log::Fatal << "Initial H matrix is not given!" << std::endl;
|
||||
}
|
||||
|
||||
// Make sure the initial W, H matrices have correct size.
|
||||
if (w.n_rows != V.n_rows)
|
||||
{
|
||||
@@ -85,6 +132,72 @@ class GivenInitialization
|
||||
H = h;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fill W or H with given matrix.
|
||||
*
|
||||
* @param V Input matrix.
|
||||
* @param r Rank of decomposition.
|
||||
* @param M W or H matrix, to be initialized to given matrix.
|
||||
* @param whichMatrix If true, initialize W. Otherwise, initialize H.
|
||||
*/
|
||||
template<typename MatType>
|
||||
inline void InitializeOne(const MatType& V,
|
||||
const size_t r,
|
||||
arma::mat& M,
|
||||
const bool whichMatrix = true)
|
||||
{
|
||||
if (whichMatrix)
|
||||
{
|
||||
// Make sure the initial W matrix is given.
|
||||
if (!wIsGiven)
|
||||
{
|
||||
Log::Fatal << "Initial W matrix is not given!" << std::endl;
|
||||
}
|
||||
|
||||
// Make sure the initial W matrix has correct size.
|
||||
if (w.n_rows != V.n_rows)
|
||||
{
|
||||
Log::Fatal << "The number of rows in given W (" << w.n_rows
|
||||
<< ") doesn't equal the number of rows in V (" << V.n_rows
|
||||
<< ") !" << std::endl;
|
||||
}
|
||||
if (w.n_cols != r)
|
||||
{
|
||||
Log::Fatal << "The number of columns in given W (" << w.n_cols
|
||||
<< ") doesn't equal the rank of factorization (" << r
|
||||
<< ") !" << std::endl;
|
||||
}
|
||||
|
||||
// Initialize W to the given matrix.
|
||||
M = w;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Make sure the initial H matrix is given.
|
||||
if (!hIsGiven)
|
||||
{
|
||||
Log::Fatal << "Initial H matrix is not given!" << std::endl;
|
||||
}
|
||||
|
||||
// Make sure the initial H matrix has correct size.
|
||||
if (h.n_cols != V.n_cols)
|
||||
{
|
||||
Log::Fatal << "The number of columns in given H (" << h.n_cols
|
||||
<< ") doesn't equal the number of columns in V (" << V.n_cols
|
||||
<< ") !" << std::endl;
|
||||
}
|
||||
if (h.n_rows != r)
|
||||
{
|
||||
Log::Fatal << "The number of rows in given H (" << h.n_rows
|
||||
<< ") doesn't equal the rank of factorization (" << r
|
||||
<< ") !"<< std::endl;
|
||||
}
|
||||
|
||||
// Initialize H to the given matrix.
|
||||
M = h;
|
||||
}
|
||||
}
|
||||
|
||||
//! Serialize the object (in this case, there is nothing to serialize).
|
||||
template<typename Archive>
|
||||
void serialize(Archive& ar, const unsigned int /* version */)
|
||||
@@ -98,6 +211,10 @@ class GivenInitialization
|
||||
arma::mat w;
|
||||
//! The H matrix for initialization.
|
||||
arma::mat h;
|
||||
//! Whether initial W is given.
|
||||
bool wIsGiven;
|
||||
//! Whether initial H is given.
|
||||
bool hIsGiven;
|
||||
};
|
||||
|
||||
} // namespace amf
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
/**
|
||||
* @file merge_init.hpp
|
||||
* @author Ziyang Jiang
|
||||
*
|
||||
* Initialization rule for alternating matrix factorization (AMF). This simple
|
||||
* initialization is performed by assigning a given matrix to W or H and a
|
||||
* random matrix to another one.
|
||||
*
|
||||
* 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_AMF_MERGE_INIT_HPP
|
||||
#define MLPACK_METHODS_AMF_MERGE_INIT_HPP
|
||||
|
||||
#include <mlpack/prereqs.hpp>
|
||||
|
||||
namespace mlpack {
|
||||
namespace amf {
|
||||
|
||||
/**
|
||||
* This initialization rule for AMF simply takes in two initialization rules,
|
||||
* and initialize W with the first rule and H with the second rule.
|
||||
*/
|
||||
template<typename WInitializationRuleType, typename HInitializationRuleType>
|
||||
class MergeInitialization
|
||||
{
|
||||
public:
|
||||
// Empty constructor required for the InitializeRule template
|
||||
MergeInitialization() { }
|
||||
|
||||
// Initialize the MergeInitialization object with existing initialization
|
||||
// rules.
|
||||
MergeInitialization(const WInitializationRuleType& wInitRule,
|
||||
const HInitializationRuleType& hInitRule) :
|
||||
wInitializationRule(wInitRule),
|
||||
hInitializationRule(hInitRule)
|
||||
{ }
|
||||
|
||||
/**
|
||||
* Initialize W and H with the corresponding initialization rules.
|
||||
*
|
||||
* @param V Input matrix.
|
||||
* @param r Rank of decomposition.
|
||||
* @param W W matrix, to be initialized to given matrix.
|
||||
* @param H H matrix, to be initialized to given matrix.
|
||||
*/
|
||||
template<typename MatType>
|
||||
inline void Initialize(const MatType& V,
|
||||
const size_t r,
|
||||
arma::mat& W,
|
||||
arma::mat& H)
|
||||
{
|
||||
wInitializationRule.InitializeOne(V, r, W);
|
||||
hInitializationRule.InitializeOne(V, r, H, false);
|
||||
}
|
||||
|
||||
private:
|
||||
// Initialization rule for W matrix
|
||||
WInitializationRuleType wInitializationRule;
|
||||
// Initialization rule for H matrix
|
||||
HInitializationRuleType hInitializationRule;
|
||||
};
|
||||
|
||||
} // namespace amf
|
||||
} // namespace mlpack
|
||||
|
||||
#endif
|
||||
@@ -51,6 +51,35 @@ class RandomInitialization
|
||||
H.randu(r, m);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fill W or H with random uniform noise.
|
||||
*
|
||||
* @param V Input matrix.
|
||||
* @param r Rank of decomposition.
|
||||
* @param M W or H matrix, to be filled with random noise.
|
||||
* @param whichMatrix If true, initialize W. Otherwise, initialize H.
|
||||
*/
|
||||
template<typename MatType>
|
||||
inline void InitializeOne(const MatType& V,
|
||||
const size_t r,
|
||||
arma::mat& M,
|
||||
const bool whichMatrix = true)
|
||||
{
|
||||
// Simple implementation (left in the header file due to its simplicity).
|
||||
const size_t n = V.n_rows;
|
||||
const size_t m = V.n_cols;
|
||||
|
||||
// Initialize W or H to random values
|
||||
if (whichMatrix)
|
||||
{
|
||||
M.randu(n, r);
|
||||
}
|
||||
else
|
||||
{
|
||||
M.randu(r, m);
|
||||
}
|
||||
}
|
||||
|
||||
//! Serialize the object (in this case, there is nothing to serialize).
|
||||
template<typename Archive>
|
||||
void serialize(Archive& /* ar */, const unsigned int /* version */) { }
|
||||
|
||||
@@ -9,6 +9,7 @@ set(SOURCES
|
||||
softplus_function.hpp
|
||||
swish_function.hpp
|
||||
mish_function.hpp
|
||||
lisht_function.hpp
|
||||
gelu_function.hpp
|
||||
)
|
||||
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
/**
|
||||
* @file lisht_function.hpp
|
||||
* @author Kartik Dutt
|
||||
*
|
||||
* Definition and implementation of the LiSHT function as described by
|
||||
* Swalpa K. Roy, Suvojit Manna, Shiv Ram Dubey and Bidyut B. Chaudhuri.
|
||||
*
|
||||
* For more information, see the following paper.
|
||||
*
|
||||
* @code
|
||||
* @misc{
|
||||
* author = {Swalpa K. Roy, Suvojit Manna, Shiv R. Dubey and
|
||||
* Bidyut B. Chaudhuri},
|
||||
* title = {LiSHT: Non-Parametric Linearly Scaled Hyperbolic Tangent
|
||||
* Activation Function for Neural Networks},
|
||||
* year = {2019}
|
||||
* }
|
||||
* @endcode
|
||||
*
|
||||
* 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_ACTIVATION_FUNCTIONS_LISHT_FUNCTION_HPP
|
||||
#define MLPACK_METHODS_ANN_ACTIVATION_FUNCTIONS_LISHT_FUNCTION_HPP
|
||||
|
||||
#include <mlpack/prereqs.hpp>
|
||||
#include <algorithm>
|
||||
|
||||
namespace mlpack {
|
||||
namespace ann /** Artificial Neural Network. */ {
|
||||
|
||||
/**
|
||||
* The LiSHT function, defined by
|
||||
*
|
||||
* @f{eqnarray*}{
|
||||
* f(x) = x * tanh(x)
|
||||
* f'(x) = tanh(x) + x * (1 - tanh^{2}(x))
|
||||
* @f}
|
||||
*/
|
||||
class LiSHTFunction
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Computes the LiSHT function.
|
||||
*
|
||||
* @param x Input data.
|
||||
* @return f(x).
|
||||
*/
|
||||
static double Fn(const double x)
|
||||
{
|
||||
return x * std::tanh(x);
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the LiSHT function.
|
||||
*
|
||||
* @param x Input data.
|
||||
* @param y The resulting output activation.
|
||||
*/
|
||||
template <typename InputVecType, typename OutputVecType>
|
||||
static void Fn(const InputVecType &x, OutputVecType &y)
|
||||
{
|
||||
y = x % arma::tanh(x);
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the first derivative of the LiSHT function.
|
||||
*
|
||||
* @param y Input data.
|
||||
* @return f'(x)
|
||||
*/
|
||||
static double Deriv(const double y)
|
||||
{
|
||||
return std::tanh(y) + y * (1 - std::pow(std::tanh(y), 2));
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the first derivatives of the LiSHT function.
|
||||
*
|
||||
* @param y Input activations.
|
||||
* @param x The resulting derivatives.
|
||||
*/
|
||||
template <typename InputVecType, typename OutputVecType>
|
||||
static void Deriv(const InputVecType &y, OutputVecType &x)
|
||||
{
|
||||
x = arma::tanh(y) + y % (1 - arma::pow(arma::tanh(y), 2));
|
||||
}
|
||||
}; // class LishtFunction
|
||||
|
||||
} // namespace ann
|
||||
} // namespace mlpack
|
||||
|
||||
#endif
|
||||
@@ -85,7 +85,7 @@ class AtrousConvolution
|
||||
const size_t inputHeight = 0,
|
||||
const size_t dilationWidth = 1,
|
||||
const size_t dilationHeight = 1,
|
||||
const std::string paddingType = "None");
|
||||
const std::string& paddingType = "None");
|
||||
|
||||
/**
|
||||
* Create the AtrousConvolution object using the specified number of
|
||||
@@ -116,13 +116,13 @@ class AtrousConvolution
|
||||
const size_t kernelHeight,
|
||||
const size_t strideWidth,
|
||||
const size_t strideHeight,
|
||||
const std::tuple<size_t, size_t> padW,
|
||||
const std::tuple<size_t, size_t> padH,
|
||||
const std::tuple<size_t, size_t>& padW,
|
||||
const std::tuple<size_t, size_t>& padH,
|
||||
const size_t inputWidth = 0,
|
||||
const size_t inputHeight = 0,
|
||||
const size_t dilationWidth = 1,
|
||||
const size_t dilationHeight = 1,
|
||||
const std::string paddingType = "None");
|
||||
const std::string& paddingType = "None");
|
||||
|
||||
/*
|
||||
* Set the weight and bias term.
|
||||
|
||||
@@ -63,45 +63,23 @@ AtrousConvolution<
|
||||
const size_t inputHeight,
|
||||
const size_t dilationWidth,
|
||||
const size_t dilationHeight,
|
||||
const std::string paddingType) :
|
||||
inSize(inSize),
|
||||
outSize(outSize),
|
||||
kernelWidth(kernelWidth),
|
||||
kernelHeight(kernelHeight),
|
||||
strideWidth(strideWidth),
|
||||
strideHeight(strideHeight),
|
||||
inputWidth(inputWidth),
|
||||
inputHeight(inputHeight),
|
||||
outputWidth(0),
|
||||
outputHeight(0),
|
||||
dilationWidth(dilationWidth),
|
||||
dilationHeight(dilationHeight)
|
||||
const std::string& paddingType) :
|
||||
AtrousConvolution(
|
||||
inSize,
|
||||
outSize,
|
||||
kernelWidth,
|
||||
kernelHeight,
|
||||
strideWidth,
|
||||
strideHeight,
|
||||
std::tuple<size_t, size_t>(padW, padW),
|
||||
std::tuple<size_t, size_t>(padH, padH),
|
||||
inputWidth,
|
||||
inputHeight,
|
||||
dilationWidth,
|
||||
dilationHeight,
|
||||
paddingType)
|
||||
{
|
||||
weights.set_size((outSize * inSize * kernelWidth * kernelHeight) + outSize,
|
||||
1);
|
||||
|
||||
// Transform paddingType to lowercase.
|
||||
std::string paddingTypeLow = paddingType;
|
||||
std::transform(paddingType.begin(), paddingType.end(), paddingTypeLow.begin(),
|
||||
[](unsigned char c){ return std::tolower(c); });
|
||||
|
||||
size_t padWLeft = padW;
|
||||
size_t padWRight = padW;
|
||||
size_t padHBottom = padH;
|
||||
size_t padHTop = padH;
|
||||
if (paddingTypeLow == "valid")
|
||||
{
|
||||
padWLeft = 0;
|
||||
padWRight = 0;
|
||||
padHTop = 0;
|
||||
padHBottom = 0;
|
||||
}
|
||||
else if (paddingTypeLow == "same")
|
||||
{
|
||||
InitializeSamePadding(padWLeft, padWRight, padHTop, padHBottom);
|
||||
}
|
||||
|
||||
padding = ann::Padding<>(padWLeft, padWRight, padHTop, padHBottom);
|
||||
// Nothing to do here.
|
||||
}
|
||||
|
||||
template<
|
||||
@@ -124,13 +102,13 @@ AtrousConvolution<
|
||||
const size_t kernelHeight,
|
||||
const size_t strideWidth,
|
||||
const size_t strideHeight,
|
||||
const std::tuple<size_t, size_t> padW,
|
||||
const std::tuple<size_t, size_t> padH,
|
||||
const std::tuple<size_t, size_t>& padW,
|
||||
const std::tuple<size_t, size_t>& padH,
|
||||
const size_t inputWidth,
|
||||
const size_t inputHeight,
|
||||
const size_t dilationWidth,
|
||||
const size_t dilationHeight,
|
||||
const std::string paddingType) :
|
||||
const std::string& paddingType) :
|
||||
inSize(inSize),
|
||||
outSize(outSize),
|
||||
kernelWidth(kernelWidth),
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <mlpack/methods/ann/activation_functions/hard_sigmoid_function.hpp>
|
||||
#include <mlpack/methods/ann/activation_functions/swish_function.hpp>
|
||||
#include <mlpack/methods/ann/activation_functions/mish_function.hpp>
|
||||
#include <mlpack/methods/ann/activation_functions/lisht_function.hpp>
|
||||
#include <mlpack/methods/ann/activation_functions/gelu_function.hpp>
|
||||
|
||||
namespace mlpack {
|
||||
@@ -209,6 +210,17 @@ template <
|
||||
using MishFunctionLayer = BaseLayer<
|
||||
ActivationFunction, InputDataType, OutputDataType>;
|
||||
|
||||
/**
|
||||
* Standard LiSHT-Layer using the LiSHT activation function.
|
||||
*/
|
||||
template <
|
||||
class ActivationFunction = LiSHTFunction,
|
||||
typename InputDataType = arma::mat,
|
||||
typename OutputDataType = arma::mat
|
||||
>
|
||||
using LiSHTFunctionLayer = BaseLayer<
|
||||
ActivationFunction, InputDataType, OutputDataType>;
|
||||
|
||||
/**
|
||||
* Standard GELU-Layer using the GELU activation function.
|
||||
*/
|
||||
|
||||
@@ -76,7 +76,7 @@ class Convolution
|
||||
const size_t padH = 0,
|
||||
const size_t inputWidth = 0,
|
||||
const size_t inputHeight = 0,
|
||||
const std::string paddingType = "None");
|
||||
const std::string& paddingType = "None");
|
||||
|
||||
/**
|
||||
* Create the Convolution object using the specified number of input maps,
|
||||
@@ -104,11 +104,11 @@ class Convolution
|
||||
const size_t kernelHeight,
|
||||
const size_t strideWidth,
|
||||
const size_t strideHeight,
|
||||
const std::tuple<size_t, size_t> padW,
|
||||
const std::tuple<size_t, size_t> padH,
|
||||
const std::tuple<size_t, size_t>& padW,
|
||||
const std::tuple<size_t, size_t>& padH,
|
||||
const size_t inputWidth = 0,
|
||||
const size_t inputHeight = 0,
|
||||
const std::string paddingType = "None");
|
||||
const std::string& paddingType = "None");
|
||||
|
||||
/*
|
||||
* Set the weight and bias term.
|
||||
|
||||
@@ -60,43 +60,20 @@ Convolution<
|
||||
const size_t padH,
|
||||
const size_t inputWidth,
|
||||
const size_t inputHeight,
|
||||
const std::string paddingType) :
|
||||
inSize(inSize),
|
||||
outSize(outSize),
|
||||
kernelWidth(kernelWidth),
|
||||
kernelHeight(kernelHeight),
|
||||
strideWidth(strideWidth),
|
||||
strideHeight(strideHeight),
|
||||
padWLeft(padW),
|
||||
padWRight(padW),
|
||||
padHBottom(padH),
|
||||
padHTop(padH),
|
||||
inputWidth(inputWidth),
|
||||
inputHeight(inputHeight),
|
||||
outputWidth(0),
|
||||
outputHeight(0)
|
||||
const std::string& paddingType) :
|
||||
Convolution(
|
||||
inSize,
|
||||
outSize,
|
||||
kernelWidth,
|
||||
kernelHeight,
|
||||
strideWidth,
|
||||
strideHeight,
|
||||
std::tuple<size_t, size_t>(padW, padW),
|
||||
std::tuple<size_t, size_t>(padH, padH),
|
||||
inputWidth,
|
||||
inputHeight)
|
||||
{
|
||||
weights.set_size((outSize * inSize * kernelWidth * kernelHeight) + outSize,
|
||||
1);
|
||||
|
||||
// Transform paddingType to lowercase.
|
||||
std::string paddingTypeLow = paddingType;
|
||||
std::transform(paddingType.begin(), paddingType.end(), paddingTypeLow.begin(),
|
||||
[](unsigned char c){ return std::tolower(c); });
|
||||
|
||||
if (paddingTypeLow == "valid")
|
||||
{
|
||||
padWLeft = 0;
|
||||
padWRight = 0;
|
||||
padHTop = 0;
|
||||
padHBottom = 0;
|
||||
}
|
||||
else if (paddingTypeLow == "same")
|
||||
{
|
||||
InitializeSamePadding();
|
||||
}
|
||||
|
||||
padding = ann::Padding<>(padWLeft, padWRight, padHTop, padHBottom);
|
||||
// Nothing to do here.
|
||||
}
|
||||
|
||||
template<
|
||||
@@ -119,11 +96,11 @@ Convolution<
|
||||
const size_t kernelHeight,
|
||||
const size_t strideWidth,
|
||||
const size_t strideHeight,
|
||||
const std::tuple<size_t, size_t> padW,
|
||||
const std::tuple<size_t, size_t> padH,
|
||||
const std::tuple<size_t, size_t>& padW,
|
||||
const std::tuple<size_t, size_t>& padH,
|
||||
const size_t inputWidth,
|
||||
const size_t inputHeight,
|
||||
const std::string paddingType) :
|
||||
const std::string& paddingType) :
|
||||
inSize(inSize),
|
||||
outSize(outSize),
|
||||
kernelWidth(kernelWidth),
|
||||
|
||||
@@ -67,12 +67,13 @@ class TransposedConvolution
|
||||
* @param kernelHeight Height of the filter/kernel.
|
||||
* @param strideWidth Stride of filter application in the x direction.
|
||||
* @param strideHeight Stride of filter application in the y direction.
|
||||
* @param padWidth Padding width of the input.
|
||||
* @param padHeight Padding height of the input.
|
||||
* @param padW Padding width of the input.
|
||||
* @param padH Padding height of the input.
|
||||
* @param inputWidth The width of the input data.
|
||||
* @param inputHeight The height of the input data.
|
||||
* @param outputWidth The width of the output data.
|
||||
* @param outputHeight The height of the output data.
|
||||
* @param paddingType The type of padding (Valid or Same). Defaults to None.
|
||||
*/
|
||||
TransposedConvolution(const size_t inSize,
|
||||
const size_t outSize,
|
||||
@@ -80,12 +81,55 @@ class TransposedConvolution
|
||||
const size_t kernelHeight,
|
||||
const size_t strideWidth = 1,
|
||||
const size_t strideHeight = 1,
|
||||
const size_t padWidth = 0,
|
||||
const size_t padHeight = 0,
|
||||
const size_t padW = 0,
|
||||
const size_t padH = 0,
|
||||
const size_t inputWidth = 0,
|
||||
const size_t inputHeight = 0,
|
||||
const size_t outputWidth = 0,
|
||||
const size_t outputHeight = 0);
|
||||
const size_t outputHeight = 0,
|
||||
const std::string& paddingType = "None");
|
||||
|
||||
/**
|
||||
* Create the Transposed Convolution object using the specified number of
|
||||
* input maps, output maps, filter size, stride and padding parameter.
|
||||
*
|
||||
* Note: The equivalent stride of a transposed convolution operation is always
|
||||
* equal to 1. In this implementation, stride of filter represents the stride
|
||||
* of the associated convolution operation.
|
||||
* Note: Padding of input represents padding of associated convolution
|
||||
* operation.
|
||||
*
|
||||
* @param inSize The number of input maps.
|
||||
* @param outSize The number of output maps.
|
||||
* @param kernelWidth Width of the filter/kernel.
|
||||
* @param kernelHeight Height of the filter/kernel.
|
||||
* @param strideWidth Stride of filter application in the x direction.
|
||||
* @param strideHeight Stride of filter application in the y direction.
|
||||
* @param padW A two-value tuple indicating padding widths of the input.
|
||||
* First value is padding at left side. Second value is padding on
|
||||
* right side.
|
||||
* @param padH A two-value tuple indicating padding heights of the input.
|
||||
* First value is padding at top. Second value is padding on
|
||||
* bottom.
|
||||
* @param inputWidth The width of the input data.
|
||||
* @param inputHeight The height of the input data.
|
||||
* @param outputWidth The width of the output data.
|
||||
* @param outputHeight The height of the output data.
|
||||
* @param paddingType The type of padding (Valid or Same). Defaults to None.
|
||||
*/
|
||||
TransposedConvolution(const size_t inSize,
|
||||
const size_t outSize,
|
||||
const size_t kernelWidth,
|
||||
const size_t kernelHeight,
|
||||
const size_t strideWidth,
|
||||
const size_t strideHeight,
|
||||
const std::tuple<size_t, size_t>& padW,
|
||||
const std::tuple<size_t, size_t>& padH,
|
||||
const size_t inputWidth = 0,
|
||||
const size_t inputHeight = 0,
|
||||
const size_t outputWidth = 0,
|
||||
const size_t outputHeight = 0,
|
||||
const std::string& paddingType = "None");
|
||||
|
||||
/*
|
||||
* Set the weight and bias term.
|
||||
@@ -199,15 +243,25 @@ class TransposedConvolution
|
||||
//! Modify the stride height.
|
||||
size_t& StrideHeight() { return strideHeight; }
|
||||
|
||||
//! Get the padding width.
|
||||
size_t PadWidth() const { return padWidth; }
|
||||
//! Modify the padding width.
|
||||
size_t& PadWidth() { return padWidth; }
|
||||
//! Get the top padding height.
|
||||
size_t PadHTop() const { return padHTop; }
|
||||
//! Modify the top padding height.
|
||||
size_t& PadHTop() { return padHTop; }
|
||||
|
||||
//! Get the padding height.
|
||||
size_t PadHeight() const { return padHeight; }
|
||||
//! Modify the padding height.
|
||||
size_t& PadHeight() { return padHeight; }
|
||||
//! Get the bottom padding height.
|
||||
size_t PadHBottom() const { return padHBottom; }
|
||||
//! Modify the bottom padding height.
|
||||
size_t& PadHBottom() { return padHBottom; }
|
||||
|
||||
//! Get the left padding width.
|
||||
size_t PadWLeft() const { return padWLeft; }
|
||||
//! Modify the left padding width.
|
||||
size_t& PadWLeft() { return padWLeft; }
|
||||
|
||||
//! Get the right padding width.
|
||||
size_t PadWRight() const { return padWRight; }
|
||||
//! Modify the right padding width.
|
||||
size_t& PadWRight() { return padWRight; }
|
||||
|
||||
//! Modify the bias weights of the layer.
|
||||
arma::mat& Bias() { return bias; }
|
||||
@@ -235,6 +289,11 @@ class TransposedConvolution
|
||||
output.slice(s) = arma::fliplr(arma::flipud(input.slice(s)));
|
||||
}
|
||||
|
||||
/*
|
||||
* Function to assign padding such that output size is same as input size.
|
||||
*/
|
||||
void InitializeSamePadding();
|
||||
|
||||
/*
|
||||
* Rotates a dense matrix counterclockwise by 180 degrees.
|
||||
*
|
||||
@@ -328,11 +387,17 @@ class TransposedConvolution
|
||||
//! Locally-stored stride of the filter in y-direction.
|
||||
size_t strideHeight;
|
||||
|
||||
//! Locally-stored padding width.
|
||||
size_t padWidth;
|
||||
//! Locally-stored left-side padding width.
|
||||
size_t padWLeft;
|
||||
|
||||
//! Locally-stored padding height.
|
||||
size_t padHeight;
|
||||
//! Locally-stored right-side padding width.
|
||||
size_t padWRight;
|
||||
|
||||
//! Locally-stored bottom padding height.
|
||||
size_t padHBottom;
|
||||
|
||||
//! Locally-stored top padding height.
|
||||
size_t padHTop;
|
||||
|
||||
//! Locally-stored number of zeros added to the right of input.
|
||||
size_t aW;
|
||||
|
||||
@@ -57,18 +57,68 @@ TransposedConvolution<
|
||||
const size_t kernelHeight,
|
||||
const size_t strideWidth,
|
||||
const size_t strideHeight,
|
||||
const size_t padWidth,
|
||||
const size_t padHeight,
|
||||
const size_t padW,
|
||||
const size_t padH,
|
||||
const size_t inputWidth,
|
||||
const size_t inputHeight,
|
||||
const size_t outputWidth,
|
||||
const size_t outputHeight) :
|
||||
const size_t outputHeight,
|
||||
const std::string& paddingType) :
|
||||
TransposedConvolution(
|
||||
inSize,
|
||||
outSize,
|
||||
kernelWidth,
|
||||
kernelHeight,
|
||||
strideWidth,
|
||||
strideHeight,
|
||||
std::tuple<size_t, size_t>(padW, padW),
|
||||
std::tuple<size_t, size_t>(padH, padH),
|
||||
inputWidth,
|
||||
inputHeight,
|
||||
outputWidth,
|
||||
outputHeight,
|
||||
paddingType)
|
||||
{
|
||||
// Nothing to do here.
|
||||
}
|
||||
|
||||
template<
|
||||
typename ForwardConvolutionRule,
|
||||
typename BackwardConvolutionRule,
|
||||
typename GradientConvolutionRule,
|
||||
typename InputDataType,
|
||||
typename OutputDataType
|
||||
>
|
||||
TransposedConvolution<
|
||||
ForwardConvolutionRule,
|
||||
BackwardConvolutionRule,
|
||||
GradientConvolutionRule,
|
||||
InputDataType,
|
||||
OutputDataType
|
||||
>::TransposedConvolution(
|
||||
const size_t inSize,
|
||||
const size_t outSize,
|
||||
const size_t kernelWidth,
|
||||
const size_t kernelHeight,
|
||||
const size_t strideWidth,
|
||||
const size_t strideHeight,
|
||||
const std::tuple<size_t, size_t>& padW,
|
||||
const std::tuple<size_t, size_t>& padH,
|
||||
const size_t inputWidth,
|
||||
const size_t inputHeight,
|
||||
const size_t outputWidth,
|
||||
const size_t outputHeight,
|
||||
const std::string& paddingType) :
|
||||
inSize(inSize),
|
||||
outSize(outSize),
|
||||
kernelWidth(kernelWidth),
|
||||
kernelHeight(kernelHeight),
|
||||
strideWidth(strideWidth),
|
||||
strideHeight(strideHeight),
|
||||
padWLeft(std::get<0>(padW)),
|
||||
padWRight(std::get<1>(padW)),
|
||||
padHBottom(std::get<1>(padH)),
|
||||
padHTop(std::get<0>(padH)),
|
||||
inputWidth(inputWidth),
|
||||
inputHeight(inputHeight),
|
||||
outputWidth(outputWidth),
|
||||
@@ -76,26 +126,49 @@ TransposedConvolution<
|
||||
{
|
||||
weights.set_size((outSize * inSize * kernelWidth * kernelHeight) + outSize,
|
||||
1);
|
||||
// Transform paddingType to lowercase.
|
||||
std::string paddingTypeLow = paddingType;
|
||||
std::transform(paddingType.begin(), paddingType.end(), paddingTypeLow.begin(),
|
||||
[](unsigned char c){ return std::tolower(c); });
|
||||
|
||||
aW = (outputWidth + 2 * padWidth - kernelWidth) % strideWidth;
|
||||
aH = (outputHeight + 2 * padHeight - kernelHeight) % strideHeight;
|
||||
if (paddingTypeLow == "valid")
|
||||
{
|
||||
// Set Padding to 0.
|
||||
padWLeft = 0;
|
||||
padWRight = 0;
|
||||
padHTop = 0;
|
||||
padHBottom = 0;
|
||||
}
|
||||
else if (paddingTypeLow == "same")
|
||||
{
|
||||
InitializeSamePadding();
|
||||
}
|
||||
|
||||
const size_t padWidthForward = kernelWidth - padWidth - 1;
|
||||
const size_t padHeightForward = kernelHeight - padHeight - 1;
|
||||
const size_t totalPadWidth = padWLeft + padWRight;
|
||||
const size_t totalPadHeight = padHTop + padHBottom;
|
||||
|
||||
paddingForward = ann::Padding<>(padWidthForward, padWidthForward + aW,
|
||||
padHeightForward, padHeightForward + aH);
|
||||
paddingBackward = ann::Padding<>(padWidth, padWidth, padHeight, padHeight);
|
||||
aW = (outputWidth + totalPadWidth - kernelWidth) % strideWidth;
|
||||
aH = (outputHeight + totalPadHeight - kernelHeight) % strideHeight;
|
||||
|
||||
const size_t padWidthLeftForward = kernelWidth - padWLeft - 1;
|
||||
const size_t padHeightTopForward = kernelHeight - padHTop - 1;
|
||||
const size_t padWidthRightForward = kernelWidth - padWRight - 1;
|
||||
const size_t padHeightBottomtForward = kernelHeight - padHBottom - 1;
|
||||
|
||||
paddingForward = ann::Padding<>(padWidthLeftForward,
|
||||
padWidthRightForward + aW, padHeightTopForward,
|
||||
padHeightBottomtForward + aH);
|
||||
paddingBackward = ann::Padding<>(padWLeft, padWRight, padHTop, padHBottom);
|
||||
|
||||
// Check if the output height and width are possible given the other
|
||||
// parameters of the layer.
|
||||
if (outputWidth != strideWidth * (inputWidth - 1) +
|
||||
aW + kernelWidth - 2 * padWidth ||
|
||||
aW + kernelWidth - totalPadWidth ||
|
||||
outputHeight != strideHeight * (inputHeight - 1) +
|
||||
aH + kernelHeight - 2 * padHeight)
|
||||
aH + kernelHeight - totalPadHeight)
|
||||
{
|
||||
Log::Fatal << "The output width / output height is not possible given "
|
||||
<< "the other parameters of the layer." << std::endl;
|
||||
<< "the other parameters of the layer." << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,12 +217,13 @@ void TransposedConvolution<
|
||||
{
|
||||
InsertZeros(inputTemp, strideWidth, strideHeight, inputExpandedTemp);
|
||||
|
||||
if (paddingForward.PadWLeft() != 0 || paddingForward.PadHTop() != 0 ||
|
||||
aW != 0 || aH != 0)
|
||||
if (paddingForward.PadWLeft() != 0 || paddingForward.PadWRight() != 0 ||
|
||||
paddingForward.PadHTop() != 0 || paddingForward.PadHBottom() != 0)
|
||||
{
|
||||
inputPaddedTemp.set_size(inputExpandedTemp.n_rows +
|
||||
paddingForward.PadWLeft() * 2 + aW, inputExpandedTemp.n_cols +
|
||||
paddingForward.PadHTop() * 2 + aH, inputExpandedTemp.n_slices);
|
||||
paddingForward.PadWLeft() + paddingForward.PadWRight(),
|
||||
inputExpandedTemp.n_cols + paddingForward.PadHTop() +
|
||||
paddingForward.PadHBottom(), inputExpandedTemp.n_slices);
|
||||
|
||||
for (size_t i = 0; i < inputExpandedTemp.n_slices; ++i)
|
||||
{
|
||||
@@ -165,12 +239,13 @@ void TransposedConvolution<
|
||||
}
|
||||
}
|
||||
else if (paddingForward.PadWLeft() != 0 ||
|
||||
paddingForward.PadWRight() != 0 ||
|
||||
paddingForward.PadHTop() != 0 ||
|
||||
aW != 0 ||
|
||||
aH != 0)
|
||||
paddingForward.PadHBottom() != 0)
|
||||
{
|
||||
inputPaddedTemp.set_size(inputTemp.n_rows + paddingForward.PadWLeft() * 2 +
|
||||
aW, inputTemp.n_cols + paddingForward.PadHTop() * 2 + aH,
|
||||
inputPaddedTemp.set_size(inputTemp.n_rows + paddingForward.PadWLeft() +
|
||||
paddingForward.PadWRight(), inputTemp.n_cols +
|
||||
paddingForward.PadHTop() + paddingForward.PadHBottom(),
|
||||
inputTemp.n_slices);
|
||||
|
||||
for (size_t i = 0; i < inputTemp.n_slices; ++i)
|
||||
@@ -202,9 +277,9 @@ void TransposedConvolution<
|
||||
if (strideWidth > 1 ||
|
||||
strideHeight > 1 ||
|
||||
paddingForward.PadWLeft() != 0 ||
|
||||
paddingForward.PadWRight() != 0 ||
|
||||
paddingForward.PadHTop() != 0 ||
|
||||
aW != 0 ||
|
||||
aH != 0)
|
||||
paddingForward.PadHBottom() != 0)
|
||||
{
|
||||
ForwardConvolutionRule::Convolution(inputPaddedTemp.slice(inMap +
|
||||
batchCount * inSize), rotatedFilter, convOutput, 1, 1);
|
||||
@@ -242,11 +317,13 @@ void TransposedConvolution<
|
||||
arma::Cube<eT> mappedError(gy.memptr(), outputWidth, outputHeight,
|
||||
outSize * batchSize, false, false);
|
||||
arma::Cube<eT> mappedErrorPadded;
|
||||
if (paddingBackward.PadWLeft() != 0 || paddingBackward.PadHTop() != 0)
|
||||
if (paddingBackward.PadWLeft() != 0 || paddingBackward.PadWRight() != 0 ||
|
||||
paddingBackward.PadHTop() != 0 || paddingBackward.PadHBottom() != 0)
|
||||
{
|
||||
mappedErrorPadded.set_size(mappedError.n_rows +
|
||||
paddingBackward.PadWLeft() * 2, mappedError.n_cols +
|
||||
paddingBackward.PadHTop() * 2, mappedError.n_slices);
|
||||
paddingBackward.PadWLeft() + paddingBackward.PadWRight(),
|
||||
mappedError.n_cols + paddingBackward.PadHTop() +
|
||||
paddingBackward.PadHBottom(), mappedError.n_slices);
|
||||
|
||||
for (size_t i = 0; i < mappedError.n_slices; ++i)
|
||||
{
|
||||
@@ -273,7 +350,8 @@ void TransposedConvolution<
|
||||
{
|
||||
arma::Mat<eT> output;
|
||||
|
||||
if (paddingBackward.PadWLeft() != 0 || paddingBackward.PadHTop() != 0)
|
||||
if (paddingBackward.PadWLeft() != 0 || paddingBackward.PadWRight() != 0 ||
|
||||
paddingBackward.PadHTop() != 0 || paddingBackward.PadHBottom() != 0)
|
||||
{
|
||||
BackwardConvolutionRule::Convolution(mappedErrorPadded.slice(outMap),
|
||||
weight.slice(outMapIdx), output, strideWidth, strideHeight);
|
||||
@@ -334,9 +412,9 @@ void TransposedConvolution<
|
||||
if (strideWidth > 1 ||
|
||||
strideHeight > 1 ||
|
||||
paddingForward.PadWLeft() != 0 ||
|
||||
paddingForward.PadWRight() != 0 ||
|
||||
paddingForward.PadHTop() != 0 ||
|
||||
aW != 0 ||
|
||||
aH != 0)
|
||||
paddingForward.PadHBottom() != 0)
|
||||
{
|
||||
inputSlice = inputPaddedTemp.slice(inMap + batchCount * inSize);
|
||||
}
|
||||
@@ -387,6 +465,10 @@ void TransposedConvolution<
|
||||
ar & BOOST_SERIALIZATION_NVP(padWidth);
|
||||
ar & BOOST_SERIALIZATION_NVP(padHeight);
|
||||
}
|
||||
ar &BOOST_SERIALIZATION_NVP(padWLeft);
|
||||
ar &BOOST_SERIALIZATION_NVP(padWRight);
|
||||
ar &BOOST_SERIALIZATION_NVP(padHBottom);
|
||||
ar &BOOST_SERIALIZATION_NVP(padHTop);
|
||||
ar & BOOST_SERIALIZATION_NVP(inputWidth);
|
||||
ar & BOOST_SERIALIZATION_NVP(inputHeight);
|
||||
ar & BOOST_SERIALIZATION_NVP(outputWidth);
|
||||
@@ -402,9 +484,49 @@ void TransposedConvolution<
|
||||
{
|
||||
weights.set_size((outSize * inSize * kernelWidth * kernelHeight) + outSize,
|
||||
1);
|
||||
size_t totalPadWidth = padWLeft + padWRight;
|
||||
size_t totalPadHeight = padHTop + padHBottom;
|
||||
aW = (outputWidth + kernelWidth - totalPadWidth - 2) % strideWidth;
|
||||
aH = (outputHeight + kernelHeight - totalPadHeight - 2) % strideHeight;
|
||||
}
|
||||
}
|
||||
template<
|
||||
typename ForwardConvolutionRule,
|
||||
typename BackwardConvolutionRule,
|
||||
typename GradientConvolutionRule,
|
||||
typename InputDataType,
|
||||
typename OutputDataType
|
||||
>
|
||||
void TransposedConvolution<
|
||||
ForwardConvolutionRule,
|
||||
BackwardConvolutionRule,
|
||||
GradientConvolutionRule,
|
||||
InputDataType,
|
||||
OutputDataType
|
||||
>::InitializeSamePadding(){
|
||||
/**
|
||||
* Using O=s*(I-1) + K -2P + A
|
||||
* where
|
||||
* s=stride
|
||||
* I=Input Shape
|
||||
* K=Kernel Size
|
||||
* P=Padding
|
||||
*/
|
||||
const size_t totalHorizontalPadding = (strideWidth - 1) * inputWidth +
|
||||
kernelWidth - strideWidth;
|
||||
const size_t totalVerticalPadding = (strideHeight - 1) * inputHeight +
|
||||
kernelHeight - strideHeight;
|
||||
|
||||
aW = (outputWidth + kernelWidth - 2 * padWidth - 2) % strideWidth;
|
||||
aH = (outputHeight + kernelHeight - 2 * padHeight - 2) % strideHeight;
|
||||
padWLeft = totalVerticalPadding / 2;
|
||||
padWRight = totalVerticalPadding - totalVerticalPadding / 2;
|
||||
padHTop = totalHorizontalPadding / 2;
|
||||
padHBottom = totalHorizontalPadding - totalHorizontalPadding / 2;
|
||||
|
||||
// If Padding is negative throw a fatal error.
|
||||
if (totalHorizontalPadding < 0 || totalVerticalPadding < 0)
|
||||
{
|
||||
Log::Fatal << "The output width / output height is not possible given "
|
||||
<< "same padding for the layer." << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,8 @@ set(SOURCES
|
||||
earth_mover_distance_impl.hpp
|
||||
kl_divergence.hpp
|
||||
kl_divergence_impl.hpp
|
||||
mean_bias_error.hpp
|
||||
mean_bias_error_impl.hpp
|
||||
mean_squared_error.hpp
|
||||
mean_squared_error_impl.hpp
|
||||
mean_squared_logarithmic_error.hpp
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
/**
|
||||
* @file mean_bias_error.hpp
|
||||
* @author Saksham Rastogi
|
||||
*
|
||||
* Definition of the mean bias error performance function.
|
||||
*
|
||||
* 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_LOSS_FUNCTION_MEAN_BIAS_ERROR_HPP
|
||||
#define MLPACK_METHODS_ANN_LOSS_FUNCTION_MEAN_BIAS_ERROR_HPP
|
||||
|
||||
#include <mlpack/prereqs.hpp>
|
||||
|
||||
namespace mlpack {
|
||||
namespace ann /** Artificial Neural Network. */ {
|
||||
|
||||
/**
|
||||
* The mean bias error performance function measures the network's
|
||||
* performance according to the mean of errors.
|
||||
*
|
||||
* @tparam InputDataType Type of the input data (arma::colvec, arma::mat,
|
||||
* arma::sp_mat or arma::cube).
|
||||
* @tparam OutputDataType Type of the output data (arma::colvec, arma::mat,
|
||||
* arma::sp_mat or arma::cube).
|
||||
*/
|
||||
template <
|
||||
typename InputDataType = arma::mat,
|
||||
typename OutputDataType = arma::mat
|
||||
>
|
||||
class MeanBiasError
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Create the MeanBiasError object.
|
||||
*/
|
||||
MeanBiasError();
|
||||
|
||||
/**
|
||||
* Computes the mean bias error function.
|
||||
*
|
||||
* @param input Input data used for evaluating the specified function.
|
||||
* @param target The target vector.
|
||||
*/
|
||||
template<typename InputType, typename TargetType>
|
||||
double Forward(const InputType&& input, const TargetType&& target);
|
||||
|
||||
/**
|
||||
* Ordinary feed backward pass of a neural network.
|
||||
*
|
||||
* @param input The propagated input activation.
|
||||
* @param target The target vector.
|
||||
* @param output The calculated error.
|
||||
*/
|
||||
template<typename InputType, typename TargetType, typename OutputType>
|
||||
void Backward(const InputType&& input,
|
||||
const TargetType&& target,
|
||||
OutputType&& output);
|
||||
|
||||
//! Get the output parameter.
|
||||
OutputDataType& OutputParameter() const { return outputParameter; }
|
||||
//! Modify the output parameter.
|
||||
OutputDataType& OutputParameter() { return outputParameter; }
|
||||
|
||||
/**
|
||||
* Serialize the layer.
|
||||
*/
|
||||
template<typename Archive>
|
||||
void serialize(Archive& ar, const unsigned int /* version */);
|
||||
|
||||
private:
|
||||
//! Locally-stored output parameter object.
|
||||
OutputDataType outputParameter;
|
||||
}; // class MeanBiasError
|
||||
|
||||
} // namespace ann
|
||||
} // namespace mlpack
|
||||
|
||||
// Include implementation.
|
||||
#include "mean_bias_error_impl.hpp"
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,59 @@
|
||||
/**
|
||||
* @file mean_bias_error_impl.hpp
|
||||
* @author Saksham Rastogi
|
||||
*
|
||||
* Implementation of the mean bias error performance function.
|
||||
*
|
||||
* 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_LOSS_FUNCTION_MEAN_BIAS_ERROR_IMPL_HPP
|
||||
#define MLPACK_METHODS_ANN_LOSS_FUNCTION_MEAN_BIAS_ERROR_IMPL_HPP
|
||||
|
||||
|
||||
// In case it hasn't yet been included.
|
||||
#include "mean_bias_error.hpp"
|
||||
|
||||
namespace mlpack {
|
||||
namespace ann /** Artificial Neural Network. */ {
|
||||
|
||||
template<typename InputDataType, typename OutputDataType>
|
||||
MeanBiasError<InputDataType, OutputDataType>::MeanBiasError()
|
||||
{
|
||||
// Nothing to do here.
|
||||
}
|
||||
|
||||
template<typename InputDataType, typename OutputDataType>
|
||||
template<typename InputType, typename TargetType>
|
||||
double MeanBiasError<InputDataType, OutputDataType>::Forward(
|
||||
const InputType&& input, const TargetType&& target)
|
||||
{
|
||||
return arma::accu(target - input) / target.n_cols;
|
||||
}
|
||||
|
||||
template<typename InputDataType, typename OutputDataType>
|
||||
template<typename InputType, typename TargetType, typename OutputType>
|
||||
void MeanBiasError<InputDataType, OutputDataType>::Backward(
|
||||
const InputType&& input,
|
||||
const TargetType&& target,
|
||||
OutputType&& output)
|
||||
{
|
||||
output.set_size(arma::size(input));
|
||||
output.fill(-1.0);
|
||||
}
|
||||
|
||||
template<typename InputDataType, typename OutputDataType>
|
||||
template<typename Archive>
|
||||
void MeanBiasError<InputDataType, OutputDataType>::serialize(
|
||||
Archive& /* ar */,
|
||||
const unsigned int /* version */)
|
||||
{
|
||||
// Nothing to do here.
|
||||
}
|
||||
|
||||
} // namespace ann
|
||||
} // namespace mlpack
|
||||
|
||||
#endif
|
||||
@@ -14,9 +14,9 @@
|
||||
#include <mlpack/core/util/mlpack_main.hpp>
|
||||
|
||||
#include <mlpack/methods/amf/amf.hpp>
|
||||
|
||||
#include <mlpack/methods/amf/init_rules/random_init.hpp>
|
||||
#include <mlpack/methods/amf/init_rules/given_init.hpp>
|
||||
#include <mlpack/methods/amf/init_rules/merge_init.hpp>
|
||||
#include <mlpack/methods/amf/update_rules/nmf_mult_dist.hpp>
|
||||
#include <mlpack/methods/amf/update_rules/nmf_mult_div.hpp>
|
||||
#include <mlpack/methods/amf/update_rules/nmf_als.hpp>
|
||||
@@ -130,6 +130,68 @@ void SaveWH(const bool bindingTransposed, arma::mat&& w, arma::mat&& h)
|
||||
}
|
||||
}
|
||||
|
||||
template<typename UpdateRuleType>
|
||||
void ApplyFactorization(const arma::mat& V,
|
||||
const size_t r,
|
||||
arma::mat& W,
|
||||
arma::mat& H)
|
||||
{
|
||||
const size_t maxIterations = CLI::GetParam<int>("max_iterations");
|
||||
const double minResidue = CLI::GetParam<double>("min_residue");
|
||||
|
||||
SimpleResidueTermination srt(minResidue, maxIterations);
|
||||
|
||||
// Load input dataset. We know if the data is transposed based on the
|
||||
// BINDING_MATRIX_TRANSPOSED macro, which will be 'true' or 'false'.
|
||||
arma::mat initialW, initialH;
|
||||
LoadInitialWH(BINDING_MATRIX_TRANSPOSED, initialW, initialH);
|
||||
if (CLI::HasParam("initial_w") && CLI::HasParam("initial_h"))
|
||||
{
|
||||
// Initialize W and H with given matrices
|
||||
GivenInitialization ginit = GivenInitialization(initialW, initialH);
|
||||
AMF<SimpleResidueTermination,
|
||||
GivenInitialization,
|
||||
UpdateRuleType> amf(srt, ginit);
|
||||
amf.Apply(V, r, W, H);
|
||||
}
|
||||
else if (CLI::HasParam("initial_w"))
|
||||
{
|
||||
// Merge GivenInitialization and RandomInitialization rules
|
||||
// to initialize W with the given matrix, and H with random noise
|
||||
GivenInitialization ginit = GivenInitialization(initialW);
|
||||
RandomInitialization rinit = RandomInitialization();
|
||||
MergeInitialization<GivenInitialization, RandomInitialization> minit =
|
||||
MergeInitialization<GivenInitialization, RandomInitialization>
|
||||
(ginit, rinit);
|
||||
AMF<SimpleResidueTermination,
|
||||
MergeInitialization<GivenInitialization, RandomInitialization>,
|
||||
UpdateRuleType> amf(srt, minit);
|
||||
amf.Apply(V, r, W, H);
|
||||
}
|
||||
else if (CLI::HasParam("initial_h"))
|
||||
{
|
||||
// Merge GivenInitialization and RandomInitialization rules
|
||||
// to initialize H with the given matrix, and W with random noise
|
||||
GivenInitialization ginit = GivenInitialization(initialH, false);
|
||||
RandomInitialization rinit = RandomInitialization();
|
||||
MergeInitialization<RandomInitialization, GivenInitialization> minit =
|
||||
MergeInitialization<RandomInitialization, GivenInitialization>
|
||||
(rinit, ginit);
|
||||
AMF<SimpleResidueTermination,
|
||||
MergeInitialization<RandomInitialization, GivenInitialization>,
|
||||
UpdateRuleType> amf(srt, minit);
|
||||
amf.Apply(V, r, W, H);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Use random initialization
|
||||
AMF<SimpleResidueTermination,
|
||||
RandomInitialization,
|
||||
UpdateRuleType> amf(srt);
|
||||
amf.Apply(V, r, W, H);
|
||||
}
|
||||
}
|
||||
|
||||
static void mlpackMain()
|
||||
{
|
||||
// Initialize random seed.
|
||||
@@ -140,8 +202,6 @@ static void mlpackMain()
|
||||
|
||||
// Gather parameters.
|
||||
const size_t r = CLI::GetParam<int>("rank");
|
||||
const size_t maxIterations = CLI::GetParam<int>("max_iterations");
|
||||
const double minResidue = CLI::GetParam<double>("min_residue");
|
||||
const string updateRules = CLI::GetParam<string>("update_rules");
|
||||
|
||||
// Validate parameters.
|
||||
@@ -153,10 +213,7 @@ static void mlpackMain()
|
||||
true, "max_iterations must be non-negative");
|
||||
|
||||
RequireAtLeastOnePassed({ "h", "w" }, false, "no output will be saved");
|
||||
RequireNoneOrAllPassed({"initial_w", "initial_h"}, true);
|
||||
|
||||
// Load input dataset. We know if the data is transposed based on the
|
||||
// BINDING_MATRIX_TRANSPOSED macro, which will be 'true' or 'false'.
|
||||
arma::mat V = std::move(CLI::GetParam<arma::mat>("input"));
|
||||
|
||||
arma::mat W;
|
||||
@@ -167,76 +224,19 @@ static void mlpackMain()
|
||||
{
|
||||
Log::Info << "Performing NMF with multiplicative distance-based update "
|
||||
<< "rules." << std::endl;
|
||||
|
||||
SimpleResidueTermination srt(minResidue, maxIterations);
|
||||
if (CLI::HasParam("initial_w"))
|
||||
{
|
||||
// Initialization with given W, H matrices.
|
||||
arma::mat initialW, initialH;
|
||||
LoadInitialWH(BINDING_MATRIX_TRANSPOSED, initialW, initialH);
|
||||
GivenInitialization ginit = GivenInitialization(initialW, initialH);
|
||||
|
||||
AMF<SimpleResidueTermination,
|
||||
GivenInitialization> amf(srt, ginit);
|
||||
amf.Apply(V, r, W, H);
|
||||
}
|
||||
else
|
||||
{
|
||||
AMF<> amf(srt);
|
||||
amf.Apply(V, r, W, H);
|
||||
}
|
||||
ApplyFactorization<NMFMultiplicativeDistanceUpdate>(V, r, W, H);
|
||||
}
|
||||
else if (updateRules == "multdiv")
|
||||
{
|
||||
Log::Info << "Performing NMF with multiplicative divergence-based update "
|
||||
<< "rules." << std::endl;
|
||||
|
||||
SimpleResidueTermination srt(minResidue, maxIterations);
|
||||
if (CLI::HasParam("initial_w"))
|
||||
{
|
||||
// Initialization with given W, H matrices.
|
||||
arma::mat initialW, initialH;
|
||||
LoadInitialWH(BINDING_MATRIX_TRANSPOSED, initialW, initialH);
|
||||
GivenInitialization ginit = GivenInitialization(initialW, initialH);
|
||||
|
||||
AMF<SimpleResidueTermination,
|
||||
GivenInitialization,
|
||||
NMFMultiplicativeDivergenceUpdate> amf(srt, ginit);
|
||||
amf.Apply(V, r, W, H);
|
||||
}
|
||||
else
|
||||
{
|
||||
AMF<SimpleResidueTermination,
|
||||
RandomInitialization,
|
||||
NMFMultiplicativeDivergenceUpdate> amf(srt);
|
||||
amf.Apply(V, r, W, H);
|
||||
}
|
||||
ApplyFactorization<NMFMultiplicativeDivergenceUpdate>(V, r, W, H);
|
||||
}
|
||||
else if (updateRules == "als")
|
||||
{
|
||||
Log::Info << "Performing NMF with alternating least squared update rules."
|
||||
<< std::endl;
|
||||
|
||||
SimpleResidueTermination srt(minResidue, maxIterations);
|
||||
if (CLI::HasParam("initial_w"))
|
||||
{
|
||||
// Initialization with given W, H matrices.
|
||||
arma::mat initialW, initialH;
|
||||
LoadInitialWH(BINDING_MATRIX_TRANSPOSED, initialW, initialH);
|
||||
GivenInitialization ginit = GivenInitialization(initialW, initialH);
|
||||
|
||||
AMF<SimpleResidueTermination,
|
||||
GivenInitialization,
|
||||
NMFALSUpdate> amf(srt, ginit);
|
||||
amf.Apply(V, r, W, H);
|
||||
}
|
||||
else
|
||||
{
|
||||
AMF<SimpleResidueTermination,
|
||||
RandomInitialization,
|
||||
NMFALSUpdate> amf(srt);
|
||||
amf.Apply(V, r, W, H);
|
||||
}
|
||||
ApplyFactorization<NMFALSUpdate>(V, r, W, H);
|
||||
}
|
||||
|
||||
// Save results. Remember from our discussion in the comments earlier that we
|
||||
|
||||
@@ -71,7 +71,6 @@ class SoftmaxRegression
|
||||
SoftmaxRegression(const size_t inputSize = 0,
|
||||
const size_t numClasses = 0,
|
||||
const bool fitIntercept = false);
|
||||
|
||||
/**
|
||||
* Construct the SoftmaxRegression class with the provided data and labels.
|
||||
* This will train the model. Optionally, the parameter 'lambda' can be
|
||||
@@ -94,23 +93,45 @@ class SoftmaxRegression
|
||||
const double lambda = 0.0001,
|
||||
const bool fitIntercept = false,
|
||||
OptimizerType optimizer = OptimizerType());
|
||||
|
||||
/**
|
||||
* Construct the SoftmaxRegression class with the provided data and labels.
|
||||
* This will train the model. Optionally, the parameter 'lambda' can be
|
||||
* passed, which controls the amount of L2-regularization in the objective
|
||||
* function. By default, the model takes a small value.
|
||||
*
|
||||
* @tparam OptimizerType Desired optimizer type.
|
||||
* @tparam CallbackTypes Types of Callback Functions.
|
||||
* @param data Input training features. Each column associate with one sample
|
||||
* @param labels Labels associated with the feature data.
|
||||
* @param inputSize Size of the input feature vector.
|
||||
* @param numClasses Number of classes for classification.
|
||||
* @param lambda L2-regularization constant.
|
||||
* @param fitIntercept add intercept term or not.
|
||||
* @param optimizer Desired optimizer.
|
||||
* @param callbacks Callback function for ensmallen optimizer `OptimizerType`.
|
||||
* See https://www.ensmallen.org/docs.html#callback-documentation.
|
||||
*/
|
||||
template<typename OptimizerType, typename... CallbackTypes>
|
||||
SoftmaxRegression(const arma::mat& data,
|
||||
const arma::Row<size_t>& labels,
|
||||
const size_t numClasses,
|
||||
const double lambda,
|
||||
const bool fitIntercept,
|
||||
OptimizerType optimizer,
|
||||
CallbackTypes&&... callbacks);
|
||||
/**
|
||||
* Classify the given points, returning the predicted labels for each point.
|
||||
* The function calculates the probabilities for every class, given a data
|
||||
* point. It then chooses the class which has the highest probability among
|
||||
* all.
|
||||
*
|
||||
* @param dataset Set of points to classify.
|
||||
* @param labels Predicted labels for each point.
|
||||
*/
|
||||
void Classify(const arma::mat& dataset, arma::Row<size_t>& labels) const;
|
||||
|
||||
/**
|
||||
* Classify the given point. The predicted class label is returned.
|
||||
* The function calculates the probabilites for every class, given the point.
|
||||
* It then chooses the class which has the highest probability among all.
|
||||
*
|
||||
* @param point Point to be classified.
|
||||
* @return Predicted class label of the point.
|
||||
*/
|
||||
@@ -151,7 +172,6 @@ class SoftmaxRegression
|
||||
*/
|
||||
double ComputeAccuracy(const arma::mat& testData,
|
||||
const arma::Row<size_t>& labels) const;
|
||||
|
||||
/**
|
||||
* Train the softmax regression with the given training data.
|
||||
*
|
||||
@@ -167,6 +187,25 @@ class SoftmaxRegression
|
||||
const arma::Row<size_t>& labels,
|
||||
const size_t numClasses,
|
||||
OptimizerType optimizer = OptimizerType());
|
||||
/**
|
||||
* Train the softmax regression with the given training data.
|
||||
*
|
||||
* @tparam OptimizerType Desired optimizer type.
|
||||
* @tparam CallbackTypes Types of Callback Functions.
|
||||
* @param data Input data with each column as one example.
|
||||
* @param labels Labels associated with the feature data.
|
||||
* @param numClasses Number of classes for classification.
|
||||
* @param optimizer Desired optimizer.
|
||||
* @param callbacks Callback function for ensmallen optimizer `OptimizerType`.
|
||||
* See https://www.ensmallen.org/docs.html#callback-documentation.
|
||||
* @return Objective value of the final point.
|
||||
*/
|
||||
template<typename OptimizerType = ens::L_BFGS, typename... CallbackTypes>
|
||||
double Train(const arma::mat& data,
|
||||
const arma::Row<size_t>& labels,
|
||||
const size_t numClasses,
|
||||
OptimizerType optimizer,
|
||||
CallbackTypes&&... callbacks);
|
||||
|
||||
//! Sets the number of classes.
|
||||
size_t& NumClasses() { return numClasses; }
|
||||
@@ -188,7 +227,7 @@ class SoftmaxRegression
|
||||
|
||||
//! Gets the features size of the training data
|
||||
size_t FeatureSize() const
|
||||
{ return fitIntercept ? parameters.n_cols - 1 :
|
||||
{ return fitIntercept ? parameters.n_cols - 1:
|
||||
parameters.n_cols; }
|
||||
|
||||
/**
|
||||
|
||||
@@ -175,6 +175,11 @@ class SoftmaxRegressionFunction
|
||||
{
|
||||
return initialPoint.n_cols;
|
||||
}
|
||||
/**
|
||||
* Return the number of separable functions
|
||||
(the number of predictor points).
|
||||
*/
|
||||
size_t NumFunctions() const { return data.n_cols; }
|
||||
|
||||
//! Sets the regularization parameter.
|
||||
double& Lambda() { return lambda; }
|
||||
|
||||
@@ -33,6 +33,22 @@ SoftmaxRegression::SoftmaxRegression(
|
||||
Train(data, labels, numClasses, optimizer);
|
||||
}
|
||||
|
||||
template<typename OptimizerType, typename... CallbackTypes>
|
||||
SoftmaxRegression::SoftmaxRegression(
|
||||
const arma::mat& data,
|
||||
const arma::Row<size_t>& labels,
|
||||
const size_t numClasses,
|
||||
const double lambda,
|
||||
const bool fitIntercept,
|
||||
OptimizerType optimizer,
|
||||
CallbackTypes&&... callbacks) :
|
||||
numClasses(numClasses),
|
||||
lambda(lambda),
|
||||
fitIntercept(fitIntercept)
|
||||
{
|
||||
Train(data, labels, numClasses, optimizer, callbacks...);
|
||||
}
|
||||
|
||||
template<typename VecType>
|
||||
size_t SoftmaxRegression::Classify(const VecType& point) const
|
||||
{
|
||||
@@ -47,8 +63,8 @@ double SoftmaxRegression::Train(const arma::mat& data,
|
||||
const size_t numClasses,
|
||||
OptimizerType optimizer)
|
||||
{
|
||||
SoftmaxRegressionFunction regressor(data, labels, numClasses,
|
||||
lambda, fitIntercept);
|
||||
SoftmaxRegressionFunction regressor(data, labels, numClasses, lambda,
|
||||
fitIntercept);
|
||||
if (parameters.is_empty())
|
||||
parameters = regressor.GetInitialPoint();
|
||||
|
||||
@@ -63,6 +79,29 @@ double SoftmaxRegression::Train(const arma::mat& data,
|
||||
return out;
|
||||
}
|
||||
|
||||
template<typename OptimizerType, typename... CallbackTypes>
|
||||
double SoftmaxRegression::Train(const arma::mat& data,
|
||||
const arma::Row<size_t>& labels,
|
||||
const size_t numClasses,
|
||||
OptimizerType optimizer,
|
||||
CallbackTypes&&... callbacks)
|
||||
{
|
||||
SoftmaxRegressionFunction regressor(data, labels, numClasses, lambda,
|
||||
fitIntercept);
|
||||
if (parameters.is_empty())
|
||||
parameters = regressor.GetInitialPoint();
|
||||
|
||||
// Train the model.
|
||||
Timer::Start("softmax_regression_optimization");
|
||||
const double out = optimizer.Optimize(regressor, parameters, callbacks...);
|
||||
Timer::Stop("softmax_regression_optimization");
|
||||
|
||||
Log::Info << "SoftmaxRegression::SoftmaxRegression(): final objective of "
|
||||
<< "trained model is " << out << "." << std::endl;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
} // namespace regression
|
||||
} // namespace mlpack
|
||||
|
||||
|
||||
@@ -273,6 +273,5 @@ Model* TrainSoftmax(const size_t maxIterations)
|
||||
sm = new Model(trainData, trainLabels, numClasses,
|
||||
CLI::GetParam<double>("lambda"), intercept, std::move(optimizer));
|
||||
}
|
||||
|
||||
return sm;
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <mlpack/methods/ann/activation_functions/swish_function.hpp>
|
||||
#include <mlpack/methods/ann/activation_functions/hard_sigmoid_function.hpp>
|
||||
#include <mlpack/methods/ann/activation_functions/mish_function.hpp>
|
||||
#include <mlpack/methods/ann/activation_functions/lisht_function.hpp>
|
||||
#include <mlpack/methods/ann/activation_functions/gelu_function.hpp>
|
||||
|
||||
#include <boost/test/unit_test.hpp>
|
||||
@@ -635,6 +636,7 @@ BOOST_AUTO_TEST_CASE(HardSigmoidFunctionTest)
|
||||
CheckDerivativeCorrect<HardSigmoidFunction>(desiredActivations,
|
||||
desiredDerivatives);
|
||||
}
|
||||
|
||||
/**
|
||||
* Basic test of the Mish function.
|
||||
*/
|
||||
@@ -657,6 +659,31 @@ BOOST_AUTO_TEST_CASE(MishFunctionTest)
|
||||
desiredDerivatives);
|
||||
}
|
||||
|
||||
/**
|
||||
* Basic test of the LiSHT function.
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE(LiSHTFunctionTest)
|
||||
{
|
||||
// Calculated using tfa.activations.LiSHT().
|
||||
// where tfa is tensorflow_addons.
|
||||
const arma::colvec desiredActivations("1.928055 3.189384 \
|
||||
4.4988894 100.2 0.7615942 \
|
||||
0.7615942 1.9280552 0");
|
||||
|
||||
const arma::colvec desiredDerivatives("1.1150033 1.0181904 \
|
||||
1.001978 1.0 \
|
||||
1.0896928 1.0896928 \
|
||||
1.1150033 0.0");
|
||||
|
||||
CheckActivationCorrect<LiSHTFunction>(activationData,
|
||||
desiredActivations);
|
||||
CheckDerivativeCorrect<LiSHTFunction>(desiredActivations,
|
||||
desiredDerivatives);
|
||||
}
|
||||
|
||||
/**
|
||||
* Basic test of the GELU function.
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE(GELUFunctionTest)
|
||||
{
|
||||
// Calculated using torch.nn.gelu().
|
||||
@@ -682,4 +709,5 @@ BOOST_AUTO_TEST_CASE(GELUFunctionTest)
|
||||
CheckDerivativeCorrect<GELUFunction>(desiredActivations,
|
||||
desiredDerivatives);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END();
|
||||
|
||||
@@ -2931,4 +2931,105 @@ BOOST_AUTO_TEST_CASE(ConvolutionLayerPaddingTest)
|
||||
module2.Backward(std::move(input), std::move(output), std::move(delta));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that the padding options in Transposed Convolution layer.
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE(TransposedConvolutionLayerPaddingTest)
|
||||
{
|
||||
arma::mat output, input, delta;
|
||||
|
||||
TransposedConvolution<> module1(1, 1, 3, 3, 1, 1, 0, 0, 4, 4, 6, 6, "VALID");
|
||||
// Test the forward function.
|
||||
// Valid Should give the same result.
|
||||
input = arma::linspace<arma::colvec>(0, 15, 16);
|
||||
module1.Parameters() = arma::mat(9 + 1, 1, arma::fill::zeros);
|
||||
module1.Reset();
|
||||
module1.Forward(std::move(input), std::move(output));
|
||||
// Value calculated using tensorflow.nn.conv2d_transpose().
|
||||
BOOST_REQUIRE_EQUAL(arma::accu(output), 0.0);
|
||||
|
||||
// Test the Backward Function.
|
||||
module1.Backward(std::move(input), std::move(output), std::move(delta));
|
||||
BOOST_REQUIRE_EQUAL(arma::accu(delta), 0.0);
|
||||
|
||||
// Test Valid for non zero padding.
|
||||
TransposedConvolution<> module2(1, 1, 3, 3, 2, 2,
|
||||
std::tuple<size_t, size_t>(0, 0), std::tuple<size_t, size_t>(0, 0),
|
||||
2, 2, 5, 5, "VALID");
|
||||
// Test the forward function.
|
||||
input = arma::linspace<arma::colvec>(0, 3, 4);
|
||||
module2.Parameters() = arma::mat(25 + 1, 1, arma::fill::zeros);
|
||||
module2.Parameters()(2) = 8.0;
|
||||
module2.Parameters()(4) = 6.0;
|
||||
module2.Parameters()(6) = 4.0;
|
||||
module2.Parameters()(8) = 2.0;
|
||||
module2.Reset();
|
||||
module2.Forward(std::move(input), std::move(output));
|
||||
// Value calculated using torch.nn.functional.conv_transpose2d().
|
||||
BOOST_REQUIRE_EQUAL(arma::accu(output), 120.0);
|
||||
|
||||
// Test the Backward Function.
|
||||
module2.Backward(std::move(input), std::move(output), std::move(delta));
|
||||
BOOST_REQUIRE_EQUAL(arma::accu(delta), 960.0);
|
||||
|
||||
// Test for same padding type.
|
||||
TransposedConvolution<> module3(1, 1, 3, 3, 2, 2, 0, 0, 3, 3, 3, 3, "SAME");
|
||||
// Test the forward function.
|
||||
input = arma::linspace<arma::colvec>(0, 8, 9);
|
||||
module3.Parameters() = arma::mat(9 + 1, 1, arma::fill::zeros);
|
||||
module3.Reset();
|
||||
module3.Forward(std::move(input), std::move(output));
|
||||
BOOST_REQUIRE_EQUAL(arma::accu(output), 0);
|
||||
BOOST_REQUIRE_EQUAL(output.n_rows, input.n_rows);
|
||||
BOOST_REQUIRE_EQUAL(output.n_cols, input.n_cols);
|
||||
|
||||
// Test the Backward Function.
|
||||
module3.Backward(std::move(input), std::move(output), std::move(delta));
|
||||
BOOST_REQUIRE_EQUAL(arma::accu(delta), 0.0);
|
||||
|
||||
// Output shape should equal input.
|
||||
TransposedConvolution<> module4(1, 1, 3, 3, 1, 1,
|
||||
std::tuple<size_t, size_t>(2, 2), std::tuple<size_t, size_t>(2, 2),
|
||||
5, 5, 5, 5, "SAME");
|
||||
// Test the forward function.
|
||||
input = arma::linspace<arma::colvec>(0, 24, 25);
|
||||
module4.Parameters() = arma::mat(9 + 1, 1, arma::fill::zeros);
|
||||
module4.Reset();
|
||||
module4.Forward(std::move(input), std::move(output));
|
||||
BOOST_REQUIRE_EQUAL(arma::accu(output), 0);
|
||||
BOOST_REQUIRE_EQUAL(output.n_rows, input.n_rows);
|
||||
BOOST_REQUIRE_EQUAL(output.n_cols, input.n_cols);
|
||||
|
||||
// Test the Backward Function.
|
||||
module4.Backward(std::move(input), std::move(output), std::move(delta));
|
||||
BOOST_REQUIRE_EQUAL(arma::accu(delta), 0.0);
|
||||
|
||||
TransposedConvolution<> module5(1, 1, 3, 3, 2, 2, 0, 0, 2, 2, 2, 2, "SAME");
|
||||
// Test the forward function.
|
||||
input = arma::linspace<arma::colvec>(0, 3, 4);
|
||||
module5.Parameters() = arma::mat(25 + 1, 1, arma::fill::zeros);
|
||||
module5.Reset();
|
||||
module5.Forward(std::move(input), std::move(output));
|
||||
BOOST_REQUIRE_EQUAL(arma::accu(output), 0);
|
||||
BOOST_REQUIRE_EQUAL(output.n_rows, input.n_rows);
|
||||
BOOST_REQUIRE_EQUAL(output.n_cols, input.n_cols);
|
||||
|
||||
// Test the Backward Function.
|
||||
module5.Backward(std::move(input), std::move(output), std::move(delta));
|
||||
BOOST_REQUIRE_EQUAL(arma::accu(delta), 0.0);
|
||||
|
||||
TransposedConvolution<> module6(1, 1, 4, 4, 1, 1, 1, 1, 5, 5, 5, 5, "SAME");
|
||||
// Test the forward function.
|
||||
input = arma::linspace<arma::colvec>(0, 24, 25);
|
||||
module6.Parameters() = arma::mat(16 + 1, 1, arma::fill::zeros);
|
||||
module6.Reset();
|
||||
module6.Forward(std::move(input), std::move(output));
|
||||
BOOST_REQUIRE_EQUAL(arma::accu(output), 0);
|
||||
BOOST_REQUIRE_EQUAL(output.n_rows, input.n_rows);
|
||||
BOOST_REQUIRE_EQUAL(output.n_cols, input.n_cols);
|
||||
|
||||
// Test the Backward Function.
|
||||
module6.Backward(std::move(input), std::move(output), std::move(delta));
|
||||
BOOST_REQUIRE_EQUAL(arma::accu(delta), 0.0);
|
||||
}
|
||||
BOOST_AUTO_TEST_SUITE_END();
|
||||
|
||||
@@ -19,8 +19,9 @@
|
||||
#include <mlpack/methods/lmnn/lmnn.hpp>
|
||||
#include <mlpack/methods/nca/nca.hpp>
|
||||
#include <mlpack/core/metrics/lmetric.hpp>
|
||||
#include <mlpack/methods/softmax_regression/softmax_regression.hpp>
|
||||
#include <mlpack/methods/softmax_regression/softmax_regression_impl.hpp>
|
||||
#include <mlpack/methods/ann/init_rules/gaussian_init.hpp>
|
||||
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
using namespace mlpack;
|
||||
@@ -29,6 +30,7 @@ using namespace mlpack::regression;
|
||||
using namespace mlpack::lmnn;
|
||||
using namespace mlpack::metric;
|
||||
using namespace mlpack::nca;
|
||||
using namespace mlpack::distribution;
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(CallbackTest);
|
||||
|
||||
@@ -94,12 +96,12 @@ BOOST_AUTO_TEST_CASE(RNNCallbackTest)
|
||||
// Create model with user defined rho parameter.
|
||||
RNN<NegativeLogLikelihood<>, RandomInitialization> model(
|
||||
rho, false, NegativeLogLikelihood<>(), init);
|
||||
model.Add<IdentityLayer<> >();
|
||||
model.Add<Linear<> >(1, 10);
|
||||
model.Add<IdentityLayer<>>();
|
||||
model.Add<Linear<>>(1, 10);
|
||||
|
||||
// Use LSTM layer with rho.
|
||||
model.Add<LSTM<> >(10, 3, rho);
|
||||
model.Add<LogSoftMax<> >();
|
||||
model.Add<LSTM<>>(10, 3, rho);
|
||||
model.Add<LogSoftMax<>>();
|
||||
|
||||
std::stringstream stream;
|
||||
model.Train(input, target, ens::PrintLoss(stream));
|
||||
@@ -120,12 +122,12 @@ BOOST_AUTO_TEST_CASE(RNNWithOptimizerCallbackTest)
|
||||
// Create model with user defined rho parameter.
|
||||
RNN<NegativeLogLikelihood<>, RandomInitialization> model(
|
||||
rho, false, NegativeLogLikelihood<>(), init);
|
||||
model.Add<IdentityLayer<> >();
|
||||
model.Add<Linear<> >(1, 10);
|
||||
model.Add<IdentityLayer<>>();
|
||||
model.Add<Linear<>>(1, 10);
|
||||
|
||||
// Use LSTM layer with rho.
|
||||
model.Add<LSTM<> >(10, 3, rho);
|
||||
model.Add<LogSoftMax<> >();
|
||||
model.Add<LSTM<>>(10, 3, rho);
|
||||
model.Add<LogSoftMax<>>();
|
||||
|
||||
std::stringstream stream;
|
||||
ens::StandardSGD opt(0.1, 1, 5);
|
||||
@@ -139,17 +141,17 @@ BOOST_AUTO_TEST_CASE(RNNWithOptimizerCallbackTest)
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE(LRWithOptimizerCallback)
|
||||
{
|
||||
arma::mat data("1 2 3;"
|
||||
"1 2 3");
|
||||
arma::Row<size_t> responses("1 1 0");
|
||||
arma::mat data("1 2 3;"
|
||||
"1 2 3");
|
||||
arma::Row<size_t> responses("1 1 0");
|
||||
|
||||
ens::StandardSGD sgd(0.1, 1, 5);
|
||||
LogisticRegression<> logisticRegression(data, responses, sgd, 0.001);
|
||||
std::stringstream stream;
|
||||
logisticRegression.Train<ens::StandardSGD>(data, responses, sgd,
|
||||
ens::PrintLoss(stream));
|
||||
ens::StandardSGD sgd(0.1, 1, 5);
|
||||
LogisticRegression<> logisticRegression(data, responses, sgd, 0.001);
|
||||
std::stringstream stream;
|
||||
logisticRegression.Train<ens::StandardSGD>(data, responses, sgd,
|
||||
ens::PrintLoss(stream));
|
||||
|
||||
BOOST_REQUIRE_GT(stream.str().length(), 0);
|
||||
BOOST_REQUIRE_GT(stream.str().length(), 0);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -158,8 +160,8 @@ BOOST_AUTO_TEST_CASE(LRWithOptimizerCallback)
|
||||
BOOST_AUTO_TEST_CASE(LMNNWithOptimizerCallback)
|
||||
{
|
||||
// Useful but simple dataset with six points and two classes.
|
||||
arma::mat dataset = "-0.1 -0.1 -0.1 0.1 0.1 0.1;"
|
||||
" 1.0 0.0 -1.0 1.0 0.0 -1.0 ";
|
||||
arma::mat dataset = "-0.1 -0.1 -0.1 0.1 0.1 0.1;"
|
||||
" 1.0 0.0 -1.0 1.0 0.0 -1.0 ";
|
||||
arma::Row<size_t> labels = " 0 0 0 1 1 1 ";
|
||||
|
||||
LMNN<> lmnn(dataset, labels, 1);
|
||||
@@ -177,8 +179,8 @@ BOOST_AUTO_TEST_CASE(LMNNWithOptimizerCallback)
|
||||
BOOST_AUTO_TEST_CASE(NCAWithOptimizerCallback)
|
||||
{
|
||||
// Useful but simple dataset with six points and two classes.
|
||||
arma::mat data = "-0.1 -0.1 -0.1 0.1 0.1 0.1;"
|
||||
" 1.0 0.0 -1.0 1.0 0.0 -1.0 ";
|
||||
arma::mat data = "-0.1 -0.1 -0.1 0.1 0.1 0.1;"
|
||||
" 1.0 0.0 -1.0 1.0 0.0 -1.0 ";
|
||||
arma::Row<size_t> labels = " 0 0 0 1 1 1 ";
|
||||
|
||||
NCA<SquaredEuclideanDistance> nca(data, labels);
|
||||
@@ -190,6 +192,41 @@ BOOST_AUTO_TEST_CASE(NCAWithOptimizerCallback)
|
||||
BOOST_REQUIRE_GT(stream.str().length(), 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test softmax_regression implementation with PrintLoss callback.
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE(SRWithOptimizerCallback)
|
||||
{
|
||||
const size_t points = 1000;
|
||||
const size_t inputSize = 3;
|
||||
const size_t numClasses = 3;
|
||||
const double lambda = 0.5;
|
||||
|
||||
// Generate two-Gaussian dataset.
|
||||
GaussianDistribution g1(arma::vec("1.0 9.0 1.0"), arma::eye<arma::mat>(3, 3));
|
||||
GaussianDistribution g2(arma::vec("4.0 3.0 4.0"), arma::eye<arma::mat>(3, 3));
|
||||
|
||||
arma::mat data(inputSize, points);
|
||||
arma::Row<size_t> labels(points);
|
||||
|
||||
for (size_t i = 0; i < points / 2; i++)
|
||||
{
|
||||
data.col(i) = g1.Random();
|
||||
labels(i) = 0;
|
||||
}
|
||||
for (size_t i = points / 2; i < points; i++)
|
||||
{
|
||||
data.col(i) = g2.Random();
|
||||
labels(i) = 1;
|
||||
}
|
||||
ens::StandardSGD sgd(0.1, 1, 5);
|
||||
std::stringstream stream;
|
||||
// Train softmax regression object.
|
||||
SoftmaxRegression sr(data, labels, numClasses, lambda);
|
||||
sr.Train(data, labels, numClasses, sgd, ens::ProgressBar(70, stream));
|
||||
|
||||
BOOST_REQUIRE_GT(stream.str().length(), 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Tests the RBM Implementation with PrintLoss callback.
|
||||
@@ -205,7 +242,10 @@ BOOST_AUTO_TEST_CASE(RBMCallbackTest)
|
||||
|
||||
GaussianInitialization gaussian(0, 0.1);
|
||||
RBM<GaussianInitialization> model(trainData,
|
||||
gaussian, trainData.n_rows, hiddenLayerSize, batchSize);
|
||||
gaussian,
|
||||
trainData.n_rows,
|
||||
hiddenLayerSize,
|
||||
batchSize);
|
||||
|
||||
size_t numRBMIterations = 10;
|
||||
ens::StandardSGD msgd(0.03, batchSize, numRBMIterations, 0, true);
|
||||
|
||||
@@ -222,4 +222,218 @@ BOOST_AUTO_TEST_CASE(CosineTreeModifiedGramSchmidt)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the copy constructor & copy assignment using Cosine trees.
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE(CopyConstructorAndOperatorCosineTreeTest)
|
||||
{
|
||||
// Initialize constants required for the test.
|
||||
const size_t numRows = 10;
|
||||
const size_t numCols = 15;
|
||||
|
||||
// Vectors to hold depth-first traversal
|
||||
// of the number of columns in each node.
|
||||
std::vector<int> v1, v2, v3;
|
||||
|
||||
// Make a random dataset.
|
||||
arma::mat* data = new arma::mat(numRows, numCols, arma::fill::randu);
|
||||
|
||||
// Make a cosine tree, with the generated dataset.
|
||||
CosineTree* ctree1 = new CosineTree(*data);
|
||||
|
||||
// Stacks for depth first search of the tree.
|
||||
std::vector<CosineTree*> nodeStack1, nodeStack2, nodeStack3;
|
||||
nodeStack1.push_back(ctree1);
|
||||
|
||||
// While stack is not empty.
|
||||
while (nodeStack1.size())
|
||||
{
|
||||
// Pop a node from the stack and split it.
|
||||
CosineTree *currentNode1, *currentLeft1, *currentRight1;
|
||||
|
||||
currentNode1 = nodeStack1.back();
|
||||
currentNode1->CosineNodeSplit();
|
||||
nodeStack1.pop_back();
|
||||
|
||||
// Obtain pointers to the children of the node.
|
||||
currentLeft1 = currentNode1->Left();
|
||||
currentRight1 = currentNode1->Right();
|
||||
|
||||
// If children exist.
|
||||
if (currentLeft1 && currentRight1)
|
||||
{
|
||||
// Push the child nodes on to the stack.
|
||||
nodeStack1.push_back(currentLeft1);
|
||||
nodeStack1.push_back(currentRight1);
|
||||
|
||||
v1.push_back(currentNode1->NumColumns());
|
||||
}
|
||||
}
|
||||
|
||||
// Copy constructor and operator.
|
||||
CosineTree ctree2(*ctree1);
|
||||
CosineTree ctree3 = *ctree1;
|
||||
|
||||
delete ctree1;
|
||||
delete data;
|
||||
|
||||
nodeStack2.push_back(&ctree2);
|
||||
nodeStack3.push_back(&ctree3);
|
||||
|
||||
// While stacks are not empty.
|
||||
while (nodeStack2.size() && nodeStack3.size())
|
||||
{
|
||||
// Pop a node from the stack and split it.
|
||||
CosineTree *currentNode2, *currentLeft2, *currentRight2;
|
||||
CosineTree *currentNode3, *currentLeft3, *currentRight3;
|
||||
|
||||
currentNode2 = nodeStack2.back();
|
||||
nodeStack2.pop_back();
|
||||
|
||||
currentNode3 = nodeStack3.back();
|
||||
nodeStack3.pop_back();
|
||||
|
||||
// Obtain pointers to the children of the node.
|
||||
currentLeft2 = currentNode2->Left();
|
||||
currentRight2 = currentNode2->Right();
|
||||
|
||||
currentLeft3 = currentNode3->Left();
|
||||
currentRight3 = currentNode3->Right();
|
||||
|
||||
// If children exist.
|
||||
if (currentLeft2 && currentRight2 && currentLeft3 && currentRight3)
|
||||
{
|
||||
// Push the child nodes on to the stack.
|
||||
nodeStack2.push_back(currentLeft2);
|
||||
nodeStack2.push_back(currentRight2);
|
||||
|
||||
v2.push_back(currentNode2->NumColumns());
|
||||
|
||||
nodeStack3.push_back(currentLeft3);
|
||||
nodeStack3.push_back(currentRight3);
|
||||
|
||||
v3.push_back(currentNode3->NumColumns());
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < v1.size(); i++)
|
||||
{
|
||||
BOOST_REQUIRE_EQUAL(v1.at(i), v2.at(i));
|
||||
BOOST_REQUIRE_EQUAL(v1.at(i), v3.at(i));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the move constructor & move assignment using Cosine trees.
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE(MoveConstructorAndOperatorCosineTreeTest)
|
||||
{
|
||||
// Initialize constants required for the test.
|
||||
const size_t numRows = 10;
|
||||
const size_t numCols = 15;
|
||||
|
||||
// Vectors to hold depth-first traversal
|
||||
// of the number of columns in each node.
|
||||
std::vector<int> v1, v2, v3;
|
||||
|
||||
// Make a random dataset.
|
||||
arma::mat data = arma::randu(numRows, numCols);
|
||||
|
||||
// Make a cosine tree, with the generated dataset.
|
||||
CosineTree ctree1(data);
|
||||
|
||||
// Stacks for depth first search of the tree.
|
||||
std::vector<CosineTree*> nodeStack1, nodeStack2, nodeStack3;
|
||||
nodeStack1.push_back(&ctree1);
|
||||
|
||||
// While stack is not empty.
|
||||
while (nodeStack1.size())
|
||||
{
|
||||
// Pop a node from the stack and split it.
|
||||
CosineTree *currentNode1, *currentLeft1, *currentRight1;
|
||||
|
||||
currentNode1 = nodeStack1.back();
|
||||
currentNode1->CosineNodeSplit();
|
||||
nodeStack1.pop_back();
|
||||
|
||||
// Obtain pointers to the children of the node.
|
||||
currentLeft1 = currentNode1->Left();
|
||||
currentRight1 = currentNode1->Right();
|
||||
|
||||
// If children exist.
|
||||
if (currentLeft1 && currentRight1)
|
||||
{
|
||||
// Push the child nodes on to the stack.
|
||||
nodeStack1.push_back(currentLeft1);
|
||||
nodeStack1.push_back(currentRight1);
|
||||
|
||||
v1.push_back(currentNode1->NumColumns());
|
||||
}
|
||||
}
|
||||
|
||||
// Move constructor.
|
||||
CosineTree ctree2(std::move(ctree1));
|
||||
|
||||
nodeStack2.push_back(&ctree2);
|
||||
|
||||
// While stacks are not empty.
|
||||
while (nodeStack2.size())
|
||||
{
|
||||
// Pop a node from the stack and split it.
|
||||
CosineTree *currentNode2, *currentLeft2, *currentRight2;
|
||||
|
||||
currentNode2 = nodeStack2.back();
|
||||
nodeStack2.pop_back();
|
||||
|
||||
// Obtain pointers to the children of the node.
|
||||
currentLeft2 = currentNode2->Left();
|
||||
currentRight2 = currentNode2->Right();
|
||||
|
||||
// If children exist.
|
||||
if (currentLeft2 && currentRight2)
|
||||
{
|
||||
// Push the child nodes on to the stack.
|
||||
nodeStack2.push_back(currentLeft2);
|
||||
nodeStack2.push_back(currentRight2);
|
||||
|
||||
v2.push_back(currentNode2->NumColumns());
|
||||
}
|
||||
}
|
||||
|
||||
// Move operator.
|
||||
CosineTree ctree3 = std::move(ctree2);
|
||||
|
||||
nodeStack3.push_back(&ctree3);
|
||||
|
||||
// While stacks are not empty.
|
||||
while (nodeStack3.size())
|
||||
{
|
||||
// Pop a node from the stack and split it.
|
||||
CosineTree *currentNode3, *currentLeft3, *currentRight3;
|
||||
|
||||
currentNode3 = nodeStack3.back();
|
||||
nodeStack3.pop_back();
|
||||
|
||||
// Obtain pointers to the children of the node.
|
||||
currentLeft3 = currentNode3->Left();
|
||||
currentRight3 = currentNode3->Right();
|
||||
|
||||
// If children exist.
|
||||
if (currentLeft3 && currentRight3)
|
||||
{
|
||||
// Push the child nodes on to the stack.
|
||||
nodeStack3.push_back(currentLeft3);
|
||||
nodeStack3.push_back(currentRight3);
|
||||
|
||||
v3.push_back(currentNode3->NumColumns());
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < v1.size(); i++)
|
||||
{
|
||||
BOOST_REQUIRE_EQUAL(v1.at(i), v2.at(i));
|
||||
BOOST_REQUIRE_EQUAL(v1.at(i), v3.at(i));
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END();
|
||||
|
||||
@@ -1357,6 +1357,34 @@ BOOST_AUTO_TEST_CASE(CopyConstructorAndOperatorCoverTreeTest)
|
||||
CheckMatrices(distances, distances3);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the copy constructor and copy operator using the BinarySpaceTree.
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE(CopyConstructorAndOperatorBinarySpaceTreeTest)
|
||||
{
|
||||
arma::mat dataset = arma::randu<arma::mat>(5, 500);
|
||||
typedef NeighborSearch<NearestNeighborSort, EuclideanDistance, arma::mat,
|
||||
KDTree> NeighborSearchType;
|
||||
NeighborSearchType knn(std::move(dataset));
|
||||
|
||||
// Copy constructor and operator.
|
||||
NeighborSearchType knn2(knn);
|
||||
NeighborSearchType knn3 = knn;
|
||||
|
||||
// Get results.
|
||||
arma::mat distances, distances2, distances3;
|
||||
arma::Mat<size_t> neighbors, neighbors2, neighbors3;
|
||||
|
||||
knn.Search(3, neighbors, distances);
|
||||
knn2.Search(3, neighbors2, distances2);
|
||||
knn3.Search(3, neighbors3, distances3);
|
||||
|
||||
CheckMatrices(neighbors, neighbors2);
|
||||
CheckMatrices(neighbors, neighbors3);
|
||||
CheckMatrices(distances, distances2);
|
||||
CheckMatrices(distances, distances3);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the copy constructor and copy operator using the Spill Tree.
|
||||
*/
|
||||
@@ -1385,6 +1413,34 @@ BOOST_AUTO_TEST_CASE(CopyConstructorAndOperatorSpillTreeTest)
|
||||
CheckMatrices(distances, distances3);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the copy constructor and copy operator using the Octree.
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE(CopyConstructorAndOperatorOctreeTest)
|
||||
{
|
||||
arma::mat dataset = arma::randu<arma::mat>(5, 500);
|
||||
typedef NeighborSearch<NearestNeighborSort, EuclideanDistance, arma::mat,
|
||||
Octree> NeighborSearchType;
|
||||
NeighborSearchType knn(std::move(dataset));
|
||||
|
||||
// Copy constructor and operator.
|
||||
NeighborSearchType knn2(knn);
|
||||
NeighborSearchType knn3 = knn;
|
||||
|
||||
// Get results.
|
||||
arma::mat distances, distances2, distances3;
|
||||
arma::Mat<size_t> neighbors, neighbors2, neighbors3;
|
||||
|
||||
knn.Search(3, neighbors, distances);
|
||||
knn2.Search(3, neighbors2, distances2);
|
||||
knn3.Search(3, neighbors3, distances3);
|
||||
|
||||
CheckMatrices(neighbors, neighbors2);
|
||||
CheckMatrices(neighbors, neighbors3);
|
||||
CheckMatrices(distances, distances2);
|
||||
CheckMatrices(distances, distances3);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the move constructor.
|
||||
*/
|
||||
@@ -1411,7 +1467,7 @@ BOOST_AUTO_TEST_CASE(MoveConstructorTest)
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the move constructor using R trees.
|
||||
* Test the move constructor & move assignment using R trees.
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE(MoveConstructorRTreeTest)
|
||||
{
|
||||
@@ -1421,8 +1477,8 @@ BOOST_AUTO_TEST_CASE(MoveConstructorRTreeTest)
|
||||
NeighborSearchType* knn = new NeighborSearchType(std::move(dataset));
|
||||
|
||||
// Get predictions.
|
||||
arma::mat distances, distances2;
|
||||
arma::Mat<size_t> neighbors, neighbors2;
|
||||
arma::mat distances, distances2, distances3;
|
||||
arma::Mat<size_t> neighbors, neighbors2, neighbors3;
|
||||
|
||||
knn->Search(3, neighbors, distances);
|
||||
|
||||
@@ -1433,11 +1489,83 @@ BOOST_AUTO_TEST_CASE(MoveConstructorRTreeTest)
|
||||
|
||||
knn2.Search(3, neighbors2, distances2);
|
||||
|
||||
// Use move assignment.
|
||||
NeighborSearchType knn3 = std::move(knn2);
|
||||
knn3.Search(3, neighbors3, distances3);
|
||||
|
||||
CheckMatrices(neighbors, neighbors2);
|
||||
CheckMatrices(neighbors, neighbors3);
|
||||
CheckMatrices(distances, distances2);
|
||||
CheckMatrices(distances, distances3);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Test the move constructor & move assignment using Binary Space trees.
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE(MoveConstructorBinarySpaceTreeTest)
|
||||
{
|
||||
arma::mat dataset = arma::randu<arma::mat>(5, 500);
|
||||
typedef NeighborSearch<NearestNeighborSort, EuclideanDistance, arma::mat,
|
||||
KDTree> NeighborSearchType;
|
||||
NeighborSearchType* knn = new NeighborSearchType(std::move(dataset));
|
||||
|
||||
// Get predictions.
|
||||
arma::mat distances, distances2, distances3;
|
||||
arma::Mat<size_t> neighbors, neighbors2, neighbors3;
|
||||
|
||||
knn->Search(3, neighbors, distances);
|
||||
|
||||
// Use move constructor.
|
||||
NeighborSearchType knn2(std::move(*knn));
|
||||
|
||||
delete knn;
|
||||
|
||||
knn2.Search(3, neighbors2, distances2);
|
||||
|
||||
// Use move assignment.
|
||||
NeighborSearchType knn3 = std::move(knn2);
|
||||
knn3.Search(3, neighbors3, distances3);
|
||||
|
||||
CheckMatrices(neighbors, neighbors2);
|
||||
CheckMatrices(neighbors, neighbors3);
|
||||
CheckMatrices(distances, distances2);
|
||||
CheckMatrices(distances, distances3);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the move constructor & move assignment using Octree.
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE(MoveConstructorOctreeTest)
|
||||
{
|
||||
arma::mat dataset = arma::randu<arma::mat>(5, 500);
|
||||
typedef NeighborSearch<NearestNeighborSort, EuclideanDistance, arma::mat,
|
||||
Octree> NeighborSearchType;
|
||||
NeighborSearchType* knn = new NeighborSearchType(std::move(dataset));
|
||||
|
||||
// Get predictions.
|
||||
arma::mat distances, distances2, distances3;
|
||||
arma::Mat<size_t> neighbors, neighbors2, neighbors3;
|
||||
|
||||
knn->Search(3, neighbors, distances);
|
||||
|
||||
// Use move constructor.
|
||||
NeighborSearchType knn2(std::move(*knn));
|
||||
|
||||
delete knn;
|
||||
|
||||
knn2.Search(3, neighbors2, distances2);
|
||||
|
||||
// Use move assignment.
|
||||
NeighborSearchType knn3 = std::move(knn2);
|
||||
knn3.Search(3, neighbors3, distances3);
|
||||
|
||||
CheckMatrices(neighbors, neighbors2);
|
||||
CheckMatrices(neighbors, neighbors3);
|
||||
CheckMatrices(distances, distances2);
|
||||
CheckMatrices(distances, distances3);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the move constructor & move assignment using Cover Tree.
|
||||
*/
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* @author Dakshit Agrawal
|
||||
* @author Sourabh Varshney
|
||||
* @author Atharva Khandait
|
||||
* @author Saksham Rastogi
|
||||
*
|
||||
* Tests for loss functions in mlpack::methods::ann:loss_functions.
|
||||
*
|
||||
@@ -21,6 +22,7 @@
|
||||
#include <mlpack/methods/ann/loss_functions/cross_entropy_error.hpp>
|
||||
#include <mlpack/methods/ann/loss_functions/reconstruction_loss.hpp>
|
||||
#include <mlpack/methods/ann/loss_functions/mean_squared_logarithmic_error.hpp>
|
||||
#include <mlpack/methods/ann/loss_functions/mean_bias_error.hpp>
|
||||
#include <mlpack/methods/ann/loss_functions/dice_loss.hpp>
|
||||
#include <mlpack/methods/ann/init_rules/nguyen_widrow_init.hpp>
|
||||
#include <mlpack/methods/ann/ffn.hpp>
|
||||
@@ -431,4 +433,42 @@ BOOST_AUTO_TEST_CASE(DiceLossTest)
|
||||
BOOST_REQUIRE_EQUAL(output.n_cols, input2.n_cols);
|
||||
}
|
||||
|
||||
/*
|
||||
* Simple test for the mean bias error performance function.
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE(SimpleMeanBiasErrorTest)
|
||||
{
|
||||
arma::mat input, output, target;
|
||||
MeanBiasError<> module;
|
||||
|
||||
// Test the Forward function on a user generator input and compare it against
|
||||
// the manually calculated result.
|
||||
input = arma::mat("1.0 0.0 1.0 -1.0 -1.0 0.0 -1.0 0.0");
|
||||
target = arma::zeros(1, 8);
|
||||
double error = module.Forward(std::move(input), std::move(target));
|
||||
BOOST_REQUIRE_EQUAL(error, 0.125);
|
||||
|
||||
// Test the Backward function.
|
||||
module.Backward(std::move(input), std::move(target), std::move(output));
|
||||
// We should get a vector with -1 everywhere.
|
||||
for (double el : output)
|
||||
{
|
||||
BOOST_REQUIRE_EQUAL(el, -1);
|
||||
}
|
||||
BOOST_REQUIRE_EQUAL(output.n_rows, input.n_rows);
|
||||
BOOST_REQUIRE_EQUAL(output.n_cols, input.n_cols);
|
||||
|
||||
// Test the error function on a single input.
|
||||
input = arma::mat("2");
|
||||
target = arma::mat("3");
|
||||
error = module.Forward(std::move(input), std::move(target));
|
||||
BOOST_REQUIRE_EQUAL(error, 1.0);
|
||||
|
||||
// Test the Backward function on a single input.
|
||||
module.Backward(std::move(input), std::move(target), std::move(output));
|
||||
// Test whether the output is negative.
|
||||
BOOST_REQUIRE_EQUAL(arma::accu(output), -1);
|
||||
BOOST_REQUIRE_EQUAL(output.n_elem, 1);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END();
|
||||
|
||||
@@ -284,4 +284,83 @@ BOOST_AUTO_TEST_CASE(NMFMaxIterationTest)
|
||||
BOOST_REQUIRE_GT(arma::norm(h1 - h2), 1e-5);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test NMF with given initial_w and initial_h.
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE(NMFWHGivenInitTest)
|
||||
{
|
||||
mat v = arma::randu(10, 10);
|
||||
mat initialW = arma::randu(10, 5);
|
||||
mat initialH = arma::randu(5, 10);
|
||||
int r = 5;
|
||||
|
||||
SetInputParam("input", v);
|
||||
SetInputParam("rank", r);
|
||||
SetInputParam("initial_w", initialW);
|
||||
SetInputParam("initial_h", initialH);
|
||||
|
||||
mlpackMain();
|
||||
|
||||
const mat w = CLI::GetParam<mat>("w");
|
||||
const mat h = CLI::GetParam<mat>("h");
|
||||
|
||||
// Check the shapes of W and H.
|
||||
BOOST_REQUIRE_EQUAL(w.n_rows, 10);
|
||||
BOOST_REQUIRE_EQUAL(w.n_cols, 5);
|
||||
BOOST_REQUIRE_EQUAL(h.n_rows, 5);
|
||||
BOOST_REQUIRE_EQUAL(h.n_cols, 10);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test NMF with given initial_w.
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE(NMFWGivenInitTest)
|
||||
{
|
||||
mat v = arma::randu(10, 10);
|
||||
mat initialW = arma::randu(10, 5);
|
||||
int r = 5;
|
||||
|
||||
SetInputParam("input", v);
|
||||
SetInputParam("rank", r);
|
||||
SetInputParam("initial_w", initialW);
|
||||
|
||||
mlpackMain();
|
||||
|
||||
const mat w = CLI::GetParam<mat>("w");
|
||||
const mat h = CLI::GetParam<mat>("h");
|
||||
|
||||
// Check the shapes of W and H.
|
||||
BOOST_REQUIRE_EQUAL(w.n_rows, 10);
|
||||
BOOST_REQUIRE_EQUAL(w.n_cols, 5);
|
||||
BOOST_REQUIRE_EQUAL(h.n_rows, 5);
|
||||
BOOST_REQUIRE_EQUAL(h.n_cols, 10);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test NMF with given initial_h.
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE(NMFHGivenInitTest)
|
||||
{
|
||||
mat v = arma::randu(10, 10);
|
||||
mat initialH = arma::randu(5, 10);
|
||||
int r = 5;
|
||||
|
||||
SetInputParam("input", v);
|
||||
SetInputParam("rank", r);
|
||||
SetInputParam("initial_h", initialH);
|
||||
|
||||
mlpackMain();
|
||||
|
||||
const mat w = CLI::GetParam<mat>("w");
|
||||
const mat h = CLI::GetParam<mat>("h");
|
||||
|
||||
// Check the shapes of W and H.
|
||||
BOOST_REQUIRE_EQUAL(w.n_rows, 10);
|
||||
BOOST_REQUIRE_EQUAL(w.n_cols, 5);
|
||||
BOOST_REQUIRE_EQUAL(h.n_rows, 5);
|
||||
BOOST_REQUIRE_EQUAL(h.n_cols, 10);
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END();
|
||||
|
||||
|
||||
@@ -666,9 +666,7 @@ BOOST_AUTO_TEST_CASE(SoftmaxRegressionTest)
|
||||
labels[i] = 0;
|
||||
for (size_t i = 500; i < 1000; ++i)
|
||||
labels[i] = 1;
|
||||
|
||||
SoftmaxRegression sr(dataset, labels, 2);
|
||||
|
||||
SoftmaxRegression srXml(dataset.n_rows, 2);
|
||||
SoftmaxRegression srText(dataset.n_rows, 2);
|
||||
SoftmaxRegression srBinary(dataset.n_rows, 2);
|
||||
|
||||
@@ -360,8 +360,8 @@ BOOST_AUTO_TEST_CASE(SoftmaxRegressionTrainTest)
|
||||
SoftmaxRegression sr(dataset.n_rows, 2);
|
||||
SoftmaxRegression sr2(dataset.n_rows, 2);
|
||||
sr.Parameters() = sr2.Parameters();
|
||||
sr.Train(dataset, labels, 2);
|
||||
ens::L_BFGS lbfgs;
|
||||
sr.Train(dataset, labels, 2, std::move(lbfgs));
|
||||
sr2.Train(dataset, labels, 2, std::move(lbfgs));
|
||||
|
||||
// Ensure that the parameters are the same.
|
||||
|
||||
Reference in New Issue
Block a user