From fca53ed16d4ba590e503b3b56c60fb8813621ac8 Mon Sep 17 00:00:00 2001 From: NippunSharma Date: Wed, 10 Mar 2021 20:05:15 +0530 Subject: [PATCH 01/37] initial_commit --- .../bindings/python/mlpack/preprocess_json_params.py | 8 ++++++++ src/mlpack/bindings/python/mlpack/serialization.hpp | 12 ++++++++++++ src/mlpack/bindings/python/mlpack/serialization.pxd | 1 + src/mlpack/bindings/python/print_class_defn.hpp | 7 +++++++ src/mlpack/bindings/python/print_pyx.cpp | 2 +- 5 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 src/mlpack/bindings/python/mlpack/preprocess_json_params.py diff --git a/src/mlpack/bindings/python/mlpack/preprocess_json_params.py b/src/mlpack/bindings/python/mlpack/preprocess_json_params.py new file mode 100644 index 0000000000..001591a02c --- /dev/null +++ b/src/mlpack/bindings/python/mlpack/preprocess_json_params.py @@ -0,0 +1,8 @@ +def preprocess_params(params, return_dic=False): + params_decoded = params.decode("utf-8").replace("true", "True")\ + .replace("false", "False") + if return_dic: + dic = eval(params_decoded) + return params_decoded, dic + else: + return params_decoded diff --git a/src/mlpack/bindings/python/mlpack/serialization.hpp b/src/mlpack/bindings/python/mlpack/serialization.hpp index 879e559d07..df85aa5a2c 100644 --- a/src/mlpack/bindings/python/mlpack/serialization.hpp +++ b/src/mlpack/bindings/python/mlpack/serialization.hpp @@ -38,6 +38,18 @@ void SerializeIn(T* t, const std::string& str, const std::string& name) b(cereal::make_nvp(name.c_str(), *t)); } +template +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(); +} + } // namespace python } // namespace bindings } // namespace mlpack diff --git a/src/mlpack/bindings/python/mlpack/serialization.pxd b/src/mlpack/bindings/python/mlpack/serialization.pxd index 3df3306467..a8d5298a90 100644 --- a/src/mlpack/bindings/python/mlpack/serialization.pxd +++ b/src/mlpack/bindings/python/mlpack/serialization.pxd @@ -12,3 +12,4 @@ 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 \ No newline at end of file diff --git a/src/mlpack/bindings/python/print_class_defn.hpp b/src/mlpack/bindings/python/print_class_defn.hpp index 6ed4973951..cd2ee2c5c0 100644 --- a/src/mlpack/bindings/python/print_class_defn.hpp +++ b/src/mlpack/bindings/python/print_class_defn.hpp @@ -72,6 +72,9 @@ void PrintClassDefn( * def __getstate__(self): * return SerializeOut(self.modelptr, "") * + * def _params(self): + * return SerializeOutJSON(self.modelptr, "") + * * def __setstate__(self, state): * SerializeIn(self.modelptr, state, "") * @@ -92,6 +95,10 @@ void PrintClassDefn( std::cout << " return SerializeOut(self.modelptr, \"" << printedType << "\")" << std::endl; std::cout << std::endl; + std::cout << " def _params(self):" << std::endl; + std::cout << " return SerializeOutJSON(self.modelptr, \"" << printedType + << "\")" << std::endl; + std::cout << std::endl; std::cout << " def __setstate__(self, state):" << std::endl; std::cout << " SerializeIn(self.modelptr, state, \"" << printedType << "\")" << std::endl; diff --git a/src/mlpack/bindings/python/print_pyx.cpp b/src/mlpack/bindings/python/print_pyx.cpp index 6853c969da..3b8ef867cc 100644 --- a/src/mlpack/bindings/python/print_pyx.cpp +++ b/src/mlpack/bindings/python/print_pyx.cpp @@ -80,7 +80,7 @@ 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 serialization cimport SerializeIn, SerializeOut, SerializeOutJSON" << endl; cout << endl; cout << "import numpy as np" << endl; cout << "cimport numpy as np" << endl; From c7c51a8dbecae63997ad98b7bd2e74fc8d340752 Mon Sep 17 00:00:00 2001 From: NippunSharma Date: Wed, 10 Mar 2021 21:21:16 +0530 Subject: [PATCH 02/37] added to cmakelist --- src/mlpack/bindings/python/CMakeLists.txt | 1 + .../bindings/python/mlpack/preprocess_json_params.py | 3 ++- src/mlpack/bindings/python/print_class_defn.hpp | 8 ++++---- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/mlpack/bindings/python/CMakeLists.txt b/src/mlpack/bindings/python/CMakeLists.txt index c36a026590..c32edaaa24 100644 --- a/src/mlpack/bindings/python/CMakeLists.txt +++ b/src/mlpack/bindings/python/CMakeLists.txt @@ -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 diff --git a/src/mlpack/bindings/python/mlpack/preprocess_json_params.py b/src/mlpack/bindings/python/mlpack/preprocess_json_params.py index 001591a02c..2d5f764ae2 100644 --- a/src/mlpack/bindings/python/mlpack/preprocess_json_params.py +++ b/src/mlpack/bindings/python/mlpack/preprocess_json_params.py @@ -1,4 +1,5 @@ -def preprocess_params(params, return_dic=False): +def process_params(model, return_dic=False): + params = model.params() params_decoded = params.decode("utf-8").replace("true", "True")\ .replace("false", "False") if return_dic: diff --git a/src/mlpack/bindings/python/print_class_defn.hpp b/src/mlpack/bindings/python/print_class_defn.hpp index cd2ee2c5c0..5c436ff2ae 100644 --- a/src/mlpack/bindings/python/print_class_defn.hpp +++ b/src/mlpack/bindings/python/print_class_defn.hpp @@ -95,10 +95,6 @@ void PrintClassDefn( std::cout << " return SerializeOut(self.modelptr, \"" << printedType << "\")" << std::endl; std::cout << std::endl; - std::cout << " def _params(self):" << std::endl; - std::cout << " return SerializeOutJSON(self.modelptr, \"" << printedType - << "\")" << std::endl; - std::cout << std::endl; std::cout << " def __setstate__(self, state):" << std::endl; std::cout << " SerializeIn(self.modelptr, state, \"" << printedType << "\")" << std::endl; @@ -107,6 +103,10 @@ void PrintClassDefn( std::cout << " return (self.__class__, (), self.__getstate__())" << std::endl; std::cout << std::endl; + std::cout << " def params(self):" << std::endl; + std::cout << " return SerializeOutJSON(self.modelptr, \"" << printedType + << "\")" << std::endl; + std::cout << std::endl; } /** From 53402fdbc37a8a3c882be40b12de071f20b13363 Mon Sep 17 00:00:00 2001 From: NippunSharma Date: Thu, 15 Apr 2021 11:05:33 +0530 Subject: [PATCH 03/37] added preprocessing --- .../python/mlpack/preprocess_json_params.py | 111 +++++++++++++++++- 1 file changed, 106 insertions(+), 5 deletions(-) diff --git a/src/mlpack/bindings/python/mlpack/preprocess_json_params.py b/src/mlpack/bindings/python/mlpack/preprocess_json_params.py index 2d5f764ae2..1fb7227499 100644 --- a/src/mlpack/bindings/python/mlpack/preprocess_json_params.py +++ b/src/mlpack/bindings/python/mlpack/preprocess_json_params.py @@ -1,9 +1,110 @@ -def process_params(model, return_dic=False): +from random import randint +import numpy as np +import pprint + +def process_params(model, return_str=False, pretty_print=False): params = model.params() params_decoded = params.decode("utf-8").replace("true", "True")\ .replace("false", "False") - if return_dic: - dic = eval(params_decoded) - return params_decoded, dic + + # this is to handle same key names of "elem". + # same key values cannot exist in python dictionary, + # so I am replacing "elem" with random numbers. + str_to_find = '"elem":' + res = [i for i in range(len(params_decoded)) if\ + params_decoded.startswith(str_to_find, i)] + + # this variable keeps track of what random numbers are generated, + # to avoid same random numbers generated for two "elem" keys. + gen_nums = [] + + for i in range(len(res)): + random_num = random_with_N_digits(4) + + # keep generating until unique number is not found. + while(random_num in gen_nums): + random_num = random_with_N_digits(4) + + params_decoded = params_decoded[:res[i]] + '"{}":'.format(random_num) +\ + params_decoded[res[i]+len(str_to_find):] + + # now we can convert it to a python dictionary. + params_dic = eval(params_decoded) + + # remove "cereal_class_version". + scrub(params_dic, "cereal_class_version") + + # convert armadillo dictionary to numpy array + arma_to_np(params_dic) + + pp = pprint.PrettyPrinter() + + if pretty_print: + pp.pprint(params_dic) + + if return_str: + return params_dic, pp.pformat(params_dic) else: - return params_decoded + return params_dic + +def arma_to_np(obj): + """ + This function replaces the armadillo dictionary vector to + numpy array in the given dictionary. + """ + if isinstance(obj, dict): + for key in obj.keys(): + if isinstance(obj[key], dict): + # 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"]) + elem_keys = list(set(obj[key].keys()).difference(set(["n_rows", "n_cols", "vec_state"]))) + elems = [] + for elem in elem_keys: + elems.append(obj[key][elem]) + + if n_rows*n_cols != len(elems): + raise RuntimeError("Shape {}x{} not valid with number of elements {}" + .format(n_rows, n_cols, len(elems))) + + elems = np.array(elems).reshape(n_cols, n_rows).astype(float) + obj[key] = elems + 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: + pass + +def scrub(obj, bad_key): + """ + This function removes a certain key-value pair from the + given dictionary. + """ + if isinstance(obj, dict): + for key in list(obj.keys()): + if key == bad_key: + del obj[key] + else: + scrub(obj[key], bad_key) + elif isinstance(obj, list): + for i in range(len(obj)): + if obj[i] == bad_key: + del obj[i] + else: + scrub(obj[i], bad_key) + else: + pass + +def random_with_N_digits(n): + """ + Generates random N digit numbers. + """ + range_start = 10**(n-1) + range_end = (10**n)-1 + return randint(range_start, range_end) \ No newline at end of file From 9c5da70aa033b0c0e43f57ee52824e4cde425212 Mon Sep 17 00:00:00 2001 From: NippunSharma Date: Sat, 17 Apr 2021 21:08:29 +0530 Subject: [PATCH 04/37] added reversed processing --- .../python/mlpack/preprocess_json_params.py | 82 ++++++++++++++++++- .../bindings/python/mlpack/serialization.hpp | 8 ++ .../bindings/python/mlpack/serialization.pxd | 3 +- .../bindings/python/print_class_defn.hpp | 14 +++- src/mlpack/bindings/python/print_pyx.cpp | 2 +- 5 files changed, 99 insertions(+), 10 deletions(-) diff --git a/src/mlpack/bindings/python/mlpack/preprocess_json_params.py b/src/mlpack/bindings/python/mlpack/preprocess_json_params.py index 1fb7227499..209f817838 100644 --- a/src/mlpack/bindings/python/mlpack/preprocess_json_params.py +++ b/src/mlpack/bindings/python/mlpack/preprocess_json_params.py @@ -1,9 +1,11 @@ from random import randint import numpy as np +import json import pprint +from copy import deepcopy -def process_params(model, return_str=False, pretty_print=False): - params = model.params() +def process_params(model, return_str=False, pretty_print=False, remove_version=False): + params = model.get_params() params_decoded = params.decode("utf-8").replace("true", "True")\ .replace("false", "False") @@ -32,7 +34,8 @@ def process_params(model, return_str=False, pretty_print=False): params_dic = eval(params_decoded) # remove "cereal_class_version". - scrub(params_dic, "cereal_class_version") + if remove_version: + scrub(params_dic, "cereal_class_version") # convert armadillo dictionary to numpy array arma_to_np(params_dic) @@ -47,9 +50,80 @@ def process_params(model, return_str=False, pretty_print=False): else: return params_dic +def feed_params(model, params_dic): + """ + This function takes in a model and the parameters dictionary, + and sets the parameters of the model as the given parameters. + """ + # deepcopy to prevent changes to the user dictionary. + params_dic_copy = deepcopy(params_dic) + + # this list for keeping track of the random numbers generated to replace + # '"elem":' string, because python dictionaries cannot hold same keys. + rand_gen = [] + np_to_arma(params_dic_copy, rand_gen) + + # dumping to string. + params_str = json.dumps(params_dic_copy) + + # replacing random numbers with '"elem":' to match JSON given by cereal. + for rand_num in rand_gen: + params_str = params_str.replace('"{}":'.format(rand_num), '"elem":') + + # setting parameters to the model. + model.set_params(params_str.encode("utf-8")) + +def np_to_arma(obj, rand_gen): + """ + This function replaces a numpy array to json representation + of armadillo vector. This is reverse of "arma_to_np(obj)". + """ + if isinstance(obj, dict): + 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 = str(1),str(1) + + dic = dict() + + if len(obj[key].shape) == 1: + n_rows = obj[key].shape[0] + dic["vec_state"] = str(1) + elif len(obj[key].shape) == 2: + n_rows, n_cols = obj[key].shape + dic["vec_state"] = str(2) + else: + raise RuntimeError("Invalid number of dimensions in array {}".format(len(onj[key].shape))) + + dic["n_rows"] = str(n_cols) # implicit transpose + dic["n_cols"] = str(n_rows) # implicit transpose + + elems = obj[key].flatten().astype(float) + + # writing elements of vector with random generated keys, + # these keys will be replaced by '"elem":' in "feed_params()" function. + for elem in elems: + random_key = random_with_N_digits(4) + while(random_key in rand_gen): + random_key = random_with_N_digits(4) + rand_gen.append(random_key) + dic[str(random_key)] = elem + + obj[key] = dic + else: + np_to_arma(obj[key], rand_gen) + elif isinstance(obj, list): + for i in range(len(obj)): + np_to_arma(obj[i], rand_gen) + else: + pass + def arma_to_np(obj): """ - This function replaces the armadillo dictionary vector to + This function replaces the JSON representation of armadillo vector to numpy array in the given dictionary. """ if isinstance(obj, dict): diff --git a/src/mlpack/bindings/python/mlpack/serialization.hpp b/src/mlpack/bindings/python/mlpack/serialization.hpp index df85aa5a2c..15f837a2de 100644 --- a/src/mlpack/bindings/python/mlpack/serialization.hpp +++ b/src/mlpack/bindings/python/mlpack/serialization.hpp @@ -50,6 +50,14 @@ std::string SerializeOutJSON(T* t, const std::string& name) return oss.str(); } +template +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 diff --git a/src/mlpack/bindings/python/mlpack/serialization.pxd b/src/mlpack/bindings/python/mlpack/serialization.pxd index a8d5298a90..dc3998fb70 100644 --- a/src/mlpack/bindings/python/mlpack/serialization.pxd +++ b/src/mlpack/bindings/python/mlpack/serialization.pxd @@ -12,4 +12,5 @@ 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 \ No newline at end of file + string SerializeOutJSON[T](T* t, string name) nogil + void SerializeInJSON[T](T* t, string str, string name) nogil \ No newline at end of file diff --git a/src/mlpack/bindings/python/print_class_defn.hpp b/src/mlpack/bindings/python/print_class_defn.hpp index 5c436ff2ae..2f66adc241 100644 --- a/src/mlpack/bindings/python/print_class_defn.hpp +++ b/src/mlpack/bindings/python/print_class_defn.hpp @@ -72,14 +72,17 @@ void PrintClassDefn( * def __getstate__(self): * return SerializeOut(self.modelptr, "") * - * def _params(self): - * return SerializeOutJSON(self.modelptr, "") - * * def __setstate__(self, state): * SerializeIn(self.modelptr, state, "") * * def __reduce_ex__(self): * return (self.__class__, (), self.__getstate__()) + * + * def get_params(self): + * return SerializeOutJSON(self.modelptr, "") + * + * def set_params(self, state): + * SerializeInJSON(seld.modelptr, state, "") * @endcode */ std::cout << "cdef class " << strippedType << "Type:" << std::endl; @@ -103,9 +106,12 @@ void PrintClassDefn( std::cout << " return (self.__class__, (), self.__getstate__())" << std::endl; std::cout << std::endl; - std::cout << " def params(self):" << std::endl; + std::cout << " def get_params(self):" << std::endl; std::cout << " return SerializeOutJSON(self.modelptr, \"" << printedType << "\")" << std::endl; + std::cout << " def set_params(self, state):" << std::endl; + std::cout << " SerializeInJSON(self.modelptr, state, \"" << printedType + << "\")" << std::endl; std::cout << std::endl; } diff --git a/src/mlpack/bindings/python/print_pyx.cpp b/src/mlpack/bindings/python/print_pyx.cpp index 3b8ef867cc..edcdb66ac1 100644 --- a/src/mlpack/bindings/python/print_pyx.cpp +++ b/src/mlpack/bindings/python/print_pyx.cpp @@ -80,7 +80,7 @@ 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, SerializeOutJSON" << endl; + cout << "from serialization cimport SerializeIn, SerializeOut, SerializeOutJSON, SerializeInJSON" << endl; cout << endl; cout << "import numpy as np" << endl; cout << "cimport numpy as np" << endl; From 3f41561ef0d29f1e1aa3879d68fca8636b15f5f2 Mon Sep 17 00:00:00 2001 From: NippunSharma Date: Mon, 24 May 2021 14:59:40 +0530 Subject: [PATCH 05/37] changed way to handle same key values --- src/mlpack/bindings/python/CMakeLists.txt | 1 + .../python/mlpack/preprocess_json_params.py | 271 +++++++++++------- .../bindings/python/print_class_defn.hpp | 36 ++- src/mlpack/bindings/python/print_pyx.cpp | 1 + 4 files changed, 198 insertions(+), 111 deletions(-) diff --git a/src/mlpack/bindings/python/CMakeLists.txt b/src/mlpack/bindings/python/CMakeLists.txt index c32edaaa24..cf0066a132 100644 --- a/src/mlpack/bindings/python/CMakeLists.txt +++ b/src/mlpack/bindings/python/CMakeLists.txt @@ -203,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/) diff --git a/src/mlpack/bindings/python/mlpack/preprocess_json_params.py b/src/mlpack/bindings/python/mlpack/preprocess_json_params.py index 209f817838..dc42876223 100644 --- a/src/mlpack/bindings/python/mlpack/preprocess_json_params.py +++ b/src/mlpack/bindings/python/mlpack/preprocess_json_params.py @@ -1,124 +1,105 @@ +#!/usr/bin/env python + from random import randint import numpy as np import json import pprint from copy import deepcopy +from collections import OrderedDict -def process_params(model, return_str=False, pretty_print=False, remove_version=False): - params = model.get_params() - params_decoded = params.decode("utf-8").replace("true", "True")\ - .replace("false", "False") - - # this is to handle same key names of "elem". - # same key values cannot exist in python dictionary, - # so I am replacing "elem" with random numbers. - str_to_find = '"elem":' - res = [i for i in range(len(params_decoded)) if\ - params_decoded.startswith(str_to_find, i)] - - # this variable keeps track of what random numbers are generated, - # to avoid same random numbers generated for two "elem" keys. - gen_nums = [] - - for i in range(len(res)): - random_num = random_with_N_digits(4) - - # keep generating until unique number is not found. - while(random_num in gen_nums): - random_num = random_with_N_digits(4) - - params_decoded = params_decoded[:res[i]] + '"{}":'.format(random_num) +\ - params_decoded[res[i]+len(str_to_find):] - - # now we can convert it to a python dictionary. - params_dic = eval(params_decoded) - - # remove "cereal_class_version". - if remove_version: - scrub(params_dic, "cereal_class_version") - - # convert armadillo dictionary to numpy array - arma_to_np(params_dic) +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() - if pretty_print: - pp.pprint(params_dic) + params_dic = json.loads(params, object_pairs_hook=value_resolver) + + # remove "cereal_class_version". + cereal_class_version = [] # this stores the cereal_class_version value for all deleted pairs. + 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 feed_params(model, params_dic): +def process_params_in(model, params_dic): """ This function takes in a model and the parameters dictionary, - and sets the parameters of the model as the given parameters. + 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) - # this list for keeping track of the random numbers generated to replace - # '"elem":' string, because python dictionaries cannot hold same keys. - rand_gen = [] - np_to_arma(params_dic_copy, rand_gen) + # convert numpy to armadillo. + np_to_arma(params_dic_copy) + + 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. - params_str = json.dumps(params_dic_copy) + params_str = json.dumps(params_dic_copy, cls=restore_value) + return params_str - # replacing random numbers with '"elem":' to match JSON given by cereal. - for rand_num in rand_gen: - params_str = params_str.replace('"{}":'.format(rand_num), '"elem":') - - # setting parameters to the model. - model.set_params(params_str.encode("utf-8")) - -def np_to_arma(obj, rand_gen): +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, dict): + 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 = str(1),str(1) - - dic = dict() - - if len(obj[key].shape) == 1: - n_rows = obj[key].shape[0] - dic["vec_state"] = str(1) - elif len(obj[key].shape) == 2: - n_rows, n_cols = obj[key].shape - dic["vec_state"] = str(2) - else: - raise RuntimeError("Invalid number of dimensions in array {}".format(len(onj[key].shape))) + 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 - elems = obj[key].flatten().astype(float) - - # writing elements of vector with random generated keys, - # these keys will be replaced by '"elem":' in "feed_params()" function. - for elem in elems: - random_key = random_with_N_digits(4) - while(random_key in rand_gen): - random_key = random_with_N_digits(4) - rand_gen.append(random_key) - dic[str(random_key)] = elem + 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], rand_gen) + np_to_arma(obj[key]) elif isinstance(obj, list): for i in range(len(obj)): - np_to_arma(obj[i], rand_gen) + 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): @@ -126,25 +107,15 @@ def arma_to_np(obj): This function replaces the JSON representation of armadillo vector to numpy array in the given dictionary. """ - if isinstance(obj, dict): + if isinstance(obj, OrderedDict): for key in obj.keys(): - if isinstance(obj[key], dict): + 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"]) - elem_keys = list(set(obj[key].keys()).difference(set(["n_rows", "n_cols", "vec_state"]))) - elems = [] - for elem in elem_keys: - elems.append(obj[key][elem]) - - if n_rows*n_cols != len(elems): - raise RuntimeError("Shape {}x{} not valid with number of elements {}" - .format(n_rows, n_cols, len(elems))) - - elems = np.array(elems).reshape(n_cols, n_rows).astype(float) - obj[key] = elems + obj[key] = np.array(obj[key]["elem"]).reshape(n_cols, n_rows).astype(type(obj[key]["elem"][0])) # implicit transpose else: arma_to_np(obj[key]) else: @@ -153,32 +124,124 @@ def arma_to_np(obj): 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): +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, dict): + 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) + 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)): - if obj[i] == bad_key: - del obj[i] - else: - scrub(obj[i], bad_key) + 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 random_with_N_digits(n): - """ - Generates random N digit numbers. - """ - range_start = 10**(n-1) - range_end = (10**n)-1 - return randint(range_start, range_end) \ No newline at end of file +def value_resolver(pairs): + ''' + This function converts multiple "elem" occurences to a list. + 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. + 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): + 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 + temp.move_to_end(key, last=False) diff --git a/src/mlpack/bindings/python/print_class_defn.hpp b/src/mlpack/bindings/python/print_class_defn.hpp index 2f66adc241..ff1de4b26e 100644 --- a/src/mlpack/bindings/python/print_class_defn.hpp +++ b/src/mlpack/bindings/python/print_class_defn.hpp @@ -62,10 +62,12 @@ void PrintClassDefn( * @code * cdef class Type: * cdef * modelptr - * + * cdef public dict scrubbed_params + * * def __cinit__(self): * self.modelptr = new () - * + * self.scrubbed_params = dict() + * * def __dealloc__(self): * del self.modelptr * @@ -78,18 +80,29 @@ void PrintClassDefn( * def __reduce_ex__(self): * return (self.__class__, (), self.__getstate__()) * - * def get_params(self): + * def _get_cpp_params(self): * return SerializeOutJSON(self.modelptr, "") * - * def set_params(self, state): - * SerializeInJSON(seld.modelptr, state, "") + * def _set_cpp_params(self, state): + * SerializeInJSON(self.modelptr, state, "") + * + * 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; @@ -106,13 +119,22 @@ void PrintClassDefn( std::cout << " return (self.__class__, (), self.__getstate__())" << std::endl; std::cout << std::endl; - std::cout << " def get_params(self):" << std::endl; + std::cout << " def _get_cpp_params(self):" << std::endl; std::cout << " return SerializeOutJSON(self.modelptr, \"" << printedType << "\")" << std::endl; - std::cout << " def set_params(self, state):" << 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; } /** diff --git a/src/mlpack/bindings/python/print_pyx.cpp b/src/mlpack/bindings/python/print_pyx.cpp index edcdb66ac1..1878b68d20 100644 --- a/src/mlpack/bindings/python/print_pyx.cpp +++ b/src/mlpack/bindings/python/print_pyx.cpp @@ -80,6 +80,7 @@ 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 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; From 9f80053f5d6c1a1bdc5e7decbe701afc5eb6f83f Mon Sep 17 00:00:00 2001 From: NippunSharma Date: Mon, 24 May 2021 15:05:02 +0530 Subject: [PATCH 06/37] added license and added description --- .../python/mlpack/preprocess_json_params.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/mlpack/bindings/python/mlpack/preprocess_json_params.py b/src/mlpack/bindings/python/mlpack/preprocess_json_params.py index dc42876223..f83996b59c 100644 --- a/src/mlpack/bindings/python/mlpack/preprocess_json_params.py +++ b/src/mlpack/bindings/python/mlpack/preprocess_json_params.py @@ -1,5 +1,18 @@ #!/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) +This file defines the to_matrix() function, which can be used to convert Pandas +dataframes or other types of array-like objects to numpy ndarrays for use in +mlpack bindings. + +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. +""" from random import randint import numpy as np import json From 719f23ee71764d4ab56d27f71cef6fd40066626b Mon Sep 17 00:00:00 2001 From: NippunSharma Date: Mon, 24 May 2021 15:13:07 +0530 Subject: [PATCH 07/37] removed unused imports --- src/mlpack/bindings/python/mlpack/preprocess_json_params.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/mlpack/bindings/python/mlpack/preprocess_json_params.py b/src/mlpack/bindings/python/mlpack/preprocess_json_params.py index f83996b59c..10f2a90dda 100644 --- a/src/mlpack/bindings/python/mlpack/preprocess_json_params.py +++ b/src/mlpack/bindings/python/mlpack/preprocess_json_params.py @@ -13,7 +13,6 @@ 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. """ -from random import randint import numpy as np import json import pprint From 3307cf1921df875727dc6ac8b6ee7d27df0ce905 Mon Sep 17 00:00:00 2001 From: NippunSharma Date: Mon, 24 May 2021 18:44:22 +0530 Subject: [PATCH 08/37] added comments --- .../python/mlpack/preprocess_json_params.py | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/mlpack/bindings/python/mlpack/preprocess_json_params.py b/src/mlpack/bindings/python/mlpack/preprocess_json_params.py index 10f2a90dda..8128762959 100644 --- a/src/mlpack/bindings/python/mlpack/preprocess_json_params.py +++ b/src/mlpack/bindings/python/mlpack/preprocess_json_params.py @@ -31,6 +31,7 @@ def process_params_out(model, params, return_str=False): # for pretty printing. pp = pprint.PrettyPrinter() + # value_resolver defined later. params_dic = json.loads(params, object_pairs_hook=value_resolver) # remove "cereal_class_version". @@ -68,11 +69,12 @@ def process_params_in(model, 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. + # dumping to string. restore_value defined later. params_str = json.dumps(params_dic_copy, cls=restore_value) return params_str @@ -177,7 +179,8 @@ def scrub(obj, bad_key, values, full_paths, ref_path): def value_resolver(pairs): ''' - This function converts multiple "elem" occurences to a list. + This function converts multiple "elem" occurences to a list when + used with json.loads(). Eg: str({ vec_state: 1, @@ -211,7 +214,8 @@ def value_resolver(pairs): class restore_value(json.JSONEncoder): ''' - This is a custom encoder. + This is a custom encoder that converts a dictionary to + correct json format for ingesting in cereal. Eg: dict({ vec_state: 1, @@ -249,6 +253,10 @@ class restore_value(json.JSONEncoder): 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]: @@ -256,4 +264,5 @@ def insert_in_dic(dic, path, key, val): else: temp = temp[path[idx]] temp[key] = val + # moving key-value pair to the start. temp.move_to_end(key, last=False) From 872f868eb312591e24d7b470040e1cddf8b8183e Mon Sep 17 00:00:00 2001 From: NippunSharma Date: Mon, 24 May 2021 19:10:02 +0530 Subject: [PATCH 09/37] updated comment --- src/mlpack/bindings/python/mlpack/preprocess_json_params.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/mlpack/bindings/python/mlpack/preprocess_json_params.py b/src/mlpack/bindings/python/mlpack/preprocess_json_params.py index 8128762959..0b929c9387 100644 --- a/src/mlpack/bindings/python/mlpack/preprocess_json_params.py +++ b/src/mlpack/bindings/python/mlpack/preprocess_json_params.py @@ -4,9 +4,8 @@ preprocess_json_params.py: utility functions for json paramter preprocessing (see set_cpp_param() and get_cpp_param() methods in print_class_defn.hpp) -This file defines the to_matrix() function, which can be used to convert Pandas -dataframes or other types of array-like objects to numpy ndarrays for use in -mlpack bindings. +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 From 39b814887bad244c8855ffe19a74030bdcf5d944 Mon Sep 17 00:00:00 2001 From: Abhinav Anand Date: Wed, 26 May 2021 13:22:44 +0530 Subject: [PATCH 10/37] faster forward pass of mean pool layer --- src/mlpack/methods/ann/layer/mean_pooling.hpp | 25 ++++++++++++++++--- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/src/mlpack/methods/ann/layer/mean_pooling.hpp b/src/mlpack/methods/ann/layer/mean_pooling.hpp index 80daaa9951..57f621f682 100644 --- a/src/mlpack/methods/ann/layer/mean_pooling.hpp +++ b/src/mlpack/methods/ann/layer/mean_pooling.hpp @@ -160,12 +160,23 @@ class MeanPooling template void Pooling(const arma::Mat& input, arma::Mat& output) { + arma::mat inputPre = input; + size_t inRow = input.n_rows; + size_t inCol = input.n_cols; + + for(int i = 1; i < inCol; i++) + inputPre.col(i) += inputPre.col(i - 1); + + for(int i = 1; i < inRow; 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 +185,17 @@ 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)); + 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 / input.n_elem; } } } From 8b6bdfb5fcbdcf6ac29983764a6e8ba3a16042ff Mon Sep 17 00:00:00 2001 From: abh2k <41710346+abh2k@users.noreply.github.com> Date: Wed, 26 May 2021 20:08:03 +0530 Subject: [PATCH 11/37] Fixed kernalArea --- src/mlpack/methods/ann/layer/mean_pooling.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/mlpack/methods/ann/layer/mean_pooling.hpp b/src/mlpack/methods/ann/layer/mean_pooling.hpp index 57f621f682..8b066c6d3c 100644 --- a/src/mlpack/methods/ann/layer/mean_pooling.hpp +++ b/src/mlpack/methods/ann/layer/mean_pooling.hpp @@ -163,6 +163,7 @@ class MeanPooling arma::mat inputPre = input; size_t inRow = input.n_rows; size_t inCol = input.n_cols; + size_t kernalArea = kernelWidth * kernelHeight; for(int i = 1; i < inCol; i++) inputPre.col(i) += inputPre.col(i - 1); @@ -195,7 +196,7 @@ class MeanPooling if(colidx >= 1) val -= inputPre(rowEnd, colidx - 1); - output(i, j) = val / input.n_elem; + output(i, j) = val / kernalArea; } } } From bd95076c4e2295da009544c58a973abb3edbdc22 Mon Sep 17 00:00:00 2001 From: abh2k <41710346+abh2k@users.noreply.github.com> Date: Wed, 26 May 2021 20:10:52 +0530 Subject: [PATCH 12/37] Fixed kernal area if ceil = true --- src/mlpack/methods/ann/layer/mean_pooling.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/methods/ann/layer/mean_pooling.hpp b/src/mlpack/methods/ann/layer/mean_pooling.hpp index 8b066c6d3c..ce9252bc29 100644 --- a/src/mlpack/methods/ann/layer/mean_pooling.hpp +++ b/src/mlpack/methods/ann/layer/mean_pooling.hpp @@ -163,7 +163,6 @@ class MeanPooling arma::mat inputPre = input; size_t inRow = input.n_rows; size_t inCol = input.n_cols; - size_t kernalArea = kernelWidth * kernelHeight; for(int i = 1; i < inCol; i++) inputPre.col(i) += inputPre.col(i - 1); @@ -186,6 +185,7 @@ class MeanPooling if (colEnd > input.n_cols - 1) colEnd = input.n_cols - 1; + size_t kernalArea = (rowEnd - rowidx + 1) * (colEnd - colidx + 1); val += inputPre(rowEnd, colEnd); if(rowidx >= 1) { From 20a17d32fa07a669feba8818e0985c1f074836d6 Mon Sep 17 00:00:00 2001 From: abh2k <41710346+abh2k@users.noreply.github.com> Date: Thu, 27 May 2021 08:23:52 +0530 Subject: [PATCH 13/37] Style Fixes. --- src/mlpack/methods/ann/layer/mean_pooling.hpp | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/mlpack/methods/ann/layer/mean_pooling.hpp b/src/mlpack/methods/ann/layer/mean_pooling.hpp index ce9252bc29..31e12a1541 100644 --- a/src/mlpack/methods/ann/layer/mean_pooling.hpp +++ b/src/mlpack/methods/ann/layer/mean_pooling.hpp @@ -160,14 +160,12 @@ class MeanPooling template void Pooling(const arma::Mat& input, arma::Mat& output) { - arma::mat inputPre = input; - size_t inRow = input.n_rows; - size_t inCol = input.n_cols; + arma::Mt inputPre = input; - for(int i = 1; i < inCol; i++) + for(size_t i = 1; i < input.n_cols; ++i) inputPre.col(i) += inputPre.col(i - 1); - for(int i = 1; i < inRow; i++) + 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; @@ -185,15 +183,15 @@ class MeanPooling if (colEnd > input.n_cols - 1) colEnd = input.n_cols - 1; - size_t kernalArea = (rowEnd - rowidx + 1) * (colEnd - colidx + 1); + const kernalArea = (rowEnd - rowidx + 1) * (colEnd - colidx + 1); val += inputPre(rowEnd, colEnd); - if(rowidx >= 1) + if (rowidx >= 1) { - if(colidx >= 1) + if (colidx >= 1) val += inputPre(rowidx - 1, colidx - 1); val -= inputPre(rowidx - 1, colEnd); } - if(colidx >= 1) + if (colidx >= 1) val -= inputPre(rowEnd, colidx - 1); output(i, j) = val / kernalArea; From c884d1538e57f3407a2d6e6a1e3990c87d8b2d37 Mon Sep 17 00:00:00 2001 From: abh2k <41710346+abh2k@users.noreply.github.com> Date: Thu, 27 May 2021 08:58:04 +0530 Subject: [PATCH 14/37] Minor fix --- src/mlpack/methods/ann/layer/mean_pooling.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/methods/ann/layer/mean_pooling.hpp b/src/mlpack/methods/ann/layer/mean_pooling.hpp index 31e12a1541..eeb380f206 100644 --- a/src/mlpack/methods/ann/layer/mean_pooling.hpp +++ b/src/mlpack/methods/ann/layer/mean_pooling.hpp @@ -183,7 +183,7 @@ class MeanPooling if (colEnd > input.n_cols - 1) colEnd = input.n_cols - 1; - const kernalArea = (rowEnd - rowidx + 1) * (colEnd - colidx + 1); + const size_t kernalArea = (rowEnd - rowidx + 1) * (colEnd - colidx + 1); val += inputPre(rowEnd, colEnd); if (rowidx >= 1) { From b3a691c3ab197458d0aa63f9c18064576e0324bb Mon Sep 17 00:00:00 2001 From: abh2k <41710346+abh2k@users.noreply.github.com> Date: Thu, 27 May 2021 11:58:25 +0530 Subject: [PATCH 15/37] Update mean_pooling.hpp --- src/mlpack/methods/ann/layer/mean_pooling.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/methods/ann/layer/mean_pooling.hpp b/src/mlpack/methods/ann/layer/mean_pooling.hpp index eeb380f206..799f729884 100644 --- a/src/mlpack/methods/ann/layer/mean_pooling.hpp +++ b/src/mlpack/methods/ann/layer/mean_pooling.hpp @@ -160,7 +160,7 @@ class MeanPooling template void Pooling(const arma::Mat& input, arma::Mat& output) { - arma::Mt inputPre = input; + arma::Mat inputPre = input; for(size_t i = 1; i < input.n_cols; ++i) inputPre.col(i) += inputPre.col(i - 1); From b29c92b154a8eea64b187905f21b6dd671b4535c Mon Sep 17 00:00:00 2001 From: Nippun Sharma <53967069+NippunSharma@users.noreply.github.com> Date: Thu, 27 May 2021 18:06:09 +0530 Subject: [PATCH 16/37] added doc --- src/mlpack/bindings/python/print_type_doc_impl.hpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/mlpack/bindings/python/print_type_doc_impl.hpp b/src/mlpack/bindings/python/print_type_doc_impl.hpp index 9648d9f580..a154e7eee9 100644 --- a/src/mlpack/bindings/python/print_type_doc_impl.hpp +++ b/src/mlpack/bindings/python/print_type_doc_impl.hpp @@ -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 using 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. The user can inspect the " + "parameters as well change the parameter values in the dictionary " + "(without deleting any keys) and pass that back into the model " + "using the set_cpp_params() method."; } } // namespace python From 00e70ca799e3c667d66c2bd00a016386b39cae1a Mon Sep 17 00:00:00 2001 From: Nippun Sharma <53967069+NippunSharma@users.noreply.github.com> Date: Thu, 27 May 2021 18:06:33 +0530 Subject: [PATCH 17/37] Update src/mlpack/bindings/python/mlpack/preprocess_json_params.py Co-authored-by: Ryan Curtin --- src/mlpack/bindings/python/mlpack/preprocess_json_params.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/bindings/python/mlpack/preprocess_json_params.py b/src/mlpack/bindings/python/mlpack/preprocess_json_params.py index 0b929c9387..5ce0e3887d 100644 --- a/src/mlpack/bindings/python/mlpack/preprocess_json_params.py +++ b/src/mlpack/bindings/python/mlpack/preprocess_json_params.py @@ -257,7 +257,7 @@ def insert_in_dic(dic, path, key, val): after following a particular path. ''' temp = dic[path[0]] - for idx in range(1,len(path)): + for idx in range(1, len(path)): if "listidx_" in path[idx]: temp = temp[int(path[idx].replace("listidx_", ""))] else: From c054b86486a4e4e24a31869b55ecbf3f19736a2c Mon Sep 17 00:00:00 2001 From: Nippun Sharma <53967069+NippunSharma@users.noreply.github.com> Date: Thu, 27 May 2021 18:06:42 +0530 Subject: [PATCH 18/37] Update src/mlpack/bindings/python/mlpack/preprocess_json_params.py Co-authored-by: Ryan Curtin --- src/mlpack/bindings/python/mlpack/preprocess_json_params.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/bindings/python/mlpack/preprocess_json_params.py b/src/mlpack/bindings/python/mlpack/preprocess_json_params.py index 5ce0e3887d..5504940d21 100644 --- a/src/mlpack/bindings/python/mlpack/preprocess_json_params.py +++ b/src/mlpack/bindings/python/mlpack/preprocess_json_params.py @@ -74,7 +74,7 @@ def process_params_in(model, params_dic): 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) + params_str = json.dumps(params_dic_copy, cls=restore_value) return params_str def np_to_arma(obj): From 8779900b6ebbfb0229568a0df189c8b5c535fc17 Mon Sep 17 00:00:00 2001 From: Nippun Sharma <53967069+NippunSharma@users.noreply.github.com> Date: Thu, 27 May 2021 18:07:09 +0530 Subject: [PATCH 19/37] added new line --- src/mlpack/bindings/python/mlpack/serialization.pxd | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/mlpack/bindings/python/mlpack/serialization.pxd b/src/mlpack/bindings/python/mlpack/serialization.pxd index dc3998fb70..b82c9e73a5 100644 --- a/src/mlpack/bindings/python/mlpack/serialization.pxd +++ b/src/mlpack/bindings/python/mlpack/serialization.pxd @@ -13,4 +13,5 @@ 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 \ No newline at end of file + void SerializeInJSON[T](T* t, string str, string name) nogil + From 99c2d40a6ab7b4aacf3cf237f7624867aad4fcd2 Mon Sep 17 00:00:00 2001 From: Nippun Sharma <53967069+NippunSharma@users.noreply.github.com> Date: Thu, 27 May 2021 18:17:59 +0530 Subject: [PATCH 20/37] wrapped lines to 80 chars --- .../python/mlpack/preprocess_json_params.py | 46 ++++++++++++------- 1 file changed, 30 insertions(+), 16 deletions(-) diff --git a/src/mlpack/bindings/python/mlpack/preprocess_json_params.py b/src/mlpack/bindings/python/mlpack/preprocess_json_params.py index 5504940d21..cd87ae4bc7 100644 --- a/src/mlpack/bindings/python/mlpack/preprocess_json_params.py +++ b/src/mlpack/bindings/python/mlpack/preprocess_json_params.py @@ -25,7 +25,8 @@ def process_params_out(model, params, return_str=False): 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. + 3) return_str (bool) - if True then a pretty string version of the + params is returned. ''' # for pretty printing. pp = pprint.PrettyPrinter() @@ -34,14 +35,16 @@ def process_params_out(model, params, return_str=False): params_dic = json.loads(params, object_pairs_hook=value_resolver) # remove "cereal_class_version". - cereal_class_version = [] # this stores the cereal_class_version value for all deleted pairs. + # 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' 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) + 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"] = { @@ -112,7 +115,8 @@ def np_to_arma(obj): 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. + # we cannot recurse further if we do not have a + # dictionary or list object, so just pass. pass def arma_to_np(obj): @@ -128,7 +132,9 @@ def arma_to_np(obj): if "vec_state" in obj[key].keys(): n_rows = int(obj[key]["n_rows"]) n_cols = int(obj[key]["n_cols"]) - obj[key] = np.array(obj[key]["elem"]).reshape(n_cols, n_rows).astype(type(obj[key]["elem"][0])) # implicit transpose + # 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: @@ -137,7 +143,8 @@ def arma_to_np(obj): 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. + # 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): @@ -148,10 +155,12 @@ def scrub(obj, bad_key, values, full_paths, ref_path): 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. + (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()): @@ -238,13 +247,18 @@ class restore_value(json.JSONEncoder): 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") + 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 += ', ' + 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()) + 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)) From a0ae1ae7e0c8537be301d82d2d7341990fe3bf27 Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Thu, 27 May 2021 16:51:42 +0200 Subject: [PATCH 21/37] Clean old no longer used download var for ensmallen and stb Signed-off-by: Omar Shrit --- CMakeLists.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b314b0f5ce..71b5c0d8d5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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) From a916ac4d45c53665529c5e592827f53760ad129e Mon Sep 17 00:00:00 2001 From: Omar Shrit Date: Thu, 27 May 2021 23:23:23 +0200 Subject: [PATCH 22/37] Remove the variables from documenatations and README Signed-off-by: Omar Shrit --- README.md | 2 -- doc/guide/build.hpp | 3 --- 2 files changed, 5 deletions(-) diff --git a/README.md b/README.md index 16d6e5a4ab..f7000edef0 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/doc/guide/build.hpp b/doc/guide/build.hpp index a1ce7dfe31..ca48677cf0 100644 --- a/doc/guide/build.hpp +++ b/doc/guide/build.hpp @@ -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 From 0bed1fec961b047d315c690d46ea52deddc1afff Mon Sep 17 00:00:00 2001 From: abh2k <41710346+abh2k@users.noreply.github.com> Date: Fri, 28 May 2021 08:46:31 +0530 Subject: [PATCH 23/37] Apply suggestions from code review Co-authored-by: Marcus Edel --- src/mlpack/methods/ann/layer/mean_pooling.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mlpack/methods/ann/layer/mean_pooling.hpp b/src/mlpack/methods/ann/layer/mean_pooling.hpp index 799f729884..2480a9525f 100644 --- a/src/mlpack/methods/ann/layer/mean_pooling.hpp +++ b/src/mlpack/methods/ann/layer/mean_pooling.hpp @@ -162,10 +162,10 @@ class MeanPooling { arma::Mat inputPre = input; - for(size_t i = 1; i < input.n_cols; ++i) + 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) + 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; From 2ca058b3a73acd5c2f5f10448bb6a7b6060f5f78 Mon Sep 17 00:00:00 2001 From: Nippun Sharma <53967069+NippunSharma@users.noreply.github.com> Date: Fri, 28 May 2021 09:59:14 +0530 Subject: [PATCH 24/37] added to history --- HISTORY.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/HISTORY.md b/HISTORY.md index 2f7aab9538..51583448ac 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,5 +1,7 @@ ### mlpack ?.?.? ###### ????-??-?? + * Added dict-style inspection of mlpack models in python bindings (#2868). + * Added warm start feature to Random Forest (#2881); this feature is accessible from mlpack's bindings to different languages. From b190489ede4ae531ab0596bb76858fc5d0befbde Mon Sep 17 00:00:00 2001 From: Nippun Sharma <53967069+NippunSharma@users.noreply.github.com> Date: Wed, 2 Jun 2021 00:14:25 +0530 Subject: [PATCH 25/37] Update src/mlpack/bindings/python/print_type_doc_impl.hpp Co-authored-by: Ryan Curtin --- src/mlpack/bindings/python/print_type_doc_impl.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/bindings/python/print_type_doc_impl.hpp b/src/mlpack/bindings/python/print_type_doc_impl.hpp index a154e7eee9..cbcb129246 100644 --- a/src/mlpack/bindings/python/print_type_doc_impl.hpp +++ b/src/mlpack/bindings/python/print_type_doc_impl.hpp @@ -157,7 +157,7 @@ std::string PrintTypeDoc( "and internally holds a pointer to C++ memory containing the mlpack " "model. This model pointer has 2 methods using 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 " + "The `get_cpp_params()` method returns a python ordered dictionary that " "contains all the parameters of the model. The user can inspect the " "parameters as well change the parameter values in the dictionary " "(without deleting any keys) and pass that back into the model " From d26b744ed56ff56f54a6d3c896ef2f32c6c88669 Mon Sep 17 00:00:00 2001 From: Nippun Sharma <53967069+NippunSharma@users.noreply.github.com> Date: Wed, 2 Jun 2021 00:14:34 +0530 Subject: [PATCH 26/37] Update src/mlpack/bindings/python/print_type_doc_impl.hpp Co-authored-by: Ryan Curtin --- src/mlpack/bindings/python/print_type_doc_impl.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/mlpack/bindings/python/print_type_doc_impl.hpp b/src/mlpack/bindings/python/print_type_doc_impl.hpp index cbcb129246..767947807b 100644 --- a/src/mlpack/bindings/python/print_type_doc_impl.hpp +++ b/src/mlpack/bindings/python/print_type_doc_impl.hpp @@ -161,7 +161,6 @@ std::string PrintTypeDoc( "contains all the parameters of the model. The user can inspect the " "parameters as well change the parameter values in the dictionary " "(without deleting any keys) and pass that back into the model " - "using the set_cpp_params() method."; } } // namespace python From 297961a78c859ed05d9b5419a49ac0aad58b96fa Mon Sep 17 00:00:00 2001 From: Nippun Sharma <53967069+NippunSharma@users.noreply.github.com> Date: Wed, 2 Jun 2021 00:14:52 +0530 Subject: [PATCH 27/37] Update src/mlpack/bindings/python/print_type_doc_impl.hpp Co-authored-by: Ryan Curtin --- src/mlpack/bindings/python/print_type_doc_impl.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/bindings/python/print_type_doc_impl.hpp b/src/mlpack/bindings/python/print_type_doc_impl.hpp index 767947807b..0c52f1d481 100644 --- a/src/mlpack/bindings/python/print_type_doc_impl.hpp +++ b/src/mlpack/bindings/python/print_type_doc_impl.hpp @@ -155,7 +155,7 @@ 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. This model pointer has 2 methods using which the parameters " + "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. The user can inspect the " From 41024f6f7f188cf53854b574cc8b0db02d6e8f0c Mon Sep 17 00:00:00 2001 From: Nippun Sharma <53967069+NippunSharma@users.noreply.github.com> Date: Wed, 2 Jun 2021 00:15:11 +0530 Subject: [PATCH 28/37] Update src/mlpack/bindings/python/print_type_doc_impl.hpp Co-authored-by: Ryan Curtin --- src/mlpack/bindings/python/print_type_doc_impl.hpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/mlpack/bindings/python/print_type_doc_impl.hpp b/src/mlpack/bindings/python/print_type_doc_impl.hpp index 0c52f1d481..c062e9c7e1 100644 --- a/src/mlpack/bindings/python/print_type_doc_impl.hpp +++ b/src/mlpack/bindings/python/print_type_doc_impl.hpp @@ -158,9 +158,10 @@ std::string PrintTypeDoc( "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. The user can inspect the " - "parameters as well change the parameter values in the dictionary " - "(without deleting any keys) and pass that back into the model " + "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 From aaa1a47259f08b5cff4c9fdae82d95e7bff1e501 Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Tue, 1 Jun 2021 19:15:10 -0400 Subject: [PATCH 29/37] Better handling of tree resetting for HoeffdingTree. --- .../hoeffding_trees/hoeffding_tree.hpp | 42 ++- .../hoeffding_trees/hoeffding_tree_impl.hpp | 291 ++++++++++-------- 2 files changed, 196 insertions(+), 137 deletions(-) diff --git a/src/mlpack/methods/hoeffding_trees/hoeffding_tree.hpp b/src/mlpack/methods/hoeffding_trees/hoeffding_tree.hpp index b58d97a423..546d573d34 100644 --- a/src/mlpack/methods/hoeffding_trees/hoeffding_tree.hpp +++ b/src/mlpack/methods/hoeffding_trees/hoeffding_tree.hpp @@ -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,20 +183,31 @@ 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. * * @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. */ template void Train(const MatType& data, const arma::Row& labels, - const bool batchTraining = true); + const bool batchTraining = true, + const bool resetTree = false); /** * 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`. */ template void Train(const MatType& data, @@ -205,7 +216,8 @@ class HoeffdingTree const bool batchTraining = true); /** - * 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 +391,24 @@ class HoeffdingTree typename NumericSplitType::SplitInfo numericSplit; //! If the split has occurred, these are the children. std::vector children; + + /** + * Perform training (typically after a reset, but not necessarily). This + * assumes datasetInfo and dimensionMappings are set correctly. + */ + template + void TrainInternal(const MatType& data, + const arma::Row& labels, + const bool batchTraining); + + /** + * Reset the tree. This assumes datasetInfo is set correctly. + */ + void ResetTree( + const CategoricalSplitType& categoricalSplitIn = + CategoricalSplitType(0, 0), + const NumericSplitType& numericSplitIn = + NumericSplitType(0)); }; } // namespace tree diff --git a/src/mlpack/methods/hoeffding_trees/hoeffding_tree_impl.hpp b/src/mlpack/methods/hoeffding_trees/hoeffding_tree_impl.hpp index f79b0eb027..848824c15b 100644 --- a/src/mlpack/methods/hoeffding_trees/hoeffding_tree_impl.hpp +++ b/src/mlpack/methods/hoeffding_trees/hoeffding_tree_impl.hpp @@ -28,7 +28,7 @@ HoeffdingTree< NumericSplitType, CategoricalSplitType >::HoeffdingTree(const MatType& data, - const data::DatasetInfo& datasetInfo, + const data::DatasetInfo& datasetInfoIn, const arma::Row& labels, const size_t numClasses, const bool batchTraining, @@ -39,15 +39,14 @@ HoeffdingTree< const CategoricalSplitType& categoricalSplitIn, const NumericSplitType& numericSplitIn) : - dimensionMappings(new std::unordered_map>()), - 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( - datasetInfo.NumMappings(i), numClasses, categoricalSplitIn)); - (*dimensionMappings)[i] = std::make_pair(data::Datatype::categorical, - categoricalSplits.size() - 1); - } - else - { - numericSplits.push_back(NumericSplitType(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( - datasetInfo.NumMappings(i), numClasses, categoricalSplitIn)); - (*dimensionMappings)[i] = std::make_pair(data::Datatype::categorical, - categoricalSplits.size() - 1); - } - else - { - numericSplits.push_back(NumericSplitType(numClasses, - numericSplitIn)); - (*dimensionMappings)[i] = std::make_pair(data::Datatype::numeric, - numericSplits.size() - 1); - } - } + ResetTree(categoricalSplitIn, numericSplitIn); } else { @@ -381,71 +348,26 @@ void HoeffdingTree< CategoricalSplitType >::Train(const MatType& data, const arma::Row& labels, - const bool batchTraining) + const bool batchTraining, + const bool resetTree) { - 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()) { - // 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 indices(children.size(), arma::uvec(data.n_cols)); - arma::Col counts = - arma::zeros>(children.size()); + // Set the number of classes correctly. + numClasses = 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 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. @@ -468,40 +390,13 @@ void HoeffdingTree< datasetInfo = &info; ownsInfo = false; - // Generate mappings. - if (ownsMappings) - delete dimensionMappings; + // Set the number of classes correctly. + numClasses = arma::max(labels) + 1; - const CategoricalSplitType categoricalSplitIn(0, 0); - const NumericSplitType numericSplitIn(0); - - dimensionMappings = - new std::unordered_map>(); - for (size_t i = 0; i < datasetInfo->Dimensionality(); ++i) - { - if (datasetInfo->Type(i) == data::Datatype::categorical) - { - categoricalSplits.push_back(CategoricalSplitType( - datasetInfo->NumMappings(i), numClasses, categoricalSplitIn)); - (*dimensionMappings)[i] = std::make_pair(data::Datatype::categorical, - categoricalSplits.size() - 1); - } - else - { - numericSplits.push_back(NumericSplitType(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 +931,140 @@ void HoeffdingTree< } } +template< + typename FitnessFunction, + template class NumericSplitType, + template class CategoricalSplitType +> +template +void HoeffdingTree< + FitnessFunction, + NumericSplitType, + CategoricalSplitType +>::TrainInternal(const MatType& data, + const arma::Row& 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 indices(children.size(), arma::uvec(data.n_cols)); + arma::Col counts = + arma::zeros>(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 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 class NumericSplitType, + template class CategoricalSplitType +> +void HoeffdingTree< + FitnessFunction, + NumericSplitType, + CategoricalSplitType +>::ResetTree(const CategoricalSplitType& categoricalSplitIn, + const NumericSplitType& numericSplitIn) +{ + // Generate mappings. + if (ownsMappings) + delete dimensionMappings; + + categoricalSplits.clear(); + numericSplits.clear(); + + dimensionMappings = + new std::unordered_map>(); + ownsMappings = true; + for (size_t i = 0; i < datasetInfo->Dimensionality(); ++i) + { + if (datasetInfo->Type(i) == data::Datatype::categorical) + { + categoricalSplits.push_back(CategoricalSplitType( + datasetInfo->NumMappings(i), numClasses, categoricalSplitIn)); + (*dimensionMappings)[i] = std::make_pair(data::Datatype::categorical, + categoricalSplits.size() - 1); + } + else + { + numericSplits.push_back(NumericSplitType(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::SplitInfo(0); + numericSplit = typename NumericSplitType::SplitInfo(); +} + } // namespace tree } // namespace mlpack From 6461067aacfecd8c7d8d85f861ea2ccdb186deb7 Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Tue, 1 Jun 2021 19:15:45 -0400 Subject: [PATCH 30/37] Add tests for using HoeffdingTrees with an empty constructor. --- src/mlpack/tests/hoeffding_tree_test.cpp | 49 +++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/src/mlpack/tests/hoeffding_tree_test.cpp b/src/mlpack/tests/hoeffding_tree_test.cpp index de7db90443..3b3a7c902f 100644 --- a/src/mlpack/tests/hoeffding_tree_test.cpp +++ b/src/mlpack/tests/hoeffding_tree_test.cpp @@ -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,50 @@ TEST_CASE("HoeffdingTreeModelSerializationTest", "[HoeffdingTreeTest]") } } } + +TEST_CASE("HoeffdingTreeEmptyConstructorTrainTest", "[HoeffdingTreeTest]") +{ + // Generate data. + arma::mat data(5, 1000, arma::fill::randu); + // Generate labels. + arma::Row 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. + data = arma::mat(4, 3000); + labels.set_size(3000); + data::DatasetInfo info(4); // All features are numeric, except the fourth. + info.MapString("0", 3); + for (size_t i = 0; i < 3000; i += 3) + { + data(0, i) = mlpack::math::Random(); + data(1, i) = mlpack::math::Random(); + data(2, i) = mlpack::math::Random(); + data(3, i) = 0.0; + labels[i] = 0; + + data(0, i + 1) = mlpack::math::Random(); + data(1, i + 1) = mlpack::math::Random() - 1.0; + data(2, i + 1) = mlpack::math::Random() + 0.5; + data(3, i + 1) = 0.0; + labels[i + 1] = 2; + + data(0, i + 2) = mlpack::math::Random(); + data(1, i + 2) = mlpack::math::Random() + 1.0; + data(2, i + 2) = mlpack::math::Random() + 0.8; + data(3, i + 2) = 0.0; + labels[i + 2] = 1; + } + + // Ensure we can train without throwing an exception. + REQUIRE_NOTHROW(ht.Train(data, info, labels)); +} From 052a0216d9da9bb17d190e92e2c6234d33e15851 Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Tue, 1 Jun 2021 19:15:56 -0400 Subject: [PATCH 31/37] Update HISTORY. --- HISTORY.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/HISTORY.md b/HISTORY.md index 9eec0b93e5..b4b523a3a6 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -54,6 +54,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. + ### mlpack 3.4.2 ###### 2020-10-26 * Added Mean Absolute Percentage Error. From 54402ee5ac9bf2588b6a1218be752fe2ecf0aa09 Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Wed, 2 Jun 2021 17:53:49 -0400 Subject: [PATCH 32/37] Add numClasses argument to HoeffdingTree training methods. --- .../methods/decision_tree/decision_tree.hpp | 8 ++-- .../hoeffding_trees/hoeffding_tree.hpp | 18 +++++++-- .../hoeffding_trees/hoeffding_tree_impl.hpp | 13 +++--- src/mlpack/tests/hoeffding_tree_test.cpp | 40 ++++++++++--------- 4 files changed, 49 insertions(+), 30 deletions(-) diff --git a/src/mlpack/methods/decision_tree/decision_tree.hpp b/src/mlpack/methods/decision_tree/decision_tree.hpp index 9afc4191b8..df81dc61ad 100644 --- a/src/mlpack/methods/decision_tree/decision_tree.hpp +++ b/src/mlpack/methods/decision_tree/decision_tree.hpp @@ -203,10 +203,10 @@ class DecisionTree : typename std::remove_reference::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. diff --git a/src/mlpack/methods/hoeffding_trees/hoeffding_tree.hpp b/src/mlpack/methods/hoeffding_trees/hoeffding_tree.hpp index 546d573d34..2c58dfa787 100644 --- a/src/mlpack/methods/hoeffding_trees/hoeffding_tree.hpp +++ b/src/mlpack/methods/hoeffding_trees/hoeffding_tree.hpp @@ -188,18 +188,22 @@ class HoeffdingTree * * 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. + * 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 void Train(const MatType& data, const arma::Row& labels, const bool batchTraining = true, - const bool resetTree = false); + const bool resetTree = false, + const size_t numClasses = 0); /** * Train on a set of points, either in streaming mode or in batch mode, with @@ -208,12 +212,20 @@ class HoeffdingTree * 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 void Train(const MatType& data, const data::DatasetInfo& info, const arma::Row& 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. The tree diff --git a/src/mlpack/methods/hoeffding_trees/hoeffding_tree_impl.hpp b/src/mlpack/methods/hoeffding_trees/hoeffding_tree_impl.hpp index 848824c15b..77d6dc5b3c 100644 --- a/src/mlpack/methods/hoeffding_trees/hoeffding_tree_impl.hpp +++ b/src/mlpack/methods/hoeffding_trees/hoeffding_tree_impl.hpp @@ -349,11 +349,13 @@ void HoeffdingTree< >::Train(const MatType& data, const arma::Row& labels, const bool batchTraining, - const bool resetTree) + const bool resetTree, + const size_t numClassesIn) { // 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()) + if (resetTree || data.n_rows != datasetInfo->Dimensionality() || + numClassesIn != 0) { // Create a new datasetInfo, which assumes that all features are numeric. if (ownsInfo) @@ -362,7 +364,7 @@ void HoeffdingTree< ownsInfo = true; // Set the number of classes correctly. - numClasses = arma::max(labels) + 1; + numClasses = (numClassesIn != 0) ? numClassesIn : arma::max(labels) + 1; ResetTree(); } @@ -382,7 +384,8 @@ void HoeffdingTree< >::Train(const MatType& data, const data::DatasetInfo& info, const arma::Row& labels, - const bool batchTraining) + const bool batchTraining, + const size_t numClassesIn) { // Take over new DatasetInfo. if (ownsInfo) @@ -391,7 +394,7 @@ void HoeffdingTree< ownsInfo = false; // Set the number of classes correctly. - numClasses = arma::max(labels) + 1; + numClasses = (numClassesIn != 0) ? numClassesIn : arma::max(labels) + 1; ResetTree(); diff --git a/src/mlpack/tests/hoeffding_tree_test.cpp b/src/mlpack/tests/hoeffding_tree_test.cpp index 3b3a7c902f..02db5e5c24 100644 --- a/src/mlpack/tests/hoeffding_tree_test.cpp +++ b/src/mlpack/tests/hoeffding_tree_test.cpp @@ -1494,31 +1494,35 @@ TEST_CASE("HoeffdingTreeEmptyConstructorTrainTest", "[HoeffdingTreeTest]") REQUIRE_NOTHROW(ht.Train(data, labels)); // Now, create a categorical dataset and retrain. - data = arma::mat(4, 3000); - labels.set_size(3000); + arma::mat data2 = arma::mat(4, 3000); + arma::Row labels2(3000); data::DatasetInfo info(4); // All features are numeric, except the fourth. info.MapString("0", 3); for (size_t i = 0; i < 3000; i += 3) { - data(0, i) = mlpack::math::Random(); - data(1, i) = mlpack::math::Random(); - data(2, i) = mlpack::math::Random(); - data(3, i) = 0.0; - labels[i] = 0; + 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; - data(0, i + 1) = mlpack::math::Random(); - data(1, i + 1) = mlpack::math::Random() - 1.0; - data(2, i + 1) = mlpack::math::Random() + 0.5; - data(3, i + 1) = 0.0; - labels[i + 1] = 2; + 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; - data(0, i + 2) = mlpack::math::Random(); - data(1, i + 2) = mlpack::math::Random() + 1.0; - data(2, i + 2) = mlpack::math::Random() + 0.8; - data(3, i + 2) = 0.0; - labels[i + 2] = 1; + 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(data, info, labels)); + 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)); } From 639f1d3e4e84d3e515354a448291e453b0b7a585 Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Wed, 2 Jun 2021 17:54:09 -0400 Subject: [PATCH 33/37] Update HISTORY. --- HISTORY.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/HISTORY.md b/HISTORY.md index b4b523a3a6..4409dbcfb2 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -55,7 +55,7 @@ `make mlpack_test` to build the tests. * Fixes to `HoeffdingTree`: ensure that training still works when empty - constructor is used. + constructor is used (#2964). ### mlpack 3.4.2 ###### 2020-10-26 From bfde132ca75044fdcf01c0c5f4c8b39fcbbb26b5 Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Wed, 2 Jun 2021 18:08:49 -0400 Subject: [PATCH 34/37] Fix style issues (hopefully). --- src/mlpack/bindings/python/print_pyx.cpp | 3 +- src/mlpack/core/cv/cv_base_impl.hpp | 4 +-- src/mlpack/core/util/mlpack_main.hpp | 4 +-- src/mlpack/core/util/size_checks.hpp | 4 +-- .../simple_residue_termination.hpp | 2 +- .../activation_functions/silu_function.hpp | 30 ++++++++++--------- .../tanh_exponential_function.hpp | 5 ++-- src/mlpack/methods/ann/ffn_impl.hpp | 18 +++++------ .../methods/ann/layer/atrous_convolution.hpp | 10 ++++--- src/mlpack/methods/ann/layer/base_layer.hpp | 4 +-- .../methods/ann/layer/concatenate_impl.hpp | 8 ++--- .../ann/layer/flatten_t_swish_impl.hpp | 12 ++++---- src/mlpack/methods/ann/layer/gru.hpp | 2 +- src/mlpack/methods/ann/layer/isrlu.hpp | 1 - src/mlpack/methods/ann/layer/linear.hpp | 2 +- src/mlpack/methods/ann/layer/lp_pooling.hpp | 10 ++++--- src/mlpack/methods/ann/layer/lstm.hpp | 5 +++- src/mlpack/methods/ann/layer/lstm_impl.hpp | 12 ++++---- src/mlpack/methods/ann/layer/mean_pooling.hpp | 14 +++++---- .../methods/ann/layer/pixel_shuffle_impl.hpp | 10 +++---- .../methods/ann/layer/recurrent_impl.hpp | 29 ++++++++++-------- .../methods/ann/layer/reparametrization.hpp | 8 ++--- .../ann/layer/reparametrization_impl.hpp | 18 +++++------ .../binary_cross_entropy_loss_impl.hpp | 2 +- .../ann/loss_functions/huber_loss_impl.hpp | 14 +++++---- .../ann/loss_functions/kl_divergence_impl.hpp | 8 +++-- .../sigmoid_cross_entropy_error.hpp | 6 ++-- .../loss_functions/triplet_margin_loss.hpp | 2 +- .../triplet_margin_loss_impl.hpp | 9 ++++-- src/mlpack/methods/ann/rnn_impl.hpp | 15 ++++------ 30 files changed, 145 insertions(+), 126 deletions(-) diff --git a/src/mlpack/bindings/python/print_pyx.cpp b/src/mlpack/bindings/python/print_pyx.cpp index 6853c969da..d2f03a8f4c 100644 --- a/src/mlpack/bindings/python/print_pyx.cpp +++ b/src/mlpack/bindings/python/print_pyx.cpp @@ -230,7 +230,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; diff --git a/src/mlpack/core/cv/cv_base_impl.hpp b/src/mlpack/core/cv/cv_base_impl.hpp index 0da9f8f4fa..0a3d01e511 100644 --- a/src/mlpack/core/cv/cv_base_impl.hpp +++ b/src/mlpack/core/cv/cv_base_impl.hpp @@ -108,8 +108,8 @@ void CVBase::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 - 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 - 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 \ No newline at end of file +#endif diff --git a/src/mlpack/methods/ann/activation_functions/tanh_exponential_function.hpp b/src/mlpack/methods/ann/activation_functions/tanh_exponential_function.hpp index cabe427a88..536e42f94c 100644 --- a/src/mlpack/methods/ann/activation_functions/tanh_exponential_function.hpp +++ b/src/mlpack/methods/ann/activation_functions/tanh_exponential_function.hpp @@ -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: /** diff --git a/src/mlpack/methods/ann/ffn_impl.hpp b/src/mlpack/methods/ann/ffn_impl.hpp index 401c094ca6..921ded0bd7 100644 --- a/src/mlpack/methods/ann/ffn_impl.hpp +++ b/src/mlpack/methods/ann/ffn_impl.hpp @@ -111,8 +111,8 @@ double FFN::Train( OptimizerType& optimizer, CallbackTypes&&... callbacks) { - CheckInputShape > >(network, - predictors.n_rows, + CheckInputShape > >(network, + predictors.n_rows, "FFN<>::Train()"); ResetData(std::move(predictors), std::move(responses)); @@ -137,8 +137,8 @@ double FFN::Train( arma::mat responses, CallbackTypes&&... callbacks) { - CheckInputShape > >(network, - predictors.n_rows, + CheckInputShape > >(network, + predictors.n_rows, "FFN<>::Train()"); ResetData(std::move(predictors), std::move(responses)); @@ -227,9 +227,8 @@ template::Predict( arma::mat predictors, arma::mat& results) { - CheckInputShape > >(network, - predictors.n_rows, - "FFN<>::Predict()"); + CheckInputShape > >( + network, predictors.n_rows, "FFN<>::Predict()"); if (parameter.is_empty()) ResetParameters(); @@ -264,9 +263,8 @@ template double FFN::Evaluate( const PredictorsType& predictors, const ResponsesType& responses) { - CheckInputShape > >(network, - predictors.n_rows, - "FFN<>::Evaluate()"); + CheckInputShape > >( + network, predictors.n_rows, "FFN<>::Evaluate()"); if (parameter.is_empty()) ResetParameters(); diff --git a/src/mlpack/methods/ann/layer/atrous_convolution.hpp b/src/mlpack/methods/ann/layer/atrous_convolution.hpp index daddab76f2..d6086de86f 100644 --- a/src/mlpack/methods/ann/layer/atrous_convolution.hpp +++ b/src/mlpack/methods/ann/layer/atrous_convolution.hpp @@ -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. diff --git a/src/mlpack/methods/ann/layer/base_layer.hpp b/src/mlpack/methods/ann/layer/base_layer.hpp index 9c6bd19478..e2d7aaf809 100644 --- a/src/mlpack/methods/ann/layer/base_layer.hpp +++ b/src/mlpack/methods/ann/layer/base_layer.hpp @@ -29,7 +29,7 @@ #include #include #include -#include +#include 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 diff --git a/src/mlpack/methods/ann/layer/concatenate_impl.hpp b/src/mlpack/methods/ann/layer/concatenate_impl.hpp index bfede6c162..cf85443cf6 100644 --- a/src/mlpack/methods/ann/layer/concatenate_impl.hpp +++ b/src/mlpack/methods/ann/layer/concatenate_impl.hpp @@ -27,7 +27,7 @@ Concatenate::Concatenate() : } template -Concatenate::Concatenate(const Concatenate& layer) : +Concatenate::Concatenate(const Concatenate& layer) : inRows(layer.inRows), weights(layer.weights), delta(layer.delta), @@ -37,7 +37,7 @@ Concatenate::Concatenate(const Concatenate& layer } template -Concatenate::Concatenate(Concatenate&& layer) : +Concatenate::Concatenate(Concatenate&& layer) : inRows(layer.inRows), weights(std::move(layer.weights)), delta(std::move(layer.delta)), @@ -51,7 +51,7 @@ Concatenate& Concatenate:: operator=(const Concatenate& layer) { - if (this != &layer) + if (this != &layer) { inRows = layer.inRows; weights = layer.weights; @@ -67,7 +67,7 @@ Concatenate& Concatenate:: operator=(Concatenate&& layer) { - if (this != &layer) + if (this != &layer) { inRows = layer.inRows; weights = std::move(layer.weights); diff --git a/src/mlpack/methods/ann/layer/flatten_t_swish_impl.hpp b/src/mlpack/methods/ann/layer/flatten_t_swish_impl.hpp index 1ce5364da8..edc616ac3c 100644 --- a/src/mlpack/methods/ann/layer/flatten_t_swish_impl.hpp +++ b/src/mlpack/methods/ann/layer/flatten_t_swish_impl.hpp @@ -48,9 +48,9 @@ void FlattenTSwish::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::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::serialize( } // namespace ann } // namespace mlpack -#endif \ No newline at end of file +#endif diff --git a/src/mlpack/methods/ann/layer/gru.hpp b/src/mlpack/methods/ann/layer/gru.hpp index 3d98a712d8..c895ee7f81 100644 --- a/src/mlpack/methods/ann/layer/gru.hpp +++ b/src/mlpack/methods/ann/layer/gru.hpp @@ -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; } diff --git a/src/mlpack/methods/ann/layer/isrlu.hpp b/src/mlpack/methods/ann/layer/isrlu.hpp index b0a786c6ba..36722b91c3 100644 --- a/src/mlpack/methods/ann/layer/isrlu.hpp +++ b/src/mlpack/methods/ann/layer/isrlu.hpp @@ -126,7 +126,6 @@ class ISRLU //! ISRLU Hyperparameter (alpha > 0). double alpha; - }; // class ISRLU } // namespace ann diff --git a/src/mlpack/methods/ann/layer/linear.hpp b/src/mlpack/methods/ann/layer/linear.hpp index cc31117c53..5b9d23bd87 100644 --- a/src/mlpack/methods/ann/layer/linear.hpp +++ b/src/mlpack/methods/ann/layer/linear.hpp @@ -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; diff --git a/src/mlpack/methods/ann/layer/lp_pooling.hpp b/src/mlpack/methods/ann/layer/lp_pooling.hpp index 03ef9f540e..1c2b841e24 100644 --- a/src/mlpack/methods/ann/layer/lp_pooling.hpp +++ b/src/mlpack/methods/ann/layer/lp_pooling.hpp @@ -196,11 +196,12 @@ class LpPooling const arma::Mat& error, arma::Mat& output) { - arma::Mat 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); diff --git a/src/mlpack/methods/ann/layer/lstm.hpp b/src/mlpack/methods/ann/layer/lstm.hpp index 98be4b500f..effca7328e 100644 --- a/src/mlpack/methods/ann/layer/lstm.hpp +++ b/src/mlpack/methods/ann/layer/lstm.hpp @@ -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 diff --git a/src/mlpack/methods/ann/layer/lstm_impl.hpp b/src/mlpack/methods/ann/layer/lstm_impl.hpp index 9d720732c4..2b298d18aa 100644 --- a/src/mlpack/methods/ann/layer/lstm_impl.hpp +++ b/src/mlpack/methods/ann/layer/lstm_impl.hpp @@ -26,7 +26,7 @@ LSTM::LSTM() template LSTM::LSTM( - const LSTM& layer) : + const LSTM& layer) : inSize(layer.inSize), outSize(layer.outSize), rho(layer.rho), @@ -45,7 +45,7 @@ LSTM::LSTM( template LSTM::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::LSTM( } template -LSTM& +LSTM& LSTM :: operator=(const LSTM& layer) { if (this != &layer) @@ -82,11 +82,11 @@ LSTM :: operator=(const LSTM& layer) rhoSize = layer.rho; bpttSteps = layer.bpttSteps; } - return *this; + return *this; } template -LSTM& +LSTM& LSTM :: operator=(LSTM&& layer) { if (this != &layer) @@ -105,7 +105,7 @@ LSTM :: operator=(LSTM&& layer) rhoSize = std::move(layer.rho); bpttSteps = std::move(layer.bpttSteps); } - return *this; + return *this; } template diff --git a/src/mlpack/methods/ann/layer/mean_pooling.hpp b/src/mlpack/methods/ann/layer/mean_pooling.hpp index 2480a9525f..afba6470c7 100644 --- a/src/mlpack/methods/ann/layer/mean_pooling.hpp +++ b/src/mlpack/methods/ann/layer/mean_pooling.hpp @@ -164,7 +164,7 @@ class MeanPooling 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); @@ -210,12 +210,13 @@ class MeanPooling const arma::Mat& error, arma::Mat& output) { - arma::Mat 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; @@ -233,7 +234,8 @@ class MeanPooling 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)); unpooledError = arma::Mat(InputArea.n_rows, InputArea.n_cols); unpooledError.fill(error(rowidx, colidx) / InputArea.n_elem); diff --git a/src/mlpack/methods/ann/layer/pixel_shuffle_impl.hpp b/src/mlpack/methods/ann/layer/pixel_shuffle_impl.hpp index f56f708981..4de0816990 100644 --- a/src/mlpack/methods/ann/layer/pixel_shuffle_impl.hpp +++ b/src/mlpack/methods/ann/layer/pixel_shuffle_impl.hpp @@ -77,12 +77,11 @@ void PixelShuffle::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::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); } } } - } } diff --git a/src/mlpack/methods/ann/layer/recurrent_impl.hpp b/src/mlpack/methods/ann/layer/recurrent_impl.hpp index e6b933bd20..046c48fa0f 100644 --- a/src/mlpack/methods/ann/layer/recurrent_impl.hpp +++ b/src/mlpack/methods/ann/layer/recurrent_impl.hpp @@ -128,9 +128,12 @@ Recurrent::Recurrent( template -size_t Recurrent::InputShape() const +size_t +Recurrent::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::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; + } } } } diff --git a/src/mlpack/methods/ann/layer/reparametrization.hpp b/src/mlpack/methods/ann/layer/reparametrization.hpp index a526d746bf..d3a183b9fd 100644 --- a/src/mlpack/methods/ann/layer/reparametrization.hpp +++ b/src/mlpack/methods/ann/layer/reparametrization.hpp @@ -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); diff --git a/src/mlpack/methods/ann/layer/reparametrization_impl.hpp b/src/mlpack/methods/ann/layer/reparametrization_impl.hpp index cef6a32b0d..117e67a620 100644 --- a/src/mlpack/methods/ann/layer/reparametrization_impl.hpp +++ b/src/mlpack/methods/ann/layer/reparametrization_impl.hpp @@ -46,7 +46,7 @@ Reparametrization::Reparametrization( << "included." << std::endl; } } - + template Reparametrization::Reparametrization( const Reparametrization& layer) : @@ -55,7 +55,7 @@ Reparametrization::Reparametrization( includeKl(layer.includeKl), beta(layer.beta) { - // Nothing to do here. + // Nothing to do here. } template @@ -66,13 +66,13 @@ Reparametrization::Reparametrization( includeKl(std::move(layer.includeKl)), beta(std::move(layer.beta)) { - // Nothing to do here. + // Nothing to do here. } - + template Reparametrization& Reparametrization:: -operator=(const Reparametrization& layer) +operator=(const Reparametrization& layer) { if (this != &layer) { @@ -83,11 +83,11 @@ operator=(const Reparametrization& layer) } return *this; } - + template Reparametrization& Reparametrization:: -operator=(Reparametrization&& layer) +operator=(Reparametrization&& layer) { if (this != &layer) { @@ -98,8 +98,8 @@ operator=(Reparametrization&& layer) } return *this; } - - + + template template void Reparametrization::Forward( diff --git a/src/mlpack/methods/ann/loss_functions/binary_cross_entropy_loss_impl.hpp b/src/mlpack/methods/ann/loss_functions/binary_cross_entropy_loss_impl.hpp index 89e7aaf1c2..4555240b88 100644 --- a/src/mlpack/methods/ann/loss_functions/binary_cross_entropy_loss_impl.hpp +++ b/src/mlpack/methods/ann/loss_functions/binary_cross_entropy_loss_impl.hpp @@ -34,7 +34,7 @@ BCELoss::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; diff --git a/src/mlpack/methods/ann/loss_functions/huber_loss_impl.hpp b/src/mlpack/methods/ann/loss_functions/huber_loss_impl.hpp index d692734754..50b2c61858 100644 --- a/src/mlpack/methods/ann/loss_functions/huber_loss_impl.hpp +++ b/src/mlpack/methods/ann/loss_functions/huber_loss_impl.hpp @@ -31,16 +31,17 @@ HuberLoss::HuberLoss( template template typename PredictionType::elem_type -HuberLoss::Forward(const PredictionType& prediction, - const TargetType& target) +HuberLoss::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::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; } diff --git a/src/mlpack/methods/ann/loss_functions/kl_divergence_impl.hpp b/src/mlpack/methods/ann/loss_functions/kl_divergence_impl.hpp index aa1a5c1b62..9c74453a21 100644 --- a/src/mlpack/methods/ann/loss_functions/kl_divergence_impl.hpp +++ b/src/mlpack/methods/ann/loss_functions/kl_divergence_impl.hpp @@ -29,8 +29,9 @@ KLDivergence::KLDivergence(const bool takeMean) : template template typename PredictionType::elem_type -KLDivergence::Forward(const PredictionType& prediction, - const TargetType& target) +KLDivergence::Forward( + const PredictionType& prediction, + const TargetType& target) { if (takeMean) { @@ -52,7 +53,8 @@ void KLDivergence::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 { diff --git a/src/mlpack/methods/ann/loss_functions/sigmoid_cross_entropy_error.hpp b/src/mlpack/methods/ann/loss_functions/sigmoid_cross_entropy_error.hpp index 2d0bed9721..a1f4384e7f 100644 --- a/src/mlpack/methods/ann/loss_functions/sigmoid_cross_entropy_error.hpp +++ b/src/mlpack/methods/ann/loss_functions/sigmoid_cross_entropy_error.hpp @@ -65,8 +65,10 @@ class SigmoidCrossEntropyError * @param target The target vector. */ template - 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. * diff --git a/src/mlpack/methods/ann/loss_functions/triplet_margin_loss.hpp b/src/mlpack/methods/ann/loss_functions/triplet_margin_loss.hpp index fba54973f0..980d863d17 100644 --- a/src/mlpack/methods/ann/loss_functions/triplet_margin_loss.hpp +++ b/src/mlpack/methods/ann/loss_functions/triplet_margin_loss.hpp @@ -108,4 +108,4 @@ class TripletMarginLoss // include implementation. #include "triplet_margin_loss_impl.hpp" -#endif \ No newline at end of file +#endif diff --git a/src/mlpack/methods/ann/loss_functions/triplet_margin_loss_impl.hpp b/src/mlpack/methods/ann/loss_functions/triplet_margin_loss_impl.hpp index a007490be0..2a43bc4ac4 100644 --- a/src/mlpack/methods/ann/loss_functions/triplet_margin_loss_impl.hpp +++ b/src/mlpack/methods/ann/loss_functions/triplet_margin_loss_impl.hpp @@ -33,8 +33,10 @@ TripletMarginLoss::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::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; } diff --git a/src/mlpack/methods/ann/rnn_impl.hpp b/src/mlpack/methods/ann/rnn_impl.hpp index 5077eb9896..3e7d6d0323 100644 --- a/src/mlpack/methods/ann/rnn_impl.hpp +++ b/src/mlpack/methods/ann/rnn_impl.hpp @@ -149,9 +149,8 @@ double RNN::Train( OptimizerType& optimizer, CallbackTypes&&... callbacks) { - CheckInputShape > >(network, - predictors.n_rows, - "RNN<>::Train()"); + CheckInputShape > >( + network, predictors.n_rows, "RNN<>::Train()"); numFunctions = responses.n_cols; @@ -197,9 +196,8 @@ double RNN::Train( arma::cube responses, CallbackTypes&&... callbacks) { - CheckInputShape > >(network, - predictors.n_rows, - "RNN<>::Train()"); + CheckInputShape > >( + network, predictors.n_rows, "RNN<>::Train()"); numFunctions = responses.n_cols; @@ -233,9 +231,8 @@ template::Predict( arma::cube predictors, arma::cube& results, const size_t batchSize) { - CheckInputShape > >(network, - predictors.n_rows, - "RNN<>::Predict()"); + CheckInputShape > >( + network, predictors.n_rows, "RNN<>::Predict()"); ResetCells(); From 963139172bc09bf24d02ee6d860e37e07d5226a0 Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Wed, 2 Jun 2021 21:21:28 -0400 Subject: [PATCH 35/37] Some more style fixes. --- .../methods/ann/layer/concatenate_impl.hpp | 21 ++++---- .../ann/layer/flatten_t_swish_impl.hpp | 2 +- .../methods/ann/util/check_input_shape.hpp | 3 +- src/mlpack/methods/kde/kde_impl.hpp | 2 - .../methods/neighbor_search/ns_model.hpp | 2 +- .../methods/neighbor_search/ns_model_impl.hpp | 1 - src/mlpack/methods/pca/pca_impl.hpp | 2 +- .../range_search/range_search_impl.hpp | 4 +- src/mlpack/methods/rann/ra_model.hpp | 2 +- .../q_learning_impl.hpp | 2 +- .../tests/activation_functions_test.cpp | 52 +++++++++++-------- src/mlpack/tests/ann_layer_test.cpp | 2 +- src/mlpack/tests/ann_visitor_test.cpp | 4 +- src/mlpack/tests/cli_binding_test.cpp | 6 ++- src/mlpack/tests/decision_tree_test.cpp | 6 +-- src/mlpack/tests/feedforward_network_test.cpp | 12 +++-- src/mlpack/tests/hmm_test.cpp | 8 +-- src/mlpack/tests/krann_search_test.cpp | 10 ++-- src/mlpack/tests/recurrent_network_test.cpp | 6 +-- src/mlpack/tests/size_checks_test.cpp | 3 +- 20 files changed, 80 insertions(+), 70 deletions(-) diff --git a/src/mlpack/methods/ann/layer/concatenate_impl.hpp b/src/mlpack/methods/ann/layer/concatenate_impl.hpp index cf85443cf6..54b53471c8 100644 --- a/src/mlpack/methods/ann/layer/concatenate_impl.hpp +++ b/src/mlpack/methods/ann/layer/concatenate_impl.hpp @@ -21,27 +21,28 @@ namespace ann /** Artificial Neural Network. */ { template Concatenate::Concatenate() : - inRows(0) + inRows(0) { // Nothing to do here. } template -Concatenate::Concatenate(const Concatenate& layer) : - inRows(layer.inRows), - weights(layer.weights), - delta(layer.delta), - concat(layer.concat) +Concatenate::Concatenate( + const Concatenate& layer) : + inRows(layer.inRows), + weights(layer.weights), + delta(layer.delta), + concat(layer.concat) { // Nothing to to here. } template Concatenate::Concatenate(Concatenate&& layer) : - inRows(layer.inRows), - weights(std::move(layer.weights)), - delta(std::move(layer.delta)), - concat(std::move(layer.concat)) + inRows(layer.inRows), + weights(std::move(layer.weights)), + delta(std::move(layer.delta)), + concat(std::move(layer.concat)) { // Nothing to do here. } diff --git a/src/mlpack/methods/ann/layer/flatten_t_swish_impl.hpp b/src/mlpack/methods/ann/layer/flatten_t_swish_impl.hpp index edc616ac3c..41410a544f 100644 --- a/src/mlpack/methods/ann/layer/flatten_t_swish_impl.hpp +++ b/src/mlpack/methods/ann/layer/flatten_t_swish_impl.hpp @@ -50,7 +50,7 @@ void FlattenTSwish::Backward( DataType derivate, 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) { diff --git a/src/mlpack/methods/ann/util/check_input_shape.hpp b/src/mlpack/methods/ann/util/check_input_shape.hpp index 566c363e3f..59f2c72da2 100644 --- a/src/mlpack/methods/ann/util/check_input_shape.hpp +++ b/src/mlpack/methods/ann/util/check_input_shape.hpp @@ -22,7 +22,8 @@ namespace mlpack { namespace ann /** Artificial Neural Network. */{ template -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) diff --git a/src/mlpack/methods/kde/kde_impl.hpp b/src/mlpack/methods/kde/kde_impl.hpp index 054c02119d..9fdadd2e3e 100644 --- a/src/mlpack/methods/kde/kde_impl.hpp +++ b/src/mlpack/methods/kde/kde_impl.hpp @@ -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; diff --git a/src/mlpack/methods/neighbor_search/ns_model.hpp b/src/mlpack/methods/neighbor_search/ns_model.hpp index b13918fa7d..e09fd6489c 100644 --- a/src/mlpack/methods/neighbor_search/ns_model.hpp +++ b/src/mlpack/methods/neighbor_search/ns_model.hpp @@ -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; diff --git a/src/mlpack/methods/neighbor_search/ns_model_impl.hpp b/src/mlpack/methods/neighbor_search/ns_model_impl.hpp index 319fb652af..050398089a 100644 --- a/src/mlpack/methods/neighbor_search/ns_model_impl.hpp +++ b/src/mlpack/methods/neighbor_search/ns_model_impl.hpp @@ -516,7 +516,6 @@ void NSModel::InitializeModel(const NeighborSearchMode searchMode, epsilon); break; } - } //! Build the reference tree. diff --git a/src/mlpack/methods/pca/pca_impl.hpp b/src/mlpack/methods/pca/pca_impl.hpp index f469933c14..e1b6fe1958 100644 --- a/src/mlpack/methods/pca/pca_impl.hpp +++ b/src/mlpack/methods/pca/pca_impl.hpp @@ -74,7 +74,7 @@ void PCA::Apply(const arma::mat& data, arma::mat eigvec; Apply(data, transformedData, eigVal, eigvec); } - + /** * Apply Principal Component Analysis to the provided data set. * diff --git a/src/mlpack/methods/range_search/range_search_impl.hpp b/src/mlpack/methods/range_search/range_search_impl.hpp index cce20339a3..37b86baf61 100644 --- a/src/mlpack/methods/range_search/range_search_impl.hpp +++ b/src/mlpack/methods/range_search/range_search_impl.hpp @@ -174,7 +174,8 @@ RangeSearch::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::operator=(RangeSearch&& other) other.singleMode = false; other.baseCases = 0; other.scores = 0; - } return *this; } diff --git a/src/mlpack/methods/rann/ra_model.hpp b/src/mlpack/methods/rann/ra_model.hpp index 572d599a0d..32ff60af07 100644 --- a/src/mlpack/methods/rann/ra_model.hpp +++ b/src/mlpack/methods/rann/ra_model.hpp @@ -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; diff --git a/src/mlpack/methods/reinforcement_learning/q_learning_impl.hpp b/src/mlpack/methods/reinforcement_learning/q_learning_impl.hpp index 9fe689aa26..de28d05e74 100644 --- a/src/mlpack/methods/reinforcement_learning/q_learning_impl.hpp +++ b/src/mlpack/methods/reinforcement_learning/q_learning_impl.hpp @@ -54,7 +54,7 @@ QLearning< // Set up q-learning network. if (learningNetwork.Parameters().is_empty()) learningNetwork.ResetParameters(); - + targetNetwork.ResetParameters(); #if ENS_VERSION_MAJOR == 1 diff --git a/src/mlpack/tests/activation_functions_test.cpp b/src/mlpack/tests/activation_functions_test.cpp index fcca17d2c0..cd4f7d4711 100644 --- a/src/mlpack/tests/activation_functions_test.cpp +++ b/src/mlpack/tests/activation_functions_test.cpp @@ -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) + 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; @@ -696,7 +698,7 @@ void CheckFlattenTSwishDerivateCorrect(const arma::colvec input, const arma::col arma::colvec derivate; fts.Backward(input,error,derivate); - for(size_t i = 0; i < derivate.n_elem; ++i) + 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,29 +1283,32 @@ TEST_CASE("TanhExpFunctionTest", "[ActivationFunctionsTest]") 1.03924 0.449818 1.00002 0.761594"); CheckActivationCorrect(activationData, desiredActivations); - CheckDerivativeCorrect(desiredActivations, desiredDerivatives); + CheckDerivativeCorrect(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(activationData,desiredActivation); - CheckDerivativeCorrect(desiredActivation,desiredDerivate); + arma::colvec desiredDerivate( + "0.38191673159599304 1.073788046836853 1.0392179489135742 \ + 0.49049633741378784 0.36713290214538574 0.8354039788246155 \ + 0.5 1.0004087686538696"); + + CheckActivationCorrect(activationData, desiredActivation); + CheckDerivativeCorrect(desiredActivation, desiredDerivate); } /** @@ -1316,13 +1320,15 @@ TEST_CASE("FlattenTSwishFunctionTest","[ActivationFunctionsTest]") 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); -} \ No newline at end of file + CheckFlattenTSwishActivationCorrect(input, desiredActivation); + CheckFlattenTSwishDerivateCorrect(desiredActivation, desiredDerivation); +} diff --git a/src/mlpack/tests/ann_layer_test.cpp b/src/mlpack/tests/ann_layer_test.cpp index 13576eb11a..1d94b16560 100644 --- a/src/mlpack/tests/ann_layer_test.cpp +++ b/src/mlpack/tests/ann_layer_test.cpp @@ -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); diff --git a/src/mlpack/tests/ann_visitor_test.cpp b/src/mlpack/tests/ann_visitor_test.cpp index b9316e8f0f..29f376611e 100644 --- a/src/mlpack/tests/ann_visitor_test.cpp +++ b/src/mlpack/tests/ann_visitor_test.cpp @@ -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); } diff --git a/src/mlpack/tests/cli_binding_test.cpp b/src/mlpack/tests/cli_binding_test.cpp index 76cf6a652d..342323b504 100644 --- a/src/mlpack/tests/cli_binding_test.cpp +++ b/src/mlpack/tests/cli_binding_test.cpp @@ -539,7 +539,8 @@ TEST_CASE("SetParamDatasetInfoMatTest", "[CLIOptionTest]") typedef tuple TupleType; TupleType testTuple{filename, 0, 0}; tuple t1 = make_tuple(di, m); - tuple, TupleType> t2 = make_tuple(t1, testTuple); + tuple, 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, TupleType>& t3 = - *boost::any_cast, TupleType>>(&d.value); + *boost::any_cast, TupleType>>( + &d.value); REQUIRE(get<0>(get<1>(t3)) == "new_filename.csv"); } diff --git a/src/mlpack/tests/decision_tree_test.cpp b/src/mlpack/tests/decision_tree_test.cpp index 8fcf6b1e95..d0bc624ca3 100644 --- a/src/mlpack/tests/decision_tree_test.cpp +++ b/src/mlpack/tests/decision_tree_test.cpp @@ -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 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 diff --git a/src/mlpack/tests/feedforward_network_test.cpp b/src/mlpack/tests/feedforward_network_test.cpp index a41d745676..d802092158 100644 --- a/src/mlpack/tests/feedforward_network_test.cpp +++ b/src/mlpack/tests/feedforward_network_test.cpp @@ -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 >(); 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); diff --git a/src/mlpack/tests/hmm_test.cpp b/src/mlpack/tests/hmm_test.cpp index 394d1a688e..de78b48d8e 100644 --- a/src/mlpack/tests/hmm_test.cpp +++ b/src/mlpack/tests/hmm_test.cpp @@ -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 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. diff --git a/src/mlpack/tests/krann_search_test.cpp b/src/mlpack/tests/krann_search_test.cpp index a548b30438..5e6bff9446 100644 --- a/src/mlpack/tests/krann_search_test.cpp +++ b/src/mlpack/tests/krann_search_test.cpp @@ -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 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 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 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 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) diff --git a/src/mlpack/tests/recurrent_network_test.cpp b/src/mlpack/tests/recurrent_network_test.cpp index 7781b6c50c..4b5aca4afb 100644 --- a/src/mlpack/tests/recurrent_network_test.cpp +++ b/src/mlpack/tests/recurrent_network_test.cpp @@ -923,9 +923,9 @@ TEST_CASE("RNNCheckInputShapeTest", "[RecurrentNetworkTest]") model.Add >(); 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); diff --git a/src/mlpack/tests/size_checks_test.cpp b/src/mlpack/tests/size_checks_test.cpp index d5c7f22e46..0e22a4aab7 100644 --- a/src/mlpack/tests/size_checks_test.cpp +++ b/src/mlpack/tests/size_checks_test.cpp @@ -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")); } /** From a392d2f9b84537f3bacbdd012f95631ec30e4dba Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Wed, 2 Jun 2021 22:01:37 -0400 Subject: [PATCH 36/37] Some more style fixes. --- src/mlpack/methods/neighbor_search/ns_model.hpp | 2 +- src/mlpack/methods/rann/ra_model.hpp | 2 +- src/mlpack/tests/activation_functions_test.cpp | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/mlpack/methods/neighbor_search/ns_model.hpp b/src/mlpack/methods/neighbor_search/ns_model.hpp index e09fd6489c..6d9fba3670 100644 --- a/src/mlpack/methods/neighbor_search/ns_model.hpp +++ b/src/mlpack/methods/neighbor_search/ns_model.hpp @@ -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; diff --git a/src/mlpack/methods/rann/ra_model.hpp b/src/mlpack/methods/rann/ra_model.hpp index 32ff60af07..2223f05ebe 100644 --- a/src/mlpack/methods/rann/ra_model.hpp +++ b/src/mlpack/methods/rann/ra_model.hpp @@ -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; diff --git a/src/mlpack/tests/activation_functions_test.cpp b/src/mlpack/tests/activation_functions_test.cpp index cd4f7d4711..b60855d9b4 100644 --- a/src/mlpack/tests/activation_functions_test.cpp +++ b/src/mlpack/tests/activation_functions_test.cpp @@ -674,7 +674,7 @@ void CheckFlattenTSwishActivationCorrect(const arma::colvec input, FlattenTSwish<> fts(0.4); arma::colvec activations; - fts.Forward(input,activations); + 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)); @@ -697,7 +697,7 @@ void CheckFlattenTSwishDerivateCorrect(const arma::colvec input, arma::colvec error = arma::ones(input.n_elem); arma::colvec derivate; - fts.Backward(input,error,derivate); + 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)); @@ -1290,7 +1290,7 @@ TEST_CASE("TanhExpFunctionTest", "[ActivationFunctionsTest]") /** * 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"); @@ -1314,7 +1314,7 @@ TEST_CASE("SILUFunctionTest","[ActivationFunctionsTest]") /** * 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"); From ec58b6dd7b912fe9b81e744e021258d6f8885f00 Mon Sep 17 00:00:00 2001 From: Ryan Curtin Date: Fri, 4 Jun 2021 19:45:53 -0400 Subject: [PATCH 37/37] Fix missing semicolon. --- src/mlpack/bindings/python/print_type_doc_impl.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mlpack/bindings/python/print_type_doc_impl.hpp b/src/mlpack/bindings/python/print_type_doc_impl.hpp index c062e9c7e1..8ab5986721 100644 --- a/src/mlpack/bindings/python/print_type_doc_impl.hpp +++ b/src/mlpack/bindings/python/print_type_doc_impl.hpp @@ -161,7 +161,7 @@ std::string PrintTypeDoc( "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." + "`set_cpp_params()` method."; } } // namespace python