MicroDuckTask#
- class torchrl.envs.MicroDuckTask(command_low: Tensor, command_high: Tensor, warm_start_velocity: Tensor, warm_start_fraction: Tensor, joint_reset_noise_scale: Tensor, gait_frequency_hz: Tensor, gait_frequency_per_mps: Tensor, reward_weights: Tensor, params: TensorDict, weight: Tensor, name: str, *, batch_size, device=None, names=None)[source]#
One locomotion task of
MicroDuckEnv, as data.A task is a row of tensors and a name: the command box, the reset distribution, the gait clock, the reward weights and parameters, and a label. A library is a stack of tasks, and every env of a
MicroDuckEnvbatch holds one row of the library for the duration of an episode. Gathering rows withlibrary[task_id]copies the name entries like the tensors, which needstensordict>=0.14.1. Build tasks with the presets (MicroDuckEnv.tracking_task(),MicroDuckEnv.standing_task(),MicroDuckEnv.speed_range_task(),MicroDuckEnv.sidestep_task(),MicroDuckEnv.turning_task(),MicroDuckEnv.jump_task()), which fill every field and accept overrides, and stack them withtorch.stack()or by handing a sequence to the env. Stacking is the structural validation: every task must carry the full reward weight vector and every parameter key.- Parameters:
command_low (torch.Tensor) – lower corner of the planar command box
(vx, vy)in m/s, shape(2,). A fixed command is a box withcommand_low == command_high.command_high (torch.Tensor) – upper corner of the command box, shape
(2,). The command is drawn uniformly in the box at reset and held for the episode.warm_start_velocity (torch.Tensor) –
(low, high)speed interval in m/s, shape(2,). At reset, awarm_start_fractionof the envs whose command is nonzero start already moving along the commanded direction at a speed drawn from it.warm_start_fraction (torch.Tensor) – fraction of resets that receive the warm start, scalar in
[0, 1].joint_reset_noise_scale (torch.Tensor) – uniform noise added to the joint positions at reset, in radians, scalar.
gait_frequency_hz (torch.Tensor) – frequency of the gait clock exposed in the observation at zero command, scalar.
gait_frequency_per_mps (torch.Tensor) – increase of the clock frequency per m/s of commanded speed, scalar.
reward_weights (torch.Tensor) – one weight per registered reward term, in the order of
MicroDuckEnv.REWARD_TERMS, shape(num_terms,). A zero weight turns the term off; an all-zero row is “no built-in reward”, for a transform to fill in.params (TensorDict) – scalar parameters read by the reward terms, one entry per key of
MicroDuckEnv.REWARD_PARAMS(for exampletracking_stdorpose_std).weight (torch.Tensor) – relative weight of the task when the env draws a task per env at reset, scalar and non-negative.
name (str) – label of the task, for logging and evaluation; the presets derive it from their arguments (
"tracking+0.20","sidestep-0.15","jump") and acceptname=to override.
Examples
Two tasks stacked into a library, one row per env picked at reset:
>>> import torch >>> from torchrl.envs import MicroDuckEnv >>> library = torch.stack( ... [MicroDuckEnv.tracking_task(0.2, weight=2.0), MicroDuckEnv.jump_task()] ... ) >>> library.shape, library.command_high[:, 0], library.weight (torch.Size([2]), tensor([0.2000, 0.0000]), tensor([2., 1.])) >>> list(library.name) ['tracking+0.20', 'jump'] >>> env = MicroDuckEnv(download=True, tasks=library, num_envs=4) >>> rollout = env.rollout(20) >>> rollout["task_id"][:, 0, 0], rollout["command"][:, 0] (tensor([0, 1, 0, 0]), tensor([[0.2, 0.0], [0.0, 0.0], [0.2, 0.0], [0.2, 0.0]]))
Overrides retune one row: reward weights by term name, term parameters and reset fields by name.
>>> task = MicroDuckEnv.tracking_task( ... 0.2, reward_weights={"tracking": 4.0}, tracking_std=0.2, warm_start_fraction=0.5, ... warm_start_velocity=(0.1, 0.3), ... ) >>> task.reward_weights[list(MicroDuckEnv.REWARD_TERMS).index("tracking")] tensor(4.) >>> task.params["tracking_std"], task.warm_start_fraction (tensor(0.2000), tensor(0.5000))
See also
MicroDuckEnvconsumes an ordered library of these rows;MicroDuckTaskSamplerchooses a row at reset; andMicroDuckSkillspreserves the library alongside a trained skill policy.- property device: torch.device#
Retrieves the device type of tensor class.
- dumps(prefix: str | None = None, copy_existing: bool = False, *, num_threads: int = 0, return_early: bool = False, share_non_tensor: bool = False, robust_key: bool | None = True, archive: bool | None = None, compression: str | int | None = None) Self#
Saves the tensordict to disk, and returns a memory-mapped copy of it.
save(and its aliasdumps) ismemmap(): it takes the same arguments.selfis not changed. Read the result back withload(). See Saving TensorDict and tensorclass objects.- Parameters:
prefix (str or Path) – the directory where the tensordict is written, one file per leaf. If
prefixends with".tdz"orarchive=True, a single archive file is written instead.- Keyword Arguments:
archive (bool, optional) – if
True, write a single archive file. Defaults toNone, which writes an archive ifprefixends with".tdz".compression (str or int, optional) – the compression of the archive. See
memmap().
All the other arguments are those of
memmap().Examples
>>> import tempfile >>> import torch >>> from tensordict import TensorDict >>> td = TensorDict(a=torch.zeros(3), nested=TensorDict(b=torch.ones(3), batch_size=[3]), batch_size=[3]) >>> with tempfile.TemporaryDirectory() as path: ... _ = td.save(path) ... loaded = TensorDict.load(path) ... print((loaded == td).all()) True
- extend(tensordict: list[TensorDictBase] | TensorDictBase) None#
Appends tensordicts to the lazy stack that the instance holds.
Deprecated since version 0.15: Build a new instance with
tensordict.lazy_stack()ortorch.cat()instead.
- classmethod fields() tuple[dataclasses.Field, ...]#
Returns the fields of the tensorclass.
Deprecated since version 0.15: Use
dataclasses.fields(cls)instead. It returns the same tuple ofdataclasses.Fieldobjects.
- from_csv(*, auto_batch_size: bool = False, batch_dims: int | None = None, device: torch.device | None = None, batch_size: torch.Size | None = None, separator: str | None = None, dtype: torch.dtype | None = None, **kwargs) Self#
Creates a TensorDict from a CSV file.
Requires either pandas or pyarrow to be installed.
- Parameters:
path (str or Path) – Path to the CSV file.
- Keyword Arguments:
auto_batch_size (bool, optional) – If
True, the batch size will be computed automatically. Defaults toFalse.batch_dims (int, optional) – If
auto_batch_sizeisTrue, defines how many dimensions the output tensordict should have. Defaults toNone.device (torch.device, optional) – The device for tensor data. Defaults to
None.batch_size (torch.Size, optional) – The batch size. Defaults to
[num_rows].separator (str, optional) – If provided, column names are split on this separator to create nested TensorDicts. Defaults to
None.dtype (torch.dtype, optional) – If provided, all numeric columns are cast to this dtype. Defaults to
None.**kwargs – Additional keyword arguments forwarded to the CSV reader (
pandas.read_csvorpyarrow.csv.read_csv).
- Returns:
A TensorDict representation of the CSV data.
Examples
>>> import os >>> import tempfile >>> import torch >>> from tensordict import TensorDict >>> data = TensorDict(obs=torch.arange(3.0), reward=torch.ones(3), batch_size=[3]) >>> with tempfile.TemporaryDirectory() as tmpdir: ... path = os.path.join(tmpdir, "data.csv") ... data.to_csv(path) ... td = TensorDict.from_csv(path) ... td32 = TensorDict.from_csv(path, dtype=torch.float32) >>> td.batch_size, td["obs"].dtype, td32["obs"].dtype (torch.Size([3]), torch.float64, torch.float32)
- from_json(*, auto_batch_size: bool = False, batch_dims: int | None = None, device: torch.device | None = None, batch_size: torch.Size | None = None, separator: str | None = None, dtype: torch.dtype | None = None, lines: bool = False, **kwargs) Self#
Creates a TensorDict from a JSON file.
Supports both standard JSON (array of records) and JSON Lines format. For nested JSON objects, use
from_dict()instead.Requires pandas for best results. Falls back to stdlib
jsonfor simple cases.- Parameters:
path (str or Path) – Path to the JSON file.
- Keyword Arguments:
auto_batch_size (bool, optional) – If
True, the batch size will be computed automatically. Defaults toFalse.batch_dims (int, optional) – If
auto_batch_sizeisTrue, defines how many dimensions the output tensordict should have. Defaults toNone.device (torch.device, optional) – The device for tensor data. Defaults to
None.batch_size (torch.Size, optional) – The batch size. Defaults to
[num_rows].separator (str, optional) – If provided, column names are split on this separator to create nested TensorDicts. Defaults to
None.dtype (torch.dtype, optional) – If provided, all numeric columns are cast to this dtype. Defaults to
None.lines (bool, optional) – If
True, reads the file as JSON Lines (one JSON object per line). Defaults toFalse.**kwargs – Additional keyword arguments forwarded to the JSON reader.
- Returns:
A TensorDict representation of the JSON data.
Examples
>>> import os >>> import tempfile >>> import torch >>> from tensordict import TensorDict >>> data = TensorDict(obs=torch.arange(3.0), reward=torch.ones(3), batch_size=[3]) >>> with tempfile.TemporaryDirectory() as tmpdir: ... path = os.path.join(tmpdir, "data.json") ... data.to_json(path) ... td = TensorDict.from_json(path) ... path_lines = os.path.join(tmpdir, "data.jsonl") ... data.to_json(path_lines, lines=True) ... td_lines = TensorDict.from_json(path_lines, lines=True) >>> td.batch_size, td_lines.batch_size (torch.Size([3]), torch.Size([3]))
- from_module(as_module: bool = False, lock: bool = False, use_state_dict: bool = False, filter_empty: bool = True)#
Puts the parameters and buffers of a module in a tensordict.
The entries are the parameters and buffers of the module themselves, not copies. Submodules become nested tensordicts.
Note
This method does not lock the result by default (
lock=False). The functiontensordict.from_module()locks it by default (lock=True).- Parameters:
module (nn.Module) – the module to get the parameters from.
as_module (bool, optional) – if
True, aTensorDictParamsinstance is returned, which can be used to store parameters within atorch.nn.Module. Defaults toFalse.lock (bool, optional) – if
True, the resulting tensordict is locked. Defaults toFalse.use_state_dict (bool, optional) – if
True, the state-dict from the module is used and unflattened into a TensorDict with the tree structure of the model. Use it when the module has state-dict hooks. Defaults toFalse.filter_empty (bool, optional) – if
True, submodules without parameters or buffers (nn.ReLU, for example) get no entry. IfFalse, they get an empty tensordict. Defaults toTrue.
- Returns:
a
TensorDict, or aTensorDictParamsifas_module=True.
Examples
>>> from torch import nn >>> from tensordict import TensorDict >>> module = nn.Sequential(nn.Linear(3, 4), nn.ReLU()) >>> params = TensorDict.from_module(module) >>> params["0", "weight"] is module[0].weight True >>> list(params.keys()) ['0'] >>> params.is_locked False
- from_pandas(*, auto_batch_size: bool = False, batch_dims: int | None = None, device: torch.device | None = None, batch_size: torch.Size | None = None, separator: str | None = None, dtype: torch.dtype | None = None) Self#
Converts a pandas DataFrame to a TensorDict.
Numeric columns become tensors, string/object columns become
NonTensorData.- Parameters:
dataframe (pd.DataFrame) – The pandas DataFrame to convert.
- Keyword Arguments:
auto_batch_size (bool, optional) – If
True, the batch size will be computed automatically. Defaults toFalse.batch_dims (int, optional) – If
auto_batch_sizeisTrue, defines how many dimensions the output tensordict should have. Defaults toNone.device (torch.device, optional) – The device for tensor data. Defaults to
None.batch_size (torch.Size, optional) – The batch size. Defaults to
[num_rows].separator (str, optional) – If provided, column names are split on this separator to create nested TensorDicts. For example, with
separator=".", a column"obs.x"becomestd["obs", "x"]. Defaults toNone.dtype (torch.dtype, optional) – If provided, all numeric columns are cast to this dtype. Defaults to
None.
- Returns:
A TensorDict representation of the DataFrame.
Examples
>>> from tensordict import TensorDict >>> import pandas as pd >>> df = pd.DataFrame({"a": [1, 2, 3], "b": [4.0, 5.0, 6.0]}) >>> td = TensorDict.from_pandas(df) >>> print(td) TensorDict( fields={ a: Tensor(shape=torch.Size([3]), device=cpu, dtype=torch.int64, is_shared=False), b: Tensor(shape=torch.Size([3]), device=cpu, dtype=torch.float64, is_shared=False)}, batch_size=torch.Size([3]), device=None, is_shared=False)
- from_parquet(*, auto_batch_size: bool = False, batch_dims: int | None = None, device: torch.device | None = None, batch_size: torch.Size | None = None, separator: str | None = None, dtype: torch.dtype | None = None, columns: list[str] | None = None, **kwargs) Self#
Creates a TensorDict from a Parquet file.
Requires either pyarrow or pandas to be installed. Prefers pyarrow when available for better performance.
- Parameters:
path (str or Path) – Path to the Parquet file.
- Keyword Arguments:
auto_batch_size (bool, optional) – If
True, the batch size will be computed automatically. Defaults toFalse.batch_dims (int, optional) – If
auto_batch_sizeisTrue, defines how many dimensions the output tensordict should have. Defaults toNone.device (torch.device, optional) – The device for tensor data. Defaults to
None.batch_size (torch.Size, optional) – The batch size. Defaults to
[num_rows].separator (str, optional) – If provided, column names are split on this separator to create nested TensorDicts. Defaults to
None.dtype (torch.dtype, optional) – If provided, all numeric columns are cast to this dtype. Defaults to
None.columns (list of str, optional) – If provided, only read these columns from the file. Defaults to
None(all columns).**kwargs – Additional keyword arguments forwarded to the Parquet reader.
- Returns:
A TensorDict representation of the Parquet data.
Examples
>>> import os >>> import tempfile >>> import torch >>> from tensordict import TensorDict >>> data = TensorDict(obs=torch.arange(3.0), reward=torch.ones(3), batch_size=[3]) >>> with tempfile.TemporaryDirectory() as tmpdir: ... path = os.path.join(tmpdir, "data.parquet") ... data.to_parquet(path) ... td = TensorDict.from_parquet(path) ... td_obs = TensorDict.from_parquet(path, columns=["obs"]) >>> sorted(td.keys()), sorted(td_obs.keys()) (['obs', 'reward'], ['obs'])
- from_schema(*, batch_size: Sequence[int] | torch.Size | None = None, storage: str | None = None, device=None, **kwargs) TensorDictBase#
Pre-allocate a zero-filled TensorDict from a schema.
Creates a
TensorDictBasewhose storage backend is selected bystorage. Each entry inschemamaps a field name to an(element_shape, dtype)pair; the full stored shape is[*batch_size, *element_shape].- Parameters:
schema – Mapping from field name to
(element_shape, dtype).element_shapeis the per-element shape (excludingbatch_size).- Keyword Arguments:
batch_size – Overall batch dimensions prepended to every element shape. Defaults to
().storage (str or None) –
Backend selector:
None– plainTensorDictwith regular tensors."memmap"– memory-mapped tensors on disk. Passprefix=<dir>in kwargs."h5"– HDF5 viaPersistentTensorDict. Passfilename=<path>in kwargs."zarr"– zarr (requireszarr>=3.0) viaPersistentTensorDict. Passfilename=<path or store>in kwargs."shared"– CPU shared-memory tensors."redis"/"dragonfly"– delegates toTensorDictStore.from_schema().
device – Device for the resulting tensors (ignored by some backends).
**kwargs – Backend-specific arguments forwarded to the underlying constructor (e.g.
prefixfor memmap,filenamefor h5,host/portfor redis).
- Returns:
A new
TensorDictBasesubclass instance with pre-allocated (zero-filled) keys.
Examples
>>> import torch >>> from tensordict import TensorDict >>> td = TensorDict.from_schema( ... {"obs": ([84, 84, 3], torch.uint8), ... "reward": ([], torch.float32)}, ... batch_size=[1000], ... ) >>> td["obs"].shape torch.Size([1000, 84, 84, 3])
>>> import tempfile >>> with tempfile.TemporaryDirectory() as d: ... td_mm = TensorDict.from_schema( ... {"obs": ([4], torch.float32)}, ... batch_size=[8], ... storage="memmap", ... prefix=d, ... ) ... assert td_mm.is_memmap()
- classmethod from_tensordict(tensordict: TensorDictBase, non_tensordict: dict | None = None, safe: bool | None = None) Self#
Wraps a tensordict in a new instance of the tensorclass, without copying the leaves.
If
tensordictis aTensorDict, the entries of the fields annotated with a tensorclass (orOptionalof one) that are tensordicts become instances of that tensorclass, recursively. They are set in a shallow copy oftensordict, which keeps its own entries. An entry with keys that the annotated class does not declare stays a tensordict. Other backends are wrapped as they are: setting a tensorclass in them would write to their storage (e.g. an H5 file).- Parameters:
tensordict (TensorDictBase) – the tensordict that holds the tensor fields.
non_tensordict (dict, optional) – the values of the non-tensor fields. The fields that neither argument holds are set to
None.safe (bool, optional) – Deprecated in 0.15, to be removed in TensorDict 0.17. Whether to raise an error if
tensordictis not aTensorDictBase. Without it, such a tensordict raises an error.
Examples
>>> import torch >>> from tensordict import TensorClass >>> class Pose(TensorClass): ... q: torch.Tensor >>> class Obs(TensorClass): ... a: Pose >>> obs = Obs(a=Pose(q=torch.zeros(5, 4), batch_size=[5]), batch_size=[5]) >>> type(Obs.from_tensordict(obs.to_tensordict()).a).__name__ 'Pose'
- get(key: NestedKey, *args, **kwargs)#
Gets the value stored with the input key.
- Parameters:
key (str, tuple of str) – key to be queried. If tuple of str it is equivalent to chained calls of getattr.
default – default value if the key is not found in the tensorclass.
- Returns:
value stored with the input key
- classmethod load(prefix: str | Path, *args, **kwargs) Self#
Loads a tensordict that
save()ormemmap()wrote to disk.loadisload_memmap(): it takes the same arguments, includingallow_pickle,deviceandmode. The leaves of the result are memory-mapped tensors that read the files. See Saving TensorDict and tensorclass objects and the example ofsave().- Parameters:
prefix (str or Path) – the directory, or the
".tdz"archive file, to read.
- load_(prefix: str | Path, *args, **kwargs)#
Loads a tensordict from disk within the current tensordict.
This method is a proxy to
load_memmap_().Deprecated since version 0.15: Use
load_memmap_()instead.
- classmethod load_memmap(prefix: str | Path, device: torch.device | None = None, non_blocking: bool = False, *, out: TensorDictBase | None = None, robust_key: bool | None = True, subpath: NestedKey | None = None, mode: str | None = None, num_threads: int = 0, allow_pickle: bool | None = None) Self#
Loads a memory-mapped tensordict from disk.
- Parameters:
prefix (str or Path to folder) – the path to the folder where the saved tensordict should be fetched, or the path to a memmap archive file written through
save(..., archive=True)/ a".tdz"prefix (or packed withpack_memmap()). Archives are memory-mapped once and every leaf is exposed as a zero-copy view into the mapping: only the pages of the leaves that are actually accessed are read from disk. Unlike directory-backed tensordicts, in-place writes to the leaves of an archive-loaded tensordict do not propagate to the file by default (seemode).device (torch.device or equivalent, optional) – if provided, the data will be asynchronously cast to that device. Supports “meta” device, in which case the data isn’t loaded but a set of empty “meta” tensors are created. This is useful to get a sense of the total model size and structure without actually opening any file.
non_blocking (bool, optional) – if
True, synchronize won’t be called after loading tensors on device. Defaults toFalse.out (TensorDictBase, optional) – optional tensordict where the data should be loaded. Its nested containers are reused, but its leaves are rebound to the loaded tensors, so their storage is not reused. Keys of
outthat are missing from the saved data are removed. Ifouthas a device, the data is loaded on it, and a differentdeviceraises aValueError. To write the data into the preallocated storage ofout, useout.update_(TensorDict.load_memmap(prefix, device=device))instead.robust_key (bool, optional) – if
True(default), expects robust key encoding was used when saving and decodes filenames accordingly. IfFalse, uses legacy behavior. IfNone, uses the default robust behavior.subpath (NestedKey or str path, optional) – the location of a nested tensordict to load, as a nested key (e.g.
("module", "0"), with arbitrary nesting allowed as usual) or as a"/"-separated string path (e.g."module/0"). Only that subtree is loaded. Works both for directories (equivalent to appending the path toprefix) and for archives.mode (str, optional) – how the files are memory-mapped. With
"r", the mapping is copy-on-write: in-place writes to the leaves stay in memory. They reach the files only if the tensordict is saved there, andmemmap_()without a prefix does not write back toprefix. With"r+", the mapping is shared: in-place writes propagate to the files, and a file that is not writable raises aPermissionError. Defaults toNone, which maps archives as with"r", and each file of a directory as with"r+"if the process can write it, as with"r"otherwise. Prefer"r"for data that is only read: on some network file systems (e.g. Lustre), page faults on a shared writable mapping take write locks, so readers on different nodes block each other. On Linux, copy-on-write mappings count against the memory commit limit, so a file larger than the available RAM and swap can fail to map with"r". With archives,"r+"requires uncompressed, aligned tensor payloads (i.e. archives written by tensordict withoutcompression) and is not available for nested-tensor leaves. In-place writes do not update the per-entry CRC-32 stored by the zip format;load_memmap()ignores checksums, but callrefresh_archive_checksums()before handing a modified archive to tools that verify them (unzip,unpack_memmap(), …).num_threads (int, optional) – number of threads used to decompress the leaves of a compressed archive (deflate entries are inflated in parallel, which scales nearly linearly). Without compression, loading is a metadata-only operation and this argument has no effect. Defaults to
0(sequential).allow_pickle (bool, optional) – whether pickled non-tensor fields may be loaded. Pickle can execute arbitrary code, so pass
Trueonly for data from a trusted source andFalsefor untrusted data. In TensorDict 0.14 and 0.15, omitting this option loads pickle with aFutureWarning; the default will change toFalsein 0.16. Saves without a pickle sidecar do not require this option.
Examples
>>> import torch >>> from tensordict import TensorDict >>> td = TensorDict.fromkeys(["a", "b", "c", ("nested", "e")], 0) >>> _ = td.memmap("./saved_td") >>> td_load = TensorDict.load_memmap("./saved_td") >>> assert (td == td_load).all()
This method also allows loading nested tensordicts.
Examples
>>> nested = TensorDict.load_memmap("./saved_td/nested") >>> assert nested["e"] == 0
A tensordict can also be loaded on “meta” device or, alternatively, as a fake tensor.
Examples
>>> import tempfile >>> td = TensorDict({"a": torch.zeros(()), "b": {"c": torch.zeros(())}}) >>> with tempfile.TemporaryDirectory() as path: ... _ = td.save(path) ... td_load = TensorDict.load_memmap(path, device="meta") ... print("meta:", td_load) ... from torch._subclasses import FakeTensorMode ... with FakeTensorMode(): ... td_load = TensorDict.load_memmap(path) ... print("fake:", td_load) meta: TensorDict( fields={ a: Tensor(shape=torch.Size([]), device=meta, dtype=torch.float32, is_shared=False), b: TensorDict( fields={ c: Tensor(shape=torch.Size([]), device=meta, dtype=torch.float32, is_shared=False)}, batch_size=torch.Size([]), device=meta, is_shared=False)}, batch_size=torch.Size([]), device=meta, is_shared=False) fake: TensorDict( fields={ a: FakeTensor(shape=torch.Size([]), device=cpu, dtype=torch.float32, is_shared=False), b: TensorDict( fields={ c: FakeTensor(shape=torch.Size([]), device=cpu, dtype=torch.float32, is_shared=False)}, batch_size=torch.Size([]), device=cpu, is_shared=False)}, batch_size=torch.Size([]), device=cpu, is_shared=False)
- load_memmap_(prefix: str | Path, robust_key: bool | None = True, *, allow_pickle: bool | None = None, mode: str | None = None)#
Loads the content of a memory-mapped tensorclass within the tensorclass where
load_memmap_is called.See
load_memmap_()for more info.
- load_state_dict(state_dict: dict[str, Any], strict=True, assign=False, from_flatten=None)#
Loads a state_dict into the tensorclass.
Supports both the new format (logical keys with
_metadata) and the legacy format (_tensordict/_non_tensordictwrapper keys).
- memmap(prefix: str | None = None, copy_existing: bool = False, *, num_threads: int = 0, return_early: bool = False, share_non_tensor: bool = False, existsok: bool = True, robust_key: bool | None = True, archive: bool | None = None, compression: str | int | None = None) Self#
Writes all tensors onto a corresponding memory-mapped Tensor in a new tensordict.
- Parameters:
prefix (str) – directory prefix where the memory-mapped tensors will be stored. The directory tree structure will mimic the tensordict’s. If
prefixends with".tdz"(orarchive=Trueis passed), a single-file archive is written instead of a directory: a standard zip file whose entries replicate the memmap directory layout. Seearchivebelow.copy_existing (bool) – If False (default), an exception will be raised if an entry in the tensordict is already a tensor stored on disk with an associated file, but is not saved in the correct location according to prefix. If
True, any existing Tensor will be copied to the new location.
- Keyword Arguments:
num_threads (int, optional) – the number of threads used to write the memmap tensors. Defaults to 0.
return_early (bool, optional) – if
Trueandnum_threads>0, the method will return a future of the tensordict.share_non_tensor (bool, optional) – if
True, the non-tensor data will be shared between the processes and writing operation (such as inplace update or set) on any of the workers within a single node will update the value on all other workers. If the number of non_tensor leaves is high (e.g., sharing large stacks of non-tensor data) this may result in OOM or similar errors. Defaults toFalse.existsok (bool, optional) – if
False, an exception will be raised if a tensor already exists in the same path. Defaults toTrue.robust_key (bool, optional) – if
True(default), uses robust key encoding that safely handles keys with path separators and special characters. IfFalse, uses legacy behavior (keys used as-is). IfNone, uses the default robust behavior.archive (bool, optional) – if
True,prefixdesignates a single file rather than a directory and the tensordict is written as a memmap archive: a zip file mirroring the memmap directory tree, with tensor payloads stored uncompressed and aligned so thatload_memmap()can memory-map the file and expose every leaf as a zero-copy view. IfNone(default), archive mode is enabled whenprefixends with".tdz". The result ofload_memmap()on an archive behaves like the result offrom_consolidated(): all leaves are views into a single storage, and in-place writes do not propagate to the file. Archives and memmap directories are mutually convertible withpack_memmap()/unpack_memmap()(or any zip tool). Note that archives are written sequentially (single data pass) andnum_threadshas no effect on them. An existing archive is replaced by a new file rather than rewritten in place: a symlink is followed, but other hard links to the old file keep the old contents.compression (str or int, optional) – compression for archive entries (
"stored","deflate","bzip2","lzma"or azipfileconstant). Defaults to"stored"(uncompressed), which is what enables zero-copy loading. Compressed archives load correctly but leaves are decompressed in memory on access. Only valid in archive mode.
The TensorDict is then locked, meaning that any writing operations that isn’t in-place will throw an exception (eg, rename, set or remove an entry). Once the tensordict is unlocked, the memory-mapped attribute is turned to
False, because cross-process identity is not guaranteed anymore.- Returns:
A new tensordict with the tensors stored on disk if
return_early=False, otherwise aTensorDictFutureinstance.
Note
Serialising in this fashion might be slow with deeply nested tensordicts, so it is not recommended to call this method inside a training loop.
- memmap_(prefix: str | None = None, copy_existing: bool = False, *, num_threads: int = 0, return_early: bool = False, share_non_tensor: bool = False, existsok: bool = True, robust_key: bool | None = True) Self#
Writes all tensors onto a corresponding memory-mapped Tensor, in-place.
- Parameters:
prefix (str) – directory prefix where the memory-mapped tensors will be stored. The directory tree structure will mimic the tensordict’s.
copy_existing (bool) – If False (default), an exception will be raised if an entry in the tensordict is already a tensor stored on disk with an associated file, but is not saved in the correct location according to prefix. If
True, any existing Tensor will be copied to the new location.
- Keyword Arguments:
num_threads (int, optional) – the number of threads used to write the memmap tensors. Defaults to 0.
return_early (bool, optional) – if
Trueandnum_threads>0, the method will return a future of the tensordict. The resulting tensordict can be queried using future.result().share_non_tensor (bool, optional) – if
True, the non-tensor data will be shared between the processes and writing operation (such as inplace update or set) on any of the workers within a single node will update the value on all other workers. If the number of non-tensor leaves is high (e.g., sharing large stacks of non-tensor data) this may result in OOM or similar errors. Defaults toFalse.existsok (bool, optional) – if
False, an exception will be raised if a tensor already exists in the same path. Defaults toTrue.robust_key (bool, optional) – if
True(default), uses robust key encoding that safely handles keys with path separators and special characters. IfFalse, uses legacy behavior (keys used as-is). IfNone, uses the default robust behavior.
The TensorDict is then locked, meaning that any writing operations that isn’t in-place will throw an exception (eg, rename, set or remove an entry). Once the tensordict is unlocked, the memory-mapped attribute is turned to
False, because cross-process identity is not guaranteed anymore.- Returns:
self if
return_early=False, otherwise aTensorDictFutureinstance.
Note
Serialising in this fashion might be slow with deeply nested tensordicts, so it is not recommended to call this method inside a training loop.
- memmap_like(prefix: str | None = None, copy_existing: bool = False, *, existsok: bool = True, num_threads: int = 0, return_early: bool = False, share_non_tensor: bool = False, robust_key: bool | None = True, archive: bool | None = None) Self#
Creates a memory-mapped tensordict with the same keys, shapes and dtypes, without copying the values.
The files are filled with zeros. Write the values into the result afterwards, for example with
update_()or indexing.- Parameters:
prefix (str) – directory prefix where the memory-mapped tensors will be stored. The directory tree structure will mimic the tensordict’s. If
prefixends with".tdz"(orarchive=Trueis passed), a preallocated single-file archive is created instead. Seearchivebelow.copy_existing (bool) – If False (default), an exception will be raised if an entry in the tensordict is already a tensor stored on disk with an associated file, but is not saved in the correct location according to prefix. If
True, any existing Tensor will be copied to the new location.
- Keyword Arguments:
num_threads (int, optional) – the number of threads used to write the memmap tensors. Defaults to 0.
return_early (bool, optional) – if
Trueandnum_threads>0, the method will return a future of the tensordict.share_non_tensor (bool, optional) – if
True, the non-tensor data will be shared between the processes and writing operation (such as inplace update or set) on any of the workers within a single node will update the value on all other workers. If the number of non-tensor leaves is high (e.g., sharing large stacks of non-tensor data) this may result in OOM or similar errors. Defaults toFalse.existsok (bool, optional) – if
False, an exception will be raised if a tensor already exists in the same path. Defaults toTrue.robust_key (bool, optional) – if
True(default), uses robust key encoding that safely handles keys with path separators and special characters. IfFalse, uses legacy behavior (keys used as-is). IfNone, uses the default robust behavior.archive (bool, optional) – if
True,prefixdesignates a single file and a preallocated, zero-filled memmap archive is created and loaded back withload_memmap(prefix, mode="r+"): the returned tensordict writes through to the archive. IfNone(default), archive mode is enabled whenprefixends with".tdz". In-place writes leave the zip per-entry checksums stale; callrefresh_archive_checksums()before handing the archive to tools that verify them. Nested tensors are not supported in this mode.
The TensorDict is then locked, meaning that any writing operations that isn’t in-place will throw an exception (eg, rename, set or remove an entry). Once the tensordict is unlocked, the memory-mapped attribute is turned to
False, because cross-process identity is not guaranteed anymore.- Returns:
A new
TensorDictinstance with data stored as memory-mapped tensors ifreturn_early=False, otherwise aTensorDictFutureinstance.
Note
This is the recommended method to write a set of large buffers on disk, as
memmap_()will copy the information, which can be slow for large content.Examples
>>> import torch >>> from tensordict import TensorDict >>> td = TensorDict({ ... "a": torch.zeros((3, 64, 64), dtype=torch.uint8), ... "b": torch.zeros(1, dtype=torch.int64), ... }, batch_size=[]).expand(1_000) # expand does not allocate new memory >>> import tempfile >>> with tempfile.TemporaryDirectory() as path: ... buffer = td.memmap_like(path) ... print(buffer.is_memmap(), buffer["a"].shape) True torch.Size([1000, 3, 64, 64])
- memmap_refresh_(*, allow_pickle: bool | None = None)#
Refreshes the content of the memory-mapped tensordict if it has a
saved_path.This method will raise an exception if no path is associated with it.
- Parameters:
allow_pickle (bool, optional) – whether pickled non-tensor fields may be loaded. See
load_memmap().
- save(prefix: str | None = None, copy_existing: bool = False, *, num_threads: int = 0, return_early: bool = False, share_non_tensor: bool = False, robust_key: bool | None = True, archive: bool | None = None, compression: str | int | None = None) Self#
Saves the tensordict to disk, and returns a memory-mapped copy of it.
save(and its aliasdumps) ismemmap(): it takes the same arguments.selfis not changed. Read the result back withload(). See Saving TensorDict and tensorclass objects.- Parameters:
prefix (str or Path) – the directory where the tensordict is written, one file per leaf. If
prefixends with".tdz"orarchive=True, a single archive file is written instead.- Keyword Arguments:
archive (bool, optional) – if
True, write a single archive file. Defaults toNone, which writes an archive ifprefixends with".tdz".compression (str or int, optional) – the compression of the archive. See
memmap().
All the other arguments are those of
memmap().Examples
>>> import tempfile >>> import torch >>> from tensordict import TensorDict >>> td = TensorDict(a=torch.zeros(3), nested=TensorDict(b=torch.ones(3), batch_size=[3]), batch_size=[3]) >>> with tempfile.TemporaryDirectory() as path: ... _ = td.save(path) ... loaded = TensorDict.load(path) ... print((loaded == td).all()) True
- select(*keys, inplace: bool = False, strict: bool = True, as_tensordict: bool = False)#
TensorClass-specific select that supports
as_tensordict.
- set(key: NestedKey, value: Any, inplace: bool = False, non_blocking: bool = False)#
Sets a new key-value pair.
- Parameters:
key (str, tuple of str) – name of the key to be set. If tuple of str it is equivalent to chained calls of getattr followed by a final setattr.
value (Any) – value to be stored in the tensorclass
inplace (bool, optional) – if
True, set will tentatively try to update the value in-place. IfFalseor if the key isn’t present, the value will be simply written at its destination.
- Returns:
self
- state_dict(destination=None, prefix='', keep_vars=False, flatten=True) dict[str, Any]#
Returns a state_dict with logical keys, matching TensorDictBase conventions.
Tensor fields appear as data keys. Non-tensor fields (strings, ints, etc.) and the tensorclass type are stored in
_metadata. This replaces the legacy_tensordict/_non_tensordictwrapper format.
- to_tensordict(*, retain_none: bool | None = None) TensorDict#
Convert the tensorclass into a regular TensorDict.
Makes a copy of all entries. Memmap and shared memory tensors are converted to regular tensors.
- Keyword Arguments:
retain_none (bool, optional) – if
True, fields set toNoneare written asNoneentries. Defaults toNone, which drops them.- Returns:
A new TensorDict object containing the same values as the tensorclass.
Examples
>>> from typing import Any >>> import torch >>> from tensordict import TensorClass >>> class Foo(TensorClass): ... x: torch.Tensor ... y: Any = None >>> foo = Foo(x=torch.zeros(3)) >>> sorted(foo.to_tensordict().keys()) ['x'] >>> sorted(foo.to_tensordict(retain_none=True).keys()) ['x', 'y']
- unbind(dim: int)#
Returns a tuple of indexed tensorclass instances unbound along the indicated dimension.
Resulting tensorclass instances will share the storage of the initial tensorclass instance.