torch_blue.vi.VIModule
- class torch_blue.vi.VIModule(variable_shapes: Mapping[str, Tuple[int, ...] | None] | None = None, variational_distribution: Distribution | List[Distribution] = MeanFieldNormal(), prior: Distribution | List[Distribution] = MeanFieldNormal(), rescale_prior: bool = False, kaiming_initialization: bool = True, prior_initialization: bool = False, return_log_probs: bool = True, device: torch.device | None = None, dtype: torch.dtype | None = None, convert_overwrite: bool = False)
Bases:
torch.nn.ModuleBase class for Modules using Variational Inference.
This class takes the place of
torch.nn.Modulefor BNNs. It is used for any Bayesian module. While atorch.nn.Modulemay be contained within aVIModuleand vice versa there should always be a singularVIModulecontaining all others to avoid superfluous sampling dimensions.VIModulecontains some additional functionality. Firstly, it keeps track of whether the model should return the log probability of the sampled weight (i.e., the log probability to obtain these specific values when sampling from the prior or variational distribution).These are needed for loss calculation byKullbackLeiblerLoss. This is handled automatically as part of accessing the weight matrices, ifreturn_log_probsis True. For evaluation, it can be set to False.The outermost module will aggregate the log probabilities and pack the output and log probs into a
VIReturnobject, which behaves like a pytorch Tensor. However, it has the added attributelog_probswhere the log probs are stored. This is used by losses, therefore it is easiest to wrap all operations into aVIModuleand feed the output directly into a loss function. Classical losses will treat it like a Tensor and torch_blue losses can use the log prob information. If the model has multiple output Tensors, each will contain the full log prob information.Important
When defining custom modules with weights make sure to retrieve them using
sample_variables()as this will maintain the automatic log prob tracking.Secondly, a model of nested
VIModuleautomatically identifies the outermost module and sets the_has_sampling_responsibilityflag. This makes the outermost module always accept the keyword argument samples, which defaults to 10. Since BNNs require multiple samples for each forward pass, the input batch is duplicated accordingly and the forward pass is performed vectorized on all samples. While this is significantly faster than serial evaluation, it naturally requires more memory. Additionally, a certain few operations do not function correctly with the vectorization and should not be used inVIModule. Most importantly, this affects the operators+=,-=,*=, and/=. However, their longform versions work fine, e.g.a = a + binstead ofa += b.If the constructed module does not have its own weights,
super().__init__()is called without arguments. In this setting the methodsget_log_probs(),get_variational_parameters(),reset_variational_parameters(), andsample_variable()cannot be used and raiseNoVariablesError.Any weight matrix in a BNN may require multiple parameters (e.g. mean and std). These are stored in separate attributes and therefore cannot be created without knowledge of the variational distribution. Therefore, only their shapes are provided to
super().__init__()via the variable_shapes argument. This should be a dictionary, where the keys are the random variable names as strings (e.g. “weight” and “bias”) and the values are tuples of integers specifying the shape.After initialization these variables can be accessed as an attribute under the specified name. Each access will yield a new sample. The shape of a random variable can be set to
None. In that case accessing it will always returnNone.Note
The insertion order of the dictionary becomes the order
self.random_variables.The names of the created attributes can be discovered using the
variational_parameter_name()method.Additionally, a module with random variables accepts arguments from
VIkwargsas keyword arguments. If a list of priors or variational distributions is provided they are again assumed to follow the insertion order as described above.- Parameters:
variable_shapes (Optional[Mapping[str, Optional[Tuple[int, ...]]]], default = None) – Shape specifications for all random variables. Keys are turned into
self.random_variablesin insertion order.VIkwargs – Several standard keyword arguments. See
VIkwargsfor details.
- Raises:
NoVariablesError – If the module does not have Bayesian parameters of its own and a method requiring them is called.
- property random_variables: Tuple[str, Ellipsis] | None
Names of the modules random variables.
- reset_variational_parameters() None
Reset or initialize the parameters of the Module.
- Raises:
NoVariablesError – If the module does not have parameters of its own.
- static variational_parameter_name(variable: str, variational_parameter: str) str
Get the attribute name of the variational parameter for the specified variable.
- Parameters:
variable (str) – Random variable name as specified in self.random_variables.
variational_parameter (str) – Variational parameter name as specified by the variational distribution.
- Returns:
The attribute name of the specified parameter.
- Return type:
str
- get_variational_parameters(variable: str) List[torch.Tensor]
Get all variational parameters for the specified variable.
- Parameters:
variable (str) – Random variable name as specified in self.random_variables.
- Returns:
All variational parameters for the specified variable in the order specified by the associated variational distribution.
- Return type:
List[Tensor]
- Raises:
NoVariablesError – If the module does not have parameters of its own or the requested variable is None.
- get_log_probs(sample: torch.Tensor, variable: str) torch.Tensor
Get prior and variational log prob of the sampled parameters.
Accepts the sampled parameters as returned by the self.sample_variable method and calculates the total prior and variational log probability.
- Parameters:
sample (Tensor) – Sampled parameter as returned by the self.sample_variable method.
variable (str) – The name of the relevant variable.
- Returns:
A Tensor containing two values: the log probability of the sampled values, if they were drawn from the prior or variational distribution (in that order).
- Return type:
Tensor
- Raises:
NoVariablesError – If the module does not have parameters of its own.
- sample_variable(variable: str) torch.Tensor | None
Draw one sample from the variational distribution of one random variable.
This also performs log prob tracking, if
return_log_probsis True.- Parameters:
variable (str) – The variable to sample.
- Returns:
The sampled variable.
- Return type:
Tensor
- Raises:
NoVariablesError – If the module does not have parameters of its own.
- sampled_forward(*input_: torch.Tensor | None, samples: int = 10, **kwargs: Any) torch_blue.vi.utils.vi_return.VIReturn | Tuple[torch_blue.vi.utils.vi_return.VIReturn, ...]
Forward pass of the module evaluating multiple weight samples.
This will automatically be called by the outermost module. Instead of the
forward()method. It grabs thesamplesargument, if provided, and copies the input batch the specified number of times. Theforward()is performed vectorized over that additional sample dimension.If you need more information on how this is achieved, check the documentation of this class’ __post_init__ method in the source code. Note this goes in deep and if checking the source code seems too much hassle you should probably not touch it and write an issue instead.
- reset_log_probs() None
Reset all tracked log probabilities.
- gather_log_probs() torch.Tensor
Gather and aggregate log probs from all submodules, then reset them.
- Returns:
The aggregated log probabilities of all submodules.
- Return type:
Tensor
- property return_log_probs: bool
Set whether the module returns log probabilities.
Log probabilities are required for most standard losses.
- Returns:
Whether the module returns log probabilities.
- Return type:
bool