Merge branch 'master' into adagrad_policy

This commit is contained in:
Marcus Edel
2017-03-24 19:23:15 +01:00
committed by GitHub
13 changed files with 614 additions and 96 deletions
+2
View File
@@ -74,6 +74,8 @@ Copyright:
Copyright 2017, Praveen Ch <chvsp972911@gmail.com>
Copyright 2017, Kirill Mishchenko <ki.mishchenko@gmail.com>
Copyright 2017, Abhinav Moudgil <abhinavmoudgil95@gmail.com>
Copyright 2017, Thyrix Yang <thyrixyang@gmail.com>
Copyright 2017, Sagar B Hathwar <sagarbhathwar@gmail.com>
License: BSD-3-clause
All rights reserved.
+9 -16
View File
@@ -21,8 +21,7 @@ a machine learning analog to LAPACK. It aims to implement a wide array of
machine learning methods and functions as a "swiss army knife" for machine
learning researchers.
0. Contents
-----------
### 0. Contents
1. [Introduction](#1-introduction)
2. [Citation details](#2-citation-details)
@@ -32,8 +31,7 @@ learning researchers.
6. [Further documentation](#6-further-documentation)
7. [Bug reporting](#7-bug-reporting)
1. Introduction
---------------
### 1. Introduction
The mlpack website can be found at http://www.mlpack.org and contains numerous
tutorials and extensive documentation. This README serves as a guide for what
@@ -45,8 +43,7 @@ documentation. The website should be consulted for further information:
- [Development Site (Github)](http://www.github.com/mlpack/mlpack/)
- [API documentation](http://www.mlpack.org/docs/mlpack-git/doxygen.php)
2. Citation details
-------------------
### 2. Citation details
If you use mlpack in your research or software, please cite mlpack using the
citation below (given in BiBTeX format):
@@ -64,8 +61,7 @@ citation below (given in BiBTeX format):
Citations are beneficial for the growth and improvement of mlpack.
3. Dependencies
---------------
### 3. Dependencies
mlpack has the following dependencies:
@@ -80,8 +76,7 @@ each of those packages for more information.
If you are compiling Armadillo by hand, ensure that LAPACK and BLAS are enabled.
4. Building mlpack from source
------------------------------
### 4. Building mlpack from source
This section discusses how to build mlpack from source. However, mlpack is in
the repositories of many Linux distributions and so it may be easier to use the
@@ -178,8 +173,7 @@ manually). One way to do this, on Linux, is to ensure that the
(or whatever directory `libmlpack.so` is installed in.)
5. Running mlpack programs
--------------------------
### 5. Running mlpack programs
After building mlpack, the executables will reside in `build/bin/`. You can call
them from there, or you can install the library and (depending on system
@@ -211,8 +205,7 @@ unique to `mlpack_knn` but is available in all mlpack programs. Verbose
output also gives timing output at the end of the program, which can be very
useful.
6. Further documentation
------------------------
### 6. Further documentation
The documentation given here is only a fraction of the available documentation
for mlpack. If doxygen is installed, you can type `make doc` to build the
@@ -224,8 +217,8 @@ older versions of mlpack:
- [Development Site (Github)](https://www.github.com/mlpack/mlpack/)
- [API documentation](http://www.mlpack.org/docs/mlpack-git/doxygen.php)
7. Bug reporting
----------------
### 7. Bug reporting
(see also [mlpack help](http://www.mlpack.org/help.html))
If you find a bug in mlpack or have any problems, numerous routes are available
+2
View File
@@ -215,6 +215,8 @@
* - Praveen Ch <chvsp972911@gmail.com>
* - Kirill Mishchenko <ki.mishchenko@gmail.com>
* - Abhinav Moudgil <abhinavmoudgil95@gmail.com>
* - Thyrix Yang <thyrixyang@gmail.com>
* - Sagar B Hathwar <sagarbhathwar@gmail.com>
*/
// First, include all of the prerequisites.
+34 -23
View File
@@ -20,10 +20,20 @@ template bool Load<int>(const std::string&,
const bool,
const bool);
template bool Load<size_t>(const std::string&,
arma::Mat<size_t>&,
const bool,
const bool);
template bool Load<unsigned int>(const std::string&,
arma::Mat<unsigned int>&,
const bool,
const bool);
template bool Load<unsigned long>(const std::string&,
arma::Mat<unsigned long>&,
const bool,
const bool);
template bool Load<unsigned long long>(const std::string&,
arma::Mat<unsigned long long>&,
const bool,
const bool);
template bool Load<float>(const std::string&,
arma::Mat<float>&,
@@ -35,22 +45,32 @@ template bool Load<double>(const std::string&,
const bool,
const bool);
template bool Load<unsigned long long>(const std::string&,
arma::Mat<unsigned long long>&,
const bool,
const bool);
template bool Load<int, IncrementPolicy>(const std::string&,
arma::Mat<int>&,
DatasetMapper<IncrementPolicy>&,
const bool,
const bool);
template bool Load<size_t, IncrementPolicy>(const std::string&,
arma::Mat<size_t>&,
DatasetMapper<IncrementPolicy>&,
const bool,
const bool);
template bool Load<unsigned int, IncrementPolicy>(
const std::string&,
arma::Mat<unsigned int>&,
DatasetMapper<IncrementPolicy>&,
const bool,
const bool);
template bool Load<unsigned long, IncrementPolicy>(
const std::string&,
arma::Mat<unsigned long>&,
DatasetMapper<IncrementPolicy>&,
const bool,
const bool);
template bool Load<unsigned long long, IncrementPolicy>(
const std::string&,
arma::Mat<unsigned long long>&,
DatasetMapper<IncrementPolicy>&,
const bool,
const bool);
template bool Load<float, IncrementPolicy>(const std::string&,
arma::Mat<float>&,
@@ -64,14 +84,5 @@ template bool Load<double, IncrementPolicy>(const std::string&,
const bool,
const bool);
#ifndef _WIN32
template bool Load<unsigned long long, IncrementPolicy>(
const std::string&,
arma::Mat<unsigned long long>&,
DatasetMapper<IncrementPolicy>&,
const bool,
const bool);
#endif
} // namespace data
} // namespace mlpack
+26 -21
View File
@@ -69,27 +69,32 @@ extern template bool Load<int>(const std::string&,
const bool,
const bool);
extern template bool Load<size_t>(const std::string&,
arma::Mat<size_t>&,
const bool,
const bool);
// size_t and uword should be one of these three typedefs.
extern template bool Load<unsigned int>(const std::string&,
arma::Mat<unsigned int>&,
const bool,
const bool);
extern template bool Load<unsigned long>(const std::string&,
arma::Mat<unsigned long>&,
const bool,
const bool);
extern template bool Load<unsigned long long>(const std::string&,
arma::Mat<unsigned long long>&,
const bool,
const bool);
extern template bool Load<float>(const std::string&,
arma::Mat<float>&,
const bool,
const bool);
extern template bool Load<double>(const std::string&,
arma::Mat<double>&,
const bool,
const bool);
#ifndef _WIN32
extern template bool Load<unsigned long long>(
const std::string&,
arma::Mat<unsigned long long>&,
const bool,
const bool);
#endif
/**
* Load a column vector from a file, guessing the filetype from the extension.
*
@@ -200,9 +205,16 @@ extern template bool Load<int, IncrementPolicy>(
const bool,
const bool);
extern template bool Load<size_t, IncrementPolicy>(
extern template bool Load<arma::u32, IncrementPolicy>(
const std::string&,
arma::Mat<size_t>&,
arma::Mat<arma::u32>&,
DatasetMapper<IncrementPolicy>&,
const bool,
const bool);
extern template bool Load<arma::u64, IncrementPolicy>(
const std::string&,
arma::Mat<arma::u64>&,
DatasetMapper<IncrementPolicy>&,
const bool,
const bool);
@@ -221,13 +233,6 @@ extern template bool Load<double, IncrementPolicy>(
const bool,
const bool);
extern template bool Load<unsigned long long, IncrementPolicy>(
const std::string&,
arma::Mat<unsigned long long>&,
DatasetMapper<IncrementPolicy>&,
const bool,
const bool);
/**
* Load a model from a file, guessing the filetype from the extension, or,
* optionally, loading the specified format. If automatic extension detection
@@ -6,6 +6,7 @@ set(SOURCES
kathirvalavakumar_subavathi_init.hpp
nguyen_widrow_init.hpp
zero_init.hpp
gaussian_init.hpp
)
# Add directory name to sources.
@@ -0,0 +1,88 @@
/**
* @file gaussian_init.hpp
* @author Kris Singh
*
* Intialization rule for the neural networks. This simple initialization is
* performed by assigning a gaussian matrix with a given mean and variance
* to the weight matrix.
*
* 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_INIT_RULES_GAUSSIAN_INIT_HPP
#define MLPACK_METHODS_ANN_INIT_RULES_GAUSSIAN_INIT_HPP
#include <mlpack/prereqs.hpp>
#include <mlpack/core/math/random.hpp>
using namespace mlpack::math;
namespace mlpack {
namespace ann /** Artificial Neural Network. */ {
/**
* This class is used to initialize weigth matrix with a gaussian.
*/
class GaussianInitialization
{
public:
/**
* Initialize the gaussian with the given mean and variance.
*
* @param mean Mean of the gaussian
* @param variance Variance of the gaussian
*/
GaussianInitialization(const double mean = 0, const double variance = 1) :
mean(mean), variance(variance)
{
// Nothing to do here.
}
/**
* Initialize the elements weight matrix using a Gaussian Distribution.
*
* @param W Weight matrix to initialize.
* @param rows Number of rows.
* @param cols Number of columns.
*/
void Initialize(arma::mat& W,
const size_t rows,
const size_t cols)
{
W = arma::mat(rows, cols);
W.imbue( [&]() { return arma::as_scalar(RandNormal(mean, variance)); } );
}
/**
* Initialize randomly the elements of the specified weight 3rd order tensor.
*
* @param W Weight matrix to initialize.
* @param rows Number of rows.
* @param cols Number of columns.
* @param slice Numbers of slices.
*/
void Initialize(arma::cube & W,
const size_t rows,
const size_t cols,
const size_t slices)
{
W = arma::cube(rows, cols, slices);
for (size_t i = 0; i < slices; i++)
Initialize(W.slice(i), rows, cols);
}
private:
//! Mean of the gaussian.
const double mean;
//! Variance of the gaussian.
const double variance;
}; // class GaussianInitialization
} // namespace ann
} // namespace mlpack
#endif
@@ -227,6 +227,16 @@ void DecisionTree<FitnessFunction,
const size_t numClasses,
const size_t minimumLeafSize)
{
// Sanity check on data.
if (data.n_cols != labels.n_elem)
{
std::ostringstream oss;
oss << "DecisionTree::Train(): number of points (" << data.n_cols << ") "
<< "does not match number of labels (" << labels.n_elem << ")!"
<< std::endl;
throw std::invalid_argument(oss.str());
}
// Clear children if needed.
for (size_t i = 0; i < children.size(); ++i)
delete children[i];
@@ -347,6 +357,16 @@ void DecisionTree<FitnessFunction,
const size_t numClasses,
const size_t minimumLeafSize)
{
// Sanity check on data.
if (data.n_cols != labels.n_elem)
{
std::ostringstream oss;
oss << "DecisionTree::Train(): number of points (" << data.n_cols << ") "
<< "does not match number of labels (" << labels.n_elem << ")!"
<< std::endl;
throw std::invalid_argument(oss.str());
}
// Clear children if needed.
for (size_t i = 0; i < children.size(); ++i)
delete children[i];
@@ -133,6 +133,40 @@ class SoftmaxRegression
*/
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.
*/
template<typename VecType>
size_t Classify(const VecType& point) const;
/**
* Classify the given points, returning class probabilities and predicted
* class label 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 Matrix of data points to be classified.
* @param labels Predicted labels for each point.
* @param probabilities Class probabilities for each point.
*/
void Classify(const arma::mat& dataset, arma::Row<size_t>& labels,
arma::mat& probabilites) const;
/**
* Classify the given points, returning class probabilities for each point.
*
* @param dataset Matrix of data points to be classified.
* @param probabilities Class probabilities for each point.
*/
void Classify(const arma::mat& dataset,
arma::mat& probabilities) const;
/**
* Computes accuracy of the learned model given the feature data and the
* labels associated with each data point. Predictions are made using the
@@ -161,7 +195,7 @@ class SoftmaxRegression
* @param numClasses Number of classes for classification.
* @return Objective value of the final point.
*/
double Train(const arma::mat &data, const arma::Row<size_t>& labels,
double Train(const arma::mat& data, const arma::Row<size_t>& labels,
const size_t numClasses);
//! Sets the number of classes.
@@ -75,35 +75,8 @@ void SoftmaxRegression<OptimizerType>::Classify(const arma::mat& dataset,
arma::Row<size_t>& labels)
const
{
if (dataset.n_rows != FeatureSize())
{
std::ostringstream oss;
oss << "SoftmaxRegression::Classify(): dataset has " << dataset.n_rows
<< " dimensions, but model has " << FeatureSize() << "dimensions";
throw std::invalid_argument(oss.str());
}
// Calculate the probabilities for each test input.
arma::mat hypothesis, probabilities;
if (fitIntercept)
{
// In order to add the intercept term, we should compute following matrix:
// [1; data] = arma::join_cols(ones(1, data.n_cols), data)
// hypothesis = arma::exp(parameters * [1; data]).
//
// Since the cost of join maybe high due to the copy of original data,
// split the hypothesis computation to two components.
hypothesis = arma::exp(
arma::repmat(parameters.col(0), 1, dataset.n_cols) +
parameters.cols(1, parameters.n_cols - 1) * dataset);
}
else
{
hypothesis = arma::exp(parameters * dataset);
}
probabilities = hypothesis / arma::repmat(arma::sum(hypothesis, 0),
numClasses, 1);
arma::mat probabilities;
Classify(dataset, probabilities);
// Prepare necessary data.
labels.zeros(dataset.n_cols);
@@ -128,6 +101,82 @@ void SoftmaxRegression<OptimizerType>::Classify(const arma::mat& dataset,
}
}
template<template<typename> class OptimizerType>
template<typename VecType>
size_t SoftmaxRegression<OptimizerType>::Classify(const VecType& point) const
{
arma::Row<size_t> label(1);
Classify(point, label);
return size_t(label(0));
}
template<template<typename> class OptimizerType>
void SoftmaxRegression<OptimizerType>::Classify(const arma::mat& dataset,
arma::Row<size_t>& labels,
arma::mat& probabilities)
const
{
Classify(dataset, probabilities);
// Prepare necessary data.
labels.zeros(dataset.n_cols);
double maxProbability = 0;
// For each test input.
for (size_t i = 0; i < dataset.n_cols; i++)
{
// For each class.
for (size_t j = 0; j < numClasses; j++)
{
// If a higher class probability is encountered, change prediction.
if (probabilities(j, i) > maxProbability)
{
maxProbability = probabilities(j, i);
labels(i) = j;
}
}
// Set maximum probability to zero for the next input.
maxProbability = 0;
}
}
template<template<typename> class OptimizerType>
void SoftmaxRegression<OptimizerType>::Classify(const arma::mat& dataset,
arma::mat& probabilities)
const
{
if (dataset.n_rows != FeatureSize())
{
std::ostringstream oss;
oss << "SoftmaxRegression::Classify(): dataset has " << dataset.n_rows
<< " dimensions, but model has " << FeatureSize() << "dimensions";
throw std::invalid_argument(oss.str());
}
// Calculate the probabilities for each test input.
arma::mat hypothesis;
if (fitIntercept)
{
// In order to add the intercept term, we should compute following matrix:
// [1; data] = arma::join_cols(ones(1, data.n_cols), data)
// hypothesis = arma::exp(parameters * [1; data]).
//
// Since the cost of join maybe high due to the copy of original data,
// split the hypothesis computation to two components.
hypothesis = arma::exp(
arma::repmat(parameters.col(0), 1, dataset.n_cols) +
parameters.cols(1, parameters.n_cols - 1) * dataset);
}
else
{
hypothesis = arma::exp(parameters * dataset);
}
probabilities = hypothesis / arma::repmat(arma::sum(hypothesis, 0),
numClasses, 1);
}
template<template<typename> class OptimizerType>
double SoftmaxRegression<OptimizerType>::ComputeAccuracy(
const arma::mat& testData,
+4 -6
View File
@@ -136,17 +136,15 @@ BOOST_AUTO_TEST_CASE(TestBooleanOption)
// Now, if we specify this flag, it should be true.
int argc = 2;
char* argv[2];
argv[0] = strcpy(new char[strlen("programname") + 1], "programname");
argv[1] = strcpy(new char[strlen("--flag_test") + 1], "--flag_test");
const char* argv[2];
argv[0] = "programname";
argv[1] = "--flag_test";
CLI::ParseCommandLine(argc, argv);
CLI::ParseCommandLine(argc, const_cast<char**>(argv));
BOOST_REQUIRE_EQUAL(CLI::GetParam<bool>("flag_test"), true);
BOOST_REQUIRE_EQUAL(CLI::HasParam("flag_test"), true);
delete[] argv[0];
delete[] argv[1];
}
/**
+57
View File
@@ -10,6 +10,7 @@
* http://www.opensource.org/licenses/BSD-3-Clause for more information.
*/
#include <mlpack/core.hpp>
#include <mlpack/core/math/random.hpp>
#include <mlpack/methods/ann/init_rules/kathirvalavakumar_subavathi_init.hpp>
#include <mlpack/methods/ann/init_rules/nguyen_widrow_init.hpp>
@@ -17,6 +18,8 @@
#include <mlpack/methods/ann/init_rules/orthogonal_init.hpp>
#include <mlpack/methods/ann/init_rules/random_init.hpp>
#include <mlpack/methods/ann/init_rules/zero_init.hpp>
#include <mlpack/methods/ann/init_rules/gaussian_init.hpp>
#include <boost/test/unit_test.hpp>
#include "test_tools.hpp"
@@ -123,4 +126,58 @@ BOOST_AUTO_TEST_CASE(OivsInitTest)
BOOST_REQUIRE_EQUAL(1, 1);
}
// Test the GaussianInitialization class.
BOOST_AUTO_TEST_CASE(GaussianInitTest)
{
const size_t row = 7;
const size_t col = 7;
const size_t slice = 2;
double mean = 1;
double mean3d = 1;
double var = 1;
double var3d = 1;
arma::mat weights;
arma::cube weights3d;
GaussianInitialization t(0, 0.2);
// It isn't guaranteed that the method will converge in the specified number
// of iterations using random weights. If this works 1 of 5 times, I'm fine
// with that.
size_t counter = 0;
for(size_t trial = 0; trial < 5; trial++)
{
for(size_t i = 0; i < 10; i++)
{
t.Initialize(weights, row, col);
t.Initialize(weights3d, row, col, slice);
// Calaculate mean and variance over the dense matrix.
mean += arma::accu(weights) / weights.n_elem;
var += arma::accu(pow((weights.t() - mean), 2)) / weights.n_elem - 1;
// Calaculate mean and variance over the 3rd order tensor.
mean3d += arma::accu(weights3d.slice(0)) / weights3d.slice(0).n_elem;
var3d += arma::accu(pow((weights3d.slice(0) - mean), 2)) /
weights3d.slice(0).n_elem - 1;
}
mean /= 10;
var /= 10;
mean3d /= 10;
var3d /= 10;
if ((mean > 0 && mean < 0.4) && (var > 0 && var < 0.6) &&
(mean3d > 0 && mean3d < 0.4) && (var3d > 0 && var3d < 0.6))
{
counter++;
break;
}
}
BOOST_REQUIRE(counter >= 1);
}
BOOST_AUTO_TEST_SUITE_END();
@@ -413,4 +413,262 @@ BOOST_AUTO_TEST_CASE(SoftmaxRegressionOptimizerTrainTest)
}
}
BOOST_AUTO_TEST_CASE(SoftmaxRegressionClassifySinglePointTest)
{
const size_t points = 5000;
const size_t inputSize = 5;
const size_t numClasses = 5;
const double lambda = 0.5;
// Generate five-Gaussian dataset.
arma::mat identity = arma::eye<arma::mat>(5, 5);
GaussianDistribution g1(arma::vec("1.0 9.0 1.0 2.0 2.0"), identity);
GaussianDistribution g2(arma::vec("4.0 3.0 4.0 2.0 2.0"), identity);
GaussianDistribution g3(arma::vec("3.0 2.0 7.0 0.0 5.0"), identity);
GaussianDistribution g4(arma::vec("4.0 1.0 1.0 2.0 7.0"), identity);
GaussianDistribution g5(arma::vec("1.0 0.0 1.0 8.0 3.0"), identity);
arma::mat data(inputSize, points);
arma::Row<size_t> labels(points);
for (size_t i = 0; i < points / 5; i++)
{
data.col(i) = g1.Random();
labels(i) = 0;
}
for (size_t i = points / 5; i < (2 * points) / 5; i++)
{
data.col(i) = g2.Random();
labels(i) = 1;
}
for (size_t i = (2 * points) / 5; i < (3 * points) / 5; i++)
{
data.col(i) = g3.Random();
labels(i) = 2;
}
for (size_t i = (3 * points) / 5; i < (4 * points) / 5; i++)
{
data.col(i) = g4.Random();
labels(i) = 3;
}
for (size_t i = (4 * points) / 5; i < points; i++)
{
data.col(i) = g5.Random();
labels(i) = 4;
}
// Train softmax regression object.
SoftmaxRegression<> sr(data, labels, numClasses, lambda);
// Create test dataset.
for (size_t i = 0; i < points / 5; i++)
{
data.col(i) = g1.Random();
labels(i) = 0;
}
for (size_t i = points / 5; i < (2 * points) / 5; i++)
{
data.col(i) = g2.Random();
labels(i) = 1;
}
for (size_t i = (2 * points) / 5; i < (3 * points) / 5; i++)
{
data.col(i) = g3.Random();
labels(i) = 2;
}
for (size_t i = (3 * points) / 5; i < (4 * points) / 5; i++)
{
data.col(i) = g4.Random();
labels(i) = 3;
}
for (size_t i = (4 * points) / 5; i < points; i++)
{
data.col(i) = g5.Random();
labels(i) = 4;
}
sr.Classify(data, labels);
for(size_t i = 0; i < data.n_cols; ++i)
{
BOOST_REQUIRE_EQUAL(sr.Classify(data.col(i)), labels(i));
}
}
BOOST_AUTO_TEST_CASE(SoftmaxRegressionComputeProbabilitiesTest)
{
const size_t points = 5000;
const size_t inputSize = 5;
const size_t numClasses = 5;
const double lambda = 0.5;
// Generate five-Gaussian dataset.
arma::mat identity = arma::eye<arma::mat>(5, 5);
GaussianDistribution g1(arma::vec("1.0 9.0 1.0 2.0 2.0"), identity);
GaussianDistribution g2(arma::vec("4.0 3.0 4.0 2.0 2.0"), identity);
GaussianDistribution g3(arma::vec("3.0 2.0 7.0 0.0 5.0"), identity);
GaussianDistribution g4(arma::vec("4.0 1.0 1.0 2.0 7.0"), identity);
GaussianDistribution g5(arma::vec("1.0 0.0 1.0 8.0 3.0"), identity);
arma::mat data(inputSize, points);
arma::Row<size_t> labels(points);
for (size_t i = 0; i < points / 5; i++)
{
data.col(i) = g1.Random();
labels(i) = 0;
}
for (size_t i = points / 5; i < (2 * points) / 5; i++)
{
data.col(i) = g2.Random();
labels(i) = 1;
}
for (size_t i = (2 * points) / 5; i < (3 * points) / 5; i++)
{
data.col(i) = g3.Random();
labels(i) = 2;
}
for (size_t i = (3 * points) / 5; i < (4 * points) / 5; i++)
{
data.col(i) = g4.Random();
labels(i) = 3;
}
for (size_t i = (4 * points) / 5; i < points; i++)
{
data.col(i) = g5.Random();
labels(i) = 4;
}
// Train softmax regression object.
SoftmaxRegression<> sr(data, labels, numClasses, lambda);
// Create test dataset.
for (size_t i = 0; i < points / 5; i++)
{
data.col(i) = g1.Random();
labels(i) = 0;
}
for (size_t i = points / 5; i < (2 * points) / 5; i++)
{
data.col(i) = g2.Random();
labels(i) = 1;
}
for (size_t i = (2 * points) / 5; i < (3 * points) / 5; i++)
{
data.col(i) = g3.Random();
labels(i) = 2;
}
for (size_t i = (3 * points) / 5; i < (4 * points) / 5; i++)
{
data.col(i) = g4.Random();
labels(i) = 3;
}
for (size_t i = (4 * points) / 5; i < points; i++)
{
data.col(i) = g5.Random();
labels(i) = 4;
}
arma::mat probabilities;
sr.Classify(data, probabilities);
BOOST_REQUIRE_EQUAL(probabilities.n_cols, data.n_cols);
BOOST_REQUIRE_EQUAL(probabilities.n_rows, sr.NumClasses());
for(size_t i = 0; i < data.n_cols; ++i)
{
BOOST_REQUIRE_CLOSE(arma::sum(probabilities.col(i)), 1.0, 1e-5);
}
}
BOOST_AUTO_TEST_CASE(SoftmaxRegressionComputeProbabilitiesAndLabelsTest)
{
const size_t points = 5000;
const size_t inputSize = 5;
const size_t numClasses = 5;
const double lambda = 0.5;
// Generate five-Gaussian dataset.
arma::mat identity = arma::eye<arma::mat>(5, 5);
GaussianDistribution g1(arma::vec("1.0 9.0 1.0 2.0 2.0"), identity);
GaussianDistribution g2(arma::vec("4.0 3.0 4.0 2.0 2.0"), identity);
GaussianDistribution g3(arma::vec("3.0 2.0 7.0 0.0 5.0"), identity);
GaussianDistribution g4(arma::vec("4.0 1.0 1.0 2.0 7.0"), identity);
GaussianDistribution g5(arma::vec("1.0 0.0 1.0 8.0 3.0"), identity);
arma::mat data(inputSize, points);
arma::Row<size_t> labels(points);
for (size_t i = 0; i < points / 5; i++)
{
data.col(i) = g1.Random();
labels(i) = 0;
}
for (size_t i = points / 5; i < (2 * points) / 5; i++)
{
data.col(i) = g2.Random();
labels(i) = 1;
}
for (size_t i = (2 * points) / 5; i < (3 * points) / 5; i++)
{
data.col(i) = g3.Random();
labels(i) = 2;
}
for (size_t i = (3 * points) / 5; i < (4 * points) / 5; i++)
{
data.col(i) = g4.Random();
labels(i) = 3;
}
for (size_t i = (4 * points) / 5; i < points; i++)
{
data.col(i) = g5.Random();
labels(i) = 4;
}
// Train softmax regression object.
SoftmaxRegression<> sr(data, labels, numClasses, lambda);
// Create test dataset.
for (size_t i = 0; i < points / 5; i++)
{
data.col(i) = g1.Random();
labels(i) = 0;
}
for (size_t i = points / 5; i < (2 * points) / 5; i++)
{
data.col(i) = g2.Random();
labels(i) = 1;
}
for (size_t i = (2 * points) / 5; i < (3 * points) / 5; i++)
{
data.col(i) = g3.Random();
labels(i) = 2;
}
for (size_t i = (3 * points) / 5; i < (4 * points) / 5; i++)
{
data.col(i) = g4.Random();
labels(i) = 3;
}
for (size_t i = (4 * points) / 5; i < points; i++)
{
data.col(i) = g5.Random();
labels(i) = 4;
}
arma::mat probabilities;
arma::Row<size_t> testLabels;
sr.Classify(data, labels);
sr.Classify(data, testLabels, probabilities);
BOOST_REQUIRE_EQUAL(probabilities.n_cols, data.n_cols);
BOOST_REQUIRE_EQUAL(probabilities.n_rows, sr.NumClasses());
for(size_t i = 0; i < data.n_cols; ++i)
{
BOOST_REQUIRE_CLOSE(arma::sum(probabilities.col(i)), 1.0, 1e-5);
BOOST_REQUIRE_EQUAL(testLabels(i), labels(i));
}
}
BOOST_AUTO_TEST_SUITE_END();