Skip to content

SupervisedModel

Bases: ABC

A model for supervised learning tasks.

Methods:

Name Description
fit

Create a copy of this model and fit it with the given training data.

get_feature_names

Return the names of the feature columns.

get_features_schema

Return the schema of the feature columns.

get_target_name

Return the name of the target column.

get_target_type

Return the type of the target column.

predict

Predict the target values on the given dataset.

Attributes:

Name Type Description
is_fitted bool

Whether the model is fitted.

Source code in src/safeds/ml/classical/_supervised_model.py
class SupervisedModel(ABC):
    """A model for supervised learning tasks."""

    # ------------------------------------------------------------------------------------------------------------------
    # Dunder methods
    # ------------------------------------------------------------------------------------------------------------------

    # The decorator is needed so the class really cannot be instantiated
    @abstractmethod
    def __init__(self) -> None:
        self._feature_schema: Schema | None = None
        self._target_name: str | None = None
        self._target_type: ColumnType | None = None
        self._wrapped_model: ClassifierMixin | RegressorMixin | None = None

    # The decorator ensures that the method is overridden in all subclasses
    @abstractmethod
    def __hash__(self) -> int:
        return _structural_hash(
            self.__class__.__qualname__,
            self._feature_schema,
            self._target_name,
            self._target_type,
        )

    # ------------------------------------------------------------------------------------------------------------------
    # Properties
    # ------------------------------------------------------------------------------------------------------------------

    @property
    def is_fitted(self) -> bool:
        """Whether the model is fitted."""
        return None not in (self._feature_schema, self._target_name, self._target_type, self._wrapped_model)

    # ------------------------------------------------------------------------------------------------------------------
    # Learning and prediction
    # ------------------------------------------------------------------------------------------------------------------

    def fit(self, training_set: TabularDataset) -> Self:
        """
        Create a copy of this model and fit it with the given training data.

        **Note:** This model is not modified.

        Parameters
        ----------
        training_set:
            The training data containing the features and target.

        Returns
        -------
        fitted_model:
            The fitted model.

        Raises
        ------
        PlainTableError
            If a table is passed instead of a TabularDataset.
        DatasetMissesDataError
            If the given training set contains no data.
        FittingWithChoiceError
            When trying to call this method on a model with hyperparameter choices.
        LearningError
            If the training data contains invalid values or if the training failed.
        """
        if not isinstance(training_set, TabularDataset) and isinstance(training_set, Table):
            raise PlainTableError
        if training_set.to_table().row_count == 0:
            raise DatasetMissesDataError

        self._check_additional_fit_preconditions()
        self._check_more_additional_fit_preconditions(training_set)

        wrapped_model = self._get_sklearn_model()
        _fit_sklearn_model_in_place(wrapped_model, training_set)

        result = self._clone()
        result._feature_schema = training_set.features.schema
        result._target_name = training_set.target.name
        result._target_type = training_set.target.type
        result._wrapped_model = wrapped_model

        return result

    def predict(
        self,
        dataset: Table | TabularDataset,
    ) -> TabularDataset:
        """
        Predict the target values on the given dataset.

        **Note:** The model must be fitted.

        Parameters
        ----------
        dataset:
            The dataset containing at least the features.

        Returns
        -------
        prediction:
            The given dataset with an additional column for the predicted target values.

        Raises
        ------
        NotFittedError
            If the model has not been fitted yet.
        DatasetMissesFeaturesError
            If the dataset misses feature columns.
        PredictionError
            If predicting with the given dataset failed.
        """
        self._check_additional_predict_preconditions(dataset)

        return _predict_with_sklearn_model(
            self._wrapped_model,
            dataset,
            self.get_feature_names(),
            self.get_target_name(),
        )

    # ------------------------------------------------------------------------------------------------------------------
    # Introspection
    # ------------------------------------------------------------------------------------------------------------------

    def get_feature_names(self) -> list[str]:
        """
        Return the names of the feature columns.

        **Note:** The model must be fitted.

        Returns
        -------
        feature_names:
            The names of the feature columns.

        Raises
        ------
        NotFittedError
            If the model has not been fitted yet.
        """
        # Used in favor of is_fitted, so the type checker is happy
        if self._feature_schema is None:
            raise NotFittedError(kind="model")

        return self._feature_schema.column_names

    def get_features_schema(self) -> Schema:
        """
        Return the schema of the feature columns.

        **Note:** The model must be fitted.

        Returns
        -------
        feature_schema:
            The schema of the feature columns.

        Raises
        ------
        NotFittedError
            If the model has not been fitted yet.
        """
        # Used in favor of is_fitted, so the type checker is happy
        if self._feature_schema is None:
            raise NotFittedError(kind="model")

        return self._feature_schema

    def get_target_name(self) -> str:
        """
        Return the name of the target column.

        **Note:** The model must be fitted.

        Returns
        -------
        target_name:
            The name of the target column.

        Raises
        ------
        NotFittedError
            If the model has not been fitted yet.
        """
        # Used in favor of is_fitted, so the type checker is happy
        if self._target_name is None:
            raise NotFittedError(kind="model")

        return self._target_name

    def get_target_type(self) -> ColumnType:
        """
        Return the type of the target column.

        **Note:** The model must be fitted.

        Returns
        -------
        target_type:
            The type of the target column.

        Raises
        ------
        NotFittedError
            If the model has not been fitted yet.
        """
        # Used in favor of is_fitted, so the type checker is happy
        if self._target_type is None:
            raise NotFittedError(kind="model")

        return self._target_type

    # ------------------------------------------------------------------------------------------------------------------
    # Template methods
    # ------------------------------------------------------------------------------------------------------------------

    def _check_additional_fit_preconditions(self) -> None:  # noqa: B027
        """Check additional preconditions for fitting the model and raise an error if any are violated."""

    def _check_more_additional_fit_preconditions(self, training_set: TabularDataset) -> None:  # noqa: B027
        """Check additional preconditions for fitting the model and raise an error if any are violated."""

    def _check_additional_fit_by_exhaustive_search_preconditions(self) -> None:  # noqa: B027
        """Check additional preconditions for fitting by exhaustive search and raise an error if any are violated."""

    def _check_additional_predict_preconditions(self, dataset: Table | TabularDataset) -> None:  # noqa: B027
        """
        Check additional preconditions for predicting with the model and raise an error if any are violated.

        Parameters
        ----------
        dataset:
            The dataset containing at least the features.
        """

    def _get_models_for_all_choices(self) -> list[Self]:
        """Get a list of all possible models, given the Parameter Choices."""
        raise NotImplementedError  # pragma: no cover

    @abstractmethod
    def _clone(self) -> Self:
        """
        Return a new instance of this model with the same hyperparameters.

        Returns
        -------
        clone:
            A new instance of this model.
        """

    @abstractmethod
    def _get_sklearn_model(self) -> ClassifierMixin | RegressorMixin:
        """
        Return a new scikit-learn model that implements the algorithm of this model.

        Returns
        -------
        sklearn_model:
            The scikit-learn model.
        """

is_fitted

Whether the model is fitted.

fit

Create a copy of this model and fit it with the given training data.

Note: This model is not modified.

Parameters:

Name Type Description Default
training_set TabularDataset

The training data containing the features and target.

required

Returns:

Name Type Description
fitted_model Self

The fitted model.

Raises:

Type Description
PlainTableError

If a table is passed instead of a TabularDataset.

DatasetMissesDataError

If the given training set contains no data.

FittingWithChoiceError

When trying to call this method on a model with hyperparameter choices.

LearningError

If the training data contains invalid values or if the training failed.

Source code in src/safeds/ml/classical/_supervised_model.py
def fit(self, training_set: TabularDataset) -> Self:
    """
    Create a copy of this model and fit it with the given training data.

    **Note:** This model is not modified.

    Parameters
    ----------
    training_set:
        The training data containing the features and target.

    Returns
    -------
    fitted_model:
        The fitted model.

    Raises
    ------
    PlainTableError
        If a table is passed instead of a TabularDataset.
    DatasetMissesDataError
        If the given training set contains no data.
    FittingWithChoiceError
        When trying to call this method on a model with hyperparameter choices.
    LearningError
        If the training data contains invalid values or if the training failed.
    """
    if not isinstance(training_set, TabularDataset) and isinstance(training_set, Table):
        raise PlainTableError
    if training_set.to_table().row_count == 0:
        raise DatasetMissesDataError

    self._check_additional_fit_preconditions()
    self._check_more_additional_fit_preconditions(training_set)

    wrapped_model = self._get_sklearn_model()
    _fit_sklearn_model_in_place(wrapped_model, training_set)

    result = self._clone()
    result._feature_schema = training_set.features.schema
    result._target_name = training_set.target.name
    result._target_type = training_set.target.type
    result._wrapped_model = wrapped_model

    return result

get_feature_names

Return the names of the feature columns.

Note: The model must be fitted.

Returns:

Name Type Description
feature_names list[str]

The names of the feature columns.

Raises:

Type Description
NotFittedError

If the model has not been fitted yet.

Source code in src/safeds/ml/classical/_supervised_model.py
def get_feature_names(self) -> list[str]:
    """
    Return the names of the feature columns.

    **Note:** The model must be fitted.

    Returns
    -------
    feature_names:
        The names of the feature columns.

    Raises
    ------
    NotFittedError
        If the model has not been fitted yet.
    """
    # Used in favor of is_fitted, so the type checker is happy
    if self._feature_schema is None:
        raise NotFittedError(kind="model")

    return self._feature_schema.column_names

get_features_schema

Return the schema of the feature columns.

Note: The model must be fitted.

Returns:

Name Type Description
feature_schema Schema

The schema of the feature columns.

Raises:

Type Description
NotFittedError

If the model has not been fitted yet.

Source code in src/safeds/ml/classical/_supervised_model.py
def get_features_schema(self) -> Schema:
    """
    Return the schema of the feature columns.

    **Note:** The model must be fitted.

    Returns
    -------
    feature_schema:
        The schema of the feature columns.

    Raises
    ------
    NotFittedError
        If the model has not been fitted yet.
    """
    # Used in favor of is_fitted, so the type checker is happy
    if self._feature_schema is None:
        raise NotFittedError(kind="model")

    return self._feature_schema

get_target_name

Return the name of the target column.

Note: The model must be fitted.

Returns:

Name Type Description
target_name str

The name of the target column.

Raises:

Type Description
NotFittedError

If the model has not been fitted yet.

Source code in src/safeds/ml/classical/_supervised_model.py
def get_target_name(self) -> str:
    """
    Return the name of the target column.

    **Note:** The model must be fitted.

    Returns
    -------
    target_name:
        The name of the target column.

    Raises
    ------
    NotFittedError
        If the model has not been fitted yet.
    """
    # Used in favor of is_fitted, so the type checker is happy
    if self._target_name is None:
        raise NotFittedError(kind="model")

    return self._target_name

get_target_type

Return the type of the target column.

Note: The model must be fitted.

Returns:

Name Type Description
target_type ColumnType

The type of the target column.

Raises:

Type Description
NotFittedError

If the model has not been fitted yet.

Source code in src/safeds/ml/classical/_supervised_model.py
def get_target_type(self) -> ColumnType:
    """
    Return the type of the target column.

    **Note:** The model must be fitted.

    Returns
    -------
    target_type:
        The type of the target column.

    Raises
    ------
    NotFittedError
        If the model has not been fitted yet.
    """
    # Used in favor of is_fitted, so the type checker is happy
    if self._target_type is None:
        raise NotFittedError(kind="model")

    return self._target_type

predict

Predict the target values on the given dataset.

Note: The model must be fitted.

Parameters:

Name Type Description Default
dataset Table | TabularDataset

The dataset containing at least the features.

required

Returns:

Name Type Description
prediction TabularDataset

The given dataset with an additional column for the predicted target values.

Raises:

Type Description
NotFittedError

If the model has not been fitted yet.

DatasetMissesFeaturesError

If the dataset misses feature columns.

PredictionError

If predicting with the given dataset failed.

Source code in src/safeds/ml/classical/_supervised_model.py
def predict(
    self,
    dataset: Table | TabularDataset,
) -> TabularDataset:
    """
    Predict the target values on the given dataset.

    **Note:** The model must be fitted.

    Parameters
    ----------
    dataset:
        The dataset containing at least the features.

    Returns
    -------
    prediction:
        The given dataset with an additional column for the predicted target values.

    Raises
    ------
    NotFittedError
        If the model has not been fitted yet.
    DatasetMissesFeaturesError
        If the dataset misses feature columns.
    PredictionError
        If predicting with the given dataset failed.
    """
    self._check_additional_predict_preconditions(dataset)

    return _predict_with_sklearn_model(
        self._wrapped_model,
        dataset,
        self.get_feature_names(),
        self.get_target_name(),
    )