From 165c97c107aa52fddb6951c7092f2dccb164c64d Mon Sep 17 00:00:00 2001 From: Lars Reimann Date: Mon, 27 Mar 2023 12:48:03 +0200 Subject: [PATCH] feat: return new model when calling `fit` (#91) Closes #69. ### Summary of Changes The `fit` method of classifiers/regressors now returns a new (fitted) classifier regressor. The receiver of the method call is not changed anymore. This is consistent with the methods on the `Table` class and other data containers. Furthermore, `fit` is now a pure function, which works better in notebooks and our own [execution strategy](https://arxiv.org/abs/2302.14556). --------- Co-authored-by: lars-reimann --- docs/tutorials/machine_learning.ipynb | 6 ++-- src/safeds/ml/_util_sklearn.py | 8 +++-- src/safeds/ml/classification/_ada_boost.py | 33 ++++++++++++----- src/safeds/ml/classification/_classifier.py | 16 ++++++--- .../ml/classification/_decision_tree.py | 33 ++++++++++++----- .../_gradient_boosting_classification.py | 33 ++++++++++++----- .../ml/classification/_k_nearest_neighbors.py | 36 +++++++++++++------ .../ml/classification/_logistic_regression.py | 33 ++++++++++++----- .../ml/classification/_random_forest.py | 33 ++++++++++++----- src/safeds/ml/regression/_ada_boost.py | 33 ++++++++++++----- src/safeds/ml/regression/_decision_tree.py | 33 ++++++++++++----- .../ml/regression/_elastic_net_regression.py | 33 ++++++++++++----- .../_gradient_boosting_regression.py | 36 +++++++++++++------ .../ml/regression/_k_nearest_neighbors.py | 35 +++++++++++++----- src/safeds/ml/regression/_lasso_regression.py | 33 ++++++++++++----- .../ml/regression/_linear_regression.py | 33 ++++++++++++----- src/safeds/ml/regression/_random_forest.py | 33 ++++++++++++----- src/safeds/ml/regression/_regressor.py | 16 ++++++--- src/safeds/ml/regression/_ridge_regression.py | 33 ++++++++++++----- .../ml/classification/test_ada_boost.py | 8 ++--- .../ml/classification/test_decision_tree.py | 8 ++--- .../classification/test_gradient_boosting.py | 8 ++--- .../test_k_nearest_neighbors.py | 8 ++--- .../test_logistic_regression.py | 8 ++--- .../ml/classification/test_random_forest.py | 8 ++--- tests/safeds/ml/regression/test_ada_boost.py | 8 ++--- .../ml/regression/test_decision_tree.py | 8 ++--- .../safeds/ml/regression/test_elastic_net.py | 8 ++--- .../ml/regression/test_gradient_boosting.py | 8 ++--- .../ml/regression/test_k_nearest_neighbors.py | 8 ++--- .../ml/regression/test_lasso_regression.py | 8 ++--- .../ml/regression/test_linear_regression.py | 8 ++--- .../ml/regression/test_random_forest.py | 8 ++--- .../ml/regression/test_ridge_regression.py | 8 ++--- tests/safeds/ml/test_util_sklearn.py | 4 +-- 35 files changed, 473 insertions(+), 200 deletions(-) diff --git a/docs/tutorials/machine_learning.ipynb b/docs/tutorials/machine_learning.ipynb index 11c5641f3..809b85df5 100644 --- a/docs/tutorials/machine_learning.ipynb +++ b/docs/tutorials/machine_learning.ipynb @@ -60,7 +60,7 @@ "from safeds.ml.regression import LinearRegression\n", "\n", "model = LinearRegression()\n", - "model.fit(tagged_table)" + "fitted_model = model.fit(tagged_table)" ], "metadata": { "collapsed": false @@ -71,7 +71,7 @@ "source": [ "## Predicting new values\n", "\n", - "The `fit` method trains the model in place. This means that the model object is modified and can be used to make predictions. Predictions are made by calling the `predict` method on the model object. The `predict` method takes a `Table` as input and returns a `Table` with the predictions:" + "The `fit` method returns the fitted model, the original model is **not** changed. Predictions are made by calling the `predict` method on the fitted model. The `predict` method takes a `Table` as input and returns a `Table` with the predictions:" ], "metadata": { "collapsed": false @@ -87,7 +87,7 @@ " \"b\": [2, 0, 5, 2, 7],\n", " \"c\": [1, 4, 3, 2, 1]})\n", "\n", - "model.predict(dataset=test_set)\n" + "fitted_model.predict(dataset=test_set)\n" ], "metadata": { "collapsed": false diff --git a/src/safeds/ml/_util_sklearn.py b/src/safeds/ml/_util_sklearn.py index 5de4708b0..a403682f7 100644 --- a/src/safeds/ml/_util_sklearn.py +++ b/src/safeds/ml/_util_sklearn.py @@ -1,4 +1,4 @@ -from typing import Any +from typing import Any, Optional from safeds.data.tabular.containers import Table, TaggedTable from safeds.exceptions import LearningError, PredictionError @@ -34,7 +34,7 @@ def fit(model: Any, tagged_table: TaggedTable) -> None: # noinspection PyProtectedMember -def predict(model: Any, dataset: Table, target_name: str) -> TaggedTable: +def predict(model: Any, dataset: Table, target_name: Optional[str]) -> TaggedTable: """ Predict a target vector using a dataset containing feature vectors. The model has to be trained first. @@ -57,6 +57,10 @@ def predict(model: Any, dataset: Table, target_name: str) -> TaggedTable: PredictionError If predicting with the given dataset failed. """ + + if model is None or target_name is None: + raise PredictionError("The model was not trained") + dataset_df = dataset._data dataset_df.columns = dataset.schema.get_column_names() try: diff --git a/src/safeds/ml/classification/_ada_boost.py b/src/safeds/ml/classification/_ada_boost.py index 55a503b9b..4c6080d65 100644 --- a/src/safeds/ml/classification/_ada_boost.py +++ b/src/safeds/ml/classification/_ada_boost.py @@ -1,3 +1,7 @@ +from __future__ import annotations + +from typing import Optional + from safeds.data.tabular.containers import Table, TaggedTable from safeds.ml._util_sklearn import fit, predict from sklearn.ensemble import AdaBoostClassifier as sk_AdaBoostClassifier @@ -12,25 +16,38 @@ class AdaBoost(Classifier): """ def __init__(self) -> None: - self._wrapped_classifier = sk_AdaBoostClassifier() - self._target_name = "" + self._wrapped_classifier: Optional[sk_AdaBoostClassifier] = None + self._target_name: Optional[str] = None - def fit(self, training_set: TaggedTable) -> None: + def fit(self, training_set: TaggedTable) -> AdaBoost: """ - Fit this model given a tagged table. + Create a new classifier based on this one and fit it with the given training data. This classifier is not + modified. Parameters ---------- training_set : TaggedTable - The tagged table containing the feature and target vectors. + The training data containing the feature and target vectors. + + Returns + ------- + fitted_classifier : AdaBoost + The fitted classifier. Raises ------ LearningError - If the tagged table contains invalid values or if the training failed. + If the training data contains invalid values or if the training failed. """ - fit(self._wrapped_classifier, training_set) - self._target_name = training_set.target.name + + wrapped_classifier = sk_AdaBoostClassifier() + fit(wrapped_classifier, training_set) + + result = AdaBoost() + result._wrapped_classifier = wrapped_classifier + result._target_name = training_set.target.name + + return result def predict(self, dataset: Table) -> TaggedTable: """ diff --git a/src/safeds/ml/classification/_classifier.py b/src/safeds/ml/classification/_classifier.py index ef4c59710..3c30ca13d 100644 --- a/src/safeds/ml/classification/_classifier.py +++ b/src/safeds/ml/classification/_classifier.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from abc import ABC, abstractmethod from safeds.data.tabular.containers import Table, TaggedTable @@ -10,19 +12,25 @@ class Classifier(ABC): """ @abstractmethod - def fit(self, training_set: TaggedTable) -> None: + def fit(self, training_set: TaggedTable) -> Classifier: """ - Fit this model given a tagged table. + Create a new classifier based on this one and fit it with the given training data. This classifier is not + modified. Parameters ---------- training_set : TaggedTable - The tagged table containing the feature and target vectors. + The training data containing the feature and target vectors. + + Returns + ------- + fitted_classifier : Classifier + The fitted classifier. Raises ------ LearningError - If the tagged table contains invalid values or if the training failed. + If the training data contains invalid values or if the training failed. """ @abstractmethod diff --git a/src/safeds/ml/classification/_decision_tree.py b/src/safeds/ml/classification/_decision_tree.py index 317549b17..aa83ee77b 100644 --- a/src/safeds/ml/classification/_decision_tree.py +++ b/src/safeds/ml/classification/_decision_tree.py @@ -1,3 +1,7 @@ +from __future__ import annotations + +from typing import Optional + from safeds.data.tabular.containers import Table, TaggedTable from safeds.ml._util_sklearn import fit, predict from sklearn.tree import DecisionTreeClassifier as sk_DecisionTreeClassifier @@ -12,25 +16,38 @@ class DecisionTree(Classifier): """ def __init__(self) -> None: - self._wrapped_classifier = sk_DecisionTreeClassifier() - self._target_name = "" + self._wrapped_classifier: Optional[sk_DecisionTreeClassifier] = None + self._target_name: Optional[str] = None - def fit(self, training_set: TaggedTable) -> None: + def fit(self, training_set: TaggedTable) -> DecisionTree: """ - Fit this model given a tagged table. + Create a new classifier based on this one and fit it with the given training data. This classifier is not + modified. Parameters ---------- training_set : TaggedTable - The tagged table containing the feature and target vectors. + The training data containing the feature and target vectors. + + Returns + ------- + fitted_classifier : DecisionTree + The fitted classifier. Raises ------ LearningError - If the tagged table contains invalid values or if the training failed. + If the training data contains invalid values or if the training failed. """ - fit(self._wrapped_classifier, training_set) - self._target_name = training_set.target.name + + wrapped_classifier = sk_DecisionTreeClassifier() + fit(wrapped_classifier, training_set) + + result = DecisionTree() + result._wrapped_classifier = wrapped_classifier + result._target_name = training_set.target.name + + return result def predict(self, dataset: Table) -> TaggedTable: """ diff --git a/src/safeds/ml/classification/_gradient_boosting_classification.py b/src/safeds/ml/classification/_gradient_boosting_classification.py index 5d80292a6..4252783a9 100644 --- a/src/safeds/ml/classification/_gradient_boosting_classification.py +++ b/src/safeds/ml/classification/_gradient_boosting_classification.py @@ -1,3 +1,7 @@ +from __future__ import annotations + +from typing import Optional + from safeds.data.tabular.containers import Table, TaggedTable from safeds.ml._util_sklearn import fit, predict from sklearn.ensemble import GradientBoostingClassifier as sk_GradientBoostingClassifier @@ -12,25 +16,38 @@ class GradientBoosting(Classifier): """ def __init__(self) -> None: - self._wrapped_classifier = sk_GradientBoostingClassifier() - self._target_name = "" + self._wrapped_classifier: Optional[sk_GradientBoostingClassifier] = None + self._target_name: Optional[str] = None - def fit(self, training_set: TaggedTable) -> None: + def fit(self, training_set: TaggedTable) -> GradientBoosting: """ - Fit this model given a tagged table. + Create a new classifier based on this one and fit it with the given training data. This classifier is not + modified. Parameters ---------- training_set : TaggedTable - The tagged table containing the feature and target vectors. + The training data containing the feature and target vectors. + + Returns + ------- + fitted_classifier : GradientBoosting + The fitted classifier. Raises ------ LearningError - If the tagged table contains invalid values or if the training failed. + If the training data contains invalid values or if the training failed. """ - fit(self._wrapped_classifier, training_set) - self._target_name = training_set.target.name + + wrapped_classifier = sk_GradientBoostingClassifier() + fit(wrapped_classifier, training_set) + + result = GradientBoosting() + result._wrapped_classifier = wrapped_classifier + result._target_name = training_set.target.name + + return result # noinspection PyProtectedMember def predict(self, dataset: Table) -> TaggedTable: diff --git a/src/safeds/ml/classification/_k_nearest_neighbors.py b/src/safeds/ml/classification/_k_nearest_neighbors.py index 2cb16a612..7a0c7a12f 100644 --- a/src/safeds/ml/classification/_k_nearest_neighbors.py +++ b/src/safeds/ml/classification/_k_nearest_neighbors.py @@ -1,3 +1,7 @@ +from __future__ import annotations + +from typing import Optional + from safeds.data.tabular.containers import Table, TaggedTable from safeds.ml._util_sklearn import fit, predict from sklearn.neighbors import KNeighborsClassifier as sk_KNeighborsClassifier @@ -16,27 +20,39 @@ class KNearestNeighbors(Classifier): """ def __init__(self, n_neighbors: int) -> None: - self._wrapped_classifier = sk_KNeighborsClassifier( - n_jobs=-1, n_neighbors=n_neighbors - ) - self._target_name = "" + self._n_neighbors = n_neighbors - def fit(self, training_set: TaggedTable) -> None: + self._wrapped_classifier: Optional[sk_KNeighborsClassifier] = None + self._target_name: Optional[str] = None + + def fit(self, training_set: TaggedTable) -> KNearestNeighbors: """ - Fit this model given a tagged table. + Create a new classifier based on this one and fit it with the given training data. This classifier is not + modified. Parameters ---------- training_set : TaggedTable - The tagged table containing the feature and target vectors. + The training data containing the feature and target vectors. + + Returns + ------- + fitted_classifier : KNearestNeighbors + The fitted classifier. Raises ------ LearningError - If the tagged table contains invalid values or if the training failed. + If the training data contains invalid values or if the training failed. """ - fit(self._wrapped_classifier, training_set) - self._target_name = training_set.target.name + wrapped_classifier = sk_KNeighborsClassifier(self._n_neighbors, n_jobs=-1) + fit(wrapped_classifier, training_set) + + result = KNearestNeighbors(self._n_neighbors) + result._wrapped_classifier = wrapped_classifier + result._target_name = training_set.target.name + + return result def predict(self, dataset: Table) -> TaggedTable: """ diff --git a/src/safeds/ml/classification/_logistic_regression.py b/src/safeds/ml/classification/_logistic_regression.py index c489591d3..46fcc102f 100644 --- a/src/safeds/ml/classification/_logistic_regression.py +++ b/src/safeds/ml/classification/_logistic_regression.py @@ -1,3 +1,7 @@ +from __future__ import annotations + +from typing import Optional + from safeds.data.tabular.containers import Table, TaggedTable from safeds.ml._util_sklearn import fit, predict from sklearn.linear_model import LogisticRegression as sk_LogisticRegression @@ -12,25 +16,38 @@ class LogisticRegression(Classifier): """ def __init__(self) -> None: - self._wrapped_classifier = sk_LogisticRegression(n_jobs=-1) - self._target_name = "" + self._wrapped_classifier: Optional[sk_LogisticRegression] = None + self._target_name: Optional[str] = None - def fit(self, training_set: TaggedTable) -> None: + def fit(self, training_set: TaggedTable) -> LogisticRegression: """ - Fit this model given a tagged table. + Create a new classifier based on this one and fit it with the given training data. This classifier is not + modified. Parameters ---------- training_set : TaggedTable - The tagged table containing the feature and target vectors. + The training data containing the feature and target vectors. + + Returns + ------- + fitted_classifier : LogisticRegression + The fitted classifier. Raises ------ LearningError - If the tagged table contains invalid values or if the training failed. + If the training data contains invalid values or if the training failed. """ - fit(self._wrapped_classifier, training_set) - self._target_name = training_set.target.name + + wrapped_classifier = sk_LogisticRegression(n_jobs=-1) + fit(wrapped_classifier, training_set) + + result = LogisticRegression() + result._wrapped_classifier = wrapped_classifier + result._target_name = training_set.target.name + + return result def predict(self, dataset: Table) -> TaggedTable: """ diff --git a/src/safeds/ml/classification/_random_forest.py b/src/safeds/ml/classification/_random_forest.py index 4a9aff14e..9f8928f94 100644 --- a/src/safeds/ml/classification/_random_forest.py +++ b/src/safeds/ml/classification/_random_forest.py @@ -1,3 +1,7 @@ +from __future__ import annotations + +from typing import Optional + from safeds.data.tabular.containers import Table, TaggedTable from safeds.ml._util_sklearn import fit, predict from sklearn.ensemble import RandomForestClassifier as sk_RandomForestClassifier @@ -11,25 +15,38 @@ class RandomForest(Classifier): """ def __init__(self) -> None: - self._wrapped_classifier = sk_RandomForestClassifier(n_jobs=-1) - self._target_name = "" + self._wrapped_classifier: Optional[sk_RandomForestClassifier] = None + self._target_name: Optional[str] = None - def fit(self, training_set: TaggedTable) -> None: + def fit(self, training_set: TaggedTable) -> RandomForest: """ - Fit this model given a tagged table. + Create a new classifier based on this one and fit it with the given training data. This classifier is not + modified. Parameters ---------- training_set : TaggedTable - The tagged table containing the feature and target vectors. + The training data containing the feature and target vectors. + + Returns + ------- + fitted_classifier : RandomForest + The fitted classifier. Raises ------ LearningError - If the tagged table contains invalid values or if the training failed. + If the training data contains invalid values or if the training failed. """ - fit(self._wrapped_classifier, training_set) - self._target_name = training_set.target.name + + wrapped_classifier = sk_RandomForestClassifier(n_jobs=-1) + fit(wrapped_classifier, training_set) + + result = RandomForest() + result._wrapped_classifier = wrapped_classifier + result._target_name = training_set.target.name + + return result def predict(self, dataset: Table) -> TaggedTable: """ diff --git a/src/safeds/ml/regression/_ada_boost.py b/src/safeds/ml/regression/_ada_boost.py index 8a6be0e0b..52d1d42f3 100644 --- a/src/safeds/ml/regression/_ada_boost.py +++ b/src/safeds/ml/regression/_ada_boost.py @@ -1,3 +1,7 @@ +from __future__ import annotations + +from typing import Optional + from safeds.data.tabular.containers import Table, TaggedTable from safeds.ml._util_sklearn import fit, predict from sklearn.ensemble import AdaBoostRegressor as sk_AdaBoostRegressor @@ -12,25 +16,38 @@ class AdaBoost(Regressor): """ def __init__(self) -> None: - self._wrapped_regressor = sk_AdaBoostRegressor() - self._target_name = "" + self._wrapped_regressor: Optional[sk_AdaBoostRegressor] = None + self._target_name: Optional[str] = None - def fit(self, training_set: TaggedTable) -> None: + def fit(self, training_set: TaggedTable) -> AdaBoost: """ - Fit this model given a tagged table. + Create a new regressor based on this one and fit it with the given training data. This regressor is not + modified. Parameters ---------- training_set : TaggedTable - The tagged table containing the feature and target vectors. + The training data containing the feature and target vectors. + + Returns + ------- + fitted_regressor : AdaBoost + The fitted regressor. Raises ------ LearningError - If the tagged table contains invalid values or if the training failed. + If the training data contains invalid values or if the training failed. """ - fit(self._wrapped_regressor, training_set) - self._target_name = training_set.target.name + + wrapped_regressor = sk_AdaBoostRegressor() + fit(wrapped_regressor, training_set) + + result = AdaBoost() + result._wrapped_regressor = wrapped_regressor + result._target_name = training_set.target.name + + return result def predict(self, dataset: Table) -> TaggedTable: """ diff --git a/src/safeds/ml/regression/_decision_tree.py b/src/safeds/ml/regression/_decision_tree.py index e7eeae520..5b71d8374 100644 --- a/src/safeds/ml/regression/_decision_tree.py +++ b/src/safeds/ml/regression/_decision_tree.py @@ -1,3 +1,7 @@ +from __future__ import annotations + +from typing import Optional + from safeds.data.tabular.containers import Table, TaggedTable from safeds.ml._util_sklearn import fit, predict from sklearn.tree import DecisionTreeRegressor as sk_DecisionTreeRegressor @@ -12,25 +16,38 @@ class DecisionTree(Regressor): """ def __init__(self) -> None: - self._wrapped_regressor = sk_DecisionTreeRegressor() - self._target_name = "" + self._wrapped_regressor: Optional[sk_DecisionTreeRegressor] = None + self._target_name: Optional[str] = None - def fit(self, training_set: TaggedTable) -> None: + def fit(self, training_set: TaggedTable) -> DecisionTree: """ - Fit this model given a tagged table. + Create a new regressor based on this one and fit it with the given training data. This regressor is not + modified. Parameters ---------- training_set : TaggedTable - The tagged table containing the feature and target vectors. + The training data containing the feature and target vectors. + + Returns + ------- + fitted_regressor : DecisionTree + The fitted regressor. Raises ------ LearningError - If the tagged table contains invalid values or if the training failed. + If the training data contains invalid values or if the training failed. """ - fit(self._wrapped_regressor, training_set) - self._target_name = training_set.target.name + + wrapped_regressor = sk_DecisionTreeRegressor() + fit(wrapped_regressor, training_set) + + result = DecisionTree() + result._wrapped_regressor = wrapped_regressor + result._target_name = training_set.target.name + + return result def predict(self, dataset: Table) -> TaggedTable: """ diff --git a/src/safeds/ml/regression/_elastic_net_regression.py b/src/safeds/ml/regression/_elastic_net_regression.py index 2da3d2867..37f548d6a 100644 --- a/src/safeds/ml/regression/_elastic_net_regression.py +++ b/src/safeds/ml/regression/_elastic_net_regression.py @@ -1,3 +1,7 @@ +from __future__ import annotations + +from typing import Optional + from safeds.data.tabular.containers import Table, TaggedTable from safeds.ml._util_sklearn import fit, predict from sklearn.linear_model import ElasticNet as sk_ElasticNet @@ -12,25 +16,38 @@ class ElasticNetRegression(Regressor): """ def __init__(self) -> None: - self._wrapped_regressor = sk_ElasticNet() - self._target_name = "" + self._wrapped_regressor: Optional[sk_ElasticNet] = None + self._target_name: Optional[str] = None - def fit(self, training_set: TaggedTable) -> None: + def fit(self, training_set: TaggedTable) -> ElasticNetRegression: """ - Fit this model given a tagged table. + Create a new regressor based on this one and fit it with the given training data. This regressor is not + modified. Parameters ---------- training_set : TaggedTable - The tagged table containing the feature and target vectors. + The training data containing the feature and target vectors. + + Returns + ------- + fitted_regressor : ElasticNetRegression + The fitted regressor. Raises ------ LearningError - If the tagged table contains invalid values or if the training failed. + If the training data contains invalid values or if the training failed. """ - fit(self._wrapped_regressor, training_set) - self._target_name = training_set.target.name + + wrapped_regressor = sk_ElasticNet() + fit(wrapped_regressor, training_set) + + result = ElasticNetRegression() + result._wrapped_regressor = wrapped_regressor + result._target_name = training_set.target.name + + return result def predict(self, dataset: Table) -> TaggedTable: """ diff --git a/src/safeds/ml/regression/_gradient_boosting_regression.py b/src/safeds/ml/regression/_gradient_boosting_regression.py index 68bb20967..c87085d86 100644 --- a/src/safeds/ml/regression/_gradient_boosting_regression.py +++ b/src/safeds/ml/regression/_gradient_boosting_regression.py @@ -1,3 +1,7 @@ +from __future__ import annotations + +from typing import Optional + from safeds.data.tabular.containers import Table, TaggedTable from safeds.ml._util_sklearn import fit, predict from sklearn.ensemble import GradientBoostingRegressor as sk_GradientBoostingRegressor @@ -12,28 +16,38 @@ class GradientBoosting(Regressor): """ def __init__(self) -> None: - self._wrapped_regressor = sk_GradientBoostingRegressor() - self._target_name = "" + self._wrapped_regressor: Optional[sk_GradientBoostingRegressor] = None + self._target_name: Optional[str] = None - def fit(self, training_set: TaggedTable) -> None: + def fit(self, training_set: TaggedTable) -> GradientBoosting: """ - Fit this model given a tagged table. + Create a new regressor based on this one and fit it with the given training data. This regressor is not + modified. Parameters - ---------- - tagged_table : SupervisedDataset - The tagged table containing the feature and target vectors. + training_set : TaggedTable + The training data containing the feature and target vectors. + + Returns + ------- + fitted_regressor : GradientBoosting + The fitted regressor. Raises ------ LearningError - If the tagged table contains invalid values or if the training failed. + If the training data contains invalid values or if the training failed. """ - fit(self._wrapped_regressor, training_set) - self._target_name = training_set.target.name - # noinspection PyProtectedMember + wrapped_regressor = sk_GradientBoostingRegressor() + fit(wrapped_regressor, training_set) + + result = GradientBoosting() + result._wrapped_regressor = wrapped_regressor + result._target_name = training_set.target.name + + return result def predict(self, dataset: Table) -> TaggedTable: """ diff --git a/src/safeds/ml/regression/_k_nearest_neighbors.py b/src/safeds/ml/regression/_k_nearest_neighbors.py index 315a10509..c9b5fd3b5 100644 --- a/src/safeds/ml/regression/_k_nearest_neighbors.py +++ b/src/safeds/ml/regression/_k_nearest_neighbors.py @@ -1,3 +1,7 @@ +from __future__ import annotations + +from typing import Optional + from safeds.data.tabular.containers import Table, TaggedTable from safeds.ml._util_sklearn import fit, predict from sklearn.neighbors import KNeighborsRegressor as sk_KNeighborsRegressor @@ -16,25 +20,40 @@ class KNearestNeighbors(Regressor): """ def __init__(self, n_neighbors: int) -> None: - self._wrapped_regressor = sk_KNeighborsRegressor(n_neighbors) - self._target_name = "" + self._n_neighbors = n_neighbors + + self._wrapped_regressor: Optional[sk_KNeighborsRegressor] = None + self._target_name: Optional[str] = None - def fit(self, training_set: TaggedTable) -> None: + def fit(self, training_set: TaggedTable) -> KNearestNeighbors: """ - Fit this model given a tagged table. + Create a new regressor based on this one and fit it with the given training data. This regressor is not + modified. Parameters ---------- training_set : TaggedTable - The tagged table containing the feature and target vectors. + The training data containing the feature and target vectors. + + Returns + ------- + fitted_regressor : KNearestNeighbors + The fitted regressor. Raises ------ LearningError - If the tagged table contains invalid values or if the training failed. + If the training data contains invalid values or if the training failed. """ - fit(self._wrapped_regressor, training_set) - self._target_name = training_set.target.name + + wrapped_regressor = sk_KNeighborsRegressor(self._n_neighbors, n_jobs=-1) + fit(wrapped_regressor, training_set) + + result = KNearestNeighbors(self._n_neighbors) + result._wrapped_regressor = wrapped_regressor + result._target_name = training_set.target.name + + return result def predict(self, dataset: Table) -> TaggedTable: """ diff --git a/src/safeds/ml/regression/_lasso_regression.py b/src/safeds/ml/regression/_lasso_regression.py index 74b23ee9a..824107481 100644 --- a/src/safeds/ml/regression/_lasso_regression.py +++ b/src/safeds/ml/regression/_lasso_regression.py @@ -1,3 +1,7 @@ +from __future__ import annotations + +from typing import Optional + from safeds.data.tabular.containers import Table, TaggedTable from safeds.ml._util_sklearn import fit, predict from sklearn.linear_model import Lasso as sk_Lasso @@ -12,25 +16,38 @@ class LassoRegression(Regressor): """ def __init__(self) -> None: - self._wrapped_regressor = sk_Lasso() - self._target_name = "" + self._wrapped_regressor: Optional[sk_Lasso] = None + self._target_name: Optional[str] = None - def fit(self, training_set: TaggedTable) -> None: + def fit(self, training_set: TaggedTable) -> LassoRegression: """ - Fit this model given a tagged table. + Create a new regressor based on this one and fit it with the given training data. This regressor is not + modified. Parameters ---------- training_set : TaggedTable - The tagged table containing the feature and target vectors. + The training data containing the feature and target vectors. + + Returns + ------- + fitted_regressor : LassoRegression + The fitted regressor. Raises ------ LearningError - If the tagged table contains invalid values or if the training failed. + If the training data contains invalid values or if the training failed. """ - fit(self._wrapped_regressor, training_set) - self._target_name = training_set.target.name + + wrapped_regressor = sk_Lasso() + fit(wrapped_regressor, training_set) + + result = LassoRegression() + result._wrapped_regressor = wrapped_regressor + result._target_name = training_set.target.name + + return result def predict(self, dataset: Table) -> TaggedTable: """ diff --git a/src/safeds/ml/regression/_linear_regression.py b/src/safeds/ml/regression/_linear_regression.py index 54f61e984..d05286188 100644 --- a/src/safeds/ml/regression/_linear_regression.py +++ b/src/safeds/ml/regression/_linear_regression.py @@ -1,3 +1,7 @@ +from __future__ import annotations + +from typing import Optional + from safeds.data.tabular.containers import Table, TaggedTable from safeds.ml._util_sklearn import fit, predict from sklearn.linear_model import LinearRegression as sk_LinearRegression @@ -12,25 +16,38 @@ class LinearRegression(Regressor): """ def __init__(self) -> None: - self._wrapped_regressor = sk_LinearRegression(n_jobs=-1) - self._target_name = "" + self._wrapped_regressor: Optional[sk_LinearRegression] = None + self._target_name: Optional[str] = None - def fit(self, training_set: TaggedTable) -> None: + def fit(self, training_set: TaggedTable) -> LinearRegression: """ - Fit this model given a tagged table. + Create a new regressor based on this one and fit it with the given training data. This regressor is not + modified. Parameters ---------- training_set : TaggedTable - The tagged table containing the feature and target vectors. + The training data containing the feature and target vectors. + + Returns + ------- + fitted_regressor : LinearRegression + The fitted regressor. Raises ------ LearningError - If the tagged table contains invalid values or if the training failed. + If the training data contains invalid values or if the training failed. """ - fit(self._wrapped_regressor, training_set) - self._target_name = training_set.target.name + + wrapped_regressor = sk_LinearRegression(n_jobs=-1) + fit(wrapped_regressor, training_set) + + result = LinearRegression() + result._wrapped_regressor = wrapped_regressor + result._target_name = training_set.target.name + + return result def predict(self, dataset: Table) -> TaggedTable: """ diff --git a/src/safeds/ml/regression/_random_forest.py b/src/safeds/ml/regression/_random_forest.py index 91acaa652..9a49b1298 100644 --- a/src/safeds/ml/regression/_random_forest.py +++ b/src/safeds/ml/regression/_random_forest.py @@ -1,3 +1,7 @@ +from __future__ import annotations + +from typing import Optional + from safeds.data.tabular.containers import Table, TaggedTable from safeds.ml._util_sklearn import fit, predict from sklearn.ensemble import RandomForestRegressor as sk_RandomForestRegressor @@ -11,25 +15,38 @@ class RandomForest(Regressor): """ def __init__(self) -> None: - self._wrapped_regressor = sk_RandomForestRegressor(n_jobs=-1) - self._target_name = "" + self._wrapped_regressor: Optional[sk_RandomForestRegressor] = None + self._target_name: Optional[str] = None - def fit(self, training_set: TaggedTable) -> None: + def fit(self, training_set: TaggedTable) -> RandomForest: """ - Fit this model given a tagged table. + Create a new regressor based on this one and fit it with the given training data. This regressor is not + modified. Parameters ---------- training_set : TaggedTable - The tagged table containing the feature and target vectors. + The training data containing the feature and target vectors. + + Returns + ------- + fitted_regressor : RandomForest + The fitted regressor. Raises ------ LearningError - If the tagged table contains invalid values or if the training failed. + If the training data contains invalid values or if the training failed. """ - fit(self._wrapped_regressor, training_set) - self._target_name = training_set.target.name + + wrapped_regressor = sk_RandomForestRegressor(n_jobs=-1) + fit(wrapped_regressor, training_set) + + result = RandomForest() + result._wrapped_regressor = wrapped_regressor + result._target_name = training_set.target.name + + return result def predict(self, dataset: Table) -> TaggedTable: """ diff --git a/src/safeds/ml/regression/_regressor.py b/src/safeds/ml/regression/_regressor.py index 232971314..e84371399 100644 --- a/src/safeds/ml/regression/_regressor.py +++ b/src/safeds/ml/regression/_regressor.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from abc import ABC, abstractmethod from safeds.data.tabular.containers import Column, Table, TaggedTable @@ -12,19 +14,25 @@ class Regressor(ABC): """ @abstractmethod - def fit(self, training_set: TaggedTable) -> None: + def fit(self, training_set: TaggedTable) -> Regressor: """ - Fit this model given a tagged table. + Create a new regressor based on this one and fit it with the given training data. This regressor is not + modified. Parameters ---------- training_set : TaggedTable - The tagged table containing the feature and target vectors. + The training data containing the feature and target vectors. + + Returns + ------- + fitted_regressor : Regressor + The fitted regressor. Raises ------ LearningError - If the tagged table contains invalid values or if the training failed. + If the training data contains invalid values or if the training failed. """ @abstractmethod diff --git a/src/safeds/ml/regression/_ridge_regression.py b/src/safeds/ml/regression/_ridge_regression.py index b3d23beca..bfcbe5404 100644 --- a/src/safeds/ml/regression/_ridge_regression.py +++ b/src/safeds/ml/regression/_ridge_regression.py @@ -1,3 +1,7 @@ +from __future__ import annotations + +from typing import Optional + from safeds.data.tabular.containers import Table, TaggedTable from safeds.ml._util_sklearn import fit, predict from sklearn.linear_model import Ridge as sk_Ridge @@ -12,25 +16,38 @@ class RidgeRegression(Regressor): """ def __init__(self) -> None: - self._wrapped_regressor = sk_Ridge() - self._target_name = "" + self._wrapped_regressor: Optional[sk_Ridge] = None + self._target_name: Optional[str] = None - def fit(self, training_set: TaggedTable) -> None: + def fit(self, training_set: TaggedTable) -> RidgeRegression: """ - Fit this model given a tagged table. + Create a new regressor based on this one and fit it with the given training data. This regressor is not + modified. Parameters ---------- training_set : TaggedTable - The tagged table containing the feature and target vectors. + The training data containing the feature and target vectors. + + Returns + ------- + fitted_regressor : RidgeRegression + The fitted regressor. Raises ------ LearningError - If the tagged table contains invalid values or if the training failed. + If the training data contains invalid values or if the training failed. """ - fit(self._wrapped_regressor, training_set) - self._target_name = training_set.target.name + + wrapped_regressor = sk_Ridge() + fit(wrapped_regressor, training_set) + + result = RidgeRegression() + result._wrapped_regressor = wrapped_regressor + result._target_name = training_set.target.name + + return result def predict(self, dataset: Table) -> TaggedTable: """ diff --git a/tests/safeds/ml/classification/test_ada_boost.py b/tests/safeds/ml/classification/test_ada_boost.py index 0989ffdba..41b04c9f7 100644 --- a/tests/safeds/ml/classification/test_ada_boost.py +++ b/tests/safeds/ml/classification/test_ada_boost.py @@ -40,8 +40,8 @@ class TestPredict: def test_should_succeed_on_valid_data( self, classifier: Classifier, valid_data: TaggedTable ) -> None: - classifier.fit(valid_data) - classifier.predict(valid_data.features) + fitted_classifier = classifier.fit(valid_data) + fitted_classifier.predict(valid_data.features) assert True # This asserts that the predict method succeeds def test_should_raise_when_not_fitted( @@ -53,6 +53,6 @@ def test_should_raise_when_not_fitted( def test_should_raise_on_invalid_data( self, classifier: Classifier, valid_data: TaggedTable, invalid_data: TaggedTable ) -> None: - classifier.fit(valid_data) + fitted_classifier = classifier.fit(valid_data) with pytest.raises(PredictionError): - classifier.predict(invalid_data.features) + fitted_classifier.predict(invalid_data.features) diff --git a/tests/safeds/ml/classification/test_decision_tree.py b/tests/safeds/ml/classification/test_decision_tree.py index 091ff7f8c..68f0fad22 100644 --- a/tests/safeds/ml/classification/test_decision_tree.py +++ b/tests/safeds/ml/classification/test_decision_tree.py @@ -40,8 +40,8 @@ class TestPredict: def test_should_succeed_on_valid_data( self, classifier: Classifier, valid_data: TaggedTable ) -> None: - classifier.fit(valid_data) - classifier.predict(valid_data.features) + fitted_classifier = classifier.fit(valid_data) + fitted_classifier.predict(valid_data.features) assert True # This asserts that the predict method succeeds def test_should_raise_when_not_fitted( @@ -53,6 +53,6 @@ def test_should_raise_when_not_fitted( def test_should_raise_on_invalid_data( self, classifier: Classifier, valid_data: TaggedTable, invalid_data: TaggedTable ) -> None: - classifier.fit(valid_data) + fitted_classifier = classifier.fit(valid_data) with pytest.raises(PredictionError): - classifier.predict(invalid_data.features) + fitted_classifier.predict(invalid_data.features) diff --git a/tests/safeds/ml/classification/test_gradient_boosting.py b/tests/safeds/ml/classification/test_gradient_boosting.py index c820c62b8..d1bf2446d 100644 --- a/tests/safeds/ml/classification/test_gradient_boosting.py +++ b/tests/safeds/ml/classification/test_gradient_boosting.py @@ -44,8 +44,8 @@ class TestPredict: def test_should_succeed_on_valid_data( self, classifier: Classifier, valid_data: TaggedTable ) -> None: - classifier.fit(valid_data) - classifier.predict(valid_data.features) + fitted_classifier = classifier.fit(valid_data) + fitted_classifier.predict(valid_data.features) assert True # This asserts that the predict method succeeds def test_should_raise_when_not_fitted( @@ -57,6 +57,6 @@ def test_should_raise_when_not_fitted( def test_should_raise_on_invalid_data( self, classifier: Classifier, valid_data: TaggedTable, invalid_data: TaggedTable ) -> None: - classifier.fit(valid_data) + fitted_classifier = classifier.fit(valid_data) with pytest.raises(PredictionError): - classifier.predict(invalid_data.features) + fitted_classifier.predict(invalid_data.features) diff --git a/tests/safeds/ml/classification/test_k_nearest_neighbors.py b/tests/safeds/ml/classification/test_k_nearest_neighbors.py index c202248bb..93359a9c6 100644 --- a/tests/safeds/ml/classification/test_k_nearest_neighbors.py +++ b/tests/safeds/ml/classification/test_k_nearest_neighbors.py @@ -42,8 +42,8 @@ class TestPredict: def test_should_succeed_on_valid_data( self, classifier: Classifier, valid_data: TaggedTable ) -> None: - classifier.fit(valid_data) - classifier.predict(valid_data.features) + fitted_classifier = classifier.fit(valid_data) + fitted_classifier.predict(valid_data.features) assert True # This asserts that the predict method succeeds def test_should_raise_when_not_fitted( @@ -55,6 +55,6 @@ def test_should_raise_when_not_fitted( def test_should_raise_on_invalid_data( self, classifier: Classifier, valid_data: TaggedTable, invalid_data: TaggedTable ) -> None: - classifier.fit(valid_data) + fitted_classifier = classifier.fit(valid_data) with pytest.raises(PredictionError): - classifier.predict(invalid_data.features) + fitted_classifier.predict(invalid_data.features) diff --git a/tests/safeds/ml/classification/test_logistic_regression.py b/tests/safeds/ml/classification/test_logistic_regression.py index 936f8beae..fd62ad8ea 100644 --- a/tests/safeds/ml/classification/test_logistic_regression.py +++ b/tests/safeds/ml/classification/test_logistic_regression.py @@ -42,8 +42,8 @@ class TestPredict: def test_should_succeed_on_valid_data( self, classifier: Classifier, valid_data: TaggedTable ) -> None: - classifier.fit(valid_data) - classifier.predict(valid_data.features) + fitted_classifier = classifier.fit(valid_data) + fitted_classifier.predict(valid_data.features) assert True # This asserts that the predict method succeeds def test_should_raise_when_not_fitted( @@ -55,6 +55,6 @@ def test_should_raise_when_not_fitted( def test_should_raise_on_invalid_data( self, classifier: Classifier, valid_data: TaggedTable, invalid_data: TaggedTable ) -> None: - classifier.fit(valid_data) + fitted_classifier = classifier.fit(valid_data) with pytest.raises(PredictionError): - classifier.predict(invalid_data.features) + fitted_classifier.predict(invalid_data.features) diff --git a/tests/safeds/ml/classification/test_random_forest.py b/tests/safeds/ml/classification/test_random_forest.py index df0da59a9..181e2a577 100644 --- a/tests/safeds/ml/classification/test_random_forest.py +++ b/tests/safeds/ml/classification/test_random_forest.py @@ -40,8 +40,8 @@ class TestPredict: def test_should_succeed_on_valid_data( self, classifier: Classifier, valid_data: TaggedTable ) -> None: - classifier.fit(valid_data) - classifier.predict(valid_data.features) + fitted_classifier = classifier.fit(valid_data) + fitted_classifier.predict(valid_data.features) assert True # This asserts that the predict method succeeds def test_should_raise_when_not_fitted( @@ -53,6 +53,6 @@ def test_should_raise_when_not_fitted( def test_should_raise_on_invalid_data( self, classifier: Classifier, valid_data: TaggedTable, invalid_data: TaggedTable ) -> None: - classifier.fit(valid_data) + fitted_classifier = classifier.fit(valid_data) with pytest.raises(PredictionError): - classifier.predict(invalid_data.features) + fitted_classifier.predict(invalid_data.features) diff --git a/tests/safeds/ml/regression/test_ada_boost.py b/tests/safeds/ml/regression/test_ada_boost.py index d290f49c0..d067ece5a 100644 --- a/tests/safeds/ml/regression/test_ada_boost.py +++ b/tests/safeds/ml/regression/test_ada_boost.py @@ -40,8 +40,8 @@ class TestPredict: def test_should_succeed_on_valid_data( self, regressor: Regressor, valid_data: TaggedTable ) -> None: - regressor.fit(valid_data) - regressor.predict(valid_data.features) + fitted_regressor = regressor.fit(valid_data) + fitted_regressor.predict(valid_data.features) assert True # This asserts that the predict method succeeds def test_should_raise_when_not_fitted( @@ -53,6 +53,6 @@ def test_should_raise_when_not_fitted( def test_should_raise_on_invalid_data( self, regressor: Regressor, valid_data: TaggedTable, invalid_data: TaggedTable ) -> None: - regressor.fit(valid_data) + fitted_regressor = regressor.fit(valid_data) with pytest.raises(PredictionError): - regressor.predict(invalid_data.features) + fitted_regressor.predict(invalid_data.features) diff --git a/tests/safeds/ml/regression/test_decision_tree.py b/tests/safeds/ml/regression/test_decision_tree.py index 6db937abe..51dee8f84 100644 --- a/tests/safeds/ml/regression/test_decision_tree.py +++ b/tests/safeds/ml/regression/test_decision_tree.py @@ -40,8 +40,8 @@ class TestPredict: def test_should_succeed_on_valid_data( self, regressor: Regressor, valid_data: TaggedTable ) -> None: - regressor.fit(valid_data) - regressor.predict(valid_data.features) + fitted_regressor = regressor.fit(valid_data) + fitted_regressor.predict(valid_data.features) assert True # This asserts that the predict method succeeds def test_should_raise_when_not_fitted( @@ -53,6 +53,6 @@ def test_should_raise_when_not_fitted( def test_should_raise_on_invalid_data( self, regressor: Regressor, valid_data: TaggedTable, invalid_data: TaggedTable ) -> None: - regressor.fit(valid_data) + fitted_regressor = regressor.fit(valid_data) with pytest.raises(PredictionError): - regressor.predict(invalid_data.features) + fitted_regressor.predict(invalid_data.features) diff --git a/tests/safeds/ml/regression/test_elastic_net.py b/tests/safeds/ml/regression/test_elastic_net.py index 06e443372..1f317fe76 100644 --- a/tests/safeds/ml/regression/test_elastic_net.py +++ b/tests/safeds/ml/regression/test_elastic_net.py @@ -42,8 +42,8 @@ class TestPredict: def test_should_succeed_on_valid_data( self, regressor: Regressor, valid_data: TaggedTable ) -> None: - regressor.fit(valid_data) - regressor.predict(valid_data.features) + fitted_regressor = regressor.fit(valid_data) + fitted_regressor.predict(valid_data.features) assert True # This asserts that the predict method succeeds def test_should_raise_when_not_fitted( @@ -55,6 +55,6 @@ def test_should_raise_when_not_fitted( def test_should_raise_on_invalid_data( self, regressor: Regressor, valid_data: TaggedTable, invalid_data: TaggedTable ) -> None: - regressor.fit(valid_data) + fitted_regressor = regressor.fit(valid_data) with pytest.raises(PredictionError): - regressor.predict(invalid_data.features) + fitted_regressor.predict(invalid_data.features) diff --git a/tests/safeds/ml/regression/test_gradient_boosting.py b/tests/safeds/ml/regression/test_gradient_boosting.py index 023dd76f4..40816d73a 100644 --- a/tests/safeds/ml/regression/test_gradient_boosting.py +++ b/tests/safeds/ml/regression/test_gradient_boosting.py @@ -44,8 +44,8 @@ class TestPredict: def test_should_succeed_on_valid_data( self, regressor: Regressor, valid_data: TaggedTable ) -> None: - regressor.fit(valid_data) - regressor.predict(valid_data.features) + fitted_regressor = regressor.fit(valid_data) + fitted_regressor.predict(valid_data.features) assert True # This asserts that the predict method succeeds def test_should_raise_when_not_fitted( @@ -57,6 +57,6 @@ def test_should_raise_when_not_fitted( def test_should_raise_on_invalid_data( self, regressor: Regressor, valid_data: TaggedTable, invalid_data: TaggedTable ) -> None: - regressor.fit(valid_data) + fitted_regressor = regressor.fit(valid_data) with pytest.raises(PredictionError): - regressor.predict(invalid_data.features) + fitted_regressor.predict(invalid_data.features) diff --git a/tests/safeds/ml/regression/test_k_nearest_neighbors.py b/tests/safeds/ml/regression/test_k_nearest_neighbors.py index 0ad18d54a..0e14ed4d9 100644 --- a/tests/safeds/ml/regression/test_k_nearest_neighbors.py +++ b/tests/safeds/ml/regression/test_k_nearest_neighbors.py @@ -42,8 +42,8 @@ class TestPredict: def test_should_succeed_on_valid_data( self, regressor: Regressor, valid_data: TaggedTable ) -> None: - regressor.fit(valid_data) - regressor.predict(valid_data.features) + fitted_regressor = regressor.fit(valid_data) + fitted_regressor.predict(valid_data.features) assert True # This asserts that the predict method succeeds def test_should_raise_when_not_fitted( @@ -55,6 +55,6 @@ def test_should_raise_when_not_fitted( def test_should_raise_on_invalid_data( self, regressor: Regressor, valid_data: TaggedTable, invalid_data: TaggedTable ) -> None: - regressor.fit(valid_data) + fitted_regressor = regressor.fit(valid_data) with pytest.raises(PredictionError): - regressor.predict(invalid_data.features) + fitted_regressor.predict(invalid_data.features) diff --git a/tests/safeds/ml/regression/test_lasso_regression.py b/tests/safeds/ml/regression/test_lasso_regression.py index 362871a31..4de72b8f2 100644 --- a/tests/safeds/ml/regression/test_lasso_regression.py +++ b/tests/safeds/ml/regression/test_lasso_regression.py @@ -40,8 +40,8 @@ class TestPredict: def test_should_succeed_on_valid_data( self, regressor: Regressor, valid_data: TaggedTable ) -> None: - regressor.fit(valid_data) - regressor.predict(valid_data.features) + fitted_regressor = regressor.fit(valid_data) + fitted_regressor.predict(valid_data.features) assert True # This asserts that the predict method succeeds def test_should_raise_when_not_fitted( @@ -53,6 +53,6 @@ def test_should_raise_when_not_fitted( def test_should_raise_on_invalid_data( self, regressor: Regressor, valid_data: TaggedTable, invalid_data: TaggedTable ) -> None: - regressor.fit(valid_data) + fitted_regressor = regressor.fit(valid_data) with pytest.raises(PredictionError): - regressor.predict(invalid_data.features) + fitted_regressor.predict(invalid_data.features) diff --git a/tests/safeds/ml/regression/test_linear_regression.py b/tests/safeds/ml/regression/test_linear_regression.py index fbabe70ec..2084a1ac4 100644 --- a/tests/safeds/ml/regression/test_linear_regression.py +++ b/tests/safeds/ml/regression/test_linear_regression.py @@ -40,8 +40,8 @@ class TestPredict: def test_should_succeed_on_valid_data( self, regressor: Regressor, valid_data: TaggedTable ) -> None: - regressor.fit(valid_data) - regressor.predict(valid_data.features) + fitted_regressor = regressor.fit(valid_data) + fitted_regressor.predict(valid_data.features) assert True # This asserts that the predict method succeeds def test_should_raise_when_not_fitted( @@ -53,6 +53,6 @@ def test_should_raise_when_not_fitted( def test_should_raise_on_invalid_data( self, regressor: Regressor, valid_data: TaggedTable, invalid_data: TaggedTable ) -> None: - regressor.fit(valid_data) + fitted_regressor = regressor.fit(valid_data) with pytest.raises(PredictionError): - regressor.predict(invalid_data.features) + fitted_regressor.predict(invalid_data.features) diff --git a/tests/safeds/ml/regression/test_random_forest.py b/tests/safeds/ml/regression/test_random_forest.py index 87a30bbce..0d47b7681 100644 --- a/tests/safeds/ml/regression/test_random_forest.py +++ b/tests/safeds/ml/regression/test_random_forest.py @@ -40,8 +40,8 @@ class TestPredict: def test_should_succeed_on_valid_data( self, regressor: Regressor, valid_data: TaggedTable ) -> None: - regressor.fit(valid_data) - regressor.predict(valid_data.features) + fitted_regressor = regressor.fit(valid_data) + fitted_regressor.predict(valid_data.features) assert True # This asserts that the predict method succeeds def test_should_raise_when_not_fitted( @@ -53,6 +53,6 @@ def test_should_raise_when_not_fitted( def test_should_raise_on_invalid_data( self, regressor: Regressor, valid_data: TaggedTable, invalid_data: TaggedTable ) -> None: - regressor.fit(valid_data) + fitted_regressor = regressor.fit(valid_data) with pytest.raises(PredictionError): - regressor.predict(invalid_data.features) + fitted_regressor.predict(invalid_data.features) diff --git a/tests/safeds/ml/regression/test_ridge_regression.py b/tests/safeds/ml/regression/test_ridge_regression.py index 6f201e9e9..0ec6f6978 100644 --- a/tests/safeds/ml/regression/test_ridge_regression.py +++ b/tests/safeds/ml/regression/test_ridge_regression.py @@ -40,8 +40,8 @@ class TestPredict: def test_should_succeed_on_valid_data( self, regressor: Regressor, valid_data: TaggedTable ) -> None: - regressor.fit(valid_data) - regressor.predict(valid_data.features) + fitted_regressor = regressor.fit(valid_data) + fitted_regressor.predict(valid_data.features) assert True # This asserts that the predict method succeeds def test_should_raise_when_not_fitted( @@ -53,6 +53,6 @@ def test_should_raise_when_not_fitted( def test_should_raise_on_invalid_data( self, regressor: Regressor, valid_data: TaggedTable, invalid_data: TaggedTable ) -> None: - regressor.fit(valid_data) + fitted_regressor = regressor.fit(valid_data) with pytest.raises(PredictionError): - regressor.predict(invalid_data.features) + fitted_regressor.predict(invalid_data.features) diff --git a/tests/safeds/ml/test_util_sklearn.py b/tests/safeds/ml/test_util_sklearn.py index 07d32d91f..88bb03b3c 100644 --- a/tests/safeds/ml/test_util_sklearn.py +++ b/tests/safeds/ml/test_util_sklearn.py @@ -12,11 +12,11 @@ def test_predict_should_not_warn_about_feature_names() -> None: training_set = TaggedTable(Table({"a": [1, 2, 3], "b": [2, 4, 6]}), target_name="b") model = LinearRegression() - model.fit(training_set) + fitted_model = model.fit(training_set) test_set = Table({"a": [4, 5, 6]}) # No warning should be emitted with warnings.catch_warnings(): warnings.filterwarnings("error", message="X has feature names") - model.predict(dataset=test_set) + fitted_model.predict(dataset=test_set)