LazyStackedTensorDict#
LazyStackedTensorDict has the methods of TensorDictBase,
listed by task in Methods by task. This page lists only the
methods that LazyStackedTensorDict adds, and the overrides that have their own
documentation.
- class tensordict.LazyStackedTensorDict(*tensordicts: T, stack_dim: int = 0, hook_out: callable | None = None, hook_in: callable | None = None, batch_size: Sequence[int] | None = None, device: device | None = None, names: Sequence[str] | None = None, stack_dim_name: str | None = None, strict_shape: bool = False)#
Bases:
TensorDictBaseA stack of tensordicts that keeps each input as a separate tensordict.
torch.stack()andtensordict.stack()return a denseTensorDict. They raise an error when the inputs have different keys, entry shapes or batch sizes. A lazy stack accepts these inputs: it keeps a list of the input tensordicts and stacks their entries only when you read them. Use it for data whose size changes from one sample to the next, such as text or episodes of different lengths. Stacking and variable-size data explains when to use a dense or a lazy stack, and Which container should I use? compares the containers.Build a lazy stack with
tensordict.lazy_stack()orLazyStackedTensorDict(*tds, stack_dim=dim). To get a denseTensorDictwhen the inputs allow it and a lazy stack otherwise, usetensordict.maybe_dense_stack().>>> import torch >>> from tensordict import LazyStackedTensorDict, TensorDict >>> tds = [TensorDict(a=torch.zeros(3)), TensorDict(a=torch.ones(4))] >>> td_stack = LazyStackedTensorDict(*tds, stack_dim=0) >>> td_stack.batch_size torch.Size([2]) >>> td_stack[0] is tds[0] True >>> td_stack.get("a", as_padded_tensor=True) tensor([[0., 0., 0., 0.], [1., 1., 1., 1.]])
A lazy stack behaves as follows:
Indexing along the stack dimension returns the input objects:
td_stack[i] is tds[i].Reading a key (
td_stack["a"]) stacks the entries into a new tensor. In-place changes to that tensor do not reach the inputs. Writes through the lazy stack (td_stack["a"] = value,apply_()) do reach them.If the entry shapes differ,
td_stack["a"]raises an error. Passas_nested_tensor,as_padded_tensororas_listtoget()to read the entries as a nested tensor, a padded tensor or a list. These arguments apply even when the shapes match.keys()lists only the keys that every input has. The printed lazy stack shows the other keys underexclusive_fields.The batch sizes of the inputs must have the same number of dimensions. If a dimension differs between inputs, it is
-1in the stackedbatch_size. Usestrict_shape=Trueto raise an error instead. An entry shape has-1in the same way for each dimension that differs between inputs.
- Parameters:
*tensordicts (TensorDictBase) – the tensordicts to stack.
- Keyword Arguments:
stack_dim (int) – the dimension of the batch size along which the tensordicts are stacked. It must be between
-td.ndim - 1andtd.ndim, wheretdis one of the inputs. Defaults to0.hook_out (callable, optional) –
a callable to execute after
get().Deprecated since version 0.15:
hook_outbelongs to thevmap()support of lazy stacks and has no replacement.hook_in (callable, optional) –
a callable to execute before
set().Deprecated since version 0.15:
hook_inbelongs to thevmap()support of lazy stacks and has no replacement.batch_size (Size or list of int, optional) – if no tensordict is given, the batch size of the stacked tensordicts: the empty stack has a
batch_sizewith0atstack_dim. If tensordicts are given, it must equal the stacked batch size, or the constructor raises aRuntimeError.device (device, optional) – the device of an empty stack. If tensordicts are given, the stack takes the device of the first one and ignores this argument.
names (list of str, optional) – the dimension names of an empty stack. If tensordicts are given, the names come from them, and this argument is ignored with a
FutureWarning. To name the dims of such a stack, passstack_dim_name, or setnameson the stack. Starting with TensorDict 0.17, the default will change to applying these names to the stack.stack_dim_name (str, optional) – the name of the stack dimension. Defaults to
None.strict_shape (bool, optional) – if
True, the batch sizes of the inputs must be equal, or the constructor raises aRuntimeError. Defaults toFalse.
Examples
>>> import torch >>> from tensordict import LazyStackedTensorDict, TensorDict >>> tds = [TensorDict({'a': torch.randn(3, 4)}, batch_size=[3]) ... for _ in range(10)] >>> td_stack = LazyStackedTensorDict.lazy_stack(tds, -1) >>> print(td_stack.shape) torch.Size([3, 10]) >>> print(td_stack.get("a").shape) torch.Size([3, 10, 4]) >>> print(td_stack[:, 0] is tds[0]) True
Inputs with different batch sizes give
-1in the batch size:>>> td_stack = LazyStackedTensorDict( ... TensorDict(a=torch.zeros(3), batch_size=[3]), ... TensorDict(a=torch.zeros(4), batch_size=[4]), ... ) >>> td_stack.batch_size torch.Size([2, -1])
Inputs with different keys keep their own keys:
>>> td_stack = LazyStackedTensorDict( ... TensorDict(a=torch.zeros(3)), TensorDict(a=torch.zeros(3), b=torch.ones(2)) ... ) >>> list(td_stack.keys()) ['a'] >>> td_stack[1]["b"] tensor([1., 1.])
Note
You can assign a list to a key of a lazy stack. The list must have the structure that
tensor.tolist()returns: the length of its first level must equal the first dimension of the lazy stack, whether or not it is the stack dimension.>>> td = LazyStackedTensorDict(TensorDict(), TensorDict(), stack_dim=0) >>> td["a"] = [torch.ones(2), torch.zeros(1)] >>> assert td[1]["a"] == torch.zeros(1) >>> td["b"] = ["a string", "another string"] >>> assert td[1]["b"] == "another string"
- append(tensordict: T) None#
Append a TensorDict onto the stack.
Analogous to list.append. The appended TensorDict must have compatible batch_size and device. The append operation is in-place, nothing is returned.
- Parameters:
tensordict (TensorDictBase) – The TensorDict to be appended onto the stack.
- classmethod from_dict(input_dict: Dict[str, Dict[NestedKey, Any]] | List[Dict[NestedKey, Any]], *other, auto_batch_size: bool = False, batch_size=None, device=None, batch_dims=None, stack_dim_name=None, stack_dim=0, names: list[str] | None = None)#
Builds a lazy stack from a list of dicts, one tensordict per dict.
Each dict goes through
tensordict.TensorDict.from_dict(), then the results are stacked lazily, so the dicts can have different keys and entry shapes. A dict whose keys are"0","1", … is read as that list.- Parameters:
input_dict (list of dicts, or dict of dicts) – the data of each stacked tensordict.
*other – passed to
tensordict.TensorDict.from_dict().
- Keyword Arguments:
auto_batch_size (bool, optional) – if
True, the batch size of each tensordict is computed from its data. Defaults toFalse.batch_size (Size, optional) – the batch size of each stacked tensordict.
device (device, optional) – the device of each stacked tensordict.
batch_dims (int, optional) – with
auto_batch_size, the number of batch dimensions to keep.stack_dim_name (str, optional) – the name of the stack dimension.
stack_dim (int, optional) – the stack dimension. Defaults to
0.names (list of str, optional) – the names of the dimensions of the result, stack dimension included. Exclusive with
stack_dim_name. Without abatch_size, onlynames[stack_dim]is used today and the members get no names. Starting with TensorDict 0.17, the default will change to giving the others to the members once their batch size is known (aFutureWarningis emitted when this changes the result). Passing other entries whose number differs from the member batch dimensions is deprecated and will be removed in TensorDict 0.17 (aDeprecationWarningis emitted); usestack_dim_nameinstead.
- Returns:
Examples
>>> import torch >>> from tensordict import LazyStackedTensorDict >>> td = LazyStackedTensorDict.from_dict( ... [{"a": torch.zeros(3)}, {"a": torch.zeros(4)}], stack_dim_name="t" ... ) >>> td.batch_size, td.names (torch.Size([2]), ['t']) >>> td[1]["a"].shape torch.Size([4])
- classmethod from_list(input: list[Mapping], *, auto_batch_size: bool | None = None, batch_size: Size | None = None, device: device | None = None, batch_dims: int | None = None, names: list[str] | None = None, lazy: bool | None = None) Self#
Builds a lazy stack from a list of dicts.
Same as
from_dict()with a list.lazyis ignored: the result is always a lazy stack. Seetensordict.TensorDictBase.from_list()for the other arguments.Examples
>>> import torch >>> from tensordict import LazyStackedTensorDict >>> td = LazyStackedTensorDict.from_list( ... [{"a": torch.zeros(3)}, {"a": torch.zeros(4)}], auto_batch_size=True ... ) >>> td.batch_size torch.Size([2, -1])
- get_item_shape(key)#
Gets the shape of an item in the lazy stack.
Heterogeneous dimensions are returned as -1.
This implementation is inefficient as it will attempt to stack the items to compute their shape, and should only be used for printing.
- get_nestedtensor(key: NestedKey, default: Any = NO_DEFAULT, *, layout: layout | None = None) Tensor | TensorCollection#
Returns a nested tensor when stacking cannot be achieved.
Deprecated since version 0.15: Use
get(key, as_nested_tensor=True)instead. It differs in three ways: it builds atorch.jaggednested tensor unless you passlayout=torch.strided, whereas this method builds atorch.stridedone by default; when a tensordefaultis given and some tensordicts lackkey, it returnsdefaultitself, whereas this method usesdefaultas the value of the tensordicts that lackkey; and when the stack dim is not 0, it nests the tensors along the stack dim and puts that dim first, whereas this method raises.- Parameters:
key (NestedKey) – the entry to nest.
default (Any, optional) –
the default value to return in case the key isn’t in all sub-tensordicts.
Note
In case the default is a tensor, this method will attempt the construction of a nestedtensor with it. Otherwise, the default value will be returned.
- Keyword Arguments:
layout (layout, optional) – the layout for the nested tensor.
Examples
>>> import torch >>> from tensordict import LazyStackedTensorDict, TensorDict >>> td0 = TensorDict({"a": torch.zeros(4), "b": torch.zeros(4)}, []) >>> td1 = TensorDict({"a": torch.ones(5)}, []) >>> td = LazyStackedTensorDict.lazy_stack([td0, td1], 0) >>> a = td.get_nestedtensor("a") >>> # using a tensor as default uses this default to build the nested tensor >>> b = td.get_nestedtensor("b", default=torch.ones(4)) >>> assert (b[1] == 1).all() >>> # using anything else as default returns the default >>> b2 = td.get_nestedtensor("b", None) >>> assert b2 is None
- property hook_in: Callable | None#
The callable that the lazy stack applies to the values it writes.
Deprecated since version 0.15:
hook_inbelongs to thevmap()support of lazy stacks and has no replacement.
- property hook_out: Callable | None#
The callable that the lazy stack applies to the values it returns.
Deprecated since version 0.15:
hook_outbelongs to thevmap()support of lazy stacks and has no replacement.
- insert(index: int, tensordict: T) None#
Insert a TensorDict into the stack at the specified index.
Analogous to list.insert. The inserted TensorDict must have compatible batch_size and device. Insertion is in-place, nothing is returned.
- Parameters:
index (int) – The index at which the new TensorDict should be inserted.
tensordict (TensorDictBase) – The TensorDict to be inserted into the stack.
- classmethod lazy_stack(items: Sequence[TensorDictBase], dim: int = 0, *, device: device | str | int | None = None, out: T | None = None, stack_dim_name: str | None = None, strict_shape: bool = False, as_list: bool = False, as_padded_tensor: bool = False, as_nested_tensor: bool = False, padding_side: str = 'right', layout: layout | None = None, padding_value: float | int | bool = 0.0) Self#
Stacks tensordicts in a LazyStackedTensorDict.
The result keeps each input as a separate tensordict, so the inputs can have different keys, entry shapes and batch sizes. See
LazyStackedTensorDictfor the behavior of the result, and Stacking and variable-size data for the choice between a dense and a lazy stack.If
itemsholds tensorclass instances of one class, the result is an instance of that class that holds a lazy stack. Ifitemsholds tensors, they are stacked withtorch.stack(), unless one ofas_list,as_padded_tensororas_nested_tensoris set.- Parameters:
items (Sequence of TensorDictBase instances) – the tensordicts to stack. It must not be empty, or a
RuntimeErroris raised.dim (int, optional) – the dim along which to perform the lazy stack. Defaults to 0. A
dimbelow-batch_dims - 1warns and wraps around once more (and raises if it is still out of range). Starting with TensorDict 0.17, the default will change to raising anIndexError, as for a tensor.
- Keyword Arguments:
device (device, optional) – not used: the stack takes the device of the first item.
out (TensorDictBase, optional) – a LazyStackedTensorDict where to write the data. Its batch size must be the stacked batch size.
stack_dim_name (str, optional) – a name for the stacked dimension.
strict_shape (bool, optional) – if
True, the batch sizes of the items must be equal, or aRuntimeErroris raised. Defaults toFalse.
The following keyword arguments apply only when
itemsis a list of tensors. With tensordicts, they have no effect. To read padded or nested entries from a lazy stack of tensordicts, pass them toget()instead.- Keyword Arguments:
as_list (bool, optional) – if
True, the tensors are returned as a list. Exclusive withas_padded_tensorandas_nested_tensor. Defaults toFalse.as_padded_tensor (bool, optional) – if
True, the tensors are padded to the largest shape and stacked into one tensor: each dim is padded to its largest size.padding_valuesets the padding value andpadding_sidesets the side of every padded dim. Exclusive withas_listandas_nested_tensor. Defaults toFalse.as_nested_tensor (bool, optional) – if
True, the tensors are returned as a nested tensor (torch.nested).layoutsets its layout. Tensors that are nested tensors themselves raise aValueError, as a nested tensor has a single nested level. Exclusive withas_listandas_padded_tensor. Defaults toFalse.layout (layout, optional) – the layout of the nested tensor when
as_nested_tensor=True:torch.jaggedortorch.strided. Defaults totorch.jagged.padding_side (str) – The side of padding. Must be “left” or “right”. Defaults to “right”.
padding_value (scalar or bool, optional) – The padding value. Defaults to 0.0.
- Returns:
a
LazyStackedTensorDict, or a tensorclass instance ifitemsholds tensorclass instances.
Examples
>>> import torch >>> from tensordict import LazyStackedTensorDict, TensorDict >>> td_stack = LazyStackedTensorDict.lazy_stack( ... [TensorDict(a=torch.zeros(3)), TensorDict(a=torch.zeros(4))] ... ) >>> type(td_stack).__name__ 'LazyStackedTensorDict' >>> td_stack.get("a", as_list=True) [tensor([0., 0., 0.]), tensor([0., 0., 0., 0.])]
- classmethod maybe_dense_stack(items: Sequence[TensorDictBase], dim: int = 0, out: T | None = None, strict: bool = False) Self#
Stacks tensordicts densely if possible, or onto a LazyStackedTensorDict otherwise.
Use this function when the inputs usually match, but can differ. If every item has the same keys and the same entry shapes, the result is the dense stack that
torch.stack()returns. Otherwise, the result is the lazy stack thatlazy_stack()returns. See Stacking and variable-size data.- Parameters:
items (Sequence of TensorDictBase or tensorclass instances) – the tensordicts to stack.
dim (int, optional) – the new dimension. Defaults to
0. Adimoutside[-batch_dims - 1, batch_dims]warns, and is used on the dims of the leaves. Starting with TensorDict 0.17, the default will change to raising anIndexError, as for a tensor.out (TensorDictBase, optional) – a tensordict to write the result into.
strict (bool, optional) – used only with
out. IfTrue,outmust have the same keys as the items, or aRuntimeErroris raised. Defaults toFalse.
- Returns:
a
TensorDict(or the tensorclass of the items) if the items can be stacked densely, aLazyStackedTensorDictotherwise.
Examples
>>> from tensordict import LazyStackedTensorDict, TensorDict >>> td0 = TensorDict({"a": 0}, []) >>> td1 = TensorDict({"b": 0}, []) >>> out = LazyStackedTensorDict.maybe_dense_stack([td0, td0]) # same keys: dense stack >>> assert type(out) is TensorDict and out.shape == (2,) >>> out = LazyStackedTensorDict.maybe_dense_stack([td0, td1]) # different keys: lazy stack >>> assert isinstance(out, LazyStackedTensorDict) and out.shape == (2,)