From a1b5267cea78a0697459749a4fdbff9735b22764 Mon Sep 17 00:00:00 2001 From: PGijsbers Date: Sat, 27 Oct 2018 13:59:35 +0200 Subject: [PATCH 1/8] 2 typo's --- src/skmultiflow/bayes/naive_bayes.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/skmultiflow/bayes/naive_bayes.py b/src/skmultiflow/bayes/naive_bayes.py index 30a6d29da..41a339042 100644 --- a/src/skmultiflow/bayes/naive_bayes.py +++ b/src/skmultiflow/bayes/naive_bayes.py @@ -7,8 +7,8 @@ class NaiveBayes(StreamModel): A mask for scikit-learn's Naive Bayes classifier. - Because scikit-multiflow's framework require a few interfaces, not present - int scikit-learn, this mask allows the first to use classifiers native to + Because scikit-multiflow's framework requires a few interfaces, not present + in scikit-learn, this mask allows the first to use classifiers native to the latter. """ From 3d56ff848595e5059b039b8c7e889755d784a06a Mon Sep 17 00:00:00 2001 From: PGijsbers Date: Sat, 27 Oct 2018 14:03:30 +0200 Subject: [PATCH 2/8] [docs] Clarifications. --- src/skmultiflow/core/base.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/skmultiflow/core/base.py b/src/skmultiflow/core/base.py index e9139fc95..7ea50a320 100644 --- a/src/skmultiflow/core/base.py +++ b/src/skmultiflow/core/base.py @@ -78,7 +78,7 @@ def predict(self, X): Parameters ---------- X : Numpy.ndarray of shape (n_samples, n_features) - The matrix of samples one wants to predict. + The matrix of samples one wants to predict the labels for. Returns ------- @@ -94,7 +94,7 @@ def predict_proba(self, X): Parameters ---------- X : Numpy.ndarray of shape (n_samples, n_features) - The matrix of samples one wants to predict. + The matrix of samples one wants to predict the class probabilities for. Returns ------- From a4dfef507adc5f313c45e9dabaefd4885309fc33 Mon Sep 17 00:00:00 2001 From: PGijsbers Date: Sat, 27 Oct 2018 14:40:43 +0200 Subject: [PATCH 3/8] [docs] typo --- src/skmultiflow/core/base_object.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/skmultiflow/core/base_object.py b/src/skmultiflow/core/base_object.py index a825eaec9..05c5f7ca6 100644 --- a/src/skmultiflow/core/base_object.py +++ b/src/skmultiflow/core/base_object.py @@ -5,8 +5,8 @@ class BaseObject(metaclass=ABCMeta): """ BaseObject The most basic object, from which classes in scikit-multiflow - derive from. It guarantees that all classes have at least the - two basic functions described in this base class. + derive. It guarantees that all classes have at least the two + basic functions described in this base class. """ @@ -28,7 +28,7 @@ def get_class_type(self): def get_info(self): """ get_info - A sum up of all important characteristics of a class. + A sum-up of all important characteristics of a class. The default format of the return string is as follows: ClassName: attribute_one: value_one - attribute_two: value_two \ From 15bc805be52ccb2b252e51743f1026bed6cc2142 Mon Sep 17 00:00:00 2001 From: PGijsbers Date: Sat, 27 Oct 2018 14:44:04 +0200 Subject: [PATCH 4/8] [docs] typo --- src/skmultiflow/core/pipeline.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/skmultiflow/core/pipeline.py b/src/skmultiflow/core/pipeline.py index da66e13ad..0bac666c4 100644 --- a/src/skmultiflow/core/pipeline.py +++ b/src/skmultiflow/core/pipeline.py @@ -17,7 +17,7 @@ class Pipeline(BaseObject): The last step should be an estimator (learner), so it should implement partial_fit, and predict at least. - Since it has an estimator as the last step, the Pipeline will act like as + Since it has an estimator as the last step, the Pipeline will act like an estimator itself, in a way that it can be directly passed to evaluation objects, as if it was a learner. From 797418bdda3666ab267e787ba4b8dd53e4ce9d30 Mon Sep 17 00:00:00 2001 From: PGijsbers Date: Sat, 27 Oct 2018 14:44:51 +0200 Subject: [PATCH 5/8] Removed assignment that was immediately overwritten anyway. --- src/skmultiflow/core/pipeline.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/skmultiflow/core/pipeline.py b/src/skmultiflow/core/pipeline.py index 0bac666c4..b9824bc35 100644 --- a/src/skmultiflow/core/pipeline.py +++ b/src/skmultiflow/core/pipeline.py @@ -250,7 +250,6 @@ def _validate_steps(self): """ names, estimators = zip(*self.steps) - transforms = classifier = None classifier = estimators[-1] transforms = estimators[:-1] From 6354cbbdde19f73da94c1a19b465f953e9dac28e Mon Sep 17 00:00:00 2001 From: PGijsbers Date: Sat, 27 Oct 2018 14:53:47 +0200 Subject: [PATCH 6/8] [docs] space before first sentence, typo. --- src/skmultiflow/trees/hoeffding_tree.py | 132 ++++++++++++------------ 1 file changed, 66 insertions(+), 66 deletions(-) diff --git a/src/skmultiflow/trees/hoeffding_tree.py b/src/skmultiflow/trees/hoeffding_tree.py index e54b4d62d..c0851e536 100644 --- a/src/skmultiflow/trees/hoeffding_tree.py +++ b/src/skmultiflow/trees/hoeffding_tree.py @@ -26,7 +26,7 @@ class HoeffdingTree(StreamModel): - """Hoeffding Tree or VFDT. + """ Hoeffding Tree or VFDT. Parameters ---------- @@ -87,7 +87,7 @@ class HoeffdingTree(StreamModel): """ class FoundNode(object): - """Base class for tree nodes. + """ Base class for tree nodes. Parameters ---------- @@ -106,7 +106,7 @@ def __init__(self, node=None, parent=None, parent_branch=None): self.parent_branch = parent_branch class Node(metaclass=ABCMeta): - """Base class for nodes in a Hoeffding Tree. + """ Base class for nodes in a Hoeffding Tree. Parameters ---------- @@ -123,7 +123,7 @@ def __init__(self, class_observations=None): @staticmethod def is_leaf(): - """Determine if the node is a leaf. + """ Determine if the node is a leaf. Returns ------- @@ -133,7 +133,7 @@ def is_leaf(): return True def filter_instance_to_leaf(self, X, parent, parent_branch): - """Travers down the tree to locate the corresponding leaf for an instance. + """ Traverse down the tree to locate the corresponding leaf for an instance. Parameters ---------- @@ -153,7 +153,7 @@ def filter_instance_to_leaf(self, X, parent, parent_branch): return HoeffdingTree.FoundNode(self, parent, parent_branch) def get_observed_class_distribution(self): - """Get the current observed class distribution at the node. + """ Get the current observed class distribution at the node. Returns ------- @@ -164,7 +164,7 @@ def get_observed_class_distribution(self): return self._observed_class_distribution def get_class_votes(self, X, ht): - """Get the votes per class for a given instance. + """ Get the votes per class for a given instance. Parameters ---------- @@ -182,7 +182,7 @@ def get_class_votes(self, X, ht): return self._observed_class_distribution def observed_class_distribution_is_pure(self): - """Check if observed class distribution is pure, i.e. if all samples belong to the same class. + """ Check if observed class distribution is pure, i.e. if all samples belong to the same class. Returns ------- @@ -199,7 +199,7 @@ def observed_class_distribution_is_pure(self): return count < 2 def subtree_depth(self): - """Calculate the depth of the subtree from this node. + """ Calculate the depth of the subtree from this node. Returns ------- @@ -210,7 +210,7 @@ def subtree_depth(self): return 0 def calculate_promise(self): - """Calculate node's promise. + """ Calculate node's promise. Returns ------- @@ -225,7 +225,7 @@ def calculate_promise(self): return 0 def __sizeof__(self): - """Calculate the size of the node. + """ Calculate the size of the node. Returns ------- @@ -236,7 +236,7 @@ def __sizeof__(self): return object.__sizeof__(self) + sys.getsizeof(self._observed_class_distribution) def calc_byte_size_including_subtree(self): - """Calculate the size of the node including its subtree. + """ Calculate the size of the node including its subtree. Returns ------- @@ -247,7 +247,7 @@ def calc_byte_size_including_subtree(self): return self.__sizeof__() def describe_subtree(self, ht, buffer, indent=0): - """Walk the tree and write its structure to a buffer string. + """ Walk the tree and write its structure to a buffer string. Parameters ---------- @@ -272,7 +272,7 @@ def get_description(self): pass class SplitNode(Node): - """Node that splits the data in a Hoeffding Tree. + """ Node that splits the data in a Hoeffding Tree. Parameters ---------- @@ -284,18 +284,18 @@ class SplitNode(Node): """ def __init__(self, split_test, class_observations): - """SplitNode class constructor.""" + """ SplitNode class constructor.""" super().__init__(class_observations) self._split_test = split_test # Dict of tuples (branch, child) self._children = {} def num_children(self): - """Count the number of children for a node.""" + """ Count the number of children for a node.""" return len(self._children) def set_child(self, index, node): - """Set node as child. + """ Set node as child. Parameters ---------- @@ -311,7 +311,7 @@ def set_child(self, index, node): self._children[index] = node def get_child(self, index): - """Retrieve a node's child given its branch index. + """ Retrieve a node's child given its branch index. Parameters ---------- @@ -330,7 +330,7 @@ def get_child(self, index): return None def instance_child_index(self, X): - """Get the branch index for a given instance at the current node. + """ Get the branch index for a given instance at the current node. Returns ------- @@ -342,7 +342,7 @@ def instance_child_index(self, X): @staticmethod def is_leaf(): - """Determine if the node is a leaf. + """ Determine if the node is a leaf. Returns ------- @@ -353,7 +353,7 @@ def is_leaf(): return False def filter_instance_to_leaf(self, X, parent, parent_branch): - """Travers down the tree to locate the corresponding leaf for an instance. + """ Traverse down the tree to locate the corresponding leaf for an instance. Parameters ---------- @@ -381,7 +381,7 @@ def filter_instance_to_leaf(self, X, parent, parent_branch): return HoeffdingTree.FoundNode(self, parent, parent_branch) def subtree_depth(self): - """Calculate the depth of the subtree from this node. + """ Calculate the depth of the subtree from this node. Returns ------- @@ -397,7 +397,7 @@ def subtree_depth(self): return max_child_depth + 1 def __sizeof__(self): - """Calculate the size of the node. + """ Calculate the size of the node. Returns ------- @@ -407,7 +407,7 @@ def __sizeof__(self): return object.__sizeof__(self) + sys.getsizeof(self._children) + sys.getsizeof(self._split_test) def calc_byte_size_including_subtree(self): - """Calculate the size of the node including its subtree. + """ Calculate the size of the node including its subtree. Returns ------- @@ -422,7 +422,7 @@ def calc_byte_size_including_subtree(self): return byte_size def describe_subtree(self, ht, buffer, indent=0): - """Walk the tree and write its structure to a buffer string. + """ Walk the tree and write its structure to a buffer string. Parameters ---------- @@ -443,7 +443,7 @@ def describe_subtree(self, ht, buffer, indent=0): child.describe_subtree(ht, buffer, indent + 2) class LearningNode(Node): - """Base class for Learning Nodes in a Hoeffding Tree. + """ Base class for Learning Nodes in a Hoeffding Tree. Parameters ---------- @@ -473,7 +473,7 @@ def learn_from_instance(self, X, y, weight, ht): pass class InactiveLearningNode(LearningNode): - """Inactive learning node that does not grow. + """ Inactive learning node that does not grow. Parameters ---------- @@ -486,7 +486,7 @@ def __init__(self, initial_class_observations=None): super().__init__(initial_class_observations) def learn_from_instance(self, X, y, weight, ht): - """Update the node with the provided instance. + """ Update the node with the provided instance. Parameters ---------- @@ -506,7 +506,7 @@ def learn_from_instance(self, X, y, weight, ht): self._observed_class_distribution[y] = weight class ActiveLearningNode(LearningNode): - """Learning node that supports growth. + """ Learning node that supports growth. Parameters ---------- @@ -521,7 +521,7 @@ def __init__(self, initial_class_observations): self._attribute_observers = {} def learn_from_instance(self, X, y, weight, ht): - """Update the node with the provided instance. + """ Update the node with the provided instance. Parameters ---------- @@ -552,7 +552,7 @@ def learn_from_instance(self, X, y, weight, ht): obs.observe_attribute_class(X[i], int(y), weight) def get_weight_seen(self): - """Calculate the total weight seen by the node. + """ Calculate the total weight seen by the node. Returns ------- @@ -563,7 +563,7 @@ def get_weight_seen(self): return sum(self._observed_class_distribution.values()) def get_weight_seen_at_last_split_evaluation(self): - """Retrieve the weight seen at last split evaluation. + """ Retrieve the weight seen at last split evaluation. Returns ------- @@ -574,7 +574,7 @@ def get_weight_seen_at_last_split_evaluation(self): return self._weight_seen_at_last_split_evaluation def set_weight_seen_at_last_split_evaluation(self, weight): - """Retrieve the weight seen at last split evaluation. + """ Retrieve the weight seen at last split evaluation. Parameters ---------- @@ -585,7 +585,7 @@ def set_weight_seen_at_last_split_evaluation(self, weight): self._weight_seen_at_last_split_evaluation = weight def get_best_split_suggestions(self, criterion, ht): - """Find possible split candidates. + """ Find possible split candidates. Parameters ---------- @@ -615,7 +615,7 @@ def get_best_split_suggestions(self, criterion, ht): return best_suggestions def disable_attribute(self, att_idx): - """Disable an attribute observer. + """ Disable an attribute observer. Parameters ---------- @@ -627,7 +627,7 @@ def disable_attribute(self, att_idx): self._attribute_observers[att_idx] = AttributeClassObserverNull() class LearningNodeNB(ActiveLearningNode): - """Learning node that uses Naive Bayes models. + """ Learning node that uses Naive Bayes models. Parameters ---------- @@ -640,7 +640,7 @@ def __init__(self, initial_class_observations): super().__init__(initial_class_observations) def get_class_votes(self, X, ht): - """Get the votes per class for a given instance. + """ Get the votes per class for a given instance. Parameters ---------- @@ -661,7 +661,7 @@ def get_class_votes(self, X, ht): return super().get_class_votes(X, ht) def disable_attribute(self, att_index): - """Disable an attribute observer. + """ Disable an attribute observer. Disabled in Nodes using Naive Bayes, since poor attributes are used in Naive Bayes calculation. @@ -674,7 +674,7 @@ def disable_attribute(self, att_index): pass class LearningNodeNBAdaptive(LearningNodeNB): - """Learning node that uses Adaptive Naive Bayes models. + """ Learning node that uses Adaptive Naive Bayes models. Parameters ---------- @@ -683,13 +683,13 @@ class LearningNodeNBAdaptive(LearningNodeNB): """ def __init__(self, initial_class_observations): - """LearningNodeNBAdaptive class constructor. """ + """ LearningNodeNBAdaptive class constructor. """ super().__init__(initial_class_observations) self._mc_correct_weight = 0.0 self._nb_correct_weight = 0.0 def learn_from_instance(self, X, y, weight, ht): - """Update the node with the provided instance. + """ Update the node with the provided instance. Parameters ---------- @@ -715,7 +715,7 @@ def learn_from_instance(self, X, y, weight, ht): super().learn_from_instance(X, y, weight, ht) def get_class_votes(self, X, ht): - """Get the votes per class for a given instance. + """ Get the votes per class for a given instance. Parameters ---------- @@ -751,7 +751,7 @@ def __init__(self, leaf_prediction='nba', nb_threshold=0, nominal_attributes=None): - """HoeffdingTree class constructor.""" + """ HoeffdingTree class constructor.""" super().__init__() self.max_byte_size = max_byte_size self.memory_estimate_period = memory_estimate_period @@ -893,7 +893,7 @@ def nominal_attributes(self): def nominal_attributes(self, nominal_attributes): if nominal_attributes is None: nominal_attributes = [] - logger.debug("No Nominal attributes have been defined, will consider all attributes as numerical") + logger.debug("No Nominal attributes have been defined, will consider all attributes as numerical.") self._nominal_attributes = nominal_attributes @property @@ -905,7 +905,7 @@ def classes(self, value): self._classes = value def __sizeof__(self): - """Calculate the size of the tree. + """ Calculate the size of the tree. Returns ------- @@ -919,7 +919,7 @@ def __sizeof__(self): return size def measure_byte_size(self): - """Calculate the size of the tree. + """ Calculate the size of the tree. Returns ------- @@ -930,7 +930,7 @@ def measure_byte_size(self): return self.__sizeof__() def reset(self): - """Reset the Hoeffding Tree to default values.""" + """ Reset the Hoeffding Tree to default values.""" self._tree_root = None self._decision_node_cnt = 0 self._active_leaf_node_cnt = 0 @@ -947,7 +947,7 @@ def fit(self, X, y, classes=None, weight=None): raise NotImplementedError def partial_fit(self, X, y, classes=None, weight=None): - """Incrementally trains the model. Train samples (instances) are compossed of X attributes and their + """ Incrementally trains the model. Train samples (instances) are composed of X attributes and their corresponding targets y. Tasks performed before training: @@ -992,7 +992,7 @@ def partial_fit(self, X, y, classes=None, weight=None): self._partial_fit(X[i], y[i], weight[i]) def _partial_fit(self, X, y, weight): - """Trains the model on samples X and corresponding targets y. + """ Trains the model on samples X and corresponding targets y. Private function where actual training is carried on. @@ -1051,7 +1051,7 @@ def get_votes_for_instance(self, X): return {} def predict(self, X): - """Predicts the label of the X instance(s) + """ Predicts the label of the X instance(s) Parameters ---------- @@ -1073,7 +1073,7 @@ def predict(self, X): return np.array(predictions) def predict_proba(self, X): - """Predicts probabilities of all label of the X instance(s) + """ Predicts probabilities of all label of the X instance(s) Parameters ---------- @@ -1107,7 +1107,7 @@ def predict_proba(self, X): @property def get_model_measurements(self): - """Collect metrics corresponding to the current status of the tree. + """ Collect metrics corresponding to the current status of the tree. Returns ------- @@ -1126,7 +1126,7 @@ def get_model_measurements(self): return measurements def measure_tree_depth(self): - """Calculate the depth of the tree. + """ Calculate the depth of the tree. Returns ------- @@ -1138,7 +1138,7 @@ def measure_tree_depth(self): return 0 def _new_learning_node(self, initial_class_observations=None): - """Create a new learning node. The type of learning node depends on the tree configuration.""" + """ Create a new learning node. The type of learning node depends on the tree configuration.""" if initial_class_observations is None: initial_class_observations = {} if self._leaf_prediction == MAJORITY_CLASS: @@ -1149,7 +1149,7 @@ def _new_learning_node(self, initial_class_observations=None): return self.LearningNodeNBAdaptive(initial_class_observations) def get_model_description(self): - """Walk the tree and return its structure in a buffer. + """ Walk the tree and return its structure in a buffer. Returns ------- @@ -1167,7 +1167,7 @@ def get_model_description(self): @staticmethod def compute_hoeffding_bound(range_val, confidence, n): - r"""Compute the Hoeffding bound, used to decide how many samples are necessary at each node. + r""" Compute the Hoeffding bound, used to decide how many samples are necessary at each node. Notes ----- @@ -1206,11 +1206,11 @@ def compute_hoeffding_bound(range_val, confidence, n): return np.sqrt((range_val * range_val * np.log(1.0 / confidence)) / (2.0 * n)) def new_split_node(self, split_test, class_observations): - """Create a new split node.""" + """ Create a new split node.""" return self.SplitNode(split_test, class_observations) def _attempt_to_split(self, node: ActiveLearningNode, parent: SplitNode, parent_idx: int): - """Attempt to split a node. + """ Attempt to split a node. If the samples seen so far are not from the same class then: @@ -1293,7 +1293,7 @@ def _attempt_to_split(self, node: ActiveLearningNode, parent: SplitNode, parent_ self.enforce_tracker_limit() def enforce_tracker_limit(self): - """Track the size of the tree and disable/enable nodes if required.""" + """ Track the size of the tree and disable/enable nodes if required.""" byte_size = (self._active_leaf_byte_size_estimate + self._inactive_leaf_node_cnt * self._inactive_leaf_byte_size_estimate) \ * self._byte_size_estimate_overhead_fraction @@ -1324,7 +1324,7 @@ def enforce_tracker_limit(self): learning_nodes[i].parent_branch) def estimate_model_byte_size(self): - """Calculate the size of the model and trigger tracker function if the actual model size exceeds the max size + """ Calculate the size of the model and trigger tracker function if the actual model size exceeds the max size in the configuration.""" learning_nodes = self._find_learning_nodes() total_active_size = 0 @@ -1346,7 +1346,7 @@ def estimate_model_byte_size(self): self.enforce_tracker_limit() def deactivate_all_leaves(self): - """Deactivate all leaves.""" + """ Deactivate all leaves. """ learning_nodes = self._find_learning_nodes() for i in range(len(learning_nodes)): if isinstance(learning_nodes[i], self.ActiveLearningNode): @@ -1355,7 +1355,7 @@ def deactivate_all_leaves(self): learning_nodes[i].parent_branch) def _deactivate_learning_node(self, to_deactivate: ActiveLearningNode, parent: SplitNode, parent_branch: int): - """Deactivate a learning node. + """ Deactivate a learning node. Parameters ---------- @@ -1376,7 +1376,7 @@ def _deactivate_learning_node(self, to_deactivate: ActiveLearningNode, parent: S self._inactive_leaf_node_cnt += 1 def _activate_learning_node(self, to_activate: InactiveLearningNode, parent: SplitNode, parent_branch: int): - """Activate a learning node. + """ Activate a learning node. Parameters ---------- @@ -1397,7 +1397,7 @@ def _activate_learning_node(self, to_activate: InactiveLearningNode, parent: Spl self._inactive_leaf_node_cnt -= 1 def _find_learning_nodes(self): - """Find learning nodes in the tree. + """ Find learning nodes in the tree. Returns ------- @@ -1409,7 +1409,7 @@ def _find_learning_nodes(self): return found_list def __find_learning_nodes(self, node, parent, parent_branch, found): - """Find learning nodes in the tree from a given node. + """ Find learning nodes in the tree from a given node. Parameters ---------- @@ -1437,7 +1437,7 @@ def score(self, X, y): raise NotImplementedError def get_info(self): - """Collect information about the Hoeffding Tree configuration. + """ Collect information about the Hoeffding Tree configuration. Returns ------- From f7b717abda180183901aa8750b0be892ff9fe397 Mon Sep 17 00:00:00 2001 From: PGijsbers Date: Sat, 27 Oct 2018 18:27:29 +0200 Subject: [PATCH 7/8] Type check output of predict and predict_proba. --- tests/bayes/test_naive_bayes.py | 5 ++++- tests/lazy/test_knn.py | 3 +++ tests/lazy/test_knn_adwin.py | 3 +++ tests/lazy/test_sam_knn.py | 3 +++ tests/meta/test_adaptive_random_forests.py | 4 ++++ tests/meta/test_batch_incremental.py | 2 ++ tests/meta/test_classifier_chains.py | 3 +++ tests/meta/test_leverage_bagging.py | 3 +++ tests/meta/test_multi_output_learner.py | 3 ++- tests/meta/test_oza_bagging.py | 2 ++ tests/meta/test_oza_bagging_adwin.py | 2 ++ tests/meta/test_regressor_chains.py | 3 ++- tests/neural_networks/test_perceptron.py | 3 +++ tests/trees/test_hoeffding_adaptive_tree.py | 7 +++++++ tests/trees/test_hoeffding_tree.py | 2 ++ tests/trees/test_lc_hoeffding_tree.py | 5 +++-- tests/trees/test_multi_target_regression_hoeffding_tree.py | 1 + tests/trees/test_regression_hoeffding_adaptive_tree.py | 2 ++ tests/trees/test_regression_hoeffding_tree.py | 2 ++ 19 files changed, 53 insertions(+), 5 deletions(-) diff --git a/tests/bayes/test_naive_bayes.py b/tests/bayes/test_naive_bayes.py index 4c3afbb59..633c75a14 100644 --- a/tests/bayes/test_naive_bayes.py +++ b/tests/bayes/test_naive_bayes.py @@ -53,4 +53,7 @@ def test_naive_bayes(test_path): expected_score = 0.751503006012024 assert np.isclose(expected_score, learner.score(X=X_batch[4501:], y=y_batch[4501:])) - assert 'estimator' == learner.get_class_type() \ No newline at end of file + assert 'estimator' == learner.get_class_type() + + assert type(learner.predict(X)) == np.ndarray + assert type(learner.predict_proba(X)) == np.ndarray diff --git a/tests/lazy/test_knn.py b/tests/lazy/test_knn.py index 395b5ff23..1bf10abf5 100644 --- a/tests/lazy/test_knn.py +++ b/tests/lazy/test_knn.py @@ -58,3 +58,6 @@ def test_knn(): correct_predictions = sum(predictions == y_batch[4501:4550]) expected_correct_predictions = 49 assert correct_predictions == expected_correct_predictions + + assert type(learner.predict(X)) == np.ndarray + assert type(learner.predict_proba(X)) == np.ndarray diff --git a/tests/lazy/test_knn_adwin.py b/tests/lazy/test_knn_adwin.py index e2ccfb612..b0eb57129 100644 --- a/tests/lazy/test_knn_adwin.py +++ b/tests/lazy/test_knn_adwin.py @@ -52,3 +52,6 @@ def test_knn_adwin(): correct_predictions = sum(np.array(predictions) == y[951:]) expected_correct_predictions = 47 assert correct_predictions == expected_correct_predictions + + assert type(learner.predict(X)) == np.ndarray + assert type(learner.predict_proba(X)) == np.ndarray diff --git a/tests/lazy/test_sam_knn.py b/tests/lazy/test_sam_knn.py index 17d4b88e2..e654310f3 100644 --- a/tests/lazy/test_sam_knn.py +++ b/tests/lazy/test_sam_knn.py @@ -41,6 +41,9 @@ def test_sam_knn(package_path): assert np.alltrue(predictions == expected_predictions) + assert type(learner.predict(X)) == np.ndarray + # assert type(learner.predict_proba(X)) == np.ndarray predict_proba not implemented. + def test_sam_knn_coverage(package_path): diff --git a/tests/meta/test_adaptive_random_forests.py b/tests/meta/test_adaptive_random_forests.py index c527e03ae..d1876efb2 100644 --- a/tests/meta/test_adaptive_random_forests.py +++ b/tests/meta/test_adaptive_random_forests.py @@ -45,6 +45,8 @@ def test_adaptive_random_forests(): # Temporary disable as pre-3.6 give different predictions than 3.6+ assert np.alltrue(predictions == last_version_predictions) + assert type(learner.predict(X)) == np.ndarray + def test_adaptive_random_forests_labels_given(): stream = RandomTreeGenerator(tree_random_state=112, sample_random_state=112, n_classes=2) @@ -128,3 +130,5 @@ def test_adaptive_random_forests_batch_predict_proba(): if sys.version_info.major == 3 and sys.version_info.minor >= 6: # Temporary disable as pre-3.6 give different predictions than 3.6+ assert np.alltrue(all_predictions.argmax(axis=1) == last_version_predictions) + + assert type(learner.predict_proba(X)) == np.ndarray diff --git a/tests/meta/test_batch_incremental.py b/tests/meta/test_batch_incremental.py index b1fa5eee4..7305ec68d 100644 --- a/tests/meta/test_batch_incremental.py +++ b/tests/meta/test_batch_incremental.py @@ -48,3 +48,5 @@ def test_batch_incremental(): assert np.alltrue(predictions == expected_predictions) assert np.isclose(expected_performance, performance) assert correct_predictions == expected_correct_predictions + + assert type(learner.predict(X)) == np.ndarray diff --git a/tests/meta/test_classifier_chains.py b/tests/meta/test_classifier_chains.py index cb67f5ccd..a88081e8c 100644 --- a/tests/meta/test_classifier_chains.py +++ b/tests/meta/test_classifier_chains.py @@ -90,6 +90,9 @@ def test_classifier_chains(): assert np.alltrue(np.array_equal(predictions, expected_predictions)) assert correct_predictions == expected_correct_predictions + assert type(learner.predict(X)) == np.ndarray + # assert type(learner.predict_proba(X)) == np.ndarray Not available because default loss is set to 'hinge' + def test_classifier_chains_all(): seed = 1 diff --git a/tests/meta/test_leverage_bagging.py b/tests/meta/test_leverage_bagging.py index 3a56aa910..e51bb77d8 100644 --- a/tests/meta/test_leverage_bagging.py +++ b/tests/meta/test_leverage_bagging.py @@ -40,3 +40,6 @@ def test_leverage_bagging(): assert np.alltrue(predictions == expected_predictions) assert np.isclose(expected_performance, performance) assert correct_predictions == expected_correct_predictions + + assert type(learner.predict(X)) == np.ndarray + assert type(learner.predict_proba(X)) == np.ndarray diff --git a/tests/meta/test_multi_output_learner.py b/tests/meta/test_multi_output_learner.py index 9db762358..3d1138cfd 100644 --- a/tests/meta/test_multi_output_learner.py +++ b/tests/meta/test_multi_output_learner.py @@ -92,4 +92,5 @@ def test_multi_output_learner(): assert np.isclose(expected_performance, perf) assert correct_predictions == expected_correct_predictions - + assert type(classifier.predict(X)) == np.ndarray + assert type(classifier.predict_proba(X)) == np.ndarray diff --git a/tests/meta/test_oza_bagging.py b/tests/meta/test_oza_bagging.py index 8d10039d3..1caa084ac 100644 --- a/tests/meta/test_oza_bagging.py +++ b/tests/meta/test_oza_bagging.py @@ -41,3 +41,5 @@ def test_oza_bagging(): assert np.isclose(expected_performance, performance) assert correct_predictions == expected_correct_predictions + assert type(learner.predict(X)) == np.ndarray + assert type(learner.predict_proba(X)) == np.ndarray diff --git a/tests/meta/test_oza_bagging_adwin.py b/tests/meta/test_oza_bagging_adwin.py index 6d7a515d9..34cf22f06 100644 --- a/tests/meta/test_oza_bagging_adwin.py +++ b/tests/meta/test_oza_bagging_adwin.py @@ -41,3 +41,5 @@ def test_oza_bagging_adwin(): assert np.isclose(expected_performance, performance) assert correct_predictions == expected_correct_predictions + assert type(learner.predict(X)) == np.ndarray + assert type(learner.predict_proba(X)) == np.ndarray diff --git a/tests/meta/test_regressor_chains.py b/tests/meta/test_regressor_chains.py index d8adbceac..e36e4dc5e 100644 --- a/tests/meta/test_regressor_chains.py +++ b/tests/meta/test_regressor_chains.py @@ -81,8 +81,9 @@ def test_regressor_chains(): [-113.86249490223707, 2634310697909.643, 1.580428629322546e+23], [-35.92856878407447, -5410985463428.589, 2.522168862637753e+23]] - print(predictions) assert np.allclose(np.array(predictions).all(), np.array(expected_predictions).all()) + assert type(learner.predict(X)) == np.ndarray + test_regressor_chains() diff --git a/tests/neural_networks/test_perceptron.py b/tests/neural_networks/test_perceptron.py index 16ad46a30..c214e7bf8 100644 --- a/tests/neural_networks/test_perceptron.py +++ b/tests/neural_networks/test_perceptron.py @@ -59,3 +59,6 @@ def test_perceptron(test_path): # assert np.isclose(expected_accuracy, accuracy) # Removed due to npn-replicable error in Travis build assert 'estimator' == learner.get_class_type() + + assert type(learner.predict(X)) == np.ndarray + assert type(learner.predict_proba(X)) == np.ndarray diff --git a/tests/trees/test_hoeffding_adaptive_tree.py b/tests/trees/test_hoeffding_adaptive_tree.py index f47b55794..631cab3ad 100644 --- a/tests/trees/test_hoeffding_adaptive_tree.py +++ b/tests/trees/test_hoeffding_adaptive_tree.py @@ -59,6 +59,9 @@ def test_hat_mc(test_path): or (learner.get_model_description() == expected_model_4) \ + assert type(learner.predict(X)) == np.ndarray + assert type(learner.predict_proba(X)) == np.ndarray + stream.restart() X, y = stream.next_sample(5000) @@ -108,6 +111,8 @@ def test_hat_nb(test_path): ' - nominal_attributes: [] - ' assert learner.get_info() == expected_info + assert type(learner.predict(X)) == np.ndarray + assert type(learner.predict_proba(X)) == np.ndarray def test_hat_nba(test_path): @@ -150,3 +155,5 @@ def test_hat_nba(test_path): ' - nominal_attributes: [] - ' assert learner.get_info() == expected_info + assert type(learner.predict(X)) == np.ndarray + assert type(learner.predict_proba(X)) == np.ndarray diff --git a/tests/trees/test_hoeffding_tree.py b/tests/trees/test_hoeffding_tree.py index ba1778f07..60e4a1006 100644 --- a/tests/trees/test_hoeffding_tree.py +++ b/tests/trees/test_hoeffding_tree.py @@ -53,6 +53,8 @@ def test_hoeffding_tree(test_path): expected_model_2 = 'Leaf = Class 1.0 | {1.0: 1745.0, 2.0: 978.0, 0.0: 1423.0, 3.0: 854.0}\n' assert (learner.get_model_description() == expected_model_1) \ or (learner.get_model_description() == expected_model_2) + assert type(learner.predict(X)) == np.ndarray + assert type(learner.predict_proba(X)) == np.ndarray def test_hoeffding_tree_coverage(): diff --git a/tests/trees/test_lc_hoeffding_tree.py b/tests/trees/test_lc_hoeffding_tree.py index b4259b548..1df256aae 100644 --- a/tests/trees/test_lc_hoeffding_tree.py +++ b/tests/trees/test_lc_hoeffding_tree.py @@ -1,7 +1,6 @@ import numpy as np from skmultiflow.trees import LCHT from skmultiflow.data import MultilabelGenerator -import os def test_lc_hoeffding_tree(test_path): stream = MultilabelGenerator(n_samples=10000, n_features=15, n_targets=3, n_labels=4, random_state=112) @@ -34,4 +33,6 @@ def test_lc_hoeffding_tree(test_path): [1, 0, 1], [0, 1, 1], [1, 1, 1], [1, 1, 1], [0, 1, 0], [0, 1, 0], [1, 1, 1], [1, 1, 1], [1, 1, 1]] - assert np.alltrue(predictions == expected_predictions) \ No newline at end of file + assert np.alltrue(predictions == expected_predictions) + assert type(learner.predict(X)) == np.ndarray + assert type(learner.predict_proba(X)) == np.ndarray diff --git a/tests/trees/test_multi_target_regression_hoeffding_tree.py b/tests/trees/test_multi_target_regression_hoeffding_tree.py index dd17c6328..8fce0ed57 100644 --- a/tests/trees/test_multi_target_regression_hoeffding_tree.py +++ b/tests/trees/test_multi_target_regression_hoeffding_tree.py @@ -49,6 +49,7 @@ def test_multi_target_regression_hoeffding_tree_mean(test_path): 'nominal_attributes: [] - ' assert learner.get_info() == expected_info assert isinstance(learner.get_model_description(), type('')) + assert type(learner.predict(X)) == np.ndarray def test_multi_target_regression_hoeffding_tree_perceptron(test_path): diff --git a/tests/trees/test_regression_hoeffding_adaptive_tree.py b/tests/trees/test_regression_hoeffding_adaptive_tree.py index d593f4a5c..7ca761206 100644 --- a/tests/trees/test_regression_hoeffding_adaptive_tree.py +++ b/tests/trees/test_regression_hoeffding_adaptive_tree.py @@ -53,6 +53,7 @@ def test_hoeffding_tree(): assert learner.get_info() == expected_info assert isinstance(learner.get_model_description(), type('')) + assert type(learner.predict(X)) == np.ndarray def test_hoeffding_tree_perceptron(): @@ -103,3 +104,4 @@ def test_hoeffding_tree_perceptron(): assert learner.get_info() == expected_info assert isinstance(learner.get_model_description(), type('')) + assert type(learner.predict(X)) == np.ndarray diff --git a/tests/trees/test_regression_hoeffding_tree.py b/tests/trees/test_regression_hoeffding_tree.py index 9637480cb..423e0aa09 100644 --- a/tests/trees/test_regression_hoeffding_tree.py +++ b/tests/trees/test_regression_hoeffding_tree.py @@ -54,6 +54,7 @@ def test_hoeffding_tree(): assert learner.get_info() == expected_info assert isinstance(learner.get_model_description(), type('')) + assert type(learner.predict(X)) == np.ndarray def test_hoeffding_tree_perceptron(): @@ -104,6 +105,7 @@ def test_hoeffding_tree_perceptron(): assert learner.get_info() == expected_info assert isinstance(learner.get_model_description(), type('')) + assert type(learner.predict(X)) == np.ndarray def test_hoeffding_tree_coverage(test_path): From d727a17c989323f8217f6981dab2f59bb7445e10 Mon Sep 17 00:00:00 2001 From: PGijsbers Date: Sat, 27 Oct 2018 18:29:47 +0200 Subject: [PATCH 8/8] Fixed output of predict and predict_proba to be of type numpy.ndarray. --- src/skmultiflow/lazy/sam_knn.py | 2 +- src/skmultiflow/meta/adaptive_random_forests.py | 5 +++-- src/skmultiflow/meta/leverage_bagging.py | 8 ++++---- src/skmultiflow/meta/oza_bagging.py | 8 ++++---- src/skmultiflow/neural_networks/perceptron.py | 7 ++++--- src/skmultiflow/trees/regression_hoeffding_tree.py | 4 ++-- 6 files changed, 18 insertions(+), 16 deletions(-) diff --git a/src/skmultiflow/lazy/sam_knn.py b/src/skmultiflow/lazy/sam_knn.py index c27ee0690..4d0e2bb83 100644 --- a/src/skmultiflow/lazy/sam_knn.py +++ b/src/skmultiflow/lazy/sam_knn.py @@ -376,7 +376,7 @@ def predict(self, X): for i in range(r): distancesSTM = SAMKNN.get_distances(X[i], self._STMSamples) predictedLabel.append(self.predictFct(X[i], None, distancesSTM)) - return predictedLabel + return np.asarray(predictedLabel) def predict_proba(self, X): raise NotImplementedError diff --git a/src/skmultiflow/meta/adaptive_random_forests.py b/src/skmultiflow/meta/adaptive_random_forests.py index eb180652e..771ff5fcc 100644 --- a/src/skmultiflow/meta/adaptive_random_forests.py +++ b/src/skmultiflow/meta/adaptive_random_forests.py @@ -1,4 +1,5 @@ from copy import deepcopy +import numpy as np from sklearn.preprocessing import normalize from skmultiflow.core.base_object import BaseObject @@ -230,7 +231,7 @@ def predict(self, X): Samples for which we want to predict the labels. Returns ------- - list + numpy.ndarray Predicted labels for all instances in X. """ r, _ = get_dimensions(X) @@ -242,7 +243,7 @@ def predict(self, X): predictions.append(0) else: predictions.append(max(votes, key=votes.get)) - return predictions + return np.asarray(predictions) def predict_proba(self, X): """ Predicts the class probabilities for the X instance(s). diff --git a/src/skmultiflow/meta/leverage_bagging.py b/src/skmultiflow/meta/leverage_bagging.py index 22addbd9b..d4e86dc92 100644 --- a/src/skmultiflow/meta/leverage_bagging.py +++ b/src/skmultiflow/meta/leverage_bagging.py @@ -316,8 +316,8 @@ def predict(self, X): Returns ------- - list - A list with the label prediction for all the samples in X. + numpy.ndarray + A numpy.ndarray with the label prediction for all the samples in X. """ r, c = get_dimensions(X) @@ -328,7 +328,7 @@ def predict(self, X): proba = np.zeros((r, 1)) for i in range(r): predictions.append(np.argmax(proba[i])) - return predictions + return np.asarray(predictions) def predict_proba(self, X): """ predict_proba @@ -392,7 +392,7 @@ def predict_proba(self, X): aux.append([x / sum_proba[i] for x in proba[i]]) else: aux.append(proba[i]) - return aux + return np.asarray(aux) def predict_binary_proba(self, X): """ predict_binary_proba diff --git a/src/skmultiflow/meta/oza_bagging.py b/src/skmultiflow/meta/oza_bagging.py index 9de454b74..58463980f 100644 --- a/src/skmultiflow/meta/oza_bagging.py +++ b/src/skmultiflow/meta/oza_bagging.py @@ -196,8 +196,8 @@ def predict(self, X): Returns ------- - list - A list with the label prediction for all the samples in X. + numpy.ndarray + A numpy.ndarray with the label prediction for all the samples in X. """ r, c = get_dimensions(X) @@ -207,7 +207,7 @@ def predict(self, X): return None for i in range(r): predictions.append(np.argmax(proba[i])) - return predictions + return np.asarray(predictions) def predict_proba(self, X): """ predict_proba @@ -267,7 +267,7 @@ def predict_proba(self, X): aux.append([x / sum_proba[i] for x in proba[i]]) else: aux.append(proba[i]) - return aux + return np.asarray(aux) def score(self, X, y): raise NotImplementedError diff --git a/src/skmultiflow/neural_networks/perceptron.py b/src/skmultiflow/neural_networks/perceptron.py index 66c908e85..379535e38 100644 --- a/src/skmultiflow/neural_networks/perceptron.py +++ b/src/skmultiflow/neural_networks/perceptron.py @@ -1,3 +1,4 @@ +import numpy as np from skmultiflow.core.base import StreamModel from sklearn.linear_model.perceptron import Perceptron @@ -107,11 +108,11 @@ def predict(self, X): Returns ------- - list - A list containing the predicted labels for all instances in X. + numpy.ndarray + A numpy.ndarray containing the predicted labels for all instances in X. """ - return self.classifier.predict(X) + return np.asarray(self.classifier.predict(X)) def predict_proba(self, X): """ predict_proba diff --git a/src/skmultiflow/trees/regression_hoeffding_tree.py b/src/skmultiflow/trees/regression_hoeffding_tree.py index 975467f01..93e1f6121 100644 --- a/src/skmultiflow/trees/regression_hoeffding_tree.py +++ b/src/skmultiflow/trees/regression_hoeffding_tree.py @@ -555,7 +555,7 @@ def predict(self, X): Returns ------- - list + numpy.ndarray Predicted target values. """ @@ -584,7 +584,7 @@ def predict(self, X): else: # Model is empty predictions.append(0.0) - return predictions + return np.asarray(predictions) def predict_proba(self, X): pass