@@ -5,7 +5,9 @@ set(SOURCES
|
||||
cli_option.hpp
|
||||
default_param.hpp
|
||||
default_param_impl.hpp
|
||||
delete_allocated_memory.hpp
|
||||
end_program.hpp
|
||||
get_allocated_memory.hpp
|
||||
get_param.hpp
|
||||
get_raw_param.hpp
|
||||
get_printable_param.hpp
|
||||
|
||||
@@ -89,13 +89,15 @@ void AddToPO(const util::ParamData& d,
|
||||
(boost::program_options::options_description*) output;
|
||||
|
||||
// Generate the name to be given to boost::program_options.
|
||||
const std::string mappedName = MapParameterName<T>(d.name);
|
||||
const std::string mappedName =
|
||||
MapParameterName<typename std::remove_pointer<T>::type>(d.name);
|
||||
std::string boostName = (d.alias != '\0') ? mappedName + "," +
|
||||
std::string(1, d.alias) : mappedName;
|
||||
|
||||
// Note that we have to add the option as type equal to the mapped type, not
|
||||
// the true type of the option.
|
||||
AddToPO<typename ParameterType<T>::type>(boostName, d.desc, *desc);
|
||||
AddToPO<typename ParameterType<typename std::remove_pointer<T>::type>::type>(
|
||||
boostName, d.desc, *desc);
|
||||
}
|
||||
|
||||
} // namespace cli
|
||||
|
||||
@@ -28,6 +28,8 @@
|
||||
#include "set_param.hpp"
|
||||
#include "get_printable_param_name.hpp"
|
||||
#include "get_printable_param_value.hpp"
|
||||
#include "get_allocated_memory.hpp"
|
||||
#include "delete_allocated_memory.hpp"
|
||||
|
||||
namespace mlpack {
|
||||
namespace bindings {
|
||||
@@ -88,19 +90,21 @@ class CLIOption
|
||||
data.cppType = cppName;
|
||||
|
||||
// Apply default value.
|
||||
if (std::is_same<N, typename ParameterType<N>::type>::value)
|
||||
if (std::is_same<typename std::remove_pointer<N>::type,
|
||||
typename ParameterType<typename
|
||||
std::remove_pointer<N>::type>::type>::value)
|
||||
{
|
||||
data.value = boost::any(defaultValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
typename ParameterType<N>::type tmp;
|
||||
data.value = boost::any(std::tuple<N, typename ParameterType<N>::type>(
|
||||
defaultValue, tmp));
|
||||
typename ParameterType<typename std::remove_pointer<N>::type>::type tmp;
|
||||
data.value = boost::any(std::tuple<N, decltype(tmp)>(defaultValue, tmp));
|
||||
}
|
||||
|
||||
const std::string tname = data.tname;
|
||||
const std::string boostName = MapParameterName<N>(identifier);
|
||||
const std::string boostName = MapParameterName<
|
||||
typename std::remove_pointer<N>::type>(identifier);
|
||||
std::string progOptId = (alias[0] != '\0') ? boostName + ","
|
||||
+ std::string(1, alias[0]) : boostName;
|
||||
|
||||
@@ -152,6 +156,10 @@ class CLIOption
|
||||
&GetPrintableParamName<N>;
|
||||
CLI::GetSingleton().functionMap[tname]["GetPrintableParamValue"] =
|
||||
&GetPrintableParamValue<N>;
|
||||
CLI::GetSingleton().functionMap[tname]["GetAllocatedMemory"] =
|
||||
&GetAllocatedMemory<N>;
|
||||
CLI::GetSingleton().functionMap[tname]["DeleteAllocatedMemory"] =
|
||||
&DeleteAllocatedMemory<N>;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -54,10 +54,19 @@ std::string DefaultParamImpl(
|
||||
const util::ParamData& data,
|
||||
const typename boost::enable_if_c<
|
||||
arma::is_arma_type<T>::value ||
|
||||
data::HasSerialize<T>::value ||
|
||||
std::is_same<T, std::tuple<mlpack::data::DatasetInfo,
|
||||
arma::mat>>::value>::type* /* junk */ = 0);
|
||||
|
||||
/**
|
||||
* Return the default value of a model option (this returns the default
|
||||
* filename, or '' if the default is no file).
|
||||
*/
|
||||
template<typename T>
|
||||
std::string DefaultParamImpl(
|
||||
const util::ParamData& data,
|
||||
const typename boost::disable_if<arma::is_arma_type<T>>::type* = 0,
|
||||
const typename boost::enable_if<data::HasSerialize<T>>::type* = 0);
|
||||
|
||||
/**
|
||||
* Return the default value of an option. This is the function that will be
|
||||
* placed into the CLI functionMap.
|
||||
@@ -68,7 +77,7 @@ void DefaultParam(const util::ParamData& data,
|
||||
void* output)
|
||||
{
|
||||
std::string* outstr = (std::string*) output;
|
||||
*outstr = DefaultParamImpl<T>(data);
|
||||
*outstr = DefaultParamImpl<typename std::remove_pointer<T>::type>(data);
|
||||
}
|
||||
|
||||
} // namespace cli
|
||||
|
||||
@@ -70,7 +70,6 @@ std::string DefaultParamImpl(
|
||||
const util::ParamData& data,
|
||||
const typename boost::enable_if_c<
|
||||
arma::is_arma_type<T>::value ||
|
||||
data::HasSerialize<T>::value ||
|
||||
std::is_same<T, std::tuple<mlpack::data::DatasetInfo,
|
||||
arma::mat>>::value>::type* /* junk */)
|
||||
{
|
||||
@@ -81,6 +80,24 @@ std::string DefaultParamImpl(
|
||||
return "'" + filename + "'";
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the default value of a model option (this returns the default
|
||||
* filename, or '' if the default is no file).
|
||||
*/
|
||||
template<typename T>
|
||||
std::string DefaultParamImpl(
|
||||
const util::ParamData& data,
|
||||
const typename boost::disable_if<arma::is_arma_type<T>>::type* /* junk */,
|
||||
const typename boost::enable_if<data::HasSerialize<T>>::type* /* junk */)
|
||||
{
|
||||
// Get the filename and return it, or return an empty string.
|
||||
typedef std::tuple<T*, std::string> TupleType;
|
||||
const TupleType& tuple = *boost::any_cast<TupleType>(&data.value);
|
||||
const std::string& filename = std::get<1>(tuple);
|
||||
return "'" + filename + "'";
|
||||
}
|
||||
|
||||
|
||||
} // namespace cli
|
||||
} // namespace bindings
|
||||
} // namespace mlpack
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
/**
|
||||
* @file delete_allocated_memory.hpp
|
||||
* @author Ryan Curtin
|
||||
*
|
||||
* If any memory has been allocated by the parameter, delete it.
|
||||
*/
|
||||
#ifndef MLPACK_BINDINGS_CLI_DELETE_ALLOCATED_MEMORY_HPP
|
||||
#define MLPACK_BINDINGS_CLI_DELETE_ALLOCATED_MEMORY_HPP
|
||||
|
||||
#include <mlpack/core/util/param_data.hpp>
|
||||
|
||||
namespace mlpack {
|
||||
namespace bindings {
|
||||
namespace cli {
|
||||
|
||||
template<typename T>
|
||||
void DeleteAllocatedMemoryImpl(
|
||||
const util::ParamData& /* d */,
|
||||
const typename boost::disable_if<data::HasSerialize<T>>::type* = 0,
|
||||
const typename boost::disable_if<arma::is_arma_type<T>>::type* = 0)
|
||||
{
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void DeleteAllocatedMemoryImpl(
|
||||
const util::ParamData& /* d */,
|
||||
const typename boost::enable_if<arma::is_arma_type<T>>::type* = 0)
|
||||
{
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void DeleteAllocatedMemoryImpl(
|
||||
const util::ParamData& d,
|
||||
const typename boost::disable_if<arma::is_arma_type<T>>::type* = 0,
|
||||
const typename boost::enable_if<data::HasSerialize<T>>::type* = 0)
|
||||
{
|
||||
// Delete the allocated memory (hopefully we actually own it).
|
||||
typedef std::tuple<T*, std::string> TupleType;
|
||||
delete std::get<0>(*boost::any_cast<TupleType>(&d.value));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void DeleteAllocatedMemory(
|
||||
const util::ParamData& d,
|
||||
const void* /* input */,
|
||||
void* /* output */)
|
||||
{
|
||||
DeleteAllocatedMemoryImpl<typename std::remove_pointer<T>::type>(d);
|
||||
}
|
||||
|
||||
} // namespace cli
|
||||
} // namespace bindings
|
||||
} // namespace mlpack
|
||||
|
||||
#endif
|
||||
@@ -67,6 +67,37 @@ inline void EndProgram()
|
||||
CLI::GetSingleton().timer.PrintTimer(it2.first);
|
||||
}
|
||||
}
|
||||
|
||||
// Lastly clean up any memory. If we are holding any pointers, then we "own"
|
||||
// them. But we may hold the same pointer twice, so we have to be careful to
|
||||
// not delete it multiple times.
|
||||
std::unordered_map<void*, const util::ParamData*> memoryAddresses;
|
||||
it = parameters.begin();
|
||||
while (it != parameters.end())
|
||||
{
|
||||
const util::ParamData& data = it->second;
|
||||
|
||||
void* result;
|
||||
CLI::GetSingleton().functionMap[data.tname]["GetAllocatedMemory"](data,
|
||||
NULL, (void*) &result);
|
||||
if (result != NULL && memoryAddresses.count(result) == 0)
|
||||
memoryAddresses[result] = &data;
|
||||
|
||||
++it;
|
||||
}
|
||||
|
||||
// Now we have all the unique addresses that need to be deleted.
|
||||
std::unordered_map<void*, const util::ParamData*>::const_iterator it2;
|
||||
it2 = memoryAddresses.begin();
|
||||
while (it2 != memoryAddresses.end())
|
||||
{
|
||||
const util::ParamData& data = *(it2->second);
|
||||
|
||||
CLI::GetSingleton().functionMap[data.tname]["DeleteAllocatedMemory"](data,
|
||||
NULL, NULL);
|
||||
|
||||
++it2;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace cli
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
/**
|
||||
* @file get_allocated_memory.hpp
|
||||
* @author Ryan Curtin
|
||||
*
|
||||
* If the parameter has a type that may need to be deleted, return the address
|
||||
* of that object. Otherwise return NULL.
|
||||
*/
|
||||
#ifndef MLPACK_BINDINGS_CLI_GET_ALLOCATED_MEMORY_HPP
|
||||
#define MLPACK_BINDINGS_CLI_GET_ALLOCATED_MEMORY_HPP
|
||||
|
||||
#include <mlpack/core/util/param_data.hpp>
|
||||
|
||||
namespace mlpack {
|
||||
namespace bindings {
|
||||
namespace cli {
|
||||
|
||||
template<typename T>
|
||||
void* GetAllocatedMemory(
|
||||
const util::ParamData& /* d */,
|
||||
const typename boost::disable_if<data::HasSerialize<T>>::type* = 0,
|
||||
const typename boost::disable_if<arma::is_arma_type<T>>::type* = 0)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void* GetAllocatedMemory(
|
||||
const util::ParamData& /* d */,
|
||||
const typename boost::enable_if<arma::is_arma_type<T>>::type* = 0)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void* GetAllocatedMemory(
|
||||
const util::ParamData& d,
|
||||
const typename boost::disable_if<arma::is_arma_type<T>>::type* = 0,
|
||||
const typename boost::enable_if<data::HasSerialize<T>>::type* = 0)
|
||||
{
|
||||
// Here we have a model, which is a tuple, and we need the address of the
|
||||
// memory.
|
||||
typedef std::tuple<T*, std::string> TupleType;
|
||||
return std::get<0>(*boost::any_cast<TupleType>(&d.value));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void GetAllocatedMemory(const util::ParamData& d,
|
||||
const void* /* input */,
|
||||
void* output)
|
||||
{
|
||||
*((void**) output) =
|
||||
GetAllocatedMemory<typename std::remove_pointer<T>::type>(d);
|
||||
}
|
||||
|
||||
} // namespace cli
|
||||
} // namespace bindings
|
||||
} // namespace mlpack
|
||||
|
||||
#endif
|
||||
@@ -95,24 +95,24 @@ T& GetParam(
|
||||
* @param d ParamData object to get parameter value from.
|
||||
*/
|
||||
template<typename T>
|
||||
T& GetParam(
|
||||
T*& GetParam(
|
||||
util::ParamData& d,
|
||||
const typename boost::disable_if<arma::is_arma_type<T>>::type* = 0,
|
||||
const typename boost::enable_if<data::HasSerialize<T>>::type* = 0)
|
||||
{
|
||||
// If the model is an input model, we have to load it from file. 'value'
|
||||
// contains the filename.
|
||||
typedef std::tuple<T, std::string> TupleType;
|
||||
typedef std::tuple<T*, std::string> TupleType;
|
||||
TupleType* tuple = boost::any_cast<TupleType>(&d.value);
|
||||
const std::string& value = std::get<1>(*tuple);
|
||||
T& model = std::get<0>(*tuple);
|
||||
if (d.input && !d.loaded)
|
||||
{
|
||||
data::Load(value, "model", model, true);
|
||||
T* model = new T();
|
||||
data::Load(value, "model", *model, true);
|
||||
d.loaded = true;
|
||||
std::get<0>(*tuple) = model;
|
||||
}
|
||||
|
||||
return model;
|
||||
return std::get<0>(*tuple);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -127,7 +127,8 @@ template<typename T>
|
||||
void GetParam(const util::ParamData& d, const void* /* input */, void* output)
|
||||
{
|
||||
// Cast to the correct type.
|
||||
*((T**) output) = &GetParam<T>(const_cast<util::ParamData&>(d));
|
||||
*((T**) output) = &GetParam<typename std::remove_pointer<T>::type>(
|
||||
const_cast<util::ParamData&>(d));
|
||||
}
|
||||
|
||||
} // namespace cli
|
||||
|
||||
@@ -37,16 +37,24 @@ std::string GetPrintableParam(
|
||||
const typename std::enable_if<util::IsStdVector<T>::value>::type* = 0);
|
||||
|
||||
/**
|
||||
* Print a matrix option (this just prints the filename).
|
||||
* Print a matrix/tuple option (this just prints the filename).
|
||||
*/
|
||||
template<typename T>
|
||||
std::string GetPrintableParam(
|
||||
const util::ParamData& data,
|
||||
const typename std::enable_if<arma::is_arma_type<T>::value ||
|
||||
data::HasSerialize<T>::value ||
|
||||
std::is_same<T,
|
||||
std::tuple<data::DatasetInfo, arma::mat>>::value>::type* = 0);
|
||||
|
||||
/**
|
||||
* Print a model option (this just prints the filename).
|
||||
*/
|
||||
template<typename T>
|
||||
std::string GetPrintableParam(
|
||||
const util::ParamData& data,
|
||||
const typename boost::disable_if<arma::is_arma_type<T>>::type* = 0,
|
||||
const typename boost::enable_if<data::HasSerialize<T>>::type* = 0);
|
||||
|
||||
/**
|
||||
* Print an option into a std::string. This should print a short, one-line
|
||||
* representation of the object. The string will be stored in the output
|
||||
@@ -57,7 +65,8 @@ void GetPrintableParam(const util::ParamData& data,
|
||||
const void* /* input */,
|
||||
void* output)
|
||||
{
|
||||
*((std::string*) output) = GetPrintableParam<T>(data);
|
||||
*((std::string*) output) =
|
||||
GetPrintableParam<typename std::remove_pointer<T>::type>(data);
|
||||
}
|
||||
|
||||
} // namespace cli
|
||||
|
||||
@@ -43,12 +43,11 @@ std::string GetPrintableParam(
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
//! Print a matrix/model/tuple option (this just prints the filename).
|
||||
//! Print a matrix/tuple option (this just prints the filename).
|
||||
template<typename T>
|
||||
std::string GetPrintableParam(
|
||||
const util::ParamData& data,
|
||||
const typename std::enable_if<arma::is_arma_type<T>::value ||
|
||||
data::HasSerialize<T>::value ||
|
||||
std::is_same<T,
|
||||
std::tuple<data::DatasetInfo, arma::mat>>::value>::type* /* junk */)
|
||||
{
|
||||
@@ -61,6 +60,22 @@ std::string GetPrintableParam(
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
//! Print a model option (this just prints the filename).
|
||||
template<typename T>
|
||||
std::string GetPrintableParam(
|
||||
const util::ParamData& data,
|
||||
const typename boost::disable_if<arma::is_arma_type<T>>::type* /* junk */,
|
||||
const typename boost::enable_if<data::HasSerialize<T>>::type* /* junk */)
|
||||
{
|
||||
// Extract the string from the tuple that's being held.
|
||||
typedef std::tuple<T*, typename ParameterType<T>::type> TupleType;
|
||||
const TupleType* tuple = boost::any_cast<TupleType>(&data.value);
|
||||
|
||||
std::ostringstream oss;
|
||||
oss << std::get<1>(*tuple);
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
} // namespace cli
|
||||
} // namespace bindings
|
||||
} // namespace mlpack
|
||||
|
||||
@@ -64,7 +64,8 @@ void GetPrintableParamName(
|
||||
const void* /* input */,
|
||||
void* output)
|
||||
{
|
||||
*((std::string*) output) = GetPrintableParamName<T>(d);
|
||||
*((std::string*) output) =
|
||||
GetPrintableParamName<typename std::remove_pointer<T>::type>(d);
|
||||
}
|
||||
|
||||
} // namespace cli
|
||||
|
||||
@@ -68,7 +68,8 @@ void GetPrintableParamValue(
|
||||
const void* input,
|
||||
void* output)
|
||||
{
|
||||
*((std::string*) output) = GetPrintableParamValue<T>(d,
|
||||
*((std::string*) output) =
|
||||
GetPrintableParamValue<typename std::remove_pointer<T>::type>(d,
|
||||
*((std::string*) input));
|
||||
}
|
||||
|
||||
|
||||
@@ -40,15 +40,29 @@ T& GetRawParam(
|
||||
const typename boost::enable_if_c<
|
||||
arma::is_arma_type<T>::value ||
|
||||
std::is_same<T, std::tuple<mlpack::data::DatasetInfo,
|
||||
arma::mat>>::value ||
|
||||
data::HasSerialize<T>::value>::type* = 0)
|
||||
arma::mat>>::value>::type* = 0)
|
||||
{
|
||||
// Don't load the matrix/model.
|
||||
// Don't load the matrix.
|
||||
typedef std::tuple<T, std::string> TupleType;
|
||||
T& value = std::get<0>(*boost::any_cast<TupleType>(&d.value));
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the name of a model parameter.
|
||||
*/
|
||||
template<typename T>
|
||||
T*& GetRawParam(
|
||||
util::ParamData& d,
|
||||
const typename boost::disable_if<arma::is_arma_type<T>>::type* = 0,
|
||||
const typename boost::enable_if<data::HasSerialize<T>>::type* = 0)
|
||||
{
|
||||
// Don't load the model.
|
||||
typedef std::tuple<T*, std::string> TupleType;
|
||||
T*& value = std::get<0>(*boost::any_cast<TupleType>(&d.value));
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a parameter casted to the given type. Type checking does not happen
|
||||
* here!
|
||||
@@ -63,7 +77,8 @@ void GetRawParam(const util::ParamData& d,
|
||||
void* output)
|
||||
{
|
||||
// Cast to the correct type.
|
||||
*((T**) output) = &GetRawParam<T>(const_cast<util::ParamData&>(d));
|
||||
*((T**) output) = &GetRawParam<typename std::remove_pointer<T>::type>(
|
||||
const_cast<util::ParamData&>(d));
|
||||
}
|
||||
|
||||
} // namespace cli
|
||||
|
||||
@@ -61,7 +61,8 @@ void MapParameterName(const util::ParamData& d,
|
||||
{
|
||||
// Store the mapped name in the output pointer, which is actually a string
|
||||
// pointer.
|
||||
*((std::string*) output) = MapParameterName<T>(d.name);
|
||||
*((std::string*) output) =
|
||||
MapParameterName<typename std::remove_pointer<T>::type>(d.name);
|
||||
}
|
||||
|
||||
} // namespace cli
|
||||
|
||||
@@ -70,7 +70,7 @@ void OutputParam(const util::ParamData& data,
|
||||
const void* /* input */,
|
||||
void* /* output */)
|
||||
{
|
||||
OutputParamImpl<T>(data);
|
||||
OutputParamImpl<typename std::remove_pointer<T>::type>(data);
|
||||
}
|
||||
|
||||
} // namespace cli
|
||||
|
||||
@@ -55,10 +55,10 @@ void OutputParamImpl(
|
||||
|
||||
if (output.n_elem > 0 && filename != "")
|
||||
{
|
||||
if (arma::is_Row<T>::value || arma::is_Col<T>::value)
|
||||
data::Save(filename, output, false);
|
||||
else
|
||||
data::Save(filename, output, false, !data.noTranspose);
|
||||
if (arma::is_Row<T>::value || arma::is_Col<T>::value)
|
||||
data::Save(filename, output, false);
|
||||
else
|
||||
data::Save(filename, output, false, !data.noTranspose);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,14 +72,14 @@ void OutputParamImpl(
|
||||
// The const cast is necessary here because Serialize() can't ever be marked
|
||||
// const. In this case we can assume it though, since we will be saving and
|
||||
// not loading.
|
||||
typedef std::tuple<T, std::string> TupleType;
|
||||
T& output = const_cast<T&>(std::get<0>(*boost::any_cast<TupleType>(
|
||||
typedef std::tuple<T*, std::string> TupleType;
|
||||
T*& output = const_cast<T*&>(std::get<0>(*boost::any_cast<TupleType>(
|
||||
&data.value)));
|
||||
const std::string& filename =
|
||||
std::get<1>(*boost::any_cast<TupleType>(&data.value));
|
||||
|
||||
if (filename != "")
|
||||
data::Save(filename, "model", output);
|
||||
data::Save(filename, "model", *output);
|
||||
}
|
||||
|
||||
//! Output a mapped dataset.
|
||||
|
||||
@@ -52,7 +52,7 @@ void ParseCommandLine(int argc, char** argv)
|
||||
boostNameMap[boostName] = d.name;
|
||||
}
|
||||
|
||||
// TODO: we have to mark somehow that we parsed.
|
||||
// Mark that we did parsing.
|
||||
CLI::GetSingleton().didParse = true;
|
||||
|
||||
// Parse the command line, then place the values in the right place.
|
||||
|
||||
@@ -54,7 +54,6 @@ void SetParam(
|
||||
util::ParamData& d,
|
||||
const boost::any& value,
|
||||
const typename std::enable_if<arma::is_arma_type<T>::value ||
|
||||
data::HasSerialize<T>::value ||
|
||||
std::is_same<T,
|
||||
std::tuple<data::DatasetInfo, arma::mat>>::value>::type* = 0)
|
||||
{
|
||||
@@ -64,6 +63,23 @@ void SetParam(
|
||||
std::get<1>(tuple) = boost::any_cast<std::string>(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a serializable object. This sets the filename referring to the
|
||||
* parameter.
|
||||
*/
|
||||
template<typename T>
|
||||
void SetParam(
|
||||
util::ParamData& d,
|
||||
const boost::any& value,
|
||||
const typename boost::disable_if<arma::is_arma_type<T>>::type* = 0,
|
||||
const typename boost::enable_if<data::HasSerialize<T>>::type* = 0)
|
||||
{
|
||||
// We're setting the string filename.
|
||||
typedef std::tuple<T*, typename ParameterType<T>::type> TupleType;
|
||||
TupleType& tuple = *boost::any_cast<TupleType>(&d.value);
|
||||
std::get<1>(tuple) = boost::any_cast<std::string>(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a parameter casted to the given type. Type checking does not happen
|
||||
* here!
|
||||
@@ -75,7 +91,8 @@ void SetParam(
|
||||
template<typename T>
|
||||
void SetParam(const util::ParamData& d, const void* input, void* /* output */)
|
||||
{
|
||||
SetParam<T>(const_cast<util::ParamData&>(d), *((boost::any*) input));
|
||||
SetParam<typename std::remove_pointer<T>::type>(
|
||||
const_cast<util::ParamData&>(d), *((boost::any*) input));
|
||||
}
|
||||
|
||||
} // namespace cli
|
||||
|
||||
@@ -79,7 +79,6 @@ set(CYTHON_SOURCES
|
||||
mlpack/arma_util.hpp
|
||||
mlpack/cli.pxd
|
||||
mlpack/cli_util.hpp
|
||||
mlpack/move.hpp
|
||||
mlpack/matrix_utils.py
|
||||
mlpack/serialization.hpp
|
||||
mlpack/serialization.pxd
|
||||
@@ -148,7 +147,6 @@ add_custom_command(TARGET python POST_BUILD
|
||||
mlpack/arma_util.hpp
|
||||
mlpack/cli.pxd
|
||||
mlpack/cli_util.hpp
|
||||
mlpack/move.hpp
|
||||
mlpack/matrix_utils.py
|
||||
mlpack
|
||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/src/mlpack/bindings/python/)
|
||||
|
||||
@@ -113,7 +113,7 @@ inline std::string GetCythonType(
|
||||
const typename boost::disable_if<arma::is_arma_type<T>>::type* = 0,
|
||||
const typename boost::enable_if<data::HasSerialize<T>>::type* = 0)
|
||||
{
|
||||
return d.cppType;
|
||||
return d.cppType + "*";
|
||||
}
|
||||
|
||||
} // namespace python
|
||||
|
||||
@@ -73,7 +73,7 @@ std::string GetPrintableParam(
|
||||
const typename boost::enable_if<data::HasSerialize<T>>::type* = 0)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << data.cppType << " model";
|
||||
oss << data.cppType << " model at " << boost::any_cast<T*>(data.value);
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
@@ -110,7 +110,8 @@ void GetPrintableParam(const util::ParamData& data,
|
||||
const void* /* input */,
|
||||
void* output)
|
||||
{
|
||||
*((std::string*) output) = GetPrintableParam<T>(data);
|
||||
*((std::string*) output) =
|
||||
GetPrintableParam<typename std::remove_pointer<T>::type>(data);
|
||||
}
|
||||
|
||||
} // namespace python
|
||||
|
||||
@@ -79,7 +79,7 @@ void ImportDecl(const util::ParamData& d,
|
||||
const void* indent,
|
||||
void* /* output */)
|
||||
{
|
||||
ImportDecl<T>(d, *((size_t*) indent));
|
||||
ImportDecl<typename std::remove_pointer<T>::type>(d, *((size_t*) indent));
|
||||
}
|
||||
|
||||
} // namespace python
|
||||
|
||||
@@ -19,14 +19,15 @@ import numpy
|
||||
numpy.import_array()
|
||||
|
||||
cimport arma
|
||||
from libcpp cimport bool
|
||||
|
||||
"""
|
||||
Convert a numpy ndarray to a matrix.
|
||||
"""
|
||||
cdef arma.Mat[double]* numpy_to_mat_d(numpy.ndarray[numpy.double_t, ndim=2] X) \
|
||||
except +
|
||||
cdef arma.Mat[size_t]* numpy_to_mat_s(numpy.ndarray[numpy.npy_intp, ndim=2] X) \
|
||||
except +
|
||||
cdef arma.Mat[double]* numpy_to_mat_d(numpy.ndarray[numpy.double_t, ndim=2] X, \
|
||||
bool takeOwnership) except +
|
||||
cdef arma.Mat[size_t]* numpy_to_mat_s(numpy.ndarray[numpy.npy_intp, ndim=2] X, \
|
||||
bool takeOwnership) except +
|
||||
|
||||
"""
|
||||
Convert an Armadillo object to a numpy ndarray of the given type.
|
||||
@@ -39,10 +40,10 @@ cdef numpy.ndarray[numpy.npy_intp, ndim=2] mat_to_numpy_s(arma.Mat[size_t]& X) \
|
||||
"""
|
||||
Convert a numpy one-dimensional ndarray to a row of the given type.
|
||||
"""
|
||||
cdef arma.Row[double]* numpy_to_row_d(numpy.ndarray[numpy.double_t, ndim=1] X) \
|
||||
except +
|
||||
cdef arma.Row[size_t]* numpy_to_row_s(numpy.ndarray[numpy.npy_intp, ndim=1] X) \
|
||||
except +
|
||||
cdef arma.Row[double]* numpy_to_row_d(numpy.ndarray[numpy.double_t, ndim=1] X, \
|
||||
bool takeOwnership) except +
|
||||
cdef arma.Row[size_t]* numpy_to_row_s(numpy.ndarray[numpy.npy_intp, ndim=1] X, \
|
||||
bool takeOwnership) except +
|
||||
|
||||
"""
|
||||
Convert an Armadillo row vector to a one-dimensional numpy ndarray of the
|
||||
@@ -56,10 +57,10 @@ cdef numpy.ndarray[numpy.npy_intp, ndim=1] row_to_numpy_s(arma.Row[size_t]& X) \
|
||||
"""
|
||||
Convert a numpy one-dimensional ndarray to a column vector of the given type.
|
||||
"""
|
||||
cdef arma.Col[double]* numpy_to_col_d(numpy.ndarray[numpy.double_t, ndim=1] X) \
|
||||
except +
|
||||
cdef arma.Col[size_t]* numpy_to_col_s(numpy.ndarray[numpy.npy_intp, ndim=1] X) \
|
||||
except +
|
||||
cdef arma.Col[double]* numpy_to_col_d(numpy.ndarray[numpy.double_t, ndim=1] X, \
|
||||
bool takeOwnership) except +
|
||||
cdef arma.Col[size_t]* numpy_to_col_s(numpy.ndarray[numpy.npy_intp, ndim=1] X, \
|
||||
bool takeOwnership) except +
|
||||
|
||||
"""
|
||||
Convert an Armadillo column vector to a one-dimensional numpy ndarray of the
|
||||
|
||||
@@ -24,6 +24,7 @@ import numpy
|
||||
numpy.import_array()
|
||||
|
||||
cimport arma
|
||||
from libcpp cimport bool
|
||||
|
||||
cdef extern from "numpy/arrayobject.h":
|
||||
void PyArray_ENABLEFLAGS(numpy.ndarray arr, int flags)
|
||||
@@ -31,6 +32,7 @@ cdef extern from "numpy/arrayobject.h":
|
||||
|
||||
cdef extern from "<mlpack/bindings/python/mlpack/arma_util.hpp>":
|
||||
void SetMemState[T](T& m, int state)
|
||||
size_t GetMemState[T](T& m)
|
||||
double* GetMemory(arma.Mat[double]& m)
|
||||
double* GetMemory(arma.Col[double]& m)
|
||||
double* GetMemory(arma.Row[double]& m)
|
||||
@@ -38,38 +40,43 @@ cdef extern from "<mlpack/bindings/python/mlpack/arma_util.hpp>":
|
||||
size_t* GetMemory(arma.Col[size_t]& m)
|
||||
size_t* GetMemory(arma.Row[size_t]& m)
|
||||
|
||||
cdef arma.Mat[double]* numpy_to_mat_d(numpy.ndarray[numpy.double_t, ndim=2] X) \
|
||||
except +:
|
||||
cdef arma.Mat[double]* numpy_to_mat_d(numpy.ndarray[numpy.double_t, ndim=2] X, \
|
||||
bool takeOwnership) except +:
|
||||
"""
|
||||
Convert a numpy ndarray to a matrix.
|
||||
Convert a numpy ndarray to a matrix. The memory will still be owned by numpy.
|
||||
"""
|
||||
if not (X.flags.c_contiguous or X.flags.owndata):
|
||||
# If needed, make a copy where we own the memory.
|
||||
X = X.copy(order="C")
|
||||
takeOwnership = True
|
||||
|
||||
cdef arma.Mat[double]* m = new arma.Mat[double](<double*> X.data, X.shape[1], X.shape[0], False, True)
|
||||
cdef arma.Mat[double]* m = new arma.Mat[double](<double*> X.data, X.shape[1],\
|
||||
X.shape[0], False, False)
|
||||
|
||||
# Transfer ownership to the Armadillo matrix.
|
||||
PyArray_CLEARFLAGS(X, numpy.NPY_OWNDATA)
|
||||
SetMemState[arma.Mat[double]](m[0], 0)
|
||||
# Take ownership of the memory, if we need to.
|
||||
if takeOwnership:
|
||||
PyArray_CLEARFLAGS(X, numpy.NPY_OWNDATA)
|
||||
SetMemState[arma.Mat[double]](m[0], 0)
|
||||
|
||||
return m
|
||||
|
||||
cdef arma.Mat[size_t]* numpy_to_mat_s(numpy.ndarray[numpy.npy_intp, ndim=2] X) \
|
||||
except +:
|
||||
cdef arma.Mat[size_t]* numpy_to_mat_s(numpy.ndarray[numpy.npy_intp, ndim=2] X, \
|
||||
bool takeOwnership) except +:
|
||||
"""
|
||||
Convert a numpy ndarray to a matrix.
|
||||
Convert a numpy ndarray to a matrix. The memory will still be owned by numpy.
|
||||
"""
|
||||
if not (X.flags.c_contiguous or X.flags.owndata):
|
||||
# If needed, make a copy where we own the memory.
|
||||
X = X.copy(order="C")
|
||||
takeOwnership = True
|
||||
|
||||
cdef arma.Mat[size_t]* m = new arma.Mat[size_t](<size_t*> X.data, X.shape[1],
|
||||
X.shape[0], False, True)
|
||||
X.shape[0], False, False)
|
||||
|
||||
# Transfer ownership to the Armadillo matrix.
|
||||
PyArray_CLEARFLAGS(X, numpy.NPY_OWNDATA)
|
||||
SetMemState[arma.Mat[size_t]](m[0], 0)
|
||||
# Take ownership of the memory, if we need to.
|
||||
if takeOwnership:
|
||||
PyArray_CLEARFLAGS(X, numpy.NPY_OWNDATA)
|
||||
SetMemState[arma.Mat[size_t]](m[0], 0)
|
||||
|
||||
return m
|
||||
|
||||
@@ -85,9 +92,10 @@ cdef numpy.ndarray[numpy.double_t, ndim=2] mat_to_numpy_d(arma.Mat[double]& X) \
|
||||
cdef numpy.ndarray[numpy.double_t, ndim=2] output = \
|
||||
numpy.PyArray_SimpleNewFromData(2, &dims[0], numpy.NPY_DOUBLE, GetMemory(X))
|
||||
|
||||
# Transfer memory ownership.
|
||||
SetMemState[arma.Mat[double]](X, 1)
|
||||
PyArray_ENABLEFLAGS(output, numpy.NPY_OWNDATA)
|
||||
# Transfer memory ownership, if needed.
|
||||
if GetMemState[arma.Mat[double]](X) == 0:
|
||||
SetMemState[arma.Mat[double]](X, 1)
|
||||
PyArray_ENABLEFLAGS(output, numpy.NPY_OWNDATA)
|
||||
|
||||
return output
|
||||
|
||||
@@ -103,45 +111,52 @@ cdef numpy.ndarray[numpy.npy_intp, ndim=2] mat_to_numpy_s(arma.Mat[size_t]& X) \
|
||||
cdef numpy.ndarray[numpy.npy_intp, ndim=2] output = \
|
||||
numpy.PyArray_SimpleNewFromData(2, &dims[0], numpy.NPY_INTP, GetMemory(X))
|
||||
|
||||
# Transfer memory ownership.
|
||||
SetMemState[arma.Mat[size_t]](X, 1)
|
||||
PyArray_ENABLEFLAGS(output, numpy.NPY_OWNDATA)
|
||||
# Transfer memory ownership, if needed.
|
||||
if GetMemState[arma.Mat[size_t]](X) == 0:
|
||||
SetMemState[arma.Mat[size_t]](X, 1)
|
||||
PyArray_ENABLEFLAGS(output, numpy.NPY_OWNDATA)
|
||||
|
||||
return output
|
||||
|
||||
cdef arma.Row[double]* numpy_to_row_d(numpy.ndarray[numpy.double_t, ndim=1] X) \
|
||||
except +:
|
||||
cdef arma.Row[double]* numpy_to_row_d(numpy.ndarray[numpy.double_t, ndim=1] X, \
|
||||
bool takeOwnership) except +:
|
||||
"""
|
||||
Convert a numpy one-dimensional ndarray to a row.
|
||||
Convert a numpy one-dimensional ndarray to a row. The memory will still be
|
||||
owned by numpy.
|
||||
"""
|
||||
if not (X.flags.c_contiguous or X.flags.owndata):
|
||||
# If needed, make a copy where we own the memory.
|
||||
X = X.copy(order="C")
|
||||
takeOwnership = True
|
||||
|
||||
cdef arma.Row[double]* m = new arma.Row[double](<double*> X.data, X.shape[0],
|
||||
False, True)
|
||||
False, False)
|
||||
|
||||
# Transfer ownership to the Armadillo matrix.
|
||||
PyArray_CLEARFLAGS(X, numpy.NPY_OWNDATA)
|
||||
SetMemState[arma.Row[double]](m[0], 0)
|
||||
# Transfer memory ownership, if needed.
|
||||
if takeOwnership:
|
||||
PyArray_CLEARFLAGS(X, numpy.NPY_OWNDATA)
|
||||
SetMemState[arma.Row[double]](m[0], 0)
|
||||
|
||||
return m
|
||||
|
||||
cdef arma.Row[size_t]* numpy_to_row_s(numpy.ndarray[numpy.npy_intp, ndim=1] X) \
|
||||
except +:
|
||||
cdef arma.Row[size_t]* numpy_to_row_s(numpy.ndarray[numpy.npy_intp, ndim=1] X, \
|
||||
bool takeOwnership) except +:
|
||||
"""
|
||||
Convert a numpy one-dimensional ndarray to a row.
|
||||
Convert a numpy one-dimensional ndarray to a row. The memory will still be
|
||||
owned by numpy.
|
||||
"""
|
||||
if not (X.flags.c_contiguous or X.flags.owndata):
|
||||
# If needed, make a copy where we own the memory.
|
||||
X = X.copy(order="C")
|
||||
takeOwnership = True
|
||||
|
||||
cdef arma.Row[size_t]* m = new arma.Row[size_t](<size_t*> X.data, X.shape[0],
|
||||
False, True)
|
||||
False, False)
|
||||
|
||||
# Transfer ownership to the Armadillo matrix.
|
||||
PyArray_CLEARFLAGS(X, numpy.NPY_OWNDATA)
|
||||
SetMemState[arma.Row[size_t]](m[0], 0)
|
||||
# Transfer memory ownership, if needed.
|
||||
if takeOwnership:
|
||||
PyArray_CLEARFLAGS(X, numpy.NPY_OWNDATA)
|
||||
SetMemState[arma.Row[size_t]](m[0], 0)
|
||||
|
||||
return m
|
||||
|
||||
@@ -155,9 +170,10 @@ cdef numpy.ndarray[numpy.double_t, ndim=1] row_to_numpy_d(arma.Row[double]& X) \
|
||||
cdef numpy.ndarray[numpy.double_t, ndim=1] output = \
|
||||
numpy.PyArray_SimpleNewFromData(1, &dim, numpy.NPY_DOUBLE, GetMemory(X))
|
||||
|
||||
# Transfer memory ownership.
|
||||
SetMemState[arma.Row[double]](X, 1)
|
||||
PyArray_ENABLEFLAGS(output, numpy.NPY_OWNDATA)
|
||||
# Transfer memory ownership, if needed.
|
||||
if GetMemState[arma.Row[double]](X) == 0:
|
||||
SetMemState[arma.Row[double]](X, 1)
|
||||
PyArray_ENABLEFLAGS(output, numpy.NPY_OWNDATA)
|
||||
|
||||
return output
|
||||
|
||||
@@ -171,45 +187,51 @@ cdef numpy.ndarray[numpy.npy_intp, ndim=1] row_to_numpy_s(arma.Row[size_t]& X) \
|
||||
cdef numpy.ndarray[numpy.npy_intp, ndim=1] output = \
|
||||
numpy.PyArray_SimpleNewFromData(1, &dim, numpy.NPY_INTP, GetMemory(X))
|
||||
|
||||
# Transfer memory ownership.
|
||||
SetMemState[arma.Row[size_t]](X, 1)
|
||||
PyArray_ENABLEFLAGS(output, numpy.NPY_OWNDATA)
|
||||
# Transfer memory ownership, if needed.
|
||||
if GetMemState[arma.Row[size_t]](X) == 0:
|
||||
SetMemState[arma.Row[size_t]](X, 1)
|
||||
PyArray_ENABLEFLAGS(output, numpy.NPY_OWNDATA)
|
||||
|
||||
return output
|
||||
|
||||
cdef arma.Col[double]* numpy_to_col_d(numpy.ndarray[numpy.double_t, ndim=1] X) \
|
||||
except +:
|
||||
cdef arma.Col[double]* numpy_to_col_d(numpy.ndarray[numpy.double_t, ndim=1] X, \
|
||||
bool takeOwnership) except +:
|
||||
"""
|
||||
Convert a numpy one-dimensional ndarray to a column vector.
|
||||
Convert a numpy one-dimensional ndarray to a column vector. The memory will
|
||||
still be owned by numpy.
|
||||
"""
|
||||
if not (X.flags.c_contiguous or X.flags.owndata):
|
||||
# If needed, make a copy where we own the memory.
|
||||
X = X.copy(order="C")
|
||||
takeOwnership = True
|
||||
|
||||
cdef arma.Col[double]* m = new arma.Col[double](<double*> X.data, X.shape[0],
|
||||
False, True)
|
||||
|
||||
# Transfer ownership to the Armadillo matrix.
|
||||
PyArray_CLEARFLAGS(X, numpy.NPY_OWNDATA)
|
||||
SetMemState[arma.Col[double]](m[0], 0)
|
||||
# Transfer memory ownership, if needed.
|
||||
if takeOwnership:
|
||||
PyArray_CLEARFLAGS(X, numpy.NPY_OWNDATA)
|
||||
SetMemState[arma.Col[double]](m[0], 0)
|
||||
|
||||
return m
|
||||
|
||||
cdef arma.Col[size_t]* numpy_to_col_s(numpy.ndarray[numpy.npy_intp, ndim=1] X) \
|
||||
except +:
|
||||
cdef arma.Col[size_t]* numpy_to_col_s(numpy.ndarray[numpy.npy_intp, ndim=1] X, \
|
||||
bool takeOwnership) except +:
|
||||
"""
|
||||
Convert a numpy one-dimensional ndarray to a column vector.
|
||||
Convert a numpy one-dimensional ndarray to a column vector. The memory will
|
||||
still be owned by numpy.
|
||||
"""
|
||||
if not (X.flags.c_contiguous or X.flags.owndata):
|
||||
# If needed, make a copy where we own the memory.
|
||||
X = X.copy(order="C")
|
||||
|
||||
cdef arma.Col[size_t]* m = new arma.Col[size_t](<size_t*> X.data, X.shape[0],
|
||||
False, True)
|
||||
False, False)
|
||||
|
||||
# Transfer ownership to the Armadillo matrix.
|
||||
PyArray_CLEARFLAGS(X, numpy.NPY_OWNDATA)
|
||||
SetMemState[arma.Col[size_t]](m[0], 0)
|
||||
# Transfer memory ownership, if needed.
|
||||
if takeOwnership:
|
||||
PyArray_CLEARFLAGS(X, numpy.NPY_OWNDATA)
|
||||
SetMemState[arma.Col[size_t]](m[0], 0)
|
||||
|
||||
return m
|
||||
|
||||
@@ -223,9 +245,10 @@ cdef numpy.ndarray[numpy.double_t, ndim=1] col_to_numpy_d(arma.Col[double]& X) \
|
||||
cdef numpy.ndarray[numpy.double_t, ndim=1] output = \
|
||||
numpy.PyArray_SimpleNewFromData(1, &dim, numpy.NPY_DOUBLE, GetMemory(X))
|
||||
|
||||
# Transfer memory ownership.
|
||||
SetMemState[arma.Col[double]](X, 1)
|
||||
PyArray_ENABLEFLAGS(output, numpy.NPY_OWNDATA)
|
||||
# Transfer memory ownership, if needed.
|
||||
if GetMemState[arma.Col[double]](X) == 0:
|
||||
SetMemState[arma.Col[double]](X, 1)
|
||||
PyArray_ENABLEFLAGS(output, numpy.NPY_OWNDATA)
|
||||
|
||||
return output
|
||||
|
||||
@@ -239,8 +262,9 @@ cdef numpy.ndarray[numpy.npy_intp, ndim=1] col_to_numpy_s(arma.Col[size_t]& X) \
|
||||
cdef numpy.ndarray[numpy.npy_intp, ndim=1] output = \
|
||||
numpy.PyArray_SimpleNewFromData(1, &dim, numpy.NPY_INTP, GetMemory(X))
|
||||
|
||||
# Transfer memory ownership.
|
||||
SetMemState[arma.Col[size_t]](X, 1)
|
||||
PyArray_ENABLEFLAGS(output, numpy.NPY_OWNDATA)
|
||||
# Transfer memory ownership, if needed.
|
||||
if GetMemState[arma.Col[size_t]](X) == 0:
|
||||
SetMemState[arma.Col[size_t]](X, 1)
|
||||
PyArray_ENABLEFLAGS(output, numpy.NPY_OWNDATA)
|
||||
|
||||
return output
|
||||
|
||||
@@ -24,6 +24,20 @@ void SetMemState(T& t, int state)
|
||||
const_cast<arma::uhword&>(t.mem_state) = state;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the memory state of the given Armadillo object.
|
||||
*/
|
||||
template<typename T>
|
||||
size_t GetMemState(T& t)
|
||||
{
|
||||
// Fake the memory state if we are using preallocated memory---since we will
|
||||
// end up copying that memory, NumPy can own it.
|
||||
if (t.mem && t.n_elem <= arma::arma_config::mat_prealloc)
|
||||
return 0;
|
||||
|
||||
return (size_t) t.mem_state;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the matrix's allocated memory pointer, unless the matrix is using its
|
||||
* internal preallocated memory, in which case we copy that and return a
|
||||
|
||||
@@ -20,6 +20,9 @@ cdef extern from "<mlpack/core/util/cli.hpp>" namespace "mlpack" nogil:
|
||||
@staticmethod
|
||||
(T&) GetParam[T](string) nogil except +
|
||||
|
||||
@staticmethod
|
||||
bool HasParam(string) nogil except +
|
||||
|
||||
@staticmethod
|
||||
void SetPassed(string) nogil except +
|
||||
|
||||
@@ -37,16 +40,13 @@ cdef extern from "<mlpack/core/util/cli.hpp>" namespace "mlpack" nogil:
|
||||
|
||||
cdef extern from "<mlpack/bindings/python/mlpack/cli_util.hpp>" \
|
||||
namespace "mlpack::util" nogil:
|
||||
void SetParam[T](string, const T&) nogil except +
|
||||
void SetParamWithInfo[T](string, const T&, const bool*) nogil except +
|
||||
void SetParam[T](string, T&) nogil except +
|
||||
void SetParamPtr[T](string, T*, bool) nogil except +
|
||||
void SetParamWithInfo[T](string, T&, const bool*) nogil except +
|
||||
(T*) GetParamPtr[T](string) nogil except +
|
||||
(T&) GetParamWithInfo[T](string) nogil except +
|
||||
void EnableVerbose() nogil except +
|
||||
void DisableVerbose() nogil except +
|
||||
void DisableBacktrace() nogil except +
|
||||
void ResetTimers() nogil except +
|
||||
void EnableTimers() nogil except +
|
||||
|
||||
cdef extern from "<mlpack/bindings/python/mlpack/move.hpp>" \
|
||||
namespace "mlpack::util" nogil:
|
||||
void MoveFromPtr[T](T&, T*) nogil except +
|
||||
void MoveToPtr[T](T*, T&) nogil except +
|
||||
|
||||
@@ -29,9 +29,27 @@ namespace util {
|
||||
* @param value Value to set parameter to.
|
||||
*/
|
||||
template<typename T>
|
||||
inline void SetParam(const std::string& identifier, const T& value)
|
||||
inline void SetParam(const std::string& identifier, T& value)
|
||||
{
|
||||
CLI::GetParam<T>(identifier) = value;
|
||||
CLI::GetParam<T>(identifier) = std::move(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the parameter to the given value, given that the type is a pointer.
|
||||
*
|
||||
* This function exists to work around both Cython's lack of support for lvalue
|
||||
* references and also its seeming lack of support for template pointer types.
|
||||
*
|
||||
* @param identifier Name of parameter.
|
||||
* @param value Value to set parameter to.
|
||||
* @param copy Whether or not the object should be copied.
|
||||
*/
|
||||
template<typename T>
|
||||
inline void SetParamPtr(const std::string& identifier,
|
||||
T* value,
|
||||
const bool copy)
|
||||
{
|
||||
CLI::GetParam<T*>(identifier) = copy ? new T(*value) : value;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -39,19 +57,20 @@ inline void SetParam(const std::string& identifier, const T& value)
|
||||
*/
|
||||
template<typename T>
|
||||
inline void SetParamWithInfo(const std::string& identifier,
|
||||
const T& matrix,
|
||||
T& matrix,
|
||||
const bool* dims)
|
||||
{
|
||||
typedef typename std::tuple<data::DatasetInfo, T> TupleType;
|
||||
typedef typename T::elem_type eT;
|
||||
|
||||
// The true type of the parameter is std::tuple<T, DatasetInfo>.
|
||||
std::get<1>(CLI::GetParam<TupleType>(identifier)) = matrix;
|
||||
const size_t dimensions = matrix.n_rows;
|
||||
std::get<1>(CLI::GetParam<TupleType>(identifier)) = std::move(matrix);
|
||||
data::DatasetInfo& di = std::get<0>(CLI::GetParam<TupleType>(identifier));
|
||||
di = data::DatasetInfo(matrix.n_rows);
|
||||
di = data::DatasetInfo(dimensions);
|
||||
|
||||
bool hasCategoricals = false;
|
||||
for (size_t i = 0; i < matrix.n_rows; ++i)
|
||||
for (size_t i = 0; i < dimensions; ++i)
|
||||
{
|
||||
if (dims[i])
|
||||
{
|
||||
@@ -63,9 +82,10 @@ inline void SetParamWithInfo(const std::string& identifier,
|
||||
// Do we need to find how many categories we have?
|
||||
if (hasCategoricals)
|
||||
{
|
||||
arma::vec maxs = arma::max(matrix, 1);
|
||||
arma::vec maxs = arma::max(
|
||||
std::get<1>(CLI::GetParam<TupleType>(identifier)), 1);
|
||||
|
||||
for (size_t i = 0; i < matrix.n_rows; ++i)
|
||||
for (size_t i = 0; i < dimensions; ++i)
|
||||
{
|
||||
if (dims[i])
|
||||
{
|
||||
@@ -81,6 +101,16 @@ inline void SetParamWithInfo(const std::string& identifier,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a pointer. This function exists to work around Cython's seeming lack
|
||||
* of support for template pointer types.
|
||||
*/
|
||||
template<typename T>
|
||||
T* GetParamPtr(const std::string& paramName)
|
||||
{
|
||||
return CLI::GetParam<T*>(paramName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the matrix part of a matrix + dataset info parameter.
|
||||
*/
|
||||
|
||||
@@ -37,7 +37,7 @@ try:
|
||||
except:
|
||||
buffer = memoryview
|
||||
|
||||
def to_matrix(x, dtype=np.double):
|
||||
def to_matrix(x, dtype=np.double, copy=False):
|
||||
"""
|
||||
Given some array-like X, return a numpy ndarray of the same type.
|
||||
"""
|
||||
@@ -48,11 +48,14 @@ def to_matrix(x, dtype=np.double):
|
||||
raise TypeError("given argument is not array-like")
|
||||
|
||||
if (isinstance(x, np.ndarray) and x.dtype == dtype and x.flags.c_contiguous):
|
||||
return x
|
||||
if copy: # Copy the matrix if required.
|
||||
return x.copy("C"), True
|
||||
else:
|
||||
return x, False
|
||||
else:
|
||||
return np.array(x, copy=True, dtype=dtype, order='C')
|
||||
return np.array(x, copy=True, dtype=dtype, order='C'), True
|
||||
|
||||
def to_matrix_with_info(x, dtype):
|
||||
def to_matrix_with_info(x, dtype, copy=False):
|
||||
"""
|
||||
Given some array-like X (which should be either a numpy ndarray or a pandas
|
||||
DataFrame, convert into a numpy matrix of the given dtype.
|
||||
@@ -66,7 +69,12 @@ def to_matrix_with_info(x, dtype):
|
||||
if isinstance(x, np.ndarray):
|
||||
# It is already an ndarray, so the vector of info is all 0s (all numeric).
|
||||
d = np.zeros([x.shape[1]], dtype=np.bool)
|
||||
return (x, d)
|
||||
|
||||
# Copy the matrix if needed.
|
||||
if copy:
|
||||
return (x.copy(order="C"), True, d)
|
||||
else:
|
||||
return (x, False, d)
|
||||
|
||||
if isinstance(x, pd.DataFrame) or isinstance(x, pd.Series):
|
||||
# It's a pandas dataframe. So we need to see if any of the dtypes are
|
||||
@@ -79,8 +87,9 @@ def to_matrix_with_info(x, dtype):
|
||||
not np.dtype(str) in dtype_array and \
|
||||
not np.dtype(unicode) in dtype_array:
|
||||
# We can just return the matrix as-is; it's all numeric.
|
||||
t = to_matrix(x, dtype=dtype, copy=copy)
|
||||
d = np.zeros([x.shape[1]], dtype=np.bool)
|
||||
return (to_matrix(x), d)
|
||||
return (t[0], t[1], d)
|
||||
|
||||
if np.dtype(str) in dtype_array or np.dtype(unicode) in dtype_array:
|
||||
raise TypeError('cannot convert matrices with string types')
|
||||
@@ -115,7 +124,10 @@ def to_matrix_with_info(x, dtype):
|
||||
catColumnIndices = [y.columns.get_loc(i) for i in catColumns]
|
||||
d[catColumnIndices] = 1
|
||||
|
||||
return (to_matrix(y.apply(pd.to_numeric)), d)
|
||||
# We'll have to force the second part of the tuple (whether or not to take
|
||||
# ownership) to true.
|
||||
t = to_matrix(y.apply(pd.to_numeric), dtype=dtype)
|
||||
return (t[0], True, d)
|
||||
|
||||
if isinstance(x, list):
|
||||
# Get the number of dimensions.
|
||||
@@ -126,7 +138,18 @@ def to_matrix_with_info(x, dtype):
|
||||
dims = len(x)
|
||||
|
||||
d = np.zeros([dims])
|
||||
return (np.array(x, dtype=dtype), d)
|
||||
out = np.array(x, dtype=dtype, copy=copy) # Try to avoid copy...
|
||||
|
||||
# Since we don't have a great way to check if these are using the same
|
||||
# memory location, we will probe manually (ugh).
|
||||
oldval = x[0]
|
||||
x[0] *= 2
|
||||
alias = False
|
||||
if out[0] == x[0]:
|
||||
alias = True
|
||||
x[0] = oldval
|
||||
|
||||
return (out, not alias, d)
|
||||
|
||||
# If we got here, the type is not known.
|
||||
raise TypeError("given matrix is not a numpy ndarray or pandas DataFrame or "\
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
/**
|
||||
* @file move.hpp
|
||||
* @author Ryan Curtin
|
||||
*
|
||||
* Utility function for Cython to use std::move.
|
||||
*/
|
||||
#ifndef MLPACK_BINDINGS_PYTHON_CYTHON_MOVE_HPP
|
||||
#define MLPACK_BINDINGS_PYTHON_CYTHON_MOVE_HPP
|
||||
|
||||
#include <utility>
|
||||
|
||||
namespace mlpack {
|
||||
namespace util {
|
||||
|
||||
template<typename T>
|
||||
void MoveToPtr(T* dest, T& src)
|
||||
{
|
||||
*(dest) = std::move(src);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void MoveFromPtr(T& dest, T* src)
|
||||
{
|
||||
dest = std::move(*src);
|
||||
}
|
||||
|
||||
} // namespace util
|
||||
} // namespace mlpack
|
||||
|
||||
#endif
|
||||
@@ -108,7 +108,7 @@ void PrintClassDefn(const util::ParamData& d,
|
||||
const void* /* input */,
|
||||
void* /* output */)
|
||||
{
|
||||
PrintClassDefn<T>(d);
|
||||
PrintClassDefn<typename std::remove_pointer<T>::type>(d);
|
||||
}
|
||||
|
||||
} // namespace python
|
||||
|
||||
@@ -39,7 +39,27 @@ void PrintDoc(const util::ParamData& d,
|
||||
oss << d.name << "_ (";
|
||||
else
|
||||
oss << d.name << " (";
|
||||
oss << GetPythonType<T>(d) << "): " << d.desc;
|
||||
oss << GetPythonType<typename std::remove_pointer<T>::type>(d) << "): "
|
||||
<< d.desc;
|
||||
|
||||
// Print a default, if possible.
|
||||
if (!d.required)
|
||||
{
|
||||
if (d.cppType == "std::string")
|
||||
{
|
||||
oss << " Default value '" << boost::any_cast<std::string>(d.value)
|
||||
<< "'.";
|
||||
}
|
||||
else if (d.cppType == "double")
|
||||
{
|
||||
oss << " Default value " << boost::any_cast<double>(d.value) << ".";
|
||||
}
|
||||
else if (d.cppType == "int")
|
||||
{
|
||||
oss << " Default value " << boost::any_cast<int>(d.value) << ".";
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << util::HyphenateString(oss.str(), indent + 4);
|
||||
}
|
||||
|
||||
|
||||
@@ -31,6 +31,11 @@ void PrintInputProcessing(
|
||||
const typename boost::disable_if<std::is_same<T,
|
||||
std::tuple<data::DatasetInfo, arma::mat>>>::type* = 0)
|
||||
{
|
||||
// The copy_all_inputs parameter must be handled first, and therefore is
|
||||
// outside the scope of this code.
|
||||
if (d.name == "copy_all_inputs")
|
||||
return;
|
||||
|
||||
const std::string prefix(indent, ' ');
|
||||
|
||||
std::string def = "None";
|
||||
@@ -104,7 +109,9 @@ void PrintInputProcessing(
|
||||
*
|
||||
* # Detect if the parameter was passed; set if so.
|
||||
* if param_name is not None:
|
||||
* param_name_mat = arma_numpy.numpy_to_mat_d(param_name)
|
||||
* param_name_tuple = to_matrix(param_name)
|
||||
* param_name_mat = arma_numpy.numpy_to_mat_d(param_name_tuple[0],
|
||||
* param_name_tuple[1])
|
||||
* SetParam[mat](<const string> 'param_name', dereference(param_name_mat))
|
||||
* CLI.SetPassed(<const string> 'param_name')
|
||||
*/
|
||||
@@ -114,27 +121,33 @@ void PrintInputProcessing(
|
||||
{
|
||||
std::cout << prefix << "if " << d.name << " is not None:" << std::endl;
|
||||
|
||||
std::cout << prefix << " " << d.name << "_tuple = to_matrix(" << d.name
|
||||
<< ", dtype=" << GetNumpyType<typename T::elem_type>() << ", "
|
||||
<< "copy=CLI.HasParam('copy_all_inputs'))" << std::endl;
|
||||
std::cout << prefix << " " << d.name << "_mat = arma_numpy.numpy_to_"
|
||||
<< GetArmaType<T>() << "_" << GetNumpyTypeChar<T>() << "(to_matrix("
|
||||
<< d.name << ", " << "dtype=" << GetNumpyType<typename T::elem_type>()
|
||||
<< "))" << std::endl;
|
||||
<< GetArmaType<T>() << "_" << GetNumpyTypeChar<T>() << "(" << d.name
|
||||
<< "_tuple[0], " << d.name << "_tuple[1])" << std::endl;
|
||||
std::cout << prefix << " SetParam[" << GetCythonType<T>(d) << "](<const "
|
||||
<< "string> '" << d.name << "', dereference(" << d.name << "_mat))"
|
||||
<< std::endl;
|
||||
std::cout << prefix << " CLI.SetPassed(<const string> '" << d.name << "')"
|
||||
<< std::endl;
|
||||
std::cout << prefix << " del " << d.name << "_mat";
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << prefix << d.name << "_tuple = to_matrix(" << d.name
|
||||
<< ", dtype=" << GetNumpyType<typename T::elem_type>() << ", "
|
||||
<< "copy=CLI.HasParam('copy_all_inputs'))" << std::endl;
|
||||
std::cout << prefix << d.name << "_mat = arma_numpy.numpy_to_"
|
||||
<< GetArmaType<T>() << "_" << GetNumpyTypeChar<T>() << "(to_matrix("
|
||||
<< d.name << ", " << "dtype=" << GetNumpyType<typename T::elem_type>()
|
||||
<< "))" << std::endl;
|
||||
<< GetArmaType<T>() << "_" << GetNumpyTypeChar<T>() << "(" << d.name
|
||||
<< "_tuple[0], " << d.name << "_tuple[1])" << std::endl;
|
||||
std::cout << prefix << "SetParam[" << GetCythonType<T>(d) << "](<const "
|
||||
<< "string> '" << d.name << "', dereference(" << d.name << "_mat))"
|
||||
<< std::endl;
|
||||
std::cout << prefix << "CLI.SetPassed(<const string> '" << d.name << "')"
|
||||
<< std::endl;
|
||||
std::cout << prefix << "del " << d.name << "_mat";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
@@ -161,12 +174,12 @@ void PrintInputProcessing(
|
||||
* # Detect if the parameter was passed; set if so.
|
||||
* if param_name is not None:
|
||||
* try:
|
||||
* MoveFromPtr[Model](CLI.GetParam[Model]('param_name'),
|
||||
* (<ModelType?> param_name).modelptr)
|
||||
* SetParamPtr[Model]('param_name', (<ModelType?> param_name).modelptr,
|
||||
* CLI.HasParam('copy_all_inputs'))
|
||||
* except TypeError as e:
|
||||
* if type(param_name).__name__ == "ModelType":
|
||||
* MoveFromPtr[Model](CLI.GetParam[Model]('param_name'),
|
||||
* (<ModelType> param_name).modelptr)
|
||||
* SetParamPtr[Model]('param_name', (<ModelType> param_name).modelptr,
|
||||
* CLI.HasParam('copy_all_inputs'))
|
||||
* else:
|
||||
* raise e
|
||||
* CLI.SetPassed(<const string> 'param_name')
|
||||
@@ -177,15 +190,15 @@ void PrintInputProcessing(
|
||||
{
|
||||
std::cout << prefix << "if " << d.name << " is not None:" << std::endl;
|
||||
std::cout << prefix << " try:" << std::endl;
|
||||
std::cout << prefix << " MoveFromPtr[" << strippedType
|
||||
<< "](CLI.GetParam[" << strippedType << "]('" << d.name << "'), (<"
|
||||
<< strippedType << "Type?> " << d.name << ").modelptr)" << std::endl;
|
||||
std::cout << prefix << " SetParamPtr[" << strippedType << "]('" << d.name
|
||||
<< "', (<" << strippedType << "Type?> " << d.name << ").modelptr, "
|
||||
<< "CLI.HasParam('copy_all_inputs'))" << std::endl;
|
||||
std::cout << prefix << " except TypeError as e:" << std::endl;
|
||||
std::cout << prefix << " if type(" << d.name << ").__name__ == '"
|
||||
<< strippedType << "Type':" << std::endl;
|
||||
std::cout << prefix << " MoveFromPtr[" << strippedType
|
||||
<< "](CLI.GetParam[" << strippedType << "]('" << d.name << "'), (<"
|
||||
<< strippedType << "Type> " << d.name << ").modelptr)" << std::endl;
|
||||
std::cout << prefix << " SetParamPtr[" << strippedType << "]('"
|
||||
<< d.name << "', (<" << strippedType << "Type> " << d.name
|
||||
<< ").modelptr, CLI.HasParam('copy_all_inputs'))" << std::endl;
|
||||
std::cout << prefix << " else:" << std::endl;
|
||||
std::cout << prefix << " raise e" << std::endl;
|
||||
std::cout << prefix << " CLI.SetPassed(<const string> '" << d.name << "')"
|
||||
@@ -194,15 +207,15 @@ void PrintInputProcessing(
|
||||
else
|
||||
{
|
||||
std::cout << prefix << "try:" << std::endl;
|
||||
std::cout << prefix << " MoveFromPtr[" << strippedType << "](CLI.GetParam["
|
||||
<< strippedType << "]('" << d.name << "'), (<" << strippedType
|
||||
<< "Type?> " << d.name << ").modelptr)" << std::endl;
|
||||
std::cout << prefix << " SetParamPtr[" << strippedType << "]('" << d.name
|
||||
<< "', (<" << strippedType << "Type?> " << d.name << ").modelptr, "
|
||||
<< "CLI.HasParam('copy_all_inputs'))" << std::endl;
|
||||
std::cout << prefix << "except TypeError as e:" << std::endl;
|
||||
std::cout << prefix << " if type(" << d.name << ").__name__ == '"
|
||||
<< strippedType << "Type':" << std::endl;
|
||||
std::cout << prefix << " MoveFromPtr[" << strippedType
|
||||
<< "](CLI.GetParam[" << strippedType << "]('" << d.name << "'), (<"
|
||||
<< strippedType << "Type> " << d.name << ").modelptr)" << std::endl;
|
||||
std::cout << prefix << " SetParamPtr[" << strippedType << "]('" << d.name
|
||||
<< "', (<" << strippedType << "Type> " << d.name << ").modelptr, "
|
||||
<< "CLI.HasParam('copy_all_inputs'))" << std::endl;
|
||||
std::cout << prefix << " else:" << std::endl;
|
||||
std::cout << prefix << " raise e" << std::endl;
|
||||
std::cout << prefix << "CLI.SetPassed(<const string> '" << d.name << "')"
|
||||
@@ -240,30 +253,34 @@ void PrintInputProcessing(
|
||||
{
|
||||
std::cout << prefix << "if " << d.name << " is not None:" << std::endl;
|
||||
std::cout << prefix << " " << d.name << "_tuple = to_matrix_with_info("
|
||||
<< d.name << ", dtype=np.double)" << std::endl;
|
||||
<< d.name << ", dtype=np.double, copy=CLI.HasParam('copy_all_inputs'))"
|
||||
<< std::endl;
|
||||
std::cout << prefix << " " << d.name << "_mat = arma_numpy.numpy_to_mat_d("
|
||||
<< d.name << "_tuple[0])" << std::endl;
|
||||
std::cout << prefix << " " << d.name << "_dims = " << d.name << "_tuple[1]"
|
||||
<< d.name << "_tuple[0], " << d.name << "_tuple[1])" << std::endl;
|
||||
std::cout << prefix << " " << d.name << "_dims = " << d.name << "_tuple[2]"
|
||||
<< std::endl;
|
||||
std::cout << prefix << " SetParamWithInfo[arma.Mat[double]](<const string>"
|
||||
<< " '" << d.name << "', dereference(" << d.name << "_mat), <const "
|
||||
<< "bool*> " << d.name << "_dims.data)" << std::endl;
|
||||
std::cout << prefix << " CLI.SetPassed(<const string> '" << d.name << "')"
|
||||
<< std::endl;
|
||||
std::cout << prefix << " del " << d.name << "_mat" << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << prefix << d.name << "_tuple = to_matrix_with_info(" << d.name
|
||||
<< ", dtype=np.double)" << std::endl;
|
||||
<< ", dtype=np.double, copy=CLI.HasParam('copy_all_inputs'))"
|
||||
<< std::endl;
|
||||
std::cout << prefix << d.name << "_mat = arma_numpy.numpy_to_mat_d("
|
||||
<< d.name << "_tuple[0])" << std::endl;
|
||||
std::cout << prefix << d.name << "_dims = " << d.name << "_tuple[1]"
|
||||
<< d.name << "_tuple[0], " << d.name << "_tuple[1])" << std::endl;
|
||||
std::cout << prefix << d.name << "_dims = " << d.name << "_tuple[2]"
|
||||
<< std::endl;
|
||||
std::cout << prefix << "SetParamWithInfo[arma.Mat[double]](<const string>"
|
||||
<< " '" << d.name << "', dereference(" << d.name << "_mat), <const "
|
||||
<< "bool*> " << d.name << "_dims.data)" << std::endl;
|
||||
std::cout << prefix << "CLI.SetPassed(<const string> '" << d.name << "')"
|
||||
<< std::endl;
|
||||
std::cout << prefix << "del " << d.name << "_mat" << std::endl;
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
@@ -284,7 +301,8 @@ void PrintInputProcessing(const util::ParamData& d,
|
||||
const void* input,
|
||||
void* /* output */)
|
||||
{
|
||||
PrintInputProcessing<T>(d, *((size_t*) input));
|
||||
PrintInputProcessing<typename std::remove_pointer<T>::type>(d,
|
||||
*((size_t*) input));
|
||||
}
|
||||
|
||||
} // namespace python
|
||||
|
||||
@@ -180,13 +180,47 @@ void PrintOutputProcessing(
|
||||
* This gives us code like:
|
||||
*
|
||||
* result = ModelType()
|
||||
* MoveToPtr[Model]((<ModelType?> model).modelptr),
|
||||
* CLI.GetParam[Model]('name'))
|
||||
* (<ModelType?> result).modelptr = GetParamPtr[Model]('name')
|
||||
*/
|
||||
std::cout << prefix << "result = " << strippedType << "Type()" << std::endl;
|
||||
std::cout << prefix << "MoveToPtr[" << strippedType << "]((<"
|
||||
<< strippedType << "Type?> result).modelptr, CLI.GetParam["
|
||||
<< strippedType << "]('" << d.name << "'))" << std::endl;
|
||||
std::cout << prefix << "(<" << strippedType << "Type?> result).modelptr = "
|
||||
<< "GetParamPtr[" << strippedType << "]('" << d.name << "')"
|
||||
<< std::endl;
|
||||
|
||||
/**
|
||||
* But we also have to check to ensure there aren't any input model
|
||||
* parameters of the same type that could have the same model pointer.
|
||||
* So we need to loop through all input parameters that have the same type,
|
||||
* and double-check.
|
||||
*/
|
||||
std::map<std::string, util::ParamData>& parameters = CLI::Parameters();
|
||||
for (auto it = parameters.begin(); it != parameters.end(); ++it)
|
||||
{
|
||||
// Is it an input parameter of the same type?
|
||||
const util::ParamData& data = it->second;
|
||||
if (data.input && data.cppType == d.cppType && data.required)
|
||||
{
|
||||
std::cout << prefix << "if (<" << strippedType
|
||||
<< "Type> result).modelptr" << d.name << " == (<" << strippedType
|
||||
<< "Type> " << data.name << ").modelptr:" << std::endl;
|
||||
std::cout << prefix << " (<" << strippedType
|
||||
<< "Type> result).modelptr = <" << strippedType << "*> 0"
|
||||
<< std::endl;
|
||||
std::cout << prefix << " result = " << data.name << std::endl;
|
||||
}
|
||||
else if (data.input && data.cppType == d.cppType)
|
||||
{
|
||||
std::cout << prefix << "if " << data.name << " is not None:"
|
||||
<< std::endl;
|
||||
std::cout << prefix << " if (<" << strippedType
|
||||
<< "Type> result).modelptr" << d.name << " == (<" << strippedType
|
||||
<< "Type> " << data.name << ").modelptr:" << std::endl;
|
||||
std::cout << prefix << " (<" << strippedType
|
||||
<< "Type> result).modelptr = <" << strippedType << "*> 0"
|
||||
<< std::endl;
|
||||
std::cout << prefix << " result = " << data.name << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -194,15 +228,50 @@ void PrintOutputProcessing(
|
||||
* This gives us code like:
|
||||
*
|
||||
* result['name'] = ModelType()
|
||||
* MoveToPtr[Model*]((<ModelType?> result['name']).modelptr),
|
||||
* CLI.GetParam[Model]('name'))
|
||||
* (<ModelType?> result['name']).modelptr = GetParamPtr[Model]('name'))
|
||||
*/
|
||||
std::cout << prefix << "result['" << d.name << "'] = " << strippedType
|
||||
<< "Type()" << std::endl;
|
||||
std::cout << prefix << "MoveToPtr[" << strippedType << "]((<"
|
||||
<< strippedType << "Type?>" << " result['" << d.name
|
||||
<< "']).modelptr, CLI.GetParam[" << strippedType << "]('"
|
||||
<< d.name << "'))" << std::endl;
|
||||
std::cout << prefix << "(<" << strippedType << "Type?> result['" << d.name
|
||||
<< "']).modelptr = GetParamPtr[" << strippedType << "]('" << d.name
|
||||
<< "')" << std::endl;
|
||||
|
||||
/**
|
||||
* But we also have to check to ensure there aren't any input model
|
||||
* parameters of the same type that could have the same model pointer.
|
||||
* So we need to loop through all input parameters that have the same type,
|
||||
* and double-check.
|
||||
*/
|
||||
std::map<std::string, util::ParamData>& parameters = CLI::Parameters();
|
||||
for (auto it = parameters.begin(); it != parameters.end(); ++it)
|
||||
{
|
||||
// Is it an input parameter of the same type?
|
||||
const util::ParamData& data = it->second;
|
||||
if (data.input && data.cppType == d.cppType && data.required)
|
||||
{
|
||||
std::cout << prefix << "if (<" << strippedType << "Type> result['"
|
||||
<< d.name << "']).modelptr == (<" << strippedType << "Type> "
|
||||
<< data.name << ").modelptr:" << std::endl;
|
||||
std::cout << prefix << " (<" << strippedType << "Type> result['"
|
||||
<< d.name << "']).modelptr = <" << strippedType << "*> 0"
|
||||
<< std::endl;
|
||||
std::cout << prefix << " result['" << d.name << "'] = " << data.name
|
||||
<< std::endl;
|
||||
}
|
||||
else if (data.input && data.cppType == d.cppType)
|
||||
{
|
||||
std::cout << prefix << "if " << data.name << " is not None:"
|
||||
<< std::endl;
|
||||
std::cout << prefix << " if (<" << strippedType << "Type> result['"
|
||||
<< d.name << "']).modelptr == (<" << strippedType << "Type> "
|
||||
<< data.name << ").modelptr:" << std::endl;
|
||||
std::cout << prefix << " (<" << strippedType << "Type> result['"
|
||||
<< d.name << "']).modelptr = <" << strippedType << "*> 0"
|
||||
<< std::endl;
|
||||
std::cout << prefix << " result['" << d.name << "'] = " << data.name
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -227,7 +296,8 @@ void PrintOutputProcessing(const util::ParamData& d,
|
||||
{
|
||||
std::tuple<size_t, bool>* tuple = (std::tuple<size_t, bool>*) input;
|
||||
|
||||
PrintOutputProcessing<T>(d, std::get<0>(*tuple), std::get<1>(*tuple));
|
||||
PrintOutputProcessing<typename std::remove_pointer<T>::type>(d,
|
||||
std::get<0>(*tuple), std::get<1>(*tuple));
|
||||
}
|
||||
|
||||
} // namespace python
|
||||
|
||||
@@ -71,10 +71,10 @@ void PrintPYX(const ProgramDoc& programInfo,
|
||||
cout << "cimport arma" << endl;
|
||||
cout << "cimport arma_numpy" << endl;
|
||||
cout << "from cli cimport CLI" << endl;
|
||||
cout << "from cli cimport SetParam, SetParamWithInfo" << endl;
|
||||
cout << "from cli cimport SetParam, SetParamPtr, SetParamWithInfo, "
|
||||
<< "GetParamPtr" << endl;
|
||||
cout << "from cli cimport EnableVerbose, DisableVerbose, DisableBacktrace, "
|
||||
<< "ResetTimers, EnableTimers" << endl;
|
||||
cout << "from cli cimport MoveFromPtr, MoveToPtr" << endl;
|
||||
cout << "from matrix_utils import to_matrix, to_matrix_with_info" << endl;
|
||||
cout << "from serialization cimport SerializeIn, SerializeOut" << endl;
|
||||
cout << endl;
|
||||
@@ -177,7 +177,14 @@ void PrintPYX(const ProgramDoc& programInfo,
|
||||
cout << " DisableVerbose()" << endl;
|
||||
|
||||
// Restore the parameters.
|
||||
cout << " CLI.RestoreSettings(\"" << programInfo.programName << "\")";
|
||||
cout << " CLI.RestoreSettings(\"" << programInfo.programName << "\")"
|
||||
<< endl;
|
||||
|
||||
// Determine whether or not we need to copy parameters.
|
||||
cout << " if copy_all_inputs:" << endl;
|
||||
cout << " SetParam[bool](<const string> 'copy_all_inputs', "
|
||||
<< "copy_all_inputs)" << endl;
|
||||
cout << " CLI.SetPassed(<const string> 'copy_all_inputs')" << endl;
|
||||
|
||||
// Do any input processing.
|
||||
for (size_t i = 0; i < inputOptions.size(); ++i)
|
||||
|
||||
@@ -58,8 +58,8 @@ class PyOption
|
||||
data.required = required;
|
||||
data.input = input;
|
||||
data.loaded = false;
|
||||
// Only "verbose" will be persistent.
|
||||
if (identifier == "verbose")
|
||||
// Only "verbose" and "copy_all_inputs" will be persistent.
|
||||
if (identifier == "verbose" || identifier == "copy_all_inputs")
|
||||
data.persistent = true;
|
||||
else
|
||||
data.persistent = false;
|
||||
|
||||
@@ -23,7 +23,7 @@ class TestToMatrix(unittest.TestCase):
|
||||
"""
|
||||
d = pd.DataFrame(np.random.randn(100, 4), columns=list('abcd'))
|
||||
|
||||
m = to_matrix(d)
|
||||
m, _ = to_matrix(d)
|
||||
|
||||
self.assertTrue(isinstance(m, np.ndarray))
|
||||
self.assertEqual(m.shape[0], 100)
|
||||
@@ -40,7 +40,7 @@ class TestToMatrix(unittest.TestCase):
|
||||
"""
|
||||
d = pd.DataFrame({'a': range(5)})
|
||||
|
||||
m = to_matrix(d)
|
||||
m, _ = to_matrix(d)
|
||||
|
||||
self.assertTrue(isinstance(m, np.ndarray))
|
||||
self.assertEqual(m.shape[0], 5)
|
||||
@@ -58,7 +58,7 @@ class TestToMatrix(unittest.TestCase):
|
||||
self.assertEqual(d['a'].dtype, int)
|
||||
self.assertEqual(d['b'].dtype, np.dtype(np.double))
|
||||
|
||||
m = to_matrix(d)
|
||||
m, _ = to_matrix(d)
|
||||
|
||||
self.assertTrue(isinstance(m, np.ndarray))
|
||||
self.assertEqual(m.dtype, np.dtype(np.double))
|
||||
@@ -79,7 +79,7 @@ class TestToMatrix(unittest.TestCase):
|
||||
[0.07, 0.08, 0.09],
|
||||
[0.10, 0.11, 0.12]]
|
||||
|
||||
m = to_matrix(a)
|
||||
m, _ = to_matrix(a)
|
||||
|
||||
self.assertTrue(isinstance(m, np.ndarray))
|
||||
self.assertEqual(m.dtype, np.dtype(np.double))
|
||||
@@ -100,7 +100,7 @@ class TestToMatrix(unittest.TestCase):
|
||||
[0.07, 0.08, 9],
|
||||
[0.10, 0.11, 12]]
|
||||
|
||||
m = to_matrix(a)
|
||||
m, _ = to_matrix(a)
|
||||
|
||||
self.assertTrue(isinstance(m, np.ndarray))
|
||||
self.assertEqual(m.dtype, np.dtype(np.double))
|
||||
@@ -116,7 +116,7 @@ class TestToMatrix(unittest.TestCase):
|
||||
Make sure we can convert a numpy matrix without copying anything.
|
||||
"""
|
||||
m1 = np.random.randn(100, 5)
|
||||
m2 = to_matrix(m1)
|
||||
m2, _ = to_matrix(m1)
|
||||
|
||||
self.assertTrue(isinstance(m2, np.ndarray))
|
||||
self.assertEqual(m2.dtype, np.dtype(np.double))
|
||||
@@ -144,7 +144,7 @@ class TestToMatrixWithInfo(unittest.TestCase):
|
||||
"""
|
||||
d = pd.DataFrame(np.random.randn(100, 4), columns=list('abcd'))
|
||||
|
||||
m, dims = to_matrix_with_info(d, np.double)
|
||||
m, _, dims = to_matrix_with_info(d, np.double)
|
||||
|
||||
self.assertTrue(isinstance(m, np.ndarray))
|
||||
self.assertEqual(m.shape[0], 100)
|
||||
@@ -167,7 +167,7 @@ class TestToMatrixWithInfo(unittest.TestCase):
|
||||
"""
|
||||
d = pd.DataFrame({'a': range(5)})
|
||||
|
||||
m, dims = to_matrix_with_info(d, np.double)
|
||||
m, _, dims = to_matrix_with_info(d, np.double)
|
||||
|
||||
self.assertTrue(isinstance(m, np.ndarray))
|
||||
self.assertEqual(m.shape[0], 5)
|
||||
@@ -188,7 +188,7 @@ class TestToMatrixWithInfo(unittest.TestCase):
|
||||
self.assertEqual(d['a'].dtype, int)
|
||||
self.assertEqual(d['b'].dtype, np.dtype(np.double))
|
||||
|
||||
m, dims = to_matrix_with_info(d, np.double)
|
||||
m, _, dims = to_matrix_with_info(d, np.double)
|
||||
|
||||
self.assertTrue(isinstance(m, np.ndarray))
|
||||
self.assertEqual(m.dtype, np.dtype(np.double))
|
||||
@@ -213,7 +213,7 @@ class TestToMatrixWithInfo(unittest.TestCase):
|
||||
[0.07, 0.08, 0.09],
|
||||
[0.10, 0.11, 0.12]]
|
||||
|
||||
m, dims = to_matrix_with_info(a, np.double)
|
||||
m, _, dims = to_matrix_with_info(a, np.double)
|
||||
|
||||
self.assertTrue(isinstance(m, np.ndarray))
|
||||
self.assertEqual(m.dtype, np.dtype(np.double))
|
||||
@@ -239,7 +239,7 @@ class TestToMatrixWithInfo(unittest.TestCase):
|
||||
[0.07, 0.08, 9],
|
||||
[0.10, 0.11, 12]]
|
||||
|
||||
m, dims = to_matrix_with_info(a, np.double)
|
||||
m, _, dims = to_matrix_with_info(a, np.double)
|
||||
|
||||
self.assertTrue(isinstance(m, np.ndarray))
|
||||
self.assertEqual(m.dtype, np.dtype(np.double))
|
||||
@@ -260,7 +260,7 @@ class TestToMatrixWithInfo(unittest.TestCase):
|
||||
Make sure we can convert a numpy matrix without copying anything.
|
||||
"""
|
||||
m1 = np.random.randn(100, 5)
|
||||
m2, dims = to_matrix_with_info(m1, np.double)
|
||||
m2, _, dims = to_matrix_with_info(m1, np.double)
|
||||
|
||||
self.assertTrue(isinstance(m2, np.ndarray))
|
||||
self.assertEqual(m2.dtype, np.dtype(np.double))
|
||||
@@ -284,7 +284,7 @@ class TestToMatrixWithInfo(unittest.TestCase):
|
||||
d = pd.DataFrame({"A": ["a", "b", "c", "a"] })
|
||||
d["A"] = d["A"].astype('category') # Convert to categorical.
|
||||
|
||||
m, dims = to_matrix_with_info(d, np.double)
|
||||
m, _, dims = to_matrix_with_info(d, np.double)
|
||||
|
||||
self.assertTrue(isinstance(m, np.ndarray))
|
||||
self.assertEqual(m.dtype, np.dtype(np.double))
|
||||
|
||||
@@ -7,6 +7,7 @@ Test that passing types to Python bindings works successfully.
|
||||
import unittest
|
||||
import pandas as pd
|
||||
import numpy as np
|
||||
import copy
|
||||
|
||||
from mlpack.test_python_binding import test_python_binding
|
||||
|
||||
@@ -94,11 +95,35 @@ class TestPythonBinding(unittest.TestCase):
|
||||
and the fifth forgotten.
|
||||
"""
|
||||
x = np.random.rand(100, 5);
|
||||
z = copy.copy(x)
|
||||
|
||||
output = test_python_binding(string_in='hello',
|
||||
int_in=12,
|
||||
double_in=4.0,
|
||||
matrix_in=x)
|
||||
matrix_in=z)
|
||||
|
||||
self.assertEqual(output['matrix_out'].shape[0], 100)
|
||||
self.assertEqual(output['matrix_out'].shape[1], 4)
|
||||
self.assertEqual(output['matrix_out'].dtype, np.double)
|
||||
for i in [0, 1, 3]:
|
||||
for j in range(100):
|
||||
self.assertEqual(x[j, i], output['matrix_out'][j, i])
|
||||
|
||||
for j in range(100):
|
||||
self.assertEqual(2 * x[j, 2], output['matrix_out'][j, 2])
|
||||
|
||||
def testNumpyMatrixForceCopy(self):
|
||||
"""
|
||||
The matrix we pass in, we should get back with the third dimension doubled
|
||||
and the fifth forgotten.
|
||||
"""
|
||||
x = np.random.rand(100, 5);
|
||||
|
||||
output = test_python_binding(string_in='hello',
|
||||
int_in=12,
|
||||
double_in=4.0,
|
||||
matrix_in=x,
|
||||
copy_all_inputs=True)
|
||||
|
||||
self.assertEqual(output['matrix_out'].shape[0], 100)
|
||||
self.assertEqual(output['matrix_out'].shape[1], 4)
|
||||
@@ -139,16 +164,71 @@ class TestPythonBinding(unittest.TestCase):
|
||||
self.assertEqual(output['matrix_out'][2, 2], 26)
|
||||
self.assertEqual(output['matrix_out'][2, 3], 14)
|
||||
|
||||
def testArraylikeMatrixForceCopy(self):
|
||||
"""
|
||||
Test that we can pass an arraylike matrix.
|
||||
"""
|
||||
x = [[1, 2, 3, 4, 5],
|
||||
[6, 7, 8, 9, 10],
|
||||
[11, 12, 13, 14, 15]]
|
||||
|
||||
output = test_python_binding(string_in='hello',
|
||||
int_in=12,
|
||||
double_in=4.0,
|
||||
matrix_in=x,
|
||||
copy_all_inputs=True)
|
||||
|
||||
self.assertEqual(output['matrix_out'].shape[0], 3)
|
||||
self.assertEqual(output['matrix_out'].shape[1], 4)
|
||||
self.assertEqual(len(x), 3)
|
||||
self.assertEqual(len(x[0]), 5)
|
||||
self.assertEqual(output['matrix_out'].dtype, np.double)
|
||||
self.assertEqual(output['matrix_out'][0, 0], 1)
|
||||
self.assertEqual(output['matrix_out'][0, 1], 2)
|
||||
self.assertEqual(output['matrix_out'][0, 2], 6)
|
||||
self.assertEqual(output['matrix_out'][0, 3], 4)
|
||||
self.assertEqual(output['matrix_out'][1, 0], 6)
|
||||
self.assertEqual(output['matrix_out'][1, 1], 7)
|
||||
self.assertEqual(output['matrix_out'][1, 2], 16)
|
||||
self.assertEqual(output['matrix_out'][1, 3], 9)
|
||||
self.assertEqual(output['matrix_out'][2, 0], 11)
|
||||
self.assertEqual(output['matrix_out'][2, 1], 12)
|
||||
self.assertEqual(output['matrix_out'][2, 2], 26)
|
||||
self.assertEqual(output['matrix_out'][2, 3], 14)
|
||||
|
||||
def testNumpyUmatrix(self):
|
||||
"""
|
||||
Same as testNumpyMatrix() but with an unsigned matrix.
|
||||
"""
|
||||
x = np.random.randint(0, high=500, size=[100, 5])
|
||||
z = copy.copy(x)
|
||||
|
||||
output = test_python_binding(string_in='hello',
|
||||
int_in=12,
|
||||
double_in=4.0,
|
||||
umatrix_in=z)
|
||||
|
||||
self.assertEqual(output['umatrix_out'].shape[0], 100)
|
||||
self.assertEqual(output['umatrix_out'].shape[1], 4)
|
||||
self.assertEqual(output['umatrix_out'].dtype, np.long)
|
||||
for i in [0, 1, 3]:
|
||||
for j in range(100):
|
||||
self.assertEqual(x[j, i], output['umatrix_out'][j, i])
|
||||
|
||||
for j in range(100):
|
||||
self.assertEqual(2 * x[j, 2], output['umatrix_out'][j, 2])
|
||||
|
||||
def testNumpyUmatrixForceCopy(self):
|
||||
"""
|
||||
Same as testNumpyMatrix() but with an unsigned matrix.
|
||||
"""
|
||||
x = np.random.randint(0, high=500, size=[100, 5])
|
||||
|
||||
output = test_python_binding(string_in='hello',
|
||||
int_in=12,
|
||||
double_in=4.0,
|
||||
umatrix_in=x)
|
||||
umatrix_in=x,
|
||||
copy_all_inputs=True)
|
||||
|
||||
self.assertEqual(output['umatrix_out'].shape[0], 100)
|
||||
self.assertEqual(output['umatrix_out'].shape[1], 4)
|
||||
@@ -189,16 +269,67 @@ class TestPythonBinding(unittest.TestCase):
|
||||
self.assertEqual(output['umatrix_out'][2, 2], 26)
|
||||
self.assertEqual(output['umatrix_out'][2, 3], 14)
|
||||
|
||||
def testArraylikeUmatrixForceCopy(self):
|
||||
"""
|
||||
Test that we can pass an arraylike unsigned matrix.
|
||||
"""
|
||||
x = [[1, 2, 3, 4, 5],
|
||||
[6, 7, 8, 9, 10],
|
||||
[11, 12, 13, 14, 15]]
|
||||
|
||||
output = test_python_binding(string_in='hello',
|
||||
int_in=12,
|
||||
double_in=4.0,
|
||||
umatrix_in=x,
|
||||
copy_all_inputs=True)
|
||||
|
||||
self.assertEqual(output['umatrix_out'].shape[0], 3)
|
||||
self.assertEqual(output['umatrix_out'].shape[1], 4)
|
||||
self.assertEqual(len(x), 3)
|
||||
self.assertEqual(len(x[0]), 5)
|
||||
self.assertEqual(output['umatrix_out'].dtype, np.long)
|
||||
self.assertEqual(output['umatrix_out'][0, 0], 1)
|
||||
self.assertEqual(output['umatrix_out'][0, 1], 2)
|
||||
self.assertEqual(output['umatrix_out'][0, 2], 6)
|
||||
self.assertEqual(output['umatrix_out'][0, 3], 4)
|
||||
self.assertEqual(output['umatrix_out'][1, 0], 6)
|
||||
self.assertEqual(output['umatrix_out'][1, 1], 7)
|
||||
self.assertEqual(output['umatrix_out'][1, 2], 16)
|
||||
self.assertEqual(output['umatrix_out'][1, 3], 9)
|
||||
self.assertEqual(output['umatrix_out'][2, 0], 11)
|
||||
self.assertEqual(output['umatrix_out'][2, 1], 12)
|
||||
self.assertEqual(output['umatrix_out'][2, 2], 26)
|
||||
self.assertEqual(output['umatrix_out'][2, 3], 14)
|
||||
|
||||
def testCol(self):
|
||||
"""
|
||||
Test a column vector input parameter.
|
||||
"""
|
||||
x = np.random.rand(100)
|
||||
z = copy.copy(x)
|
||||
|
||||
output = test_python_binding(string_in='hello',
|
||||
int_in=12,
|
||||
double_in=4.0,
|
||||
col_in=z)
|
||||
|
||||
self.assertEqual(output['col_out'].shape[0], 100)
|
||||
self.assertEqual(output['col_out'].dtype, np.double)
|
||||
|
||||
for i in range(100):
|
||||
self.assertEqual(output['col_out'][i], x[i] * 2)
|
||||
|
||||
def testColForceCopy(self):
|
||||
"""
|
||||
Test a column vector input parameter.
|
||||
"""
|
||||
x = np.random.rand(100)
|
||||
|
||||
output = test_python_binding(string_in='hello',
|
||||
int_in=12,
|
||||
double_in=4.0,
|
||||
col_in=x)
|
||||
col_in=x,
|
||||
copy_all_inputs=True)
|
||||
|
||||
self.assertEqual(output['col_out'].shape[0], 100)
|
||||
self.assertEqual(output['col_out'].dtype, np.double)
|
||||
@@ -211,11 +342,29 @@ class TestPythonBinding(unittest.TestCase):
|
||||
Test an unsigned column vector input parameter.
|
||||
"""
|
||||
x = np.random.randint(0, high=500, size=100)
|
||||
z = copy.copy(x)
|
||||
|
||||
output = test_python_binding(string_in='hello',
|
||||
int_in=12,
|
||||
double_in=4.0,
|
||||
ucol_in=x)
|
||||
ucol_in=z)
|
||||
|
||||
self.assertEqual(output['ucol_out'].shape[0], 100)
|
||||
self.assertEqual(output['ucol_out'].dtype, np.long)
|
||||
for i in range(100):
|
||||
self.assertEqual(output['ucol_out'][i], x[i] * 2)
|
||||
|
||||
def testUcolForceCopy(self):
|
||||
"""
|
||||
Test an unsigned column vector input parameter.
|
||||
"""
|
||||
x = np.random.randint(0, high=500, size=100)
|
||||
|
||||
output = test_python_binding(string_in='hello',
|
||||
int_in=12,
|
||||
double_in=4.0,
|
||||
ucol_in=x,
|
||||
copy_all_inputs=True)
|
||||
|
||||
self.assertEqual(output['ucol_out'].shape[0], 100)
|
||||
self.assertEqual(output['ucol_out'].dtype, np.long)
|
||||
@@ -227,11 +376,30 @@ class TestPythonBinding(unittest.TestCase):
|
||||
Test a row vector input parameter.
|
||||
"""
|
||||
x = np.random.rand(100)
|
||||
z = copy.copy(x)
|
||||
|
||||
output = test_python_binding(string_in='hello',
|
||||
int_in=12,
|
||||
double_in=4.0,
|
||||
row_in=x)
|
||||
row_in=z)
|
||||
|
||||
self.assertEqual(output['row_out'].shape[0], 100)
|
||||
self.assertEqual(output['row_out'].dtype, np.double)
|
||||
|
||||
for i in range(100):
|
||||
self.assertEqual(output['row_out'][i], x[i] * 2)
|
||||
|
||||
def testRowForceCopy(self):
|
||||
"""
|
||||
Test a row vector input parameter.
|
||||
"""
|
||||
x = np.random.rand(100)
|
||||
|
||||
output = test_python_binding(string_in='hello',
|
||||
int_in=12,
|
||||
double_in=4.0,
|
||||
row_in=x,
|
||||
copy_all_inputs=True)
|
||||
|
||||
self.assertEqual(output['row_out'].shape[0], 100)
|
||||
self.assertEqual(output['row_out'].dtype, np.double)
|
||||
@@ -244,11 +412,30 @@ class TestPythonBinding(unittest.TestCase):
|
||||
Test an unsigned row vector input parameter.
|
||||
"""
|
||||
x = np.random.randint(0, high=500, size=100)
|
||||
z = copy.copy(x)
|
||||
|
||||
output = test_python_binding(string_in='hello',
|
||||
int_in=12,
|
||||
double_in=4.0,
|
||||
urow_in=x)
|
||||
urow_in=z)
|
||||
|
||||
self.assertEqual(output['urow_out'].shape[0], 100)
|
||||
self.assertEqual(output['urow_out'].dtype, np.long)
|
||||
|
||||
for i in range(100):
|
||||
self.assertEqual(output['urow_out'][i], x[i] * 2)
|
||||
|
||||
def testUrowForceCopy(self):
|
||||
"""
|
||||
Test an unsigned row vector input parameter.
|
||||
"""
|
||||
x = np.random.randint(0, high=500, size=100)
|
||||
|
||||
output = test_python_binding(string_in='hello',
|
||||
int_in=12,
|
||||
double_in=4.0,
|
||||
urow_in=x,
|
||||
copy_all_inputs=True)
|
||||
|
||||
self.assertEqual(output['urow_out'].shape[0], 100)
|
||||
self.assertEqual(output['urow_out'].dtype, np.long)
|
||||
@@ -261,11 +448,31 @@ class TestPythonBinding(unittest.TestCase):
|
||||
Test that we can pass a matrix with all numeric features.
|
||||
"""
|
||||
x = np.random.rand(100, 10)
|
||||
z = copy.copy(x)
|
||||
|
||||
output = test_python_binding(string_in='hello',
|
||||
int_in=12,
|
||||
double_in=4.0,
|
||||
matrix_and_info_in=x)
|
||||
matrix_and_info_in=z)
|
||||
|
||||
self.assertEqual(output['matrix_and_info_out'].shape[0], 100)
|
||||
self.assertEqual(output['matrix_and_info_out'].shape[1], 10)
|
||||
|
||||
for i in range(10):
|
||||
for j in range(100):
|
||||
self.assertEqual(output['matrix_and_info_out'][j, i], x[j, i] * 2.0)
|
||||
|
||||
def testMatrixAndInfoNumpyForceCopy(self):
|
||||
"""
|
||||
Test that we can pass a matrix with all numeric features.
|
||||
"""
|
||||
x = np.random.rand(100, 10)
|
||||
|
||||
output = test_python_binding(string_in='hello',
|
||||
int_in=12,
|
||||
double_in=4.0,
|
||||
matrix_and_info_in=x,
|
||||
copy_all_inputs=True)
|
||||
|
||||
self.assertEqual(output['matrix_and_info_out'].shape[0], 100)
|
||||
self.assertEqual(output['matrix_and_info_out'].shape[1], 10)
|
||||
@@ -281,11 +488,38 @@ class TestPythonBinding(unittest.TestCase):
|
||||
x = pd.DataFrame(np.random.rand(10, 4), columns=list('abcd'))
|
||||
x['e'] = pd.Series(['a', 'b', 'c', 'd', 'a', 'b', 'e', 'c', 'a', 'b'],
|
||||
dtype='category')
|
||||
z = copy.copy(x)
|
||||
|
||||
output = test_python_binding(string_in='hello',
|
||||
int_in=12,
|
||||
double_in=4.0,
|
||||
matrix_and_info_in=x)
|
||||
matrix_and_info_in=z)
|
||||
|
||||
self.assertEqual(output['matrix_and_info_out'].shape[0], 10)
|
||||
self.assertEqual(output['matrix_and_info_out'].shape[1], 5)
|
||||
|
||||
cols = list('abcde')
|
||||
|
||||
for i in range(4):
|
||||
for j in range(10):
|
||||
self.assertEqual(output['matrix_and_info_out'][j, i], z[cols[i]][j] * 2)
|
||||
|
||||
for j in range(10):
|
||||
self.assertEqual(output['matrix_and_info_out'][j, 4], z[cols[4]][j])
|
||||
|
||||
def testMatrixAndInfoPandasForceCopy(self):
|
||||
"""
|
||||
Test that we can pass a matrix with some categorical features.
|
||||
"""
|
||||
x = pd.DataFrame(np.random.rand(10, 4), columns=list('abcd'))
|
||||
x['e'] = pd.Series(['a', 'b', 'c', 'd', 'a', 'b', 'e', 'c', 'a', 'b'],
|
||||
dtype='category')
|
||||
|
||||
output = test_python_binding(string_in='hello',
|
||||
int_in=12,
|
||||
double_in=4.0,
|
||||
matrix_and_info_in=x,
|
||||
copy_all_inputs=True)
|
||||
|
||||
self.assertEqual(output['matrix_and_info_out'].shape[0], 10)
|
||||
self.assertEqual(output['matrix_and_info_out'].shape[1], 5)
|
||||
@@ -345,5 +579,29 @@ class TestPythonBinding(unittest.TestCase):
|
||||
|
||||
self.assertEqual(output2['model_bw_out'], 20.0)
|
||||
|
||||
def testModelForceCopy(self):
|
||||
"""
|
||||
First create a GaussianKernel object, then send it back and make sure we get
|
||||
the right double value.
|
||||
"""
|
||||
output = test_python_binding(string_in='hello',
|
||||
int_in=12,
|
||||
double_in=4.0,
|
||||
build_model=True)
|
||||
|
||||
output2 = test_python_binding(string_in='hello',
|
||||
int_in=12,
|
||||
double_in=4.0,
|
||||
model_in=output['model_out'],
|
||||
copy_all_inputs=True)
|
||||
|
||||
output3 = test_python_binding(string_in='hello',
|
||||
int_in=12,
|
||||
double_in=4.0,
|
||||
model_in=output['model_out'])
|
||||
|
||||
self.assertEqual(output2['model_bw_out'], 20.0)
|
||||
self.assertEqual(output3['model_bw_out'], 20.0)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
||||
@@ -172,13 +172,13 @@ static void mlpackMain()
|
||||
// If we got a request to build a model, then build it.
|
||||
if (CLI::HasParam("build_model"))
|
||||
{
|
||||
CLI::GetParam<GaussianKernel>("model_out") = GaussianKernel(10.0);
|
||||
CLI::GetParam<GaussianKernel*>("model_out") = new GaussianKernel(10.0);
|
||||
}
|
||||
|
||||
// If we got an input model, double the bandwidth and output that.
|
||||
if (CLI::HasParam("model_in"))
|
||||
{
|
||||
CLI::GetParam<double>("model_bw_out") =
|
||||
CLI::GetParam<GaussianKernel>("model_in").Bandwidth() * 2.0;
|
||||
CLI::GetParam<GaussianKernel*>("model_in")->Bandwidth() * 2.0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
# Define the files we need to compile.
|
||||
# Anything not in this list will not be compiled into mlpack.
|
||||
set(SOURCES
|
||||
clean_memory.hpp
|
||||
clean_memory.cpp
|
||||
test_option.hpp
|
||||
ignore_check.hpp
|
||||
delete_allocated_memory.hpp
|
||||
get_allocated_memory.hpp
|
||||
get_param.hpp
|
||||
get_printable_param.hpp
|
||||
get_printable_param_impl.hpp
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
/**
|
||||
* @file clean_memory.cpp
|
||||
* @author Ryan Curtin
|
||||
*
|
||||
* Delete any pointers held by the CLI object.
|
||||
*/
|
||||
#include "clean_memory.hpp"
|
||||
|
||||
#include <mlpack/core.hpp>
|
||||
|
||||
namespace mlpack {
|
||||
namespace bindings {
|
||||
namespace tests {
|
||||
|
||||
/**
|
||||
* Delete any pointers held by the CLI object.
|
||||
*/
|
||||
void CleanMemory()
|
||||
{
|
||||
// If we are holding any pointers, then we "own" them. But we may hold the
|
||||
// same pointer twice, so we have to be careful to not delete it multiple
|
||||
// times.
|
||||
std::unordered_map<void*, const util::ParamData*> memoryAddresses;
|
||||
auto it = CLI::Parameters().begin();
|
||||
while (it != CLI::Parameters().end())
|
||||
{
|
||||
const util::ParamData& data = it->second;
|
||||
|
||||
void* result;
|
||||
CLI::GetSingleton().functionMap[data.tname]["GetAllocatedMemory"](data,
|
||||
NULL, (void*) &result);
|
||||
if (result != NULL && memoryAddresses.count(result) == 0)
|
||||
memoryAddresses[result] = &data;
|
||||
|
||||
++it;
|
||||
}
|
||||
|
||||
// Now we have all the unique addresses that need to be deleted.
|
||||
std::unordered_map<void*, const util::ParamData*>::const_iterator it2;
|
||||
it2 = memoryAddresses.begin();
|
||||
while (it2 != memoryAddresses.end())
|
||||
{
|
||||
const util::ParamData& data = *(it2->second);
|
||||
|
||||
CLI::GetSingleton().functionMap[data.tname]["DeleteAllocatedMemory"](data,
|
||||
NULL, NULL);
|
||||
|
||||
++it2;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace tests
|
||||
} // namespace bindings
|
||||
} // namespace mlpack
|
||||
@@ -0,0 +1,24 @@
|
||||
/**
|
||||
* @file clean_memory.hpp
|
||||
* @author Ryan Curtin
|
||||
*
|
||||
* Delete any unique pointers that are held by the CLI object. This is similar
|
||||
* to the code in end_program.hpp.
|
||||
*/
|
||||
#ifndef MLPACK_BINDINGS_TESTS_CLEAN_MEMORY_HPP
|
||||
#define MLPACK_BINDINGS_TESTS_CLEAN_MEMORY_HPP
|
||||
|
||||
namespace mlpack {
|
||||
namespace bindings {
|
||||
namespace tests {
|
||||
|
||||
/**
|
||||
* Delete any unique pointers that are held by the CLI object.
|
||||
*/
|
||||
void CleanMemory();
|
||||
|
||||
} // namespace tests
|
||||
} // namespace bindings
|
||||
} // namespace mlpack
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,56 @@
|
||||
/**
|
||||
* @file delete_allocated_memory.hpp
|
||||
* @author Ryan Curtin
|
||||
*
|
||||
* If any memory has been allocated by the parameter, delete it.
|
||||
*/
|
||||
#ifndef MLPACK_BINDINGS_CLI_DELETE_ALLOCATED_MEMORY_HPP
|
||||
#define MLPACK_BINDINGS_CLI_DELETE_ALLOCATED_MEMORY_HPP
|
||||
|
||||
#include <mlpack/core/util/param_data.hpp>
|
||||
|
||||
namespace mlpack {
|
||||
namespace bindings {
|
||||
namespace tests {
|
||||
|
||||
template<typename T>
|
||||
void DeleteAllocatedMemoryImpl(
|
||||
const util::ParamData& /* d */,
|
||||
const typename boost::disable_if<data::HasSerialize<T>>::type* = 0,
|
||||
const typename boost::disable_if<arma::is_arma_type<T>>::type* = 0)
|
||||
{
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void DeleteAllocatedMemoryImpl(
|
||||
const util::ParamData& /* d */,
|
||||
const typename boost::enable_if<arma::is_arma_type<T>>::type* = 0)
|
||||
{
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void DeleteAllocatedMemoryImpl(
|
||||
const util::ParamData& d,
|
||||
const typename boost::disable_if<arma::is_arma_type<T>>::type* = 0,
|
||||
const typename boost::enable_if<data::HasSerialize<T>>::type* = 0)
|
||||
{
|
||||
// Delete the allocated memory (hopefully we actually own it).
|
||||
delete *boost::any_cast<T*>(&d.value);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void DeleteAllocatedMemory(
|
||||
const util::ParamData& d,
|
||||
const void* /* input */,
|
||||
void* /* output */)
|
||||
{
|
||||
DeleteAllocatedMemoryImpl<typename std::remove_pointer<T>::type>(d);
|
||||
}
|
||||
|
||||
} // namespace tests
|
||||
} // namespace bindings
|
||||
} // namespace mlpack
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,57 @@
|
||||
/**
|
||||
* @file get_allocated_memory.hpp
|
||||
* @author Ryan Curtin
|
||||
*
|
||||
* If the parameter has a type that may need to be deleted, return the address
|
||||
* of that object. Otherwise return NULL.
|
||||
*/
|
||||
#ifndef MLPACK_BINDINGS_CLI_GET_ALLOCATED_MEMORY_HPP
|
||||
#define MLPACK_BINDINGS_CLI_GET_ALLOCATED_MEMORY_HPP
|
||||
|
||||
#include <mlpack/core/util/param_data.hpp>
|
||||
|
||||
namespace mlpack {
|
||||
namespace bindings {
|
||||
namespace tests {
|
||||
|
||||
template<typename T>
|
||||
void* GetAllocatedMemory(
|
||||
const util::ParamData& /* d */,
|
||||
const typename boost::disable_if<data::HasSerialize<T>>::type* = 0,
|
||||
const typename boost::disable_if<arma::is_arma_type<T>>::type* = 0)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void* GetAllocatedMemory(
|
||||
const util::ParamData& /* d */,
|
||||
const typename boost::enable_if<arma::is_arma_type<T>>::type* = 0)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void* GetAllocatedMemory(
|
||||
const util::ParamData& d,
|
||||
const typename boost::disable_if<arma::is_arma_type<T>>::type* = 0,
|
||||
const typename boost::enable_if<data::HasSerialize<T>>::type* = 0)
|
||||
{
|
||||
// Here we have a model; return its memory location.
|
||||
return *boost::any_cast<T*>(&d.value);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void GetAllocatedMemory(const util::ParamData& d,
|
||||
const void* /* input */,
|
||||
void* output)
|
||||
{
|
||||
*((void**) output) =
|
||||
GetAllocatedMemory<typename std::remove_pointer<T>::type>(d);
|
||||
}
|
||||
|
||||
} // namespace tests
|
||||
} // namespace bindings
|
||||
} // namespace mlpack
|
||||
|
||||
#endif
|
||||
@@ -72,7 +72,8 @@ void GetPrintableParam(const util::ParamData& data,
|
||||
const void* /* input */,
|
||||
void* output)
|
||||
{
|
||||
*((std::string*) output) = GetPrintableParam<T>(data);
|
||||
*((std::string*) output) =
|
||||
GetPrintableParam<typename std::remove_pointer<T>::type>(data);
|
||||
}
|
||||
|
||||
} // namespace tests
|
||||
|
||||
@@ -18,6 +18,8 @@
|
||||
#include <mlpack/core/util/cli.hpp>
|
||||
#include "get_printable_param.hpp"
|
||||
#include "get_param.hpp"
|
||||
#include "get_allocated_memory.hpp"
|
||||
#include "delete_allocated_memory.hpp"
|
||||
|
||||
namespace mlpack {
|
||||
namespace bindings {
|
||||
@@ -90,6 +92,10 @@ class TestOption
|
||||
CLI::GetSingleton().functionMap[tname]["GetPrintableParam"] =
|
||||
&GetPrintableParam<N>;
|
||||
CLI::GetSingleton().functionMap[tname]["GetParam"] = &GetParam<N>;
|
||||
CLI::GetSingleton().functionMap[tname]["GetAllocatedMemory"] =
|
||||
&GetAllocatedMemory<N>;
|
||||
CLI::GetSingleton().functionMap[tname]["DeleteAllocatedMemory"] =
|
||||
&DeleteAllocatedMemory<N>;
|
||||
|
||||
CLI::Add(std::move(data));
|
||||
|
||||
|
||||
@@ -74,6 +74,7 @@ int main(int argc, char** argv)
|
||||
|
||||
#include <mlpack/bindings/tests/test_option.hpp>
|
||||
#include <mlpack/bindings/tests/ignore_check.hpp>
|
||||
#include <mlpack/bindings/tests/clean_memory.hpp>
|
||||
|
||||
// These functions will do nothing.
|
||||
#define PRINT_PARAM_STRING(A) std::string(" ")
|
||||
@@ -138,6 +139,10 @@ static const std::string testName = "";
|
||||
|
||||
PARAM_FLAG("verbose", "Display informational messages and the full list of "
|
||||
"parameters and timers at the end of execution.", "v");
|
||||
PARAM_FLAG("copy_all_inputs", "If specified, all input parameters will be deep"
|
||||
" copied before the method is run. This is useful for debugging problems "
|
||||
"where the input parameters are being modified by the algorithm, but can "
|
||||
"slow down the code.", "");
|
||||
|
||||
// Nothing else needs to be defined---the binding will use mlpackMain() as-is.
|
||||
|
||||
|
||||
@@ -1058,9 +1058,9 @@ using DatasetInfo = DatasetMapper<IncrementPolicy, std::string>;
|
||||
// There are no uses of required models, so that is not an option to this
|
||||
// macro (it would be easy to add).
|
||||
#define PARAM_MODEL(TYPE, ID, DESC, ALIAS, REQ, IN) \
|
||||
static mlpack::util::Option<TYPE> \
|
||||
static mlpack::util::Option<TYPE*> \
|
||||
JOIN(cli_option_dummy_model_, __COUNTER__) \
|
||||
(TYPE(), ID, DESC, ALIAS, #TYPE, REQ, IN, false, testName);
|
||||
(nullptr, ID, DESC, ALIAS, #TYPE, REQ, IN, false, testName);
|
||||
#else
|
||||
// We have to do some really bizarre stuff since __COUNTER__ isn't defined. I
|
||||
// don't think we can absolutely guarantee success, but it should be "good
|
||||
@@ -1113,9 +1113,9 @@ using DatasetInfo = DatasetMapper<IncrementPolicy, std::string>;
|
||||
!TRANS, testName);
|
||||
|
||||
#define PARAM_MODEL(TYPE, ID, DESC, ALIAS, REQ, IN) \
|
||||
static mlpack::util::Option<TYPE> \
|
||||
static mlpack::util::Option<TYPE*> \
|
||||
JOIN(JOIN(cli_option_dummy_object_model_, __LINE__), opt) \
|
||||
(TYPE(), ID, DESC, ALIAS, #TYPE, REQ, IN, false, \
|
||||
(nullptr, ID, DESC, ALIAS, #TYPE, REQ, IN, false, \
|
||||
testName);
|
||||
#endif
|
||||
|
||||
|
||||
@@ -145,10 +145,11 @@ static void mlpackMain()
|
||||
|
||||
ReportIgnoredParam({{ "test", false }}, "output");
|
||||
|
||||
AdaBoostModel m;
|
||||
AdaBoostModel* m;
|
||||
if (CLI::HasParam("training"))
|
||||
{
|
||||
mat trainingData = std::move(CLI::GetParam<arma::mat>("training"));
|
||||
m = new AdaBoostModel();
|
||||
|
||||
// Load labels.
|
||||
arma::Row<size_t> labelsIn;
|
||||
@@ -172,28 +173,28 @@ static void mlpackMain()
|
||||
Row<size_t> labels;
|
||||
|
||||
// Normalize the labels.
|
||||
data::NormalizeLabels(labelsIn, labels, m.Mappings());
|
||||
data::NormalizeLabels(labelsIn, labels, m->Mappings());
|
||||
|
||||
// Get other training parameters.
|
||||
const double tolerance = CLI::GetParam<double>("tolerance");
|
||||
const size_t iterations = (size_t) CLI::GetParam<int>("iterations");
|
||||
const string weakLearner = CLI::GetParam<string>("weak_learner");
|
||||
if (weakLearner == "decision_stump")
|
||||
m.WeakLearnerType() = AdaBoostModel::WeakLearnerTypes::DECISION_STUMP;
|
||||
m->WeakLearnerType() = AdaBoostModel::WeakLearnerTypes::DECISION_STUMP;
|
||||
else if (weakLearner == "perceptron")
|
||||
m.WeakLearnerType() = AdaBoostModel::WeakLearnerTypes::PERCEPTRON;
|
||||
m->WeakLearnerType() = AdaBoostModel::WeakLearnerTypes::PERCEPTRON;
|
||||
|
||||
const size_t numClasses = m.Mappings().n_elem;
|
||||
const size_t numClasses = m->Mappings().n_elem;
|
||||
Log::Info << numClasses << " classes in dataset." << endl;
|
||||
|
||||
Timer::Start("adaboost_training");
|
||||
m.Train(trainingData, labels, numClasses, iterations, tolerance);
|
||||
m->Train(trainingData, labels, numClasses, iterations, tolerance);
|
||||
Timer::Stop("adaboost_training");
|
||||
}
|
||||
else
|
||||
{
|
||||
// We have a specified input model.
|
||||
m = std::move(CLI::GetParam<AdaBoostModel>("input_model"));
|
||||
m = CLI::GetParam<AdaBoostModel*>("input_model");
|
||||
}
|
||||
|
||||
// Perform classification, if desired.
|
||||
@@ -201,24 +202,21 @@ static void mlpackMain()
|
||||
{
|
||||
mat testingData = std::move(CLI::GetParam<arma::mat>("test"));
|
||||
|
||||
if (testingData.n_rows != m.Dimensionality())
|
||||
if (testingData.n_rows != m->Dimensionality())
|
||||
Log::Fatal << "Test data dimensionality (" << testingData.n_rows << ") "
|
||||
<< "must be the same as the model dimensionality ("
|
||||
<< m.Dimensionality() << ")!" << endl;
|
||||
<< m->Dimensionality() << ")!" << endl;
|
||||
|
||||
Row<size_t> predictedLabels(testingData.n_cols);
|
||||
Timer::Start("adaboost_classification");
|
||||
m.Classify(testingData, predictedLabels);
|
||||
m->Classify(testingData, predictedLabels);
|
||||
Timer::Stop("adaboost_classification");
|
||||
|
||||
Row<size_t> results;
|
||||
data::RevertLabels(predictedLabels, m.Mappings(), results);
|
||||
data::RevertLabels(predictedLabels, m->Mappings(), results);
|
||||
|
||||
if (CLI::HasParam("output"))
|
||||
CLI::GetParam<arma::Row<size_t>>("output") = std::move(results);
|
||||
CLI::GetParam<arma::Row<size_t>>("output") = std::move(results);
|
||||
}
|
||||
|
||||
// Should we save the model, too?
|
||||
if (CLI::HasParam("output_model"))
|
||||
CLI::GetParam<AdaBoostModel>("output_model") = std::move(m);
|
||||
CLI::GetParam<AdaBoostModel*>("output_model") = m;
|
||||
}
|
||||
|
||||
@@ -190,11 +190,12 @@ static void mlpackMain()
|
||||
}
|
||||
|
||||
// Do the building of a model, if necessary.
|
||||
ApproxKFNModel m;
|
||||
ApproxKFNModel* m;
|
||||
arma::mat referenceSet; // This may be used at query time.
|
||||
if (CLI::HasParam("reference"))
|
||||
{
|
||||
referenceSet = std::move(CLI::GetParam<arma::mat>("reference"));
|
||||
m = new ApproxKFNModel();
|
||||
|
||||
const size_t numTables = (size_t) CLI::GetParam<int>("num_tables");
|
||||
const size_t numProjections =
|
||||
@@ -205,16 +206,16 @@ static void mlpackMain()
|
||||
{
|
||||
Timer::Start("drusilla_select_construct");
|
||||
Log::Info << "Building DrusillaSelect model..." << endl;
|
||||
m.type = 0;
|
||||
m.ds = DrusillaSelect<>(referenceSet, numTables, numProjections);
|
||||
m->type = 0;
|
||||
m->ds = DrusillaSelect<>(referenceSet, numTables, numProjections);
|
||||
Timer::Stop("drusilla_select_construct");
|
||||
}
|
||||
else
|
||||
{
|
||||
Timer::Start("qdafn_construct");
|
||||
Log::Info << "Building QDAFN model..." << endl;
|
||||
m.type = 1;
|
||||
m.qdafn = QDAFN<>(referenceSet, numTables, numProjections);
|
||||
m->type = 1;
|
||||
m->qdafn = QDAFN<>(referenceSet, numTables, numProjections);
|
||||
Timer::Stop("qdafn_construct");
|
||||
}
|
||||
Log::Info << "Model built." << endl;
|
||||
@@ -222,7 +223,7 @@ static void mlpackMain()
|
||||
else
|
||||
{
|
||||
// We must load the model from what was passed.
|
||||
m = std::move(CLI::GetParam<ApproxKFNModel>("input_model"));
|
||||
m = CLI::GetParam<ApproxKFNModel*>("input_model");
|
||||
}
|
||||
|
||||
// Now, do we need to do any queries?
|
||||
@@ -238,12 +239,12 @@ static void mlpackMain()
|
||||
if (CLI::HasParam("query"))
|
||||
querySet = std::move(CLI::GetParam<arma::mat>("query"));
|
||||
|
||||
if (m.type == 0)
|
||||
if (m->type == 0)
|
||||
{
|
||||
Timer::Start("drusilla_select_search");
|
||||
Log::Info << "Searching for " << k << " furthest neighbors with "
|
||||
<< "DrusillaSelect..." << endl;
|
||||
m.ds.Search(set, k, neighbors, distances);
|
||||
m->ds.Search(set, k, neighbors, distances);
|
||||
Timer::Stop("drusilla_select_search");
|
||||
}
|
||||
else
|
||||
@@ -251,7 +252,7 @@ static void mlpackMain()
|
||||
Timer::Start("qdafn_search");
|
||||
Log::Info << "Searching for " << k << " furthest neighbors with "
|
||||
<< "QDAFN..." << endl;
|
||||
m.qdafn.Search(set, k, neighbors, distances);
|
||||
m->qdafn.Search(set, k, neighbors, distances);
|
||||
Timer::Stop("qdafn_search");
|
||||
}
|
||||
Log::Info << "Search complete." << endl;
|
||||
@@ -288,13 +289,9 @@ static void mlpackMain()
|
||||
}
|
||||
|
||||
// Save results, if desired.
|
||||
if (CLI::HasParam("neighbors"))
|
||||
CLI::GetParam<arma::Mat<size_t>>("neighbors") = std::move(neighbors);
|
||||
if (CLI::HasParam("distances"))
|
||||
CLI::GetParam<arma::mat>("distances") = std::move(distances);
|
||||
CLI::GetParam<arma::Mat<size_t>>("neighbors") = std::move(neighbors);
|
||||
CLI::GetParam<arma::mat>("distances") = std::move(distances);
|
||||
}
|
||||
|
||||
// Should we save the model?
|
||||
if (CLI::HasParam("output_model"))
|
||||
CLI::GetParam<ApproxKFNModel>("output_model") = std::move(m);
|
||||
CLI::GetParam<ApproxKFNModel*>("output_model") = m;
|
||||
}
|
||||
|
||||
@@ -115,7 +115,7 @@ PARAM_INT_IN("recommendations", "Number of recommendations to generate for each"
|
||||
|
||||
PARAM_INT_IN("seed", "Set the random seed (0 uses std::time(NULL)).", "s", 0);
|
||||
|
||||
void ComputeRecommendations(CF& cf,
|
||||
void ComputeRecommendations(CF* cf,
|
||||
const size_t numRecs,
|
||||
arma::Mat<size_t>& recommendations)
|
||||
{
|
||||
@@ -132,16 +132,16 @@ void ComputeRecommendations(CF& cf,
|
||||
|
||||
Log::Info << "Generating recommendations for " << users.n_elem << " users."
|
||||
<< endl;
|
||||
cf.GetRecommendations(numRecs, recommendations, users.row(0).t());
|
||||
cf->GetRecommendations(numRecs, recommendations, users.row(0).t());
|
||||
}
|
||||
else
|
||||
{
|
||||
Log::Info << "Generating recommendations for all users." << endl;
|
||||
cf.GetRecommendations(numRecs, recommendations);
|
||||
cf->GetRecommendations(numRecs, recommendations);
|
||||
}
|
||||
}
|
||||
|
||||
void ComputeRMSE(CF& cf)
|
||||
void ComputeRMSE(CF* cf)
|
||||
{
|
||||
// Now, compute each test point.
|
||||
arma::mat testData = std::move(CLI::GetParam<arma::mat>("test"));
|
||||
@@ -156,7 +156,7 @@ void ComputeRMSE(CF& cf)
|
||||
|
||||
// Now compute the RMSE.
|
||||
arma::vec predictions;
|
||||
cf.Predict(combinations, predictions);
|
||||
cf->Predict(combinations, predictions);
|
||||
|
||||
// Compute the root of the sum of the squared errors, divide by the number of
|
||||
// points to get the RMSE. It turns out this is just the L2-norm divided by
|
||||
@@ -168,7 +168,7 @@ void ComputeRMSE(CF& cf)
|
||||
Log::Info << "RMSE is " << rmse << "." << endl;
|
||||
}
|
||||
|
||||
void PerformAction(CF& c)
|
||||
void PerformAction(CF* c)
|
||||
{
|
||||
if (CLI::HasParam("query") || CLI::HasParam("all_user_recommendations"))
|
||||
{
|
||||
@@ -180,15 +180,13 @@ void PerformAction(CF& c)
|
||||
ComputeRecommendations(c, numRecs, recommendations);
|
||||
|
||||
// Save the output.
|
||||
if (CLI::HasParam("output"))
|
||||
CLI::GetParam<arma::Mat<size_t>>("output") = recommendations;
|
||||
CLI::GetParam<arma::Mat<size_t>>("output") = recommendations;
|
||||
}
|
||||
|
||||
if (CLI::HasParam("test"))
|
||||
ComputeRMSE(c);
|
||||
|
||||
if (CLI::HasParam("output_model"))
|
||||
CLI::GetParam<CF>("output_model") = std::move(c);
|
||||
CLI::GetParam<CF*>("output_model") = c;
|
||||
}
|
||||
|
||||
template<typename Factorizer>
|
||||
@@ -198,7 +196,7 @@ void PerformAction(Factorizer&& factorizer,
|
||||
{
|
||||
// Parameters for generating the CF object.
|
||||
const size_t neighborhood = (size_t) CLI::GetParam<int>("neighborhood");
|
||||
CF c(dataset, factorizer, neighborhood, rank);
|
||||
CF* c = new CF(dataset, factorizer, neighborhood, rank);
|
||||
|
||||
PerformAction(c);
|
||||
}
|
||||
@@ -323,7 +321,7 @@ static void mlpackMain()
|
||||
else
|
||||
{
|
||||
// Load an input model.
|
||||
CF c = std::move(CLI::GetParam<CF>("input_model"));
|
||||
CF* c = std::move(CLI::GetParam<CF*>("input_model"));
|
||||
|
||||
PerformAction(c);
|
||||
}
|
||||
|
||||
@@ -116,9 +116,10 @@ static void mlpackMain()
|
||||
ReportIgnoredParam({{ "test", false }}, "predictions");
|
||||
|
||||
// We must either load a model, or train a new stump.
|
||||
DSModel model;
|
||||
DSModel* model;
|
||||
if (CLI::HasParam("training"))
|
||||
{
|
||||
model = new DSModel();
|
||||
mat trainingData = std::move(CLI::GetParam<mat>("training"));
|
||||
|
||||
// Load labels, if necessary.
|
||||
@@ -140,18 +141,18 @@ static void mlpackMain()
|
||||
|
||||
// Normalize the labels.
|
||||
Row<size_t> labels;
|
||||
data::NormalizeLabels(labelsIn, labels, model.mappings);
|
||||
data::NormalizeLabels(labelsIn, labels, model->mappings);
|
||||
|
||||
const size_t bucketSize = CLI::GetParam<int>("bucket_size");
|
||||
const size_t classes = labels.max() + 1;
|
||||
|
||||
Timer::Start("training");
|
||||
model.stump.Train(trainingData, labels, classes, bucketSize);
|
||||
model->stump.Train(trainingData, labels, classes, bucketSize);
|
||||
Timer::Stop("training");
|
||||
}
|
||||
else
|
||||
{
|
||||
model = std::move(CLI::GetParam<DSModel>("input_model"));
|
||||
model = CLI::GetParam<DSModel*>("input_model");
|
||||
}
|
||||
|
||||
// Now, do we need to do any testing?
|
||||
@@ -160,21 +161,21 @@ static void mlpackMain()
|
||||
// Load the test file.
|
||||
mat testingData = std::move(CLI::GetParam<arma::mat>("test"));
|
||||
|
||||
if (testingData.n_rows <= model.stump.SplitDimension())
|
||||
if (testingData.n_rows <= model->stump.SplitDimension())
|
||||
Log::Fatal << "Test data dimensionality (" << testingData.n_rows << ") "
|
||||
<< "is too low; the trained stump requires at least "
|
||||
<< model.stump.SplitDimension() << " dimensions!" << endl;
|
||||
<< model->stump.SplitDimension() << " dimensions!" << endl;
|
||||
|
||||
Row<size_t> predictedLabels(testingData.n_cols);
|
||||
Timer::Start("testing");
|
||||
model.stump.Classify(testingData, predictedLabels);
|
||||
model->stump.Classify(testingData, predictedLabels);
|
||||
Timer::Stop("testing");
|
||||
|
||||
// Denormalize predicted labels, if we want to save them.
|
||||
if (CLI::HasParam("predictions"))
|
||||
{
|
||||
Row<size_t> actualLabels;
|
||||
data::RevertLabels(predictedLabels, model.mappings, actualLabels);
|
||||
data::RevertLabels(predictedLabels, model->mappings, actualLabels);
|
||||
|
||||
// Save the predicted labels as output.
|
||||
CLI::GetParam<Row<size_t>>("predictions") = std::move(actualLabels);
|
||||
@@ -182,6 +183,5 @@ static void mlpackMain()
|
||||
}
|
||||
|
||||
// Save the model, if desired.
|
||||
if (CLI::HasParam("output_model"))
|
||||
CLI::GetParam<DSModel>("output_model") = std::move(model);
|
||||
CLI::GetParam<DSModel*>("output_model") = model;
|
||||
}
|
||||
|
||||
@@ -137,13 +137,14 @@ static void mlpackMain()
|
||||
"leaf size must be positive");
|
||||
|
||||
// Load the model or build the tree.
|
||||
DecisionTreeModel model;
|
||||
DecisionTreeModel* model;
|
||||
arma::mat trainingSet;
|
||||
arma::Row<size_t> labels;
|
||||
|
||||
if (CLI::HasParam("training"))
|
||||
{
|
||||
model.info = std::move(std::get<0>(CLI::GetParam<TupleType>("training")));
|
||||
model = new DecisionTreeModel();
|
||||
model->info = std::move(std::get<0>(CLI::GetParam<TupleType>("training")));
|
||||
trainingSet = std::move(std::get<1>(CLI::GetParam<TupleType>("training")));
|
||||
if (CLI::HasParam("labels"))
|
||||
{
|
||||
@@ -169,12 +170,12 @@ static void mlpackMain()
|
||||
{
|
||||
arma::Row<double> weights =
|
||||
std::move(CLI::GetParam<arma::Mat<double>>("weights"));
|
||||
model.tree = DecisionTree<>(trainingSet, model.info, labels,
|
||||
model->tree = DecisionTree<>(trainingSet, model->info, labels,
|
||||
numClasses, weights, minLeafSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
model.tree = DecisionTree<>(trainingSet, model.info, labels,
|
||||
model->tree = DecisionTree<>(trainingSet, model->info, labels,
|
||||
numClasses, minLeafSize);
|
||||
}
|
||||
|
||||
@@ -184,7 +185,7 @@ static void mlpackMain()
|
||||
arma::Row<size_t> predictions;
|
||||
arma::mat probabilities;
|
||||
|
||||
model.tree.Classify(trainingSet, predictions, probabilities);
|
||||
model->tree.Classify(trainingSet, predictions, probabilities);
|
||||
|
||||
size_t correct = 0;
|
||||
for (size_t i = 0; i < trainingSet.n_cols; ++i)
|
||||
@@ -199,19 +200,19 @@ static void mlpackMain()
|
||||
}
|
||||
else
|
||||
{
|
||||
model = std::move(CLI::GetParam<DecisionTreeModel>("input_model"));
|
||||
model = CLI::GetParam<DecisionTreeModel*>("input_model");
|
||||
}
|
||||
|
||||
// Do we need to get predictions?
|
||||
if (CLI::HasParam("test"))
|
||||
{
|
||||
std::get<0>(CLI::GetRawParam<TupleType>("test")) = model.info;
|
||||
std::get<0>(CLI::GetRawParam<TupleType>("test")) = model->info;
|
||||
arma::mat testPoints = std::get<1>(CLI::GetParam<TupleType>("test"));
|
||||
|
||||
arma::Row<size_t> predictions;
|
||||
arma::mat probabilities;
|
||||
|
||||
model.tree.Classify(testPoints, predictions, probabilities);
|
||||
model->tree.Classify(testPoints, predictions, probabilities);
|
||||
|
||||
// Do we need to calculate accuracy?
|
||||
if (CLI::HasParam("test_labels"))
|
||||
@@ -231,13 +232,10 @@ static void mlpackMain()
|
||||
}
|
||||
|
||||
// Do we need to save outputs?
|
||||
if (CLI::HasParam("predictions"))
|
||||
CLI::GetParam<arma::Row<size_t>>("predictions") = std::move(predictions);
|
||||
if (CLI::HasParam("probabilities"))
|
||||
CLI::GetParam<arma::mat>("probabilities") = std::move(probabilities);
|
||||
CLI::GetParam<arma::Row<size_t>>("predictions") = predictions;
|
||||
CLI::GetParam<arma::mat>("probabilities") = probabilities;
|
||||
}
|
||||
|
||||
// Do we need to save the model?
|
||||
if (CLI::HasParam("output_model"))
|
||||
CLI::GetParam<DecisionTreeModel>("output_model") = std::move(model);
|
||||
CLI::GetParam<DecisionTreeModel*>("output_model") = model;
|
||||
}
|
||||
|
||||
@@ -168,7 +168,7 @@ static void mlpackMain()
|
||||
}
|
||||
else
|
||||
{
|
||||
tree = &CLI::GetParam<DTree<arma::mat>>("input_model");
|
||||
tree = CLI::GetParam<DTree<arma::mat>*>("input_model");
|
||||
}
|
||||
|
||||
// Compute the density at the provided test points and output the density in
|
||||
@@ -213,8 +213,7 @@ static void mlpackMain()
|
||||
if (!ofs.is_open())
|
||||
{
|
||||
Log::Warn << "Unable to open file '" << tagFile
|
||||
<< "' to save tag membership info."
|
||||
<< std::endl;
|
||||
<< "' to save tag membership info." << std::endl;
|
||||
}
|
||||
else if (CLI::HasParam("path_format"))
|
||||
{
|
||||
@@ -231,7 +230,7 @@ static void mlpackMain()
|
||||
else
|
||||
{
|
||||
Log::Warn << "Unknown path format specified: '" << pathFormat
|
||||
<< "'. Valid are: lr | lr-id | id-lr. Defaults to 'lr'." << endl;
|
||||
<< "'. Valid are: lr | lr-id | id-lr. Defaults to 'lr'." << endl;
|
||||
theFormat = PathCacher::FormatLR;
|
||||
}
|
||||
|
||||
@@ -284,10 +283,5 @@ static void mlpackMain()
|
||||
}
|
||||
|
||||
// Save the model, if desired.
|
||||
if (CLI::HasParam("output_model"))
|
||||
CLI::GetParam<DTree<arma::mat>>("output_model") = std::move(*tree);
|
||||
|
||||
// Clean up memory, if we need to.
|
||||
if (!CLI::HasParam("input_model") && !CLI::HasParam("output_model"))
|
||||
delete tree;
|
||||
CLI::GetParam<DTree<arma::mat>*>("output_model") = tree;
|
||||
}
|
||||
|
||||
@@ -111,10 +111,11 @@ static void mlpackMain()
|
||||
// Naive mode overrides single mode.
|
||||
ReportIgnoredParam({{ "naive", true }}, "single");
|
||||
|
||||
FastMKSModel model;
|
||||
FastMKSModel* model;
|
||||
arma::mat referenceData;
|
||||
if (CLI::HasParam("reference"))
|
||||
{
|
||||
model = new FastMKSModel();
|
||||
referenceData = std::move(CLI::GetParam<arma::mat>("reference"));
|
||||
|
||||
Log::Info << "Loaded reference data (" << referenceData.n_rows << " x "
|
||||
@@ -137,55 +138,55 @@ static void mlpackMain()
|
||||
if (kernelType == "linear")
|
||||
{
|
||||
LinearKernel lk;
|
||||
model.KernelType() = FastMKSModel::LINEAR_KERNEL;
|
||||
model.BuildModel(referenceData, lk, single, naive, base);
|
||||
model->KernelType() = FastMKSModel::LINEAR_KERNEL;
|
||||
model->BuildModel(referenceData, lk, single, naive, base);
|
||||
}
|
||||
else if (kernelType == "polynomial")
|
||||
{
|
||||
PolynomialKernel pk(degree, offset);
|
||||
model.KernelType() = FastMKSModel::POLYNOMIAL_KERNEL;
|
||||
model.BuildModel(referenceData, pk, single, naive, base);
|
||||
model->KernelType() = FastMKSModel::POLYNOMIAL_KERNEL;
|
||||
model->BuildModel(referenceData, pk, single, naive, base);
|
||||
}
|
||||
else if (kernelType == "cosine")
|
||||
{
|
||||
CosineDistance cd;
|
||||
model.KernelType() = FastMKSModel::COSINE_DISTANCE;
|
||||
model.BuildModel(referenceData, cd, single, naive, base);
|
||||
model->KernelType() = FastMKSModel::COSINE_DISTANCE;
|
||||
model->BuildModel(referenceData, cd, single, naive, base);
|
||||
}
|
||||
else if (kernelType == "gaussian")
|
||||
{
|
||||
GaussianKernel gk(bandwidth);
|
||||
model.KernelType() = FastMKSModel::GAUSSIAN_KERNEL;
|
||||
model.BuildModel(referenceData, gk, single, naive, base);
|
||||
model->KernelType() = FastMKSModel::GAUSSIAN_KERNEL;
|
||||
model->BuildModel(referenceData, gk, single, naive, base);
|
||||
}
|
||||
else if (kernelType == "epanechnikov")
|
||||
{
|
||||
EpanechnikovKernel ek(bandwidth);
|
||||
model.KernelType() = FastMKSModel::EPANECHNIKOV_KERNEL;
|
||||
model.BuildModel(referenceData, ek, single, naive, base);
|
||||
model->KernelType() = FastMKSModel::EPANECHNIKOV_KERNEL;
|
||||
model->BuildModel(referenceData, ek, single, naive, base);
|
||||
}
|
||||
else if (kernelType == "triangular")
|
||||
{
|
||||
TriangularKernel tk(bandwidth);
|
||||
model.KernelType() = FastMKSModel::TRIANGULAR_KERNEL;
|
||||
model.BuildModel(referenceData, tk, single, naive, base);
|
||||
model->KernelType() = FastMKSModel::TRIANGULAR_KERNEL;
|
||||
model->BuildModel(referenceData, tk, single, naive, base);
|
||||
}
|
||||
else if (kernelType == "hyptan")
|
||||
{
|
||||
HyperbolicTangentKernel htk(scale, offset);
|
||||
model.KernelType() = FastMKSModel::HYPTAN_KERNEL;
|
||||
model.BuildModel(referenceData, htk, single, naive, base);
|
||||
model->KernelType() = FastMKSModel::HYPTAN_KERNEL;
|
||||
model->BuildModel(referenceData, htk, single, naive, base);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Load model from file, then do whatever is necessary.
|
||||
model = std::move(CLI::GetParam<FastMKSModel>("input_model"));
|
||||
model = CLI::GetParam<FastMKSModel*>("input_model");
|
||||
}
|
||||
|
||||
// Set search preferences.
|
||||
model.Naive() = CLI::HasParam("naive");
|
||||
model.SingleMode() = CLI::HasParam("single");
|
||||
model->Naive() = CLI::HasParam("naive");
|
||||
model->SingleMode() = CLI::HasParam("single");
|
||||
|
||||
// Should we do search?
|
||||
if (CLI::HasParam("k"))
|
||||
@@ -202,23 +203,19 @@ static void mlpackMain()
|
||||
Log::Info << "Loaded query data (" << queryData.n_rows << " x "
|
||||
<< queryData.n_cols << ")." << endl;
|
||||
|
||||
model.Search(queryData, (size_t) CLI::GetParam<int>("k"), indices,
|
||||
model->Search(queryData, (size_t) CLI::GetParam<int>("k"), indices,
|
||||
kernels, base);
|
||||
}
|
||||
else
|
||||
{
|
||||
model.Search((size_t) CLI::GetParam<int>("k"), indices, kernels);
|
||||
model->Search((size_t) CLI::GetParam<int>("k"), indices, kernels);
|
||||
}
|
||||
|
||||
// Save output, if we were asked to.
|
||||
if (CLI::HasParam("kernels"))
|
||||
CLI::GetParam<arma::mat>("kernels") = std::move(kernels);
|
||||
|
||||
if (CLI::HasParam("indices"))
|
||||
CLI::GetParam<arma::Mat<size_t>>("indices") = std::move(indices);
|
||||
// Save output.
|
||||
CLI::GetParam<arma::mat>("kernels") = std::move(kernels);
|
||||
CLI::GetParam<arma::Mat<size_t>>("indices") = std::move(indices);
|
||||
}
|
||||
|
||||
// Save the model, if requested.
|
||||
if (CLI::HasParam("output_model"))
|
||||
CLI::GetParam<FastMKSModel>("output_model") = std::move(model);
|
||||
// Save the model.
|
||||
CLI::GetParam<FastMKSModel*>("output_model") = model;
|
||||
}
|
||||
|
||||
@@ -55,15 +55,14 @@ static void mlpackMain()
|
||||
RequireParamValue<int>("samples", [](int x) { return x > 0; }, true,
|
||||
"number of samples must be greater than 0");
|
||||
|
||||
GMM gmm = std::move(CLI::GetParam<GMM>("input_model"));
|
||||
GMM* gmm = CLI::GetParam<GMM*>("input_model");
|
||||
|
||||
size_t length = (size_t) CLI::GetParam<int>("samples");
|
||||
Log::Info << "Generating " << length << " samples..." << endl;
|
||||
arma::mat samples(gmm.Dimensionality(), length);
|
||||
arma::mat samples(gmm->Dimensionality(), length);
|
||||
for (size_t i = 0; i < length; ++i)
|
||||
samples.col(i) = gmm.Random();
|
||||
samples.col(i) = gmm->Random();
|
||||
|
||||
// Save, if the user asked for it.
|
||||
if (CLI::HasParam("output"))
|
||||
CLI::GetParam<arma::mat>("output") = std::move(samples);
|
||||
CLI::GetParam<arma::mat>("output") = std::move(samples);
|
||||
}
|
||||
|
||||
@@ -46,16 +46,15 @@ static void mlpackMain()
|
||||
RequireAtLeastOnePassed({ "output" }, false, "no results will be saved");
|
||||
|
||||
// Get the GMM and the points.
|
||||
GMM gmm = std::move(CLI::GetParam<GMM>("input_model"));
|
||||
GMM* gmm = CLI::GetParam<GMM*>("input_model");
|
||||
|
||||
arma::mat dataset = std::move(CLI::GetParam<arma::mat>("input"));
|
||||
|
||||
// Now calculate the probabilities.
|
||||
arma::rowvec probabilities(dataset.n_cols);
|
||||
for (size_t i = 0; i < dataset.n_cols; ++i)
|
||||
probabilities[i] = gmm.Probability(dataset.unsafe_col(i));
|
||||
probabilities[i] = gmm->Probability(dataset.unsafe_col(i));
|
||||
|
||||
// And save the result.
|
||||
if (CLI::HasParam("output"))
|
||||
CLI::GetParam<arma::mat>("output") = std::move(probabilities);
|
||||
CLI::GetParam<arma::mat>("output") = std::move(probabilities);
|
||||
}
|
||||
|
||||
@@ -153,17 +153,21 @@ static void mlpackMain()
|
||||
}
|
||||
|
||||
// Initialize GMM.
|
||||
GMM gmm(size_t(gaussians), dataPoints.n_rows);
|
||||
GMM* gmm;
|
||||
|
||||
if (CLI::HasParam("input_model"))
|
||||
{
|
||||
gmm = std::move(CLI::GetParam<GMM>("input_model"));
|
||||
gmm = CLI::GetParam<GMM*>("input_model");
|
||||
|
||||
if (gmm.Dimensionality() != dataPoints.n_rows)
|
||||
if (gmm->Dimensionality() != dataPoints.n_rows)
|
||||
Log::Fatal << "Given input data (with " << PRINT_PARAM_STRING("input")
|
||||
<< ") has dimensionality " << dataPoints.n_rows << ", but the initial"
|
||||
<< " model (given with " << PRINT_PARAM_STRING("input_model")
|
||||
<< " has dimensionality " << gmm.Dimensionality() << "!" << endl;
|
||||
<< " has dimensionality " << gmm->Dimensionality() << "!" << endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
gmm = new GMM(size_t(gaussians), dataPoints.n_rows);
|
||||
}
|
||||
|
||||
// Gather parameters for EMFit object.
|
||||
@@ -199,7 +203,7 @@ static void mlpackMain()
|
||||
// Compute the parameters of the model using the EM algorithm.
|
||||
Timer::Start("em");
|
||||
EMFit<KMeansType, DiagonalConstraint> em(maxIterations, tolerance, k);
|
||||
likelihood = gmm.Train(dataPoints, CLI::GetParam<int>("trials"), false,
|
||||
likelihood = gmm->Train(dataPoints, CLI::GetParam<int>("trials"), false,
|
||||
em);
|
||||
Timer::Stop("em");
|
||||
}
|
||||
@@ -208,7 +212,7 @@ static void mlpackMain()
|
||||
// Compute the parameters of the model using the EM algorithm.
|
||||
Timer::Start("em");
|
||||
EMFit<KMeansType> em(maxIterations, tolerance, k);
|
||||
likelihood = gmm.Train(dataPoints, CLI::GetParam<int>("trials"), false,
|
||||
likelihood = gmm->Train(dataPoints, CLI::GetParam<int>("trials"), false,
|
||||
em);
|
||||
Timer::Stop("em");
|
||||
}
|
||||
@@ -217,7 +221,7 @@ static void mlpackMain()
|
||||
// Compute the parameters of the model using the EM algorithm.
|
||||
Timer::Start("em");
|
||||
EMFit<KMeansType, NoConstraint> em(maxIterations, tolerance, k);
|
||||
likelihood = gmm.Train(dataPoints, CLI::GetParam<int>("trials"), false,
|
||||
likelihood = gmm->Train(dataPoints, CLI::GetParam<int>("trials"), false,
|
||||
em);
|
||||
Timer::Stop("em");
|
||||
}
|
||||
@@ -231,7 +235,7 @@ static void mlpackMain()
|
||||
// Compute the parameters of the model using the EM algorithm.
|
||||
Timer::Start("em");
|
||||
EMFit<kmeans::KMeans<>, DiagonalConstraint> em(maxIterations, tolerance);
|
||||
likelihood = gmm.Train(dataPoints, CLI::GetParam<int>("trials"), false,
|
||||
likelihood = gmm->Train(dataPoints, CLI::GetParam<int>("trials"), false,
|
||||
em);
|
||||
Timer::Stop("em");
|
||||
}
|
||||
@@ -240,7 +244,7 @@ static void mlpackMain()
|
||||
// Compute the parameters of the model using the EM algorithm.
|
||||
Timer::Start("em");
|
||||
EMFit<> em(maxIterations, tolerance);
|
||||
likelihood = gmm.Train(dataPoints, CLI::GetParam<int>("trials"), false,
|
||||
likelihood = gmm->Train(dataPoints, CLI::GetParam<int>("trials"), false,
|
||||
em);
|
||||
Timer::Stop("em");
|
||||
}
|
||||
@@ -249,7 +253,7 @@ static void mlpackMain()
|
||||
// Compute the parameters of the model using the EM algorithm.
|
||||
Timer::Start("em");
|
||||
EMFit<KMeans<>, NoConstraint> em(maxIterations, tolerance);
|
||||
likelihood = gmm.Train(dataPoints, CLI::GetParam<int>("trials"), false,
|
||||
likelihood = gmm->Train(dataPoints, CLI::GetParam<int>("trials"), false,
|
||||
em);
|
||||
Timer::Stop("em");
|
||||
}
|
||||
@@ -257,6 +261,5 @@ static void mlpackMain()
|
||||
|
||||
Log::Info << "Log-likelihood of estimate: " << likelihood << "." << endl;
|
||||
|
||||
if (CLI::HasParam("output_model"))
|
||||
CLI::GetParam<GMM>("output_model") = std::move(gmm);
|
||||
CLI::GetParam<GMM*>("output_model") = gmm;
|
||||
}
|
||||
|
||||
@@ -79,5 +79,5 @@ struct Loglik
|
||||
static void mlpackMain()
|
||||
{
|
||||
// Load model, and calculate the log-likelihood of the sequence.
|
||||
CLI::GetParam<HMMModel>("input_model").PerformAction<Loglik>((void*) NULL);
|
||||
CLI::GetParam<HMMModel*>("input_model")->PerformAction<Loglik>((void*) NULL);
|
||||
}
|
||||
|
||||
@@ -436,21 +436,21 @@ static void mlpackMain()
|
||||
typeId = HMMType::GaussianMixtureModelHMM;
|
||||
|
||||
// If we have a model file, we can autodetect the type.
|
||||
HMMModel hmm(typeId);
|
||||
HMMModel* hmm;
|
||||
if (CLI::HasParam("input_model"))
|
||||
{
|
||||
hmm = std::move(CLI::GetParam<HMMModel>("input_model"));
|
||||
hmm = CLI::GetParam<HMMModel*>("input_model");
|
||||
}
|
||||
else
|
||||
{
|
||||
// We need to initialize the model.
|
||||
hmm.PerformAction<Init, vector<mat>>(&trainSeq);
|
||||
hmm = new HMMModel(typeId);
|
||||
hmm->PerformAction<Init, vector<mat>>(&trainSeq);
|
||||
}
|
||||
|
||||
// Train the model.
|
||||
hmm.PerformAction<Train, vector<mat>>(&trainSeq);
|
||||
hmm->PerformAction<Train, vector<mat>>(&trainSeq);
|
||||
|
||||
// If necessary, save the output.
|
||||
if (CLI::HasParam("output_model"))
|
||||
CLI::GetParam<HMMModel>("output_model") = std::move(hmm);
|
||||
CLI::GetParam<HMMModel*>("output_model") = hmm;
|
||||
}
|
||||
|
||||
@@ -77,8 +77,7 @@ struct Viterbi
|
||||
hmm.Predict(dataSeq, sequence);
|
||||
|
||||
// Save output.
|
||||
if (CLI::HasParam("output"))
|
||||
CLI::GetParam<arma::Mat<size_t>>("output") = std::move(sequence);
|
||||
CLI::GetParam<arma::Mat<size_t>>("output") = std::move(sequence);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -86,5 +85,5 @@ static void mlpackMain()
|
||||
{
|
||||
RequireAtLeastOnePassed({ "output" }, false, "no results will be saved");
|
||||
|
||||
CLI::GetParam<HMMModel>("input_model").PerformAction<Viterbi>((void*) NULL);
|
||||
CLI::GetParam<HMMModel*>("input_model")->PerformAction<Viterbi>((void*) NULL);
|
||||
}
|
||||
|
||||
@@ -140,25 +140,25 @@ static void mlpackMain()
|
||||
true, "unrecognized numeric split strategy");
|
||||
|
||||
// Do we need to load a model or do we already have one?
|
||||
HoeffdingTreeModel model;
|
||||
HoeffdingTreeModel* model;
|
||||
DatasetInfo datasetInfo;
|
||||
arma::mat trainingSet;
|
||||
arma::Row<size_t> labels;
|
||||
if (CLI::HasParam("input_model"))
|
||||
{
|
||||
model = std::move(CLI::GetParam<HoeffdingTreeModel>("input_model"));
|
||||
model = CLI::GetParam<HoeffdingTreeModel*>("input_model");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Initialize a model.
|
||||
if (!CLI::HasParam("info_gain") && (numericSplitStrategy == "domingos"))
|
||||
model = HoeffdingTreeModel(HoeffdingTreeModel::GINI_HOEFFDING);
|
||||
model = new HoeffdingTreeModel(HoeffdingTreeModel::GINI_HOEFFDING);
|
||||
else if (!CLI::HasParam("info_gain") && (numericSplitStrategy == "binary"))
|
||||
model = HoeffdingTreeModel(HoeffdingTreeModel::GINI_BINARY);
|
||||
model = new HoeffdingTreeModel(HoeffdingTreeModel::GINI_BINARY);
|
||||
else if (CLI::HasParam("info_gain") && (numericSplitStrategy == "domingos"))
|
||||
model = HoeffdingTreeModel(HoeffdingTreeModel::INFO_HOEFFDING);
|
||||
model = new HoeffdingTreeModel(HoeffdingTreeModel::INFO_HOEFFDING);
|
||||
else if (CLI::HasParam("info_gain") && (numericSplitStrategy == "binary"))
|
||||
model = HoeffdingTreeModel(HoeffdingTreeModel::INFO_BINARY);
|
||||
model = new HoeffdingTreeModel(HoeffdingTreeModel::INFO_BINARY);
|
||||
}
|
||||
|
||||
// Now, do we need to train?
|
||||
@@ -207,7 +207,7 @@ static void mlpackMain()
|
||||
if (!CLI::HasParam("input_model"))
|
||||
{
|
||||
// Build the model.
|
||||
model.BuildModel(trainingSet, datasetInfo, labels,
|
||||
model->BuildModel(trainingSet, datasetInfo, labels,
|
||||
arma::max(labels) + 1, batchTraining, confidence, maxSamples,
|
||||
100, minSamples, bins, observationsBeforeBinning);
|
||||
--passes; // This model-building takes one pass.
|
||||
@@ -219,12 +219,12 @@ static void mlpackMain()
|
||||
// We only need to do batch training if we've not already called
|
||||
// BuildModel.
|
||||
if (CLI::HasParam("input_model"))
|
||||
model.Train(trainingSet, labels, true);
|
||||
model->Train(trainingSet, labels, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (size_t p = 0; p < passes; ++p)
|
||||
model.Train(trainingSet, labels, false);
|
||||
model->Train(trainingSet, labels, false);
|
||||
}
|
||||
|
||||
Timer::Stop("tree_training");
|
||||
@@ -235,7 +235,7 @@ static void mlpackMain()
|
||||
{
|
||||
// Get training error.
|
||||
arma::Row<size_t> predictions;
|
||||
model.Classify(trainingSet, predictions);
|
||||
model->Classify(trainingSet, predictions);
|
||||
|
||||
size_t correct = 0;
|
||||
for (size_t i = 0; i < labels.n_elem; ++i)
|
||||
@@ -248,7 +248,7 @@ static void mlpackMain()
|
||||
}
|
||||
|
||||
// Get the number of nodes in the tree.
|
||||
Log::Info << model.NumNodes() << " nodes in the tree." << endl;
|
||||
Log::Info << model->NumNodes() << " nodes in the tree." << endl;
|
||||
|
||||
// The tree is trained or loaded. Now do any testing if we need.
|
||||
if (CLI::HasParam("test"))
|
||||
@@ -262,7 +262,7 @@ static void mlpackMain()
|
||||
arma::rowvec probabilities;
|
||||
|
||||
Timer::Start("tree_testing");
|
||||
model.Classify(testSet, predictions, probabilities);
|
||||
model->Classify(testSet, predictions, probabilities);
|
||||
Timer::Stop("tree_testing");
|
||||
|
||||
if (CLI::HasParam("test_labels"))
|
||||
@@ -281,14 +281,10 @@ static void mlpackMain()
|
||||
100.0 << ")." << endl;
|
||||
}
|
||||
|
||||
if (CLI::HasParam("predictions"))
|
||||
CLI::GetParam<arma::Row<size_t>>("predictions") = std::move(predictions);
|
||||
|
||||
if (CLI::HasParam("probabilities"))
|
||||
CLI::GetParam<arma::mat>("probabilities") = std::move(probabilities);
|
||||
CLI::GetParam<arma::Row<size_t>>("predictions") = std::move(predictions);
|
||||
CLI::GetParam<arma::mat>("probabilities") = std::move(probabilities);
|
||||
}
|
||||
|
||||
// Check the accuracy on the training set.
|
||||
if (CLI::HasParam("output_model"))
|
||||
CLI::GetParam<HoeffdingTreeModel>("output_model") = std::move(model);
|
||||
CLI::GetParam<HoeffdingTreeModel*>("output_model") = model;
|
||||
}
|
||||
|
||||
@@ -120,11 +120,12 @@ static void mlpackMain()
|
||||
"no results will be saved");
|
||||
ReportIgnoredParam({{ "test", true }}, "output_predictions");
|
||||
|
||||
// Initialize the object.
|
||||
LARS lars(useCholesky, lambda1, lambda2);
|
||||
|
||||
LARS* lars;
|
||||
if (CLI::HasParam("input"))
|
||||
{
|
||||
// Initialize the object.
|
||||
lars = new LARS(useCholesky, lambda1, lambda2);
|
||||
|
||||
// Load covariates. We can avoid LARS transposing our data by choosing to
|
||||
// not transpose this data (that's why we used PARAM_TMATRIX_IN).
|
||||
mat matX = std::move(CLI::GetParam<arma::mat>("input"));
|
||||
@@ -146,11 +147,11 @@ static void mlpackMain()
|
||||
|
||||
vec beta;
|
||||
arma::rowvec y = std::move(matY);
|
||||
lars.Train(matX, y, beta, false /* do not transpose */);
|
||||
lars->Train(matX, y, beta, false /* do not transpose */);
|
||||
}
|
||||
else // We must have --input_model_file.
|
||||
{
|
||||
lars = std::move(CLI::GetParam<LARS>("input_model"));
|
||||
lars = CLI::GetParam<LARS*>("input_model");
|
||||
}
|
||||
|
||||
if (CLI::HasParam("test"))
|
||||
@@ -162,19 +163,17 @@ static void mlpackMain()
|
||||
|
||||
// Make sure the dimensionality is right. We haven't transposed, so, we
|
||||
// check n_cols not n_rows.
|
||||
if (testPoints.n_cols != lars.BetaPath().back().n_elem)
|
||||
if (testPoints.n_cols != lars->BetaPath().back().n_elem)
|
||||
Log::Fatal << "Dimensionality of test set (" << testPoints.n_cols << ") "
|
||||
<< "is not equal to the dimensionality of the model ("
|
||||
<< lars.BetaPath().back().n_elem << ")!" << endl;
|
||||
<< lars->BetaPath().back().n_elem << ")!" << endl;
|
||||
|
||||
arma::rowvec predictions;
|
||||
lars.Predict(testPoints.t(), predictions, false);
|
||||
lars->Predict(testPoints.t(), predictions, false);
|
||||
|
||||
// Save test predictions (one per line).
|
||||
if (CLI::HasParam("output_predictions"))
|
||||
CLI::GetParam<arma::mat>("output_predictions") = predictions.t();
|
||||
CLI::GetParam<arma::mat>("output_predictions") = predictions.t();
|
||||
}
|
||||
|
||||
if (CLI::HasParam("output_model"))
|
||||
CLI::GetParam<LARS>("output_model") = std::move(lars);
|
||||
CLI::GetParam<LARS*>("output_model") = lars;
|
||||
}
|
||||
|
||||
@@ -96,7 +96,7 @@ static void mlpackMain()
|
||||
mat regressors;
|
||||
rowvec responses;
|
||||
|
||||
LinearRegression lr;
|
||||
LinearRegression* lr;
|
||||
|
||||
const bool computeModel = !CLI::HasParam("input_model");
|
||||
const bool computePrediction = CLI::HasParam("test");
|
||||
@@ -148,14 +148,14 @@ static void mlpackMain()
|
||||
}
|
||||
|
||||
Timer::Start("regression");
|
||||
lr = LinearRegression(regressors, responses, lambda);
|
||||
lr = new LinearRegression(regressors, responses, lambda);
|
||||
Timer::Stop("regression");
|
||||
}
|
||||
else
|
||||
{
|
||||
// A model file was passed in, so load it.
|
||||
Timer::Start("load_model");
|
||||
lr = std::move(CLI::GetParam<LinearRegression>("input_model"));
|
||||
lr = CLI::GetParam<LinearRegression*>("input_model");
|
||||
Timer::Stop("load_model");
|
||||
}
|
||||
|
||||
@@ -168,10 +168,15 @@ static void mlpackMain()
|
||||
Timer::Stop("load_test_points");
|
||||
|
||||
// Ensure that test file data has the right number of features.
|
||||
if ((lr.Parameters().n_elem - 1) != points.n_rows)
|
||||
if ((lr->Parameters().n_elem - 1) != points.n_rows)
|
||||
{
|
||||
Log::Fatal << "The model was trained on " << lr.Parameters().n_elem - 1
|
||||
<< "-dimensional data, but the test points in '"
|
||||
// If we built the model, nothing will free it so we have to...
|
||||
const size_t dimensions = lr->Parameters().n_elem - 1;
|
||||
if (computeModel)
|
||||
delete lr;
|
||||
|
||||
Log::Fatal << "The model was trained on " << dimensions << "-dimensional "
|
||||
<< "data, but the test points in '"
|
||||
<< CLI::GetPrintableParam<mat>("test") << "' are " << points.n_rows
|
||||
<< "-dimensional!" << endl;
|
||||
}
|
||||
@@ -179,15 +184,13 @@ static void mlpackMain()
|
||||
// Perform the predictions using our model.
|
||||
rowvec predictions;
|
||||
Timer::Start("prediction");
|
||||
lr.Predict(points, predictions);
|
||||
lr->Predict(points, predictions);
|
||||
Timer::Stop("prediction");
|
||||
|
||||
// Save predictions.
|
||||
if (CLI::HasParam("output_predictions"))
|
||||
CLI::GetParam<rowvec>("output_predictions") = std::move(predictions);
|
||||
CLI::GetParam<rowvec>("output_predictions") = std::move(predictions);
|
||||
}
|
||||
|
||||
// Save the model if needed.
|
||||
if (CLI::HasParam("output_model"))
|
||||
CLI::GetParam<LinearRegression>("output_model") = std::move(lr);
|
||||
CLI::GetParam<LinearRegression*>("output_model") = lr;
|
||||
}
|
||||
|
||||
@@ -120,9 +120,11 @@ static void mlpackMain()
|
||||
ReportIgnoredParam({{ "training", false }}, "tolerance");
|
||||
|
||||
// Do we have an existing model?
|
||||
LocalCoordinateCoding lcc(0, 0.0);
|
||||
LocalCoordinateCoding* lcc;
|
||||
if (CLI::HasParam("input_model"))
|
||||
lcc = std::move(CLI::GetParam<LocalCoordinateCoding>("input_model"));
|
||||
lcc = CLI::GetParam<LocalCoordinateCoding*>("input_model");
|
||||
else
|
||||
lcc = new LocalCoordinateCoding(0, 0.0);
|
||||
|
||||
if (CLI::HasParam("training"))
|
||||
{
|
||||
@@ -136,10 +138,10 @@ static void mlpackMain()
|
||||
matX.col(i) /= norm(matX.col(i), 2);
|
||||
}
|
||||
|
||||
lcc.Lambda() = CLI::GetParam<double>("lambda");
|
||||
lcc.Atoms() = (size_t) CLI::GetParam<int>("atoms");
|
||||
lcc.MaxIterations() = (size_t) CLI::GetParam<int>("max_iterations");
|
||||
lcc.Tolerance() = CLI::GetParam<double>("tolerance");
|
||||
lcc->Lambda() = CLI::GetParam<double>("lambda");
|
||||
lcc->Atoms() = (size_t) CLI::GetParam<int>("atoms");
|
||||
lcc->MaxIterations() = (size_t) CLI::GetParam<int>("max_iterations");
|
||||
lcc->Tolerance() = CLI::GetParam<double>("tolerance");
|
||||
|
||||
// Inform the user if we are overwriting their model.
|
||||
if (CLI::HasParam("input_model"))
|
||||
@@ -147,35 +149,35 @@ static void mlpackMain()
|
||||
Log::Info << "Using dictionary from existing model in '"
|
||||
<< CLI::GetPrintableParam<string>("input_model") << "' as initial "
|
||||
<< "dictionary for training." << endl;
|
||||
lcc.Train<NothingInitializer>(matX);
|
||||
lcc->Train<NothingInitializer>(matX);
|
||||
}
|
||||
else if (CLI::HasParam("initial_dictionary"))
|
||||
{
|
||||
// Load initial dictionary directly into LCC object.
|
||||
lcc.Dictionary() = std::move(CLI::GetParam<mat>("initial_dictionary"));
|
||||
lcc->Dictionary() = std::move(CLI::GetParam<mat>("initial_dictionary"));
|
||||
|
||||
// Validate the size of the initial dictionary.
|
||||
if (lcc.Dictionary().n_cols != lcc.Atoms())
|
||||
if (lcc->Dictionary().n_cols != lcc->Atoms())
|
||||
{
|
||||
Log::Fatal << "The initial dictionary has " << lcc.Dictionary().n_cols
|
||||
Log::Fatal << "The initial dictionary has " << lcc->Dictionary().n_cols
|
||||
<< " atoms, but the number of atoms was specified to be "
|
||||
<< lcc.Atoms() << "!" << endl;
|
||||
<< lcc->Atoms() << "!" << endl;
|
||||
}
|
||||
|
||||
if (lcc.Dictionary().n_rows != matX.n_rows)
|
||||
if (lcc->Dictionary().n_rows != matX.n_rows)
|
||||
{
|
||||
Log::Fatal << "The initial dictionary has " << lcc.Dictionary().n_rows
|
||||
Log::Fatal << "The initial dictionary has " << lcc->Dictionary().n_rows
|
||||
<< " dimensions, but the data has " << matX.n_rows << " dimensions!"
|
||||
<< endl;
|
||||
}
|
||||
|
||||
// Train the model.
|
||||
lcc.Train<NothingInitializer>(matX);
|
||||
lcc->Train<NothingInitializer>(matX);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Run with the default initialization.
|
||||
lcc.Train(matX);
|
||||
lcc->Train(matX);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -184,9 +186,9 @@ static void mlpackMain()
|
||||
{
|
||||
mat matY = std::move(CLI::GetParam<mat>("test"));
|
||||
|
||||
if (matY.n_rows != lcc.Dictionary().n_rows)
|
||||
if (matY.n_rows != lcc->Dictionary().n_rows)
|
||||
Log::Fatal << "Model was trained with a dimensionality of "
|
||||
<< lcc.Dictionary().n_rows << ", but data in test file "
|
||||
<< lcc->Dictionary().n_rows << ", but data in test file "
|
||||
<< CLI::GetPrintableParam<mat>("test") << " has a dimensionality of "
|
||||
<< matY.n_rows << "!" << endl;
|
||||
|
||||
@@ -199,17 +201,12 @@ static void mlpackMain()
|
||||
}
|
||||
|
||||
mat codes;
|
||||
lcc.Encode(matY, codes);
|
||||
lcc->Encode(matY, codes);
|
||||
|
||||
if (CLI::HasParam("codes"))
|
||||
CLI::GetParam<mat>("codes") = std::move(codes);
|
||||
CLI::GetParam<mat>("codes") = std::move(codes);
|
||||
}
|
||||
|
||||
// Did the user want to save the dictionary?
|
||||
if (CLI::HasParam("dictionary"))
|
||||
CLI::GetParam<mat>("dictionary") = std::move(lcc.Dictionary());
|
||||
|
||||
// Did the user want to save the model?
|
||||
if (CLI::HasParam("output_model"))
|
||||
CLI::GetParam<LocalCoordinateCoding>("output_model") = std::move(lcc);
|
||||
// Save the dictionary and the model.
|
||||
CLI::GetParam<mat>("dictionary") = lcc->Dictionary();
|
||||
CLI::GetParam<LocalCoordinateCoding*>("output_model") = lcc;
|
||||
}
|
||||
|
||||
@@ -206,16 +206,18 @@ static void mlpackMain()
|
||||
regressors = std::move(CLI::GetParam<arma::mat>("training"));
|
||||
|
||||
// Load the model, if necessary.
|
||||
LogisticRegression<> model(0, 0); // Empty model.
|
||||
LogisticRegression<>* model;
|
||||
if (CLI::HasParam("input_model"))
|
||||
model = std::move(CLI::GetParam<LogisticRegression<>>("input_model"));
|
||||
model = CLI::GetParam<LogisticRegression<>*>("input_model");
|
||||
else
|
||||
{
|
||||
model = new LogisticRegression<>(0, 0);
|
||||
|
||||
// Set the size of the parameters vector, if necessary.
|
||||
if (!CLI::HasParam("labels"))
|
||||
model.Parameters() = arma::zeros<arma::rowvec>(regressors.n_rows);
|
||||
model->Parameters() = arma::zeros<arma::rowvec>(regressors.n_rows);
|
||||
else
|
||||
model.Parameters() = arma::zeros<arma::rowvec>(regressors.n_rows + 1);
|
||||
model->Parameters() = arma::zeros<arma::rowvec>(regressors.n_rows + 1);
|
||||
}
|
||||
|
||||
// Check if the responses are in a separate file.
|
||||
@@ -242,7 +244,7 @@ static void mlpackMain()
|
||||
// Now, do the training.
|
||||
if (CLI::HasParam("training"))
|
||||
{
|
||||
model.Lambda() = lambda;
|
||||
model->Lambda() = lambda;
|
||||
|
||||
if (optimizerType == "sgd")
|
||||
{
|
||||
@@ -254,7 +256,7 @@ static void mlpackMain()
|
||||
Log::Info << "Training model with SGD optimizer." << endl;
|
||||
|
||||
// This will train the model.
|
||||
model.Train(regressors, responses, sgdOpt);
|
||||
model->Train(regressors, responses, sgdOpt);
|
||||
}
|
||||
else if (optimizerType == "lbfgs")
|
||||
{
|
||||
@@ -264,7 +266,7 @@ static void mlpackMain()
|
||||
Log::Info << "Training model with L-BFGS optimizer." << endl;
|
||||
|
||||
// This will train the model.
|
||||
model.Train(regressors, responses, lbfgsOpt);
|
||||
model->Train(regressors, responses, lbfgsOpt);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -278,7 +280,7 @@ static void mlpackMain()
|
||||
{
|
||||
Log::Info << "Predicting classes of points in '"
|
||||
<< CLI::GetPrintableParam<arma::mat>("test") << "'." << endl;
|
||||
model.Classify(testSet, predictions, decisionBoundary);
|
||||
model->Classify(testSet, predictions, decisionBoundary);
|
||||
|
||||
CLI::GetParam<arma::Row<size_t>>("output") = std::move(predictions);
|
||||
}
|
||||
@@ -288,13 +290,12 @@ static void mlpackMain()
|
||||
Log::Info << "Calculating class probabilities of points in '"
|
||||
<< CLI::GetPrintableParam<arma::mat>("test") << "'." << endl;
|
||||
arma::mat probabilities;
|
||||
model.Classify(testSet, probabilities);
|
||||
model->Classify(testSet, probabilities);
|
||||
|
||||
CLI::GetParam<arma::mat>("output_probabilities") =
|
||||
std::move(probabilities);
|
||||
}
|
||||
}
|
||||
|
||||
if (CLI::HasParam("output_model"))
|
||||
CLI::GetParam<LogisticRegression<>>("output_model") = std::move(model);
|
||||
CLI::GetParam<LogisticRegression<>*>("output_model") = model;
|
||||
}
|
||||
|
||||
@@ -154,9 +154,10 @@ static void mlpackMain()
|
||||
Log::Info << "Using LSH with " << numProj << " projections (K) and " <<
|
||||
numTables << " tables (L) with hash width(r): " << hashWidth << endl;
|
||||
|
||||
LSHSearch<> allkann;
|
||||
LSHSearch<>* allkann;
|
||||
if (CLI::HasParam("reference"))
|
||||
{
|
||||
allkann = new LSHSearch<>();
|
||||
referenceData = std::move(CLI::GetParam<arma::mat>("reference"));
|
||||
Log::Info << "Using reference data from '"
|
||||
<< CLI::GetPrintableParam<arma::mat>("reference") << "' ("
|
||||
@@ -164,13 +165,13 @@ static void mlpackMain()
|
||||
<< endl;
|
||||
|
||||
Timer::Start("hash_building");
|
||||
allkann.Train(std::move(referenceData), numProj, numTables, hashWidth,
|
||||
allkann->Train(std::move(referenceData), numProj, numTables, hashWidth,
|
||||
secondHashSize, bucketSize);
|
||||
Timer::Stop("hash_building");
|
||||
}
|
||||
else if (CLI::HasParam("input_model"))
|
||||
{
|
||||
allkann = std::move(CLI::GetParam<LSHSearch<>>("input_model"));
|
||||
allkann = CLI::GetParam<LSHSearch<>*>("input_model");
|
||||
}
|
||||
|
||||
if (CLI::HasParam("k"))
|
||||
@@ -184,11 +185,11 @@ static void mlpackMain()
|
||||
<< CLI::GetPrintableParam<arma::mat>("query") << "' ("
|
||||
<< queryData.n_rows << " x " << queryData.n_cols << ")." << endl;
|
||||
|
||||
allkann.Search(queryData, k, neighbors, distances, 0, numProbes);
|
||||
allkann->Search(queryData, k, neighbors, distances, 0, numProbes);
|
||||
}
|
||||
else
|
||||
{
|
||||
allkann.Search(k, neighbors, distances, 0, numProbes);
|
||||
allkann->Search(k, neighbors, distances, 0, numProbes);
|
||||
}
|
||||
|
||||
Log::Info << "Neighbors computed." << endl;
|
||||
@@ -205,20 +206,17 @@ static void mlpackMain()
|
||||
<< endl;
|
||||
|
||||
// Compute recall and print it.
|
||||
double recallPercentage = 100 * allkann.ComputeRecall(neighbors,
|
||||
double recallPercentage = 100 * allkann->ComputeRecall(neighbors,
|
||||
trueNeighbors);
|
||||
|
||||
Log::Info << "Recall: " << recallPercentage << endl;
|
||||
}
|
||||
|
||||
// Save output, if desired.
|
||||
// Save output, if we did a search..
|
||||
if (CLI::HasParam("k"))
|
||||
{
|
||||
if (CLI::HasParam("distances"))
|
||||
CLI::GetParam<arma::mat>("distances") = std::move(distances);
|
||||
if (CLI::HasParam("neighbors"))
|
||||
CLI::GetParam<arma::Mat<size_t>>("neighbors") = std::move(neighbors);
|
||||
CLI::GetParam<arma::mat>("distances") = std::move(distances);
|
||||
CLI::GetParam<arma::Mat<size_t>>("neighbors") = std::move(neighbors);
|
||||
}
|
||||
if (CLI::HasParam("output_model"))
|
||||
CLI::GetParam<LSHSearch<>>("output_model") = std::move(allkann);
|
||||
CLI::GetParam<LSHSearch<>*>("output_model") = allkann;
|
||||
}
|
||||
|
||||
@@ -118,9 +118,10 @@ static void mlpackMain()
|
||||
Log::Warn << "No test set given; no task will be performed!" << std::endl;
|
||||
|
||||
// Either we have to train a model, or load a model.
|
||||
NBCModel model;
|
||||
NBCModel* model;
|
||||
if (CLI::HasParam("training"))
|
||||
{
|
||||
model = new NBCModel();
|
||||
mat trainingData = std::move(CLI::GetParam<mat>("training"));
|
||||
|
||||
Row<size_t> labels;
|
||||
@@ -130,7 +131,7 @@ static void mlpackMain()
|
||||
{
|
||||
// Load labels.
|
||||
Row<size_t> rawLabels = std::move(CLI::GetParam<Row<size_t>>("labels"));
|
||||
data::NormalizeLabels(rawLabels, labels, model.mappings);
|
||||
data::NormalizeLabels(rawLabels, labels, model->mappings);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -138,7 +139,7 @@ static void mlpackMain()
|
||||
Log::Info << "Using last dimension of training data as training labels."
|
||||
<< endl;
|
||||
data::NormalizeLabels(trainingData.row(trainingData.n_rows - 1), labels,
|
||||
model.mappings);
|
||||
model->mappings);
|
||||
// Remove the label row.
|
||||
trainingData.shed_row(trainingData.n_rows - 1);
|
||||
}
|
||||
@@ -146,14 +147,14 @@ static void mlpackMain()
|
||||
const bool incrementalVariance = CLI::HasParam("incremental_variance");
|
||||
|
||||
Timer::Start("nbc_training");
|
||||
model.nbc = NaiveBayesClassifier<>(trainingData, labels,
|
||||
model.mappings.n_elem, incrementalVariance);
|
||||
model->nbc = NaiveBayesClassifier<>(trainingData, labels,
|
||||
model->mappings.n_elem, incrementalVariance);
|
||||
Timer::Stop("nbc_training");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Load the model from file.
|
||||
model = std::move(CLI::GetParam<NBCModel>("input_model"));
|
||||
model = CLI::GetParam<NBCModel*>("input_model");
|
||||
}
|
||||
|
||||
// Do we need to do testing?
|
||||
@@ -161,10 +162,10 @@ static void mlpackMain()
|
||||
{
|
||||
mat testingData = std::move(CLI::GetParam<mat>("test"));
|
||||
|
||||
if (testingData.n_rows != model.nbc.Means().n_rows)
|
||||
if (testingData.n_rows != model->nbc.Means().n_rows)
|
||||
{
|
||||
Log::Fatal << "Test data dimensionality (" << testingData.n_rows << ") "
|
||||
<< "must be the same as training data (" << model.nbc.Means().n_rows
|
||||
<< "must be the same as training data (" << model->nbc.Means().n_rows
|
||||
<< ")!" << std::endl;
|
||||
}
|
||||
|
||||
@@ -172,23 +173,21 @@ static void mlpackMain()
|
||||
Row<size_t> predictions;
|
||||
mat probabilities;
|
||||
Timer::Start("nbc_testing");
|
||||
model.nbc.Classify(testingData, predictions, probabilities);
|
||||
model->nbc.Classify(testingData, predictions, probabilities);
|
||||
Timer::Stop("nbc_testing");
|
||||
|
||||
if (CLI::HasParam("output"))
|
||||
{
|
||||
// Un-normalize labels to prepare output.
|
||||
Row<size_t> rawResults;
|
||||
data::RevertLabels(predictions, model.mappings, rawResults);
|
||||
data::RevertLabels(predictions, model->mappings, rawResults);
|
||||
|
||||
// Output results.
|
||||
CLI::GetParam<Row<size_t>>("output") = std::move(rawResults);
|
||||
}
|
||||
|
||||
if (CLI::HasParam("output_probs"))
|
||||
CLI::GetParam<mat>("output_probs") = probabilities;
|
||||
CLI::GetParam<mat>("output_probs") = probabilities;
|
||||
}
|
||||
|
||||
if (CLI::HasParam("output_model"))
|
||||
CLI::GetParam<NBCModel>("output_model") = std::move(model);
|
||||
CLI::GetParam<NBCModel*>("output_model") = model;
|
||||
}
|
||||
|
||||
@@ -157,7 +157,7 @@ static void mlpackMain()
|
||||
epsilon = 1 - percentage;
|
||||
|
||||
// We either have to load the reference data, or we have to load the model.
|
||||
NSModel<FurthestNeighborSort> kfn;
|
||||
NSModel<FurthestNeighborSort>* kfn;
|
||||
|
||||
const string algorithm = CLI::GetParam<string>("algorithm");
|
||||
RequireParamInSet<string>("algorithm", { "naive", "single_tree", "dual_tree",
|
||||
@@ -175,6 +175,8 @@ static void mlpackMain()
|
||||
|
||||
if (CLI::HasParam("reference"))
|
||||
{
|
||||
kfn = new KFNModel();
|
||||
|
||||
// Get all the parameters.
|
||||
RequireParamInSet<string>("tree_type", { "kd", "cover", "r", "r-star",
|
||||
"ball", "x", "hilbert-r", "r-plus", "r-plus-plus", "vp", "rp", "max-rp",
|
||||
@@ -212,8 +214,8 @@ static void mlpackMain()
|
||||
else if (treeType == "oct")
|
||||
tree = KFNModel::OCTREE;
|
||||
|
||||
kfn.TreeType() = tree;
|
||||
kfn.RandomBasis() = randomBasis;
|
||||
kfn->TreeType() = tree;
|
||||
kfn->RandomBasis() = randomBasis;
|
||||
|
||||
arma::mat referenceSet = std::move(CLI::GetParam<arma::mat>("reference"));
|
||||
|
||||
@@ -221,27 +223,28 @@ static void mlpackMain()
|
||||
<< CLI::GetPrintableParam<arma::mat>("reference") << "' ("
|
||||
<< referenceSet.n_rows << "x" << referenceSet.n_cols << ")." << endl;
|
||||
|
||||
kfn.BuildModel(std::move(referenceSet), size_t(lsInt), searchMode, epsilon);
|
||||
kfn->BuildModel(std::move(referenceSet), size_t(lsInt), searchMode,
|
||||
epsilon);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Load the model from file.
|
||||
kfn = std::move(CLI::GetParam<KFNModel>("input_model"));
|
||||
kfn = CLI::GetParam<KFNModel*>("input_model");
|
||||
|
||||
// Adjust search mode.
|
||||
kfn.SearchMode() = searchMode;
|
||||
kfn.Epsilon() = epsilon;
|
||||
kfn->SearchMode() = searchMode;
|
||||
kfn->Epsilon() = epsilon;
|
||||
|
||||
// If leaf_size wasn't provided, let's consider the current value in the
|
||||
// loaded model. Else, update it (only considered when building the query
|
||||
// tree).
|
||||
if (CLI::HasParam("leaf_size"))
|
||||
kfn.LeafSize() = size_t(lsInt);
|
||||
kfn->LeafSize() = size_t(lsInt);
|
||||
|
||||
Log::Info << "Using kFN model from '"
|
||||
<< CLI::GetPrintableParam<KFNModel>("input_model") << "' (trained on "
|
||||
<< kfn.Dataset().n_rows << "x" << kfn.Dataset().n_cols << " dataset)."
|
||||
<< endl;
|
||||
<< CLI::GetPrintableParam<KFNModel*>("input_model") << "' (trained on "
|
||||
<< kfn->Dataset().n_rows << "x" << kfn->Dataset().n_cols
|
||||
<< " dataset)." << endl;
|
||||
}
|
||||
|
||||
// Perform search, if desired.
|
||||
@@ -261,11 +264,11 @@ static void mlpackMain()
|
||||
// Sanity check on k value: must be greater than 0, must be less than the
|
||||
// number of reference points. Since it is unsigned, we only test the upper
|
||||
// bound.
|
||||
if (k > kfn.Dataset().n_cols)
|
||||
if (k > kfn->Dataset().n_cols)
|
||||
{
|
||||
Log::Fatal << "Invalid k: " << k << "; must be greater than 0 and less "
|
||||
<< "than or equal to the number of reference points ("
|
||||
<< kfn.Dataset().n_cols << ")." << endl;
|
||||
<< kfn->Dataset().n_cols << ")." << endl;
|
||||
}
|
||||
|
||||
// Now run the search.
|
||||
@@ -273,21 +276,19 @@ static void mlpackMain()
|
||||
arma::mat distances;
|
||||
|
||||
if (CLI::HasParam("query"))
|
||||
kfn.Search(std::move(queryData), k, neighbors, distances);
|
||||
kfn->Search(std::move(queryData), k, neighbors, distances);
|
||||
else
|
||||
kfn.Search(k, neighbors, distances);
|
||||
kfn->Search(k, neighbors, distances);
|
||||
Log::Info << "Search complete." << endl;
|
||||
|
||||
// Save output, if desired.
|
||||
if (CLI::HasParam("neighbors"))
|
||||
CLI::GetParam<arma::Mat<size_t>>("neighbors") = std::move(neighbors);
|
||||
if (CLI::HasParam("distances"))
|
||||
CLI::GetParam<arma::mat>("distances") = std::move(distances);
|
||||
// Save output.
|
||||
CLI::GetParam<arma::Mat<size_t>>("neighbors") = std::move(neighbors);
|
||||
CLI::GetParam<arma::mat>("distances") = std::move(distances);
|
||||
|
||||
// Calculate the effective error, if desired.
|
||||
if (CLI::HasParam("true_distances"))
|
||||
{
|
||||
if (kfn.Epsilon() == 0)
|
||||
if (kfn->Epsilon() == 0)
|
||||
Log::Warn << PRINT_PARAM_STRING("true_distances") << " specified, but "
|
||||
<< "the search is exact, so there is no need to calculate the "
|
||||
<< "error!" << endl;
|
||||
@@ -307,7 +308,7 @@ static void mlpackMain()
|
||||
// Calculate the recall, if desired.
|
||||
if (CLI::HasParam("true_neighbors"))
|
||||
{
|
||||
if (kfn.Epsilon() == 0)
|
||||
if (kfn->Epsilon() == 0)
|
||||
Log::Warn << PRINT_PARAM_STRING("true_neighbors") << " specified, but "
|
||||
<< "the search is exact, so there is no need to calculate the "
|
||||
<< "recall!" << endl;
|
||||
@@ -324,6 +325,5 @@ static void mlpackMain()
|
||||
}
|
||||
}
|
||||
|
||||
if (CLI::HasParam("output_model"))
|
||||
CLI::GetParam<KFNModel>("output_model") = std::move(kfn);
|
||||
CLI::GetParam<KFNModel*>("output_model") = kfn;
|
||||
}
|
||||
|
||||
@@ -166,7 +166,7 @@ static void mlpackMain()
|
||||
"epsilon must be positive");
|
||||
|
||||
// We either have to load the reference data, or we have to load the model.
|
||||
KNNModel knn;
|
||||
KNNModel* knn;
|
||||
|
||||
const string algorithm = CLI::GetParam<string>("algorithm");
|
||||
RequireParamInSet<string>("algorithm", { "naive", "single_tree", "dual_tree",
|
||||
@@ -184,6 +184,8 @@ static void mlpackMain()
|
||||
|
||||
if (CLI::HasParam("reference"))
|
||||
{
|
||||
knn = new KNNModel();
|
||||
|
||||
// Get all the parameters.
|
||||
const string treeType = CLI::GetParam<string>("tree_type");
|
||||
const bool randomBasis = CLI::HasParam("random_basis");
|
||||
@@ -223,11 +225,11 @@ static void mlpackMain()
|
||||
else if (treeType == "oct")
|
||||
tree = KNNModel::OCTREE;
|
||||
|
||||
knn.TreeType() = tree;
|
||||
knn.RandomBasis() = randomBasis;
|
||||
knn.LeafSize() = size_t(lsInt);
|
||||
knn.Tau() = tau;
|
||||
knn.Rho() = rho;
|
||||
knn->TreeType() = tree;
|
||||
knn->RandomBasis() = randomBasis;
|
||||
knn->LeafSize() = size_t(lsInt);
|
||||
knn->Tau() = tau;
|
||||
knn->Rho() = rho;
|
||||
|
||||
arma::mat referenceSet = std::move(CLI::GetParam<arma::mat>("reference"));
|
||||
|
||||
@@ -236,27 +238,28 @@ static void mlpackMain()
|
||||
<< referenceSet.n_rows << " x " << referenceSet.n_cols << ")."
|
||||
<< endl;
|
||||
|
||||
knn.BuildModel(std::move(referenceSet), size_t(lsInt), searchMode, epsilon);
|
||||
knn->BuildModel(std::move(referenceSet), size_t(lsInt), searchMode,
|
||||
epsilon);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Load the model from file.
|
||||
knn = std::move(CLI::GetParam<KNNModel>("input_model"));
|
||||
knn = CLI::GetParam<KNNModel*>("input_model");
|
||||
|
||||
// Adjust search mode.
|
||||
knn.SearchMode() = searchMode;
|
||||
knn.Epsilon() = epsilon;
|
||||
knn->SearchMode() = searchMode;
|
||||
knn->Epsilon() = epsilon;
|
||||
|
||||
// If leaf_size wasn't provided, let's consider the current value in the
|
||||
// loaded model. Else, update it (only considered when building the query
|
||||
// tree).
|
||||
if (CLI::HasParam("leaf_size"))
|
||||
knn.LeafSize() = size_t(lsInt);
|
||||
knn->LeafSize() = size_t(lsInt);
|
||||
|
||||
Log::Info << "Loaded kNN model from '"
|
||||
<< CLI::GetPrintableParam<KNNModel>("input_model") << "' (trained on "
|
||||
<< knn.Dataset().n_rows << "x" << knn.Dataset().n_cols << " dataset)."
|
||||
<< endl;
|
||||
<< CLI::GetPrintableParam<KNNModel*>("input_model") << "' (trained on "
|
||||
<< knn->Dataset().n_rows << "x" << knn->Dataset().n_cols
|
||||
<< " dataset)." << endl;
|
||||
}
|
||||
|
||||
// Perform search, if desired.
|
||||
@@ -276,11 +279,11 @@ static void mlpackMain()
|
||||
// Sanity check on k value: must be greater than 0, must be less than the
|
||||
// number of reference points. Since it is unsigned, we only test the upper
|
||||
// bound.
|
||||
if (k > knn.Dataset().n_cols)
|
||||
if (k > knn->Dataset().n_cols)
|
||||
{
|
||||
Log::Fatal << "Invalid k: " << k << "; must be greater than 0 and less ";
|
||||
Log::Fatal << "than or equal to the number of reference points (";
|
||||
Log::Fatal << knn.Dataset().n_cols << ")." << endl;
|
||||
Log::Fatal << knn->Dataset().n_cols << ")." << endl;
|
||||
}
|
||||
|
||||
// Now run the search.
|
||||
@@ -288,21 +291,19 @@ static void mlpackMain()
|
||||
arma::mat distances;
|
||||
|
||||
if (CLI::HasParam("query"))
|
||||
knn.Search(std::move(queryData), k, neighbors, distances);
|
||||
knn->Search(std::move(queryData), k, neighbors, distances);
|
||||
else
|
||||
knn.Search(k, neighbors, distances);
|
||||
knn->Search(k, neighbors, distances);
|
||||
Log::Info << "Search complete." << endl;
|
||||
|
||||
// Save output, if desired.
|
||||
if (CLI::HasParam("neighbors"))
|
||||
CLI::GetParam<arma::Mat<size_t>>("neighbors") = std::move(neighbors);
|
||||
if (CLI::HasParam("distances"))
|
||||
CLI::GetParam<arma::mat>("distances") = std::move(distances);
|
||||
// Save output.
|
||||
CLI::GetParam<arma::Mat<size_t>>("neighbors") = std::move(neighbors);
|
||||
CLI::GetParam<arma::mat>("distances") = std::move(distances);
|
||||
|
||||
// Calculate the effective error, if desired.
|
||||
if (CLI::HasParam("true_distances"))
|
||||
{
|
||||
if (knn.TreeType() != KNNModel::SPILL_TREE && knn.Epsilon() == 0)
|
||||
if (knn->TreeType() != KNNModel::SPILL_TREE && knn->Epsilon() == 0)
|
||||
Log::Warn << PRINT_PARAM_STRING("true_distances") << "specified, but "
|
||||
<< "the search is exact, so there is no need to calculate the "
|
||||
<< "error!" << endl;
|
||||
@@ -322,7 +323,7 @@ static void mlpackMain()
|
||||
// Calculate the recall, if desired.
|
||||
if (CLI::HasParam("true_neighbors"))
|
||||
{
|
||||
if (knn.TreeType() != KNNModel::SPILL_TREE && knn.Epsilon() == 0)
|
||||
if (knn->TreeType() != KNNModel::SPILL_TREE && knn->Epsilon() == 0)
|
||||
Log::Warn << PRINT_PARAM_STRING("true_neighbors") << " specified, but "
|
||||
<< " the search is exact, so there is no need to calculate the "
|
||||
<< "recall!" << endl;
|
||||
@@ -339,6 +340,5 @@ static void mlpackMain()
|
||||
}
|
||||
}
|
||||
|
||||
if (CLI::HasParam("output_model"))
|
||||
CLI::GetParam<KNNModel>("output_model") = std::move(knn);
|
||||
CLI::GetParam<KNNModel*>("output_model") = knn;
|
||||
}
|
||||
|
||||
@@ -137,14 +137,18 @@ static void mlpackMain()
|
||||
true, "maximum number of iterations must be nonnegative");
|
||||
|
||||
// Now, load our model, if there is one.
|
||||
PerceptronModel p;
|
||||
PerceptronModel* p;
|
||||
if (CLI::HasParam("input_model"))
|
||||
{
|
||||
Log::Info << "Using saved perceptron from "
|
||||
<< CLI::GetPrintableParam<PerceptronModel>("input_model") << "."
|
||||
<< CLI::GetPrintableParam<PerceptronModel*>("input_model") << "."
|
||||
<< endl;
|
||||
|
||||
p = std::move(CLI::GetParam<PerceptronModel>("input_model"));
|
||||
p = CLI::GetParam<PerceptronModel*>("input_model");
|
||||
}
|
||||
else
|
||||
{
|
||||
p = new PerceptronModel();
|
||||
}
|
||||
|
||||
// Next, load the training data and labels (if they have been given).
|
||||
@@ -186,8 +190,8 @@ static void mlpackMain()
|
||||
|
||||
// Normalize the labels.
|
||||
Row<size_t> labels;
|
||||
data::NormalizeLabels(labelsIn, labels, p.Map());
|
||||
const size_t numClasses = p.Map().n_elem;
|
||||
data::NormalizeLabels(labelsIn, labels, p->Map());
|
||||
const size_t numClasses = p->Map().n_elem;
|
||||
|
||||
// Now, if we haven't already created a perceptron, do it. Otherwise, make
|
||||
// sure the dimensions are right, then continue training.
|
||||
@@ -195,35 +199,35 @@ static void mlpackMain()
|
||||
{
|
||||
// Create and train the classifier.
|
||||
Timer::Start("training");
|
||||
p.P() = Perceptron<>(trainingData, labels, numClasses, maxIterations);
|
||||
p->P() = Perceptron<>(trainingData, labels, numClasses, maxIterations);
|
||||
Timer::Stop("training");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Check dimensionality.
|
||||
if (p.P().Weights().n_rows != trainingData.n_rows)
|
||||
if (p->P().Weights().n_rows != trainingData.n_rows)
|
||||
{
|
||||
Log::Fatal << "Perceptron from '"
|
||||
<< CLI::GetPrintableParam<PerceptronModel>("input_model")
|
||||
<< "' is built on data with " << p.P().Weights().n_rows
|
||||
<< CLI::GetPrintableParam<PerceptronModel*>("input_model")
|
||||
<< "' is built on data with " << p->P().Weights().n_rows
|
||||
<< " dimensions, but data in '"
|
||||
<< CLI::GetPrintableParam<arma::mat>("training") << "' has "
|
||||
<< trainingData.n_rows << "dimensions!" << endl;
|
||||
}
|
||||
|
||||
// Check the number of labels.
|
||||
if (numClasses > p.P().Weights().n_cols)
|
||||
if (numClasses > p->P().Weights().n_cols)
|
||||
{
|
||||
Log::Fatal << "Perceptron from '"
|
||||
<< CLI::GetPrintableParam<PerceptronModel>("input_model") << "' "
|
||||
<< "has " << p.P().Weights().n_cols << " classes, but the training "
|
||||
<< "data has " << numClasses + 1 << " classes!" << endl;
|
||||
<< CLI::GetPrintableParam<PerceptronModel*>("input_model") << "' "
|
||||
<< "has " << p->P().Weights().n_cols << " classes, but the training"
|
||||
<< " data has " << numClasses + 1 << " classes!" << endl;
|
||||
}
|
||||
|
||||
// Now train.
|
||||
Timer::Start("training");
|
||||
p.P().MaxIterations() = maxIterations;
|
||||
p.P().Train(trainingData, labels.t(), numClasses);
|
||||
p->P().MaxIterations() = maxIterations;
|
||||
p->P().Train(trainingData, labels.t(), numClasses);
|
||||
Timer::Stop("training");
|
||||
}
|
||||
}
|
||||
@@ -235,29 +239,28 @@ static void mlpackMain()
|
||||
<< CLI::GetPrintableParam<arma::mat>("test") << "'." << endl;
|
||||
mat testData = std::move(CLI::GetParam<arma::mat>("test"));
|
||||
|
||||
if (testData.n_rows != p.P().Weights().n_rows)
|
||||
if (testData.n_rows != p->P().Weights().n_rows)
|
||||
{
|
||||
Log::Fatal << "Test data dimensionality (" << testData.n_rows << ") must "
|
||||
<< "be the same as the dimensionality of the perceptron ("
|
||||
<< p.P().Weights().n_rows << ")!" << endl;
|
||||
<< p->P().Weights().n_rows << ")!" << endl;
|
||||
}
|
||||
|
||||
// Time the running of the perceptron classifier.
|
||||
Row<size_t> predictedLabels(testData.n_cols);
|
||||
Timer::Start("testing");
|
||||
p.P().Classify(testData, predictedLabels);
|
||||
p->P().Classify(testData, predictedLabels);
|
||||
Timer::Stop("testing");
|
||||
|
||||
// Un-normalize labels to prepare output.
|
||||
Row<size_t> results;
|
||||
data::RevertLabels(predictedLabels, p.Map(), results);
|
||||
data::RevertLabels(predictedLabels, p->Map(), results);
|
||||
|
||||
// Save the predicted labels.
|
||||
if (CLI::HasParam("output"))
|
||||
CLI::GetParam<arma::Row<size_t>>("output") = std::move(results);
|
||||
}
|
||||
|
||||
// Lastly, do we need to save the output model?
|
||||
if (CLI::HasParam("output_model"))
|
||||
CLI::GetParam<PerceptronModel>("output_model") = std::move(p);
|
||||
// Lastly, save the output model.
|
||||
CLI::GetParam<PerceptronModel*>("output_model") = p;
|
||||
}
|
||||
|
||||
@@ -104,9 +104,11 @@ static void mlpackMain()
|
||||
ReportIgnoredParam({{ "training", false }}, "num_trees");
|
||||
ReportIgnoredParam({{ "training", false }}, "minimum_leaf_size");
|
||||
|
||||
RandomForestModel rfModel;
|
||||
RandomForestModel* rfModel;
|
||||
if (CLI::HasParam("training"))
|
||||
{
|
||||
rfModel = new RandomForestModel();
|
||||
|
||||
// Train the model on the given input data.
|
||||
arma::mat data = std::move(CLI::GetParam<arma::mat>("training"));
|
||||
arma::Row<size_t> labels =
|
||||
@@ -121,13 +123,13 @@ static void mlpackMain()
|
||||
const size_t numClasses = arma::max(labels) + 1;
|
||||
|
||||
// Train the model.
|
||||
rfModel.rf.Train(data, labels, numClasses, numTrees, minimumLeafSize);
|
||||
rfModel->rf.Train(data, labels, numClasses, numTrees, minimumLeafSize);
|
||||
|
||||
// Did we want training accuracy?
|
||||
if (CLI::HasParam("print_training_accuracy"))
|
||||
{
|
||||
arma::Row<size_t> predictions;
|
||||
rfModel.rf.Classify(data, predictions);
|
||||
rfModel->rf.Classify(data, predictions);
|
||||
|
||||
const size_t correct = arma::accu(predictions == labels);
|
||||
|
||||
@@ -139,7 +141,7 @@ static void mlpackMain()
|
||||
else
|
||||
{
|
||||
// Then we must be loading a model.
|
||||
rfModel = std::move(CLI::GetParam<RandomForestModel>("input_model"));
|
||||
rfModel = CLI::GetParam<RandomForestModel*>("input_model");
|
||||
}
|
||||
|
||||
if (CLI::HasParam("test"))
|
||||
@@ -149,7 +151,7 @@ static void mlpackMain()
|
||||
// Get predictions and probabilities.
|
||||
arma::Row<size_t> predictions;
|
||||
arma::mat probabilities;
|
||||
rfModel.rf.Classify(testData, predictions, probabilities);
|
||||
rfModel->rf.Classify(testData, predictions, probabilities);
|
||||
|
||||
// Did we want to calculate test accuracy?
|
||||
if (CLI::HasParam("test_labels"))
|
||||
@@ -164,14 +166,11 @@ static void mlpackMain()
|
||||
<< ")." << endl;
|
||||
}
|
||||
|
||||
// Should we save the outputs?
|
||||
if (CLI::HasParam("probabilities"))
|
||||
CLI::GetParam<arma::mat>("probabilities") = std::move(probabilities);
|
||||
if (CLI::HasParam("predictions"))
|
||||
CLI::GetParam<arma::Row<size_t>>("predictions") = std::move(predictions);
|
||||
// Save the outputs.
|
||||
CLI::GetParam<arma::mat>("probabilities") = std::move(probabilities);
|
||||
CLI::GetParam<arma::Row<size_t>>("predictions") = std::move(predictions);
|
||||
}
|
||||
|
||||
// Did the user want to save the output model?
|
||||
if (CLI::HasParam("output_model"))
|
||||
CLI::GetParam<RandomForestModel>("output_model") = std::move(rfModel);
|
||||
// Save the output model.
|
||||
CLI::GetParam<RandomForestModel*>("output_model") = rfModel;
|
||||
}
|
||||
|
||||
@@ -136,11 +136,13 @@ static void mlpackMain()
|
||||
"leaf size must be greater than 0");
|
||||
|
||||
// We either have to load the reference data, or we have to load the model.
|
||||
RSModel rs;
|
||||
RSModel* rs;
|
||||
const bool naive = CLI::HasParam("naive");
|
||||
const bool singleMode = CLI::HasParam("single_mode");
|
||||
if (CLI::HasParam("reference"))
|
||||
{
|
||||
rs = new RSModel();
|
||||
|
||||
// Get all the parameters.
|
||||
const string treeType = CLI::GetParam<string>("tree_type");
|
||||
RequireParamInSet<string>("tree_type", { "kd", "cover", "r", "r-star",
|
||||
@@ -178,8 +180,8 @@ static void mlpackMain()
|
||||
else if (treeType == "oct")
|
||||
tree = RSModel::OCTREE;
|
||||
|
||||
rs.TreeType() = tree;
|
||||
rs.RandomBasis() = randomBasis;
|
||||
rs->TreeType() = tree;
|
||||
rs->RandomBasis() = randomBasis;
|
||||
|
||||
arma::mat referenceSet = std::move(CLI::GetParam<arma::mat>("reference"));
|
||||
|
||||
@@ -189,22 +191,22 @@ static void mlpackMain()
|
||||
|
||||
const size_t leafSize = size_t(lsInt);
|
||||
|
||||
rs.BuildModel(std::move(referenceSet), leafSize, naive, singleMode);
|
||||
rs->BuildModel(std::move(referenceSet), leafSize, naive, singleMode);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Load the model from file.
|
||||
rs = std::move(CLI::GetParam<RSModel>("input_model"));
|
||||
rs = CLI::GetParam<RSModel*>("input_model");
|
||||
|
||||
Log::Info << "Using range search model from '"
|
||||
<< CLI::GetPrintableParam<RSModel>("input_model") << "' ("
|
||||
<< "trained on " << rs.Dataset().n_rows << "x" << rs.Dataset().n_cols
|
||||
<< "trained on " << rs->Dataset().n_rows << "x" << rs->Dataset().n_cols
|
||||
<< " dataset)." << endl;
|
||||
|
||||
// Adjust singleMode and naive if necessary.
|
||||
rs.SingleMode() = CLI::HasParam("single_mode");
|
||||
rs.Naive() = CLI::HasParam("naive");
|
||||
rs.LeafSize() = size_t(lsInt);
|
||||
rs->SingleMode() = CLI::HasParam("single_mode");
|
||||
rs->Naive() = CLI::HasParam("naive");
|
||||
rs->LeafSize() = size_t(lsInt);
|
||||
}
|
||||
|
||||
// Perform search, if desired.
|
||||
@@ -235,9 +237,9 @@ static void mlpackMain()
|
||||
vector<vector<double>> distances;
|
||||
|
||||
if (CLI::HasParam("query"))
|
||||
rs.Search(std::move(queryData), r, neighbors, distances);
|
||||
rs->Search(std::move(queryData), r, neighbors, distances);
|
||||
else
|
||||
rs.Search(r, neighbors, distances);
|
||||
rs->Search(r, neighbors, distances);
|
||||
|
||||
Log::Info << "Search complete." << endl;
|
||||
|
||||
@@ -301,7 +303,6 @@ static void mlpackMain()
|
||||
}
|
||||
}
|
||||
|
||||
// Save the output model, if desired.
|
||||
if (CLI::HasParam("output_model"))
|
||||
CLI::GetParam<RSModel>("output_model") = std::move(rs);
|
||||
// Save the output model.
|
||||
CLI::GetParam<RSModel*>("output_model") = rs;
|
||||
}
|
||||
|
||||
@@ -135,11 +135,13 @@ static void mlpackMain()
|
||||
"leaf size must be greater than 0");
|
||||
|
||||
// We either have to load the reference data, or we have to load the model.
|
||||
RANNModel rann;
|
||||
RANNModel* rann;
|
||||
const bool naive = CLI::HasParam("naive");
|
||||
const bool singleMode = CLI::HasParam("single_mode");
|
||||
if (CLI::HasParam("reference"))
|
||||
{
|
||||
rann = new RANNModel();
|
||||
|
||||
// Get all the parameters.
|
||||
const string treeType = CLI::GetParam<string>("tree_type");
|
||||
RequireParamInSet<string>("tree_type", { "kd", "cover", "r", "r-star", "x",
|
||||
@@ -169,8 +171,8 @@ static void mlpackMain()
|
||||
else if (treeType == "oct")
|
||||
tree = RANNModel::OCTREE;
|
||||
|
||||
rann.TreeType() = tree;
|
||||
rann.RandomBasis() = randomBasis;
|
||||
rann->TreeType() = tree;
|
||||
rann->RandomBasis() = randomBasis;
|
||||
|
||||
arma::mat referenceSet = std::move(CLI::GetParam<arma::mat>("reference"));
|
||||
|
||||
@@ -179,33 +181,33 @@ static void mlpackMain()
|
||||
<< referenceSet.n_rows << " x " << referenceSet.n_cols << ")."
|
||||
<< endl;
|
||||
|
||||
rann.BuildModel(std::move(referenceSet), size_t(lsInt), naive, singleMode);
|
||||
rann->BuildModel(std::move(referenceSet), size_t(lsInt), naive, singleMode);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Load the model from file.
|
||||
rann = std::move(CLI::GetParam<RANNModel>("input_model"));
|
||||
rann = CLI::GetParam<RANNModel*>("input_model");
|
||||
|
||||
Log::Info << "Using rank-approximate kNN model from '"
|
||||
<< CLI::GetPrintableParam<RANNModel>("input_model") << "' (trained on "
|
||||
<< rann.Dataset().n_rows << "x" << rann.Dataset().n_cols << " dataset)."
|
||||
<< endl;
|
||||
<< rann->Dataset().n_rows << "x" << rann->Dataset().n_cols
|
||||
<< " dataset)." << endl;
|
||||
|
||||
// Adjust singleMode and naive if necessary.
|
||||
rann.SingleMode() = CLI::HasParam("single_mode");
|
||||
rann.Naive() = CLI::HasParam("naive");
|
||||
rann.LeafSize() = size_t(lsInt);
|
||||
rann->SingleMode() = CLI::HasParam("single_mode");
|
||||
rann->Naive() = CLI::HasParam("naive");
|
||||
rann->LeafSize() = size_t(lsInt);
|
||||
}
|
||||
|
||||
// Apply the parameters for search.
|
||||
if (CLI::HasParam("tau"))
|
||||
rann.Tau() = CLI::GetParam<double>("tau");
|
||||
rann->Tau() = CLI::GetParam<double>("tau");
|
||||
if (CLI::HasParam("alpha"))
|
||||
rann.Alpha() = CLI::GetParam<double>("alpha");
|
||||
rann->Alpha() = CLI::GetParam<double>("alpha");
|
||||
if (CLI::HasParam("single_sample_limit"))
|
||||
rann.SingleSampleLimit() = CLI::GetParam<double>("single_sample_limit");
|
||||
rann.SampleAtLeaves() = CLI::HasParam("sample_at_leaves");
|
||||
rann.FirstLeafExact() = CLI::HasParam("sample_at_leaves");
|
||||
rann->SingleSampleLimit() = CLI::GetParam<double>("single_sample_limit");
|
||||
rann->SampleAtLeaves() = CLI::HasParam("sample_at_leaves");
|
||||
rann->FirstLeafExact() = CLI::HasParam("sample_at_leaves");
|
||||
|
||||
// Perform search, if desired.
|
||||
if (CLI::HasParam("k"))
|
||||
@@ -224,28 +226,26 @@ static void mlpackMain()
|
||||
// Sanity check on k value: must be greater than 0, must be less than the
|
||||
// number of reference points. Since it is unsigned, we only test the upper
|
||||
// bound.
|
||||
if (k > rann.Dataset().n_cols)
|
||||
if (k > rann->Dataset().n_cols)
|
||||
{
|
||||
Log::Fatal << "Invalid k: " << k << "; must be greater than 0 and less ";
|
||||
Log::Fatal << "than or equal to the number of reference points (";
|
||||
Log::Fatal << rann.Dataset().n_cols << ")." << endl;
|
||||
Log::Fatal << rann->Dataset().n_cols << ")." << endl;
|
||||
}
|
||||
|
||||
arma::Mat<size_t> neighbors;
|
||||
arma::mat distances;
|
||||
if (CLI::HasParam("query"))
|
||||
rann.Search(std::move(queryData), k, neighbors, distances);
|
||||
rann->Search(std::move(queryData), k, neighbors, distances);
|
||||
else
|
||||
rann.Search(k, neighbors, distances);
|
||||
rann->Search(k, neighbors, distances);
|
||||
Log::Info << "Search complete." << endl;
|
||||
|
||||
// Save output, if desired.
|
||||
if (CLI::HasParam("neighbors"))
|
||||
CLI::GetParam<arma::Mat<size_t>>("neighbors") = std::move(neighbors);
|
||||
if (CLI::HasParam("distances"))
|
||||
CLI::GetParam<arma::mat>("distances") = std::move(distances);
|
||||
// Save output.
|
||||
CLI::GetParam<arma::Mat<size_t>>("neighbors") = std::move(neighbors);
|
||||
CLI::GetParam<arma::mat>("distances") = std::move(distances);
|
||||
}
|
||||
|
||||
if (CLI::HasParam("output_model"))
|
||||
CLI::GetParam<RANNModel>("output_model") = std::move(rann);
|
||||
// Save the output model.
|
||||
CLI::GetParam<RANNModel*>("output_model") = rann;
|
||||
}
|
||||
|
||||
@@ -113,7 +113,7 @@ void TestClassifyAcc(const size_t numClasses, const Model& model);
|
||||
|
||||
// Build the softmax model given the parameters.
|
||||
template<typename Model>
|
||||
unique_ptr<Model> TrainSoftmax(const size_t maxIterations);
|
||||
Model* TrainSoftmax(const size_t maxIterations);
|
||||
|
||||
static void mlpackMain()
|
||||
{
|
||||
@@ -144,13 +144,11 @@ static void mlpackMain()
|
||||
RequireAtLeastOnePassed({ "output_model", "predictions" }, false, "no results"
|
||||
" will be saved");
|
||||
|
||||
using SM = SoftmaxRegression;
|
||||
unique_ptr<SM> sm = TrainSoftmax<SM>(maxIterations);
|
||||
SoftmaxRegression* sm = TrainSoftmax<SoftmaxRegression>(maxIterations);
|
||||
|
||||
TestClassifyAcc(sm->NumClasses(), *sm);
|
||||
|
||||
if (CLI::HasParam("output_model"))
|
||||
CLI::GetParam<SM>("output_model") = std::move(*sm);
|
||||
CLI::GetParam<SoftmaxRegression*>("output_model") = sm;
|
||||
}
|
||||
|
||||
size_t CalculateNumberOfClasses(const size_t numClasses,
|
||||
@@ -233,17 +231,14 @@ void TestClassifyAcc(size_t numClasses, const Model& model)
|
||||
}
|
||||
|
||||
template<typename Model>
|
||||
unique_ptr<Model> TrainSoftmax(const size_t maxIterations)
|
||||
Model* TrainSoftmax(const size_t maxIterations)
|
||||
{
|
||||
using namespace mlpack;
|
||||
|
||||
using SRF = regression::SoftmaxRegressionFunction;
|
||||
|
||||
unique_ptr<Model> sm;
|
||||
Model* sm;
|
||||
if (CLI::HasParam("input_model"))
|
||||
{
|
||||
sm.reset(new Model(0, 0, false));
|
||||
*sm = std::move(CLI::GetParam<Model>("input_model"));
|
||||
sm = CLI::GetParam<Model*>("input_model");
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -262,8 +257,8 @@ unique_ptr<Model> TrainSoftmax(const size_t maxIterations)
|
||||
|
||||
const size_t numBasis = 5;
|
||||
optimization::L_BFGS optimizer(numBasis, maxIterations);
|
||||
sm.reset(new Model(trainData, trainLabels, numClasses,
|
||||
CLI::GetParam<double>("lambda"), intercept, std::move(optimizer)));
|
||||
sm = new Model(trainData, trainLabels, numClasses,
|
||||
CLI::GetParam<double>("lambda"), intercept, std::move(optimizer));
|
||||
}
|
||||
|
||||
return sm;
|
||||
|
||||
@@ -146,9 +146,11 @@ static void mlpackMain()
|
||||
"Newton method tolerance must be nonnegative");
|
||||
|
||||
// Do we have an existing model?
|
||||
SparseCoding sc(0, 0.0);
|
||||
SparseCoding* sc;
|
||||
if (CLI::HasParam("input_model"))
|
||||
sc = std::move(CLI::GetParam<SparseCoding>("input_model"));
|
||||
sc = CLI::GetParam<SparseCoding*>("input_model");
|
||||
else
|
||||
sc = new SparseCoding(0, 0.0);
|
||||
|
||||
if (CLI::HasParam("training"))
|
||||
{
|
||||
@@ -162,12 +164,12 @@ static void mlpackMain()
|
||||
matX.col(i) /= norm(matX.col(i), 2);
|
||||
}
|
||||
|
||||
sc.Lambda1() = CLI::GetParam<double>("lambda1");
|
||||
sc.Lambda2() = CLI::GetParam<double>("lambda2");
|
||||
sc.MaxIterations() = (size_t) CLI::GetParam<int>("max_iterations");
|
||||
sc.Atoms() = (size_t) CLI::GetParam<int>("atoms");
|
||||
sc.ObjTolerance() = CLI::GetParam<double>("objective_tolerance");
|
||||
sc.NewtonTolerance() = CLI::GetParam<double>("newton_tolerance");
|
||||
sc->Lambda1() = CLI::GetParam<double>("lambda1");
|
||||
sc->Lambda2() = CLI::GetParam<double>("lambda2");
|
||||
sc->MaxIterations() = (size_t) CLI::GetParam<int>("max_iterations");
|
||||
sc->Atoms() = (size_t) CLI::GetParam<int>("atoms");
|
||||
sc->ObjTolerance() = CLI::GetParam<double>("objective_tolerance");
|
||||
sc->NewtonTolerance() = CLI::GetParam<double>("newton_tolerance");
|
||||
|
||||
// Inform the user if we are overwriting their model.
|
||||
if (CLI::HasParam("input_model"))
|
||||
@@ -175,36 +177,36 @@ static void mlpackMain()
|
||||
Log::Info << "Using dictionary from existing model in '"
|
||||
<< CLI::GetPrintableParam<SparseCoding>("input_model")
|
||||
<< "' as initial dictionary for training." << endl;
|
||||
sc.Train<NothingInitializer>(matX);
|
||||
sc->Train<NothingInitializer>(matX);
|
||||
}
|
||||
else if (CLI::HasParam("initial_dictionary"))
|
||||
{
|
||||
// Load initial dictionary directly into sparse coding object.
|
||||
sc.Dictionary() =
|
||||
sc->Dictionary() =
|
||||
std::move(CLI::GetParam<arma::mat>("initial_dictionary"));
|
||||
|
||||
// Validate size of initial dictionary.
|
||||
if (sc.Dictionary().n_cols != sc.Atoms())
|
||||
if (sc->Dictionary().n_cols != sc->Atoms())
|
||||
{
|
||||
Log::Fatal << "The initial dictionary has " << sc.Dictionary().n_cols
|
||||
Log::Fatal << "The initial dictionary has " << sc->Dictionary().n_cols
|
||||
<< " atoms, but the number of atoms was specified to be "
|
||||
<< sc.Atoms() << "!" << endl;
|
||||
<< sc->Atoms() << "!" << endl;
|
||||
}
|
||||
|
||||
if (sc.Dictionary().n_rows != matX.n_rows)
|
||||
if (sc->Dictionary().n_rows != matX.n_rows)
|
||||
{
|
||||
Log::Fatal << "The initial dictionary has " << sc.Dictionary().n_rows
|
||||
Log::Fatal << "The initial dictionary has " << sc->Dictionary().n_rows
|
||||
<< " dimensions, but the data has " << matX.n_rows << " dimensions!"
|
||||
<< endl;
|
||||
}
|
||||
|
||||
// Run sparse coding.
|
||||
sc.Train<NothingInitializer>(matX);
|
||||
sc->Train<NothingInitializer>(matX);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Run sparse coding with the default initialization.
|
||||
sc.Train(matX);
|
||||
sc->Train(matX);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -213,9 +215,9 @@ static void mlpackMain()
|
||||
{
|
||||
mat matY = std::move(CLI::GetParam<arma::mat>("test"));
|
||||
|
||||
if (matY.n_rows != sc.Dictionary().n_rows)
|
||||
if (matY.n_rows != sc->Dictionary().n_rows)
|
||||
Log::Fatal << "Model was trained with a dimensionality of "
|
||||
<< sc.Dictionary().n_rows << ", but test data '"
|
||||
<< sc->Dictionary().n_rows << ", but test data '"
|
||||
<< CLI::GetPrintableParam<arma::mat>("test") << "' have a "
|
||||
<< "dimensionality of " << matY.n_rows << "!" << endl;
|
||||
|
||||
@@ -228,20 +230,15 @@ static void mlpackMain()
|
||||
}
|
||||
|
||||
mat codes;
|
||||
sc.Encode(matY, codes);
|
||||
sc->Encode(matY, codes);
|
||||
|
||||
if (CLI::HasParam("codes"))
|
||||
CLI::GetParam<arma::mat>("codes") = std::move(codes);
|
||||
CLI::GetParam<arma::mat>("codes") = std::move(codes);
|
||||
}
|
||||
|
||||
// Did the user want to save the dictionary? If so we can move that, but only
|
||||
// if we are not also saving an output model.
|
||||
if (CLI::HasParam("dictionary") && !CLI::HasParam("output_model"))
|
||||
CLI::GetParam<arma::mat>("dictionary") = std::move(sc.Dictionary());
|
||||
else if (CLI::HasParam("dictionary"))
|
||||
CLI::GetParam<arma::mat>("dictionary") = sc.Dictionary();
|
||||
// Did the user want to save the dictionary? Use an alias for the dictionary.
|
||||
CLI::GetParam<arma::mat>("dictionary") = arma::mat(sc->Dictionary().memptr(),
|
||||
sc->Dictionary().n_rows, sc->Dictionary().n_cols, false, false);
|
||||
|
||||
// Did the user want to save the model?
|
||||
if (CLI::HasParam("output_model"))
|
||||
CLI::GetParam<SparseCoding>("output_model") = std::move(sc);
|
||||
// Save the model.
|
||||
CLI::GetParam<SparseCoding*>("output_model") = sc;
|
||||
}
|
||||
|
||||
@@ -238,20 +238,21 @@ BOOST_AUTO_TEST_CASE(GetParamModelTest)
|
||||
data::Save("kernel.bin", "model", gk);
|
||||
|
||||
// Create tuple.
|
||||
gk.Bandwidth(2.0);
|
||||
tuple<GaussianKernel, string> t = make_tuple(gk, filename);
|
||||
tuple<GaussianKernel*, string> t = make_tuple((GaussianKernel*) NULL,
|
||||
filename);
|
||||
d.value = boost::any(t);
|
||||
// Make sure it is not loaded yet.
|
||||
d.input = true;
|
||||
d.loaded = false;
|
||||
|
||||
GaussianKernel* output = NULL;
|
||||
GetParam<GaussianKernel>((const util::ParamData&) d, (void*) NULL,
|
||||
GaussianKernel** output = NULL;
|
||||
GetParam<GaussianKernel*>((const util::ParamData&) d, (void*) NULL,
|
||||
(void*) &output);
|
||||
|
||||
BOOST_REQUIRE_EQUAL(output->Bandwidth(), 5.0);
|
||||
BOOST_REQUIRE_EQUAL((*output)->Bandwidth(), 5.0);
|
||||
|
||||
remove("kernel.bin");
|
||||
delete *output;
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(RawParamDoubleTest)
|
||||
@@ -300,17 +301,17 @@ BOOST_AUTO_TEST_CASE(GetRawParamModelTest)
|
||||
kernel::GaussianKernel gk(5.0);
|
||||
|
||||
// Create tuple.
|
||||
tuple<GaussianKernel, string> t = make_tuple(gk, filename);
|
||||
tuple<GaussianKernel*, string> t = make_tuple(&gk, filename);
|
||||
d.value = boost::any(t);
|
||||
// Make sure it is not loaded yet.
|
||||
d.input = true;
|
||||
d.loaded = false;
|
||||
|
||||
tuple<GaussianKernel, string>* output = NULL;
|
||||
GetRawParam<tuple<GaussianKernel, string>>((const util::ParamData&) d,
|
||||
tuple<GaussianKernel*, string>* output = NULL;
|
||||
GetRawParam<tuple<GaussianKernel*, string>>((const util::ParamData&) d,
|
||||
(void*) NULL, (void*) &output);
|
||||
|
||||
BOOST_REQUIRE_EQUAL(get<0>(*output).Bandwidth(), 5.0);
|
||||
BOOST_REQUIRE_EQUAL(get<0>(*output)->Bandwidth(), 5.0);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(GetRawParamDatasetInfoTest)
|
||||
@@ -403,7 +404,7 @@ BOOST_AUTO_TEST_CASE(OutputParamModelTest)
|
||||
// Create value.
|
||||
string filename = "kernel.bin";
|
||||
GaussianKernel gk(5.0);
|
||||
tuple<GaussianKernel, string> t = make_tuple(gk, filename);
|
||||
tuple<GaussianKernel*, string> t = make_tuple(&gk, filename);
|
||||
|
||||
d.value = boost::any(t);
|
||||
d.input = false;
|
||||
@@ -491,7 +492,7 @@ BOOST_AUTO_TEST_CASE(SetParamModelTest)
|
||||
// Create initial value.
|
||||
string filename = "kernel.bin";
|
||||
GaussianKernel gk(2.0);
|
||||
d.value = boost::any(make_tuple(gk, filename));
|
||||
d.value = boost::any(make_tuple(&gk, filename));
|
||||
|
||||
// Get a new string.
|
||||
string newFilename = "new_kernel.bin";
|
||||
@@ -501,8 +502,8 @@ BOOST_AUTO_TEST_CASE(SetParamModelTest)
|
||||
(void*) NULL);
|
||||
|
||||
// Make sure the change went through.
|
||||
tuple<GaussianKernel, string>& t =
|
||||
*boost::any_cast<tuple<GaussianKernel, string>>(&d.value);
|
||||
tuple<GaussianKernel*, string>& t =
|
||||
*boost::any_cast<tuple<GaussianKernel*, string>>(&d.value);
|
||||
|
||||
BOOST_REQUIRE_EQUAL(get<1>(t), "new_kernel.bin");
|
||||
}
|
||||
@@ -537,4 +538,97 @@ BOOST_AUTO_TEST_CASE(SetParamDatasetInfoMatTest)
|
||||
BOOST_REQUIRE_EQUAL(get<1>(t3), "new_filename.csv");
|
||||
}
|
||||
|
||||
// Test that GetAllocatedMemory() will properly return NULL for a non-model
|
||||
// type.
|
||||
BOOST_AUTO_TEST_CASE(GetAllocatedMemoryNonModelTest)
|
||||
{
|
||||
util::ParamData d;
|
||||
|
||||
bool b = true;
|
||||
d.value = boost::any(b);
|
||||
d.input = true;
|
||||
|
||||
void* result = (void*) 1; // Invalid pointer, should be overwritten.
|
||||
|
||||
GetAllocatedMemory<bool>((const util::ParamData&) d,
|
||||
(const void*) NULL, (void*) &result);
|
||||
|
||||
BOOST_REQUIRE_EQUAL(result, (void*) NULL);
|
||||
|
||||
// Also test with a matrix type.
|
||||
arma::mat test(10, 10, arma::fill::ones);
|
||||
string filename = "test.csv";
|
||||
tuple<arma::mat, string> t = make_tuple(test, filename);
|
||||
d.value = boost::any(t);
|
||||
|
||||
result = (void*) 1;
|
||||
|
||||
GetAllocatedMemory<arma::mat>((const util::ParamData&) d,
|
||||
(const void*) NULL, (void*) &result);
|
||||
|
||||
BOOST_REQUIRE_EQUAL(result, (void*) NULL);
|
||||
}
|
||||
|
||||
// Test that GetAllocatedMemory() will properly return pointers for a
|
||||
// serializable model type.
|
||||
BOOST_AUTO_TEST_CASE(GetAllocatedMemoryModelTest)
|
||||
{
|
||||
util::ParamData d;
|
||||
|
||||
GaussianKernel g(2.0);
|
||||
string filename = "hello.bin";
|
||||
tuple<GaussianKernel*, string> t = make_tuple(&g, filename);
|
||||
d.value = boost::any(t);
|
||||
d.input = true;
|
||||
|
||||
void* result = NULL;
|
||||
|
||||
GetAllocatedMemory<GaussianKernel*>((const util::ParamData&) d,
|
||||
(const void*) NULL, (void*) &result);
|
||||
|
||||
BOOST_REQUIRE_EQUAL(&g, (GaussianKernel*) result);
|
||||
}
|
||||
|
||||
// Test that calling DeleteAllocatedMemory() on non-model types does not delete
|
||||
// pointers.
|
||||
BOOST_AUTO_TEST_CASE(DeleteAllocatedMemoryNonModelTest)
|
||||
{
|
||||
util::ParamData d;
|
||||
|
||||
bool b = true;
|
||||
d.value = boost::any(b);
|
||||
d.input = true;
|
||||
|
||||
DeleteAllocatedMemory<bool>((const util::ParamData&) d,
|
||||
(const void*) NULL, (void*) NULL);
|
||||
|
||||
arma::mat test(10, 10, arma::fill::ones);
|
||||
string filename = "test.csv";
|
||||
tuple<arma::mat, string> t = make_tuple(test, filename);
|
||||
d.value = boost::any(t);
|
||||
|
||||
DeleteAllocatedMemory<arma::mat>((const util::ParamData&) d,
|
||||
(const void*) NULL, (void*) NULL);
|
||||
}
|
||||
|
||||
// Test that DeleteAllocatedMemory() will properly delete pointers for a
|
||||
// serializable model type.
|
||||
BOOST_AUTO_TEST_CASE(DeleteAllocatedMemoryModelTest)
|
||||
{
|
||||
// This test will just delete it, and we'll hope that it worked and that
|
||||
// valgrind won't throw any issues (so really we can't *quite* test this in
|
||||
// the context of the boost unit test framework).
|
||||
util::ParamData d;
|
||||
|
||||
GaussianKernel* g = new GaussianKernel(2.0);
|
||||
string filename = "hello.bin";
|
||||
tuple<GaussianKernel*, string> t = make_tuple(g, filename);
|
||||
|
||||
d.value = boost::any(t);
|
||||
d.input = false;
|
||||
|
||||
DeleteAllocatedMemory<GaussianKernel*>((const util::ParamData&) d,
|
||||
(const void*) NULL, (void*) NULL);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END();
|
||||
|
||||
@@ -866,9 +866,9 @@ BOOST_AUTO_TEST_CASE(UnmappedParamTest)
|
||||
BOOST_REQUIRE_EQUAL(CLI::GetPrintableParam<arma::mat>("matrix"), "file1.csv");
|
||||
BOOST_REQUIRE_EQUAL(CLI::GetPrintableParam<arma::mat>("matrix2"),
|
||||
"file2.csv");
|
||||
BOOST_REQUIRE_EQUAL(CLI::GetPrintableParam<GaussianKernel>("kernel"),
|
||||
BOOST_REQUIRE_EQUAL(CLI::GetPrintableParam<GaussianKernel*>("kernel"),
|
||||
"kernel.txt");
|
||||
BOOST_REQUIRE_EQUAL(CLI::GetPrintableParam<GaussianKernel>("kernel2"),
|
||||
BOOST_REQUIRE_EQUAL(CLI::GetPrintableParam<GaussianKernel*>("kernel2"),
|
||||
"kernel2.txt");
|
||||
|
||||
remove("kernel.txt");
|
||||
@@ -894,9 +894,9 @@ BOOST_AUTO_TEST_CASE(SerializationTest)
|
||||
ParseCommandLine(argc, const_cast<char**>(argv));
|
||||
|
||||
// Create the kernel we'll save.
|
||||
GaussianKernel gk(0.5);
|
||||
GaussianKernel* gk = new GaussianKernel(0.5);
|
||||
|
||||
CLI::GetParam<GaussianKernel>("kernel") = move(gk);
|
||||
CLI::GetParam<GaussianKernel*>("kernel") = gk;
|
||||
|
||||
// Save it.
|
||||
EndProgram();
|
||||
@@ -910,9 +910,12 @@ BOOST_AUTO_TEST_CASE(SerializationTest)
|
||||
ParseCommandLine(argc, const_cast<char**>(argv));
|
||||
|
||||
// Load the kernel from file.
|
||||
GaussianKernel gk2 = move(CLI::GetParam<GaussianKernel>("kernel"));
|
||||
GaussianKernel* gk2 = CLI::GetParam<GaussianKernel*>("kernel");
|
||||
|
||||
BOOST_REQUIRE_CLOSE(gk2.Bandwidth(), 0.5, 1e-5);
|
||||
BOOST_REQUIRE_CLOSE(gk2->Bandwidth(), 0.5, 1e-5);
|
||||
|
||||
// Clean up the memory...
|
||||
delete gk2;
|
||||
|
||||
// Now remove the file we made.
|
||||
remove("kernel.txt");
|
||||
|
||||
@@ -761,7 +761,6 @@ BOOST_AUTO_TEST_CASE(UseExistingModelTest)
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE(DiagonalGMMTrainTest)
|
||||
{
|
||||
Log::Warn.ignoreInput = false;
|
||||
// We'll have three diagonal-covariance Gaussian distributions from this
|
||||
// mixture.
|
||||
distribution::GaussianDistribution d1("0.0 1.0 0.0", "1.0 0.0 0.0;"
|
||||
|
||||
@@ -35,6 +35,7 @@ struct DecisionStumpTestFixture
|
||||
~DecisionStumpTestFixture()
|
||||
{
|
||||
// Clear the settings.
|
||||
bindings::tests::CleanMemory();
|
||||
CLI::ClearSettings();
|
||||
}
|
||||
};
|
||||
@@ -136,6 +137,9 @@ BOOST_AUTO_TEST_CASE(DecisionStumpLabelsLessDimensionTest)
|
||||
arma::Row<size_t> predictions;
|
||||
predictions = std::move(CLI::GetParam<arma::Row<size_t>>("predictions"));
|
||||
|
||||
// Delete the previous model.
|
||||
bindings::tests::CleanMemory();
|
||||
|
||||
// Now train DS with labels provided.
|
||||
|
||||
// Delete last row of inputData.
|
||||
@@ -198,7 +202,7 @@ BOOST_AUTO_TEST_CASE(DecisionStumpModelReuseTest)
|
||||
// Input trained model.
|
||||
SetInputParam("test", std::move(testData));
|
||||
SetInputParam("input_model",
|
||||
std::move(CLI::GetParam<DSModel>("output_model")));
|
||||
std::move(CLI::GetParam<DSModel*>("output_model")));
|
||||
|
||||
mlpackMain();
|
||||
|
||||
@@ -249,7 +253,7 @@ BOOST_AUTO_TEST_CASE(DecisionStumpTrainingVerTest)
|
||||
|
||||
// Input pre-trained model.
|
||||
SetInputParam("input_model",
|
||||
std::move(CLI::GetParam<DSModel>("output_model")));
|
||||
std::move(CLI::GetParam<DSModel*>("output_model")));
|
||||
|
||||
Log::Fatal.ignoreInput = true;
|
||||
BOOST_REQUIRE_THROW(mlpackMain(), std::runtime_error);
|
||||
|
||||
@@ -36,6 +36,7 @@ struct DecisionTreeTestFixture
|
||||
~DecisionTreeTestFixture()
|
||||
{
|
||||
// Clear the settings.
|
||||
bindings::tests::CleanMemory();
|
||||
CLI::ClearSettings();
|
||||
}
|
||||
};
|
||||
@@ -207,7 +208,7 @@ BOOST_AUTO_TEST_CASE(DecisionModelReuseTest)
|
||||
// Input trained model.
|
||||
SetInputParam("test", std::move(std::make_tuple(info, testData)));
|
||||
SetInputParam("input_model",
|
||||
std::move(CLI::GetParam<DecisionTreeModel>("output_model")));
|
||||
std::move(CLI::GetParam<DecisionTreeModel*>("output_model")));
|
||||
|
||||
mlpackMain();
|
||||
|
||||
@@ -254,7 +255,7 @@ BOOST_AUTO_TEST_CASE(DecisionTreeTrainingVerTest)
|
||||
|
||||
// Input pre-trained model.
|
||||
SetInputParam("input_model",
|
||||
std::move(CLI::GetParam<DecisionTreeModel>("output_model")));
|
||||
std::move(CLI::GetParam<DecisionTreeModel*>("output_model")));
|
||||
|
||||
Log::Fatal.ignoreInput = true;
|
||||
BOOST_REQUIRE_THROW(mlpackMain(), std::runtime_error);
|
||||
@@ -308,7 +309,7 @@ BOOST_AUTO_TEST_CASE(DecisionModelCategoricalReuseTest)
|
||||
// Input trained model.
|
||||
SetInputParam("test", std::move(std::make_tuple(info, testData)));
|
||||
SetInputParam("input_model",
|
||||
std::move(CLI::GetParam<DecisionTreeModel>("output_model")));
|
||||
std::move(CLI::GetParam<DecisionTreeModel*>("output_model")));
|
||||
|
||||
mlpackMain();
|
||||
|
||||
|
||||
@@ -38,6 +38,7 @@ struct EMSTTestFixture
|
||||
~EMSTTestFixture()
|
||||
{
|
||||
// Clear the settings.
|
||||
bindings::tests::CleanMemory();
|
||||
CLI::ClearSettings();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -32,6 +32,7 @@ struct LRTestFixture
|
||||
~LRTestFixture()
|
||||
{
|
||||
// Clear the settings.
|
||||
bindings::tests::CleanMemory();
|
||||
CLI::ClearSettings();
|
||||
}
|
||||
};
|
||||
@@ -66,6 +67,7 @@ BOOST_AUTO_TEST_CASE(LRDifferentLambdas)
|
||||
mlpackMain();
|
||||
const double testY1 = CLI::GetParam<arma::rowvec>("output_predictions")(0);
|
||||
|
||||
bindings::tests::CleanMemory();
|
||||
ResetSettings();
|
||||
|
||||
SetInputParam("training", std::move(trainX));
|
||||
@@ -100,6 +102,7 @@ BOOST_AUTO_TEST_CASE(LRResponsesRepresentation)
|
||||
mlpackMain();
|
||||
const double testY1 = CLI::GetParam<arma::rowvec>("output_predictions")(0);
|
||||
|
||||
bindings::tests::CleanMemory();
|
||||
ResetSettings();
|
||||
|
||||
arma::mat trainX2({1.0, 2.0, 3.0});
|
||||
@@ -135,12 +138,12 @@ BOOST_AUTO_TEST_CASE(LRModelReload)
|
||||
|
||||
mlpackMain();
|
||||
|
||||
LinearRegression model = CLI::GetParam<LinearRegression>("output_model");
|
||||
LinearRegression* model = CLI::GetParam<LinearRegression*>("output_model");
|
||||
const arma::rowvec testY1 = CLI::GetParam<arma::rowvec>("output_predictions");
|
||||
|
||||
ResetSettings();
|
||||
|
||||
SetInputParam("input_model", std::move(model));
|
||||
SetInputParam("input_model", model);
|
||||
SetInputParam("test", std::move(testX));
|
||||
|
||||
mlpackMain();
|
||||
@@ -209,7 +212,7 @@ BOOST_AUTO_TEST_CASE(LRWrongDimOfDataTest2)
|
||||
|
||||
mlpackMain();
|
||||
|
||||
LinearRegression model = CLI::GetParam<LinearRegression>("output_model");
|
||||
LinearRegression* model = CLI::GetParam<LinearRegression*>("output_model");
|
||||
|
||||
ResetSettings();
|
||||
|
||||
|
||||
@@ -35,6 +35,7 @@ struct NBCTestFixture
|
||||
~NBCTestFixture()
|
||||
{
|
||||
// Clear the settings.
|
||||
bindings::tests::CleanMemory();
|
||||
CLI::ClearSettings();
|
||||
}
|
||||
};
|
||||
@@ -142,6 +143,8 @@ BOOST_AUTO_TEST_CASE(NBCLabelsLessDimensionTest)
|
||||
output = std::move(CLI::GetParam<arma::Row<size_t>>("output"));
|
||||
output_probs = std::move(CLI::GetParam<arma::mat>("output_probs"));
|
||||
|
||||
bindings::tests::CleanMemory();
|
||||
|
||||
// Now train NBC with labels provided.
|
||||
|
||||
inputData.shed_row(inputData.n_rows - 1);
|
||||
@@ -208,7 +211,7 @@ BOOST_AUTO_TEST_CASE(NBCModelReuseTest)
|
||||
// Input trained model.
|
||||
SetInputParam("test", std::move(testData));
|
||||
SetInputParam("input_model",
|
||||
std::move(CLI::GetParam<NBCModel>("output_model")));
|
||||
std::move(CLI::GetParam<NBCModel*>("output_model")));
|
||||
|
||||
mlpackMain();
|
||||
|
||||
@@ -244,7 +247,7 @@ BOOST_AUTO_TEST_CASE(NBCTrainingVerTest)
|
||||
|
||||
// Input pre-trained model.
|
||||
SetInputParam("input_model",
|
||||
std::move(CLI::GetParam<NBCModel>("output_model")));
|
||||
std::move(CLI::GetParam<NBCModel*>("output_model")));
|
||||
|
||||
Log::Fatal.ignoreInput = true;
|
||||
BOOST_REQUIRE_THROW(mlpackMain(), std::runtime_error);
|
||||
@@ -290,6 +293,8 @@ BOOST_AUTO_TEST_CASE(NBCIncrementalVarianceTest)
|
||||
BOOST_REQUIRE_EQUAL(CLI::GetParam<arma::Row<size_t>>("output").n_rows, 1);
|
||||
BOOST_REQUIRE_EQUAL(CLI::GetParam<arma::mat>("output_probs").n_rows, 2);
|
||||
|
||||
bindings::tests::CleanMemory();
|
||||
|
||||
// Reset data passed.
|
||||
CLI::GetSingleton().Parameters()["training"].wasPassed = false;
|
||||
CLI::GetSingleton().Parameters()["incremental_variance"].wasPassed = false;
|
||||
|
||||
@@ -31,6 +31,7 @@ struct PCATestFixture
|
||||
~PCATestFixture()
|
||||
{
|
||||
// Clear the settings.
|
||||
bindings::tests::CleanMemory();
|
||||
CLI::ClearSettings();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -35,6 +35,7 @@ struct PerceptronTestFixture
|
||||
~PerceptronTestFixture()
|
||||
{
|
||||
// Clear the settings.
|
||||
bindings::tests::CleanMemory();
|
||||
CLI::ClearSettings();
|
||||
}
|
||||
};
|
||||
@@ -137,7 +138,9 @@ BOOST_AUTO_TEST_CASE(PerceptronLabelsLessDimensionTest)
|
||||
arma::Row<size_t> output;
|
||||
output = std::move(CLI::GetParam<arma::Row<size_t>>("output"));
|
||||
|
||||
// Now train pereptron with labels provided.
|
||||
bindings::tests::CleanMemory();
|
||||
|
||||
// Now train perceptron with labels provided.
|
||||
|
||||
// Input training data.
|
||||
SetInputParam("training", std::move(inputData));
|
||||
@@ -195,7 +198,7 @@ BOOST_AUTO_TEST_CASE(PerceptronModelReuseTest)
|
||||
// Input trained model.
|
||||
SetInputParam("test", std::move(testData));
|
||||
SetInputParam("input_model",
|
||||
std::move(CLI::GetParam<PerceptronModel>("output_model")));
|
||||
CLI::GetParam<PerceptronModel*>("output_model"));
|
||||
|
||||
mlpackMain();
|
||||
|
||||
|
||||
@@ -35,6 +35,7 @@ struct PreprocessBinarizeTestFixture
|
||||
~PreprocessBinarizeTestFixture()
|
||||
{
|
||||
// Clear the settings.
|
||||
bindings::tests::CleanMemory();
|
||||
CLI::ClearSettings();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -37,6 +37,7 @@ struct PreprocessImputerTestFixture
|
||||
~PreprocessImputerTestFixture()
|
||||
{
|
||||
// Clear the settings.
|
||||
bindings::tests::CleanMemory();
|
||||
CLI::ClearSettings();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -37,6 +37,7 @@ struct PreprocessSplitTestFixture
|
||||
~PreprocessSplitTestFixture()
|
||||
{
|
||||
// Clear the settings.
|
||||
bindings::tests::CleanMemory();
|
||||
CLI::ClearSettings();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -35,6 +35,7 @@ struct RandomForestTestFixture
|
||||
~RandomForestTestFixture()
|
||||
{
|
||||
// Clear the settings.
|
||||
bindings::tests::CleanMemory();
|
||||
CLI::ClearSettings();
|
||||
}
|
||||
};
|
||||
@@ -124,7 +125,7 @@ BOOST_AUTO_TEST_CASE(RandomForestModelReuseTest)
|
||||
// Input trained model.
|
||||
SetInputParam("test", std::move(testData));
|
||||
SetInputParam("input_model",
|
||||
std::move(CLI::GetParam<RandomForestModel>("output_model")));
|
||||
CLI::GetParam<RandomForestModel*>("output_model"));
|
||||
|
||||
mlpackMain();
|
||||
|
||||
@@ -206,7 +207,7 @@ BOOST_AUTO_TEST_CASE(RandomForestTrainingVerTest)
|
||||
|
||||
// Input pre-trained model.
|
||||
SetInputParam("input_model",
|
||||
std::move(CLI::GetParam<RandomForestModel>("output_model")));
|
||||
CLI::GetParam<RandomForestModel*>("output_model"));
|
||||
|
||||
Log::Fatal.ignoreInput = true;
|
||||
BOOST_REQUIRE_THROW(mlpackMain(), std::runtime_error);
|
||||
@@ -218,7 +219,7 @@ BOOST_AUTO_TEST_CASE(RandomForestTrainingVerTest)
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE(RandomForestDiffMinLeafSizeTest)
|
||||
{
|
||||
// Train for minimium leaf size 20.
|
||||
// Train for minimum leaf size 20.
|
||||
arma::mat inputData;
|
||||
if (!data::Load("vc2.csv", inputData))
|
||||
BOOST_FAIL("Cannot load train dataset vc2.csv!");
|
||||
@@ -236,13 +237,15 @@ BOOST_AUTO_TEST_CASE(RandomForestDiffMinLeafSizeTest)
|
||||
|
||||
// Calculate training accuracy.
|
||||
arma::Row<size_t> predictions;
|
||||
CLI::GetParam<RandomForestModel>("output_model").rf.Classify(inputData,
|
||||
CLI::GetParam<RandomForestModel*>("output_model")->rf.Classify(inputData,
|
||||
predictions);
|
||||
|
||||
size_t correct = arma::accu(predictions == labels);
|
||||
double accuracy20 = (double(correct) / double(labels.n_elem) * 100);
|
||||
|
||||
// Train for minimium leaf size 10.
|
||||
bindings::tests::CleanMemory();
|
||||
|
||||
// Train for minimum leaf size 10.
|
||||
|
||||
// Input training data.
|
||||
SetInputParam("training", inputData);
|
||||
@@ -252,13 +255,15 @@ BOOST_AUTO_TEST_CASE(RandomForestDiffMinLeafSizeTest)
|
||||
mlpackMain();
|
||||
|
||||
// Calculate training accuracy.
|
||||
CLI::GetParam<RandomForestModel>("output_model").rf.Classify(inputData,
|
||||
CLI::GetParam<RandomForestModel*>("output_model")->rf.Classify(inputData,
|
||||
predictions);
|
||||
|
||||
correct = arma::accu(predictions == labels);
|
||||
double accuracy10 = (double(correct) / double(labels.n_elem) * 100);
|
||||
|
||||
// Train for minimium leaf size 1.
|
||||
bindings::tests::CleanMemory();
|
||||
|
||||
// Train for minimum leaf size 1.
|
||||
|
||||
// Input training data.
|
||||
SetInputParam("training", inputData);
|
||||
@@ -268,7 +273,7 @@ BOOST_AUTO_TEST_CASE(RandomForestDiffMinLeafSizeTest)
|
||||
mlpackMain();
|
||||
|
||||
// Calculate training accuracy.
|
||||
CLI::GetParam<RandomForestModel>("output_model").rf.Classify(inputData,
|
||||
CLI::GetParam<RandomForestModel*>("output_model")->rf.Classify(inputData,
|
||||
predictions);
|
||||
|
||||
correct = arma::accu(predictions == labels);
|
||||
@@ -308,8 +313,9 @@ BOOST_AUTO_TEST_CASE(RandomForestDiffNumTreeTest)
|
||||
|
||||
// Calculate training accuracy.
|
||||
arma::Row<size_t> predictions;
|
||||
CLI::GetParam<RandomForestModel>("output_model").rf.Classify(testData,
|
||||
CLI::GetParam<RandomForestModel*>("output_model")->rf.Classify(testData,
|
||||
predictions);
|
||||
bindings::tests::CleanMemory();
|
||||
|
||||
size_t correct = arma::accu(predictions == testLabels);
|
||||
double accuracy1 = (double(correct) / double(testLabels.n_elem) * 100);
|
||||
@@ -324,8 +330,9 @@ BOOST_AUTO_TEST_CASE(RandomForestDiffNumTreeTest)
|
||||
mlpackMain();
|
||||
|
||||
// Calculate training accuracy.
|
||||
CLI::GetParam<RandomForestModel>("output_model").rf.Classify(testData,
|
||||
CLI::GetParam<RandomForestModel*>("output_model")->rf.Classify(testData,
|
||||
predictions);
|
||||
bindings::tests::CleanMemory();
|
||||
|
||||
correct = arma::accu(predictions == testLabels);
|
||||
double accuracy5 = (double(correct) / double(testLabels.n_elem) * 100);
|
||||
@@ -340,7 +347,7 @@ BOOST_AUTO_TEST_CASE(RandomForestDiffNumTreeTest)
|
||||
mlpackMain();
|
||||
|
||||
// Calculate training accuracy.
|
||||
CLI::GetParam<RandomForestModel>("output_model").rf.Classify(testData,
|
||||
CLI::GetParam<RandomForestModel*>("output_model")->rf.Classify(testData,
|
||||
predictions);
|
||||
|
||||
correct = arma::accu(predictions == testLabels);
|
||||
|
||||
@@ -35,6 +35,7 @@ struct SoftmaxRegressionTestFixture
|
||||
~SoftmaxRegressionTestFixture()
|
||||
{
|
||||
// Clear the settings.
|
||||
bindings::tests::CleanMemory();
|
||||
CLI::ClearSettings();
|
||||
}
|
||||
};
|
||||
@@ -150,7 +151,7 @@ BOOST_AUTO_TEST_CASE(SoftmaxRegressionModelReuseTest)
|
||||
// Input trained model.
|
||||
SetInputParam("test", std::move(testData));
|
||||
SetInputParam("input_model",
|
||||
std::move(CLI::GetParam<SoftmaxRegression>("output_model")));
|
||||
CLI::GetParam<SoftmaxRegression*>("output_model"));
|
||||
|
||||
mlpackMain();
|
||||
|
||||
@@ -273,7 +274,7 @@ BOOST_AUTO_TEST_CASE(SoftmaxRegressionTrainingVerTest)
|
||||
|
||||
// Input pre-trained model.
|
||||
SetInputParam("input_model",
|
||||
std::move(CLI::GetParam<SoftmaxRegression>("output_model")));
|
||||
CLI::GetParam<SoftmaxRegression*>("output_model"));
|
||||
|
||||
Log::Fatal.ignoreInput = true;
|
||||
BOOST_REQUIRE_THROW(mlpackMain(), std::runtime_error);
|
||||
@@ -318,7 +319,9 @@ BOOST_AUTO_TEST_CASE(SoftmaxRegressionDiffLambdaTest)
|
||||
|
||||
// Store output parameters.
|
||||
arma::mat modelParam;
|
||||
modelParam = CLI::GetParam<SoftmaxRegression>("output_model").Parameters();
|
||||
modelParam = CLI::GetParam<SoftmaxRegression*>("output_model")->Parameters();
|
||||
|
||||
bindings::tests::CleanMemory();
|
||||
|
||||
// Reset passed parameters.
|
||||
CLI::GetSingleton().Parameters()["training"].wasPassed = false;
|
||||
@@ -340,13 +343,13 @@ BOOST_AUTO_TEST_CASE(SoftmaxRegressionDiffLambdaTest)
|
||||
for (size_t i = 0; i < modelParam.n_elem; ++i)
|
||||
{
|
||||
BOOST_REQUIRE_NE(modelParam[i],
|
||||
CLI::GetParam<SoftmaxRegression>("output_model").Parameters()[i]);
|
||||
CLI::GetParam<SoftmaxRegression*>("output_model")->Parameters()[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that output object parameters are different
|
||||
* for different numbers of max_iterations.
|
||||
* Check that output object parameters are different for different numbers of
|
||||
* max_iterations.
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE(SoftmaxRegressionDiffMaxItrTest)
|
||||
{
|
||||
@@ -382,7 +385,9 @@ BOOST_AUTO_TEST_CASE(SoftmaxRegressionDiffMaxItrTest)
|
||||
|
||||
// Store output parameters.
|
||||
arma::mat modelParam;
|
||||
modelParam = CLI::GetParam<SoftmaxRegression>("output_model").Parameters();
|
||||
modelParam = CLI::GetParam<SoftmaxRegression*>("output_model")->Parameters();
|
||||
|
||||
bindings::tests::CleanMemory();
|
||||
|
||||
// Reset passed parameters.
|
||||
CLI::GetSingleton().Parameters()["training"].wasPassed = false;
|
||||
@@ -404,7 +409,7 @@ BOOST_AUTO_TEST_CASE(SoftmaxRegressionDiffMaxItrTest)
|
||||
for (size_t i = 0; i < modelParam.n_elem; ++i)
|
||||
{
|
||||
BOOST_REQUIRE_NE(modelParam[i],
|
||||
CLI::GetParam<SoftmaxRegression>("output_model").Parameters()[i]);
|
||||
CLI::GetParam<SoftmaxRegression*>("output_model")->Parameters()[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -446,7 +451,9 @@ BOOST_AUTO_TEST_CASE(SoftmaxRegressionDiffInterceptTest)
|
||||
|
||||
// Store output parameters.
|
||||
arma::mat modelParam;
|
||||
modelParam = CLI::GetParam<SoftmaxRegression>("output_model").Parameters();
|
||||
modelParam = CLI::GetParam<SoftmaxRegression*>("output_model")->Parameters();
|
||||
|
||||
bindings::tests::CleanMemory();
|
||||
|
||||
// Reset passed parameters.
|
||||
CLI::GetSingleton().Parameters()["training"].wasPassed = false;
|
||||
@@ -466,7 +473,7 @@ BOOST_AUTO_TEST_CASE(SoftmaxRegressionDiffInterceptTest)
|
||||
// Check that initial parameters has 1 more parameter than
|
||||
// final parameters matrix.
|
||||
BOOST_REQUIRE_EQUAL(
|
||||
CLI::GetParam<SoftmaxRegression>("output_model").Parameters().n_cols,
|
||||
CLI::GetParam<SoftmaxRegression*>("output_model")->Parameters().n_cols,
|
||||
modelParam.n_cols + 1);
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,10 @@
|
||||
* 3-clause BSD license along with mlpack. If not, see
|
||||
* http://www.opensource.org/licenses/BSD-3-Clause for more information.
|
||||
*/
|
||||
#ifndef MLPACK_TESTS_MAIN_TESTS_TEST_HELPER_HPP
|
||||
#define MLPACK_TESTS_MAIN_TESTS_TEST_HELPER_HPP
|
||||
|
||||
#include <mlpack/prereqs.hpp>
|
||||
|
||||
namespace mlpack {
|
||||
namespace util {
|
||||
@@ -31,3 +35,5 @@ void SetInputParam(const std::string& name, T&& value)
|
||||
|
||||
} // namespace util
|
||||
} // namespace mlpack
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user