Printing and display#
print(td) shows the structure of a TensorDict
without the values of its tensors: the dtype and shape of each tensor,
whatever its size. set_printoptions chooses the attributes
that the display shows, and parse_tensor_dict_string()
rebuilds a tensordict from a printed one. All the options are in
Available options.
What print shows#
By default, each entry prints as its dtype and its shape after the batch dims, and the batch size prints once, at the start. The display stays on one line if it fits in 80 columns, and otherwise puts one entry on each line:
>>> import torch
>>> from tensordict import TensorDict
>>> td = TensorDict(
... {
... "image": torch.randn(32, 3, 64, 64),
... "label": torch.randint(10, (32,)),
... },
... batch_size=[32],
... )
>>> print(td)
TensorDict(batch_size=[32], fields={image: f32[3,64,64], label: i64[]})
>>> sample = TensorDict(
... points=torch.zeros(1000, 3),
... cells=torch.zeros(1000, 4, dtype=torch.int64),
... data=TensorDict(pressure=torch.zeros(1000), mask=torch.zeros(1000, dtype=torch.bool)),
... batch_size=[1000],
... device="cpu",
... )
>>> print(sample)
TensorDict(batch_size=[1000], device=cpu, fields={
cells: i64[4],
data: {mask: bool[], pressure: f32[]},
points: f32[3]})
The dtype codes are those of JAX and polars: f32 for torch.float32,
i64 for torch.int64, u8, c64, bf16, bool. The rules:
A nested tensordict prints as
{...}, and with its class name when it is not aTensorDict(Mesh{...}for a tensorclass). A nested tensordict with more batch dims than its parent shows them first:sub: [5]{y: f32[3]}.In a lazy stack, a dim whose size differs between the members prints as
-1, the header showsstack_dim=, and the keys that only some members have follow underexclusive_fields=. A lazy stack nested in another entry shows only the keys that all its members have; the detailed display (compact=False) shows the others.A non-tensor entry prints as the type name of its value (
str). In aPersistentTensorDict, it prints asNonTensorDataorNonTensorStackinstead, since reading the type of the value would read the file.When the tensordict has no device (
device=None), a leaf that is not on the CPU shows its device:f32[3]@cuda:0.show_batch_size,show_device,show_dtypeandsort_keysapply;show_dtype=False(orverbose=False) prints the shapes only, as[3]. The other options (htmlaside) only apply to the detailed display: passing one of them withoutcompact, such asset_printoptions(show_grad=True), switches to the detailed display. With an explicitcompact=True, the compact display ignores them.The display reads no data and syncs no device: it uses only the shape, dtype and device of each leaf, and stacks no leaf of a lazy stack.
A
TensorDictStoreand aNonTensorStackkeep their usual display; nested in another tensordict, a store prints as its class name (TensorDictStore), since its entries would read the server.
The detailed display: compact=False#
With compact=False, the display shows the full shape, device, dtype, and
is_shared of each entry on its own line, and the batch size, device, and
is_shared of the tensordict. This was the default display in earlier releases:
>>> from tensordict import set_printoptions
>>> with set_printoptions(compact=False):
... print(td)
TensorDict(
fields={
image: Tensor(shape=torch.Size([32, 3, 64, 64]), device=cpu, dtype=torch.float32, is_shared=False),
label: Tensor(shape=torch.Size([32]), device=cpu, dtype=torch.int64, is_shared=False)},
batch_size=torch.Size([32]),
device=None,
is_shared=False)
The detailed display reads no tensor data either. It prints the tensor
leaves of an h5 or zarr file (PersistentTensorDict) from
their shape and dtype, and the tensor leaves of a lazy stack from its
members, without reading the file or stacking the leaves. The text is the
same as for the same data in memory. plain=True is the exception: it
prints statistics of the values, so it reads them. show_is_contiguous=True
also stacks a lazy leaf when one of its members is not contiguous (a
channels_last tensor, for example), since the contiguity of the result
depends on their strides.
Choose what the display shows#
set_printoptions selects the format and the attributes
that appear. Most options choose the attributes of the detailed display: if
all your work is on the CPU and nothing is shared, device=cpu and
is_shared=False repeat on every line of it and tell you nothing. It
works for the whole process, as a context manager, or as a decorator, as
torch.no_grad does for the last two. Its role is similar to
torch.set_printoptions(), which is only a function.
For the whole process#
Call set_printoptions(...).set() to change the defaults for the rest of
the process. show_device and show_is_shared control the lines of the
tensordict, and show_field_device and show_field_is_shared the
attributes of each field:
>>> set_printoptions(
... compact=False,
... show_device=False,
... show_is_shared=False,
... show_field_device=False,
... show_field_is_shared=False,
... ).set()
>>> print(td)
TensorDict(
fields={
image: Tensor(shape=torch.Size([32, 3, 64, 64]), dtype=torch.float32),
label: Tensor(shape=torch.Size([32]), dtype=torch.int64)},
batch_size=torch.Size([32]))
set() changes only the options that it gets, so
set_printoptions().set() without arguments does not reset anything. To go
back to the defaults, set the changed options again:
>>> set_printoptions(
... compact=True,
... show_device=True,
... show_is_shared=True,
... show_field_device=True,
... show_field_is_shared=True,
... ).set()
For one block of code#
Use the context manager to change the options for one block of code. At the end of the block, the previous options come back:
>>> with set_printoptions(compact=False, show_dtype=False, show_field_is_shared=False):
... print(td) # dtype and per-field is_shared hidden
TensorDict(
fields={
image: Tensor(shape=torch.Size([32, 3, 64, 64]), device=cpu),
label: Tensor(shape=torch.Size([32]), device=cpu)},
batch_size=torch.Size([32]),
device=None,
is_shared=False)
>>> print(td) # back to defaults
TensorDict(batch_size=[32], fields={image: f32[3,64,64], label: i64[]})
For one function#
Decorate a function to use the options for every repr call in it. Here,
show_is_shared=False hides the is_shared= line of the tensordict:
>>> @set_printoptions(compact=False, show_is_shared=False)
... def summarize(td):
... print(td)
>>> summarize(td)
TensorDict(
fields={
image: Tensor(shape=torch.Size([32, 3, 64, 64]), device=cpu, dtype=torch.float32, is_shared=False),
label: Tensor(shape=torch.Size([32]), device=cpu, dtype=torch.int64, is_shared=False)},
batch_size=torch.Size([32]),
device=None)
Shapes only: verbose=False#
To see only the shapes, pass verbose=False. This one argument hides the
dtype in the default display, and the device, the dtype, and is_shared in
the detailed one:
>>> with set_printoptions(verbose=False):
... print(td)
TensorDict(batch_size=[32], fields={image: [3,64,64], label: []})
>>> with set_printoptions(compact=False, verbose=False):
... print(td)
TensorDict(
fields={
image: Tensor(shape=torch.Size([32, 3, 64, 64])),
label: Tensor(shape=torch.Size([32]))},
batch_size=torch.Size([32]))
verbose=True (the default) changes nothing. Explicit keyword arguments
take precedence over verbose, so you can mix the two:
>>> with set_printoptions(compact=False, verbose=False, show_dtype=True):
... print(td)
TensorDict(
fields={
image: Tensor(shape=torch.Size([32, 3, 64, 64]), dtype=torch.float32),
label: Tensor(shape=torch.Size([32]), dtype=torch.int64)},
batch_size=torch.Size([32]))
Notebook display#
In a notebook (Jupyter, VS Code, Colab), a tensordict or a tensorclass that ends a cell displays as HTML: the entries of the compact display, one on each line, with each nested tensordict in a block that you can fold. The header shows the class name, the batch size, the dim names and the device, and a nested tensordict shows its class name and number of entries. The display uses the colors of the notebook theme, so it reads in light and dark themes.
It reads the same metadata as the compact display: no data, no device sync, and no stacking of a lazy stack.
show_batch_size,show_device,show_dtypeandsort_keysapply.It shows at most 200 entries; the rest of each block shows as
... and K more.A
TensorDictStore, aNonTensorStack, aNonTensorData, and any tensordict or tensorclass with its own text display (such asTensorDictParams, or a class that defines__repr__) keep their text display, as does any tensordict whose HTML display fails. Nested in another tensordict, aTensorDictStoreshows as its class name.set_printoptions(html=False)turns the HTML display off, and the notebook shows the text display instead.With
compact=False, passed or set by a detailed-only option such asset_printoptions(show_grad=True), the notebook shows the detailed text display instead of the HTML tree.
Available options#
These options choose the format:
Option |
Default |
Description |
|---|---|---|
|
|
Print each entry as its dtype and its shape
after the batch dims ( |
|
|
Display tensordicts as HTML in notebooks:
the tree, or the detailed text when
|
These options control the lines of the outer TensorDict(...) block of the
detailed display:
Option |
Default |
Description |
|---|---|---|
|
|
Show the |
|
|
Show the |
|
|
Show the |
These options control the attributes in the Tensor(...) description of
each field in the detailed display (show_dtype also applies to the compact
one):
Option |
Default |
Description |
|---|---|---|
|
|
Show the |
|
|
Show the |
|
|
Show the |
|
|
Show the |
This option is a shortcut for several of the options above:
Option |
Default |
Description |
|---|---|---|
|
|
When |
These options add attributes that are hidden by default, and change the order of the keys:
Option |
Default |
Description |
|---|---|---|
|
|
Show |
|
|
Show |
|
|
Show |
|
|
Show |
|
|
Append a short value summary (mean/std for floats, min/max for ints). It reads the values: the data of a file, and the stacked leaves of a lazy stack. |
|
|
Key ordering: |
Read the current options#
get_printoptions() returns a dict with the current values:
>>> from tensordict import get_printoptions
>>> get_printoptions()
{'show_batch_size': True, 'show_device': True, ...}
Rebuild a tensordict from its printed form#
When you debug, you sometimes have only the printed form of a tensordict, for
example from a log file or from the terminal of a colleague.
parse_tensor_dict_string() builds a
TensorDict from that string. The result has the keys,
shapes, dtypes, batch size, and device of the printed tensordict. All the
values are zeros, because the repr does not contain the data. It reads the
default display:
>>> from tensordict import parse_tensor_dict_string
>>> td = parse_tensor_dict_string(
... "TensorDict(batch_size=[32], fields={image: f32[3,64,64], label: i64[]})"
... )
>>> td["image"].shape, td["label"].dtype
(torch.Size([32, 3, 64, 64]), torch.int64)
and the detailed one, which older logs hold:
>>> s = """TensorDict(
... fields={
... image: Tensor(shape=torch.Size([32, 3, 64, 64]), device=cpu, dtype=torch.float32, is_shared=False),
... label: Tensor(shape=torch.Size([32]), device=cpu, dtype=torch.int64, is_shared=False)},
... batch_size=torch.Size([32]),
... device=cpu,
... is_shared=False)"""
>>> td = parse_tensor_dict_string(s)
>>> td.batch_size
torch.Size([32])
>>> td["image"].shape
torch.Size([32, 3, 64, 64])
parse_tensor_dict_string() is a debugging aid. It reads
both formats with the default options: in the detailed one, shape=,
device=, dtype=, and is_shared= for each field. It reads nested tensordicts at any depth, keys
with any character, such as my-key, and devices with an index, such as
cuda:0. It has these limits:
It reads only tensor fields and nested tensordicts. For a non-tensor field, a nested tensorclass or lazy stack, or an entry of a lazy stack whose shape differs between the members (
-1), it raisesValueError: Cannot parse the field ....If
set_printoptionshid a field attribute or added one (for exampleshow_dtype=False, orplain=Truein the detailed display), it raises the sameValueError.The compact display does not show the device of a nested tensordict, so the parser puts a nested tensordict, and the leaves without an
@devicesuffix, on the device of its parent, or on the CPU. It shows anUnbatchedTensorby its full shape, which the parser reads as the shape after the batch dims of a batched tensor.It makes each tensor on the printed device. To parse the repr of a CUDA tensordict, run it on a machine with CUDA.
It does not keep
is_shared, and it returns aTensorDictfor the repr of a lazy stack. For a lazy stack with exclusive keys, it raisesValueError: Cannot parse the exclusive_fields of a lazy stack ....
See also#
The reference entries of
set_printoptions,get_printoptions(), andparse_tensor_dict_string().Devices, dtypes, and memory: what
device=Nonein the repr means.Non-tensor data and unbatched entries: how non-tensor entries appear in the repr.