Skip to content

PNTensor

danling.tensors.pn_tensor

PNTensor (Potential Nested Tensor) — a torch.Tensor subclass that collates into NestedTensor via PyTorch DataLoader after importing danling.tensors.

PNTensor

Bases: Tensor

A tensor wrapper that can be collated into NestedTensor with PyTorch DataLoader.

PNTensor (Potential Nested Tensor) seamlessly bridges the gap between individual tensors and batched NestedTensor objects in PyTorch workflows. It’s designed specifically to work with PyTorch’s DataLoader collation mechanism, allowing datasets to return variable-length tensors that can be combined into a NestedTensor when batched.

The class provides three properties that mirror those of NestedTensor: - .tensor: The tensor itself (self) - .mask: A tensor of ones with the same shape as self - .concat: The tensor itself (self)

Other attributes and methods are inherited from torch.Tensor.

Examples:

Basic usage with PyTorch DataLoader:

Python Console Session
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
>>> from torch.utils.data import Dataset, DataLoader
>>> from danling.tensors import PNTensor
>>> class VariableLengthDataset(Dataset):
...     def __init__(self, data):
...         self.data = data
...     def __len__(self):
...         return len(self.data)
...     def __getitem__(self, idx):
...         return PNTensor(self.data[idx])
>>> # Create a dataset with variable-length sequences
>>> dataset = VariableLengthDataset([[1, 2, 3], [4, 5], [6, 7, 8, 9]])
>>> dataloader = DataLoader(dataset, batch_size=3)
>>> # The DataLoader produces NestedTensor batches by default for PNTensor
>>> batch = next(iter(dataloader))
>>> batch
NestedTensor([
    [1., 2., 3.],
    [4., 5.],
    [6., 7., 8., 9.]
])

Using PNTensor directly:

Python Console Session
1
2
3
4
5
6
7
>>> tensor = PNTensor([1, 2, 3])
>>> tensor
PNTensor([1., 2., 3.])
>>> tensor.tensor
PNTensor([1., 2., 3.])
>>> tensor.mask
PNTensor([True, True, True])
Source code in danling/tensors/pn_tensor.py
Python
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
class PNTensor(Tensor):
    r"""
    A tensor wrapper that can be collated into NestedTensor with PyTorch DataLoader.

    `PNTensor` (Potential Nested Tensor) seamlessly bridges the gap between individual tensors
    and batched `NestedTensor` objects in PyTorch workflows. It's designed specifically to work
    with PyTorch's DataLoader collation mechanism, allowing datasets to return variable-length
    tensors that can be combined into a `NestedTensor` when batched.

    The class provides three properties that mirror those of NestedTensor:
    - `.tensor`: The tensor itself (self)
    - `.mask`: A tensor of ones with the same shape as self
    - `.concat`: The tensor itself (self)

    Other attributes and methods are inherited from `torch.Tensor`.

    Examples:
        Basic usage with PyTorch DataLoader:

        >>> from torch.utils.data import Dataset, DataLoader
        >>> from danling.tensors import PNTensor
        >>> class VariableLengthDataset(Dataset):
        ...     def __init__(self, data):
        ...         self.data = data
        ...     def __len__(self):
        ...         return len(self.data)
        ...     def __getitem__(self, idx):
        ...         return PNTensor(self.data[idx])
        >>> # Create a dataset with variable-length sequences
        >>> dataset = VariableLengthDataset([[1, 2, 3], [4, 5], [6, 7, 8, 9]])
        >>> dataloader = DataLoader(dataset, batch_size=3)
        >>> # The DataLoader produces NestedTensor batches by default for PNTensor
        >>> batch = next(iter(dataloader))
        >>> batch
        NestedTensor([
            [1., 2., 3.],
            [4., 5.],
            [6., 7., 8., 9.]
        ])

        Using PNTensor directly:

        >>> tensor = PNTensor([1, 2, 3])
        >>> tensor
        PNTensor([1., 2., 3.])
        >>> tensor.tensor
        PNTensor([1., 2., 3.])
        >>> tensor.mask
        PNTensor([True, True, True])
    """

    @property
    def tensor(self) -> Tensor:
        r"""
        Identical to `self`.

        Returns:
            (torch.Tensor):

        Examples:
            >>> tensor = torch.tensor([1, 2, 3])
            >>> pn_tensor = PNTensor([1, 2, 3])
            >>> bool((tensor == pn_tensor).all())
            True
            >>> bool((tensor == pn_tensor.tensor).all())
            True
        """

        return self

    @property
    def mask(self) -> Tensor:
        r"""
        All-True boolean mask (PNTensor has no padding).

        Returns a stride-0 expanded view — no memory allocation beyond a scalar.

        Returns:
            (torch.Tensor):

        Examples:
            >>> tensor = torch.tensor([1, 2, 3])
            >>> pn_tensor = PNTensor([1, 2, 3])
            >>> bool((pn_tensor.mask == torch.ones_like(pn_tensor)).all().item())
            True
        """

        return torch.ones((), dtype=torch.bool, device=self.device).expand_as(self)

    @property
    def concat(self) -> Tensor:
        r"""
        Identical to `self`.

        Returns:
            (torch.Tensor):

        Examples:
            >>> pn_tensor = PNTensor([1, 2, 3])
            >>> bool((pn_tensor == pn_tensor.concat).all())
            True
        """

        return self

    def new_empty(self, *args, **kwargs):
        r"""Return a new empty PNTensor with the same type."""
        return PNTensor(super().new_empty(*args, **kwargs))

tensor property

Python
tensor: Tensor

Identical to self.

Returns:

Type Description
Tensor

Examples:

Python Console Session
1
2
3
4
5
6
>>> tensor = torch.tensor([1, 2, 3])
>>> pn_tensor = PNTensor([1, 2, 3])
>>> bool((tensor == pn_tensor).all())
True
>>> bool((tensor == pn_tensor.tensor).all())
True

mask property

Python
mask: Tensor

All-True boolean mask (PNTensor has no padding).

Returns a stride-0 expanded view — no memory allocation beyond a scalar.

Returns:

Type Description
Tensor

Examples:

Python Console Session
1
2
3
4
>>> tensor = torch.tensor([1, 2, 3])
>>> pn_tensor = PNTensor([1, 2, 3])
>>> bool((pn_tensor.mask == torch.ones_like(pn_tensor)).all().item())
True

concat property

Python
concat: Tensor

Identical to self.

Returns:

Type Description
Tensor

Examples:

Python Console Session
1
2
3
>>> pn_tensor = PNTensor([1, 2, 3])
>>> bool((pn_tensor == pn_tensor.concat).all())
True

new_empty

Python
new_empty(*args, **kwargs)

Return a new empty PNTensor with the same type.

Source code in danling/tensors/pn_tensor.py
Python
168
169
170
def new_empty(self, *args, **kwargs):
    r"""Return a new empty PNTensor with the same type."""
    return PNTensor(super().new_empty(*args, **kwargs))

tensor

Python
tensor(data: Any, dtype=None, device=None, requires_grad: bool = False, pin_memory: bool = False) -> PNTensor

Create a PNTensor from data, similar to torch.tensor() but returning a PNTensor.

This function is a convenient way to create PNTensor objects that can be collated into NestedTensor when used with PyTorch DataLoader after importing danling.tensors. The interface mirrors torch.tensor() to make it easy to switch between regular tensors and PNTensors.

Parameters:

Name Type Description Default

data

Any

Initial data for the tensor. Can be a list, tuple, NumPy ndarray, scalar, etc.

required

dtype

dtype | None

Desired data type of the returned tensor.

None

device

device | str | int | None

Device on which to place the tensor.

None

requires_grad

bool

If autograd should record operations on the returned tensor.

False

pin_memory

bool

If True, the tensor will be allocated in pinned memory.

False

Returns:

Name Type Description
PNTensor PNTensor

A tensor wrapper for NestedTensor-oriented collation

Examples:

Python Console Session
1
2
3
4
>>> from danling.tensors import tensor
>>> t = tensor([1, 2, 3])
>>> t
PNTensor([1, 2, 3])
Source code in danling/tensors/pn_tensor.py
Python
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
def tensor(data: Any, dtype=None, device=None, requires_grad: bool = False, pin_memory: bool = False) -> PNTensor:
    r"""
    Create a PNTensor from data, similar to torch.tensor() but returning a PNTensor.

    This function is a convenient way to create PNTensor objects that can be
    collated into NestedTensor when used with PyTorch DataLoader after importing
    ``danling.tensors``. The interface mirrors torch.tensor() to make it easy to
    switch between regular tensors and PNTensors.

    Args:
        data: Initial data for the tensor. Can be a list, tuple, NumPy ndarray, scalar, etc.
        dtype (torch.dtype | None): Desired data type of the returned tensor.
        device (torch.device | str | int | None): Device on which to place the tensor.
        requires_grad: If autograd should record operations on the returned tensor.
        pin_memory: If True, the tensor will be allocated in pinned memory.

    Returns:
        PNTensor: A tensor wrapper for NestedTensor-oriented collation

    Examples:
        >>> from danling.tensors import tensor
        >>> t = tensor([1, 2, 3])
        >>> t
        PNTensor([1, 2, 3])
    """
    return PNTensor(torch.tensor(data, dtype=dtype, device=device, requires_grad=requires_grad, pin_memory=pin_memory))