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, optional) – 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. Defaults to
None.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 dimensions 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.zeros(3, 4), batch_size=[3]) for _ in range(10)] >>> td_stack = LazyStackedTensorDict.lazy_stack(tds, -1) >>> td_stack.shape torch.Size([3, 10]) >>> td_stack.get("a").shape torch.Size([3, 10, 4]) >>> 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#
Appends a tensordict to the lazy stack, like
list.append().Same as
insert()at the end of the stack.- Parameters:
tensordict (TensorDictBase) – the tensordict to append. It must have the device of the other members and as many batch dimensions. Its sizes must match theirs, except where the batch size of the lazy stack is
-1.
- extend(tensordict: list[T] | T) None#
Appends several tensordicts to the lazy stack, like
list.extend().- Parameters:
tensordict (list of TensorDictBase or TensorDictBase) – the tensordicts to append. A tensordict is unbound along the stack dimension and its parts are appended.
- 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 dict, or dict of dict) – the data of each stacked tensordict.
*other – passed to
tensordict.TensorDict.from_dict().
- Keyword Arguments:
auto_batch_size (bool, optional) – if
True, sets the batch size of each tensordict to the largest leading shape that all its entries share. Defaults toFalse.batch_size (Size or list of int, optional) – the batch size of each stacked tensordict, without the stack dimension. Defaults to
None, which gives each tensordict the batch size[]unless its batch size is set automatically.device (device, str or int, optional) – the device of each stacked tensordict. Defaults to
None, which keeps each leaf where it is.batch_dims (int, optional) – with
auto_batch_size, the maximum number of batch dimensions of each tensordict. Defaults toNone.stack_dim_name (str, optional) – the name of the stack dimension. Defaults to
None.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, one tensordict per dict.
Same as
from_dict()with a list, stacked along dimension0. The dicts can have different keys and entry shapes.- Parameters:
- Keyword Arguments:
auto_batch_size (bool, optional) – if
True, sets the batch size of each tensordict to the largest leading shape that all its entries share. Defaults toNone, which turns it on whenbatch_dimsis given.batch_size (Size or list of int, optional) – the batch size of each stacked tensordict, without the stack dimension. Defaults to
None, which gives each tensordict the batch size[]unless its batch size is set automatically.device (device, str or int, optional) – the device of each stacked tensordict. Defaults to
None, which keeps each leaf where it is.batch_dims (int, optional) – the maximum number of batch dimensions of each tensordict when the batch size is set automatically. Defaults to
None.names (list of str, optional) – the names of the dimensions of the result, stack dimension first. See
from_dict(). Defaults toNone.lazy (bool, optional) – ignored: the result is always a lazy stack. Defaults to
None.
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)#
Returns the shape of an entry of the lazy stack, with
-1where the members differ.The shape of a tensor entry is read from the members without stacking them. Other entries are read with
get(), which stacks them.- Parameters:
key (NestedKey) – the key of the entry.
- Raises:
KeyError – if the stack has no entry at
key, or only some of its members have one.
Examples
>>> import torch >>> from tensordict import LazyStackedTensorDict, TensorDict >>> td = LazyStackedTensorDict( ... TensorDict(a=torch.zeros(3)), TensorDict(a=torch.zeros(4)) ... ) >>> td.get_item_shape("a") torch.Size([2, -1])
- get_nestedtensor(key: NestedKey, default: Any = NO_DEFAULT, *, layout: layout | None = None) Tensor | TensorCollection#
Returns an entry of the lazy stack as a nested tensor.
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 value for the tensordicts that lack
key. If it is a tensor, it is nested with the entries of the other tensordicts. Otherwise, it is returned as is. Without a default, a missing key raises aKeyError.
- Keyword Arguments:
layout (layout, optional) – the layout of the nested tensor. Defaults to
None, which builds atorch.stridedone.
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#
Inserts a tensordict into the lazy stack at
index, likelist.insert().The lazy stack is changed in place and its batch size grows by one along the stack dimension. The new tensordict is stored as is, not copied.
- Parameters:
index (int) – the position of the new tensordict along the stack dimension.
tensordict (TensorDictBase) – the tensordict to insert. It must have the device of the other members and as many batch dimensions. Its sizes must match theirs, except where the batch size of the lazy stack is
-1.
- Raises:
TypeError – if
tensordictis not a tensordict.ValueError – if the device of
tensordictdiffers from that of the members, or if its batch size does not fit the lazy stack.RuntimeError – if the lazy stack is locked.
Examples
>>> import torch >>> from tensordict import LazyStackedTensorDict, TensorDict >>> td = LazyStackedTensorDict(TensorDict(a=torch.zeros(3))) >>> td.insert(0, TensorDict(a=torch.ones(3))) >>> td.batch_size torch.Size([2]) >>> td[0]["a"] tensor([1., 1., 1.])
- 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 into a lazy stack.
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. These arguments,layout,padding_sideandpadding_valueapply only to a list of tensors. To read padded or nested entries from a lazy stack of tensordicts, pass them toget()instead.- Parameters:
items (Sequence of TensorDictBase) – the tensordicts to stack. It must not be empty, or a
RuntimeErroris raised.dim (int, optional) – the dimension along which to stack. Defaults to
0. Adimbelow-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 lazy stack to write the data into. Its batch size must be the stacked batch size. Defaults to
None.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 items must be equal, or aRuntimeErroris raised. Defaults toFalse.as_list (bool, optional) – tensors only. If
True, the tensors are returned as a list. Exclusive withas_padded_tensorandas_nested_tensor. Defaults toFalse.as_padded_tensor (bool, optional) – tensors only. 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) – tensors only. 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, optional) – the side to pad with
as_padded_tensor:"left"or"right". Defaults to"right".padding_value (float, int or bool, optional) – the padding value with
as_padded_tensor. Defaults to0.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 into a lazy stack 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. Defaults to
None.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,)
- non_tensor_items(include_nested: bool = False)#
Returns the non-tensor leaves as
(key, value)pairs, each stacked across the members.Only the keys that every member holds are listed. If
include_nestedisTrue, the nested tensordicts are searched as well.
- valid_keys(include_nested: bool = False, leaves_only: bool = False, is_leaf: Callable[[Type], bool] | None = None, *, sort: bool = False) _LazyStackedTensorDictKeysView#
Returns the keys of the lazy stack, like
keys().Deprecated since version 0.15: Use
keys()instead, which takes the same arguments. Will be removed in TensorDict 0.17.