Optimizers

Optimizer is an interface that enables the use of declearn 's optimizers for Federated Learning inside Fed-BioMed

Classes

BaseOptimizer

BaseOptimizer(model, optimizer)

Bases: Generic[OT]

Abstract base class for Optimizer and Model wrappers.

Parameters:

Name Type Description Default
model Model

model to train, interfaced via a framework-specific Model.

required
optimizer OT

optimizer that will be used for optimizing the model.

required

Raises:

Type Description
FedbiomedOptimizerError

Raised if model is not an instance of _model_cls (which may be a subset of the generic Model type).

Source code in fedbiomed/common/optimizers/generic_optimizers.py
def __init__(self, model: Model, optimizer: OT):
    """Constuctor of the optimizer wrapper that sets a reference to model and optimizer.

    Args:
        model: model to train, interfaced via a framework-specific Model.
        optimizer: optimizer that will be used for optimizing the model.

    Raises:
        FedbiomedOptimizerError:
            Raised if model is not an instance of `_model_cls` (which may
            be a subset of the generic Model type).
    """
    if not isinstance(model, self._model_cls):
        raise FedbiomedOptimizerError(
            f"{ErrorNumbers.FB626.value}, in `model` argument, expected an instance "
            f"of {self._model_cls} but got an object of type {type(model)}."
        )
    self._model: Model = model
    self.optimizer: OT = optimizer

Attributes

optimizer instance-attribute
optimizer = optimizer

Functions

init_training
init_training()

Sets up training and misceallenous parameters so the model is ready for training

Source code in fedbiomed/common/optimizers/generic_optimizers.py
def init_training(self):
    """Sets up training and misceallenous parameters so the model is ready for training
    """
    self._model.init_training()
load_state
load_state(optim_state, load_from_state=False)

Reconfigures optimizer from a given state.

This is the default method for optimizers that don't support state. Does nothing.

Parameters:

Name Type Description Default
optim_state Dict

not used

required
load_from_state optional

not used

False

Returns:

Type Description
Union[BaseOptimizer, None]

None

Source code in fedbiomed/common/optimizers/generic_optimizers.py
def load_state(self, optim_state: Dict, load_from_state: bool = False) -> Union['BaseOptimizer', None]:
    """Reconfigures optimizer from a given state.

    This is the default method for optimizers that don't support state. Does nothing.

    Args:
        optim_state: not used
        load_from_state (optional): not used

    Returns:
        None
    """
    logger.warning("load_state method of optimizer not implemented, cannot load optimizer status")
    return None
save_state
save_state()

Gets optimizer state.

This is the default method for optimizers that don't support state. Does nothing.

Returns:

Type Description
Union[Dict, None]

None

Source code in fedbiomed/common/optimizers/generic_optimizers.py
def save_state(self) -> Union[Dict, None]:
    """Gets optimizer state.

    This is the default method for optimizers that don't support state. Does nothing.

    Returns:
        None
    """
    logger.warning("save_state method of optimizer not implemented, cannot save optimizer status")
    return None
step abstractmethod
step()

Performs an optimisation step and updates model weights.

Source code in fedbiomed/common/optimizers/generic_optimizers.py
@abstractmethod
def step(self):
    """Performs an optimisation step and updates model weights.
    """

DeclearnOptimizer

DeclearnOptimizer(model, optimizer)

Bases: BaseOptimizer

Base Optimizer subclass to use a declearn-backed Optimizer.

Parameters:

Name Type Description Default
model Model

Model that wraps the actual model

required
optimizer Union[Optimizer, Optimizer]

declearn optimizer, or fedbiomed optimizer (that wraps declearn optimizer)

required
Source code in fedbiomed/common/optimizers/generic_optimizers.py
def __init__(self, model: Model, optimizer: Union[FedOptimizer, declearn.optimizer.Optimizer]):
    """Constructor of Optimizer wrapper for declearn's optimizers

    Args:
        model: Model that wraps the actual model
        optimizer: declearn optimizer,
            or fedbiomed optimizer (that wraps declearn optimizer)
    """
    logger.debug("Using declearn optimizer")
    if isinstance(optimizer, declearn.optimizer.Optimizer):
        # convert declearn optimizer into a fedbiomed optimizer wrapper
        optimizer = FedOptimizer.from_declearn_optimizer(optimizer)
    elif not isinstance(optimizer, FedOptimizer):
        raise FedbiomedOptimizerError(
            f"{ErrorNumbers.FB626.value}: expected a declearn optimizer,"
            f" but got an object with type {type(optimizer)}."
        )
    super().__init__(model, optimizer)
    self.optimizer.init_round()

Attributes

model class-attribute instance-attribute
model = None
optimizer class-attribute instance-attribute
optimizer = None

Functions

get_aux
get_aux()
Source code in fedbiomed/common/optimizers/generic_optimizers.py
def get_aux(self) -> Optional[Dict[str, Any]]:
    aux = self.optimizer.get_aux()
    return aux
load_state
load_state(optim_state, load_from_state=False)

Reconfigures optimizer from a given state (contained in optim_state argument). Usage:

>>> import torch.nn as nn
>>> from fedbiomed.common.optimizers import Optimizer
>>> from fedbiomed.common.models import TorchModel
>>> model = TorchModel(nn.Linear(4, 2))
>>> optimizer = Optimizer(lr=.1)
>>> optim = DeclearnOptimizer(model, optimizer)

>>> optim.load_state(state)  # provided state contains the state one wants to load the optimizer with
If load_from_state argument is True, it completes the current optimizer state with optim_state argument

>>> import torch.nn as nn
>>> from fedbiomed.common.optimizers import Optimizer
>>> from fedbiomed.common.optimizers.declearn import MomentumModule, AdamModule
>>> from fedbiomed.common.models import TorchModel
>>> model = TorchModel(nn.Linear(4, 2))
>>> optimizer = Optimizer(lr=.1, modules=[MomentumModule(), AdamModule()])
>>> optim_1 = DeclearnOptimizer(model, optimizer)

>>> optimizer = Optimizer(lr=.1, modules=[AdamModule(), MomentumModule()])
>>> optim_2 = DeclearnOptimizer(model, optimizer)
>>> optim_2.load_state(optim_1.save_state())
>>> optim_2.save_state()['states']
{'modules': [('momentum', {'velocity': 0.0}),
        ('adam',
        {'steps': 0,
            'vmax': None,
            'momentum': {'state': 0.0},
            'velocity': {'state': 0.0}})]}
Modules of DeclearnOptimizer will be reloaded provided that Module is the same and occupying the same index. Eg if the state contains following modules: modules=[AdamModule(), AdagradModule(), MomemtumModule()] And the Optimizer contained in the TrainingPlan has the following modules: modules=[AdamModule(), MomemtumModule()] Then only AdamModule module will be reloaded, MomentumModule will be set with default argument (they don't share the same index in the modules list).

Parameters:

Name Type Description Default
optim_state Dict[str, Any]

state of the Optimizer to be loaded. It will change the current state of the optimizer with the one loaded

required
load_from_state optional

strategy for loading states: whether to load from saved states (True) or from breakpoint (False). If set to True, loading is done partially in the sense that if some of the OptimModules is different in the optim_state and the original state of the optimizer, it loads only the OptiModule(s) from the latest state that both state has in common. Defaults to False.

False

Raises:

Type Description
FedbiomedOptimizerError

raised if state is not of dict type.

Returns:

Type Description
DeclearnOptimizer

Optimizer wrapper reloaded from optim_state argument.

Source code in fedbiomed/common/optimizers/generic_optimizers.py
def load_state(self, optim_state: Dict[str, Any], load_from_state: bool = False) -> 'DeclearnOptimizer':
    """Reconfigures optimizer from a given state (contained in `optim_state` argument).
    Usage:
    ```python
    >>> import torch.nn as nn
    >>> from fedbiomed.common.optimizers import Optimizer
    >>> from fedbiomed.common.models import TorchModel
    >>> model = TorchModel(nn.Linear(4, 2))
    >>> optimizer = Optimizer(lr=.1)
    >>> optim = DeclearnOptimizer(model, optimizer)

    >>> optim.load_state(state)  # provided state contains the state one wants to load the optimizer with
    ```
    If `load_from_state` argument is True, it completes the current optimizer state with `optim_state` argument

    ```python
    >>> import torch.nn as nn
    >>> from fedbiomed.common.optimizers import Optimizer
    >>> from fedbiomed.common.optimizers.declearn import MomentumModule, AdamModule
    >>> from fedbiomed.common.models import TorchModel
    >>> model = TorchModel(nn.Linear(4, 2))
    >>> optimizer = Optimizer(lr=.1, modules=[MomentumModule(), AdamModule()])
    >>> optim_1 = DeclearnOptimizer(model, optimizer)

    >>> optimizer = Optimizer(lr=.1, modules=[AdamModule(), MomentumModule()])
    >>> optim_2 = DeclearnOptimizer(model, optimizer)
    >>> optim_2.load_state(optim_1.save_state())
    >>> optim_2.save_state()['states']
    {'modules': [('momentum', {'velocity': 0.0}),
            ('adam',
            {'steps': 0,
                'vmax': None,
                'momentum': {'state': 0.0},
                'velocity': {'state': 0.0}})]}
    ```
    Modules of DeclearnOptimizer will be reloaded provided that Module is the same and occupying the same index.
    Eg if the state contains following modules: 
    ```modules=[AdamModule(), AdagradModule(), MomemtumModule()]```
     And the Optimizer contained in the TrainingPlan has the following modules:
    ```modules=[AdamModule(), MomemtumModule()]```
    Then only `AdamModule` module will be reloaded, `MomentumModule` will be set with default argument (they don't
    share the same index in the modules list).

    Args:
        optim_state: state of the Optimizer to be loaded. It will change the current state of the optimizer
            with the one loaded
        load_from_state (optional): strategy for loading states: whether to load from saved states (True) or
            from breakpoint (False).
            If set to True, loading is done partially in the sense that if some of the OptimModules is different in
            the optim_state and the original state of the optimizer, it loads only the OptiModule(s) from the
            latest state that both state has in common. Defaults to False.

    Raises:
        FedbiomedOptimizerError: raised if state is not of dict type.

    Returns:
        Optimizer wrapper reloaded from `optim_state` argument.
    """
    # state: breakpoint content for optimizer
    if not isinstance(optim_state, Dict):
        raise FedbiomedOptimizerError(f"{ErrorNumbers.FB626.value}, incorrect type of argument `optim_state`: "
                                      f"expecting a dict, but got {type(optim_state)}")

    if load_from_state:
        # first get Optimizer detailed in the TrainingPlan.

        init_optim_state = self.optimizer.get_state()  # we have to get states since it is the only way we can 
        # gather modules (other methods of `Optimizer are private`)

        optim_state_copy = copy.deepcopy(optim_state)
        optim_state.update(init_optim_state)  # optim_state will be updated with current optimizer state
        # check if opimizer state has changed from last optimizer to the current one
        # if it has changed, find common modules and update common states
        for component in ( 'modules', 'regularizers',):
            components_to_keep: List[Tuple[str, int]] = []  # we store here common Module between current Optimizer
            # and the ones in the `optim_state` tuple (common Module name, index in List)

            if not init_optim_state['states'].get(component) or not optim_state_copy['states'].get(component):
                continue
            self._collect_common_optimodules(
                init_optim_state,
                optim_state_copy,
                component,
                components_to_keep
            )

            for mod in components_to_keep:
                for mod_state in optim_state_copy['states'][component]:
                    if mod[0] == mod_state[0]:
                        # if we do find same module in the current optimizer than the previous one,
                        # we load the previous optimizer module state into the current one
                        optim_state['states'][component][mod[1]] = mod_state

        logger.info("Loading optimizer state from saved state")

    reloaded_optim = FedOptimizer.load_state(optim_state)
    self.optimizer = reloaded_optim
    return self
optimizer_processing
optimizer_processing()

Provides a context manager able to do some actions before and after setting up an Optimizer, mainly disabling scikit-learn internal optimizer.

Also, checks if model_args dictionary contains training parameters that won't be used or have any effect on the training, because of disabling the scikit-learn optimizer ( such as initial learning rate, learnig rate scheduler, ...). If disabling the internal optimizer leads to such changes, displays a warning.

Returns:

Name Type Description
SklearnOptimizerProcessing SklearnOptimizerProcessing

context manager providing extra logic

Usage:

    >>> dlo = DeclearnSklearnOptimizer(model, optimizer)
    >>> with dlo.optimizer_processing():
            model.train(inputs,targets)

Source code in fedbiomed/common/optimizers/generic_optimizers.py
def optimizer_processing(self) -> SklearnOptimizerProcessing:
    """Provides a context manager able to do some actions before and after setting up an Optimizer, mainly
    disabling scikit-learn internal optimizer.

    Also, checks if `model_args` dictionary contains training parameters that
    won't be used or have any effect on the training, because of disabling the scikit-learn optimizer (
    such as initial learning rate, learnig rate scheduler, ...). If disabling the internal optimizer leads
    to such changes, displays a warning.

    Returns:
        SklearnOptimizerProcessing: context manager providing extra logic

    Usage:
    ```python
        >>> dlo = DeclearnSklearnOptimizer(model, optimizer)
        >>> with dlo.optimizer_processing():
                model.train(inputs,targets)
    ```
    """
    if isinstance(self._model, SkLearnModel):
        return SklearnOptimizerProcessing(self._model, disable_internal_optimizer=True)
    else:
        raise FedbiomedOptimizerError(f"{ErrorNumbers.FB626.value}: Method optimizer_processing should be used "
                                      f"only with SkLearnModel, but model is {self._model}")
save_state
save_state()

Gets optimizer state.

Returns:

Type Description
Dict

optimizer state

Source code in fedbiomed/common/optimizers/generic_optimizers.py
def save_state(self) -> Dict:
    """Gets optimizer state.

    Returns:
        optimizer state
    """
    optim_state = self.optimizer.get_state()
    return optim_state
set_aux
set_aux(aux)
Source code in fedbiomed/common/optimizers/generic_optimizers.py
def set_aux(self, aux: Dict[str, Any]):
    # FIXME: for imported tensors in PyTorch sent as auxiliary variables,
    # we should push it on the appropriate device (ie cpu/gpu)
    self.optimizer.set_aux(aux)
step
step()

Performs one optimization step

Source code in fedbiomed/common/optimizers/generic_optimizers.py
def step(self):
    """Performs one optimization step"""
    # NOTA: for sklearn, gradients retrieved are unscaled because we are using learning rate equal to 1.
    # Therefore, it is necessary to disable the sklearn internal optimizer beforehand
    # otherwise, computation will be incorrect
    grad = declearn.model.api.Vector.build(self._model.get_gradients())
    weights = declearn.model.api.Vector.build(self._model.get_weights(
        only_trainable=False,
        exclude_buffers=True
    ))
    updates = self.optimizer.step(grad, weights)
    self._model.apply_updates(updates.coefs)
zero_grad
zero_grad()

Zeroes gradients of the Pytorch model. Basically calls the zero_grad method of the model.

Raises:

Type Description
FedbiomedOptimizerError

triggered if model has no method called zero_grad

Source code in fedbiomed/common/optimizers/generic_optimizers.py
def zero_grad(self):
    """Zeroes gradients of the Pytorch model. Basically calls the `zero_grad`
    method of the model.

    Raises:
        FedbiomedOptimizerError: triggered if model has no method called `zero_grad`
    """
    # warning: specific for pytorch
    if not isinstance(self._model, TorchModel):
        raise FedbiomedOptimizerError(f"{ErrorNumbers.FB626.value}. This method can only be used for TorchModel, "
                                      f"but got {self._model}")
    self._model.model.zero_grad()

NativeSkLearnOptimizer

NativeSkLearnOptimizer(model, optimizer=None)

Bases: BaseOptimizer

Optimizer wrapper for scikit-learn native models.

Parameters:

Name Type Description Default
model SkLearnModel

SkLearnModel model that builds a scikit-learn model.

required
optimizer Optional[None]

unused. Defaults to None.

None
Source code in fedbiomed/common/optimizers/generic_optimizers.py
def __init__(self, model: SkLearnModel, optimizer: Optional[None] = None):
    """Constructor of the Optimizer wrapper for scikit-learn native models.

    Args:
        model: SkLearnModel model that builds a scikit-learn model.
        optimizer: unused. Defaults to None.
    """

    if optimizer is not None:
        logger.info(f"Passed Optimizer {optimizer} won't be used (using only native scikit learn optimization)")
    super().__init__(model, None)
    logger.debug("Using native Sklearn Optimizer")

Functions

optimizer_processing
optimizer_processing()
Source code in fedbiomed/common/optimizers/generic_optimizers.py
def optimizer_processing(self) -> SklearnOptimizerProcessing:
    return SklearnOptimizerProcessing(self._model, disable_internal_optimizer=False)
step
step()

Performs an optimization step and updates model weights.

Source code in fedbiomed/common/optimizers/generic_optimizers.py
def step(self):
    """Performs an optimization step and updates model weights."""
    gradients = self._model.get_gradients()
    updates = {k: -v for k, v in gradients.items()}
    self._model.apply_updates(updates)

NativeTorchOptimizer

NativeTorchOptimizer(model, optimizer)

Bases: BaseOptimizer

Optimizer wrapper for pytorch native optimizers and models.

Parameters:

Name Type Description Default
model TorchModel

fedbiomed model wrapper that warps the pytorch model

required
optimizer Optimizer

pytorch native optimizers (inhereting from torch.optim.Optimizer)

required

Raises:

Type Description
FedbiomedOptimizerError

raised if optimizer is not a pytorch native optimizer ie a torch.optim.Optimizer object.

Source code in fedbiomed/common/optimizers/generic_optimizers.py
def __init__(self, model: TorchModel, optimizer: torch.optim.Optimizer):
    """Constructor of the optimizer wrapper

    Args:
        model: fedbiomed model wrapper that warps the pytorch model
        optimizer: pytorch native optimizers (inhereting from `torch.optim.Optimizer`)

    Raises:
        FedbiomedOptimizerError: raised if optimizer is not a pytorch native optimizer ie a `torch.optim.Optimizer`
            object.
    """
    if not isinstance(optimizer, torch.optim.Optimizer):
        raise FedbiomedOptimizerError(f"{ErrorNumbers.FB626.value} Expected a native pytorch `torch.optim` "
                                      f"optimizer, but got {type(optimizer)}")
    super().__init__(model, optimizer)
    logger.debug("using native torch optimizer")

Functions

get_learning_rate
get_learning_rate()

Gets learning rates from param groups in Pytorch optimizer.

For each optimizer param group, it iterates over all parameters in that parameter group and searches for the " corresponding parameter of the model by iterating over all model parameters. If it finds a correspondence, it saves the learning rate value. This function assumes that the parameters in the optimizer and the model have the same reference.

Warning

This function gathers the base learning rate applied to the model weights, including alterations due to any LR scheduler. However, it does not catch any adaptive component, e.g. due to RMSProp, Adam or such.

Returns:

Type Description
Dict[str, float]

List[float]: list of single learning rate or multiple learning rates (as many as the number of the layers contained in the model)

Source code in fedbiomed/common/optimizers/generic_optimizers.py
def get_learning_rate(self) -> Dict[str, float]:
    """Gets learning rates from param groups in Pytorch optimizer.

    For each optimizer param group, it iterates over all parameters in that parameter group and searches for the "
    corresponding parameter of the model by iterating over all model parameters. If it finds a correspondence,
    it saves the learning rate value. This function assumes that the parameters in the optimizer and the model
    have the same reference.


    !!! warning
        This function gathers the base learning rate applied to the model weights,
        including alterations due to any LR scheduler. However, it does not catch
        any adaptive component, e.g. due to RMSProp, Adam or such.

    Returns:
        List[float]: list of single learning rate or multiple learning rates
            (as many as the number of the layers contained in the model)
    """
    logger.warning(
        "`get_learning_rate` is deprecated and will be removed in future Fed-BioMed releases",
        broadcast=True)

    mapping_lr_layer_name: Dict[str, float] = {}

    for param_group in self.optimizer.param_groups:
        for layer_params in param_group['params']:
            for layer_name, tensor in self._model.model.named_parameters():
                if layer_params is tensor:
                    mapping_lr_layer_name[layer_name] = param_group['lr']
    return mapping_lr_layer_name
step
step()

Performs an optimization step and updates model weights

Source code in fedbiomed/common/optimizers/generic_optimizers.py
def step(self):
    """Performs an optimization step and updates model weights
    """
    self.optimizer.step()
zero_grad
zero_grad()

Zeroes gradients of the Pytorch model. Basically calls the zero_grad method of the optimizer.

Source code in fedbiomed/common/optimizers/generic_optimizers.py
def zero_grad(self):
    """Zeroes gradients of the Pytorch model. Basically calls the `zero_grad`
    method of the optimizer.
    """
    self.optimizer.zero_grad()

Optimizer

Optimizer(lr, decay=0.0, modules=None, regularizers=None)

Optimizer class with a declearn-backed modular SGD-core algorithm.

Parameters:

Name Type Description Default
lr float

Base learning rate (i.e. step size) applied to gradients-based updates upon applying them to a model's weights.

required
decay float

Optional weight decay parameter, used to parameterize a decoupled weight decay regularization term (see [1]) added to the updates right before the learning rate is applied and model weights are effectively updated.

0.0
modules Optional[Sequence[Union[OptiModule, str, Tuple[str, Dict[str, Any]]]]]

Optional list of plug-in modules implementing gradients' alteration into model weights' udpates. Modules will be applied to gradients following this list's ordering. See declearn.optimizer.modules.OptiModule for details. See Notes section below for details on the "specs" format.

None
regularizers Optional[Sequence[Union[Regularizer, str, Tuple[str, Dict[str, Any]]]]]

Optional list of plug-in loss regularizers. Regularizers will be applied to gradients following this list's order, prior to any other alteration (see modules above). See declearn.optimizer.regularizers.Regularizer for details. See Notes section below for details on the "specs" format.

None

Note

Regularizer and OptiModule to be used by this optimizer, specified using the regularizers and modules parameters, may be passed as ready-for-use instances, or be instantiated from specs, consisting either of a single string (the name attribute of the class to build) or a tuple grouping this name and a config dict (to specify some hyper-parameters).

References

[1] Loshchilov & Hutter, 2019. Decoupled Weight Decay Regularization. https://arxiv.org/abs/1711.05101

Source code in fedbiomed/common/optimizers/optimizer.py
def __init__(
    self,
    lr: float,
    decay: float = 0.0,
    modules: Optional[
        Sequence[Union[OptiModule, str, Tuple[str, Dict[str, Any]]]]
    ] = None,
    regularizers: Optional[
        Sequence[Union[Regularizer, str, Tuple[str, Dict[str, Any]]]]
    ] = None,
) -> None:
    """Instantiate the declearn-issued gradient-descent optimizer.

    Args:
        lr: Base learning rate (i.e. step size) applied to gradients-based
            updates upon applying them to a model's weights.
        decay: Optional weight decay parameter, used to parameterize a
            decoupled weight decay regularization term (see [1]) added to
            the updates right before the learning rate is applied and model
            weights are effectively updated.
        modules: Optional list of plug-in modules implementing gradients'
            alteration into model weights' udpates. Modules will be applied
            to gradients following this list's ordering.
            See `declearn.optimizer.modules.OptiModule` for details.
            See Notes section below for details on the "specs" format.
        regularizers: Optional list of plug-in loss regularizers.
            Regularizers will be applied to gradients following this list's
            order, prior to any other alteration (see `modules` above).
            See `declearn.optimizer.regularizers.Regularizer` for details.
            See Notes section below for details on the "specs" format.

    !!! info "Note"
        `Regularizer` and `OptiModule` to be used by this optimizer,
        specified using the `regularizers` and `modules` parameters,
        may be passed as ready-for-use instances, or be instantiated
        from specs, consisting either of a single string (the `name`
        attribute of the class to build) or a tuple grouping this
        name and a config dict (to specify some hyper-parameters).

    !!! info "References"
        [1] Loshchilov & Hutter, 2019.
            Decoupled Weight Decay Regularization.
            https://arxiv.org/abs/1711.05101
    """
    try:
        self._optimizer = DeclearnOptimizer(
            lrate=lr,
            w_decay=decay,
            modules=modules,
            regularizers=regularizers,
        )
    except (KeyError, TypeError) as exc:
        raise FedbiomedOptimizerError(
            f"{ErrorNumbers.FB621.value}: declearn Optimizer instantiation"
            f" raised the following exception: {repr(exc)}"
        ) from exc

Functions

from_declearn_optimizer classmethod
from_declearn_optimizer(declearn_optimizer)

Wrap a declearn Optimizer into a fed-biomed one.

Parameters:

Name Type Description Default
declearn_optimizer Optimizer

[declearn.optimizer.Optimizer][] instance that needs to be wrapped.

required

Returns:

Type Description
Self

Fed-BioMed Optimizer instance wrapping a copy of the input declearn optimizer.

Source code in fedbiomed/common/optimizers/optimizer.py
@classmethod
def from_declearn_optimizer(
    cls,
    declearn_optimizer: DeclearnOptimizer,
) -> Self:
    """Wrap a declearn Optimizer into a fed-biomed one.

    Args:
        declearn_optimizer: [declearn.optimizer.Optimizer][] instance that
            needs to be wrapped.

    Returns:
        Fed-BioMed `Optimizer` instance wrapping a copy of the input
            declearn optimizer.
    """
    config = declearn_optimizer.get_config()
    optim = cls(
        lr=config["lrate"],
        decay=config["w_decay"],
        modules=config["modules"],
        regularizers=config["regularizers"],
    )
    optim._optimizer.set_state(declearn_optimizer.get_state())
    return optim
get_aux
get_aux()

Return auxiliary variables that need to be shared across network.

Returns:

Type Description
Dict[str, Union[Dict[str, Any], Any]]

Aux-var dict that associates module.collect_aux_var() values to module.name keys for each and every module plugged in this Optimizer that has some auxiliary variables to share.

Note

"Auxiliary variables" are information that needs to be shared between the nodes and the researcher between training rounds, to synchronize some optimizer plug-ins that work by pair. Their production via this method can have internal side effects; get_aux should therefore be called sparingly.

Source code in fedbiomed/common/optimizers/optimizer.py
def get_aux(self) -> Dict[str, Union[Dict[str, Any], Any]]:
    """Return auxiliary variables that need to be shared across network.

    Returns:
        Aux-var dict that associates `module.collect_aux_var()` values to
            `module.name` keys for each and every module plugged in this
            Optimizer that has some auxiliary variables to share.

    !!! info "Note"
        "Auxiliary variables" are information that needs to be shared
        between the nodes and the researcher between training rounds, to
        synchronize some optimizer plug-ins that work by pair. Their
        production via this method can have internal side effects;
        `get_aux` should therefore be called sparingly.
    """
    try:
        return self._optimizer.collect_aux_var()
    except Exception as exc:
        raise FedbiomedOptimizerError(
            f"{ErrorNumbers.FB621.value}: error in 'get_aux': {exc}"
        ) from exc
get_state
get_state()

Return the configuration and current states of this Optimizer.

This method is to be used for creating breakpoints.

Returns:

Type Description
Dict[str, Any]

State-and-config dict that may be saved as part of a breakpoint file, and used to re-create this Optimizer using the Optimizer.load_state classmethod constructor.

Source code in fedbiomed/common/optimizers/optimizer.py
def get_state(self) -> Dict[str, Any]:
    """Return the configuration and current states of this Optimizer.

    This method is to be used for creating breakpoints.

    Returns:
        State-and-config dict that may be saved as part of a breakpoint
            file, and used to re-create this Optimizer using the
            `Optimizer.load_state` classmethod constructor.
    """
    try:
        config = self._optimizer.get_config()
        states = self._optimizer.get_state()
        return {"config": config, "states": states}
    except Exception as exc:
        raise FedbiomedOptimizerError(
            f"{ErrorNumbers.FB621.value}: error in 'get_state': {exc}"
        ) from exc
init_round
init_round()

Trigger start-of-training-round behavior of wrapped regularizers.

Source code in fedbiomed/common/optimizers/optimizer.py
def init_round(self) -> None:
    """Trigger start-of-training-round behavior of wrapped regularizers."""
    try:
        self._optimizer.start_round()
    except Exception as exc:
        raise FedbiomedOptimizerError(
            f"{ErrorNumbers.FB621.value}: error in 'init_round': {exc}"
        ) from exc
load_state classmethod
load_state(state)

Instantiate an Optimizer from its breakpoint state dict.

Parameters:

Name Type Description Default
state Dict[str, Any]

state-and-config dict created using the get_state method.

required

Returns:

Type Description
Self

Optimizer instance re-created from the state dict.

Raises:

Type Description
FedbiomedOptimizerError

If the input state dict has improper keys or fails to set up a declearn Optimizer and set back its state.

Source code in fedbiomed/common/optimizers/optimizer.py
@classmethod
def load_state(cls, state: Dict[str, Any]) -> Self:
    """Instantiate an Optimizer from its breakpoint state dict.

    Args:
        state: state-and-config dict created using the `get_state` method.

    Returns:
        Optimizer instance re-created from the `state` dict.

    Raises:
        FedbiomedOptimizerError: If the input `state` dict has improper keys
            or fails to set up a declearn Optimizer and set back its state.
    """
    try:
        optim = DeclearnOptimizer.from_config(state["config"])
        optim.set_state(state["states"])
    except KeyError as exc:
        raise FedbiomedOptimizerError(
            f"{ErrorNumbers.FB621.value}: Missing field in the breakpoints state: {exc}"
        ) from exc
    except Exception as exc:
        raise FedbiomedOptimizerError(
            f"{ErrorNumbers.FB621.value}: `Optimizer.load_state`: {exc}"
        ) from exc
    return cls(
        lr=optim.lrate,
        decay=optim.w_decay,
        modules=optim.modules,
        regularizers=optim.regularizers,
    )
set_aux
set_aux(aux)

Update plug-in modules based on received shared auxiliary variables.

Parameters:

Name Type Description Default
aux Dict[str, Dict[str, Any]]

Auxiliary variables received from the counterpart optimizer (on the other side of the node-researcher frontier), that are to be a {module.name: module.collect_aux_var()} or a {module.name: {node: module.collect_aux_var()}} dict (depending on which side this optimizer is on).

required

Raises:

Type Description
FedbiomedOptimizerError

If a key from aux_var does not match the name of any module plugged in this optimizer (i.e. if received variables cannot be mapped to a destinatory module).

Note

"Auxiliary variables" are information that is shared between the nodes and researcher between training rounds, to synchronize some optimizer plug-ins that work by pair. The inputs to this method are not simply stored by the Optimizer, but are processed into internal side effects; this method should therefore be called sparingly.

Source code in fedbiomed/common/optimizers/optimizer.py
def set_aux(self, aux: Dict[str, Dict[str, Any]]) -> None:
    """Update plug-in modules based on received shared auxiliary variables.

    Args:
        aux: Auxiliary variables received from the counterpart optimizer
            (on the other side of the node-researcher frontier), that are
            to be a `{module.name: module.collect_aux_var()}` *or* a
            `{module.name: {node: module.collect_aux_var()}}` dict
            (depending on which side this optimizer is on).

    Raises:
        FedbiomedOptimizerError: If a key from `aux_var` does not match the
            name of any module plugged in this optimizer (i.e. if received
            variables cannot be mapped to a destinatory module).

    !!! info "Note"
        "Auxiliary variables" are information that is shared between the
        nodes and researcher between training rounds, to synchronize some
        optimizer plug-ins that work by pair. The inputs to this method are
        not simply stored by the Optimizer, but are processed into internal
        side effects; this method should therefore be called sparingly.
    """
    try:
        self._optimizer.process_aux_var(aux)
    except Exception as exc:
        raise FedbiomedOptimizerError(
            f"{ErrorNumbers.FB621.value}: `Optimizer.set_aux`: {exc}"
        ) from exc
step
step(grads, weights)

Run an optimization step to compute and return model weight updates.

Use the pre-assigned weights and grads (set using the set_weights and set_grads methods) to compute weight updates, using the pipeline defined by this instance.

Parameters:

Name Type Description Default
grads Vector

Raw gradients based on which to compute weights updates, wrapped into a declearn Vector structure.

required
weights Vector

Current values of the weights with respect to which the gradients were computed, wrapped into a declearn Vector with the same concrete type as grads.

required

Returns:

Type Description
Vector

Updates to be applied to the model weights, computed by: - running wrapped gradients and weights through the regularizer plug-ins (that add loss-regularization terms' derivatives); - running resulting gradients through the optimodule plug-ins (that perform any defined gradient-alteration operation); - adding a decoupled weight-decay term, if one is to be used; - scaling the updates by the base learning rate. The results are wrapped into a declearn Vector structure, the concrete type of which is same as input grads and weights.

Source code in fedbiomed/common/optimizers/optimizer.py
def step(self, grads: Vector, weights: Vector) -> Vector:
    """Run an optimization step to compute and return model weight updates.

    Use the pre-assigned `weights` and `grads` (set using the `set_weights`
    and `set_grads` methods) to compute weight updates, using the pipeline
    defined by this instance.

    Args:
        grads: Raw gradients based on which to compute weights updates,
            wrapped into a declearn Vector structure.
        weights: Current values of the weights with respect to which the
            gradients were computed, wrapped into a declearn Vector with
            the same concrete type as `grads`.

    Returns:
        Updates to be applied to the model weights, computed by:
            - running wrapped gradients and weights through the regularizer
              plug-ins (that add loss-regularization terms' derivatives);
            - running resulting gradients through the optimodule plug-ins
              (that perform any defined gradient-alteration operation);
            - adding a decoupled weight-decay term, if one is to be used;
            - scaling the updates by the base learning rate.
            The results are wrapped into a declearn Vector structure, the
            concrete type of which is same as input `grads` and `weights`.
    """
    # This code mostly replicates that of
    # `declearn.optimizer.Optimizer.compute_updates_from_gradients`.
    try:
        # Add loss-regularization terms' derivatives to the raw gradients.
        for reg in self._optimizer.regularizers:
            grads = reg.run(grads, weights)
        # Iteratively refine updates by running them through the optimodules.
        for mod in self._optimizer.modules:
            grads = mod.run(grads)
        # Apply the base learning rate.
        updates = - self._optimizer.lrate * grads
        # Optionally add the decoupled weight decay term.
        if self._optimizer.w_decay:
            updates -= self._optimizer.w_decay * weights
        # Return the model updates.
        return updates
    except Exception as exc:
        raise FedbiomedOptimizerError(
            f"{ErrorNumbers.FB621.value}: error in 'step': {exc}"
        ) from exc

SklearnOptimizerProcessing

SklearnOptimizerProcessing(model, disable_internal_optimizer)

Context manager used for scikit-learn model, that checks if model parameter(s) has(ve) been changed when disabling scikit-learn internal optimizer - ie when calling disable_internal_optimizer method

Parameters:

Name Type Description Default
model SkLearnModel

a SkLearnModel that wraps a scikit-learn model

required
disable_internal_optimizer bool

whether to disable scikit-learn model internal optimizer (True) in order to apply declearn one or to keep it (False)

required
Source code in fedbiomed/common/optimizers/generic_optimizers.py
def __init__(
    self,
    model: SkLearnModel,
    disable_internal_optimizer: bool
) -> None:
    """Constructor of the object. Sets internal variables

    Args:
        model: a SkLearnModel that wraps a scikit-learn model
        disable_internal_optimizer: whether to disable scikit-learn model internal optimizer (True) in order
            to apply declearn one or to keep it (False)
    """
    self._model = model
    self._disable_internal_optimizer = disable_internal_optimizer