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 |
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
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=[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 |
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 |
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 | required |
Raises:
Type | Description |
---|---|
FedbiomedOptimizerError | raised if optimizer is not a pytorch native optimizer ie a |
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 | 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 | 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 |
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 |
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 |
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 | required |
Returns:
Type | Description |
---|---|
Self | Optimizer instance re-created from the |
Raises:
Type | Description |
---|---|
FedbiomedOptimizerError | If the input |
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 | required |
Raises:
Type | Description |
---|---|
FedbiomedOptimizerError | If a key from |
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 | 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 |
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