From 80fcac05896e433ce89265b84185881c9cf0b4eb Mon Sep 17 00:00:00 2001 From: janezd Date: Thu, 27 Aug 2020 17:58:30 +0200 Subject: [PATCH 1/3] OWLinearRegression: Add option to set intercept to 0 --- Orange/regression/linear.py | 4 +++- Orange/widgets/model/owlinearregression.py | 25 +++++++++++++++++----- 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/Orange/regression/linear.py b/Orange/regression/linear.py index 361929a9008..ac88769e8ff 100644 --- a/Orange/regression/linear.py +++ b/Orange/regression/linear.py @@ -28,8 +28,10 @@ def score(self, data): class LinearRegressionLearner(SklLearner, _FeatureScorerMixin): __wraps__ = skl_linear_model.LinearRegression - def __init__(self, preprocessors=None): + # Arguments are needed for signatures, pylint: disable=unused-argument + def __init__(self, preprocessors=None, fit_intercept=True): super().__init__(preprocessors=preprocessors) + self.params = vars() def fit(self, X, Y, W=None): model = super().fit(X, Y, W) diff --git a/Orange/widgets/model/owlinearregression.py b/Orange/widgets/model/owlinearregression.py index b9e13d6a6cf..8853485a62d 100644 --- a/Orange/widgets/model/owlinearregression.py +++ b/Orange/widgets/model/owlinearregression.py @@ -39,6 +39,7 @@ class Outputs(OWBaseLearner.Outputs): reg_type = settings.Setting(OLS) alpha_index = settings.Setting(0) l2_ratio = settings.Setting(0.5) + fit_intercept = settings.Setting(True) autosend = settings.Setting(True) alphas = list(chain([x / 10000 for x in range(1, 10)], @@ -51,6 +52,11 @@ class Outputs(OWBaseLearner.Outputs): def add_main_layout(self): # this is part of init, pylint: disable=attribute-defined-outside-init + box = gui.hBox(self.controlArea, "Parameters") + gui.checkBox(box, self, "fit_intercept", + "Fit intercept (unchecking it fixes it to zero)", + callback=self._intercept_changed) + box = gui.hBox(self.controlArea, "Regularization") gui.radioButtons(box, self, "reg_type", btnLabels=self.REGULARIZATION_TYPES, @@ -93,6 +99,9 @@ def add_main_layout(self): def handleNewSignals(self): self.apply() + def _intercept_changed(self): + self.apply() + def _reg_type_changed(self): self.controls.alpha_index.setEnabled(self.reg_type != self.OLS) self.l2_ratio_slider.setEnabled(self.reg_type == self.Elastic) @@ -116,7 +125,8 @@ def _l2_ratio_changed(self): def create_learner(self): alpha = self.alphas[self.alpha_index] preprocessors = self.preprocessors - args = {"preprocessors": preprocessors} + args = dict(preprocessors=preprocessors, + fit_intercept=self.fit_intercept) if self.reg_type == OWLinearRegression.OLS: learner = LinearRegressionLearner(**args) elif self.reg_type == OWLinearRegression.Ridge: @@ -134,9 +144,11 @@ def update_model(self): if self.model is not None: domain = Domain( [ContinuousVariable("coef")], metas=[StringVariable("name")]) - coefs = [self.model.intercept] + list(self.model.coefficients) - names = ["intercept"] + \ - [attr.name for attr in self.model.domain.attributes] + coefs = list(self.model.coefficients) + names = [attr.name for attr in self.model.domain.attributes] + if self.fit_intercept: + coefs.insert(0, self.model.intercept) + names.insert(0, "intercept") coef_table = Table.from_list(domain, list(zip(coefs, names))) coef_table.name = "coefficients" self.Outputs.coefficients.send(coef_table) @@ -155,7 +167,10 @@ def get_learner_parameters(self): .format(self.alphas[self.alpha_index], self.l2_ratio, 1 - self.l2_ratio)) - return (("Regularization", regularization), ) + return ( + ("Regularization", regularization), + ("Fit intercept", ["No", "Yes"][self.fit_intercept]) + ) if __name__ == "__main__": # pragma: no cover From 2f4c44f3aba51f0bc2dcc8b95d29c8c94becc5f0 Mon Sep 17 00:00:00 2001 From: janezd Date: Thu, 27 Aug 2020 17:58:54 +0200 Subject: [PATCH 2/3] Orange.regression.linear: Lint --- Orange/regression/linear.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Orange/regression/linear.py b/Orange/regression/linear.py index ac88769e8ff..299ae59eb83 100644 --- a/Orange/regression/linear.py +++ b/Orange/regression/linear.py @@ -41,6 +41,7 @@ def fit(self, X, Y, W=None): class RidgeRegressionLearner(LinearRegressionLearner): __wraps__ = skl_linear_model.Ridge + # Arguments are needed for signatures, pylint: disable=unused-argument def __init__(self, alpha=1.0, fit_intercept=True, normalize=False, copy_X=True, max_iter=None, tol=0.001, solver='auto', preprocessors=None): @@ -51,6 +52,7 @@ def __init__(self, alpha=1.0, fit_intercept=True, class LassoRegressionLearner(LinearRegressionLearner): __wraps__ = skl_linear_model.Lasso + # Arguments are needed for signatures, pylint: disable=unused-argument def __init__(self, alpha=1.0, fit_intercept=True, normalize=False, precompute=False, copy_X=True, max_iter=1000, tol=0.0001, warm_start=False, positive=False, @@ -62,6 +64,7 @@ def __init__(self, alpha=1.0, fit_intercept=True, normalize=False, class ElasticNetLearner(LinearRegressionLearner): __wraps__ = skl_linear_model.ElasticNet + # Arguments are needed for signatures, pylint: disable=unused-argument def __init__(self, alpha=1.0, l1_ratio=0.5, fit_intercept=True, normalize=False, precompute=False, max_iter=1000, copy_X=True, tol=0.0001, warm_start=False, positive=False, @@ -73,6 +76,7 @@ def __init__(self, alpha=1.0, l1_ratio=0.5, fit_intercept=True, class ElasticNetCVLearner(LinearRegressionLearner): __wraps__ = skl_linear_model.ElasticNetCV + # Arguments are needed for signatures, pylint: disable=unused-argument def __init__(self, l1_ratio=0.5, eps=0.001, n_alphas=100, alphas=None, fit_intercept=True, normalize=False, precompute='auto', max_iter=1000, tol=0.0001, cv=5, copy_X=True, @@ -85,6 +89,7 @@ class SGDRegressionLearner(LinearRegressionLearner): __wraps__ = skl_linear_model.SGDRegressor preprocessors = SklLearner.preprocessors + [Normalize()] + # Arguments are needed for signatures, pylint: disable=unused-argument def __init__(self, loss='squared_loss', penalty='l2', alpha=0.0001, l1_ratio=0.15, fit_intercept=True, max_iter=5, tol=1e-3, shuffle=True, epsilon=0.1, n_jobs=1, random_state=None, @@ -142,6 +147,7 @@ def __str__(self): class PolynomialModel(Model): def __init__(self, model, polyfeatures): + super().__init__() self.model = model self.polyfeatures = polyfeatures From cb5a551bbf070c3b6be599cb23ba6428348360df Mon Sep 17 00:00:00 2001 From: janezd Date: Thu, 27 Aug 2020 18:52:45 +0200 Subject: [PATCH 3/3] Polynomial Learner: Add argument include_bias --- Orange/regression/linear.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Orange/regression/linear.py b/Orange/regression/linear.py index 299ae59eb83..5f9825a0cc9 100644 --- a/Orange/regression/linear.py +++ b/Orange/regression/linear.py @@ -116,13 +116,15 @@ class PolynomialLearner(Learner): preprocessors = SklLearner.preprocessors def __init__(self, learner=LinearRegressionLearner(), degree=2, - preprocessors=None): + preprocessors=None, include_bias=True): super().__init__(preprocessors=preprocessors) self.degree = degree self.learner = learner + self.include_bias = include_bias def fit(self, X, Y, W=None): - polyfeatures = skl_preprocessing.PolynomialFeatures(self.degree) + polyfeatures = skl_preprocessing.PolynomialFeatures( + self.degree, include_bias=self.include_bias) X = polyfeatures.fit_transform(X) clf = self.learner if W is None or not self.supports_weights: