Merge branch 'master' into mean_backward

This commit is contained in:
abh2k
2021-06-06 15:19:11 +05:30
committed by GitHub
62 changed files with 864 additions and 353 deletions
-2
View File
@@ -15,8 +15,6 @@ option(TEST_VERBOSE "Run test cases with verbose output." OFF)
option(BUILD_TESTS "Build tests." ON)
option(BUILD_CLI_EXECUTABLES "Build command-line executables." ON)
option(DISABLE_DOWNLOADS "Disable downloads of dependencies during build." OFF)
option(DOWNLOAD_ENSMALLEN "If ensmallen is not found, download it." ON)
option(DOWNLOAD_STB_IMAGE "Download stb_image for image loading." ON)
option(BUILD_GO_SHLIB "Build Go shared library." OFF)
option(BUILD_DOCS "Build doxygen documentation (if doxygen is available)." ON)
+5
View File
@@ -1,5 +1,7 @@
### mlpack ?.?.?
###### ????-??-??
* Added dict-style inspection of mlpack models in python bindings (#2868).
* Added Extra Trees Algorithm (#2883). Currently, it can be used using the
class `mlpack::tree::ExtraTrees`, but only through C++.
@@ -54,6 +56,9 @@
* The `mlpack_test` target is no longer built as part of `make all`. Use
`make mlpack_test` to build the tests.
* Fixes to `HoeffdingTree`: ensure that training still works when empty
constructor is used (#2964).
### mlpack 3.4.2
###### 2020-10-26
* Added Mean Absolute Percentage Error.
-2
View File
@@ -219,10 +219,8 @@ Options are specified with the -D flag. The allowed options include:
BUILD_SHARED_LIBS=(ON/OFF): compile shared libraries and executables as
opposed to static libraries
DISABLE_DOWNLOADS=(ON/OFF): whether to disable all downloads during build
DOWNLOAD_ENSMALLEN=(ON/OFF): If ensmallen is not found, download it
ENSMALLEN_INCLUDE_DIR=(/path/to/ensmallen/include): path to include directory
for ensmallen
DOWNLOAD_STB_IMAGE=(ON/OFF): If STB is not found, download it
STB_IMAGE_INCLUDE_DIR=(/path/to/stb/include): path to include directory for
STB image library
USE_OPENMP=(ON/OFF): whether or not to use OpenMP if available
-3
View File
@@ -193,9 +193,6 @@ The full list of options mlpack allows:
(default OFF)
- DISABLE_DOWNLOADS=(ON/OFF): Disable downloads of dependencies during build
(default OFF)
- DOWNLOAD_ENSMALLEN=(ON/OFF): If ensmallen is not found, download it
(default ON)
- DOWNLOAD_STB_IMAGE=(ON/OFF): If STB is not found, download it (default ON)
- PYTHON_EXECUTABLE=(/path/to/python_version): Path to specific Python executable
- PYTHON_INSTALL_PREFIX=(/path/to/python/): Path to root of Python installation
- JULIA_EXECUTABLE=(/path/to/julia): Path to specific Julia executable
@@ -132,6 +132,7 @@ set(CYTHON_SOURCES
mlpack/matrix_utils.py
mlpack/serialization.hpp
mlpack/serialization.pxd
mlpack/preprocess_json_params.py
)
set(TEST_SOURCES
@@ -202,6 +203,7 @@ add_custom_command(TARGET python POST_BUILD
mlpack/io.pxd
mlpack/io_util.hpp
mlpack/matrix_utils.py
mlpack/preprocess_json_params.py
mlpack
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/src/mlpack/bindings/python/)
@@ -0,0 +1,281 @@
#!/usr/bin/env python
"""
preprocess_json_params.py: utility functions for json paramter preprocessing
(see set_cpp_param() and get_cpp_param() methods
in print_class_defn.hpp)
The "process_params_out" and "process_params_in" utilities are used to handle
interconversion between the output json from cereal and python dictionary.
mlpack is free software; you may redistribute it and/or modify it under the
terms of the 3-clause BSD license. You should have received a copy of the
3-clause BSD license along with mlpack. If not, see
http://www.opensource.org/licenses/BSD-3-Clause for more information.
"""
import numpy as np
import json
import pprint
from copy import deepcopy
from collections import OrderedDict
def process_params_out(model, params, return_str=False):
'''
This method processes the parameters obtained from the model.
params:
1) model - the model to process params.
2) params - json parameters of the model (which we get through cereal).
3) return_str (bool) - if True then a pretty string version of the
params is returned.
'''
# for pretty printing.
pp = pprint.PrettyPrinter()
# value_resolver defined later.
params_dic = json.loads(params, object_pairs_hook=value_resolver)
# remove "cereal_class_version".
# this stores the cereal_class_version value for all deleted pairs.
cereal_class_version = []
ref_path = []
# 'full_paths' will store the complete path in the dictionary for all
# occurrences. This will be used during the reversed process, to insert
# 'cereal_class_version' at the correct places to avoid any errors.
full_paths = []
scrub(params_dic, "cereal_class_version", cereal_class_version, full_paths,
ref_path)
# storing 'cereal_class_version' occurrences paths and values.
model.scrubbed_params["cereal_class_version"] = {
"values": cereal_class_version,
"full_paths": full_paths,
}
# convert armadillo dictionary to numpy array.
arma_to_np(params_dic)
if return_str:
return params_dic, pp.pformat(params_dic)
else:
return params_dic
def process_params_in(model, params_dic):
"""
This function takes in a model and the parameters dictionary,
and returns a string that can be ingested back into the model.
"""
# deepcopy to prevent changes to the user dictionary.
params_dic_copy = deepcopy(params_dic)
# convert numpy to armadillo.
np_to_arma(params_dic_copy)
# inserting scrubbed parameters back into dictionary.
for param_name, details in model.scrubbed_params.items():
for val, path in zip(details["values"], details["full_paths"]):
insert_in_dic(params_dic_copy, path, param_name, val)
# dumping to string. restore_value defined later.
params_str = json.dumps(params_dic_copy, cls=restore_value)
return params_str
def np_to_arma(obj):
"""
This function replaces a numpy array to json representation
of armadillo vector. This is reverse of "arma_to_np(obj)".
"""
if isinstance(obj, OrderedDict):
for key in obj.keys():
"""
Checking if this is a numpy array.
"""
if isinstance(obj[key], np.ndarray):
# n_rows, n_cols have to be strings.
n_rows, n_cols = obj[key].shape
dic = OrderedDict()
dic["n_rows"] = str(n_cols) # implicit transpose
dic["n_cols"] = str(n_rows) # implicit transpose
if n_cols != 1 and n_rows != 1:
dic["vec_state"] = "0"
elif n_rows == 1:
dic["vec_state"] = "1"
elif n_cols == 1:
dic["vec_state"] = "2"
elems = obj[key].flatten()
dic["elem"] = list(elems)
obj[key] = dic
else:
np_to_arma(obj[key])
elif isinstance(obj, list):
for i in range(len(obj)):
np_to_arma(obj[i])
else:
# we cannot recurse further if we do not have a
# dictionary or list object, so just pass.
pass
def arma_to_np(obj):
"""
This function replaces the JSON representation of armadillo vector to
numpy array in the given dictionary.
"""
if isinstance(obj, OrderedDict):
for key in obj.keys():
if isinstance(obj[key], OrderedDict):
# if "vec_state" is present in dictionary, then
# it must be armadillo vector.
if "vec_state" in obj[key].keys():
n_rows = int(obj[key]["n_rows"])
n_cols = int(obj[key]["n_cols"])
# implicit transpose
obj[key] = np.array(obj[key]["elem"])\
.reshape(n_cols, n_rows).astype(type(obj[key]["elem"][0]))
else:
arma_to_np(obj[key])
else:
arma_to_np(obj[key])
elif isinstance(obj, list):
for i in range(len(obj)):
arma_to_np(obj[i])
else:
# we cannot recurse further if we do not have a
# dictionary or list object, so just pass.
pass
def scrub(obj, bad_key, values, full_paths, ref_path):
"""
This function removes a certain key-value pair from the
given dictionary.
params:
1) obj (dict) - dictionary to traverse.
2) bad_key (str) - key to remove.
3) values (list) - list of values of all occurrences of bad_key
(this will be used to insert bad_key back into dictionary).
4) full_paths (list) - this is a list that contains full path to all
occurrences of bad_key (used to insert bad_key back
into dictionary).
5) ref_path (list) - this for keeping track of the current path in the
dictionary.
"""
if isinstance(obj, OrderedDict):
for key in list(obj.keys()):
ref_path.append(key)
if key == bad_key:
ref_path.pop()
ref_path_copy = deepcopy(ref_path)
full_paths.append(ref_path_copy)
values.append(obj[key])
del obj[key]
else:
scrub(obj[key], bad_key, values, full_paths, ref_path)
if ref_path != []:
ref_path.pop()
elif isinstance(obj, list):
for i in range(len(obj)):
ref_path.append(f"listidx_{i}")
scrub(obj[i], bad_key, values, full_paths, ref_path)
if ref_path != []:
ref_path.pop()
else:
ref_path.pop()
pass
def value_resolver(pairs):
'''
This function converts multiple "elem" occurences to a list when
used with json.loads().
Eg:
str({
vec_state: 1,
n_rows: 2,
n_cols: 1,
elem: 1,
elem: 2
})
will be converted to
dict({
vec_state: 1,
n_rows: 2,
n_cols: 1,
elem: [1,2]
})
This is done to handle same keys in the json while converting to python
dictionary.
'''
has_elem = False
for key,val in pairs:
if key == "elem":
has_elem = True
break
if has_elem:
val_list = [val for (key,val) in pairs if key == "elem"]
pairs = [(key,val) for (key,val) in pairs if key != "elem"]
pairs.append(("elem", val_list))
return OrderedDict(pairs)
class restore_value(json.JSONEncoder):
'''
This is a custom encoder that converts a dictionary to
correct json format for ingesting in cereal.
Eg:
dict({
vec_state: 1,
n_rows: 2,
n_cols: 1,
elem: [1,2]
})
will be converted into
str({
vec_state: 1,
n_rows: 2,
n_cols: 1,
elem: 1,
elem: 2
})
while encoding.
This is used to create a json that can be ingested to cereal.
'''
def encode(self, o):
if isinstance(o, dict):
if "elem" in o.keys():
to_return = '{%s' % ', '.join(
': '.join((json.encoder.py_encode_basestring(k), self.encode(v)))\
for k, v in o.items() if k != "elem")
for val in o["elem"]:
to_return += ', ' + json.encoder.py_encode_basestring("elem") +\
f': {val}'
to_return += "}"
return to_return
else:
to_return = '{%s}' % ', '.join(
': '.join((json.encoder.py_encode_basestring(k), self.encode(v)))\
for k, v in o.items())
return to_return
if isinstance(o, list):
to_return = '[%s]' % ', '.join((self.encode(k) for k in o))
return to_return
return super().encode(o)
def insert_in_dic(dic, path, key, val):
'''
This function inserts a particluar key-value pair in a dictionray
after following a particular path.
'''
temp = dic[path[0]]
for idx in range(1, len(path)):
if "listidx_" in path[idx]:
temp = temp[int(path[idx].replace("listidx_", ""))]
else:
temp = temp[path[idx]]
temp[key] = val
# moving key-value pair to the start.
temp.move_to_end(key, last=False)
@@ -38,6 +38,26 @@ void SerializeIn(T* t, const std::string& str, const std::string& name)
b(cereal::make_nvp(name.c_str(), *t));
}
template<typename T>
std::string SerializeOutJSON(T* t, const std::string& name)
{
std::ostringstream oss;
{
cereal::JSONOutputArchive b(oss);
b(cereal::make_nvp(name.c_str(), *t));
}
return oss.str();
}
template<typename T>
void SerializeInJSON(T* t, const std::string& str, const std::string& name)
{
std::istringstream iss(str);
cereal::JSONInputArchive b(iss);
b(cereal::make_nvp(name.c_str(), *t));
}
} // namespace python
} // namespace bindings
} // namespace mlpack
@@ -12,3 +12,6 @@ from libcpp.string cimport string
cdef extern from "serialization.hpp" namespace "mlpack::bindings::python" nogil:
string SerializeOut[T](T* t, string name) nogil
void SerializeIn[T](T* t, string str, string name) nogil
string SerializeOutJSON[T](T* t, string name) nogil
void SerializeInJSON[T](T* t, string str, string name) nogil
@@ -62,10 +62,12 @@ void PrintClassDefn(
* @code
* cdef class <ModelType>Type:
* cdef <ModelType>* modelptr
*
* cdef public dict scrubbed_params
*
* def __cinit__(self):
* self.modelptr = new <ModelType>()
*
* self.scrubbed_params = dict()
*
* def __dealloc__(self):
* del self.modelptr
*
@@ -77,13 +79,30 @@ void PrintClassDefn(
*
* def __reduce_ex__(self):
* return (self.__class__, (), self.__getstate__())
*
* def _get_cpp_params(self):
* return SerializeOutJSON(self.modelptr, "<ModelType>")
*
* def _set_cpp_params(self, state):
* SerializeInJSON(self.modelptr, state, "<ModelType>")
*
* def get_cpp_params(self, return_str=False):
* params = self._get_cpp_params()
* return process_params_out(self, params, return_str=return_str)
*
* def set_cpp_params(self, params_dic):
* params_str = process_params_in(self, params_dic)
* self._set_cpp_params(params_str)
*
* @endcode
*/
std::cout << "cdef class " << strippedType << "Type:" << std::endl;
std::cout << " cdef " << printedType << "* modelptr" << std::endl;
std::cout << " cdef public dict scrubbed_params" << std::endl;
std::cout << std::endl;
std::cout << " def __cinit__(self):" << std::endl;
std::cout << " self.modelptr = new " << printedType << "()" << std::endl;
std::cout << " self.scrubbed_params = dict()" << std::endl;
std::cout << std::endl;
std::cout << " def __dealloc__(self):" << std::endl;
std::cout << " del self.modelptr" << std::endl;
@@ -100,6 +119,22 @@ void PrintClassDefn(
std::cout << " return (self.__class__, (), self.__getstate__())"
<< std::endl;
std::cout << std::endl;
std::cout << " def _get_cpp_params(self):" << std::endl;
std::cout << " return SerializeOutJSON(self.modelptr, \"" << printedType
<< "\")" << std::endl;
std::cout << std::endl;
std::cout << " def _set_cpp_params(self, state):" << std::endl;
std::cout << " SerializeInJSON(self.modelptr, state, \"" << printedType
<< "\")" << std::endl;
std::cout << std::endl;
std::cout << " def get_cpp_params(self, return_str=False):" << std::endl;
std::cout << " params = self._get_cpp_params()" << std::endl;
std::cout << " return process_params_out(self, params, return_str=return_str)" << std::endl;
std::cout << std::endl;
std::cout << " def set_cpp_params(self, params_dic):" << std::endl;
std::cout << " params_str = process_params_in(self, params_dic)" << std::endl;
std::cout << " self._set_cpp_params(params_str.encode(\"utf-8\"))" << std::endl;
std::cout << std::endl;
}
/**
+4 -2
View File
@@ -80,7 +80,8 @@ void PrintPYX(const util::BindingDetails& doc,
cout << "from io cimport EnableVerbose, DisableVerbose, DisableBacktrace, "
<< "ResetTimers, EnableTimers" << endl;
cout << "from matrix_utils import to_matrix, to_matrix_with_info" << endl;
cout << "from serialization cimport SerializeIn, SerializeOut" << endl;
cout << "from preprocess_json_params import process_params_out, process_params_in" << endl;
cout << "from serialization cimport SerializeIn, SerializeOut, SerializeOutJSON, SerializeInJSON" << endl;
cout << endl;
cout << "import numpy as np" << endl;
cout << "cimport numpy as np" << endl;
@@ -230,7 +231,8 @@ void PrintPYX(const util::BindingDetails& doc,
<< "\'bool'!\")" << endl;
cout << endl;
// Before calling mlpackMain(), we check input matrices for NaN values if needed.
// Before calling mlpackMain(), we check input matrices for NaN values if
// needed.
cout << " if check_input_matrices:" << endl;
cout << " IO.CheckInputMatrices()" << endl;
@@ -155,9 +155,13 @@ std::string PrintTypeDoc(
{
return "An mlpack model pointer. This type can be pickled to or from disk, "
"and internally holds a pointer to C++ memory containing the mlpack "
"model. Note that this means that the mlpack model itself cannot be "
"easily inspected in Python; however, the pickled model can be loaded "
"in C++ and inspected there.";
"model. This model pointer has 2 methods with which the parameters "
"of the model can be inspected as well as changed through Python. "
"The `get_cpp_params()` method returns a python ordered dictionary that "
"contains all the parameters of the model. These parameters can "
"be inspected and changed. To set new parameters for a model, "
"pass the modified dictionary (without deleting any keys) to the "
"`set_cpp_params()` method.";
}
} // namespace python
+2 -2
View File
@@ -108,8 +108,8 @@ void CVBase<MLAlgorithm,
WeightsType>::AssertDataConsistency(const MatType& xs,
const PredictionsType& ys)
{
util::CheckSameSizes(xs, (size_t) ys.n_cols, "CVBase::AssertDataConsistency()",
"predictions");
util::CheckSameSizes(xs, (size_t) ys.n_cols,
"CVBase::AssertDataConsistency()", "predictions");
}
template<typename MLAlgorithm,
+2 -2
View File
@@ -230,8 +230,8 @@ 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.", "");
PARAM_FLAG("check_input_matrices", "If specified, the input matrix is checked for"
" NaN and inf values; an exception is thrown if any are found.", "");
PARAM_FLAG("check_input_matrices", "If specified, the input matrix is checked "
"for NaN and inf values; an exception is thrown if any are found.", "");
// Nothing else needs to be defined---the binding will use mlpackMain() as-is.
+2 -2
View File
@@ -37,8 +37,8 @@ inline void CheckSameSizes(const DataType& data,
{
std::ostringstream oss;
oss << callerDescription << ": number of points (" << data.n_cols << ") "
<< "does not match number of " << addInfo << " (" << label.n_elem << ")!"
<< std::endl;
<< "does not match number of " << addInfo << " (" << label.n_elem
<< ")!" << std::endl;
throw std::invalid_argument(oss.str());
}
}
@@ -40,7 +40,7 @@ class SimpleResidueTermination
* @param maxIterations Maximum number of iterations.
*/
SimpleResidueTermination(const double minResidue = 1e-5,
const size_t maxIterations = 10000) :
const size_t maxIterations = 10000) :
minResidue(minResidue),
maxIterations(maxIterations),
residue(0.0),
@@ -2,13 +2,15 @@
* @file methods/ann/activation_functions/silu_function.hpp
* @author Fawwaz Mayda
*
* Definition and implementation of the Sigmoid Weighted Linear Unit function (SILU).
* Definition and implementation of the Sigmoid Weighted Linear Unit function
* (SILU).
*
* For more information see the following paper
*
* @code
* @misc{elfwing2017sigmoidweighted ,
* title = {Sigmoid-Weighted Linear Units for Neural Network Function Approximation in Reinforcement Learning},
* title = {Sigmoid-Weighted Linear Units for Neural Network Function
* Approximation in Reinforcement Learning},
* author = {Stefan Elfwing and Eiji Uchibe and Kenji Doya},
* year = {2017},
* url = {https://arxiv.org/pdf/1702.03118.pdf},
@@ -38,7 +40,7 @@ namespace ann /* Artificial Neural Network */ {
* f'(x) &=& \frac{1}{1 + e^{-x}} * (1 + x * (1-\frac{1}{1 + e^{-x}}))\\
* @f}
*/
class SILUFunction
class SILUFunction
{
public:
/**
@@ -47,11 +49,11 @@ class SILUFunction
* @param x Input data.
* @return f(x).
*/
static double Fn(const double x)
static double Fn(const double x)
{
return x / (1.0 + std::exp(-x));
}
/**
* Computes the SILU function.
*
@@ -59,9 +61,9 @@ class SILUFunction
* @param y The resulting output activation.
*/
template<typename InputVecType, typename OutputVecType>
static void Fn(const InputVecType &x, OutputVecType &y)
static void Fn(const InputVecType &x, OutputVecType &y)
{
y = x / (1.0 + arma::exp(-x));
y = x / (1.0 + arma::exp(-x));
}
/**
@@ -70,10 +72,10 @@ class SILUFunction
* @param y Input activation.
* @return f'(x)
*/
static double Deriv(const double x)
static double Deriv(const double x)
{
double sigmoid = 1.0 / (1.0 + std::exp(-x));
return sigmoid * (1.0 + x * (1.0 - sigmoid));
double sigmoid = 1.0 / (1.0 + std::exp(-x));
return sigmoid * (1.0 + x * (1.0 - sigmoid));
}
/**
@@ -83,14 +85,14 @@ class SILUFunction
* @param x The resulting derivatives.
*/
template<typename InputVecType, typename OutputVecType>
static void Deriv(const InputVecType &x, OutputVecType &y)
static void Deriv(const InputVecType &x, OutputVecType &y)
{
OutputVecType sigmoid = 1.0 / (1.0 + arma::exp(-x));
y = sigmoid % (1.0 + x % (1.0 - sigmoid));
OutputVecType sigmoid = 1.0 / (1.0 + arma::exp(-x));
y = sigmoid % (1.0 + x % (1.0 - sigmoid));
}
}; // class SILUFunction
} // namespace ann
} // namespace mlpack
#endif
#endif
@@ -8,7 +8,8 @@
*
* @code
* @misc{The Institution of Engineering and Technology 2015 ,
* title = {TanhExp: A Smooth Activation Function with High Convergence Speed for Lightweight Neural Networks},
* title = {TanhExp: A Smooth Activation Function with High Convergence Speed
* for Lightweight Neural Networks},
* author = {Xinyu Liu and Xiaoguang Di},
* year = {2020},
* url = {https://arxiv.org/pdf/2003.09855v2.pdf},
@@ -38,7 +39,7 @@ namespace ann /** Artificial Neural Network. */ {
* f'(x) = tanh(e^x) - x*e^x*(tanh(e^x)^2 - 1)\\
* @f}
*/
class TanhExpFunction
class TanhExpFunction
{
public:
/**
+8 -10
View File
@@ -111,8 +111,8 @@ double FFN<OutputLayerType, InitializationRuleType, CustomLayers...>::Train(
OptimizerType& optimizer,
CallbackTypes&&... callbacks)
{
CheckInputShape<std::vector<LayerTypes<CustomLayers...> > >(network,
predictors.n_rows,
CheckInputShape<std::vector<LayerTypes<CustomLayers...> > >(network,
predictors.n_rows,
"FFN<>::Train()");
ResetData(std::move(predictors), std::move(responses));
@@ -137,8 +137,8 @@ double FFN<OutputLayerType, InitializationRuleType, CustomLayers...>::Train(
arma::mat responses,
CallbackTypes&&... callbacks)
{
CheckInputShape<std::vector<LayerTypes<CustomLayers...> > >(network,
predictors.n_rows,
CheckInputShape<std::vector<LayerTypes<CustomLayers...> > >(network,
predictors.n_rows,
"FFN<>::Train()");
ResetData(std::move(predictors), std::move(responses));
@@ -227,9 +227,8 @@ template<typename OutputLayerType, typename InitializationRuleType,
void FFN<OutputLayerType, InitializationRuleType, CustomLayers...>::Predict(
arma::mat predictors, arma::mat& results)
{
CheckInputShape<std::vector<LayerTypes<CustomLayers...> > >(network,
predictors.n_rows,
"FFN<>::Predict()");
CheckInputShape<std::vector<LayerTypes<CustomLayers...> > >(
network, predictors.n_rows, "FFN<>::Predict()");
if (parameter.is_empty())
ResetParameters();
@@ -264,9 +263,8 @@ template<typename PredictorsType, typename ResponsesType>
double FFN<OutputLayerType, InitializationRuleType, CustomLayers...>::Evaluate(
const PredictorsType& predictors, const ResponsesType& responses)
{
CheckInputShape<std::vector<LayerTypes<CustomLayers...> > >(network,
predictors.n_rows,
"FFN<>::Evaluate()");
CheckInputShape<std::vector<LayerTypes<CustomLayers...> > >(
network, predictors.n_rows, "FFN<>::Evaluate()");
if (parameter.is_empty())
ResetParameters();
@@ -71,7 +71,8 @@ class AtrousConvolution
* @param inputWidth The widht of the input data.
* @param inputHeight The height of the input data.
* @param dilationWidth The space between the cells of filters in x direction.
* @param dilationHeight The space between the cells of filters in y direction.
* @param dilationHeight The space between the cells of filters in y
* direction.
* @param paddingType The type of padding (Valid or Same). Defaults to None.
*/
AtrousConvolution(const size_t inSize,
@@ -108,7 +109,8 @@ class AtrousConvolution
* @param inputWidth The widht of the input data.
* @param inputHeight The height of the input data.
* @param dilationWidth The space between the cells of filters in x direction.
* @param dilationHeight The space between the cells of filters in y direction.
* @param dilationHeight The space between the cells of filters in y
* direction.
* @param paddingType The type of padding (Valid/Same/None). Defaults to None.
*/
AtrousConvolution(const size_t inSize,
@@ -266,8 +268,8 @@ class AtrousConvolution
//! Get the shape of the input.
size_t InputShape() const
{
return inputHeight * inputWidth * inSize;
}
return inputHeight * inputWidth * inSize;
}
/**
* Serialize the layer.
+2 -2
View File
@@ -29,7 +29,7 @@
#include <mlpack/methods/ann/activation_functions/gaussian_function.hpp>
#include <mlpack/methods/ann/activation_functions/hard_swish_function.hpp>
#include <mlpack/methods/ann/activation_functions/tanh_exponential_function.hpp>
#include <mlpack/methods/ann/activation_functions/silu_function.hpp>
#include <mlpack/methods/ann/activation_functions/silu_function.hpp>
namespace mlpack {
namespace ann /** Artificial Neural Network. */ {
@@ -314,7 +314,7 @@ template <
typename OutputDataType = arma::mat
>
using SILUFunctionLayer = BaseLayer<
ActivationFunction, InputDataType,OutputDataType
ActivationFunction, InputDataType, OutputDataType
>;
} // namespace ann
@@ -21,27 +21,28 @@ namespace ann /** Artificial Neural Network. */ {
template<typename InputDataType, typename OutputDataType>
Concatenate<InputDataType, OutputDataType>::Concatenate() :
inRows(0)
inRows(0)
{
// Nothing to do here.
}
template<typename InputDataType, typename OutputDataType>
Concatenate<InputDataType, OutputDataType>::Concatenate(const Concatenate& layer) :
inRows(layer.inRows),
weights(layer.weights),
delta(layer.delta),
concat(layer.concat)
Concatenate<InputDataType, OutputDataType>::Concatenate(
const Concatenate& layer) :
inRows(layer.inRows),
weights(layer.weights),
delta(layer.delta),
concat(layer.concat)
{
// Nothing to to here.
}
template<typename InputDataType, typename OutputDataType>
Concatenate<InputDataType, OutputDataType>::Concatenate(Concatenate&& layer) :
inRows(layer.inRows),
weights(std::move(layer.weights)),
delta(std::move(layer.delta)),
concat(std::move(layer.concat))
Concatenate<InputDataType, OutputDataType>::Concatenate(Concatenate&& layer) :
inRows(layer.inRows),
weights(std::move(layer.weights)),
delta(std::move(layer.delta)),
concat(std::move(layer.concat))
{
// Nothing to do here.
}
@@ -51,7 +52,7 @@ Concatenate<InputDataType, OutputDataType>&
Concatenate<InputDataType, OutputDataType>::
operator=(const Concatenate& layer)
{
if (this != &layer)
if (this != &layer)
{
inRows = layer.inRows;
weights = layer.weights;
@@ -67,7 +68,7 @@ Concatenate<InputDataType, OutputDataType>&
Concatenate<InputDataType, OutputDataType>::
operator=(Concatenate&& layer)
{
if (this != &layer)
if (this != &layer)
{
inRows = layer.inRows;
weights = std::move(layer.weights);
@@ -48,9 +48,9 @@ void FlattenTSwish<InputDataType, OutputDataType>::Backward(
const DataType& input, const DataType& gy, DataType& g)
{
DataType derivate, sigmoid;
LogisticFunction::Fn(input,sigmoid);
LogisticFunction::Fn(input, sigmoid);
derivate.set_size(arma::size(input));
for(size_t i = 0; i < input.n_elem; ++i)
for (size_t i = 0; i < input.n_elem; ++i)
{
if (input(i) >= 0)
{
@@ -58,9 +58,11 @@ void FlattenTSwish<InputDataType, OutputDataType>::Backward(
// We don't put '+ t' here because this is a derivate.
derivate(i) = input(i) * sigmoid(i);
derivate(i) = sigmoid(i) * (1.0 - derivate(i)) + derivate(i);
}
else
}
else
{
derivate(i) = 0;
}
}
g = gy % derivate;
}
@@ -77,4 +79,4 @@ void FlattenTSwish<InputDataType, OutputDataType>::serialize(
} // namespace ann
} // namespace mlpack
#endif
#endif
+1 -1
View File
@@ -156,7 +156,7 @@ class GRU
size_t OutSize() const { return outSize; }
//! Get the shape of the input.
size_t InputShape() const
size_t InputShape() const
{
return inSize;
}
-1
View File
@@ -126,7 +126,6 @@ class ISRLU
//! ISRLU Hyperparameter (alpha > 0).
double alpha;
}; // class ISRLU
} // namespace ann
+1 -1
View File
@@ -152,7 +152,7 @@ class Linear
return (inSize * outSize) + outSize;
}
//! Get the shape of the input.
//! Get the shape of the input.
size_t InputShape() const
{
return inSize;
+6 -4
View File
@@ -196,11 +196,12 @@ class LpPooling
const arma::Mat<eT>& error,
arma::Mat<eT>& output)
{
arma::Mat<eT> unpooledError;
for (size_t j = 0, colidx = 0; j < input.n_cols; j += strideHeight, colidx++)
for (size_t j = 0, colidx = 0; j < input.n_cols; j += strideHeight,
colidx++)
{
for (size_t i = 0, rowidx = 0; i < input.n_rows; i += strideWidth, rowidx++)
for (size_t i = 0, rowidx = 0; i < input.n_rows; i += strideWidth,
rowidx++)
{
size_t rowEnd = i + kernelWidth - 1;
size_t colEnd = j + kernelHeight - 1;
@@ -219,7 +220,8 @@ class LpPooling
colEnd = input.n_cols - 1;
}
arma::mat InputArea = input(arma::span(i, rowEnd), arma::span(j, colEnd));
arma::mat InputArea = input(arma::span(i, rowEnd),
arma::span(j, colEnd));
size_t sum = pow(arma::accu(arma::pow(InputArea, normType)),
(normType - 1) / normType);
+4 -1
View File
@@ -184,7 +184,10 @@ class LSTM
size_t OutSize() const { return outSize; }
//! Get the size of the weights.
size_t WeightSize() const { return (4 * outSize * inSize + 7 * outSize + 4 * outSize * outSize); }
size_t WeightSize() const
{
return (4 * outSize * inSize + 7 * outSize + 4 * outSize * outSize);
}
//! Get the shape of the input.
size_t InputShape() const
+6 -6
View File
@@ -26,7 +26,7 @@ LSTM<InputDataType, OutputDataType>::LSTM()
template<typename InputDataType, typename OutputDataType>
LSTM<InputDataType, OutputDataType>::LSTM(
const LSTM& layer) :
const LSTM& layer) :
inSize(layer.inSize),
outSize(layer.outSize),
rho(layer.rho),
@@ -45,7 +45,7 @@ LSTM<InputDataType, OutputDataType>::LSTM(
template<typename InputDataType, typename OutputDataType>
LSTM<InputDataType, OutputDataType>::LSTM(
LSTM&& layer) :
LSTM&& layer) :
inSize(std::move(layer.inSize)),
outSize(std::move(layer.outSize)),
rho(std::move(layer.rho)),
@@ -63,7 +63,7 @@ LSTM<InputDataType, OutputDataType>::LSTM(
}
template <typename InputDataType, typename OutputDataType>
LSTM<InputDataType, OutputDataType>&
LSTM<InputDataType, OutputDataType>&
LSTM<InputDataType, OutputDataType> :: operator=(const LSTM& layer)
{
if (this != &layer)
@@ -82,11 +82,11 @@ LSTM<InputDataType, OutputDataType> :: operator=(const LSTM& layer)
rhoSize = layer.rho;
bpttSteps = layer.bpttSteps;
}
return *this;
return *this;
}
template <typename InputDataType, typename OutputDataType>
LSTM<InputDataType, OutputDataType>&
LSTM<InputDataType, OutputDataType>&
LSTM<InputDataType, OutputDataType> :: operator=(LSTM&& layer)
{
if (this != &layer)
@@ -105,7 +105,7 @@ LSTM<InputDataType, OutputDataType> :: operator=(LSTM&& layer)
rhoSize = std::move(layer.rho);
bpttSteps = std::move(layer.bpttSteps);
}
return *this;
return *this;
}
template <typename InputDataType, typename OutputDataType>
+20 -5
View File
@@ -160,12 +160,21 @@ class MeanPooling
template<typename eT>
void Pooling(const arma::Mat<eT>& input, arma::Mat<eT>& output)
{
arma::Mat<eT> inputPre = input;
for (size_t i = 1; i < input.n_cols; ++i)
inputPre.col(i) += inputPre.col(i - 1);
for (size_t i = 1; i < input.n_rows; ++i)
inputPre.row(i) += inputPre.row(i - 1);
for (size_t j = 0, colidx = 0; j < output.n_cols;
++j, colidx += strideHeight)
{
for (size_t i = 0, rowidx = 0; i < output.n_rows;
++i, rowidx += strideWidth)
{
double val = 0.0;
size_t rowEnd = rowidx + kernelWidth - 1;
size_t colEnd = colidx + kernelHeight - 1;
@@ -174,11 +183,18 @@ class MeanPooling
if (colEnd > input.n_cols - 1)
colEnd = input.n_cols - 1;
arma::mat subInput = input(
arma::span(rowidx, rowEnd),
arma::span(colidx, colEnd));
const size_t kernalArea = (rowEnd - rowidx + 1) * (colEnd - colidx + 1);
val += inputPre(rowEnd, colEnd);
if (rowidx >= 1)
{
if (colidx >= 1)
val += inputPre(rowidx - 1, colidx - 1);
val -= inputPre(rowidx - 1, colEnd);
}
if (colidx >= 1)
val -= inputPre(rowEnd, colidx - 1);
output(i, j) = arma::mean(arma::mean(subInput));
output(i, j) = val / kernalArea;
}
}
}
@@ -194,7 +210,6 @@ class MeanPooling
const arma::Mat<eT>& error,
arma::Mat<eT>& output)
{
const size_t condition = kernelHeight * kernelWidth - strideHeight * strideWidth -
kernelWidth - kernelHeight;
@@ -77,12 +77,11 @@ void PixelShuffle<InputDataType, OutputDataType>::Forward(
size_t width_index = w / upscaleFactor;
size_t channel_index = (upscaleFactor * (h % upscaleFactor)) +
(w % upscaleFactor) + (c * std::pow(upscaleFactor, 2));
outputTemp(w, h, c + n * sizeOut) = inputTemp(width_index, height_index,
channel_index + n * size);
outputTemp(w, h, c + n * sizeOut) = inputTemp(width_index,
height_index, channel_index + n * size);
}
}
}
}
}
@@ -109,12 +108,11 @@ void PixelShuffle<InputDataType, OutputDataType>::Backward(
size_t width_index = w / upscaleFactor;
size_t channel_index = (upscaleFactor * (h % upscaleFactor)) +
(w % upscaleFactor) + (c * std::pow(upscaleFactor, 2));
gTemp(width_index, height_index, channel_index + n * size) = gyTemp(w, h,
c + n * sizeOut);
gTemp(width_index, height_index, channel_index + n * size) =
gyTemp(w, h, c + n * sizeOut);
}
}
}
}
}
+16 -13
View File
@@ -128,9 +128,12 @@ Recurrent<InputDataType, OutputDataType, CustomLayers...>::Recurrent(
template<typename InputDataType, typename OutputDataType,
typename... CustomLayers>
size_t Recurrent<InputDataType, OutputDataType, CustomLayers...>::InputShape() const
size_t
Recurrent<InputDataType, OutputDataType, CustomLayers...>::InputShape() const
{
const size_t inputShapeStartModule = boost::apply_visitor(InShapeVisitor(), startModule);
const size_t inputShapeStartModule = boost::apply_visitor(InShapeVisitor(),
startModule);
// Return the input shape of the first module that we have.
if (inputShapeStartModule != 0)
{
@@ -140,34 +143,34 @@ size_t Recurrent<InputDataType, OutputDataType, CustomLayers...>::InputShape() c
else
{
// Return input shape of the second module that we have.
const size_t inputShapeInputModule = boost::apply_visitor(InShapeVisitor(), inputModule);
const size_t inputShapeInputModule = boost::apply_visitor(InShapeVisitor(),
inputModule);
if (inputShapeInputModule != 0)
{
return inputShapeInputModule;
// If the input shape of second module is 0.
}
else
else // If the input shape of second module is 0.
{
// Return input shape of the third module that we have.
const size_t inputShapeFeedbackModule = boost::apply_visitor(InShapeVisitor(),
feedbackModule);
const size_t inputShapeFeedbackModule = boost::apply_visitor(
InShapeVisitor(), feedbackModule);
if (inputShapeFeedbackModule != 0)
{
return inputShapeFeedbackModule;
// If the input shape of the third module is 0.
}
else
else // If the input shape of the third module is 0.
{
// Return the shape of the fourth module that we have.
const size_t inputShapeTransferModule = boost::apply_visitor(InShapeVisitor(),
transferModule);
const size_t inputShapeTransferModule = boost::apply_visitor(
InShapeVisitor(), transferModule);
if (inputShapeTransferModule != 0)
{
return inputShapeTransferModule;
}
// If the input shape of the fourth module is 0.
else
else // If the input shape of the fourth module is 0.
{
return 0;
}
}
}
}
@@ -71,16 +71,16 @@ class Reparametrization
const bool stochastic = true,
const bool includeKl = true,
const double beta = 1);
//! Copy Constructor.
Reparametrization(const Reparametrization& layer);
//! Move Constructor.
Reparametrization(Reparametrization&& layer);
//! Copy assignment operator.
Reparametrization& operator=(const Reparametrization& layer);
//! Move assignment operator.
Reparametrization& operator=(Reparametrization&& layer);
@@ -46,7 +46,7 @@ Reparametrization<InputDataType, OutputDataType>::Reparametrization(
<< "included." << std::endl;
}
}
template <typename InputDataType, typename OutputDataType>
Reparametrization<InputDataType, OutputDataType>::Reparametrization(
const Reparametrization& layer) :
@@ -55,7 +55,7 @@ Reparametrization<InputDataType, OutputDataType>::Reparametrization(
includeKl(layer.includeKl),
beta(layer.beta)
{
// Nothing to do here.
// Nothing to do here.
}
template <typename InputDataType, typename OutputDataType>
@@ -66,13 +66,13 @@ Reparametrization<InputDataType, OutputDataType>::Reparametrization(
includeKl(std::move(layer.includeKl)),
beta(std::move(layer.beta))
{
// Nothing to do here.
// Nothing to do here.
}
template <typename InputDataType, typename OutputDataType>
Reparametrization<InputDataType, OutputDataType>&
Reparametrization<InputDataType, OutputDataType>::
operator=(const Reparametrization& layer)
operator=(const Reparametrization& layer)
{
if (this != &layer)
{
@@ -83,11 +83,11 @@ operator=(const Reparametrization& layer)
}
return *this;
}
template <typename InputDataType, typename OutputDataType>
Reparametrization<InputDataType, OutputDataType>&
Reparametrization<InputDataType, OutputDataType>::
operator=(Reparametrization&& layer)
operator=(Reparametrization&& layer)
{
if (this != &layer)
{
@@ -98,8 +98,8 @@ operator=(Reparametrization&& layer)
}
return *this;
}
template<typename InputDataType, typename OutputDataType>
template<typename eT>
void Reparametrization<InputDataType, OutputDataType>::Forward(
@@ -34,7 +34,7 @@ BCELoss<InputDataType, OutputDataType>::Forward(
{
typedef typename PredictionType::elem_type ElemType;
ElemType loss = -arma::accu(target % arma::log(prediction + eps) +
ElemType loss = -arma::accu(target % arma::log(prediction + eps) +
(1. - target) % arma::log(1. - prediction + eps));
if (reduction)
loss /= prediction.n_elem;
@@ -31,16 +31,17 @@ HuberLoss<InputDataType, OutputDataType>::HuberLoss(
template<typename InputDataType, typename OutputDataType>
template<typename PredictionType, typename TargetType>
typename PredictionType::elem_type
HuberLoss<InputDataType, OutputDataType>::Forward(const PredictionType& prediction,
const TargetType& target)
HuberLoss<InputDataType, OutputDataType>::Forward(
const PredictionType& prediction,
const TargetType& target)
{
typedef typename PredictionType::elem_type ElemType;
ElemType loss = 0;
for (size_t i = 0; i < prediction.n_elem; ++i)
{
const ElemType absError = std::abs(target[i] - prediction[i]);
loss += absError > delta
? delta * (absError - 0.5 * delta) : 0.5 * std::pow(absError, 2);
loss += absError > delta ?
delta * (absError - 0.5 * delta) : 0.5 * std::pow(absError, 2);
}
return mean ? loss / prediction.n_elem : loss;
}
@@ -58,8 +59,9 @@ void HuberLoss<InputDataType, OutputDataType>::Backward(
for (size_t i = 0; i < loss.n_elem; ++i)
{
const ElemType absError = std::abs(target[i] - prediction[i]);
loss[i] = absError > delta
? - delta * (target[i] - prediction[i]) / absError : prediction[i] - target[i];
loss[i] = absError > delta ?
-delta * (target[i] - prediction[i]) / absError :
prediction[i] - target[i];
if (mean)
loss[i] /= loss.n_elem;
}
@@ -29,8 +29,9 @@ KLDivergence<InputDataType, OutputDataType>::KLDivergence(const bool takeMean) :
template<typename InputDataType, typename OutputDataType>
template<typename PredictionType, typename TargetType>
typename PredictionType::elem_type
KLDivergence<InputDataType, OutputDataType>::Forward(const PredictionType& prediction,
const TargetType& target)
KLDivergence<InputDataType, OutputDataType>::Forward(
const PredictionType& prediction,
const TargetType& target)
{
if (takeMean)
{
@@ -52,7 +53,8 @@ void KLDivergence<InputDataType, OutputDataType>::Backward(
{
if (takeMean)
{
loss = arma::mean(arma::mean(arma::log(prediction) - arma::log(target) + 1));
loss = arma::mean(arma::mean(
arma::log(prediction) - arma::log(target) + 1));
}
else
{
@@ -65,8 +65,10 @@ class SigmoidCrossEntropyError
* @param target The target vector.
*/
template<typename PredictionType, typename TargetType>
inline typename PredictionType::elem_type Forward(const PredictionType& prediction,
const TargetType& target);
inline typename PredictionType::elem_type Forward(
const PredictionType& prediction,
const TargetType& target);
/**
* Ordinary feed backward pass of a neural network.
*
@@ -108,4 +108,4 @@ class TripletMarginLoss
// include implementation.
#include "triplet_margin_loss_impl.hpp"
#endif
#endif
@@ -33,8 +33,10 @@ TripletMarginLoss<InputDataType, OutputDataType>::Forward(
const PredictionType& prediction,
const TargetType& target)
{
PredictionType anchor = prediction.submat(0, 0, prediction.n_rows / 2 - 1, prediction.n_cols - 1);
PredictionType positive = prediction.submat(prediction.n_rows / 2, 0, prediction.n_rows - 1,
PredictionType anchor =
prediction.submat(0, 0, prediction.n_rows / 2 - 1, prediction.n_cols - 1);
PredictionType positive =
prediction.submat(prediction.n_rows / 2, 0, prediction.n_rows - 1,
prediction.n_cols - 1);
return std::max(0.0, arma::accu(arma::pow(anchor - positive, 2)) -
arma::accu(arma::pow(anchor - target, 2)) + margin) / anchor.n_cols;
@@ -51,7 +53,8 @@ void TripletMarginLoss<InputDataType, OutputDataType>::Backward(
const TargetType& target,
LossType& loss)
{
PredictionType positive = prediction.submat(prediction.n_rows / 2, 0, prediction.n_rows - 1,
PredictionType positive =
prediction.submat(prediction.n_rows / 2, 0, prediction.n_rows - 1,
prediction.n_cols - 1);
loss = 2 * (target - positive) / target.n_cols;
}
+6 -9
View File
@@ -149,9 +149,8 @@ double RNN<OutputLayerType, InitializationRuleType, CustomLayers...>::Train(
OptimizerType& optimizer,
CallbackTypes&&... callbacks)
{
CheckInputShape<std::vector<LayerTypes<CustomLayers...> > >(network,
predictors.n_rows,
"RNN<>::Train()");
CheckInputShape<std::vector<LayerTypes<CustomLayers...> > >(
network, predictors.n_rows, "RNN<>::Train()");
numFunctions = responses.n_cols;
@@ -197,9 +196,8 @@ double RNN<OutputLayerType, InitializationRuleType, CustomLayers...>::Train(
arma::cube responses,
CallbackTypes&&... callbacks)
{
CheckInputShape<std::vector<LayerTypes<CustomLayers...> > >(network,
predictors.n_rows,
"RNN<>::Train()");
CheckInputShape<std::vector<LayerTypes<CustomLayers...> > >(
network, predictors.n_rows, "RNN<>::Train()");
numFunctions = responses.n_cols;
@@ -233,9 +231,8 @@ template<typename OutputLayerType, typename InitializationRuleType,
void RNN<OutputLayerType, InitializationRuleType, CustomLayers...>::Predict(
arma::cube predictors, arma::cube& results, const size_t batchSize)
{
CheckInputShape<std::vector<LayerTypes<CustomLayers...> > >(network,
predictors.n_rows,
"RNN<>::Predict()");
CheckInputShape<std::vector<LayerTypes<CustomLayers...> > >(
network, predictors.n_rows, "RNN<>::Predict()");
ResetCells();
@@ -22,7 +22,8 @@ namespace mlpack {
namespace ann /** Artificial Neural Network. */{
template<typename T>
void CheckInputShape(const T& network, const size_t inputShape,
void CheckInputShape(const T& network,
const size_t inputShape,
const std::string& functionName)
{
for (size_t l = 0; l < network.size(); ++l)
@@ -203,10 +203,10 @@ class DecisionTree :
typename std::remove_reference<WeightsType>::type>::value>* = 0);
/**
* Take ownership of another decision tree and train on the given data and labels
* with weights, assuming that the data is all of the numeric type. Setting
* minimumLeafSize and minimumGainSplit too small may cause the tree to
* overfit, but setting them too large may cause it to underfit.
* Take ownership of another decision tree and train on the given data and
* labels with weights, assuming that the data is all of the numeric type.
* Setting minimumLeafSize and minimumGainSplit too small may cause the tree
* to overfit, but setting them too large may cause it to underfit.
*
* Use std::move if data, labels or weights are no longer needed to avoid
* copies.
@@ -164,14 +164,14 @@ class HoeffdingTree
/**
* Copy assignment operator.
*
*
* @param other Tree to copy.
*/
HoeffdingTree& operator=(const HoeffdingTree& other);
/**
* Move assignment operator.
*
*
* @param other Tree to move.
*/
HoeffdingTree& operator=(HoeffdingTree&& other);
@@ -183,29 +183,53 @@ class HoeffdingTree
/**
* Train on a set of points, either in streaming mode or in batch mode, with
* the given labels.
* the given labels. If `resetTree` is set to `true`, then reset the state of
* the tree to an empty tree before training.
*
* Note that the tree will be automatically reset if the dimensionality of
* `data` does not match the dimensionality that the tree was currently
* trained with. The tree will also be reset if `numClasses` is passed.
*
* @param data Data points to train on.
* @param labels Labels of data points.
* @param batchTraining If true, perform training in batch.
* @param resetTree If true, reset the tree to an empty tree before training.
* @param numClasses The number of classes in `labels`. Passing this will
* reset the tree. If not given and `resetTree` is `true`, then the
* number of classes will be computed from `labels`.
*/
template<typename MatType>
void Train(const MatType& data,
const arma::Row<size_t>& labels,
const bool batchTraining = true);
const bool batchTraining = true,
const bool resetTree = false,
const size_t numClasses = 0);
/**
* Train on a set of points, either in streaming mode or in batch mode, with
* the given labels and the given DatasetInfo. This will reset the tree.
* the given labels and the given `DatasetInfo`. This will reset the tree.
* This only needs to be called when the `DatasetInfo` has changed---if you
* are training incrementally but have already passed the DatasetInfo once,
* use the overload of `Train()` that does not take a `DatasetInfo` and make
* sure `resetTree` is set to `false`.
*
* @param data Data points to train on.
* @param info DatasetInfo object with information about each dimension.
* @param labels Labels of data points.
* @param batchTraining If true, perform training in batch.
* @param numClasses Number of classes in `labels`. If not specified, it is
* computed from `labels`.
*/
template<typename MatType>
void Train(const MatType& data,
const data::DatasetInfo& info,
const arma::Row<size_t>& labels,
const bool batchTraining = true);
const bool batchTraining = true,
const size_t numClasses = 0);
/**
* Train on a single point in streaming mode, with the given label.
* Train on a single point in streaming mode, with the given label. The tree
* will not be reset before training.
*
* @param point Point to train on.
* @param label Label of point to train on.
@@ -379,6 +403,24 @@ class HoeffdingTree
typename NumericSplitType<FitnessFunction>::SplitInfo numericSplit;
//! If the split has occurred, these are the children.
std::vector<HoeffdingTree*> children;
/**
* Perform training (typically after a reset, but not necessarily). This
* assumes datasetInfo and dimensionMappings are set correctly.
*/
template<typename MatType>
void TrainInternal(const MatType& data,
const arma::Row<size_t>& labels,
const bool batchTraining);
/**
* Reset the tree. This assumes datasetInfo is set correctly.
*/
void ResetTree(
const CategoricalSplitType<FitnessFunction>& categoricalSplitIn =
CategoricalSplitType<FitnessFunction>(0, 0),
const NumericSplitType<FitnessFunction>& numericSplitIn =
NumericSplitType<FitnessFunction>(0));
};
} // namespace tree
@@ -28,7 +28,7 @@ HoeffdingTree<
NumericSplitType,
CategoricalSplitType
>::HoeffdingTree(const MatType& data,
const data::DatasetInfo& datasetInfo,
const data::DatasetInfo& datasetInfoIn,
const arma::Row<size_t>& labels,
const size_t numClasses,
const bool batchTraining,
@@ -39,15 +39,14 @@ HoeffdingTree<
const CategoricalSplitType<FitnessFunction>&
categoricalSplitIn,
const NumericSplitType<FitnessFunction>& numericSplitIn) :
dimensionMappings(new std::unordered_map<size_t,
std::pair<size_t, size_t>>()),
ownsMappings(true),
dimensionMappings(NULL),
ownsMappings(false),
numSamples(0),
numClasses(numClasses),
maxSamples((maxSamples == 0) ? size_t(-1) : maxSamples),
checkInterval(checkInterval),
minSamples(minSamples),
datasetInfo(new data::DatasetInfo(datasetInfo)),
datasetInfo(new data::DatasetInfo(datasetInfoIn)),
ownsInfo(true),
successProbability(successProbability),
splitDimension(size_t(-1)),
@@ -56,24 +55,8 @@ HoeffdingTree<
categoricalSplit(0),
numericSplit()
{
// Generate dimension mappings and create split objects.
for (size_t i = 0; i < datasetInfo.Dimensionality(); ++i)
{
if (datasetInfo.Type(i) == data::Datatype::categorical)
{
categoricalSplits.push_back(CategoricalSplitType<FitnessFunction>(
datasetInfo.NumMappings(i), numClasses, categoricalSplitIn));
(*dimensionMappings)[i] = std::make_pair(data::Datatype::categorical,
categoricalSplits.size() - 1);
}
else
{
numericSplits.push_back(NumericSplitType<FitnessFunction>(numClasses,
numericSplitIn));
(*dimensionMappings)[i] = std::make_pair(data::Datatype::numeric,
numericSplits.size() - 1);
}
}
// Reset the tree.
ResetTree(categoricalSplitIn, numericSplitIn);
// Now train.
Train(data, labels, batchTraining);
@@ -119,23 +102,7 @@ HoeffdingTree<
// Do we need to generate the mappings too?
if (ownsMappings)
{
for (size_t i = 0; i < datasetInfo.Dimensionality(); ++i)
{
if (datasetInfo.Type(i) == data::Datatype::categorical)
{
categoricalSplits.push_back(CategoricalSplitType<FitnessFunction>(
datasetInfo.NumMappings(i), numClasses, categoricalSplitIn));
(*dimensionMappings)[i] = std::make_pair(data::Datatype::categorical,
categoricalSplits.size() - 1);
}
else
{
numericSplits.push_back(NumericSplitType<FitnessFunction>(numClasses,
numericSplitIn));
(*dimensionMappings)[i] = std::make_pair(data::Datatype::numeric,
numericSplits.size() - 1);
}
}
ResetTree(categoricalSplitIn, numericSplitIn);
}
else
{
@@ -381,71 +348,28 @@ void HoeffdingTree<
CategoricalSplitType
>::Train(const MatType& data,
const arma::Row<size_t>& labels,
const bool batchTraining)
const bool batchTraining,
const bool resetTree,
const size_t numClassesIn)
{
if (batchTraining)
// We need to reset the tree either if the user asked for it, or if they
// passed data whose dimensionality is different than our datasetInfo object.
if (resetTree || data.n_rows != datasetInfo->Dimensionality() ||
numClassesIn != 0)
{
// Pass all the points through the nodes, and then split only after that.
checkInterval = data.n_cols; // Only split on the last sample.
// Don't split if there are fewer than five points.
size_t oldMaxSamples = maxSamples;
maxSamples = std::max(size_t(data.n_cols - 1), size_t(5));
for (size_t i = 0; i < data.n_cols; ++i)
Train(data.col(i), labels[i]);
maxSamples = oldMaxSamples;
// Create a new datasetInfo, which assumes that all features are numeric.
if (ownsInfo)
delete datasetInfo;
datasetInfo = new data::DatasetInfo(data.n_rows);
ownsInfo = true;
// Now, if we did split, find out which points go to which child, and
// perform the same batch training.
if (children.size() > 0)
{
// We need to create a vector of indices that represent the points that
// must go to each child, so we need children.size() vectors, but we don't
// know how long they will be. Therefore, we will create vectors each of
// size data.n_cols, but will probably not use all the memory we
// allocated, and then pass subvectors to the submat() function.
std::vector<arma::uvec> indices(children.size(), arma::uvec(data.n_cols));
arma::Col<size_t> counts =
arma::zeros<arma::Col<size_t>>(children.size());
// Set the number of classes correctly.
numClasses = (numClassesIn != 0) ? numClassesIn : arma::max(labels) + 1;
for (size_t i = 0; i < data.n_cols; ++i)
{
size_t direction = CalculateDirection(data.col(i));
size_t currentIndex = counts[direction];
indices[direction][currentIndex] = i;
counts[direction]++;
}
// Now pass each of these submatrices to the children to perform
// batch-mode training.
for (size_t i = 0; i < children.size(); ++i)
{
// If we don't have any points that go to the child in question, don't
// train that child.
if (counts[i] == 0)
continue;
// The submatrix here is non-contiguous, but I think this will be faster
// than copying the points to an ordered state. We still have to
// assemble the labels vector, though.
arma::Row<size_t> childLabels = labels.cols(
indices[i].subvec(0, counts[i] - 1));
// Unfortunately, limitations of Armadillo's non-contiguous subviews
// prohibits us from successfully passing the non-contiguous subview to
// Train(), since the col() function is not provided. So,
// unfortunately, instead, we'll just extract the non-contiguous
// submatrix.
MatType childData = data.cols(indices[i].subvec(0, counts[i] - 1));
children[i]->Train(childData, childLabels, true);
}
}
}
else
{
// We aren't training in batch mode; loop through the points.
for (size_t i = 0; i < data.n_cols; ++i)
Train(data.col(i), labels[i]);
ResetTree();
}
TrainInternal(data, labels, batchTraining);
}
//! Train on a set of points.
@@ -460,7 +384,8 @@ void HoeffdingTree<
>::Train(const MatType& data,
const data::DatasetInfo& info,
const arma::Row<size_t>& labels,
const bool batchTraining)
const bool batchTraining,
const size_t numClassesIn)
{
// Take over new DatasetInfo.
if (ownsInfo)
@@ -468,40 +393,13 @@ void HoeffdingTree<
datasetInfo = &info;
ownsInfo = false;
// Generate mappings.
if (ownsMappings)
delete dimensionMappings;
// Set the number of classes correctly.
numClasses = (numClassesIn != 0) ? numClassesIn : arma::max(labels) + 1;
const CategoricalSplitType<FitnessFunction> categoricalSplitIn(0, 0);
const NumericSplitType<FitnessFunction> numericSplitIn(0);
dimensionMappings =
new std::unordered_map<size_t, std::pair<size_t, size_t>>();
for (size_t i = 0; i < datasetInfo->Dimensionality(); ++i)
{
if (datasetInfo->Type(i) == data::Datatype::categorical)
{
categoricalSplits.push_back(CategoricalSplitType<FitnessFunction>(
datasetInfo->NumMappings(i), numClasses, categoricalSplitIn));
(*dimensionMappings)[i] = std::make_pair(data::Datatype::categorical,
categoricalSplits.size() - 1);
}
else
{
numericSplits.push_back(NumericSplitType<FitnessFunction>(numClasses,
numericSplitIn));
(*dimensionMappings)[i] = std::make_pair(data::Datatype::numeric,
numericSplits.size() - 1);
}
}
// Remove any old children.
for (size_t i = 0; i < children.size(); ++i)
delete children[i];
children.clear();
ResetTree();
// Now train.
Train(data, labels, batchTraining);
TrainInternal(data, labels, batchTraining);
}
//! Train on one point.
@@ -1036,6 +934,140 @@ void HoeffdingTree<
}
}
template<
typename FitnessFunction,
template<typename> class NumericSplitType,
template<typename> class CategoricalSplitType
>
template<typename MatType>
void HoeffdingTree<
FitnessFunction,
NumericSplitType,
CategoricalSplitType
>::TrainInternal(const MatType& data,
const arma::Row<size_t>& labels,
const bool batchTraining)
{
if (batchTraining)
{
// Pass all the points through the nodes, and then split only after that.
checkInterval = data.n_cols; // Only split on the last sample.
// Don't split if there are fewer than five points.
size_t oldMaxSamples = maxSamples;
maxSamples = std::max(size_t(data.n_cols - 1), size_t(5));
for (size_t i = 0; i < data.n_cols; ++i)
Train(data.col(i), labels[i]);
maxSamples = oldMaxSamples;
// Now, if we did split, find out which points go to which child, and
// perform the same batch training.
if (children.size() > 0)
{
// We need to create a vector of indices that represent the points that
// must go to each child, so we need children.size() vectors, but we don't
// know how long they will be. Therefore, we will create vectors each of
// size data.n_cols, but will probably not use all the memory we
// allocated, and then pass subvectors to the submat() function.
std::vector<arma::uvec> indices(children.size(), arma::uvec(data.n_cols));
arma::Col<size_t> counts =
arma::zeros<arma::Col<size_t>>(children.size());
for (size_t i = 0; i < data.n_cols; ++i)
{
size_t direction = CalculateDirection(data.col(i));
size_t currentIndex = counts[direction];
indices[direction][currentIndex] = i;
counts[direction]++;
}
// Now pass each of these submatrices to the children to perform
// batch-mode training.
for (size_t i = 0; i < children.size(); ++i)
{
// If we don't have any points that go to the child in question, don't
// train that child.
if (counts[i] == 0)
continue;
// The submatrix here is non-contiguous, but I think this will be faster
// than copying the points to an ordered state. We still have to
// assemble the labels vector, though.
arma::Row<size_t> childLabels = labels.cols(
indices[i].subvec(0, counts[i] - 1));
// Unfortunately, limitations of Armadillo's non-contiguous subviews
// prohibits us from successfully passing the non-contiguous subview to
// Train(), since the col() function is not provided. So,
// unfortunately, instead, we'll just extract the non-contiguous
// submatrix.
MatType childData = data.cols(indices[i].subvec(0, counts[i] - 1));
children[i]->Train(childData, childLabels, true);
}
}
}
else
{
// We aren't training in batch mode; loop through the points.
for (size_t i = 0; i < data.n_cols; ++i)
Train(data.col(i), labels[i]);
}
}
template<
typename FitnessFunction,
template<typename> class NumericSplitType,
template<typename> class CategoricalSplitType
>
void HoeffdingTree<
FitnessFunction,
NumericSplitType,
CategoricalSplitType
>::ResetTree(const CategoricalSplitType<FitnessFunction>& categoricalSplitIn,
const NumericSplitType<FitnessFunction>& numericSplitIn)
{
// Generate mappings.
if (ownsMappings)
delete dimensionMappings;
categoricalSplits.clear();
numericSplits.clear();
dimensionMappings =
new std::unordered_map<size_t, std::pair<size_t, size_t>>();
ownsMappings = true;
for (size_t i = 0; i < datasetInfo->Dimensionality(); ++i)
{
if (datasetInfo->Type(i) == data::Datatype::categorical)
{
categoricalSplits.push_back(CategoricalSplitType<FitnessFunction>(
datasetInfo->NumMappings(i), numClasses, categoricalSplitIn));
(*dimensionMappings)[i] = std::make_pair(data::Datatype::categorical,
categoricalSplits.size() - 1);
}
else
{
numericSplits.push_back(NumericSplitType<FitnessFunction>(numClasses,
numericSplitIn));
(*dimensionMappings)[i] = std::make_pair(data::Datatype::numeric,
numericSplits.size() - 1);
}
}
// Clear children.
for (size_t i = 0; i < children.size(); ++i)
delete children[i];
children.clear();
// Reset statistics.
numSamples = 0;
splitDimension = size_t(-1);
majorityClass = 0;
majorityProbability = 0.0;
categoricalSplit =
typename CategoricalSplitType<FitnessFunction>::SplitInfo(0);
numericSplit = typename NumericSplitType<FitnessFunction>::SplitInfo();
}
} // namespace tree
} // namespace mlpack
-2
View File
@@ -264,9 +264,7 @@ operator=(KDE&& other)
// Move the other object.
this->kernel = std::move(other.kernel);
this->metric = std::move(other.metric);
// TODO: This should be: this->referenceTree = other.referenceTree;
this->referenceTree = std::move(other.referenceTree);
// TODO: This should be: this->oldFromNewReferences = other.oldFromNewReferences;
this->oldFromNewReferences = std::move(other.oldFromNewReferences);
this->relError = other.relError;
this->absError = other.absError;
@@ -44,7 +44,7 @@ class NSWrapperBase
virtual NSWrapperBase* Clone() const = 0;
//! Destruct the NSWrapperBase (nothing to do).
virtual ~NSWrapperBase() { };
virtual ~NSWrapperBase() { }
//! Return a reference to the dataset.
virtual const arma::mat& Dataset() const = 0;
@@ -516,7 +516,6 @@ void NSModel<SortPolicy>::InitializeModel(const NeighborSearchMode searchMode,
epsilon);
break;
}
}
//! Build the reference tree.
+1 -1
View File
@@ -74,7 +74,7 @@ void PCA<DecompositionPolicy>::Apply(const arma::mat& data,
arma::mat eigvec;
Apply(data, transformedData, eigVal, eigvec);
}
/**
* Apply Principal Component Analysis to the provided data set.
*
@@ -174,7 +174,8 @@ RangeSearch<MetricType, MatType, TreeType>::operator=(const RangeSearch& other)
if (this != &other)
{
oldFromNewReferences = other.oldFromNewReferences;
referenceTree = other.referenceTree ? new Tree(*other.referenceTree) : nullptr;
referenceTree = other.referenceTree ? new Tree(*other.referenceTree) :
nullptr;
referenceSet = other.referenceTree ? &referenceTree->Dataset() :
new MatType(*other.referenceSet);
treeOwner = other.referenceTree;
@@ -222,7 +223,6 @@ RangeSearch<MetricType, MatType, TreeType>::operator=(RangeSearch&& other)
other.singleMode = false;
other.baseCases = 0;
other.scores = 0;
}
return *this;
}
+1 -1
View File
@@ -41,7 +41,7 @@ class RAWrapperBase
virtual RAWrapperBase* Clone() const = 0;
//! Destruct the RAWrapperBase (nothing to do).
virtual ~RAWrapperBase() { };
virtual ~RAWrapperBase() { }
//! Return a reference to the dataset.
virtual const arma::mat& Dataset() const = 0;
@@ -54,7 +54,7 @@ QLearning<
// Set up q-learning network.
if (learningNetwork.Parameters().is_empty())
learningNetwork.ResetParameters();
targetNetwork.ResetParameters();
#if ENS_VERSION_MAJOR == 1
+32 -26
View File
@@ -664,16 +664,18 @@ void CheckSoftminDerivativeCorrect(const arma::colvec input,
* Implementation of the Flatten T Swish activation function test. The function is
* implemented as Flatten T Swish layer in the file flatten_t_swish.hpp.
*
* @param input Input data used for evaluating the Flatten T Swish activation function.
* @param input Input data used for evaluating the Flatten T Swish activation
* function.
* @param target Target data used to evaluate the Flatten T Swish activation.
*/
void CheckFlattenTSwishActivationCorrect(const arma::colvec input, const arma::colvec target)
void CheckFlattenTSwishActivationCorrect(const arma::colvec input,
const arma::colvec target)
{
FlattenTSwish<> fts(0.4);
arma::colvec activations;
fts.Forward(input,activations);
for(size_t i = 0; i < activations.n_elem; ++i)
fts.Forward(input, activations);
for (size_t i = 0; i < activations.n_elem; ++i)
{
REQUIRE(activations.at(i) == Approx(target.at(i)).epsilon(1e-5));
}
@@ -686,8 +688,8 @@ void CheckFlattenTSwishActivationCorrect(const arma::colvec input, const arma::c
* @param input Input data used for evaluating the Softmin activation function.
* @param target Target data used to evaluate the Softmin activation.
*/
void CheckFlattenTSwishDerivateCorrect(const arma::colvec input, const arma::colvec target)
void CheckFlattenTSwishDerivateCorrect(const arma::colvec input,
const arma::colvec target)
{
FlattenTSwish<> fts;
@@ -695,8 +697,8 @@ void CheckFlattenTSwishDerivateCorrect(const arma::colvec input, const arma::col
arma::colvec error = arma::ones<arma::colvec>(input.n_elem);
arma::colvec derivate;
fts.Backward(input,error,derivate);
for(size_t i = 0; i < derivate.n_elem; ++i)
fts.Backward(input, error, derivate);
for (size_t i = 0; i < derivate.n_elem; ++i)
{
REQUIRE(derivate.at(i) == Approx(target.at(i)).epsilon(1e-5));
}
@@ -1270,7 +1272,6 @@ TEST_CASE("HardSwishFunctionTest", "[ActivationFunctionsTest]")
*/
TEST_CASE("TanhExpFunctionTest", "[ActivationFunctionsTest]")
{
const arma::colvec activationData("-2 3.2 4.5 1 -1 2 0");
// Hand-calculated values.
@@ -1282,47 +1283,52 @@ TEST_CASE("TanhExpFunctionTest", "[ActivationFunctionsTest]")
1.03924 0.449818 1.00002 0.761594");
CheckActivationCorrect<TanhExpFunction>(activationData, desiredActivations);
CheckDerivativeCorrect<TanhExpFunction>(desiredActivations, desiredDerivatives);
CheckDerivativeCorrect<TanhExpFunction>(desiredActivations,
desiredDerivatives);
}
/**
* Basic test of the SILU(Sigmoid Weighted Linear Unit) Function
*/
TEST_CASE("SILUFunctionTest","[ActivationFunctionsTest]")
TEST_CASE("SILUFunctionTest", "[ActivationFunctionsTest]")
{
// Random generated values.
const arma::colvec activationData("-2 2 4.5 -5.7 -1 1 0 10");
// Calculated with PyTorch.
arma::colvec desiredActivation("-0.23840583860874176 1.7615940570831299 4.450558662414551 \
-0.01900840364396572 -0.2689414322376251 0.7310585975646973 \
0.0 9.99954605102539");
arma::colvec desiredActivation(
"-0.23840583860874176 1.7615940570831299 4.450558662414551 \
-0.01900840364396572 -0.2689414322376251 0.7310585975646973 \
0.0 9.99954605102539");
// Calculated with PyTorch.
arma::colvec desiredDerivate("0.38191673159599304 1.073788046836853 1.0392179489135742 \
0.49049633741378784 0.36713290214538574 0.8354039788246155 \
0.5 1.0004087686538696");
CheckActivationCorrect<SILUFunction>(activationData,desiredActivation);
CheckDerivativeCorrect<SILUFunction>(desiredActivation,desiredDerivate);
arma::colvec desiredDerivate(
"0.38191673159599304 1.073788046836853 1.0392179489135742 \
0.49049633741378784 0.36713290214538574 0.8354039788246155 \
0.5 1.0004087686538696");
CheckActivationCorrect<SILUFunction>(activationData, desiredActivation);
CheckDerivativeCorrect<SILUFunction>(desiredActivation, desiredDerivate);
}
/**
* Basic test of Flatten T Swish function.
*/
TEST_CASE("FlattenTSwishFunctionTest","[ActivationFunctionsTest]")
TEST_CASE("FlattenTSwishFunctionTest", "[ActivationFunctionsTest]")
{
// Random Value.
arma::colvec input("-4.0 -1.0 2 3 4 5 6");
// Hand Calculated and using PyTorch.
arma::colvec desiredActivation("0.4000000059604645 0.4000000059604645 2.1615941524505615 \
3.2577223777770996 4.328054904937744 5.3665361404418945 6.385164737701416");
arma::colvec desiredActivation(
"0.4000000059604645 0.4000000059604645 2.1615941524505615 \
3.2577223777770996 4.328054904937744 5.3665361404418945 \
6.385164737701416");
// Hand Calculated and using PyTorch.
arma::colvec desiredDerivation("0.694792 0.694792 1.096893 1.079178 1.042602 \
1.020182 1.009048");
CheckFlattenTSwishActivationCorrect(input,desiredActivation);
CheckFlattenTSwishDerivateCorrect(desiredActivation,desiredDerivation);
}
CheckFlattenTSwishActivationCorrect(input, desiredActivation);
CheckFlattenTSwishDerivateCorrect(desiredActivation, desiredDerivation);
}
+1 -1
View File
@@ -3927,7 +3927,7 @@ TEST_CASE("MeanPoolingTestCase", "[ANNLayerTest]")
CheckMatrices(output1, result1, 1e-1);
CheckMatrices(output2, result2, 1e-1);
arma::mat delta1, delta2;
arma::mat delta1, delta2;
module1.Backward(input, output1, delta1);
REQUIRE(arma::accu(delta1) == 25.5);
module2.Backward(input, output2, delta2);
+2 -2
View File
@@ -228,8 +228,8 @@ TEST_CASE("WeightSizeVisitorTestForMultiheadAttentionLayer", "[ANNVisitorTest]")
size_t randomembedDim = 768;
size_t randomnumHeads = 12;
LayerTypes<> MultiheadAttentionLayer = new MultiheadAttention<>(randomtgtSeqLen,
randomsrcSeqLen, randomembedDim, randomnumHeads);
LayerTypes<> MultiheadAttentionLayer = new MultiheadAttention<>(
randomtgtSeqLen, randomsrcSeqLen, randomembedDim, randomnumHeads);
CheckCorrectnessOfWeightSize(MultiheadAttentionLayer);
}
+4 -2
View File
@@ -539,7 +539,8 @@ TEST_CASE("SetParamDatasetInfoMatTest", "[CLIOptionTest]")
typedef tuple<string, size_t, size_t> TupleType;
TupleType testTuple{filename, 0, 0};
tuple<DatasetInfo, arma::mat> t1 = make_tuple(di, m);
tuple<tuple<DatasetInfo, arma::mat>, TupleType> t2 = make_tuple(t1, testTuple);
tuple<tuple<DatasetInfo, arma::mat>, TupleType> t2 = make_tuple(t1,
testTuple);
d.value = boost::any(t2);
d.noTranspose = false;
@@ -552,7 +553,8 @@ TEST_CASE("SetParamDatasetInfoMatTest", "[CLIOptionTest]")
// Check that the name is right.
tuple<tuple<DatasetInfo, arma::mat>, TupleType>& t3 =
*boost::any_cast<tuple<tuple<DatasetInfo, arma::mat>, TupleType>>(&d.value);
*boost::any_cast<tuple<tuple<DatasetInfo, arma::mat>, TupleType>>(
&d.value);
REQUIRE(get<0>(get<1>(t3)) == "new_filename.csv");
}
+3 -3
View File
@@ -440,8 +440,8 @@ TEST_CASE("RandomBinaryNumericSplitNoGainTest", "[DecisionTreeTest]")
* Check that RandomBinaryNumericSplit generally gives a split different than
* the BestBinaryNumericSplit.
*/
TEST_CASE("RandomBinaryNumericSplitDiffSplitTest", "[DecisionTreeTest]")
{
TEST_CASE("RandomBinaryNumericSplitDiffSplitTest", "[DecisionTreeTest]")
{
arma::vec values(1000);
arma::Row<size_t> labels(1000);
arma::rowvec weights;
@@ -476,7 +476,7 @@ TEST_CASE("RandomBinaryNumericSplitNoGainTest", "[DecisionTreeTest]")
}
REQUIRE(classProbabilities[0] != classProbabilities1[0]);
}
}
/**
* Check that the AllCategoricalSplit will split when the split is obviously
@@ -158,7 +158,8 @@ TEST_CASE("CheckCopyMovingVanillaNetworkTest", "[FeedForwardNetworkTest]")
/**
* Check whether copying and moving network with Reparametrization is working or not.
*/
TEST_CASE("CheckCopyMovingReparametrizationNetworkTest", "[FeedForwardNetworkTest]")
TEST_CASE("CheckCopyMovingReparametrizationNetworkTest",
"[FeedForwardNetworkTest]")
{
// Load the dataset.
arma::mat trainData;
@@ -285,7 +286,7 @@ TEST_CASE("CheckCopyMovingNoisyLinearTest", "[FeedForwardNetworkTest]")
TEST_CASE("CheckCopyMovingConcatenateTest", "[FeedForwardNetworkTest]")
{
// Create training input by 5x5 matrix.
arma::mat input = arma::randu(10,1);
arma::mat input = arma::randu(10, 1);
// Create training output by 1 matrix.
arma::mat output = arma::mat("1");
@@ -1000,9 +1001,10 @@ TEST_CASE("FFNCheckInputShapeTest", "[FeedForwardNetworkTest]")
model.Add<LogSoftMax<> >();
std::string expectedMsg = "FFN<>::Train(): ";
expectedMsg += "the first layer of the network expects ";
expectedMsg += std::to_string(trainData.n_rows - 3) + " elements, ";
expectedMsg += "but the input has " + std::to_string(trainData.n_rows) + " dimensions! ";
expectedMsg += "the first layer of the network expects ";
expectedMsg += std::to_string(trainData.n_rows - 3) + " elements, ";
expectedMsg += "but the input has " + std::to_string(trainData.n_rows) +
" dimensions! ";
ens::DE opt(200, 1000, 0.6, 0.8, 1e-5);
+4 -4
View File
@@ -833,10 +833,10 @@ TEST_CASE("GaussianHMMPredictTest", "[HMMTest]")
0.0521, 0.0313, 0.0188, 0.0113, 0.0068, 0.0042, 0.0026, 0.0018, 0.0014
}
};
//100 pre-calculated emission probabilities each for 10 states
// 100 pre-calculated emission probabilities each for 10 states.
std::vector<arma::vec> emissionProb = {
{ -2.7301e+03, 1.7874e+00, -1.9428e+00, -3.6365e+00, -4.0397e-01,
{ -2.7301e+03, 1.7874e+00, -1.9428e+00, -3.6365e+00, -4.0397e-01,
-1.5115e-01, -1.0328e+00, -1.1071e+00, 5.2876e-01, -1.0643e-01 },
{ -2.3684e+03, 1.8059e+00, -2.2058e+00, -4.0514e+00, -5.0935e-01,
-2.1126e-01, -1.1962e+00, -1.2567e+00, 4.1247e-01, -3.0199e-01 },
@@ -1037,7 +1037,7 @@ TEST_CASE("GaussianHMMPredictTest", "[HMMTest]")
{ -1.5426e+05, -5.8691e-01, -2.8121e-01, -1.2660e+00, -4.9111e-01,
-1.8141e-01, -5.7387e-02, -8.0842e-01, -2.9317e-01, 6.1601e-01 },
};
const double loglikelihoodRef = -2734.43;
// Test log-likelihood calculation for the whole data.
+52 -1
View File
@@ -1044,7 +1044,7 @@ TEST_CASE("BatchTrainingTest", "[HoeffdingTreeTest]")
// able to have enough samples to build to the same leaves.
HoeffdingTree<> batchTree(trainingData, info, trainingLabels, 5, true,
0.99999999);
HoeffdingTree<> streamTree(trainingLabels, info, trainingLabels, 5, false,
HoeffdingTree<> streamTree(trainingData, info, trainingLabels, 5, false,
0.99999999);
// Ensure that the performance of the batch tree is better.
@@ -1475,3 +1475,54 @@ TEST_CASE("HoeffdingTreeModelSerializationTest", "[HoeffdingTreeTest]")
}
}
}
TEST_CASE("HoeffdingTreeEmptyConstructorTrainTest", "[HoeffdingTreeTest]")
{
// Generate data.
arma::mat data(5, 1000, arma::fill::randu);
// Generate labels.
arma::Row<size_t> labels(1000);
for (size_t i = 0; i < 500; ++i)
labels[i] = 0;
for (size_t i = 500; i < 1000; ++i)
labels[i] = 1;
// Create an empty tree.
HoeffdingTree<> ht;
// Just ensure that we can train without throwing an exception.
REQUIRE_NOTHROW(ht.Train(data, labels));
// Now, create a categorical dataset and retrain.
arma::mat data2 = arma::mat(4, 3000);
arma::Row<size_t> labels2(3000);
data::DatasetInfo info(4); // All features are numeric, except the fourth.
info.MapString<double>("0", 3);
for (size_t i = 0; i < 3000; i += 3)
{
data2(0, i) = mlpack::math::Random();
data2(1, i) = mlpack::math::Random();
data2(2, i) = mlpack::math::Random();
data2(3, i) = 0.0;
labels2[i] = 0;
data2(0, i + 1) = mlpack::math::Random();
data2(1, i + 1) = mlpack::math::Random() - 1.0;
data2(2, i + 1) = mlpack::math::Random() + 0.5;
data2(3, i + 1) = 0.0;
labels2[i + 1] = 2;
data2(0, i + 2) = mlpack::math::Random();
data2(1, i + 2) = mlpack::math::Random() + 1.0;
data2(2, i + 2) = mlpack::math::Random() + 0.8;
data2(3, i + 2) = 0.0;
labels2[i + 2] = 1;
}
// Ensure we can train without throwing an exception.
REQUIRE_NOTHROW(ht.Train(data2, info, labels2));
// Train while specifying the number of classes.
REQUIRE_NOTHROW(ht.Train(data, labels, false, true, 2));
REQUIRE_NOTHROW(ht.Train(data2, info, labels2, false, 3));
}
+5 -5
View File
@@ -43,7 +43,7 @@ TEST_CASE("NaiveGuaranteeTest", "[KRANNTest]")
RASearch<> rsRann(refData, true, false, 1.0);
arma::mat qrRanks;
if (!data::Load("rann_test_qr_ranks.csv", qrRanks, false, false)) // No transpose.
if (!data::Load("rann_test_qr_ranks.csv", qrRanks, false, false))
FAIL("Cannot load dataset rann_test_qr_ranks.csv");
size_t numRounds = 1000;
@@ -105,7 +105,7 @@ TEST_CASE("SingleTreeSearch", "[KRANNTest]")
// The relative ranks for the given query reference pair
arma::Mat<size_t> qrRanks;
if (!data::Load("rann_test_qr_ranks.csv", qrRanks, false, false)) // No transpose.
if (!data::Load("rann_test_qr_ranks.csv", qrRanks, false, false))
FAIL("Cannot load dataset rann_test_qr_ranks.csv");
size_t numRounds = 1000;
@@ -166,7 +166,7 @@ TEST_CASE("DualTreeSearch", "[KRANNTest]")
RASearch<> tsdRann(refData, false, false, 1.0, 0.95, false, false, 5);
arma::Mat<size_t> qrRanks;
if (!data::Load("rann_test_qr_ranks.csv", qrRanks, false, false)) // No transpose.
if (!data::Load("rann_test_qr_ranks.csv", qrRanks, false, false))
FAIL("Cannot load dataset rann_test_qr_ranks.csv");
size_t numRounds = 1000;
@@ -300,7 +300,7 @@ TEST_CASE("SingleCoverTreeTest", "[KRANNTest]")
// The relative ranks for the given query reference pair.
arma::Mat<size_t> qrRanks;
if (!data::Load("rann_test_qr_ranks.csv", qrRanks, false, false)) // No transpose.
if (!data::Load("rann_test_qr_ranks.csv", qrRanks, false, false))
FAIL("Cannot load dataset rann_test_qr_ranks.csv");
size_t numRounds = 100;
@@ -666,7 +666,7 @@ TEST_CASE("RAModelTest", "[KRANNTest]")
models[19] = RAModel(RAModel::TreeTypes::OCTREE, true);
arma::Mat<size_t> qrRanks;
if (!data::Load("rann_test_qr_ranks.csv", qrRanks, false, false)) // No transpose.
if (!data::Load("rann_test_qr_ranks.csv", qrRanks, false, false))
FAIL("Cannot load dataset rann_test_qr_ranks.csv");
for (size_t j = 0; j < 3; ++j)
+3 -3
View File
@@ -923,9 +923,9 @@ TEST_CASE("RNNCheckInputShapeTest", "[RecurrentNetworkTest]")
model.Add<LogSoftMax<> >();
std::string expectedMsg = "RNN<>::Train(): ";
expectedMsg += "the first layer of the network expects ";
expectedMsg += std::to_string(3) + " elements, ";
expectedMsg += "but the input has " + std::to_string(1) + " dimensions! ";
expectedMsg += "the first layer of the network expects ";
expectedMsg += std::to_string(3) + " elements, ";
expectedMsg += "but the input has " + std::to_string(1) + " dimensions! ";
StandardSGD opt(0.1, 1, input.n_cols /* 1 epoch */, -100);
+2 -1
View File
@@ -32,7 +32,8 @@ TEST_CASE("CheckSizeTest", "[SizeCheckTest]")
REQUIRE_NOTHROW(CheckSameSizes(data, secondLabels, "TestChecking"));
REQUIRE_NOTHROW(CheckSameSizes(data, (size_t) 30, "TestChecking"));
REQUIRE_NOTHROW(CheckSameSizes(data, (size_t) thirdLabels.n_cols, "TestChecking"));
REQUIRE_NOTHROW(CheckSameSizes(data, (size_t) thirdLabels.n_cols,
"TestChecking"));
}
/**