leaspy.algo.personalize.scipy_minimize module

class ScipyMinimize(settings)

Bases: AbstractPersonalizeAlgo

Gradient descent based algorithm to compute individual parameters, i.e. personalize a model to a given set of subjects.

Parameters
settingsAlgorithmSettings

Settings of the algorithm. In particular the parameter custom_scipy_minimize_params may contain keyword arguments passed to scipy.optimize.minimize().

Attributes
scipy_minimize_paramsdict

Keyword arguments to be passed to scipy.optimize.minize(). A default setting depending on whether using jacobian or not is applied (cf. ScipyMinimize.DEFAULT_SCIPY_MINIMIZE_PARAMS_WITH_JACOBIAN

and ScipyMinimize.DEFAULT_SCIPY_MINIMIZE_PARAMS_WITHOUT_JACOBIAN).

You may customize it by setting the custom_scipy_minimize_params algorithm parameter.

format_convergence_issuesstr

Formatting of convergence issues. It should be a formattable string using any of those variables:

  • patient_id: str

  • optimization_result_pformat: str

  • (optimization_result_obj: dict-like)

cf. ScipyMinimize.DEFAULT_FORMAT_CONVERGENCE_ISSUES for the default format. You may customize it by setting the custom_format_convergence_issues algorithm parameter.

loggerNone or callable str -> None

The function used to display convergence issues returned by scipy.optimize.minize(). By default we print the convergences issues if and only if we do not use BFGS optimization method. You can customize it at initialization by defining a logger attribute to your AlgorithmSettings instance.

Methods

is_jacobian_implemented(model)

Check that the jacobian of model is implemented.

load_parameters(parameters)

Update the algorithm's parameters by the ones in the given dictionary.

obj(x, *args)

Objective loss function to minimize in order to get patient's individual parameters

run(model, *args[, return_noise])

Main method, run the algorithm.

run_impl(model, dataset)

Main personalize function, wraps the abstract _get_individual_parameters() method.

set_output_manager(output_settings)

Set a FitOutputManager object for the run of the algorithm

DEFAULT_FORMAT_CONVERGENCE_ISSUES = '<!> {patient_id}:\n{optimization_result_pformat}'
DEFAULT_SCIPY_MINIMIZE_PARAMS_WITHOUT_JACOBIAN = {'method': 'Powell', 'options': {'ftol': 0.0001, 'maxiter': 200, 'xtol': 0.0001}}
DEFAULT_SCIPY_MINIMIZE_PARAMS_WITH_JACOBIAN = {'method': 'BFGS', 'options': {'gtol': 0.01, 'maxiter': 200}}
deterministic: bool = False
family: str = 'personalize'
is_jacobian_implemented(model) bool

Check that the jacobian of model is implemented.

load_parameters(parameters: dict)

Update the algorithm’s parameters by the ones in the given dictionary. The keys in the io which does not belong to the algorithm’s parameters keys are ignored.

Parameters
parametersdict

Contains the pairs (key, value) of the wanted parameters

Examples

>>> settings = leaspy.io.settings.algorithm_settings.AlgorithmSettings("mcmc_saem")
>>> my_algo = leaspy.algo.fit.tensor_mcmcsaem.TensorMCMCSAEM(settings)
>>> my_algo.algo_parameters
{'n_iter': 10000,
 'n_burn_in_iter': 9000,
 'eps': 0.001,
 'L': 10,
 'sampler_ind': 'Gibbs',
 'sampler_pop': 'Gibbs',
 'annealing': {'do_annealing': False,
  'initial_temperature': 10,
  'n_plateau': 10,
  'n_iter': 200}}
>>> parameters = {'n_iter': 5000, 'n_burn_in_iter': 4000}
>>> my_algo.load_parameters(parameters)
>>> my_algo.algo_parameters
{'n_iter': 5000,
 'n_burn_in_iter': 4000,
 'eps': 0.001,
 'L': 10,
 'sampler_ind': 'Gibbs',
 'sampler_pop': 'Gibbs',
 'annealing': {'do_annealing': False,
  'initial_temperature': 10,
  'n_plateau': 10,
  'n_iter': 200}}
property log_noise_fmt

Getter

Returns
formatstr

The format for the print of the loss

name: str = 'scipy_minimize'
obj(x, *args)

Objective loss function to minimize in order to get patient’s individual parameters

Parameters
xarray-like [float]

Individual standardized parameters At initialization x = [xi_mean/xi_std, tau_mean/tau_std] (+ [0.] * n_sources if multivariate model)

*args
  • modelAbstractModel

    Model used to compute the group average parameters.

  • timepointstorch.Tensor [1,n_tpts]

    Contains the individual ages corresponding to the given values

  • valuestorch.Tensor [n_tpts, n_fts [, extra_dim_for_ordinal_model]]

    Contains the individual true scores corresponding to the given times, with nans.

  • with_gradientbool
    • If True: return (objective, gradient_objective)

    • Else: simply return objective

Returns
objectivefloat

Value of the loss function (opposite of log-likelihood).

if with_gradient is True:
2-tuple (as expected by scipy.optimize.minimize() when jac=True)
  • objective : float

  • gradient : array-like[float] of length n_dims_params

Raises
LeaspyAlgoInputError

if noise model is not currently supported by algorithm. TODO: everything that is not generic here concerning noise structure should be handle by model/NoiseModel directly!!!!

output_manager: Optional[FitOutputManager]
run(model: AbstractModel, *args, return_noise: bool = False, **extra_kwargs) Any

Main method, run the algorithm.

TODO fix proper abstract class method: input depends on algorithm… (esp. simulate != from others…)

Parameters
modelAbstractModel

The used model.

datasetDataset

Contains all the subjects’ observations with corresponding timepoints, in torch format to speed up computations.

return_noisebool (default False), keyword only

Should the algorithm return main output and optional noise output as a 2-tuple?

Returns
Depends on algorithm class: TODO change?
run_impl(model, dataset)

Main personalize function, wraps the abstract _get_individual_parameters() method.

Parameters
modelAbstractModel

A subclass object of leaspy AbstractModel.

datasetDataset

Dataset object build with leaspy class objects Data, algo & model

Returns
individual_parametersIndividualParameters

Contains individual parameters.

noise_stdfloat or torch.FloatTensor

The estimated noise (is a tensor if model.noise_model is 'gaussian_diagonal')

= \frac{1}{n_{visits} \times n_{dim}} \sqrt{\sum_{i, j \in [1, n_{visits}] \times [1, n_{dim}]} \varepsilon_{i,j}}

where \varepsilon_{i,j} = \left( f(\theta, (z_{i,j}), (t_{i,j})) - (y_{i,j}) \right)^2 , where \theta are the model’s fixed effect, (z_{i,j}) the model’s random effects, (t_{i,j}) the time-points and f the model’s estimator.

set_output_manager(output_settings)

Set a FitOutputManager object for the run of the algorithm

Parameters
output_settingsOutputsSettings

Contains the logs settings for the computation run (console print periodicity, plot periodicity …)

Examples

>>> from leaspy import AlgorithmSettings
>>> from leaspy.io.settings.outputs_settings import OutputsSettings
>>> from leaspy.algo.fit.tensor_mcmcsaem import TensorMCMCSAEM
>>> algo_settings = AlgorithmSettings("mcmc_saem")
>>> my_algo = TensorMCMCSAEM(algo_settings)
>>> settings = {'path': 'brouillons',
                'console_print_periodicity': 50,
                'plot_periodicity': 100,
                'save_periodicity': 50
                }
>>> my_algo.set_output_manager(OutputsSettings(settings))
torch_nanmean()

nanmean(input, dim=None, keepdim=False, *, dtype=None, out=None) -> Tensor

Computes the mean of all non-NaN elements along the specified dimensions.

This function is identical to torch.mean() when there are no NaN values in the input tensor. In the presence of NaN, torch.mean() will propagate the NaN to the output whereas torch.nanmean() will ignore the NaN values (torch.nanmean(a) is equivalent to torch.mean(a[~a.isnan()])).

If keepdim is True, the output tensor is of the same size as input except in the dimension(s) dim where it is of size 1. Otherwise, dim is squeezed (see torch.squeeze()), resulting in the output tensor having 1 (or len(dim)) fewer dimension(s).

Args:

input (Tensor): the input tensor. dim (int or tuple of ints): the dimension or dimensions to reduce. If None, reduces all dimensions. Default is None. keepdim (bool): whether the output tensor has dim retained or not.

Keyword args:
dtype (torch.dtype, optional): the desired data type of returned tensor.

If specified, the input tensor is casted to dtype before the operation is performed. This is useful for preventing data type overflows. Default: None.

out (Tensor, optional): the output tensor.

See also

torch.mean() computes the mean value, propagating NaN.

Example:

>>> x = torch.tensor([[torch.nan, 1, 2], [1, 2, 3]])
>>> x.mean()
tensor(nan)
>>> x.nanmean()
tensor(1.8000)
>>> x.mean(dim=0)
tensor([   nan, 1.5000, 2.5000])
>>> x.nanmean(dim=0)
tensor([1.0000, 1.5000, 2.5000])

# If all elements in the reduced dimensions are NaN then the result is NaN
>>> torch.tensor([torch.nan]).nanmean()
tensor(nan)