Merge branch 'master' into cereal
Signed-off-by: Omar Shrit <omar@shrit.me>
This commit is contained in:
@@ -24,8 +24,9 @@ steps:
|
||||
sudo apt-get install -y --allow-unauthenticated libopenblas-dev liblapack-dev g++ libboost1.70-dev libarmadillo-dev xz-utils libcereal-dev
|
||||
|
||||
if [ "$(binding)" == "python" ]; then
|
||||
/usr/bin/python3 -m pip install --upgrade pip
|
||||
/usr/bin/python3 -m pip install --upgrade --ignore-installed setuptools cython pandas
|
||||
export PYBIN=$(which python)
|
||||
$PYBIN -m pip install --upgrade pip
|
||||
$PYBIN -m pip install --upgrade --ignore-installed setuptools cython pandas
|
||||
fi
|
||||
|
||||
if [ "a$(julia.version)" != "a" ]; then
|
||||
@@ -55,7 +56,7 @@ steps:
|
||||
export GOPATH=$PWD/src/mlpack/bindings/go
|
||||
go get -u -t gonum.org/v1/gonum/...
|
||||
fi
|
||||
cmake $(CMakeArgs) ..
|
||||
cmake $(CMakeArgs) -DPYTHON_EXECUTABLE=`which python` ..
|
||||
displayName: 'CMake'
|
||||
|
||||
# Build mlpack
|
||||
|
||||
@@ -418,6 +418,8 @@ find_package(cereal "${CEREAL_VERSION}" REQUIRED)
|
||||
# Unfortunately this configuration variable is necessary and will need to be
|
||||
# updated as time goes on and new versions are released.
|
||||
set(Boost_ADDITIONAL_VERSIONS
|
||||
"1.74.0" "1.74"
|
||||
"17.3.0" "17.3"
|
||||
"1.72.0" "1.72"
|
||||
"1.71.0" "1.71"
|
||||
"1.70.0" "1.70"
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
# Project related configuration options
|
||||
#---------------------------------------------------------------------------
|
||||
PROJECT_NAME = mlpack
|
||||
PROJECT_NUMBER = 3.3.2
|
||||
PROJECT_NUMBER = 3.4.1
|
||||
OUTPUT_DIRECTORY = ./doc
|
||||
CREATE_SUBDIRS = NO
|
||||
OUTPUT_LANGUAGE = English
|
||||
|
||||
+16
@@ -1,5 +1,21 @@
|
||||
### mlpack ?.?.?
|
||||
###### ????-??-??
|
||||
|
||||
### mlpack 3.4.1
|
||||
###### 2020-09-07
|
||||
* Fix incorrect parsing of required matrix/model parameters for command-line
|
||||
bindings (#2600).
|
||||
|
||||
* Add manual type specification support to `data::Load()` and `data::Save()`
|
||||
(#2084, #2135, #2602).
|
||||
|
||||
* Remove use of internal Armadillo functionality (#2596, #2601, #2602).
|
||||
|
||||
### mlpack 3.4.0
|
||||
###### 2020-09-01
|
||||
|
||||
* Issue warnings when metrics produce NaNs in KFoldCV (#2595).
|
||||
|
||||
* Added bindings for _R_ during Google Summer of Code (#2556).
|
||||
|
||||
* Added common striptype function for all bindings (#2556).
|
||||
|
||||
@@ -23,7 +23,7 @@ src="https://cdn.rawgit.com/mlpack/mlpack.org/e7d36ed8/mlpack-black.svg" style="
|
||||
<p align="center">
|
||||
<em>
|
||||
Download:
|
||||
<a href="https://www.mlpack.org/files/mlpack-3.2.2.tar.gz">current stable version (3.2.2)</a>
|
||||
<a href="https://www.mlpack.org/files/mlpack-3.4.1.tar.gz">current stable version (3.4.1)</a>
|
||||
</em>
|
||||
</p>
|
||||
|
||||
@@ -153,7 +153,7 @@ on Ubuntu, you can install mlpack with the following command:
|
||||
|
||||
Note: Older Ubuntu versions may not have the most recent version of mlpack
|
||||
available---for instance, at the time of this writing, Ubuntu 16.04 only has
|
||||
mlpack 3.2.2 available. Options include upgrading your Ubuntu version, finding
|
||||
mlpack 3.4.1 available. Options include upgrading your Ubuntu version, finding
|
||||
a PPA or other non-official sources, or installing with a manual build.
|
||||
|
||||
There are some useful pages to consult in addition to this section:
|
||||
|
||||
@@ -104,16 +104,16 @@
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>false</ConformanceMode>
|
||||
<AdditionalIncludeDirectories>C:\boost\boost_1_66_0;C:\mlpack\armadillo-8.500.1\include;C:\mlpack\mlpack-3.2.2\build\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>C:\boost\boost_1_66_0;C:\mlpack\armadillo-8.500.1\include;C:\mlpack\mlpack-3.4.1\build\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>C:\mlpack\mlpack-3.2.2\build\Debug\mlpack.lib;C:\boost\boost_1_66_0\lib64-msvc-14.1\libboost_serialization-vc141-mt-gd-x64-1_66.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>C:\mlpack\mlpack-3.4.1\build\Debug\mlpack.lib;C:\boost\boost_1_66_0\lib64-msvc-14.1\libboost_serialization-vc141-mt-gd-x64-1_66.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
<PostBuildEvent>
|
||||
<Command>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)
|
||||
<Command>xcopy /y "C:\mlpack\mlpack-3.4.1\build\Debug\mlpack.dll" $(OutDir)
|
||||
xcopy /y "C:\mlpack\mlpack-3.4.1\packages\OpenBLAS.0.2.14.1\lib\native\bin\x64\*.dll" $(OutDir)
|
||||
xcopy /y "$(ProjectDir)..\..\..\..\src\mlpack\tests\data\german.csv" "$(ProjectDir)data\german.csv*"</Command>
|
||||
</PostBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
|
||||
+6
-6
@@ -30,7 +30,7 @@ to build mlpack on Windows, see \ref build_windows (alternatively, you can read
|
||||
is based on older versions).
|
||||
|
||||
You can download the latest mlpack release from here:
|
||||
<a href="https://www.mlpack.org/files/mlpack-3.2.2.tar.gz">mlpack-3.2.2</a>
|
||||
<a href="https://www.mlpack.org/files/mlpack-3.4.1.tar.gz">mlpack-3.4.1</a>
|
||||
|
||||
@section build_simple Simple Linux build instructions
|
||||
|
||||
@@ -38,9 +38,9 @@ Assuming all dependencies are installed in the system, you can run the commands
|
||||
below directly to build and install mlpack.
|
||||
|
||||
@code
|
||||
$ wget https://www.mlpack.org/files/mlpack-3.2.2.tar.gz
|
||||
$ tar -xvzpf mlpack-3.2.2.tar.gz
|
||||
$ mkdir mlpack-3.2.2/build && cd mlpack-3.2.2/build
|
||||
$ wget https://www.mlpack.org/files/mlpack-3.4.1.tar.gz
|
||||
$ tar -xvzpf mlpack-3.4.1.tar.gz
|
||||
$ mkdir mlpack-3.4.1/build && cd mlpack-3.4.1/build
|
||||
$ cmake ../
|
||||
$ make -j4 # The -j is the number of cores you want to use for a build.
|
||||
$ sudo make install
|
||||
@@ -65,8 +65,8 @@ configure mlpack.
|
||||
First we should unpack the mlpack source and create a build directory.
|
||||
|
||||
@code
|
||||
$ tar -xvzpf mlpack-3.2.2.tar.gz
|
||||
$ cd mlpack-3.2.2
|
||||
$ tar -xvzpf mlpack-3.4.1.tar.gz
|
||||
$ cd mlpack-3.4.1
|
||||
$ mkdir build
|
||||
@endcode
|
||||
|
||||
|
||||
@@ -32,9 +32,9 @@ build and install mlpack. You can copy-paste the commands into your shell.
|
||||
@code{.sh}
|
||||
sudo apt-get install libboost-all-dev g++ cmake libarmadillo-dev python-pip wget
|
||||
sudo pip install cython setuptools distutils numpy pandas
|
||||
wget https://www.mlpack.org/files/mlpack-3.2.2.tar.gz
|
||||
tar -xvzpf mlpack-3.2.2.tar.gz
|
||||
mkdir -p mlpack-3.2.2/build/ && cd mlpack-3.2.2/build/
|
||||
wget https://www.mlpack.org/files/mlpack-3.4.1.tar.gz
|
||||
tar -xvzpf mlpack-3.4.1.tar.gz
|
||||
mkdir -p mlpack-3.4.1/build/ && cd mlpack-3.4.1/build/
|
||||
cmake ../ && make -j4 && sudo make install
|
||||
@endcode
|
||||
|
||||
|
||||
@@ -29,17 +29,17 @@ mlpack and dependencies in Release Mode).
|
||||
@code
|
||||
- C:\boost\boost_1_71_0\lib\native\include
|
||||
- C:\mlpack\armadillo-9.800.3\include
|
||||
- C:\mlpack\mlpack-3.2.2\build\include
|
||||
- C:\mlpack\mlpack-3.4.1\build\include
|
||||
@endcode
|
||||
- Under Linker > Input > Additional Dependencies add:
|
||||
@code
|
||||
- C:\mlpack\mlpack-3.2.2\build\Debug\mlpack.lib
|
||||
- C:\mlpack\mlpack-3.4.1\build\Debug\mlpack.lib
|
||||
- C:\boost\boost_1_71_0\lib64-msvc-14.2\libboost_serialization-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.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)
|
||||
- xcopy /y "C:\mlpack\mlpack-3.4.1\build\Debug\mlpack.dll" $(OutDir)
|
||||
- xcopy /y "C:\mlpack\mlpack-3.4.1\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
|
||||
|
||||
@@ -54,7 +54,7 @@ target_link_libraries(mlpack ${MLPACK_LIBRARIES})
|
||||
|
||||
set_target_properties(mlpack
|
||||
PROPERTIES
|
||||
VERSION 3.3
|
||||
VERSION 3.4
|
||||
SOVERSION 3
|
||||
)
|
||||
|
||||
|
||||
@@ -47,8 +47,8 @@ void ParseCommandLine(int argc, char** argv)
|
||||
{
|
||||
// Add the parameter to desc.
|
||||
util::ParamData& d = it->second;
|
||||
IO::GetSingleton().functionMap[d.tname]["AddToCLI11"]
|
||||
(d, NULL, (void*) &app);
|
||||
IO::GetSingleton().functionMap[d.tname]["AddToCLI11"](d, NULL, (void*)
|
||||
&app);
|
||||
}
|
||||
|
||||
// Mark that we did parsing.
|
||||
@@ -136,13 +136,15 @@ void ParseCommandLine(int argc, char** argv)
|
||||
util::ParamData d = iter->second;
|
||||
if (d.required)
|
||||
{
|
||||
const std::string cliName;
|
||||
// CLI11 expects the parameter name to have "--" prepended.
|
||||
std::string cliName;
|
||||
IO::GetSingleton().functionMap[d.tname]["MapParameterName"](d, NULL,
|
||||
(void*) &cliName);
|
||||
cliName = "--" + cliName;
|
||||
|
||||
if (!app.count(cliName))
|
||||
{
|
||||
Log::Fatal << "Required option --" << cliName << " is undefined."
|
||||
Log::Fatal << "Required option " << cliName << " is undefined."
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -246,17 +246,32 @@ double KFoldCV<MLAlgorithm,
|
||||
{
|
||||
arma::vec evaluations(k);
|
||||
|
||||
size_t numInvalidScores = 0;
|
||||
for (size_t i = 0; i < k; ++i)
|
||||
{
|
||||
MLAlgorithm&& model = base.Train(GetTrainingSubset(xs, i),
|
||||
GetTrainingSubset(ys, i), args...);
|
||||
evaluations(i) = Metric::Evaluate(model, GetValidationSubset(xs, i),
|
||||
GetValidationSubset(ys, i));
|
||||
if (std::isnan(evaluations(i)) || std::isinf(evaluations(i)))
|
||||
{
|
||||
++numInvalidScores;
|
||||
Log::Warn << "KFoldCV::TrainAndEvaluate(): fold " << i << " returned "
|
||||
<< "a score of " << evaluations(i) << "; ignoring when computing "
|
||||
<< "the average score." << std::endl;
|
||||
}
|
||||
if (i == k - 1)
|
||||
modelPtr.reset(new MLAlgorithm(std::move(model)));
|
||||
}
|
||||
|
||||
return arma::mean(evaluations);
|
||||
if (numInvalidScores == k)
|
||||
{
|
||||
Log::Warn << "KFoldCV::TrainAndEvaluate(): all folds returned invalid "
|
||||
<< "scores! Returning 0.0 as overall score." << std::endl;
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
return arma::mean(evaluations.elem(arma::find_finite(evaluations)));
|
||||
}
|
||||
|
||||
template<typename MLAlgorithm,
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
set(SOURCES
|
||||
dataset_mapper.hpp
|
||||
dataset_mapper_impl.hpp
|
||||
detect_file_type.hpp
|
||||
detect_file_type.cpp
|
||||
extension.hpp
|
||||
format.hpp
|
||||
has_serialize.hpp
|
||||
|
||||
@@ -0,0 +1,289 @@
|
||||
/**
|
||||
* @file core/data/detect_file_type.cpp
|
||||
* @author Conrad Sanderson
|
||||
* @author Ryan Curtin
|
||||
*
|
||||
* Functionality to guess the type of a file by inspecting it. Parts of the
|
||||
* implementation are adapted from the Armadillo sources and relicensed to be a
|
||||
* part of mlpack with permission from Conrad.
|
||||
*
|
||||
* mlpack is free software; you may redistribute it and/or modify it under the
|
||||
* terms of the 3-clause BSD license. You should have received a copy of the
|
||||
* 3-clause BSD license along with mlpack. If not, see
|
||||
* http://www.opensource.org/licenses/BSD-3-Clause for more information.
|
||||
*/
|
||||
#include "extension.hpp"
|
||||
#include "detect_file_type.hpp"
|
||||
|
||||
#include <boost/algorithm/string/trim.hpp>
|
||||
#include <boost/tokenizer.hpp>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
||||
namespace mlpack {
|
||||
namespace data {
|
||||
|
||||
/**
|
||||
* Given a file type, return a logical name corresponding to that file type.
|
||||
*
|
||||
* @param type Type to get the logical name of.
|
||||
*/
|
||||
std::string GetStringType(const arma::file_type& type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case arma::csv_ascii: return "CSV data";
|
||||
case arma::raw_ascii: return "raw ASCII formatted data";
|
||||
case arma::raw_binary: return "raw binary formatted data";
|
||||
case arma::arma_ascii: return "Armadillo ASCII formatted data";
|
||||
case arma::arma_binary: return "Armadillo binary formatted data";
|
||||
case arma::pgm_binary: return "PGM data";
|
||||
case arma::hdf5_binary: return "HDF5 data";
|
||||
default: return "";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an istream, attempt to guess the file type. This is taken originally
|
||||
* from Armadillo's function guess_file_type_internal(), but we avoid using
|
||||
* internal Armadillo functionality.
|
||||
*
|
||||
* @param f Opened istream to look into to guess the file type.
|
||||
*/
|
||||
arma::file_type GuessFileType(std::istream& f)
|
||||
{
|
||||
f.clear();
|
||||
const std::fstream::pos_type pos1 = f.tellg();
|
||||
|
||||
f.clear();
|
||||
f.seekg(0, std::ios::end);
|
||||
|
||||
f.clear();
|
||||
// Get the length of the stream.
|
||||
const std::fstream::pos_type pos2 = f.tellg();
|
||||
|
||||
// Compute length of the stream.
|
||||
const arma::uword nMax = ((pos1 >= 0) && (pos2 >= 0) && (pos2 > pos1)) ?
|
||||
arma::uword(pos2 - pos1) : arma::uword(0);
|
||||
|
||||
f.clear();
|
||||
f.seekg(pos1);
|
||||
|
||||
// Handle empty files.
|
||||
if (nMax == 0)
|
||||
return arma::file_type_unknown;
|
||||
|
||||
const arma::uword nUse = std::min(nMax, arma::uword(4096));
|
||||
|
||||
unsigned char* dataMem = new unsigned char[nUse];
|
||||
memset(dataMem, 0, nUse);
|
||||
|
||||
f.clear();
|
||||
f.read(reinterpret_cast<char*>(dataMem), std::streamsize(nUse));
|
||||
|
||||
const bool loadOkay = f.good();
|
||||
|
||||
f.clear();
|
||||
f.seekg(pos1);
|
||||
|
||||
if (!loadOkay)
|
||||
{
|
||||
delete[] dataMem;
|
||||
return arma::file_type_unknown;
|
||||
}
|
||||
|
||||
bool hasBinary = false;
|
||||
bool hasBracket = false;
|
||||
bool hasComma = false;
|
||||
|
||||
for (arma::uword i = 0; i < nUse; ++i)
|
||||
{
|
||||
const unsigned char val = dataMem[i];
|
||||
if ((val <= 8) || (val >= 123))
|
||||
{
|
||||
hasBinary = true;
|
||||
break;
|
||||
} // The range checking can be made more elaborate.
|
||||
|
||||
if ((val == '(') || (val == ')'))
|
||||
{
|
||||
hasBracket = true;
|
||||
}
|
||||
if (val == ',')
|
||||
{
|
||||
hasComma = true;
|
||||
}
|
||||
}
|
||||
|
||||
delete[] dataMem;
|
||||
|
||||
if (hasBinary)
|
||||
return arma::raw_binary;
|
||||
|
||||
if (hasComma && (hasBracket == false))
|
||||
return arma::csv_ascii;
|
||||
|
||||
return arma::raw_ascii;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to auto-detect the type of a file given its extension, and by
|
||||
* inspecting the parts of the file to disambiguate between types when
|
||||
* necessary. (For instance, a .csv file could be delimited by spaces, commas,
|
||||
* or tabs.) This is meant to be used during loading.
|
||||
*
|
||||
* @param stream Opened file stream to look into for autodetection.
|
||||
* @param filename Name of the file.
|
||||
* @return The detected file type.
|
||||
*/
|
||||
arma::file_type AutoDetect(std::fstream& stream,
|
||||
const std::string& filename)
|
||||
{
|
||||
// Get the extension.
|
||||
std::string extension = Extension(filename);
|
||||
arma::file_type detectedLoadType = arma::file_type_unknown;
|
||||
|
||||
if (extension == "csv" || extension == "tsv")
|
||||
{
|
||||
detectedLoadType = GuessFileType(stream);
|
||||
if (detectedLoadType == arma::csv_ascii)
|
||||
{
|
||||
if (extension == "tsv")
|
||||
Log::Warn << "'" << filename << "' is comma-separated, not "
|
||||
"tab-separated!" << std::endl;
|
||||
}
|
||||
else if (detectedLoadType == arma::raw_ascii) // .csv file can be tsv.
|
||||
{
|
||||
if (extension == "csv")
|
||||
{
|
||||
// We should issue a warning, but we don't want to issue the warning if
|
||||
// there is only one column in the CSV (since there will be no commas
|
||||
// anyway, and it will be detected as arma::raw_ascii).
|
||||
const std::streampos pos = stream.tellg();
|
||||
std::string line;
|
||||
std::getline(stream, line, '\n');
|
||||
boost::trim(line);
|
||||
|
||||
// Reset stream position.
|
||||
stream.seekg(pos);
|
||||
|
||||
// If there are no spaces or whitespace in the line, then we shouldn't
|
||||
// print the warning.
|
||||
if ((line.find(' ') != std::string::npos) ||
|
||||
(line.find('\t') != std::string::npos))
|
||||
{
|
||||
Log::Warn << "'" << filename << "' is not a standard csv file."
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
detectedLoadType = arma::file_type_unknown;
|
||||
}
|
||||
}
|
||||
else if (extension == "txt")
|
||||
{
|
||||
// This could be raw ASCII or Armadillo ASCII (ASCII with size header).
|
||||
// We'll let Armadillo do its guessing (although we have to check if it is
|
||||
// arma_ascii ourselves) and see what we come up with.
|
||||
|
||||
// This is adapted from load_auto_detect() in diskio_meat.hpp.
|
||||
const std::string ARMA_MAT_TXT = "ARMA_MAT_TXT";
|
||||
std::string rawHeader(ARMA_MAT_TXT.length(), '\0');
|
||||
std::streampos pos = stream.tellg();
|
||||
|
||||
stream.read(&rawHeader[0], std::streamsize(ARMA_MAT_TXT.length()));
|
||||
stream.clear();
|
||||
stream.seekg(pos); // Reset stream position after peeking.
|
||||
|
||||
if (rawHeader == ARMA_MAT_TXT)
|
||||
{
|
||||
detectedLoadType = arma::arma_ascii;
|
||||
}
|
||||
else // It's not arma_ascii. Now we let Armadillo guess.
|
||||
{
|
||||
detectedLoadType = GuessFileType(stream);
|
||||
|
||||
if (detectedLoadType != arma::raw_ascii &&
|
||||
detectedLoadType != arma::csv_ascii)
|
||||
detectedLoadType = arma::file_type_unknown;
|
||||
}
|
||||
}
|
||||
else if (extension == "bin")
|
||||
{
|
||||
// This could be raw binary or Armadillo binary (binary with header). We
|
||||
// will check to see if it is Armadillo binary.
|
||||
const std::string ARMA_MAT_BIN = "ARMA_MAT_BIN";
|
||||
std::string rawHeader(ARMA_MAT_BIN.length(), '\0');
|
||||
|
||||
std::streampos pos = stream.tellg();
|
||||
|
||||
stream.read(&rawHeader[0], std::streamsize(ARMA_MAT_BIN.length()));
|
||||
stream.clear();
|
||||
stream.seekg(pos); // Reset stream position after peeking.
|
||||
|
||||
if (rawHeader == ARMA_MAT_BIN)
|
||||
{
|
||||
detectedLoadType = arma::arma_binary;
|
||||
}
|
||||
else // We can only assume it's raw binary.
|
||||
{
|
||||
detectedLoadType = arma::raw_binary;
|
||||
}
|
||||
}
|
||||
else if (extension == "pgm")
|
||||
{
|
||||
detectedLoadType = arma::pgm_binary;
|
||||
}
|
||||
else if (extension == "h5" || extension == "hdf5" || extension == "hdf" ||
|
||||
extension == "he5")
|
||||
{
|
||||
detectedLoadType = arma::hdf5_binary;
|
||||
}
|
||||
else // Unknown extension...
|
||||
{
|
||||
detectedLoadType = arma::file_type_unknown;
|
||||
}
|
||||
|
||||
return detectedLoadType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the type based only on the extension.
|
||||
*
|
||||
* @param filename Name of the file whose type we should detect.
|
||||
* @return Detected type of file.
|
||||
*/
|
||||
arma::file_type DetectFromExtension(const std::string& filename)
|
||||
{
|
||||
const std::string extension = Extension(filename);
|
||||
|
||||
if (extension == "csv")
|
||||
{
|
||||
return arma::csv_ascii;
|
||||
}
|
||||
else if (extension == "txt")
|
||||
{
|
||||
return arma::raw_ascii;
|
||||
}
|
||||
else if (extension == "bin")
|
||||
{
|
||||
return arma::arma_binary;
|
||||
}
|
||||
else if (extension == "pgm")
|
||||
{
|
||||
return arma::pgm_binary;
|
||||
}
|
||||
else if (extension == "h5" || extension == "hdf5" || extension == "hdf" ||
|
||||
extension == "he5")
|
||||
{
|
||||
return arma::hdf5_binary;
|
||||
}
|
||||
else
|
||||
{
|
||||
return arma::file_type_unknown;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace data
|
||||
} // namespace mlpack
|
||||
@@ -0,0 +1,61 @@
|
||||
/**
|
||||
* @file core/data/detect_file_type.hpp
|
||||
* @author Conrad Sanderson
|
||||
* @author Ryan Curtin
|
||||
*
|
||||
* Functionality to guess the type of a file by inspecting it. Parts of the
|
||||
* implementation are adapted from the Armadillo sources and relicensed to be a
|
||||
* part of mlpack with permission from Conrad.
|
||||
*
|
||||
* 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_CORE_DATA_DETECT_FILE_TYPE_HPP
|
||||
#define MLPACK_CORE_DATA_DETECT_FILE_TYPE_HPP
|
||||
|
||||
namespace mlpack {
|
||||
namespace data {
|
||||
|
||||
/**
|
||||
* Given a file type, return a logical name corresponding to that file type.
|
||||
*
|
||||
* @param type Type to get the logical name of.
|
||||
*/
|
||||
std::string GetStringType(const arma::file_type& type);
|
||||
|
||||
/**
|
||||
* Given an istream, attempt to guess the file type. This is taken originally
|
||||
* from Armadillo's function guess_file_type_internal(), but we avoid using
|
||||
* internal Armadillo functionality.
|
||||
*
|
||||
* @param f Opened istream to look into to guess the file type.
|
||||
*/
|
||||
arma::file_type GuessFileType(std::istream& f);
|
||||
|
||||
/**
|
||||
* Attempt to auto-detect the type of a file given its extension, and by
|
||||
* inspecting the parts of the file to disambiguate between types when
|
||||
* necessary. (For instance, a .csv file could be delimited by spaces, commas,
|
||||
* or tabs.) This is meant to be used during loading.
|
||||
*
|
||||
* @param stream Opened file stream to look into for autodetection.
|
||||
* @param filename Name of the file.
|
||||
* @return The detected file type. arma::file_type_unknown if unknown.
|
||||
*/
|
||||
arma::file_type AutoDetect(std::fstream& stream,
|
||||
const std::string& filename);
|
||||
|
||||
/**
|
||||
* Return the type based only on the extension.
|
||||
*
|
||||
* @param filename Name of the file whose type we should detect.
|
||||
* @return Detected type of file. arma::file_type_unknown if unknown.
|
||||
*/
|
||||
arma::file_type DetectFromExtension(const std::string& filename);
|
||||
|
||||
} // namespace data
|
||||
} // namespace mlpack
|
||||
|
||||
#endif
|
||||
@@ -18,32 +18,38 @@ namespace data /** Functions to load and save matrices and models. */ {
|
||||
template bool Load<int>(const std::string&,
|
||||
arma::Mat<int>&,
|
||||
const bool,
|
||||
const bool);
|
||||
const bool,
|
||||
const arma::file_type);
|
||||
|
||||
template bool Load<unsigned int>(const std::string&,
|
||||
arma::Mat<unsigned int>&,
|
||||
const bool,
|
||||
const bool);
|
||||
const bool,
|
||||
const arma::file_type);
|
||||
|
||||
template bool Load<unsigned long>(const std::string&,
|
||||
arma::Mat<unsigned long>&,
|
||||
const bool,
|
||||
const bool);
|
||||
const bool,
|
||||
const arma::file_type);
|
||||
|
||||
template bool Load<unsigned long long>(const std::string&,
|
||||
arma::Mat<unsigned long long>&,
|
||||
const bool,
|
||||
const bool);
|
||||
const bool,
|
||||
const arma::file_type);
|
||||
|
||||
template bool Load<float>(const std::string&,
|
||||
arma::Mat<float>&,
|
||||
const bool,
|
||||
const bool);
|
||||
const bool,
|
||||
const arma::file_type);
|
||||
|
||||
template bool Load<double>(const std::string&,
|
||||
arma::Mat<double>&,
|
||||
const bool,
|
||||
const bool);
|
||||
const bool,
|
||||
const arma::file_type);
|
||||
|
||||
template bool Load<int>(const std::string&,
|
||||
arma::SpMat<int>&,
|
||||
|
||||
@@ -28,23 +28,25 @@ namespace data /** Functions to load and save matrices and models. */ {
|
||||
/**
|
||||
* Loads a matrix from file, guessing the filetype from the extension. This
|
||||
* will transpose the matrix at load time (unless the transpose parameter is set
|
||||
* to false). If the filetype cannot be determined, an error will be given.
|
||||
* to false).
|
||||
*
|
||||
* The supported types of files are the same as found in Armadillo:
|
||||
*
|
||||
* - CSV (csv_ascii), denoted by .csv, or optionally .txt
|
||||
* - TSV (raw_ascii), denoted by .tsv, .csv, or .txt
|
||||
* - ASCII (raw_ascii), denoted by .json
|
||||
* - Armadillo ASCII (arma_ascii), also denoted by .txt
|
||||
* - PGM (pgm_binary), denoted by .pgm
|
||||
* - PPM (ppm_binary), denoted by .ppm
|
||||
* - Raw binary (raw_binary), denoted by .bin
|
||||
* - Armadillo binary (arma_binary), denoted by .bin
|
||||
* - HDF5, denoted by .hdf, .hdf5, .h5, or .he5
|
||||
* - CSV (arma::csv_ascii), denoted by .csv, or optionally .txt
|
||||
* - TSV (arma::raw_ascii), denoted by .tsv, .csv, or .txt
|
||||
* - ASCII (arma::raw_ascii), denoted by .json
|
||||
* - Armadillo ASCII (arma::arma_ascii), also denoted by .txt
|
||||
* - PGM (arma::pgm_binary), denoted by .pgm
|
||||
* - PPM (arma::ppm_binary), denoted by .ppm
|
||||
* - Raw binary (arma::raw_binary), denoted by .bin
|
||||
* - Armadillo binary (arma::arma_binary), denoted by .bin
|
||||
* - HDF5 (arma::hdf5_binary), denoted by .hdf, .hdf5, .h5, or .he5
|
||||
*
|
||||
* If the file extension is not one of those types, an error will be given.
|
||||
* This is preferable to Armadillo's default behavior of loading an unknown
|
||||
* filetype as raw_binary, which can have very confusing effects.
|
||||
* By default, this function will try to automatically determine the type of
|
||||
* file to load based on its extension and by inspecting the file. If you know
|
||||
* the file type and want to specify it manually, override the default
|
||||
* `inputLoadType` parameter with the correct type above (e.g.
|
||||
* `arma::csv_ascii`.)
|
||||
*
|
||||
* If the parameter 'fatal' is set to true, a std::runtime_error exception will
|
||||
* be thrown if the matrix does not load successfully. The parameter
|
||||
@@ -57,13 +59,15 @@ namespace data /** Functions to load and save matrices and models. */ {
|
||||
* @param matrix Matrix to load contents of file into.
|
||||
* @param fatal If an error should be reported as fatal (default false).
|
||||
* @param transpose If true, transpose the matrix after loading (default true).
|
||||
* @param inputLoadType Used to determine the type of file to load (default arma::auto_detect).
|
||||
* @return Boolean value indicating success or failure of load.
|
||||
*/
|
||||
template<typename eT>
|
||||
bool Load(const std::string& filename,
|
||||
arma::Mat<eT>& matrix,
|
||||
const bool fatal = false,
|
||||
const bool transpose = true);
|
||||
const bool transpose = true,
|
||||
const arma::file_type inputLoadType = arma::auto_detect);
|
||||
|
||||
/**
|
||||
* Loads a sparse matrix from file, using arma::coord_ascii format. This
|
||||
@@ -110,38 +114,45 @@ bool Load(const std::string& filename,
|
||||
extern template bool Load<int>(const std::string&,
|
||||
arma::Mat<int>&,
|
||||
const bool,
|
||||
const bool);
|
||||
const bool,
|
||||
const arma::file_type);
|
||||
|
||||
// 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);
|
||||
const bool,
|
||||
const arma::file_type);
|
||||
|
||||
extern template bool Load<unsigned long>(const std::string&,
|
||||
arma::Mat<unsigned long>&,
|
||||
const bool,
|
||||
const bool);
|
||||
const bool,
|
||||
const arma::file_type);
|
||||
|
||||
extern template bool Load<unsigned long long>(const std::string&,
|
||||
arma::Mat<unsigned long long>&,
|
||||
const bool,
|
||||
const bool);
|
||||
const bool,
|
||||
const arma::file_type);
|
||||
|
||||
extern template bool Load<float>(const std::string&,
|
||||
arma::Mat<float>&,
|
||||
const bool,
|
||||
const bool);
|
||||
const bool,
|
||||
const arma::file_type);
|
||||
|
||||
extern template bool Load<double>(const std::string&,
|
||||
arma::Mat<double>&,
|
||||
const bool,
|
||||
const bool);
|
||||
const bool,
|
||||
const arma::file_type);
|
||||
|
||||
extern template bool Load<int>(const std::string&,
|
||||
arma::Mat<int>&,
|
||||
const bool,
|
||||
const bool);
|
||||
const bool,
|
||||
const arma::file_type);
|
||||
|
||||
extern template bool Load<unsigned int>(const std::string&,
|
||||
arma::SpMat<unsigned int>&,
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "load_csv.hpp"
|
||||
#include "load.hpp"
|
||||
#include "extension.hpp"
|
||||
#include "detect_file_type.hpp"
|
||||
|
||||
#include <boost/algorithm/string/trim.hpp>
|
||||
#include <boost/tokenizer.hpp>
|
||||
@@ -88,13 +89,11 @@ template<typename eT>
|
||||
bool Load(const std::string& filename,
|
||||
arma::Mat<eT>& matrix,
|
||||
const bool fatal,
|
||||
const bool transpose)
|
||||
const bool transpose,
|
||||
const arma::file_type inputLoadType)
|
||||
{
|
||||
Timer::Start("loading_data");
|
||||
|
||||
// Get the extension.
|
||||
std::string extension = Extension(filename);
|
||||
|
||||
// Catch nonexistent files by opening the stream ourselves.
|
||||
std::fstream stream;
|
||||
#ifdef _WIN32 // Always open in binary mode on Windows.
|
||||
@@ -114,129 +113,33 @@ bool Load(const std::string& filename,
|
||||
return false;
|
||||
}
|
||||
|
||||
bool unknownType = false;
|
||||
arma::file_type loadType;
|
||||
arma::file_type loadType = inputLoadType;
|
||||
std::string stringType;
|
||||
|
||||
if (extension == "csv" || extension == "tsv")
|
||||
if (inputLoadType == arma::auto_detect)
|
||||
{
|
||||
#if (ARMA_VERSION_MAJOR == 9 && ARMA_VERSION_MINOR >= 800)
|
||||
loadType = arma::diskio::guess_file_type_internal(stream);
|
||||
#else
|
||||
loadType = arma::diskio::guess_file_type(stream);
|
||||
#endif
|
||||
if (loadType == arma::csv_ascii)
|
||||
// Attempt to auto-detect the type from the given file.
|
||||
loadType = AutoDetect(stream, filename);
|
||||
// Provide error if we don't know the type.
|
||||
if (loadType == arma::file_type_unknown)
|
||||
{
|
||||
if (extension == "tsv")
|
||||
Log::Warn << "'" << filename << "' is comma-separated, not "
|
||||
"tab-separated!" << std::endl;
|
||||
stringType = "CSV data";
|
||||
}
|
||||
else if (loadType == arma::raw_ascii) // .csv file can be tsv.
|
||||
{
|
||||
if (extension == "csv")
|
||||
{
|
||||
// We should issue a warning, but we don't want to issue the warning if
|
||||
// there is only one column in the CSV (since there will be no commas
|
||||
// anyway, and it will be detected as arma::raw_ascii).
|
||||
const std::streampos pos = stream.tellg();
|
||||
std::string line;
|
||||
std::getline(stream, line, '\n');
|
||||
boost::trim(line);
|
||||
Timer::Stop("loading_data");
|
||||
if (fatal)
|
||||
Log::Fatal << "Unable to detect type of '" << filename << "'; "
|
||||
<< "incorrect extension?" << std::endl;
|
||||
else
|
||||
Log::Warn << "Unable to detect type of '" << filename << "'; load "
|
||||
<< " failed. Incorrect extension?" << std::endl;
|
||||
|
||||
// Reset stream position.
|
||||
stream.seekg(pos);
|
||||
|
||||
// If there are no spaces or whitespace in the line, then we shouldn't
|
||||
// print the warning.
|
||||
if ((line.find(' ') != std::string::npos) ||
|
||||
(line.find('\t') != std::string::npos))
|
||||
{
|
||||
Log::Warn << "'" << filename << "' is not a standard csv file."
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
stringType = "raw ASCII formatted data";
|
||||
}
|
||||
else
|
||||
{
|
||||
unknownType = true;
|
||||
loadType = arma::raw_binary; // Won't be used; prevent a warning.
|
||||
stringType = "";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (extension == "txt")
|
||||
|
||||
stringType = GetStringType(loadType);
|
||||
|
||||
#ifndef ARMA_USE_HDF5
|
||||
if (inputLoadType == arma::hdf5_binary)
|
||||
{
|
||||
// This could be raw ASCII or Armadillo ASCII (ASCII with size header).
|
||||
// We'll let Armadillo do its guessing (although we have to check if it is
|
||||
// arma_ascii ourselves) and see what we come up with.
|
||||
|
||||
// This is taken from load_auto_detect() in diskio_meat.hpp
|
||||
const std::string ARMA_MAT_TXT = "ARMA_MAT_TXT";
|
||||
// char* rawHeader = new char[ARMA_MAT_TXT.length() + 1];
|
||||
std::string rawHeader(ARMA_MAT_TXT.length(), '\0');
|
||||
std::streampos pos = stream.tellg();
|
||||
|
||||
stream.read(&rawHeader[0], std::streamsize(ARMA_MAT_TXT.length()));
|
||||
stream.clear();
|
||||
stream.seekg(pos); // Reset stream position after peeking.
|
||||
|
||||
if (rawHeader == ARMA_MAT_TXT)
|
||||
{
|
||||
loadType = arma::arma_ascii;
|
||||
stringType = "Armadillo ASCII formatted data";
|
||||
}
|
||||
else // It's not arma_ascii. Now we let Armadillo guess.
|
||||
{
|
||||
#if (ARMA_VERSION_MAJOR == 9 && ARMA_VERSION_MINOR >= 800)
|
||||
loadType = arma::diskio::guess_file_type_internal(stream);
|
||||
#else
|
||||
loadType = arma::diskio::guess_file_type(stream);
|
||||
#endif
|
||||
if (loadType == arma::raw_ascii) // Raw ASCII (space-separated).
|
||||
stringType = "raw ASCII formatted data";
|
||||
else if (loadType == arma::csv_ascii) // CSV can be .txt too.
|
||||
stringType = "CSV data";
|
||||
else // Unknown .txt... we will throw an error.
|
||||
unknownType = true;
|
||||
}
|
||||
}
|
||||
else if (extension == "bin")
|
||||
{
|
||||
// This could be raw binary or Armadillo binary (binary with header). We
|
||||
// will check to see if it is Armadillo binary.
|
||||
const std::string ARMA_MAT_BIN = "ARMA_MAT_BIN";
|
||||
std::string rawHeader(ARMA_MAT_BIN.length(), '\0');
|
||||
|
||||
std::streampos pos = stream.tellg();
|
||||
|
||||
stream.read(&rawHeader[0], std::streamsize(ARMA_MAT_BIN.length()));
|
||||
stream.clear();
|
||||
stream.seekg(pos); // Reset stream position after peeking.
|
||||
|
||||
if (rawHeader == ARMA_MAT_BIN)
|
||||
{
|
||||
stringType = "Armadillo binary formatted data";
|
||||
loadType = arma::arma_binary;
|
||||
}
|
||||
else // We can only assume it's raw binary.
|
||||
{
|
||||
stringType = "raw binary formatted data";
|
||||
loadType = arma::raw_binary;
|
||||
}
|
||||
}
|
||||
else if (extension == "pgm")
|
||||
{
|
||||
loadType = arma::pgm_binary;
|
||||
stringType = "PGM data";
|
||||
}
|
||||
else if (extension == "h5" || extension == "hdf5" || extension == "hdf" ||
|
||||
extension == "he5")
|
||||
{
|
||||
#ifdef ARMA_USE_HDF5
|
||||
loadType = arma::hdf5_binary;
|
||||
stringType = "HDF5 data";
|
||||
#else
|
||||
// Ensure that HDF5 is supported.
|
||||
Timer::Stop("loading_data");
|
||||
if (fatal)
|
||||
Log::Fatal << "Attempted to load '" << filename << "' as HDF5 data, but "
|
||||
@@ -248,28 +151,8 @@ bool Load(const std::string& filename,
|
||||
<< std::endl;
|
||||
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else // Unknown extension...
|
||||
{
|
||||
unknownType = true;
|
||||
loadType = arma::raw_binary; // Won't be used; prevent a warning.
|
||||
stringType = "";
|
||||
}
|
||||
|
||||
// Provide error if we don't know the type.
|
||||
if (unknownType)
|
||||
{
|
||||
Timer::Stop("loading_data");
|
||||
if (fatal)
|
||||
Log::Fatal << "Unable to detect type of '" << filename << "'; "
|
||||
<< "incorrect extension?" << std::endl;
|
||||
else
|
||||
Log::Warn << "Unable to detect type of '" << filename << "'; load failed."
|
||||
<< " Incorrect extension?" << std::endl;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Try to load the file; but if it's raw_binary, it could be a problem.
|
||||
if (loadType == arma::raw_binary)
|
||||
|
||||
@@ -31,33 +31,40 @@ namespace data /** Functions to load and save matrices. */ {
|
||||
*
|
||||
* The supported types of files are the same as found in Armadillo:
|
||||
*
|
||||
* - CSV (csv_ascii), denoted by .csv, or optionally .txt
|
||||
* - ASCII (raw_ascii), denoted by .json
|
||||
* - Armadillo ASCII (arma_ascii), also denoted by .txt
|
||||
* - PGM (pgm_binary), denoted by .pgm
|
||||
* - PPM (ppm_binary), denoted by .ppm
|
||||
* - Raw binary (raw_binary), denoted by .bin
|
||||
* - Armadillo binary (arma_binary), denoted by .bin
|
||||
* - HDF5 (hdf5_binary), denoted by .hdf5, .hdf, .h5, or .he5
|
||||
* - CSV (arma::csv_ascii), denoted by .csv, or optionally .txt
|
||||
* - ASCII (arma::raw_ascii), denoted by .json
|
||||
* - Armadillo ASCII (arma::arma_ascii), also denoted by .txt
|
||||
* - PGM (arma::pgm_binary), denoted by .pgm
|
||||
* - PPM (arma::ppm_binary), denoted by .ppm
|
||||
* - Raw binary (arma::raw_binary), denoted by .bin
|
||||
* - Armadillo binary (arma::arma_binary), denoted by .bin
|
||||
* - HDF5 (arma::hdf5_binary), denoted by .hdf5, .hdf, .h5, or .he5
|
||||
*
|
||||
* If the file extension is not one of those types, an error will be given. If
|
||||
* the 'fatal' parameter is set to true, a std::runtime_error exception will be
|
||||
* thrown upon failure. If the 'transpose' parameter is set to true, the matrix
|
||||
* will be transposed before saving. Generally, because mlpack stores matrices
|
||||
* in a column-major format and most datasets are stored on disk as row-major,
|
||||
* this parameter should be left at its default value of 'true'.
|
||||
* By default, this function will try to automatically determine the format to
|
||||
* save with based only on the filename's extension. If you would prefer to
|
||||
* specify a file type manually, override the default
|
||||
* `inputSaveType` parameter with the correct type above (e.g.
|
||||
* `arma::csv_ascii`.)
|
||||
*
|
||||
* If the 'fatal' parameter is set to true, a std::runtime_error exception will
|
||||
* be thrown upon failure. If the 'transpose' parameter is set to true, the
|
||||
* matrix will be transposed before saving. Generally, because mlpack stores
|
||||
* matrices in a column-major format and most datasets are stored on disk as
|
||||
* row-major, this parameter should be left at its default value of 'true'.
|
||||
*
|
||||
* @param filename Name of file to save to.
|
||||
* @param matrix Matrix to save into file.
|
||||
* @param fatal If an error should be reported as fatal (default false).
|
||||
* @param transpose If true, transpose the matrix before saving (default true).
|
||||
* @param inputSaveType File type to save to (defaults to arma::auto_detect).
|
||||
* @return Boolean value indicating success or failure of save.
|
||||
*/
|
||||
template<typename eT>
|
||||
bool Save(const std::string& filename,
|
||||
const arma::Mat<eT>& matrix,
|
||||
const bool fatal = false,
|
||||
bool transpose = true);
|
||||
bool transpose = true,
|
||||
arma::file_type inputSaveType = arma::auto_detect);
|
||||
|
||||
/**
|
||||
* Saves a sparse matrix to file, guessing the filetype from the
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
// In case it hasn't already been included.
|
||||
#include "save.hpp"
|
||||
#include "extension.hpp"
|
||||
#include "detect_file_type.hpp"
|
||||
|
||||
#include <cereal/archives/xml.hpp>
|
||||
#include <cereal/archives/json.hpp>
|
||||
@@ -26,43 +27,53 @@ namespace data {
|
||||
template<typename eT>
|
||||
bool Save(const std::string& filename,
|
||||
const arma::Col<eT>& vec,
|
||||
const bool fatal)
|
||||
const bool fatal,
|
||||
arma::file_type inputSaveType)
|
||||
{
|
||||
// Don't transpose: one observation per line (for CSVs at least).
|
||||
return Save(filename, vec, fatal, false);
|
||||
return Save(filename, vec, fatal, false, inputSaveType);
|
||||
}
|
||||
|
||||
template<typename eT>
|
||||
bool Save(const std::string& filename,
|
||||
const arma::Row<eT>& rowvec,
|
||||
const bool fatal)
|
||||
const bool fatal,
|
||||
arma::file_type inputSaveType)
|
||||
{
|
||||
return Save(filename, rowvec, fatal, true);
|
||||
return Save(filename, rowvec, fatal, true, inputSaveType);
|
||||
}
|
||||
|
||||
template<typename eT>
|
||||
bool Save(const std::string& filename,
|
||||
const arma::Mat<eT>& matrix,
|
||||
const bool fatal,
|
||||
bool transpose)
|
||||
bool transpose,
|
||||
arma::file_type inputSaveType)
|
||||
{
|
||||
Timer::Start("saving_data");
|
||||
|
||||
// First we will try to discriminate by file extension.
|
||||
std::string extension = Extension(filename);
|
||||
if (extension == "")
|
||||
{
|
||||
Timer::Stop("saving_data");
|
||||
if (fatal)
|
||||
Log::Fatal << "No extension given with filename '" << filename << "'; "
|
||||
<< "type unknown. Save failed." << std::endl;
|
||||
else
|
||||
Log::Warn << "No extension given with filename '" << filename << "'; "
|
||||
<< "type unknown. Save failed." << std::endl;
|
||||
arma::file_type saveType = inputSaveType;
|
||||
std::string stringType = "";
|
||||
|
||||
return false;
|
||||
if (inputSaveType == arma::auto_detect)
|
||||
{
|
||||
// Detect the file type using only the extension.
|
||||
saveType = DetectFromExtension(filename);
|
||||
if (saveType == arma::file_type_unknown)
|
||||
{
|
||||
if (fatal)
|
||||
Log::Fatal << "Could not detect type of file '" << filename << "' for "
|
||||
<< "writing. Save failed." << std::endl;
|
||||
else
|
||||
Log::Warn << "Could not detect type of file '" << filename << "' for "
|
||||
<< "writing. Save failed." << std::endl;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
stringType = GetStringType(saveType);
|
||||
|
||||
// Catch errors opening the file.
|
||||
std::fstream stream;
|
||||
#ifdef _WIN32 // Always open in binary mode on Windows.
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
// The version of mlpack. If this is a git repository, this will be a version
|
||||
// with higher number than the most recent release.
|
||||
#define MLPACK_VERSION_MAJOR 3
|
||||
#define MLPACK_VERSION_MINOR 2
|
||||
#define MLPACK_VERSION_PATCH 3
|
||||
#define MLPACK_VERSION_MINOR 4
|
||||
#define MLPACK_VERSION_PATCH 2
|
||||
|
||||
// The name of the version (for use by --version).
|
||||
namespace mlpack {
|
||||
|
||||
@@ -5,6 +5,11 @@
|
||||
* Definition of the BayesianRidge class, which performs the
|
||||
* bayesian linear regression. According to the armadillo standards,
|
||||
* all the functions consider data in column-major format.
|
||||
*
|
||||
* 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_BAYESIAN_LINEAR_REGRESSION_HPP
|
||||
|
||||
@@ -16,7 +16,6 @@ add_executable(mlpack_test
|
||||
emst_test.cpp
|
||||
fastmks_test.cpp
|
||||
facilities_test.cpp
|
||||
feedforward_network_test.cpp
|
||||
gan_test.cpp
|
||||
gmm_test.cpp
|
||||
hmm_test.cpp
|
||||
@@ -25,7 +24,6 @@ add_executable(mlpack_test
|
||||
hyperplane_test.cpp
|
||||
init_rules_test.cpp
|
||||
kde_test.cpp
|
||||
kmeans_test.cpp
|
||||
krann_search_test.cpp
|
||||
ksinit_test.cpp
|
||||
lars_test.cpp
|
||||
@@ -59,9 +57,7 @@ add_executable(mlpack_test
|
||||
random_forest_test.cpp
|
||||
random_test.cpp
|
||||
range_search_test.cpp
|
||||
rbm_network_test.cpp
|
||||
rectangle_tree_test.cpp
|
||||
recurrent_network_test.cpp
|
||||
reward_clipping_test.cpp
|
||||
rl_components_test.cpp
|
||||
serialization.cpp
|
||||
@@ -97,7 +93,6 @@ add_executable(mlpack_test
|
||||
main_tests/hmm_viterbi_test.cpp
|
||||
main_tests/hoeffding_tree_test.cpp
|
||||
main_tests/kde_test.cpp
|
||||
main_tests/kmeans_test.cpp
|
||||
main_tests/krann_test.cpp
|
||||
main_tests/linear_svm_test.cpp
|
||||
main_tests/lmnn_test.cpp
|
||||
@@ -135,12 +130,14 @@ add_executable(mlpack_catch_test
|
||||
cv_test.cpp
|
||||
decision_stump_test.cpp
|
||||
decision_tree_test.cpp
|
||||
feedforward_network_test.cpp
|
||||
image_load_test.cpp
|
||||
imputation_test.cpp
|
||||
kernel_pca_test.cpp
|
||||
kernel_test.cpp
|
||||
kernel_traits_test.cpp
|
||||
kfn_test.cpp
|
||||
kmeans_test.cpp
|
||||
knn_test.cpp
|
||||
linear_regression_test.cpp
|
||||
load_save_test.cpp
|
||||
@@ -149,6 +146,8 @@ add_executable(mlpack_catch_test
|
||||
one_hot_encoding_test.cpp
|
||||
quic_svd_test.cpp
|
||||
randomized_svd_test.cpp
|
||||
rbm_network_test.cpp
|
||||
recurrent_network_test.cpp
|
||||
regularized_svd_test.cpp
|
||||
scaling_test.cpp
|
||||
serialization_catch.cpp
|
||||
@@ -169,6 +168,7 @@ add_executable(mlpack_catch_test
|
||||
main_tests/image_converter_test.cpp
|
||||
main_tests/kernel_pca_test.cpp
|
||||
main_tests/kfn_test.cpp
|
||||
main_tests/kmeans_test.cpp
|
||||
main_tests/knn_test.cpp
|
||||
main_tests/linear_regression_test.cpp
|
||||
main_tests/nca_test.cpp
|
||||
@@ -229,8 +229,6 @@ add_custom_command(TARGET mlpack_test
|
||||
set(parallel_tests
|
||||
"AsyncLearningTest;"
|
||||
"LocalCoordinateCodingTest;"
|
||||
"FeedForwardNetworkTest;"
|
||||
"RecurrentNetworkTest;"
|
||||
"GMMTest;"
|
||||
"CFTest;"
|
||||
"HMMTest;"
|
||||
|
||||
@@ -380,6 +380,26 @@ TEST_CASE("SimpleCVMSETest", "[CVTest]")
|
||||
REQUIRE(std::abs(weightedCV2.Evaluate() - expectedMSE) > 1e-5);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that scores of -nan are filtered out.
|
||||
*/
|
||||
TEST_CASE("FilterNANCVTest", "[CVTest]")
|
||||
{
|
||||
// Create a dataset with only one positive label, so it will not be in every
|
||||
// fold.
|
||||
arma::mat data(3, 10, arma::fill::randu);
|
||||
arma::Row<size_t> labels(10, arma::fill::zeros);
|
||||
labels[0] = 1;
|
||||
|
||||
const size_t numClasses = 2;
|
||||
KFoldCV<NaiveBayesClassifier<>, F1<Binary>> kfoldcv(2, data, labels,
|
||||
numClasses);
|
||||
|
||||
const double result = kfoldcv.Evaluate();
|
||||
REQUIRE(!std::isnan(result));
|
||||
REQUIRE(!std::isinf(result));
|
||||
}
|
||||
|
||||
template<typename... DTArgs>
|
||||
arma::Row<size_t> PredictLabelsWithDT(const arma::mat& data,
|
||||
const DTArgs&... args)
|
||||
|
||||
@@ -19,17 +19,14 @@
|
||||
|
||||
#include <ensmallen.hpp>
|
||||
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include "test_tools.hpp"
|
||||
#include "serialization.hpp"
|
||||
#include "catch.hpp"
|
||||
#include "serialization_catch.hpp"
|
||||
#include "custom_layer.hpp"
|
||||
|
||||
using namespace mlpack;
|
||||
using namespace mlpack::ann;
|
||||
using namespace mlpack::kmeans;
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(FeedForwardNetworkTest);
|
||||
|
||||
/**
|
||||
* Train and evaluate a model with the specified structure.
|
||||
*/
|
||||
@@ -57,13 +54,13 @@ void TestNetwork(ModelType& model,
|
||||
|
||||
size_t correct = arma::accu(prediction == testLabels);
|
||||
double classificationError = 1 - double(correct) / testData.n_cols;
|
||||
BOOST_REQUIRE_LE(classificationError, classificationErrorThreshold);
|
||||
REQUIRE(classificationError <= classificationErrorThreshold);
|
||||
}
|
||||
|
||||
/**
|
||||
* Train the vanilla network on a larger dataset.
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE(VanillaNetworkTest)
|
||||
TEST_CASE("FFVanillaNetworkTest", "[FeedForwardNetworkTest]")
|
||||
{
|
||||
// Load the dataset.
|
||||
arma::mat trainData;
|
||||
@@ -131,7 +128,7 @@ BOOST_AUTO_TEST_CASE(VanillaNetworkTest)
|
||||
TestNetwork<>(model1, dataset, labels, dataset, labels, 10, 0.2);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(ForwardBackwardTest)
|
||||
TEST_CASE("ForwardBackwardTest", "[FeedForwardNetworkTest]")
|
||||
{
|
||||
arma::mat dataset;
|
||||
dataset.load("mnist_first250_training_4s_and_9s.arm");
|
||||
@@ -204,13 +201,13 @@ BOOST_AUTO_TEST_CASE(ForwardBackwardTest)
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_REQUIRE(converged);
|
||||
REQUIRE(converged);
|
||||
}
|
||||
|
||||
/**
|
||||
* Train the dropout network on a larger dataset.
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE(DropoutNetworkTest)
|
||||
TEST_CASE("DropoutNetworkTest", "[FeedForwardNetworkTest]")
|
||||
{
|
||||
// Load the dataset.
|
||||
arma::mat trainData;
|
||||
@@ -284,7 +281,7 @@ BOOST_AUTO_TEST_CASE(DropoutNetworkTest)
|
||||
/**
|
||||
* Train the highway network on a larger dataset.
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE(HighwayNetworkTest)
|
||||
TEST_CASE("HighwayNetworkTest", "[FeedForwardNetworkTest]")
|
||||
{
|
||||
arma::mat dataset;
|
||||
dataset.load("mnist_first250_training_4s_and_9s.arm");
|
||||
@@ -311,7 +308,7 @@ BOOST_AUTO_TEST_CASE(HighwayNetworkTest)
|
||||
/**
|
||||
* Train the DropConnect network on a larger dataset.
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE(DropConnectNetworkTest)
|
||||
TEST_CASE("DropConnectNetworkTest", "[FeedForwardNetworkTest]")
|
||||
{
|
||||
// Load the dataset.
|
||||
arma::mat trainData;
|
||||
@@ -385,7 +382,7 @@ BOOST_AUTO_TEST_CASE(DropConnectNetworkTest)
|
||||
* Test miscellaneous things of FFN,
|
||||
* e.g. copy/move constructor, assignment operator.
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE(FFNMiscTest)
|
||||
TEST_CASE("FFNMiscTest", "[FeedForwardNetworkTest]")
|
||||
{
|
||||
FFN<MeanSquaredError<>> model;
|
||||
model.Add<Linear<>>(2, 3);
|
||||
@@ -400,7 +397,7 @@ BOOST_AUTO_TEST_CASE(FFNMiscTest)
|
||||
/**
|
||||
* Test that serialization works ok.
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE(SerializationTest)
|
||||
TEST_CASE("FFSerializationTest", "[FeedForwardNetworkTest]")
|
||||
{
|
||||
// Load the dataset.
|
||||
arma::mat trainData;
|
||||
@@ -449,7 +446,7 @@ BOOST_AUTO_TEST_CASE(SerializationTest)
|
||||
* Test if the custom layers work. The target is to see if the code compiles
|
||||
* when the Train and Prediction are called.
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE(CustomLayerTest)
|
||||
TEST_CASE("CustomLayerTest", "[FeedForwardNetworkTest]")
|
||||
{
|
||||
// Load the dataset.
|
||||
arma::mat trainData;
|
||||
@@ -481,7 +478,7 @@ BOOST_AUTO_TEST_CASE(CustomLayerTest)
|
||||
/**
|
||||
* Test the overload of Forward function which allows partial forward pass.
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE(PartialForwardTest)
|
||||
TEST_CASE("PartialForwardTest", "[FeedForwardNetworkTest]")
|
||||
{
|
||||
FFN<NegativeLogLikelihood<>, RandomInitialization> model;
|
||||
model.Add<Linear<> >(5, 10);
|
||||
@@ -528,7 +525,7 @@ BOOST_AUTO_TEST_CASE(PartialForwardTest)
|
||||
/**
|
||||
* Test that FFN::Train() returns finite objective value.
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE(FFNTrainReturnObjective)
|
||||
TEST_CASE("FFNTrainReturnObjective", "[FeedForwardNetworkTest]")
|
||||
{
|
||||
// Load the dataset.
|
||||
arma::mat trainData;
|
||||
@@ -557,13 +554,13 @@ BOOST_AUTO_TEST_CASE(FFNTrainReturnObjective)
|
||||
|
||||
double objVal = model.Train(trainData, trainLabels, opt);
|
||||
|
||||
BOOST_REQUIRE_EQUAL(std::isfinite(objVal), true);
|
||||
REQUIRE(std::isfinite(objVal) == true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that FFN::Model() allows us to access the instantiated network.
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE(FFNReturnModel)
|
||||
TEST_CASE("FFNReturnModel", "[FeedForwardNetworkTest]")
|
||||
{
|
||||
// Create dummy network.
|
||||
FFN<NegativeLogLikelihood<> > model;
|
||||
@@ -598,7 +595,7 @@ BOOST_AUTO_TEST_CASE(FFNReturnModel)
|
||||
* Test to see if the FFN code compiles when the Optimizer
|
||||
* doesn't have the MaxIterations() method.
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE(OptimizerTest)
|
||||
TEST_CASE("OptimizerTest", "[FeedForwardNetworkTest]")
|
||||
{
|
||||
// Load the dataset.
|
||||
arma::mat trainData;
|
||||
@@ -626,7 +623,7 @@ BOOST_AUTO_TEST_CASE(OptimizerTest)
|
||||
/**
|
||||
* Train the RBF network on a larger dataset.
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE(RBFNetworkTest)
|
||||
TEST_CASE("RBFNetworkTest", "[FeedForwardNetworkTest]")
|
||||
{
|
||||
// Load the dataset.
|
||||
arma::mat trainData;
|
||||
@@ -703,5 +700,3 @@ BOOST_AUTO_TEST_CASE(RBFNetworkTest)
|
||||
// RBFN neural net with MeanSquaredError.
|
||||
TestNetwork<>(model1, dataset, labels1, dataset, labels, 10, 0.1);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END();
|
||||
|
||||
@@ -598,6 +598,105 @@ BOOST_AUTO_TEST_CASE(InputMatrixParamTest)
|
||||
BOOST_REQUIRE_CLOSE(dataset[i], dataset2[i], 1e-10);
|
||||
}
|
||||
|
||||
// Make sure we can correctly load required matrix parameters.
|
||||
BOOST_AUTO_TEST_CASE(RequiredInputMatrixParamTest)
|
||||
{
|
||||
AddRequiredCLIOptions();
|
||||
|
||||
// --matrix is an input parameter; it won't be transposed.
|
||||
PARAM_MATRIX_IN_REQ("matrix", "Test matrix", "m");
|
||||
|
||||
// Set some fake arguments.
|
||||
const char* argv[3];
|
||||
argv[0] = "./test";
|
||||
argv[1] = "--matrix_file";
|
||||
argv[2] = "test_data_3_1000.csv";
|
||||
|
||||
int argc = 3;
|
||||
|
||||
// The const-cast is a little hacky but should be fine...
|
||||
ParseCommandLine(argc, const_cast<char**>(argv));
|
||||
|
||||
// The --matrix parameter should exist.
|
||||
BOOST_REQUIRE(IO::HasParam("matrix"));
|
||||
// The --matrix_file parameter should not exist (it should be transparent from
|
||||
// inside the program).
|
||||
Log::Fatal.ignoreInput = true;
|
||||
BOOST_REQUIRE_THROW(IO::HasParam("matrix_file"), runtime_error);
|
||||
Log::Fatal.ignoreInput = false;
|
||||
|
||||
arma::mat dataset = IO::GetParam<arma::mat>("matrix");
|
||||
arma::mat dataset2 = IO::GetParam<arma::mat>("matrix");
|
||||
|
||||
BOOST_REQUIRE_EQUAL(dataset.n_rows, 3);
|
||||
BOOST_REQUIRE_EQUAL(dataset.n_cols, 1000);
|
||||
BOOST_REQUIRE_EQUAL(dataset2.n_rows, 3);
|
||||
BOOST_REQUIRE_EQUAL(dataset2.n_cols, 1000);
|
||||
|
||||
for (size_t i = 0; i < dataset.n_elem; ++i)
|
||||
BOOST_REQUIRE_CLOSE(dataset[i], dataset2[i], 1e-10);
|
||||
}
|
||||
|
||||
// Make sure loading required matrix options by alias succeeds.
|
||||
BOOST_AUTO_TEST_CASE(RequiredInputMatrixParamAliasTest)
|
||||
{
|
||||
AddRequiredCLIOptions();
|
||||
|
||||
// --matrix is an input parameter; it won't be transposed.
|
||||
PARAM_MATRIX_IN_REQ("matrix", "Test matrix", "m");
|
||||
|
||||
// Set some fake arguments.
|
||||
const char* argv[3];
|
||||
argv[0] = "./test";
|
||||
argv[1] = "-m";
|
||||
argv[2] = "test_data_3_1000.csv";
|
||||
|
||||
int argc = 3;
|
||||
|
||||
// The const-cast is a little hacky but should be fine...
|
||||
ParseCommandLine(argc, const_cast<char**>(argv));
|
||||
|
||||
// The --matrix parameter should exist.
|
||||
BOOST_REQUIRE(IO::HasParam("matrix"));
|
||||
// The --matrix_file parameter should not exist (it should be transparent from
|
||||
// inside the program).
|
||||
Log::Fatal.ignoreInput = true;
|
||||
BOOST_REQUIRE_THROW(IO::HasParam("matrix_file"), runtime_error);
|
||||
Log::Fatal.ignoreInput = false;
|
||||
|
||||
arma::mat dataset = IO::GetParam<arma::mat>("matrix");
|
||||
arma::mat dataset2 = IO::GetParam<arma::mat>("matrix");
|
||||
|
||||
BOOST_REQUIRE_EQUAL(dataset.n_rows, 3);
|
||||
BOOST_REQUIRE_EQUAL(dataset.n_cols, 1000);
|
||||
BOOST_REQUIRE_EQUAL(dataset2.n_rows, 3);
|
||||
BOOST_REQUIRE_EQUAL(dataset2.n_cols, 1000);
|
||||
|
||||
for (size_t i = 0; i < dataset.n_elem; ++i)
|
||||
BOOST_REQUIRE_CLOSE(dataset[i], dataset2[i], 1e-10);
|
||||
}
|
||||
|
||||
// Make sure that when we don't pass a required matrix, parsing fails.
|
||||
BOOST_AUTO_TEST_CASE(RequiredUnspecifiedInputMatrixParamTest)
|
||||
{
|
||||
AddRequiredCLIOptions();
|
||||
|
||||
// --matrix is an input parameter; it won't be transposed.
|
||||
PARAM_MATRIX_IN_REQ("matrix", "Test matrix", "m");
|
||||
|
||||
// Set some fake arguments.
|
||||
const char* argv[1];
|
||||
argv[0] = "./test";
|
||||
|
||||
int argc = 1;
|
||||
|
||||
// The const-cast is a little hacky but should be fine...
|
||||
Log::Fatal.ignoreInput = true;
|
||||
BOOST_REQUIRE_THROW(ParseCommandLine(argc, const_cast<char**>(argv)),
|
||||
std::exception);
|
||||
Log::Fatal.ignoreInput = false;
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(InputMatrixNoTransposeParamTest)
|
||||
{
|
||||
AddRequiredCLIOptions();
|
||||
|
||||
@@ -22,9 +22,8 @@
|
||||
#include <mlpack/core/tree/cover_tree/cover_tree.hpp>
|
||||
#include <mlpack/methods/neighbor_search/neighbor_search.hpp>
|
||||
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include "catch.hpp"
|
||||
#include <mlpack/methods/kmeans/kill_empty_clusters.hpp>
|
||||
#include "test_tools.hpp"
|
||||
|
||||
using namespace mlpack;
|
||||
using namespace mlpack::kmeans;
|
||||
@@ -32,8 +31,6 @@ using namespace mlpack::metric;
|
||||
using namespace mlpack::tree;
|
||||
using namespace mlpack::neighbor;
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(KMeansTest);
|
||||
|
||||
// Generate dataset; written transposed because it's easier to read.
|
||||
arma::mat kMeansData(" 0.0 0.0;" // Class 1.
|
||||
" 0.3 0.4;"
|
||||
@@ -69,7 +66,7 @@ arma::mat kMeansData(" 0.0 0.0;" // Class 1.
|
||||
/**
|
||||
* 30-point 3-class test case for K-Means.
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE(KMeansSimpleTest)
|
||||
TEST_CASE("KMeansSimpleTest", "[KMeansTest]")
|
||||
{
|
||||
// This test was originally written to use RandomPartition, and is left that
|
||||
// way because RandomPartition gives better initializations here.
|
||||
@@ -83,30 +80,30 @@ BOOST_AUTO_TEST_CASE(KMeansSimpleTest)
|
||||
size_t firstClass = assignments(0);
|
||||
|
||||
for (size_t i = 1; i < 13; ++i)
|
||||
BOOST_REQUIRE_EQUAL(assignments(i), firstClass);
|
||||
REQUIRE(assignments(i) == firstClass);
|
||||
|
||||
size_t secondClass = assignments(13);
|
||||
|
||||
// To ensure that class 1 != class 2.
|
||||
BOOST_REQUIRE_NE(firstClass, secondClass);
|
||||
REQUIRE(firstClass != secondClass);
|
||||
|
||||
for (size_t i = 13; i < 20; ++i)
|
||||
BOOST_REQUIRE_EQUAL(assignments(i), secondClass);
|
||||
REQUIRE(assignments(i) == secondClass);
|
||||
|
||||
size_t thirdClass = assignments(20);
|
||||
|
||||
// To ensure that this is the third class which we haven't seen yet.
|
||||
BOOST_REQUIRE_NE(firstClass, thirdClass);
|
||||
BOOST_REQUIRE_NE(secondClass, thirdClass);
|
||||
REQUIRE(firstClass != thirdClass);
|
||||
REQUIRE(secondClass != thirdClass);
|
||||
|
||||
for (size_t i = 20; i < 30; ++i)
|
||||
BOOST_REQUIRE_EQUAL(assignments(i), thirdClass);
|
||||
REQUIRE(assignments(i) == thirdClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure the empty cluster policy class does nothing.
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE(AllowEmptyClusterTest)
|
||||
TEST_CASE("AllowEmptyClusterTest", "[KMeansTest]")
|
||||
{
|
||||
arma::Row<size_t> assignments;
|
||||
assignments.randu(30);
|
||||
@@ -129,17 +126,17 @@ BOOST_AUTO_TEST_CASE(AllowEmptyClusterTest)
|
||||
|
||||
// Make sure no assignments were changed.
|
||||
for (size_t i = 0; i < assignments.n_elem; ++i)
|
||||
BOOST_REQUIRE_EQUAL(assignments[i], assignmentsOld[i]);
|
||||
REQUIRE(assignments[i] == assignmentsOld[i]);
|
||||
|
||||
// Make sure no counts were changed.
|
||||
for (size_t i = 0; i < 3; ++i)
|
||||
BOOST_REQUIRE_EQUAL(counts[i], countsOld[i]);
|
||||
REQUIRE(counts[i] == countsOld[i]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure kill empty cluster policy removes the empty cluster.
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE(KillEmptyClusterTest)
|
||||
TEST_CASE("KillEmptyClusterTest", "[KMeansTest]")
|
||||
{
|
||||
arma::Row<size_t> assignments;
|
||||
assignments.randu(30);
|
||||
@@ -162,20 +159,20 @@ BOOST_AUTO_TEST_CASE(KillEmptyClusterTest)
|
||||
|
||||
// Make sure no assignments were changed.
|
||||
for (size_t i = 0; i < assignments.n_elem; ++i)
|
||||
BOOST_REQUIRE_EQUAL(assignments[i], assignmentsOld[i]);
|
||||
REQUIRE(assignments[i] == assignmentsOld[i]);
|
||||
|
||||
// Make sure no counts were changed for clusters that are not empty.
|
||||
for (size_t i = 0; i < 2; ++i)
|
||||
BOOST_REQUIRE_EQUAL(counts[i], countsOld[i]);
|
||||
REQUIRE(counts[i] == countsOld[i]);
|
||||
|
||||
// Make sure that counts contain one less element than old counts.
|
||||
BOOST_REQUIRE_GT(countsOld.n_elem, counts.n_elem);
|
||||
REQUIRE(countsOld.n_elem > counts.n_elem);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure the max variance method finds the correct point.
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE(MaxVarianceNewClusterTest)
|
||||
TEST_CASE("MaxVarianceNewClusterTest", "[KMeansTest]")
|
||||
{
|
||||
// Five points.
|
||||
arma::mat data("0.4 1.0 5.0 -2.0 -2.5;"
|
||||
@@ -220,22 +217,22 @@ BOOST_AUTO_TEST_CASE(MaxVarianceNewClusterTest)
|
||||
assignments[i] = closestCluster;
|
||||
}
|
||||
|
||||
BOOST_REQUIRE_EQUAL(assignments[0], 0);
|
||||
BOOST_REQUIRE_EQUAL(assignments[1], 0);
|
||||
BOOST_REQUIRE_EQUAL(assignments[2], 2);
|
||||
BOOST_REQUIRE_EQUAL(assignments[3], 1);
|
||||
BOOST_REQUIRE_EQUAL(assignments[4], 1);
|
||||
REQUIRE(assignments[0] == 0);
|
||||
REQUIRE(assignments[1] == 0);
|
||||
REQUIRE(assignments[2] == 2);
|
||||
REQUIRE(assignments[3] == 1);
|
||||
REQUIRE(assignments[4] == 1);
|
||||
|
||||
// Ensure that the counts are right.
|
||||
BOOST_REQUIRE_EQUAL(counts[0], 2);
|
||||
BOOST_REQUIRE_EQUAL(counts[1], 2);
|
||||
BOOST_REQUIRE_EQUAL(counts[2], 1);
|
||||
REQUIRE(counts[0] == 2);
|
||||
REQUIRE(counts[1] == 2);
|
||||
REQUIRE(counts[2] == 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure the random partitioner seems to return valid results.
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE(RandomPartitionTest)
|
||||
TEST_CASE("RandomPartitionTest", "[KMeansTest]")
|
||||
{
|
||||
arma::mat data;
|
||||
data.randu(2, 1000); // One thousand points.
|
||||
@@ -246,17 +243,17 @@ BOOST_AUTO_TEST_CASE(RandomPartitionTest)
|
||||
RandomPartition::Cluster(data, 18, assignments);
|
||||
|
||||
// Ensure that the right number of assignments were given.
|
||||
BOOST_REQUIRE_EQUAL(assignments.n_elem, 1000);
|
||||
REQUIRE(assignments.n_elem == 1000);
|
||||
|
||||
// Ensure that no value is greater than 17 (the maximum valid cluster).
|
||||
for (size_t i = 0; i < 1000; ++i)
|
||||
BOOST_REQUIRE_LT(assignments[i], 18);
|
||||
REQUIRE(assignments[i] < 18);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure that random initialization fails for a corner case dataset.
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE(RandomInitialAssignmentFailureTest)
|
||||
TEST_CASE("RandomInitialAssignmentFailureTest", "[KMeansTest]")
|
||||
{
|
||||
// This is a very synthetic dataset. It is one Gaussian with a huge number of
|
||||
// points combined with one faraway Gaussian with very few points. Normally,
|
||||
@@ -292,14 +289,14 @@ BOOST_AUTO_TEST_CASE(RandomInitialAssignmentFailureTest)
|
||||
|
||||
// Only one success allowed. The probability of two successes should be
|
||||
// infinitesimal.
|
||||
BOOST_REQUIRE_LT(successes, 2);
|
||||
REQUIRE(successes < 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure that specifying initial assignments is successful for a corner case
|
||||
* dataset which doesn't usually converge otherwise.
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE(InitialAssignmentTest)
|
||||
TEST_CASE("InitialAssignmentTest", "[KMeansTest]")
|
||||
{
|
||||
// For a better description of this dataset, see
|
||||
// RandomInitialAssignmentFailureTest.
|
||||
@@ -321,9 +318,9 @@ BOOST_AUTO_TEST_CASE(InitialAssignmentTest)
|
||||
|
||||
// Check results.
|
||||
for (size_t i = 0; i < 10000; ++i)
|
||||
BOOST_REQUIRE_EQUAL(assignments[i], 0);
|
||||
REQUIRE(assignments[i] == 0);
|
||||
for (size_t i = 10000; i < 10002; ++i)
|
||||
BOOST_REQUIRE_EQUAL(assignments[i], 1);
|
||||
REQUIRE(assignments[i] == 1);
|
||||
|
||||
// Now, slightly harder. Give it one incorrect assignment in each cluster.
|
||||
// The wrong assignment should be quickly fixed.
|
||||
@@ -334,16 +331,16 @@ BOOST_AUTO_TEST_CASE(InitialAssignmentTest)
|
||||
|
||||
// Check results.
|
||||
for (size_t i = 0; i < 10000; ++i)
|
||||
BOOST_REQUIRE_EQUAL(assignments[i], 0);
|
||||
REQUIRE(assignments[i] == 0);
|
||||
for (size_t i = 10000; i < 10002; ++i)
|
||||
BOOST_REQUIRE_EQUAL(assignments[i], 1);
|
||||
REQUIRE(assignments[i] == 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure specifying initial centroids is successful for a corner case which
|
||||
* doesn't usually converge otherwise.
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE(InitialCentroidTest)
|
||||
TEST_CASE("InitialCentroidTest", "[KMeansTest]")
|
||||
{
|
||||
// For a better description of this dataset, see
|
||||
// RandomInitialAssignmentFailureTest.
|
||||
@@ -365,9 +362,9 @@ BOOST_AUTO_TEST_CASE(InitialCentroidTest)
|
||||
|
||||
// Check results.
|
||||
for (size_t i = 0; i < 10000; ++i)
|
||||
BOOST_REQUIRE_EQUAL(assignments[i], 0);
|
||||
REQUIRE(assignments[i] == 0);
|
||||
for (size_t i = 10000; i < 10002; ++i)
|
||||
BOOST_REQUIRE_EQUAL(assignments[i], 1);
|
||||
REQUIRE(assignments[i] == 1);
|
||||
|
||||
// Now add a little noise to the initial centroids.
|
||||
centroids.col(0) = arma::vec("3 4");
|
||||
@@ -377,15 +374,15 @@ BOOST_AUTO_TEST_CASE(InitialCentroidTest)
|
||||
|
||||
// Check results.
|
||||
for (size_t i = 0; i < 10000; ++i)
|
||||
BOOST_REQUIRE_EQUAL(assignments[i], 0);
|
||||
REQUIRE(assignments[i] == 0);
|
||||
for (size_t i = 10000; i < 10002; ++i)
|
||||
BOOST_REQUIRE_EQUAL(assignments[i], 1);
|
||||
REQUIRE(assignments[i] == 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that initial assignments override initial centroids.
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE(InitialAssignmentOverrideTest)
|
||||
TEST_CASE("InitialAssignmentOverrideTest", "[KMeansTest]")
|
||||
{
|
||||
// For a better description of this dataset, see
|
||||
// RandomInitialAssignmentFailureTest.
|
||||
@@ -412,22 +409,22 @@ BOOST_AUTO_TEST_CASE(InitialAssignmentOverrideTest)
|
||||
// Because the initial assignments guess should take priority, we should get
|
||||
// those same results back.
|
||||
for (size_t i = 0; i < 10000; ++i)
|
||||
BOOST_REQUIRE_EQUAL(assignments[i], 0);
|
||||
REQUIRE(assignments[i] == 0);
|
||||
for (size_t i = 10000; i < 10002; ++i)
|
||||
BOOST_REQUIRE_EQUAL(assignments[i], 1);
|
||||
REQUIRE(assignments[i] == 1);
|
||||
|
||||
// Make sure the centroids are about right too.
|
||||
BOOST_REQUIRE_LT(centroids(0, 0), 10.0);
|
||||
BOOST_REQUIRE_LT(centroids(1, 0), 10.0);
|
||||
BOOST_REQUIRE_GT(centroids(0, 1), 40.0);
|
||||
BOOST_REQUIRE_GT(centroids(1, 1), 40.0);
|
||||
REQUIRE(centroids(0, 0) < 10.0);
|
||||
REQUIRE(centroids(1, 0) < 10.0);
|
||||
REQUIRE(centroids(0, 1) > 40.0);
|
||||
REQUIRE(centroids(1, 1) > 40.0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that the refined starting policy returns decent initial cluster
|
||||
* estimates.
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE(RefinedStartTest)
|
||||
TEST_CASE("RefinedStartTest", "[KMeansTest]")
|
||||
{
|
||||
// Our dataset will be five Gaussians of largely varying numbers of points and
|
||||
// we expect that the refined starting policy should return good guesses at
|
||||
@@ -486,14 +483,14 @@ BOOST_AUTO_TEST_CASE(RefinedStartTest)
|
||||
// figure is a corner case which actually does not give good clusters), and
|
||||
// random initial starts give distortion around 22000. So we'll require that
|
||||
// our distortion is less than 14000.
|
||||
BOOST_REQUIRE_LT(distortion, 14000.0);
|
||||
REQUIRE(distortion < 14000.0);
|
||||
}
|
||||
|
||||
#ifdef ARMA_HAS_SPMAT
|
||||
/**
|
||||
* Make sure sparse k-means works okay.
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE(SparseKMeansTest)
|
||||
TEST_CASE("SparseKMeansTest", "[KMeansTest]")
|
||||
{
|
||||
// Huge dimensionality, few points.
|
||||
arma::SpMat<double> data(5000, 12);
|
||||
@@ -520,23 +517,23 @@ BOOST_AUTO_TEST_CASE(SparseKMeansTest)
|
||||
size_t clusterOne = assignments[0];
|
||||
size_t clusterTwo = assignments[6];
|
||||
|
||||
BOOST_REQUIRE_EQUAL(assignments[0], clusterOne);
|
||||
BOOST_REQUIRE_EQUAL(assignments[1], clusterOne);
|
||||
BOOST_REQUIRE_EQUAL(assignments[2], clusterOne);
|
||||
BOOST_REQUIRE_EQUAL(assignments[3], clusterOne);
|
||||
BOOST_REQUIRE_EQUAL(assignments[4], clusterOne);
|
||||
BOOST_REQUIRE_EQUAL(assignments[5], clusterOne);
|
||||
BOOST_REQUIRE_EQUAL(assignments[6], clusterTwo);
|
||||
BOOST_REQUIRE_EQUAL(assignments[7], clusterTwo);
|
||||
BOOST_REQUIRE_EQUAL(assignments[8], clusterTwo);
|
||||
BOOST_REQUIRE_EQUAL(assignments[9], clusterTwo);
|
||||
BOOST_REQUIRE_EQUAL(assignments[10], clusterTwo);
|
||||
BOOST_REQUIRE_EQUAL(assignments[11], clusterTwo);
|
||||
REQUIRE(assignments[0] == clusterOne);
|
||||
REQUIRE(assignments[1] == clusterOne);
|
||||
REQUIRE(assignments[2] == clusterOne);
|
||||
REQUIRE(assignments[3] == clusterOne);
|
||||
REQUIRE(assignments[4] == clusterOne);
|
||||
REQUIRE(assignments[5] == clusterOne);
|
||||
REQUIRE(assignments[6] == clusterTwo);
|
||||
REQUIRE(assignments[7] == clusterTwo);
|
||||
REQUIRE(assignments[8] == clusterTwo);
|
||||
REQUIRE(assignments[9] == clusterTwo);
|
||||
REQUIRE(assignments[10] == clusterTwo);
|
||||
REQUIRE(assignments[11] == clusterTwo);
|
||||
}
|
||||
|
||||
#endif // ARMA_HAS_SPMAT
|
||||
|
||||
BOOST_AUTO_TEST_CASE(ElkanTest)
|
||||
TEST_CASE("ElkanTest", "[KMeansTest]")
|
||||
{
|
||||
const size_t trials = 5;
|
||||
|
||||
@@ -563,14 +560,14 @@ BOOST_AUTO_TEST_CASE(ElkanTest)
|
||||
elkan.Cluster(dataset, k, elkanAssignments, elkanCentroids, false, true);
|
||||
|
||||
for (size_t i = 0; i < dataset.n_cols; ++i)
|
||||
BOOST_REQUIRE_EQUAL(assignments[i], elkanAssignments[i]);
|
||||
REQUIRE(assignments[i] == elkanAssignments[i]);
|
||||
|
||||
for (size_t i = 0; i < centroids.n_elem; ++i)
|
||||
BOOST_REQUIRE_CLOSE(naiveCentroids[i], elkanCentroids[i], 1e-5);
|
||||
REQUIRE(naiveCentroids[i] == Approx(elkanCentroids[i]).epsilon(1e-7));
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(HamerlyTest)
|
||||
TEST_CASE("HamerlyTest", "[KMeansTest]")
|
||||
{
|
||||
const size_t trials = 5;
|
||||
|
||||
@@ -598,14 +595,14 @@ BOOST_AUTO_TEST_CASE(HamerlyTest)
|
||||
true);
|
||||
|
||||
for (size_t i = 0; i < dataset.n_cols; ++i)
|
||||
BOOST_REQUIRE_EQUAL(assignments[i], hamerlyAssignments[i]);
|
||||
REQUIRE(assignments[i] == hamerlyAssignments[i]);
|
||||
|
||||
for (size_t i = 0; i < centroids.n_elem; ++i)
|
||||
BOOST_REQUIRE_CLOSE(naiveCentroids[i], hamerlyCentroids[i], 1e-5);
|
||||
REQUIRE(naiveCentroids[i] == Approx(hamerlyCentroids[i]).epsilon(1e-7));
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(PellegMooreTest)
|
||||
TEST_CASE("PellegMooreTest", "[KMeansTest]")
|
||||
{
|
||||
const size_t trials = 5;
|
||||
|
||||
@@ -632,14 +629,14 @@ BOOST_AUTO_TEST_CASE(PellegMooreTest)
|
||||
pellegMoore.Cluster(dataset, k, pmAssignments, pmCentroids, false, true);
|
||||
|
||||
for (size_t i = 0; i < dataset.n_cols; ++i)
|
||||
BOOST_REQUIRE_EQUAL(assignments[i], pmAssignments[i]);
|
||||
REQUIRE(assignments[i] == pmAssignments[i]);
|
||||
|
||||
for (size_t i = 0; i < centroids.n_elem; ++i)
|
||||
BOOST_REQUIRE_CLOSE(naiveCentroids[i], pmCentroids[i], 1e-5);
|
||||
REQUIRE(naiveCentroids[i] == Approx(pmCentroids[i]).epsilon(1e-7));
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(DTNNTest)
|
||||
TEST_CASE("DTNNTest", "[KMeansTest]")
|
||||
{
|
||||
const size_t trials = 5;
|
||||
|
||||
@@ -664,14 +661,14 @@ BOOST_AUTO_TEST_CASE(DTNNTest)
|
||||
dtnn.Cluster(dataset, k, dtnnAssignments, dtnnCentroids, false, true);
|
||||
|
||||
for (size_t i = 0; i < dataset.n_cols; ++i)
|
||||
BOOST_REQUIRE_EQUAL(assignments[i], dtnnAssignments[i]);
|
||||
REQUIRE(assignments[i] == dtnnAssignments[i]);
|
||||
|
||||
for (size_t i = 0; i < centroids.n_elem; ++i)
|
||||
BOOST_REQUIRE_CLOSE(naiveCentroids[i], dtnnCentroids[i], 1e-5);
|
||||
REQUIRE(naiveCentroids[i] == Approx(dtnnCentroids[i]).epsilon(1e-7));
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(DTNNCoverTreeTest)
|
||||
TEST_CASE("DTNNCoverTreeTest", "[KMeansTest]")
|
||||
{
|
||||
const size_t trials = 5;
|
||||
|
||||
@@ -696,10 +693,10 @@ BOOST_AUTO_TEST_CASE(DTNNCoverTreeTest)
|
||||
dtnn.Cluster(dataset, k, dtnnAssignments, dtnnCentroids, false, true);
|
||||
|
||||
for (size_t i = 0; i < dataset.n_cols; ++i)
|
||||
BOOST_REQUIRE_EQUAL(assignments[i], dtnnAssignments[i]);
|
||||
REQUIRE(assignments[i] == dtnnAssignments[i]);
|
||||
|
||||
for (size_t i = 0; i < centroids.n_elem; ++i)
|
||||
BOOST_REQUIRE_CLOSE(naiveCentroids[i], dtnnCentroids[i], 1e-5);
|
||||
REQUIRE(naiveCentroids[i] == Approx(dtnnCentroids[i]).epsilon(1e-7));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -707,7 +704,7 @@ BOOST_AUTO_TEST_CASE(DTNNCoverTreeTest)
|
||||
* Make sure that the sample initialization strategy successfully samples points
|
||||
* from the dataset.
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE(SampleInitializationTest)
|
||||
TEST_CASE("SampleInitializationTest", "[KMeansTest]")
|
||||
{
|
||||
arma::mat dataset = arma::randu<arma::mat>(5, 100);
|
||||
const size_t clusters = 10;
|
||||
@@ -716,8 +713,8 @@ BOOST_AUTO_TEST_CASE(SampleInitializationTest)
|
||||
SampleInitialization::Cluster(dataset, clusters, centroids);
|
||||
|
||||
// Check that the size of the matrix is correct.
|
||||
BOOST_REQUIRE_EQUAL(centroids.n_cols, 10);
|
||||
BOOST_REQUIRE_EQUAL(centroids.n_rows, 5);
|
||||
REQUIRE(centroids.n_cols == 10);
|
||||
REQUIRE(centroids.n_rows == 5);
|
||||
|
||||
// Check that each entry in the matrix is some sample from the dataset.
|
||||
for (size_t i = 0; i < clusters; ++i)
|
||||
@@ -733,8 +730,6 @@ BOOST_AUTO_TEST_CASE(SampleInitializationTest)
|
||||
break;
|
||||
}
|
||||
|
||||
BOOST_REQUIRE_LT(j, dataset.n_cols);
|
||||
REQUIRE(j < dataset.n_cols);
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END();
|
||||
|
||||
@@ -48,6 +48,56 @@ TEST_CASE("NotExistLoad", "[LoadSaveTest]")
|
||||
REQUIRE(data::Load("nonexistentfile_______________.csv", out) == false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure load fails if the file extension is wrong in automatic detection mode.
|
||||
*/
|
||||
TEST_CASE("WrongExtensionWrongLoad", "[LoadSaveTest]")
|
||||
{
|
||||
// Try to load arma::arma_binary file with ".csv" extension
|
||||
arma::mat test = "1 5;"
|
||||
"2 6;"
|
||||
"3 7;"
|
||||
"4 8;";
|
||||
|
||||
arma::mat testTrans = trans(test);
|
||||
REQUIRE(testTrans.quiet_save("test_file.csv", arma::arma_binary) == true);
|
||||
|
||||
// Now reload through our interface.
|
||||
REQUIRE(data::Load("test_file.csv", test) == false);
|
||||
|
||||
// Remove the file.
|
||||
remove("test_file.csv");
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure load is successful even if the file extension is wrong when file type is specified.
|
||||
*/
|
||||
TEST_CASE("WrongExtensionCorrectLoad", "[LoadSaveTest]")
|
||||
{
|
||||
// Try to load arma::arma_binary file with ".csv" extension
|
||||
arma::mat test = "1 5;"
|
||||
"2 6;"
|
||||
"3 7;"
|
||||
"4 8;";
|
||||
|
||||
arma::mat testTrans = trans(test);
|
||||
REQUIRE(testTrans.quiet_save("test_file.csv", arma::arma_binary) == true);
|
||||
|
||||
// Now reload through our interface.
|
||||
REQUIRE(
|
||||
data::Load("test_file.csv", test, false, true, arma::arma_binary)
|
||||
== true);
|
||||
|
||||
REQUIRE(test.n_rows == 4);
|
||||
REQUIRE(test.n_cols == 2);
|
||||
|
||||
for (size_t i = 0; i < 8; i++)
|
||||
REQUIRE(test[i] == Approx((double) (i + 1)).epsilon(1e-3));
|
||||
|
||||
// Remove the file.
|
||||
remove("test_file.csv");
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure a CSV is loaded correctly.
|
||||
*/
|
||||
@@ -205,6 +255,32 @@ TEST_CASE("LoadTSVExtensionTest", "[LoadSaveTest]")
|
||||
remove("test_file.tsv");
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that we can manually specify the format for loading.
|
||||
*/
|
||||
TEST_CASE("LoadAnyExtensionFileTest", "[LoadSaveTest]")
|
||||
{
|
||||
fstream f;
|
||||
f.open("test_file.blah", fstream::out);
|
||||
|
||||
f << "1\t2\t3\t4" << endl;
|
||||
f << "5\t6\t7\t8" << endl;
|
||||
|
||||
f.close();
|
||||
|
||||
arma::mat test;
|
||||
REQUIRE(data::Load("test_file.blah", test, false, true, arma::raw_ascii));
|
||||
|
||||
REQUIRE(test.n_rows == 4);
|
||||
REQUIRE(test.n_cols == 2);
|
||||
|
||||
for (size_t i = 0; i < 8; ++i)
|
||||
REQUIRE(test[i] == Approx((double) (i + 1)).epsilon(1e-7));
|
||||
|
||||
// Remove the file.
|
||||
remove("test_file.blah");
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure a CSV is saved correctly.
|
||||
*/
|
||||
@@ -892,6 +968,32 @@ TEST_CASE("SaveArmaBinaryTest", "[LoadSaveTest]")
|
||||
remove("test_file.bin");
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure that we can manually specify the format.
|
||||
*/
|
||||
TEST_CASE("SaveArmaBinaryArbitraryExtensionTest", "[LoadSaveTest]")
|
||||
{
|
||||
arma::mat test = "1 5;"
|
||||
"2 6;"
|
||||
"3 7;"
|
||||
"4 8;";
|
||||
|
||||
REQUIRE(data::Save("test_file.blerp.blah", test, false, true,
|
||||
arma::arma_binary) == true);
|
||||
|
||||
REQUIRE(data::Load("test_file.blerp.blah", test, false, true,
|
||||
arma::arma_binary) == true);
|
||||
|
||||
REQUIRE(test.n_rows == 4);
|
||||
REQUIRE(test.n_cols == 2);
|
||||
|
||||
for (size_t i = 0; i < 8; ++i)
|
||||
REQUIRE(test[i] == Approx((double) (i + 1)).epsilon(1e-7));
|
||||
|
||||
// Remove the file.
|
||||
remove("test_file.blerp.blah");
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure raw_binary is loaded correctly.
|
||||
*/
|
||||
|
||||
@@ -19,8 +19,8 @@ static const std::string testName = "Kmeans";
|
||||
#include "test_helper.hpp"
|
||||
#include <mlpack/methods/kmeans/kmeans_main.cpp>
|
||||
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include "../test_tools.hpp"
|
||||
#include "../catch.hpp"
|
||||
#include "../test_catch_tools.hpp"
|
||||
|
||||
using namespace mlpack;
|
||||
|
||||
@@ -46,22 +46,21 @@ void ResetKmSettings()
|
||||
IO::RestoreSettings(testName);
|
||||
}
|
||||
|
||||
BOOST_FIXTURE_TEST_SUITE(KmeansMainTest, KmTestFixture);
|
||||
|
||||
/**
|
||||
* Checking that number of Clusters are non negative
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE(NonNegativeClustersTest)
|
||||
TEST_CASE_METHOD(KmTestFixture, "NonNegativeClustersTest",
|
||||
"[KmeansMainTest][BindingTests]")
|
||||
{
|
||||
arma::mat inputData;
|
||||
if (!data::Load("vc2.csv", inputData))
|
||||
BOOST_FAIL("Unable to load train dataset vc2.csv!");
|
||||
FAIL("Unable to load train dataset vc2.csv!");
|
||||
|
||||
SetInputParam("input", std::move(inputData));
|
||||
SetInputParam("clusters", (int) -1); // Invalid
|
||||
|
||||
Log::Fatal.ignoreInput = true;
|
||||
BOOST_REQUIRE_THROW(mlpackMain(), std::runtime_error);
|
||||
REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error);
|
||||
Log::Fatal.ignoreInput = false;
|
||||
}
|
||||
|
||||
@@ -69,7 +68,8 @@ BOOST_AUTO_TEST_CASE(NonNegativeClustersTest)
|
||||
/**
|
||||
* Checking that initial centroids are provided if clusters are to be auto detected
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE(AutoDetectClusterTest)
|
||||
TEST_CASE_METHOD(KmTestFixture, "AutoDetectClusterTest",
|
||||
"[KmeansMainTest][BindingTests]")
|
||||
{
|
||||
constexpr int N = 10;
|
||||
constexpr int D = 4;
|
||||
@@ -80,7 +80,7 @@ BOOST_AUTO_TEST_CASE(AutoDetectClusterTest)
|
||||
SetInputParam("clusters", (int) 0); // Invalid
|
||||
|
||||
Log::Fatal.ignoreInput = true;
|
||||
BOOST_REQUIRE_THROW(mlpackMain(), std::runtime_error);
|
||||
REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error);
|
||||
Log::Fatal.ignoreInput = false;
|
||||
}
|
||||
|
||||
@@ -88,13 +88,14 @@ BOOST_AUTO_TEST_CASE(AutoDetectClusterTest)
|
||||
/**
|
||||
* Checking that percentage is between 0 and 1 when --refined_start is specified
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE(RefinedStartPercentageTest)
|
||||
TEST_CASE_METHOD(KmTestFixture, "RefinedStartPercentageTest",
|
||||
"[KmeansMainTest][BindingTests]")
|
||||
{
|
||||
int c = 2;
|
||||
double P = 2.0;
|
||||
arma::mat inputData;
|
||||
if (!data::Load("vc2.csv", inputData))
|
||||
BOOST_FAIL("Unable to load train dataset vc2.csv!");
|
||||
FAIL("Unable to load train dataset vc2.csv!");
|
||||
|
||||
SetInputParam("input", std::move(inputData));
|
||||
SetInputParam("refined_start", true);
|
||||
@@ -102,7 +103,7 @@ BOOST_AUTO_TEST_CASE(RefinedStartPercentageTest)
|
||||
SetInputParam("percentage", std::move(P)); // Invalid
|
||||
|
||||
Log::Fatal.ignoreInput = true;
|
||||
BOOST_REQUIRE_THROW(mlpackMain(), std::runtime_error);
|
||||
REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error);
|
||||
Log::Fatal.ignoreInput = false;
|
||||
}
|
||||
|
||||
@@ -110,13 +111,14 @@ BOOST_AUTO_TEST_CASE(RefinedStartPercentageTest)
|
||||
/**
|
||||
* Checking percentage is non-negative when --refined_start is specified
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE(NonNegativePercentageTest)
|
||||
TEST_CASE_METHOD(KmTestFixture, "NonNegativePercentageTest",
|
||||
"[KmeansMainTest][BindingTests]")
|
||||
{
|
||||
int c = 2;
|
||||
double P = -1.0;
|
||||
arma::mat inputData;
|
||||
if (!data::Load("vc2.csv", inputData))
|
||||
BOOST_FAIL("Unable to load train dataset vc2.csv!");
|
||||
FAIL("Unable to load train dataset vc2.csv!");
|
||||
|
||||
SetInputParam("input", std::move(inputData));
|
||||
SetInputParam("refined_start", true);
|
||||
@@ -124,7 +126,7 @@ BOOST_AUTO_TEST_CASE(NonNegativePercentageTest)
|
||||
SetInputParam("percentage", P); // Invalid
|
||||
|
||||
Log::Fatal.ignoreInput = true;
|
||||
BOOST_REQUIRE_THROW(mlpackMain(), std::runtime_error);
|
||||
REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error);
|
||||
Log::Fatal.ignoreInput = false;
|
||||
}
|
||||
|
||||
@@ -132,12 +134,13 @@ BOOST_AUTO_TEST_CASE(NonNegativePercentageTest)
|
||||
/**
|
||||
* Checking that size and dimensionality of prediction is correct.
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE(KmClusteringSizeCheck)
|
||||
TEST_CASE_METHOD(KmTestFixture, "KmClusteringSizeCheck",
|
||||
"[KmeansMainTest][BindingTests]")
|
||||
{
|
||||
int c = 2;
|
||||
arma::mat inputData;
|
||||
if (!data::Load("vc2.csv", inputData))
|
||||
BOOST_FAIL("Unable to load train dataset vc2.csv!");
|
||||
FAIL("Unable to load train dataset vc2.csv!");
|
||||
|
||||
size_t col = inputData.n_cols;
|
||||
size_t row = inputData.n_rows;
|
||||
@@ -147,22 +150,23 @@ BOOST_AUTO_TEST_CASE(KmClusteringSizeCheck)
|
||||
|
||||
mlpackMain();
|
||||
|
||||
BOOST_REQUIRE_EQUAL(IO::GetParam<arma::mat>("output").n_rows, row+1);
|
||||
BOOST_REQUIRE_EQUAL(IO::GetParam<arma::mat>("output").n_cols, col);
|
||||
BOOST_REQUIRE_EQUAL(IO::GetParam<arma::mat>("centroid").n_rows, row);
|
||||
BOOST_REQUIRE_EQUAL(IO::GetParam<arma::mat>("centroid").n_cols, c);
|
||||
REQUIRE(IO::GetParam<arma::mat>("output").n_rows == row+1);
|
||||
REQUIRE(IO::GetParam<arma::mat>("output").n_cols == col);
|
||||
REQUIRE(IO::GetParam<arma::mat>("centroid").n_rows == row);
|
||||
REQUIRE(IO::GetParam<arma::mat>("centroid").n_cols == c);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checking that size and dimensionality of prediction is correct when --labels_only is specified
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE(KmClusteringSizeCheckLabelOnly)
|
||||
TEST_CASE_METHOD(KmTestFixture, "KmClusteringSizeCheckLabelOnly",
|
||||
"[KmeansMainTest][BindingTests]")
|
||||
{
|
||||
int c = 2;
|
||||
|
||||
arma::mat inputData;
|
||||
if (!data::Load("vc2.csv", inputData))
|
||||
BOOST_FAIL("Unable to load train dataset vc2.csv!");
|
||||
FAIL("Unable to load train dataset vc2.csv!");
|
||||
size_t col = inputData.n_cols;
|
||||
size_t row = inputData.n_rows;
|
||||
|
||||
@@ -172,24 +176,25 @@ BOOST_AUTO_TEST_CASE(KmClusteringSizeCheckLabelOnly)
|
||||
|
||||
mlpackMain();
|
||||
|
||||
BOOST_REQUIRE_EQUAL(IO::GetParam<arma::mat>("output").n_rows, 1);
|
||||
BOOST_REQUIRE_EQUAL(IO::GetParam<arma::mat>("output").n_cols, col);
|
||||
BOOST_REQUIRE_EQUAL(IO::GetParam<arma::mat>("centroid").n_rows, row);
|
||||
BOOST_REQUIRE_EQUAL(IO::GetParam<arma::mat>("centroid").n_cols, c);
|
||||
REQUIRE(IO::GetParam<arma::mat>("output").n_rows == 1);
|
||||
REQUIRE(IO::GetParam<arma::mat>("output").n_cols == col);
|
||||
REQUIRE(IO::GetParam<arma::mat>("centroid").n_rows == row);
|
||||
REQUIRE(IO::GetParam<arma::mat>("centroid").n_cols == c);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checking that predictions are not same when --allow_empty_clusters or kill_empty_clusters are specified
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE(KmClusteringEmptyClustersCheck)
|
||||
TEST_CASE_METHOD(KmTestFixture, "KmClusteringEmptyClustersCheck",
|
||||
"[KmeansMainTest][BindingTests]")
|
||||
{
|
||||
int c = 400;
|
||||
int iterations = 100;
|
||||
|
||||
arma::mat inputData;
|
||||
if (!data::Load("test_data_3_1000.csv", inputData))
|
||||
BOOST_FAIL("Unable to load train dataset test_data_3_1000.csv!");
|
||||
FAIL("Unable to load train dataset test_data_3_1000.csv!");
|
||||
arma::mat initCentroid = arma::randu<arma::mat>(inputData.n_rows, c);
|
||||
|
||||
SetInputParam("input", inputData);
|
||||
@@ -235,23 +240,24 @@ BOOST_AUTO_TEST_CASE(KmClusteringEmptyClustersCheck)
|
||||
|
||||
if (killEmptyOutput.n_elem == allowEmptyOutput.n_elem)
|
||||
{
|
||||
BOOST_REQUIRE_GT(arma::accu(killEmptyOutput != allowEmptyOutput), 1);
|
||||
BOOST_REQUIRE_GT(arma::accu(killEmptyOutput != normalOutput), 1);
|
||||
REQUIRE(arma::accu(killEmptyOutput != allowEmptyOutput) > 1);
|
||||
REQUIRE(arma::accu(killEmptyOutput != normalOutput) > 1);
|
||||
}
|
||||
BOOST_REQUIRE_GT(arma::accu(normalOutput != allowEmptyOutput), 1);
|
||||
REQUIRE(arma::accu(normalOutput != allowEmptyOutput) > 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checking that that size and dimensionality of Final Input File is correct
|
||||
* when flag --in_place is specified
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE(KmClusteringResultSizeCheck)
|
||||
TEST_CASE_METHOD(KmTestFixture, "KmClusteringResultSizeCheck",
|
||||
"[KmeansMainTest][BindingTests]")
|
||||
{
|
||||
int c = 2;
|
||||
|
||||
arma::mat inputData;
|
||||
if (!data::Load("vc2.csv", inputData))
|
||||
BOOST_FAIL("Unable to load train dataset vc2.csv!");
|
||||
FAIL("Unable to load train dataset vc2.csv!");
|
||||
|
||||
size_t row = inputData.n_rows;
|
||||
size_t col = inputData.n_cols;
|
||||
@@ -265,30 +271,32 @@ BOOST_AUTO_TEST_CASE(KmClusteringResultSizeCheck)
|
||||
// here input is actually accessed through output
|
||||
// due to a little trick in kmeans_main
|
||||
|
||||
BOOST_REQUIRE_EQUAL(processedInput.n_cols, col);
|
||||
BOOST_REQUIRE_EQUAL(processedInput.n_rows, row+1);
|
||||
REQUIRE(processedInput.n_cols == col);
|
||||
REQUIRE(processedInput.n_rows == row+1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensuring that absence of Number of Clusters is checked.
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE(KmClustersNotDefined)
|
||||
TEST_CASE_METHOD(KmTestFixture, "KmClustersNotDefined",
|
||||
"[KmeansMainTest][BindingTests]")
|
||||
{
|
||||
arma::mat inputData;
|
||||
if (!data::Load("vc2.csv", inputData))
|
||||
BOOST_FAIL("Unable to load train dataset vc2.csv!");
|
||||
FAIL("Unable to load train dataset vc2.csv!");
|
||||
|
||||
SetInputParam("input", std::move(inputData));
|
||||
|
||||
Log::Fatal.ignoreInput = true;
|
||||
BOOST_REQUIRE_THROW(mlpackMain(), std::runtime_error);
|
||||
REQUIRE_THROWS_AS(mlpackMain(), std::runtime_error);
|
||||
Log::Fatal.ignoreInput = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checking that all the algorithms yield same results
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE(AlgorithmsSimilarTest)
|
||||
TEST_CASE_METHOD(KmTestFixture, "AlgorithmsSimilarTest",
|
||||
"[KmeansMainTest][BindingTests]")
|
||||
{
|
||||
int c = 5;
|
||||
arma::mat inputData(10, 1000);
|
||||
@@ -393,5 +401,3 @@ BOOST_AUTO_TEST_CASE(AlgorithmsSimilarTest)
|
||||
CheckMatrices(naiveCentroid, dualTreeCentroid);
|
||||
CheckMatrices(naiveCentroid, dualCoverTreeCentroid);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END();
|
||||
|
||||
@@ -26,20 +26,17 @@
|
||||
#include <mlpack/methods/softmax_regression/softmax_regression.hpp>
|
||||
#include <ensmallen.hpp>
|
||||
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include "test_tools.hpp"
|
||||
#include "catch.hpp"
|
||||
|
||||
using namespace mlpack;
|
||||
using namespace mlpack::ann;
|
||||
using namespace ens;
|
||||
using namespace mlpack::regression;
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(RBMNetworkTest);
|
||||
|
||||
/*
|
||||
* Tests the BinaryRBM implementation on the Digits dataset.
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE(BinaryRBMClassificationTest)
|
||||
TEST_CASE("BinaryRBMClassificationTest", "[RBMNetworkTest]")
|
||||
{
|
||||
// Normalised dataset.
|
||||
int hiddenLayerSize = 100;
|
||||
@@ -84,7 +81,7 @@ BOOST_AUTO_TEST_CASE(BinaryRBMClassificationTest)
|
||||
double objVal = model.Train(msgd);
|
||||
|
||||
// Test that objective value returned by RBM::Train() is finite.
|
||||
BOOST_REQUIRE_EQUAL(std::isfinite(objVal), true);
|
||||
REQUIRE(std::isfinite(objVal) == true);
|
||||
|
||||
for (size_t i = 0; i < trainData.n_cols; ++i)
|
||||
{
|
||||
@@ -117,13 +114,13 @@ BOOST_AUTO_TEST_CASE(BinaryRBMClassificationTest)
|
||||
|
||||
// We allow a 6% tolerance because the RBM may not reconstruct samples as
|
||||
// well. (Typically it does, but we have no guarantee.)
|
||||
BOOST_REQUIRE_GE(rbmClassificationAccuracy, classificationAccuracy - 6.0);
|
||||
REQUIRE(rbmClassificationAccuracy >= classificationAccuracy - 6.0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Tests the SpikeSlabRBM implementation on the Digits dataset.
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE(ssRBMClassificationTest)
|
||||
TEST_CASE("ssRBMClassificationTest", "[RBMNetworkTest]")
|
||||
{
|
||||
size_t batchSize = 10;
|
||||
size_t numEpoches = 3;
|
||||
@@ -184,7 +181,7 @@ BOOST_AUTO_TEST_CASE(ssRBMClassificationTest)
|
||||
double objVal = modelssRBM.Train(msgd);
|
||||
|
||||
// Test that objective value returned by RBM::Train() is finite.
|
||||
BOOST_REQUIRE_EQUAL(std::isfinite(objVal), true);
|
||||
REQUIRE(std::isfinite(objVal) == true);
|
||||
|
||||
for (size_t i = 0; i < trainData.n_cols; ++i)
|
||||
{
|
||||
@@ -211,7 +208,7 @@ BOOST_AUTO_TEST_CASE(ssRBMClassificationTest)
|
||||
// omitted here for speed. We add a margin of 3% since ssRBM isn't guaranteed
|
||||
// to give us better results (we just generally expect it to be about as good
|
||||
// or better).
|
||||
BOOST_REQUIRE_GE(ssRbmClassificationAccuracy, 76.18 - 3.0);
|
||||
REQUIRE(ssRbmClassificationAccuracy >= 76.18 - 3.0);
|
||||
}
|
||||
|
||||
template<typename MatType = arma::mat>
|
||||
@@ -239,13 +236,13 @@ void BuildVanillaNetwork(MatType& trainData,
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < freeEnergy.n_elem; ++i)
|
||||
BOOST_REQUIRE_CLOSE(calculatedFreeEnergy(i), freeEnergy(i), 1e-3);
|
||||
REQUIRE(calculatedFreeEnergy(i) == Approx(freeEnergy(i)).epsilon(1e-5));
|
||||
}
|
||||
|
||||
/*
|
||||
* Train and evaluate a Vanilla network with the specified structure.
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE(MiscTest)
|
||||
TEST_CASE("MiscTest", "[RBMNetworkTest]")
|
||||
{
|
||||
arma::Mat<float> X = arma::Mat<float>("0.0, 0.0, 0.0;"
|
||||
"0.0, 1.0, 1.0;"
|
||||
@@ -254,5 +251,3 @@ BOOST_AUTO_TEST_CASE(MiscTest)
|
||||
X = X.t();
|
||||
BuildVanillaNetwork<arma::Mat<float>>(X, 2);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END();
|
||||
|
||||
@@ -19,9 +19,8 @@
|
||||
#include <mlpack/core/data/binarize.hpp>
|
||||
#include <mlpack/core/math/random.hpp>
|
||||
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include "test_tools.hpp"
|
||||
#include "serialization.hpp"
|
||||
#include "catch.hpp"
|
||||
#include "serialization_catch.hpp"
|
||||
#include "custom_layer.hpp"
|
||||
|
||||
using namespace mlpack;
|
||||
@@ -29,8 +28,6 @@ using namespace mlpack::ann;
|
||||
using namespace ens;
|
||||
using namespace mlpack::math;
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(RecurrentNetworkTest);
|
||||
|
||||
/**
|
||||
* Construct a 2-class dataset out of noisy sines.
|
||||
*
|
||||
@@ -75,7 +72,7 @@ void GenerateNoisySines(arma::cube& data,
|
||||
/**
|
||||
* Train the BRNN on a larger dataset.
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE(SequenceClassificationBRNNTest)
|
||||
TEST_CASE("SequenceClassificationBRNNTest", "[RecurrentNetworkTest]")
|
||||
{
|
||||
// Using same test for RNN below.
|
||||
size_t successes = 0;
|
||||
@@ -111,10 +108,10 @@ BOOST_AUTO_TEST_CASE(SequenceClassificationBRNNTest)
|
||||
|
||||
StandardSGD opt(0.1, 1, 500 * input.n_cols, -100);
|
||||
model.Train(input, labels, opt);
|
||||
BOOST_TEST_CHECKPOINT("Training over");
|
||||
INFO("Training over");
|
||||
arma::cube prediction;
|
||||
model.Predict(input, prediction);
|
||||
BOOST_TEST_CHECKPOINT("Prediction over");
|
||||
INFO("Prediction over");
|
||||
|
||||
size_t error = 0;
|
||||
for (size_t i = 0; i < prediction.n_cols; ++i)
|
||||
@@ -133,7 +130,7 @@ BOOST_AUTO_TEST_CASE(SequenceClassificationBRNNTest)
|
||||
}
|
||||
|
||||
double classificationError = 1 - double(error) / prediction.n_cols;
|
||||
BOOST_TEST_CHECKPOINT(classificationError);
|
||||
INFO(classificationError);
|
||||
if (classificationError <= 0.2)
|
||||
{
|
||||
++successes;
|
||||
@@ -141,13 +138,13 @@ BOOST_AUTO_TEST_CASE(SequenceClassificationBRNNTest)
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_REQUIRE_GE(successes, 1);
|
||||
REQUIRE(successes >= 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Train the vanilla network on a larger dataset.
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE(SequenceClassificationTest)
|
||||
TEST_CASE("SequenceClassificationTest", "[RecurrentNetworkTest]")
|
||||
{
|
||||
// It isn't guaranteed that the recurrent network will converge in the
|
||||
// specified number of iterations using random weights. If this works 1 of 6
|
||||
@@ -231,7 +228,7 @@ BOOST_AUTO_TEST_CASE(SequenceClassificationTest)
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_REQUIRE_GE(successes, 1);
|
||||
REQUIRE(successes >= 1);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -645,13 +642,13 @@ void ReberGrammarTestNetwork(ModelType& model,
|
||||
offset += 3;
|
||||
}
|
||||
|
||||
BOOST_REQUIRE_GE(successes, 1);
|
||||
REQUIRE(successes >= 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Train the specified networks on an embedded Reber grammar dataset.
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE(LSTMReberGrammarTest)
|
||||
TEST_CASE("LSTMReberGrammarTest", "[RecurrentNetworkTest]")
|
||||
{
|
||||
RNN<MeanSquaredError<> > model(5);
|
||||
model.Add<Linear<> >(7, 10);
|
||||
@@ -664,7 +661,7 @@ BOOST_AUTO_TEST_CASE(LSTMReberGrammarTest)
|
||||
/**
|
||||
* Train the specified networks on an embedded Reber grammar dataset.
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE(FastLSTMReberGrammarTest)
|
||||
TEST_CASE("FastLSTMReberGrammarTest", "[RecurrentNetworkTest]")
|
||||
{
|
||||
RNN<MeanSquaredError<> > model(5);
|
||||
model.Add<Linear<> >(7, 8);
|
||||
@@ -677,7 +674,7 @@ BOOST_AUTO_TEST_CASE(FastLSTMReberGrammarTest)
|
||||
/**
|
||||
* Train the specified networks on an embedded Reber grammar dataset.
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE(GRURecursiveReberGrammarTest)
|
||||
TEST_CASE("GRURecursiveReberGrammarTest", "[RecurrentNetworkTest]")
|
||||
{
|
||||
RNN<MeanSquaredError<> > model(5);
|
||||
model.Add<Linear<> >(7, 16);
|
||||
@@ -690,7 +687,7 @@ BOOST_AUTO_TEST_CASE(GRURecursiveReberGrammarTest)
|
||||
/**
|
||||
* Train BLSTM on an embedded Reber grammar dataset.
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE(BRNNReberGrammarTest)
|
||||
TEST_CASE("BRNNReberGrammarTest", "[RecurrentNetworkTest]")
|
||||
{
|
||||
BRNN<MeanSquaredError<>, AddMerge<>, SigmoidLayer<> > model(5);
|
||||
model.Add<Linear<> >(7, 10);
|
||||
@@ -869,14 +866,14 @@ void DistractedSequenceRecallTestNetwork(
|
||||
offset += 2;
|
||||
}
|
||||
|
||||
BOOST_REQUIRE_GE(successes, 1);
|
||||
REQUIRE(successes >= 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Train the specified networks on the Derek D. Monner's distracted sequence
|
||||
* recall task.
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE(LSTMDistractedSequenceRecallTest)
|
||||
TEST_CASE("LSTMDistractedSequenceRecallTest", "[RecurrentNetworkTest]")
|
||||
{
|
||||
DistractedSequenceRecallTestNetwork<LSTM<> >(4, 8);
|
||||
}
|
||||
@@ -885,7 +882,7 @@ BOOST_AUTO_TEST_CASE(LSTMDistractedSequenceRecallTest)
|
||||
* Train the specified networks on the Derek D. Monner's distracted sequence
|
||||
* recall task.
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE(FastLSTMDistractedSequenceRecallTest)
|
||||
TEST_CASE("FastLSTMDistractedSequenceRecallTest", "[RecurrentNetworkTest]")
|
||||
{
|
||||
DistractedSequenceRecallTestNetwork<FastLSTM<> >(4, 8);
|
||||
}
|
||||
@@ -894,7 +891,7 @@ BOOST_AUTO_TEST_CASE(FastLSTMDistractedSequenceRecallTest)
|
||||
* Train the specified networks on the Derek D. Monner's distracted sequence
|
||||
* recall task.
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE(GRUDistractedSequenceRecallTest)
|
||||
TEST_CASE("GRUDistractedSequenceRecallTest", "[RecurrentNetworkTest]")
|
||||
{
|
||||
DistractedSequenceRecallTestNetwork<GRU<> >(4, 8);
|
||||
}
|
||||
@@ -956,7 +953,7 @@ void BatchSizeTest()
|
||||
/**
|
||||
* Ensure LSTMs work with larger batch sizes.
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE(LSTMBatchSizeTest)
|
||||
TEST_CASE("LSTMBatchSizeTest", "[RecurrentNetworkTest]")
|
||||
{
|
||||
BatchSizeTest<LSTM<>>();
|
||||
}
|
||||
@@ -964,7 +961,7 @@ BOOST_AUTO_TEST_CASE(LSTMBatchSizeTest)
|
||||
/**
|
||||
* Ensure fast LSTMs work with larger batch sizes.
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE(FastLSTMBatchSizeTest)
|
||||
TEST_CASE("FastLSTMBatchSizeTest", "[RecurrentNetworkTest]")
|
||||
{
|
||||
BatchSizeTest<FastLSTM<>>();
|
||||
}
|
||||
@@ -972,7 +969,7 @@ BOOST_AUTO_TEST_CASE(FastLSTMBatchSizeTest)
|
||||
/**
|
||||
* Ensure GRUs work with larger batch sizes.
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE(GRUBatchSizeTest)
|
||||
TEST_CASE("GRUBatchSizeTest", "[RecurrentNetworkTest]")
|
||||
{
|
||||
BatchSizeTest<GRU<>>();
|
||||
}
|
||||
@@ -980,7 +977,7 @@ BOOST_AUTO_TEST_CASE(GRUBatchSizeTest)
|
||||
/**
|
||||
* Make sure the RNN can be properly serialized.
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE(SerializationTest)
|
||||
TEST_CASE("RNNSerializationTest", "[RecurrentNetworkTest]")
|
||||
{
|
||||
const size_t rho = 10;
|
||||
|
||||
@@ -1172,13 +1169,13 @@ void ReberGrammarTestCustomNetwork(const size_t hiddenSize = 4,
|
||||
offset += 3;
|
||||
}
|
||||
|
||||
BOOST_REQUIRE_GE(successes, 1);
|
||||
REQUIRE(successes >= 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Train the specified networks on an embedded Reber grammar dataset.
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE(CustomRecursiveReberGrammarTest)
|
||||
TEST_CASE("CustomRecursiveReberGrammarTest", "[RecurrentNetworkTest]")
|
||||
{
|
||||
ReberGrammarTestCustomNetwork(16, true);
|
||||
}
|
||||
@@ -1312,16 +1309,16 @@ double RNNSineTest(size_t hiddenUnits, size_t rho, size_t numEpochs = 100)
|
||||
/**
|
||||
* Test RNN using multiple timestep input and single output.
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE(MultiTimestepTest)
|
||||
TEST_CASE("MultiTimestepTest", "[RecurrentNetworkTest]")
|
||||
{
|
||||
double err = RNNSineTest(4, 10, 20);
|
||||
BOOST_REQUIRE_LE(err, 0.025);
|
||||
REQUIRE(err <= 0.025);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that RNN::Train() returns finite objective value.
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE(RNNTrainReturnObjective)
|
||||
TEST_CASE("RNNTrainReturnObjective", "[RecurrentNetworkTest]")
|
||||
{
|
||||
const size_t rho = 10;
|
||||
|
||||
@@ -1371,13 +1368,13 @@ BOOST_AUTO_TEST_CASE(RNNTrainReturnObjective)
|
||||
StandardSGD opt(0.1, 1, input.n_cols /* 1 epoch */, -100);
|
||||
double objVal = model.Train(input, labels, opt);
|
||||
|
||||
BOOST_REQUIRE_EQUAL(std::isfinite(objVal), true);
|
||||
REQUIRE(std::isfinite(objVal) == true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that BRNN::Train() returns finite objective value.
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE(BRNNTrainReturnObjective)
|
||||
TEST_CASE("BRNNTrainReturnObjective", "[RecurrentNetworkTest]")
|
||||
{
|
||||
const size_t rho = 10;
|
||||
|
||||
@@ -1407,16 +1404,16 @@ BOOST_AUTO_TEST_CASE(BRNNTrainReturnObjective)
|
||||
|
||||
StandardSGD opt(0.1, 1, 500 * input.n_cols, -100);
|
||||
double objVal = model.Train(input, labels, opt);
|
||||
BOOST_TEST_CHECKPOINT("Training over");
|
||||
INFO("Training over");
|
||||
|
||||
// Test that BRNN::Train() returns finite objective value.
|
||||
BOOST_REQUIRE_EQUAL(std::isfinite(objVal), true);
|
||||
REQUIRE(std::isfinite(objVal) == true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that RNN::Train() does not give an error for large rho.
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE(LargeRhoValueRnnTest)
|
||||
TEST_CASE("LargeRhoValueRnnTest", "[RecurrentNetworkTest]")
|
||||
{
|
||||
// Setting rho value greater than sequence length which is 17.
|
||||
const size_t rho = 100;
|
||||
@@ -1473,7 +1470,5 @@ BOOST_AUTO_TEST_CASE(LargeRhoValueRnnTest)
|
||||
}
|
||||
ens::SGD<> opt(0.01, 1, 100);
|
||||
model.Train(inputs[0], targets[0], opt);
|
||||
BOOST_TEST_CHECKPOINT("Training over");
|
||||
INFO("Training over");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END();
|
||||
|
||||
Reference in New Issue
Block a user