From f1d6ce73c416799490d8ed0aa6f9128d584ec70a Mon Sep 17 00:00:00 2001 From: Vaux Gomes Date: Thu, 1 Apr 2021 10:06:49 -0300 Subject: [PATCH] Rules can be printted now. However it is necessary postprocess the conditions to simplify the rules. Maybe in a next commit --- examples.py | 10 ++++++++-- lad/lad.py | 7 +++++-- lad/rulegenerator/eager.py | 29 +++++++++++++++++++++++++---- lad/rulegenerator/lazy.py | 3 +++ 4 files changed, 41 insertions(+), 8 deletions(-) diff --git a/examples.py b/examples.py index 5c0e852..00327f3 100644 --- a/examples.py +++ b/examples.py @@ -17,9 +17,15 @@ X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33, random_state=1) # Clasisfier -clf = LADClassifier(mode='lazy') +clf = LADClassifier(mode='eager') clf.fit(X_train, y_train) y_hat = clf.predict(X_test) -print(classification_report(y_test, y_hat)) \ No newline at end of file +print(classification_report(y_test, y_hat)) + +print(clf) + +# scores = cross_validate(LADClassifier(mode='eager'), X, y, scoring=['accuracy']) + +# print(np.mean(scores['test_accuracy'])) \ No newline at end of file diff --git a/lad/lad.py b/lad/lad.py index 4fdec58..a345843 100644 --- a/lad/lad.py +++ b/lad/lad.py @@ -74,7 +74,7 @@ def fit(self, X, y): elif self.mode == 'lazy': self.model = LazyPatterns(cpb, gsc) - + self.model.fit(Xbin, y) return self # `fit` should always return `self` @@ -89,4 +89,7 @@ def predict_proba(self, X): X = check_array(X, accept_sparse=True) check_is_fitted(self, 'is_fitted_') - return self.model.predict_proba(X) \ No newline at end of file + return self.model.predict_proba(X) + + def __str__(self): + return self.model.__str__() \ No newline at end of file diff --git a/lad/rulegenerator/eager.py b/lad/rulegenerator/eager.py index a42333c..2072718 100644 --- a/lad/rulegenerator/eager.py +++ b/lad/rulegenerator/eager.py @@ -1,6 +1,5 @@ import numpy as np - class MaxPatterns(): def __init__(self, binarizer, selector, purity): @@ -10,9 +9,6 @@ def __init__(self, binarizer, selector, purity): self.__cutpoints = binarizer.get_cutpoints() self.__selected = selector.get_selected() - def get_rules(self): - return self.__rules - def predict(self, X): weights = {} @@ -146,6 +142,8 @@ def __adjust(self): for c in __cutpoints: r['attributes'].append(c[0]) r['values'].append(c[1]) + + self.__rules.sort(key=lambda x: x['label']) def __get_stats(self, Xbin, y, instance, attributes): covered = np.where( @@ -174,3 +172,26 @@ def __get_stats(self, Xbin, y, instance, attributes): max(1.0, distance_other)/max(1.0, len(uncovered_other))) return len(covered), counts[argmax], purity, label, discrepancy + + def __str__(self): + s = f'MaxPatterns Set of Rules [{len(self.__rules)}]:\n' + + for r in self.__rules: + label = r['label'] + # weight = r['weight'] + conditions = [] + + for i, condition in enumerate(r['conditions']): + att = r['attributes'][i] + val = r['values'][i] + + if (condition): + conditions.append(f'att{att} <= {val:.4}') + else: + conditions.append(f'att{att} > {val:.4}') + + # Label -> CONDITION_1 AND CONDITION_2 AND CONDITION_n + s += f'{label} \u2192 {" AND ".join(conditions)}\n' + + return s + diff --git a/lad/rulegenerator/lazy.py b/lad/rulegenerator/lazy.py index 09d66a5..4c82a37 100644 --- a/lad/rulegenerator/lazy.py +++ b/lad/rulegenerator/lazy.py @@ -104,3 +104,6 @@ def __get_stats(self, instance, attributes, label): lift = (counts[argmax]/len(covered[0]))/(self.__labels[unique[argmax]]/self.__y.shape[0]) return label, confidence, support, lift + + def __str__(self): + print(f'LazyPatterns Set of Rules [None]:') \ No newline at end of file