Skip to content

fit

Fit

Class for fitting a model to data.

Parameters:

Name Type Description Default
model Model

Model to fit.

required
parameters list[Parameter] | Parameters

List or Parameters object of parameters to fit.

required
data dict[str | Expr, ArrayLike]

Dictionary of data to fit to. Keys correspond to model symbols.

required
loss Optional[Loss]

Loss function to use. Defaults to L2Loss.

SELoss()

Attributes:

Name Type Description
xdata

Independent data, typically chosen measurement points.

ydata

Dependent data, typically measurements.

Source code in slimfit/fit.py
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
class Fit:
    """
    Class for fitting a model to data.

    Args:
        model: Model to fit.
        parameters: List or Parameters object of parameters to fit.
        data: Dictionary of data to fit to. Keys correspond to model symbols.
        loss: Loss function to use. Defaults to L2Loss.

    Attributes:
        xdata: Independent data, typically chosen measurement points.
        ydata: Dependent data, typically measurements.
    """

    def __init__(
        self,
        model: Model,
        parameters: list[Parameter] | Parameters,
        data: dict[str | Expr, npt.ArrayLike],
        loss: Optional[Loss] = SELoss(),
    ) -> None:
        self.model = model

        # make a new instance such that external modification does not affect the
        # copy stored here
        self.parameters = Parameters(parameters)

        # Convert data keys to `str` if given as `Symbol; data values as arrays
        data: dict[str, np.ndarray] = {
            getattr(k, "name", k): np.asarray(v) for k, v in data.items()
        }
        self.loss = loss

        # 'independent' data; or 'xdata'; typically chosen measurement points
        self.xdata = {k: v for k, v in data.items() if k in self.model.symbol_names}

        # 'dependent' data; or 'ydata'; typically measurements
        self.ydata = {k: v for k, v in data.items() if k in self.model.dependent_symbols}

    def execute(
        self,
        minimizer: Optional[Type[Minimizer]] = None,
        **execute_options,
    ) -> FitResult:
        """
        Execute the fit.

        Args:
            minimizer: Optional minimizer to use. Defaults to ScipyMinimizer.
            **execute_options:

        Returns:
            Result of the fit as FitResult object.

        """

        minimizer_cls = minimizer or self.get_minimizer()
        minimizer_instance = minimizer_cls(
            self.model, self.parameters, self.loss, self.xdata, self.ydata
        )

        result = minimizer_instance.execute(**execute_options)

        result.minimizer = minimizer_instance

        return result

    def get_minimizer(self) -> Type[Minimizer]:
        """Automatically determine which minimizer to use"""
        return ScipyMinimizer

    # def hessian(self, **parameters):
    #     free_parameters = {p.name: p for p in parameters if not p.fixed}
    #     fixed_parameters = {p.name: p for p in parameters if p.fixed}
    #
    #     if extra_parameters := parameters.keys() - free_parameters.keys():
    #         raise ValueError(f"Unknown parameters: {', '.join(extra_parameters)}")
    #     if missing_parameters := free_parameters.keys() - parameters.keys():
    #         raise ValueError(f"Missing parameters: {', '.join(missing_parameters)}")
    #
    #     # but how do i know which hessian entries correspond to which parameters?

    def get_loss(self, **kwargs):
        raise NotImplementedError()
        if self.model.probabilistic:
            return LogLoss(**kwargs)
        else:
            return SELoss(**kwargs)

execute(minimizer=None, **execute_options)

Execute the fit.

Parameters:

Name Type Description Default
minimizer Optional[Type[Minimizer]]

Optional minimizer to use. Defaults to ScipyMinimizer.

None
**execute_options
{}

Returns:

Type Description
FitResult

Result of the fit as FitResult object.

Source code in slimfit/fit.py
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
def execute(
    self,
    minimizer: Optional[Type[Minimizer]] = None,
    **execute_options,
) -> FitResult:
    """
    Execute the fit.

    Args:
        minimizer: Optional minimizer to use. Defaults to ScipyMinimizer.
        **execute_options:

    Returns:
        Result of the fit as FitResult object.

    """

    minimizer_cls = minimizer or self.get_minimizer()
    minimizer_instance = minimizer_cls(
        self.model, self.parameters, self.loss, self.xdata, self.ydata
    )

    result = minimizer_instance.execute(**execute_options)

    result.minimizer = minimizer_instance

    return result

get_minimizer()

Automatically determine which minimizer to use

Source code in slimfit/fit.py
84
85
86
def get_minimizer(self) -> Type[Minimizer]:
    """Automatically determine which minimizer to use"""
    return ScipyMinimizer