Adapter#
- class bayesflow.adapters.Adapter(transforms: Sequence[Transform] | None = None, device: str = 'cpu', differentiable: bool = False, jit_compile: bool = False)[source]#
Bases:
MutableSequence[Transform]Defines an adapter to apply various transforms to simulated / real quantities in an amortized workflow. The role of the adapter is to make simulation outputs / real data neural network-friendly.
Where possible, the transforms also supply an inverse transform. An adapter can also have no transformers, in which case it simply returns a shallow copy of the input data. This can be useful for example to ensure that no side effects occur when the same data dictionary is passed to downstream consumers.
Note: most ready-made transforms are rather simple and currently support only numpy operations. However, the adapter is designed to be flexible and can accommodate arbitrary Tensors (e.g.,
torch.Tensor).In the latter cases, users can implement custom transforms by inheriting from the base
Transformclass and overriding theforwardandinversemethods.- Parameters:
- transformsSequence[Transform], optional
The sequence of transforms to execute.
- device: str, optional
Passed to keras.device to specify on which device to apply the adapter.
- differentiable: bool, optional
If False (default), adapter transforms run in a state detached from the computational graph.
- jit_compile: bool, optional
If True, lazily compile the transform sequence. The first call for each direction and set of keyword arguments runs eagerly to initialize stateful transforms. Dtype normalization and the final device handoff remain outside the compiled region. Default is False.
- static create_default(inference_variables: Sequence[str]) Adapter[source]#
Create an adapter with a set of default transforms.
- Parameters:
- inference_variablesSequence of str
The names of the variables to be inferred by an estimator.
- Returns:
- An initialized Adapter with a set of default transforms.
- forward(data: dict[str, Any], *, log_det_jac: bool = False, **kwargs) dict[str, Tensor] | tuple[dict[str, Tensor], dict[str, Tensor]][source]#
Apply the transforms in the forward direction.
- Parameters:
- datadict[str, Any]
The data to be transformed.
- log_det_jac: bool, optional
Whether to return the log determinant of the Jacobian of the transforms.
- **kwargsdict
Additional keyword arguments passed to each transform.
- Returns:
- dict | tuple[dict, dict]
The transformed data or tuple of transformed data and log determinant of the Jacobian.
- inverse(data: dict[str, Any], *, log_det_jac: bool = False, **kwargs) dict[str, Tensor] | tuple[dict[str, Tensor], dict[str, Tensor]][source]#
Apply the transforms in the inverse direction.
- Parameters:
- datadict[str, Any]
The data to be transformed.
- log_det_jac: bool, optional
Whether to return the log determinant of the Jacobian of the transforms.
- **kwargsdict
Additional keyword arguments passed to each transform.
- Returns:
- dict | tuple[dict, dict]
The transformed data or tuple of transformed data and log determinant of the Jacobian.
- __call__(data: dict[str, Any] | tuple[dict[str, Tensor], dict[str, Tensor]], *, inverse: bool = False, **kwargs) dict[str, Tensor] | tuple[dict[str, Tensor], dict[str, Tensor]][source]#
Apply the transforms in the given direction.
- Parameters:
- dataMapping[str, Any]
The data to be transformed.
- inversebool, optional
If False, apply the forward transform, else apply the inverse transform (default False).
- **kwargs
Additional keyword arguments passed to each transform.
- Returns:
- dict | tuple[dict, dict]
The transformed data or tuple of transformed data and log determinant of the Jacobian.
- append(value: Transform) Adapter[source]#
Append a transform to the list of transforms.
- Parameters:
- valueTransform
The transform to be added.
- device_handoff(data: tuple | dict[str, Any]) tuple | dict[str, Any][source]#
Convert
datatofloatxtensors and hand them off on the default device.
- extend(values: Sequence[Transform]) Adapter[source]#
Extend the adapter with a sequence of transforms.
- Parameters:
- valuesSequence of Transform
The additional transforms to extend the adapter.
- insert(index: int, value: Transform | Sequence[Transform]) Adapter[source]#
Insert a transform at a given index.
- Parameters:
- indexint
The index to insert at.
- valueTransform or Sequence of Transform
The transform or transforms to insert.
- apply(include: str | Sequence[str] = None, *, forward: str, inverse: str = None, predicate: Predicate = None, exclude: str | Sequence[str] = None, **kwargs)[source]#
Append a
KerasTransformto the adapter.- Parameters:
- forwardstr
The name of the NumPy function to use for the forward transformation.
- inversestr, optional
The name of the NumPy function to use for the inverse transformation. By default, the inverse is inferred from the forward argument for supported methods. You can find the supported methods in
INVERSE_METHODS.- predicatePredicate, optional
Function that indicates which variables should be transformed.
- includestr or Sequence of str, optional
Names of variables to include in the transform.
- excludestr or Sequence of str, optional
Names of variables to exclude from the transform.
- **kwargsdict
Additional keyword arguments passed to the transform.
- apply_serializable(include: str | Sequence[str] = None, *, forward: Callable[[Tensor], Tensor], inverse: Callable[[Tensor], Tensor], predicate: Predicate = None, exclude: str | Sequence[str] = None, **kwargs)[source]#
Append a
SerializableCustomTransformto the adapter.- Parameters:
- forwardfunction, no lambda
Registered serializable function to transform the data in the forward pass. For the adapter to be serializable, this function has to be serializable as well (see Notes). Therefore, only proper functions and no lambda functions can be used here.
- inversefunction, no lambda
Registered serializable function to transform the data in the inverse pass. For the adapter to be serializable, this function has to be serializable as well (see Notes). Therefore, only proper functions and no lambda functions can be used here.
- predicatePredicate, optional
Function that indicates which variables should be transformed.
- includestr or Sequence of str, optional
Names of variables to include in the transform.
- excludestr or Sequence of str, optional
Names of variables to exclude from the transform.
- **kwargsdict
Additional keyword arguments passed to the transform.
- Raises:
- ValueError
When the provided functions are not registered serializable functions.
Notes
Important: The forward and inverse functions have to be registered with Keras. To do so, use the @keras.saving.register_keras_serializable decorator. They must also be registered (and identical) when loading the adapter at a later point in time.
Examples
The example below shows how to use the keras.saving.register_keras_serializable decorator to register functions with Keras. Note that for this simple example, one usually would use the simpler
apply()method.>>> import keras >>> >>> @keras.saving.register_keras_serializable("custom") >>> def forward_fn(x): >>> return x**2 >>> >>> @keras.saving.register_keras_serializable("custom") >>> def inverse_fn(x): >>> return x**0.5 >>> >>> adapter = bf.Adapter().apply_serializable( >>> "x", >>> forward=forward_fn, >>> inverse=inverse_fn, >>> )
- as_set(keys: str | Sequence[str])[source]#
Append an
AsSettransform to the adapter.- Parameters:
- keysstr or Sequence of str
The names of the variables to apply the transform to.
- as_time_series(keys: str | Sequence[str])[source]#
Append an
AsTimeSeriestransform to the adapter.- Parameters:
- keysstr or Sequence of str
The names of the variables to apply the transform to.
- broadcast(keys: str | Sequence[str], *, to: str, expand: str | int | tuple = 'left', exclude: int | tuple = -1, squeeze: int | tuple = None)[source]#
Append a
Broadcasttransform to the adapter.- Parameters:
- keysstr or Sequence of str
The names of the variables to apply the transform to.
- tostr
Name of the data variable to broadcast to.
- expandstr or int or tuple, optional
Where should new dimensions be added to match the number of dimensions in to? Can be “left”, “right”, or an integer or tuple containing the indices of the new dimensions. The latter is needed if we want to include a dimension in the middle, which will be required for more advanced cases. By default we expand left.
- excludeint or tuple, optional
Which dimensions (of the dimensions after expansion) should retain their size, rather than being broadcasted to the corresponding dimension size of to? By default we exclude the last dimension (usually the data dimension) from broadcasting the size.
- squeezeint or tuple, optional
Axis to squeeze after broadcasting.
Notes
Important: Do not broadcast to variables that are used as inference variables (i.e., parameters to be inferred by the networks). The adapter will work during training but then fail during inference because the variable being broadcasted to is not available.
- concatenate(keys: str | Sequence[str], *, into: str, axis: int = -1)[source]#
Append a
Concatenatetransform to the adapter.- Parameters:
- keysstr or Sequence of str
The names of the variables to concatenate.
- intostr
The name of the resulting variable.
- axisint, optional
Along which axis to concatenate the keys. The last axis is used by default.
- convert_dtype(from_dtype: str, to_dtype: str, *, predicate: Predicate = None, include: str | Sequence[str] = None, exclude: str | Sequence[str] = None)[source]#
Append a
ConvertDTypetransform to the adapter. See alsomap_dtype().- Parameters:
- from_dtypestr
Original dtype
- to_dtypestr
Target dtype
- predicatePredicate, optional
Function that indicates which variables should be transformed.
- includestr or Sequence of str, optional
Names of variables to include in the transform.
- excludestr or Sequence of str, optional
Names of variables to exclude from the transform.
- constrain(keys: str | Sequence[str], *, lower: int | float | Tensor = None, upper: int | float | Tensor = None, method: str = 'default', inclusive: str = 'both', epsilon: float = 1e-06)[source]#
Append a
Constraintransform to the adapter.- Parameters:
- keysstr or Sequence of str
The names of the variables to constrain.
- lower: int or float or Tensor, optional
Lower bound for named data variable.
- upperint or float or Tensor, optional
Upper bound for named data variable.
- methodstr, optional
Method by which to shrink the network predictions space to specified bounds. Choose from - Double bounded methods: sigmoid, expit, (default = sigmoid) - Lower bound only methods: softplus, exp, (default = softplus) - Upper bound only methods: softplus, exp, (default = softplus)
- inclusive{‘both’, ‘lower’, ‘upper’, ‘none’}, optional
Indicates which bounds are inclusive (or exclusive). - “both” (default): Both lower and upper bounds are inclusive. - “lower”: Lower bound is inclusive, upper bound is exclusive. - “upper”: Lower bound is exclusive, upper bound is inclusive. - “none”: Both lower and upper bounds are exclusive.
- epsilonfloat, optional
Small value to ensure inclusive bounds are not violated. Current default is 1e-6 as this ensures finite outcomes with the default transformations applied to data exactly at the boundaries.
- as_correlation_matrix(keys: str | Sequence[str], cholesky: bool = False)[source]#
Append a
AsCorrelationMatrixtransform to the adapter.Constrains neural network predictions of a data variable to a valid (symmetric, positive definite, unit diagonal) K x K correlation matrix, using the transforms explained by [1].
The unconstrained representation is a flat vector of K * (K - 1) / 2 entries.
- Parameters:
- keysstr or Sequence of str
The names of the variables to constrain.
- choleskybool, optional
Whether the constrained side of the transform is the lower Cholesky factor, rather than the full correlation matrix. Default is False (use the full correlation matrix).
References
- [1] Lewandowski, D., Kurowicka, D., & Joe, H. (2009).
Generating random correlation matrices based on vines and extended onion method. Journal of Multivariate Analysis, 100(9), 1989-2001. https://doi.org/10.1016/j.jmva.2009.04.008
- as_covariance_matrix(keys: str | Sequence[str], cholesky: bool = False, diag_kwargs: dict = None)[source]#
Append a
AsCovarianceMatrixtransform to the adapter.Constrains neural network predictions of a data variable to a valid (symmetric, positive definite) K x K covariance (or precision) matrix.
The unconstrained representation is a flat vector of K * (K + 1) / 2 entries of the lower Cholesky factor of the covariance matrix. First, the K diagonal entries, passed through a lower-bounded
Constraintransform to keep them positive, followed by the K * (K - 1) / 2 entries from the lower triangular.- Parameters:
- keysstr or Sequence of str
The names of the variables to constrain.
- choleskybool, optional
Whether the constrained side of the transform is the Cholesky factor, rather than the full covariance matrix. Default is False (use the full covariance matrix).
- diag_kwargsdict, optional
Keyword arguments forwarded to the
Constraintransform that constrains the diagonal to be positive. The lower bound is always fixed to 0.0.
- as_precision_matrix(**kwargs)[source]#
Append a
AsCovarianceMatrixtransform to the adapter.A precision matrix is the inverse of a covariance matrix, but is likewise symmetric and positive definite, so the same transform applies. This is an alias for
as_covariance_matrix(); see there for the accepted parameters. Note that this transform does not itself invert a covariance matrix into a precision matrix (or vice versa), it only constrains its input to some symmetric positive definite matrix, whatever you intend that matrix to represent.
- as_simplex(keys: str | Sequence[str], axis: int | Tensor = -1, method: str = 'default')[source]#
Append a
AsSimplextransform to the adapter.Constrains neural network predictions of a data variable to a unit simplex, so that the constrained representation is non-negative and sums to one along the given axis.
- Parameters:
- keysstr or Sequence of str
The names of the variables to constrain.
- axisint, optional
The axis of the simplex-constrained data along which values sum to one over all K elements. The corresponding unconstrained representation has a size of K-1 along this axis.
- methodstr, optional
Method by which to transform between the K dimensional simplex space and the K-1 dimensional unconstrained space. - “default” / “simplex”: sum-to-zero (orthogonal basis) transform followed by a softmax transform. Plain softmax is not invertible (shifting all values by a constant results in the same inverse). The sum-to-zero removes this issue. - “stick”: stick-breaking logistic transform.
- drop(keys: str | Sequence[str])[source]#
Append a
Droptransform to the adapter.- Parameters:
- keysstr or Sequence of str
The names of the variables to drop.
- expand_dims(keys: str | Sequence[str], *, axis: int | tuple)[source]#
Append an
ExpandDimstransform to the adapter.- Parameters:
- keysstr or Sequence of str
The names of the variables to expand.
- axisint or tuple
The axis to expand.
- group(keys: Sequence[str], into: str, *, prefix: str = '')[source]#
Append a
Grouptransform to the adapter.Groups the given variables as a dictionary in the key into. As most transforms do not support nested structures, this should usually be the last transform in the adapter.
- Parameters:
- keysSequence of str
The names of the variables to group together.
- intostr
The name of the variable to store the grouped variables in.
- prefixstr, optional
An optional common prefix of the variable names before grouping, which will be removed after grouping.
- Raises:
- ValueError
If a prefix is specified, but a provided key does not start with the prefix.
- ungroup(key: str, *, prefix: str = '')[source]#
Append an
Ungrouptransform to the adapter.Ungroups the the variables in key from a dictionary into individual entries. Most transforms do not support nested structures, so this can be used to flatten a nested structure. The nesting can be re-established after the transforms using the
group()method.- Parameters:
- keystr
The name of the variable to ungroup. The corresponding variable has to be a dictionary.
- prefixstr, optional
An optional common prefix that will be added to the ungrouped variable names. This can be necessary to avoid duplicate names.
- keep(keys: str | Sequence[str])[source]#
Append a
Keeptransform to the adapter.- Parameters:
- keysstr or Sequence of str
The names of the variables to keep.
- log(keys: str | Sequence[str], *, p1: bool = False)[source]#
Append an
Logtransform to the adapter.- Parameters:
- keysstr or Sequence of str
The names of the variables to transform.
- p1boolean
Add 1 to the input before taking the logarithm?
- map_dtype(keys: str | Sequence[str], to_dtype: str)[source]#
Append a
ConvertDTypetransform to the adapter. See alsoconvert_dtype().- Parameters:
- keysstr or Sequence of str
The names of the variables to transform.
- to_dtypestr
Target dtype
- one_hot(keys: str | Sequence[str], num_classes: int)[source]#
Append a
OneHottransform to the adapter.- Parameters:
- keysstr or Sequence of str
The names of the variables to transform.
- num_classesint
Number of classes for the encoding.
- random_subsample(key: str, *, sample_size: int | float, axis: int = -1)[source]#
Append a
RandomSubsampletransform to the adapter.- Parameters:
- keystr or Sequence of str
The name of the variable to subsample.
- sample_sizeint or float
The number of samples to draw, or a fraction between 0 and 1 of the total number of samples to draw.
- axis: int, optional
Which axis to draw samples over. The last axis is used by default.
- rename(from_key: str, to_key: str)[source]#
Append a
Renametransform to the adapter.- Parameters:
- from_keystr
Variable name that should be renamed
- to_keystr
New variable name
- split(key: str, *, into: Sequence[str], indices_or_sections: int | Sequence[int] = None, axis: int = -1)[source]#
- squeeze(keys: str | Sequence[str], *, axis: int | Sequence[int])[source]#
Append a
Squeezetransform to the adapter.- Parameters:
- keysstr or Sequence of str
The names of the variables to squeeze.
- axisint or tuple
The axis to squeeze. As the number of batch dimensions might change, we advise using negative numbers (i.e., indexing from the end instead of the start).
- sqrt(keys: str | Sequence[str])[source]#
Append an
Sqrttransform to the adapter.- Parameters:
- keysstr or Sequence of str
The names of the variables to transform.
- standardize(include: str | Sequence[str] = None, *, mean: int | float | Tensor, std: int | float | Tensor, predicate: Predicate = None, exclude: str | Sequence[str] = None, **kwargs)[source]#
Append a
Standardizetransform to the adapter.- Parameters:
- includestr or Sequence of str, optional
Names of variables to include in the transform.
- meanint or float
Specifies the mean (location) of the transform.
- stdint or float
Specifies the standard deviation (scale) of the transform.
- predicatePredicate, optional
Function that indicates which variables should be transformed.
- excludestr or Sequence of str, optional
Names of variables to exclude from the transform.
- **kwargs
Additional keyword arguments passed to the transform.
- take(include: str | Sequence[str] = None, *, indices: Sequence[int], axis: int = -1, predicate: Predicate = None, exclude: str | Sequence[str] = None)[source]#
Append a
Taketransform to the adapter.- Parameters:
- includestr or Sequence of str, optional
Names of variables to include in the transform.
- indicesSequence of int
Which indices to take from the data.
- axisint, optional
Which axis to take from. The last axis is used by default.
- predicatePredicate, optional
Function that indicates which variables should be transformed.
- excludestr or Sequence of str, optional
Names of variables to exclude from the transform.
- to_array(include: str | Sequence[str] = None, *, predicate: Predicate = None, exclude: str | Sequence[str] = None, **kwargs)[source]#
Append a
ToArraytransform to the adapter.- Parameters:
- predicatePredicate, optional
Function that indicates which variables should be transformed.
- includestr or Sequence of str, optional
Names of variables to include in the transform.
- excludestr or Sequence of str, optional
Names of variables to exclude from the transform.
- **kwargsdict
Additional keyword arguments passed to the transform.
- nan_to_num(keys: str | Sequence[str], default_value: float = 0.0, return_mask: bool = False, mask_prefix: str = 'mask')[source]#
Append
NanToNumtransform to the adapter.- Parameters:
- keysstr or sequence of str
The names of the variables to clean / mask.
- default_valuefloat
Value to substitute wherever data is NaN. Defaults to 0.0.
- return_maskbool
If True, encode a binary missingness mask alongside the data, which is also used to restore the NaNs in the inverse transform. If False, the transform is not invertible and the inverse leaves the data unchanged. Defaults to False.
- mask_prefixstr
Prefix for the mask key in the output dictionary. Defaults to ‘mask_’. If the mask key already exists, a ValueError is raised to avoid overwriting existing masks.
- count(value) integer -- return number of occurrences of value#
- index(value[, start[, stop]]) integer -- return first index of value.#
Raises ValueError if the value is not present.
Supporting start and stop arguments is optional, but recommended.
- pop([index]) item -- remove and return item at index (default last).#
Raise IndexError if list is empty or index is out of range.
- remove(value)#
S.remove(value) – remove first occurrence of value. Raise ValueError if the value is not present.
- reverse()#
S.reverse() – reverse IN PLACE