-
Notifications
You must be signed in to change notification settings - Fork 0
WIP, MAINT: remove dependence on graforvfl #9
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
d5639c7
0711902
f36bcc3
3b4204b
3d39af1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,11 +1,8 @@ | ||
| numpy | ||
| scipy>=1.7.1 | ||
| scikit-learn>=1.2.1 | ||
| pandas | ||
| mealpy>=3.0.2 | ||
| permetrics>=2.0.0 | ||
| matplotlib>=3.7.5 | ||
| numpydoc | ||
| sphinx_copybutton | ||
| sphinx_design | ||
| pydata_sphinx_theme | ||
| pydata_sphinx_theme | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,5 @@ | ||
| import graforvfl | ||
| # tests/test_model.py | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. per gh-10, I think we more or less agreed to stop adding these comments for reasons related to maintainability; that's easy enough to remove |
||
|
|
||
| import numpy as np | ||
| import pytest | ||
| from numpy.testing import assert_allclose | ||
|
|
@@ -363,18 +364,59 @@ def test_invalid_alpha(Classifier): | |
| bad_est.fit(X, y) | ||
|
|
||
|
|
||
| @pytest.mark.parametrize("hidden_layer_sizes", [(10,), (100,)]) | ||
| @pytest.mark.parametrize("n_classes", [2, 5]) | ||
| @pytest.mark.parametrize("activation", activations) | ||
| @pytest.mark.parametrize("weight_scheme", weights[2:]) | ||
| @pytest.mark.parametrize("alpha", [None, 0.5, 1]) | ||
| @pytest.mark.parametrize("""hidden_layer_sizes, | ||
| n_classes, | ||
| activation, | ||
| weight_scheme, | ||
| alpha, | ||
| exp_proba_shape, | ||
| exp_proba_median, | ||
| exp_proba_min""", [ | ||
|
|
||
| # expected values are from graforvfl library | ||
| ([10,], 2, "relu", "uniform", None, (20, 2), 0.5, 0.0444571694), | ||
| ([100,], 2, "tanh", "normal", None, (20, 2), 0.5, 0.02538905725), | ||
| ([10,], 5, "softmax", "lecun_uniform", None, (20, 5), | ||
| 0.186506112, 0.08469873), | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I need help reconstituting a "reasonable" number of permutations "manually," to sample the parameter space that was previously being sampled automatically and compared against It certainly isn't sustainable to restore all the of the cases from the pervious Cartesian product of cases, and that was probably overparametrizing anyway, but certainly what I've done here is not enough. |
||
| ([10,], 2, "relu", "uniform", 0.5, (20, 2), 0.49999999999999994, | ||
| 0.04676933232591643), | ||
| ([10,], 2, "relu", "normal", 0.5, (20, 2), 0.5, | ||
| 0.13832596541020634), | ||
| ([10,], 2, "relu", "he_uniform", 0.5, (20, 2), 0.5, | ||
| 0.09354846081377409), | ||
| ([10,], 2, "relu", "lecun_uniform", 0.5, (20, 2), 0.5, | ||
| 0.09387932375067173), | ||
| ([10,], 2, "relu", "glorot_uniform", 0.5, (20, 2), | ||
| 0.49999999999999994, 0.09474642560519067), | ||
| ([10,], 2, "relu", "he_normal", 0.5, (20, 2), 0.5, | ||
| 0.13756805074436051), | ||
| ([10,], 2, "relu", "lecun_normal", 0.5, (20, 2), 0.5, | ||
| 0.1366715193146648), | ||
| ([10,], 2, "relu", "glorot_normal", 0.5, (20, 2), 0.5, | ||
| 0.147434110768701), | ||
| ([100,], 5, "relu", "normal", 1, (20, 5), 0.15697278777061396, | ||
| 0.014480242978774488), | ||
| ([100,], 5, "tanh", "normal", 1, (20, 5), 0.18173657135483476, | ||
| 0.04755723146401269), | ||
| ([100,], 5, "sigmoid", "normal", 1, (20, 5), 0.1831653950464296, | ||
| 0.05378741996708733), | ||
| ([100,], 5, "softmax", "normal", 1, (20, 5), 0.19357646668265396, | ||
| 0.10898717209741866), | ||
| ([100,], 5, "softmin", "normal", 1, (20, 5), 0.18746771358297387, | ||
| 0.09186562406164228), | ||
| ([100,], 5, "log_sigmoid", "normal", 1, (20, 5), | ||
| 0.16722029352468032, 0.012690348255702557), | ||
| ([100,], 5, "log_softmax", "normal", 1, (20, 5), | ||
| 0.1853363666712296, 0.10846041127337658), | ||
| ]) | ||
| def test_classification_against_grafo(hidden_layer_sizes, n_classes, activation, | ||
| weight_scheme, alpha): | ||
| # test binary and multi-class classification against | ||
| # the open source graforvfl library on some synthetic | ||
| weight_scheme, alpha, exp_proba_shape, | ||
| exp_proba_median, exp_proba_min): | ||
| # test binary and multi-class classification against expected values | ||
| # from the open source graforvfl library on some synthetic | ||
| # datasets | ||
| X, y = make_classification(n_classes=n_classes, | ||
| n_informative=8) | ||
| n_informative=8, random_state=0) | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this was a problem with the old code--we should pretty much always pin random seeds in test case generation--it wasn't being caught because both our library and grafo were getting the same varied data... |
||
| X_train, X_test, y_train, _ = train_test_split(X, y, test_size=0.2, | ||
| random_state=0) | ||
| model = GFDLClassifier(hidden_layer_sizes=hidden_layer_sizes, | ||
|
|
@@ -385,26 +427,14 @@ def test_classification_against_grafo(hidden_layer_sizes, n_classes, activation, | |
| reg_alpha=alpha) | ||
| model.fit(X_train, y_train) | ||
|
|
||
| grafo_act = "none" if activation == "identity" else activation | ||
| if weight_scheme == "uniform": | ||
| grafo_wts = "random_uniform" | ||
| elif weight_scheme == "normal": | ||
| grafo_wts = "random_normal" | ||
| else: | ||
| grafo_wts = weight_scheme | ||
|
|
||
| grafo_rvfl = graforvfl.RvflClassifier(size_hidden=hidden_layer_sizes[0], | ||
| act_name=grafo_act, | ||
| weight_initializer=grafo_wts, | ||
| reg_alpha=alpha, | ||
| seed=0) | ||
|
|
||
| grafo_rvfl.fit(X_train, y_train) | ||
|
|
||
| actual_proba = model.predict_proba(X_test) | ||
| expected_proba = grafo_rvfl.predict_proba(X_test) | ||
| actual_proba_shape = actual_proba.shape | ||
| actual_proba_median = np.median(actual_proba) | ||
| actual_proba_min = np.min(actual_proba) | ||
|
|
||
| np.testing.assert_allclose(actual_proba, expected_proba, rtol=2.5e-07) | ||
| np.testing.assert_allclose(actual_proba_shape, exp_proba_shape) | ||
| np.testing.assert_allclose(actual_proba_median, exp_proba_median) | ||
| np.testing.assert_allclose(actual_proba_min, exp_proba_min) | ||
|
|
||
|
|
||
| @parametrize_with_checks([GFDLClassifier(), EnsembleGFDLClassifier()]) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,5 @@ | ||
| import numpy as np | ||
| import pytest | ||
| from graforvfl import RvflRegressor | ||
| from sklearn.datasets import fetch_openml, make_regression | ||
| from sklearn.metrics import r2_score | ||
| from sklearn.model_selection import train_test_split | ||
|
|
@@ -9,20 +8,59 @@ | |
|
|
||
| from gfdl.model import GFDLRegressor | ||
|
|
||
| activations = ["relu", "tanh", "sigmoid", "identity", "softmax", "softmin", | ||
| "log_sigmoid", "log_softmax"] | ||
| weights = ["uniform", "normal", "he_uniform", "lecun_uniform", | ||
| "glorot_uniform", "he_normal", "lecun_normal", "glorot_normal"] | ||
|
|
||
|
|
||
| @pytest.mark.parametrize("n_samples", [100, 1000]) | ||
| @pytest.mark.parametrize("n_targets", [10, 100]) | ||
| @pytest.mark.parametrize("hidden_layer_sizes", [(100,), (1000,)]) | ||
| @pytest.mark.parametrize("activation", activations) | ||
| @pytest.mark.parametrize("weight_scheme", weights) | ||
| @pytest.mark.parametrize("reg_alpha", [1, 10]) | ||
| @pytest.mark.parametrize("""n_samples, | ||
| n_targets, | ||
| hidden_layer_sizes, | ||
| activation, | ||
| weight_scheme, | ||
| reg_alpha, | ||
| exp_preds_shape, | ||
| exp_preds_median, | ||
| exp_preds_min, | ||
| exp_preds_r2""", [ | ||
| # expected values are from the graforvfl library | ||
| (100, 10, (100,), "relu", "glorot_normal", 10, (25, 10), | ||
| -29.31478018, -490.57518221, 0.97537085), | ||
| (100, 10, (100,), "tanh", "uniform", 1, (25, 10), | ||
| -43.03897314, -504.32794352, 0.98411997), | ||
| (100, 10, (100,), "log_softmax", "uniform", 1, (25, 10), | ||
| -30.56871963218171, -558.1388909597706, 0.9999532782125536), | ||
| (100, 10, (100,), "log_sigmoid", "normal", 10, (25, 10), | ||
| -19.5976250350991, -574.1699708675857, 0.9853855947182326), | ||
| (100, 10, (1000,), "softmin", "he_uniform", 1, (25, 10), | ||
| -57.91870287977487, -589.6707200160679, 0.9656730623177637), | ||
| (100, 10, (1000,), "softmax", "lecun_uniform", 10, (25, 10), | ||
| -51.938696542946786, -513.4094105001416, 0.9589931777194366), | ||
| (100, 100, (100,), "sigmoid", "glorot_uniform", 1, (25, 100), | ||
| -46.92889730988215, -1585.2331437646524, 0.6496204322668526), | ||
| (100, 100, (100,), "tanh", "he_normal", 10, (25, 100), | ||
| -5.531248709518545, -1131.5021652659007, 0.6018381457540279), | ||
| (100, 100, (1000,), "relu", "lecun_normal", 1, (25, 100), | ||
| -24.857674257413233, -1241.941403822942, 0.5954067650339964), | ||
| (100, 100, (1000,), "identity", "glorot_normal", 10, (25, 100), | ||
| -49.66037744636776, -1418.0996396366454, 0.6387637880009253), | ||
| (1000, 10, (100,), "log_softmax", "glorot_normal", 1, (250, 10), | ||
| -2.157983014856103, -821.8910528092026, 0.999999671320564), | ||
| (1000, 10, (100,), "log_sigmoid", "lecun_normal", 10, (250, 10), | ||
| -2.25281191108881, -813.3197346939389, 0.9998208055604957), | ||
| (1000, 10, (1000,), "softmin", "he_normal", 1, (250, 10), | ||
| -2.932635323616438, -819.9889270165279, 0.9999535335431835), | ||
| (1000, 10, (1000,), "softmax", "glorot_uniform", 10, (250, 10), | ||
| -3.27895924524588, -809.0526184106433, 0.9996980844468629), | ||
| (1000, 100, (100,), "sigmoid", "lecun_uniform", 1, (250, 100), | ||
| 40.193814730616296, -2003.2760146757932, 0.9999864051131802), | ||
| (1000, 100, (100,), "tanh", "he_normal", 10, (250, 100), | ||
| 38.349789631939906, -1968.7361166078529, 0.9984649082549426), | ||
| (1000, 100, (1000,), "relu", "normal", 1, (250, 100), | ||
| 47.91240910167704, -2194.259205351918, 0.8620693547752554), | ||
| (1000, 100, (1000,), "identity", "uniform", 10, (250, 100), | ||
| 39.788475103832646, -2004.3219743138504, 0.9999999882159872) | ||
| ]) | ||
| def test_regression_against_grafo(n_samples, n_targets, hidden_layer_sizes, | ||
| activation, weight_scheme, reg_alpha): | ||
| activation, weight_scheme, reg_alpha, | ||
| exp_preds_shape, exp_preds_median, | ||
| exp_preds_min, exp_preds_r2): | ||
| N, d = n_samples, n_targets | ||
| RNG = 42 | ||
| X, y = make_regression(n_samples=N, | ||
|
|
@@ -42,48 +80,24 @@ def test_regression_against_grafo(n_samples, n_targets, hidden_layer_sizes, | |
| X_train_s = scaler.transform(X_train) | ||
| X_test_s = scaler.transform(X_test) | ||
|
|
||
| grafo_act = "none" if activation == "identity" else activation | ||
| if weight_scheme == "uniform": | ||
| grafo_wts = "random_uniform" | ||
| elif weight_scheme == "normal": | ||
| grafo_wts = "random_normal" | ||
| else: | ||
| grafo_wts = weight_scheme | ||
|
|
||
| # Define models | ||
| models = { | ||
| "GrafoRVFL": RvflRegressor( | ||
| size_hidden=hidden_layer_sizes[0], | ||
| act_name=grafo_act, | ||
| weight_initializer=grafo_wts, | ||
| reg_alpha=reg_alpha, | ||
| seed=RNG | ||
| ), | ||
| "GFDL": GFDLRegressor( | ||
| model = GFDLRegressor( | ||
| hidden_layer_sizes=hidden_layer_sizes, | ||
| activation=activation, | ||
| weight_scheme=weight_scheme, | ||
| direct_links=1, | ||
| seed=RNG, | ||
| reg_alpha=reg_alpha | ||
| ) | ||
| } | ||
|
|
||
| # Fit + predict | ||
| preds = {} | ||
|
|
||
| for name, model in models.items(): | ||
| Xtr, Xte = (X_train_s, X_test_s) | ||
| model.fit(Xtr, y_train) | ||
| yhat = model.predict(Xte) | ||
| preds[name] = yhat | ||
|
|
||
| # Compare GrafoRVFL and GFDL results | ||
| grf_results = preds["GrafoRVFL"] | ||
| cur_results = preds["GFDL"] | ||
|
|
||
| # Test results | ||
| np.testing.assert_allclose(cur_results, grf_results, atol=1e-07) | ||
| model.fit(X_train_s, y_train) | ||
| actual_preds = model.predict(X_test_s) | ||
| actual_preds_shape = actual_preds.shape | ||
| actual_preds_median = np.median(actual_preds) | ||
| actual_preds_min = actual_preds.min() | ||
| actual_preds_r2 = r2_score(y_test, actual_preds) | ||
| np.testing.assert_allclose(actual_preds_shape, exp_preds_shape) | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We could be a bit stricter here and for classifier test above with |
||
| np.testing.assert_allclose(actual_preds_median, exp_preds_median) | ||
| np.testing.assert_allclose(actual_preds_min, exp_preds_min) | ||
| np.testing.assert_allclose(actual_preds_r2, exp_preds_r2) | ||
|
|
||
|
|
||
| @parametrize_with_checks([GFDLRegressor()]) | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
these are transitive deps (via grafo), so being removed here (assuming we agree to remove grafo usage..)