autograd package¶
autograd.tensor module¶
- autograd.tensor.is_grad_enabled() bool¶
- autograd.tensor.no_grad()¶
- class autograd.tensor.Function(*tensors: Tensor)¶
Bases:
objectBase class for differentiable operations.
Subclasses of Function should implement the forward and backward methods to define the forward and backward passes of a particular operation. Some subclasses can be found in functional.py module
Examples
>>> # Example of a subclass (dummy function for demonstration) >>> class DummyFunction(Function): ... def forward(self, x): ... return x + 1 ... def backward(self, grad): ... return grad >>> from autograd.tensor import Tensor >>> import numpy as np >>> x = Tensor(xp.array([1, 2, 3])) >>> y = DummyFunction.apply(x) # Expected output: [2, 3, 4]
- __init__(*tensors: Tensor)¶
Initialize a Function with a set of input tensors.
- Parameters:
*tensors (Tensor) – The input tensors for this operation.
Examples
>>> from autograd.tensor import Tensor >>> x = Tensor([1, 2, 3]) >>> f = Function(x) # Although Function is abstract, this demonstrates the initializer.
- abstractmethod forward(*args: Any, **kwargs: Any) Any¶
Perform the forward pass of this operation.
This method should be overridden by subclasses to define the specific behavior of the operation. It receives NumPy arrays corresponding to the data of the input tensors.
- Parameters:
*args (xp.ndarray) – Data arrays for the input tensors.
**kwargs (Any) – Additional keyword arguments.
- Returns:
xp.ndarray – The result of the forward pass as a NumPy array.
- Raises:
NotImplementedError – If this method is not implemented in a subclass.
- abstractmethod backward(grad: Tensor) Any¶
Perform the backward pass of this operation.
This method should be overridden by subclasses to define how gradients are computed and propagated back to the input tensors.
In this context: - “grad” (the method argument) is the gradient of the loss function with respect to the output of this operation (dL/d[out]). - The return value should be the gradient of the loss function with respect to the input of this operation (dL/d[input]), so it can be passed further back along the computational graph.
- Parameters:
grad (Tensor) – The gradient with respect to the output of this operation.
- Returns:
xp.ndarray – The gradient with respect to the input(s).
- Raises:
NotImplementedError – If this method is not implemented in a subclass.
- classmethod apply(*tensors: Tensor, **kwargs: Any) Tensor¶
Construct and apply this function to the given tensors.
This method: 1) Creates an instance of the function. 2) Extracts the .data from the input tensors to pass into the function’s forward method. 3) Wraps the result in a new Tensor that references this function (for backprop).
- Parameters:
*tensors (Tensor) – Input tensors to the operation.
**kwargs (Any) – Additional keyword arguments passed to the forward method.
- Returns:
Tensor – The resulting tensor after the forward operation.
- static unbroadcast(grad_arr: Any, to_shape: Tuple[int, ...]) Any¶
Sum out broadcasted dimensions so that grad_arr can match to_shape. Essentially the inverse of numpy’s broadcasting.
- Parameters:
grad_arr (xp.ndarray) – Gradient array to unbroadcast.
to_shape (Tuple[int, ...]) – Shape to unbroadcast to.
- Returns:
xp.ndarray – Unbroadcasted gradient array.
Examples
>>> import numpy as np >>> grad_arr = xp.array([[1, 1], [1, 1]]) >>> unb = Function.unbroadcast(grad_arr, (1, 2)) # Expected output: [[2, 2]] (summing over the broadcasted dim)
- __dict__ = mappingproxy({'__module__': 'autograd.tensor', '__doc__': '\n Base class for differentiable operations.\n\n Subclasses of `Function` should implement the `forward` and `backward` methods to define the\n forward and backward passes of a particular operation. Some subclasses can be found in `functional.py` module\n\n Examples:\n >>> # Example of a subclass (dummy function for demonstration)\n >>> class DummyFunction(Function):\n ... def forward(self, x):\n ... return x + 1\n ... def backward(self, grad):\n ... return grad\n >>> from autograd.tensor import Tensor\n >>> import numpy as np\n >>> x = Tensor(xp.array([1, 2, 3]))\n >>> y = DummyFunction.apply(x) # Expected output: [2, 3, 4]\n ', '__init__': <function Function.__init__>, 'forward': <function Function.forward>, 'backward': <function Function.backward>, 'apply': <classmethod(<function Function.apply>)>, 'unbroadcast': <staticmethod(<function Function.unbroadcast>)>, '__dict__': <attribute '__dict__' of 'Function' objects>, '__weakref__': <attribute '__weakref__' of 'Function' objects>, '__annotations__': {}})¶
- __module__ = 'autograd.tensor'¶
- __weakref__¶
list of weak references to the object
- class autograd.tensor.Tensor(data: Any | Sequence[Any] | int | float | bool, creator: Function | None = None, requires_grad: bool = True)¶
Bases:
objectA Tensor is the core data structure of this autograd engine.
It holds an an optional reference to a creator function, and gradient information.
Examples
>>> import numpy as np >>> from autograd.tensor import Tensor >>> x = Tensor(xp.array([1.0, 2.0, 3.0])) # Expected: xp.array([1., 2., 3.], dtype=float32)
- __init__(data: Any | Sequence[Any] | int | float | bool, creator: Function | None = None, requires_grad: bool = True)¶
Initialize a Tensor.
- Parameters:
data (ArrayLike) – The data for this tensor. Python scalars/sequences are materialized as float32 by default, while explicit backend arrays keep their dtype.
creator (Optional[Function], optional) – The function that created this tensor. Defaults to None if this tensor is a leaf.
requires_grad (bool, optional) – Whether this tensor requires gradients. Defaults to True. Note that this default is independent of the no_grad() context; callers constructing leaf tensors inside no_grad() must still pass requires_grad=False explicitly if they want a non-grad leaf.
Examples
>>> x = Tensor([1, 2, 3]) # Expected: xp.array([1., 2., 3.], dtype=float32)
- property data: Any¶
- property grad: Tensor | None¶
Getter method of the gradient of this tensor.
The internal _grad is stored either as a Tensor or None. If it is stored as a NumPy it will be wrapped in a Tensor before returning.
- Returns:
Optional[Tensor] – The gradient if it exists, or None.
Examples
>>> x = Tensor([1, 2, 3]) >>> print(x.grad) # Expected: None
- view(*shape: int | Tuple[int, ...]) Tensor¶
Create a view of the tensor with the specified shape without copying the underlying data.
The new shape must be compatible with the total number of elements in the input tensor.
- Raises:
ValueError – If more than one -1 is specified in the new shape or if the new shape does not match the input tensor’s total size.
- Parameters:
*shape (int) – The desired shape. If -1 is present, it is inferred based on the remaining dimensions.
- Returns:
Tensor – A new tensor that shares data with the original but is shaped differently.
Examples
>>> x = Tensor(xp.array([1, 2, 3, 4])) >>> y = x.view(2, 2) >>> print(y.data.shape) # Expected: (2, 2)
- static stack(tensors: List[Tensor], axis: int = 0) Tensor¶
Stack a list of tensors along a new dimension. This operation joins a sequence of tensors by inserting a new axis at the specified position and concatenating along that axis.
- Parameters:
tensors (List[Tensor]) – The list of tensors to stack.
axis (int, optional) – The dimension along which to stack. Defaults to 0.
- Returns:
Tensor – A new tensor created by stacking.
Examples
>>> t1 = Tensor(xp.array([1, 2])) >>> t2 = Tensor(xp.array([3, 4])) >>> result = Tensor.stack([t1, t2], axis=0) # Expected: [[1, 2], [3, 4]]
- static cat(tensors: List[Tensor], axis: int = 0) Tensor¶
Concatenate a list of tensors along the specified dimension. This operation concatenates the input tensors along the given axis.
- Parameters:
tensors (List[Tensor]) – The list of tensors to concatenate.
axis (int, optional) – The dimension along which to concatenate. Defaults to 0.
- Returns:
Tensor – The concatenated tensor.
Examples
>>> t1 = Tensor(xp.array([[1, 2]])) >>> t2 = Tensor(xp.array([[3, 4]])) >>> result = Tensor.cat([t1, t2], axis=0) # Expected: [[1, 2], [3, 4]]
- __add__(other: Tensor | float | int) Tensor¶
Element-wise addition of two tensors (or a tensor and a scalar).
- Parameters:
other (Union[Tensor, float, int]) – The tensor or scalar to add.
- Returns:
Tensor – The result of addition.
- __mul__(other: Tensor | float | int) Tensor¶
Element-wise multiplication of two tensors (or a tensor and a scalar).
\[ z = x \cdot y \]- Parameters:
other (Union[Tensor, float, int]) – The tensor or scalar to multiply with.
- Returns:
Tensor – The result of multiplication.
- __matmul__(other: Tensor | float | int) Tensor¶
Perform matrix multiplication (dot product) with another tensor.
For higher-dimensional tensors, xp.matmul broadcasting rules are followed.
- Parameters:
other (Union[Tensor, float, int]) – The tensor or scalar to matmul with.
- Returns:
Tensor – The result of matrix multiplication.
- __pow__(other: Tensor | float | int) Tensor¶
Compute the power operation \(z = x^y\) with another tensor or scalar.
- Parameters:
other (Union[Tensor, float, int]) – The exponent.
- Returns:
Tensor – The result of the power operation.
Examples
>>> x = Tensor(xp.array([2, 3])) >>> y = x ** 3 # Expected: [8, 27]
- __iadd__(other: Tensor | float | int) Tensor¶
In-place addition (self += other).
Broadcasting rules apply if shapes differ. This should maintain the computational graph while modifying the tensor in-place.
- Parameters:
other (Union[Tensor, float, int]) – The tensor or scalar to add.
- Returns:
Tensor – This tensor, after in-place addition.
- __getitem__(idx: int | slice | tuple) Tensor¶
Get a sliced or indexed view of the tensor.
- Parameters:
idx (Union[int, slice, tuple]) – The index or slice.
- Returns:
Tensor – A new tensor that shares data with the original.
- __setitem__(idx: int | slice | tuple, value: Tensor | float | int) Tensor¶
Set a portion of the tensor to a given value.
- Parameters:
idx (Union[int, slice, tuple]) – The index or slice.
value (Union[Tensor, float, int]) – The value to set.
- Returns:
Tensor – The same tensor after the in-place assignment.
- sum(axis: int | Tuple[int, ...] | None = None, keepdims: bool = False) Tensor¶
Compute the sum of all elements (or along specified axis).
This function computes the sum of the input tensor elements along a specified axis or axes. If no axis is specified, all elements of the tensor are summed. Optionally, the reduced dimensions can be kept in the output tensor.
The summation is mathematically represented as:
\[ y = \sum_{i \in A} x_i \]where A represents the specified axis or axes.
- Parameters:
axis (int or tuple of ints, optional) – Axis or axes along which the sum is performed. If None, the sum of all elements is computed.
keepdims (bool, optional) – If True, the reduced axes are left in the result as dimensions with size one so that the result can be broadcast correctly against the input tensor.
Examples
- For example:
Original tensor shape (3, 4, 5), axis (1, 2), keepdims True → result shape (3, 1, 1)
Original tensor shape (3, 4, 5), axis (1, 2), keepdims False → result shape (3,)
Original tensor shape (3, 4, 5), axis None, keepdims True → result shape (1,)
Original tensor shape (3, 4, 5), axis None, keepdims False → result shape ()
- Parameters:
axis (Optional[Union[int, Tuple[int, ...]]], optional) – Axis or axes to sum over. If None, sums over all elements. Defaults to None.
keepdims (bool, optional) – Keep the reduced dimensions as size 1. Defaults to False.
- Returns:
Tensor – The tensor with summed values.
Examples
>>> x = Tensor(xp.array([[1, 2], [3, 4]])) >>> s = x.sum(axis=0, keepdims=True) # Expected: [[4, 6]]
- mean(axis: int | Tuple[int, ...] | None = None, keepdims: bool = False) Tensor¶
Compute the mean of elements (or along specified axis).
This function computes the mean of the input tensor elements along a specified axis or axes. If no axis is specified, the mean of all elements is computed. Optionally, the reduced dimensions can be kept in the output tensor.
- The mean is mathematically defined as:
- \[ y = \frac{1}{N} \sum_{i \in A} x_i \]
where A represents the specified axis or axes and N is the number of elements summed.
- For example:
Original tensor shape (3, 4, 5), axis (1, 2), keepdims True → result shape (3, 1, 1)
Original tensor shape (3, 4, 5), axis (1, 2), keepdims False → result shape (3,)
Original tensor shape (3, 4, 5), axis None, keepdims True → result shape (1,)
Original tensor shape (3, 4, 5), axis None, keepdims False → result shape ()
- Parameters:
axis (Optional[Union[int, Tuple[int, ...]]], optional) – Axis or axes to average over. If None, averages over all elements. Defaults to None.
keepdims (bool, optional) – Keep the reduced dimensions as size 1. Defaults to False.
- Returns:
Tensor – The tensor with mean values.
Examples
>>> x = Tensor(xp.array([[1, 2], [3, 4]])) >>> m = x.mean(axis=0) # Expected: [2, 3]
- max(axis: int | Tuple[int, ...] | None = None, keepdims: bool = False) Tensor¶
Compute the maximum value of elements (or along specified axis).
This function computes the maximum value of the input tensor along a specified axis or axes. If no axis is specified, the maximum over all elements is computed. Optionally, the reduced dimensions can be kept in the output tensor.
Mathematically, the maximum is computed as:
\[ y = \max_{i \in A} \; x_i \]where A represents the specified axis or axes.
- Parameters:
axis (Optional[Union[int, Tuple[int, ...]]], optional) – Axis or axes to compute max over. If None, computes global max. Defaults to None.
keepdims (bool, optional) – Keep the reduced dimensions as size 1. Defaults to False.
- Returns:
Tensor – The tensor with maximum values.
Examples
>>> x = Tensor(xp.array([[1, 5], [3, 4]])) >>> m = x.max(axis=0) # Expected: [3, 5]
- gather(index: Any = 0) Tensor¶
Gather rows from a 2D tensor using specified row indices.
This operation extracts rows from the input tensor corresponding to the given index or indices. It is particularly useful for selecting specific rows from a matrix, such as picking particular examples from a batch of data. When a single index is provided, it returns the corresponding row; when multiple indices are provided (e.g., as a list or tuple), it returns a new tensor composed of rows at those positions.
- Parameters:
index (int or list/tuple of ints) – The row index or indices to gather from the tensor. Defaults to 0.
- Returns:
Tensor – A new tensor containing the gathered rows.
Example
>>> tensor = Tensor([[10, 20], [30, 40], [50, 60]]) >>> gathered = tensor.gather([0, 2]) >>> print(gathered) Tensor([[10, 20], [50, 60]])
- sqrt() Tensor¶
Compute the element-wise square root of the tensor.
- Returns:
Tensor – The result of the sqrt operation.
Examples
>>> x = Tensor(xp.array([4, 9, 16])) >>> y = x.sqrt() # Expected: [2, 3, 4]
- maximum(other: Tensor | float | int) Tensor¶
Element-wise maximum between two tensors or a tensor and a scalar.
This function performs an element-wise comparison between two input tensors and returns a new tensor containing the maximum value from each pair of elements. When both inputs are equal, the gradient is split equally between them.
- Parameters:
other (Union[Tensor, float, int]) – The tensor or scalar to compare.
- Returns:
Tensor – Element-wise maximum.
Examples
>>> x = Tensor(xp.array([1, 5, 3])) >>> y = Tensor(xp.array([2, 4, 3])) >>> z = x.maximum(y) # Expected: [2, 5, 3]
- pad(pad_width: int | Tuple[int, int] | Tuple[int, int, int, int] | Tuple[Tuple[int, int], ...], mode: str = 'constant', constant_values: int | float = 0) Tensor¶
Pad the tensor according to specified widths in each dimension.
This operation pads the input tensor using the given padding widths and mode. The interpretation of the
pad_widthargument is as follows:If an int is provided, all dimensions are padded with that value.
If a tuple of 2 values is provided, it is interpreted as padding for the last dimension (PyTorch style): (pad_left, pad_right).
If a tuple of 4 values is provided, it is interpreted as padding for the last two dimensions: (pad_left, pad_right, pad_top, pad_bottom).
If a tuple of tuples is provided, each inner tuple specifies (pad_before, pad_after) for each dimension.
The padded values are determined by the specified mode (default is “constant”) and the constant value provided.
- Parameters:
pad_width (int or tuple) – Specifies how much padding to add on each dimension.
mode (str, optional) – Padding mode. Defaults to “constant”.
constant_values (int or float, optional) – Fill value for constant padding. Defaults to 0.
- Returns:
Tensor – The padded tensor.
Example
>>> tensor = Tensor([[1, 2], [3, 4]]) >>> padded_tensor = tensor.pad(pad_width=1, mode="constant", constant_values=0) >>> print(padded_tensor) Tensor([[0, 0, 0, 0], [0, 1, 2, 0], [0, 3, 4, 0], [0, 0, 0, 0]])
- forward(data: Any) None¶
Placeholder for forward logic if needed. Currently unused.
- backward(grad: Tensor | Any | Sequence[Any] | int | float | bool | None = None) None¶
Compute gradients for all upstream nodes in the graph via backpropagation.
If grad is None, we treat the gradient as ones (like d(self)/d(self) = 1).
2. We then do a post-order traversal of the graph: gather all nodes that lead to this tensor and store them in a topologically sorted list. 3. Finally, we go through that list in reverse order to apply each node’s .backward(…), passing gradients back to the node’s inputs.
As a side effect, each ancestor Tensor accumulates its .grad field.
- Parameters:
grad (Optional[Union[Tensor, ArrayLike]]) – The gradient w.r.t. this tensor’s output.
Examples
>>> # In a typical usage, backward() is invoked on the loss tensor. >>> loss.backward()
- property shape: Tuple[int, ...]¶
Return the shape of the underlying NumPy data.
- Returns:
Tuple[int, …] – The shape of this tensor.
Examples
>>> x = Tensor(xp.array([[1,2],[3,4]])) >>> print(x.shape) # Expected: (2, 2)
- reshape(*shape: int) Tensor¶
Return a new tensor with the same data but a different shape. It is functionally similar to numpy’s reshape.
- Parameters:
*shape (int) – The desired new shape.
- Returns:
Tensor – A reshaped tensor.
Examples
>>> x = Tensor(xp.array([1, 2, 3, 4])) >>> y = x.reshape(2,2) >>> print(y.data.shape) # Expected: (2, 2)
- expand(*shape: int | Sequence[int]) Tensor¶
Broadcast the tensor to a new shape without copying data.
This operation broadcasts the input tensor to a new shape. The forward pass creates a new mx with the specified shape (via broadcasting), and the backward pass reduces the gradient back to the shape of the original tensor.
- Parameters:
*shape (Union[int, Sequence[int]]) – The target shape, which can be specified as multiple int arguments or as a single tuple/list.
- Returns:
Tensor – A new tensor broadcast to the specified shape.
Example
>>> tensor = Tensor([1, 2, 3]) >>> expanded_tensor = tensor.expand(3, 3) >>> print(expanded_tensor) Tensor([[1, 2, 3], [1, 2, 3], [1, 2, 3]])
- permute(*dims: int) Tensor¶
Reorder (permute) the dimensions of this tensor. .. rubric:: Examples
>>> import numpy as np >>> from your_module import Tensor, Permute >>> t = Tensor(xp.array([[1, 2], [3, 4]])) >>> op = Permute() >>> result = op.forward(t.data, dims=[1, 0]) >>> print(result) [[1, 3], [2, 4]]
- Parameters:
*dims (int) – A sequence of dimension indices indicating the new order.
- Returns:
Tensor – A new tensor with permuted dimensions.
Example
>>> tensor = Tensor([[1, 2], [3, 4]]) >>> permuted_tensor = tensor.permute(1, 0) >>> print(permuted_tensor) Tensor([[1, 3], [2, 4]])
- transpose(dim0: int = 0, dim1: int = 1) Tensor¶
Swap two dimensions of this tensor.
This operation swaps the positions of two specified dimensions of the input tensor. The backward pass applies the same transposition to the gradient, restoring the original dimension order.
- Parameters:
dim0 (int, optional) – First dimension to swap. Defaults to 0.
dim1 (int, optional) – Second dimension to swap. Defaults to 1.
- Returns:
Tensor – A new tensor with the specified dimensions swapped.
Examples
>>> tensor = Tensor(xp.array([[1, 2], [3, 4]])) >>> t = tensor.transpose(0, 1) >>> print(t.data) [[1, 3], [2, 4]]
- strided_windows(kernel_size: int, stride: int) Tensor¶
Extract sliding windows of size kernel_size with stride stride.
This operation generates overlapping windows from the input tensor using the specified kernel size and stride. The output shape is given by:
\[ (H_{out}, W_{out}, batch\_size, channels, kernel\_size, kernel\_size) \]where
\[\begin{split} \begin{align} H_{out} = \frac{height - kernel\_size}{stride} + 1 \\ W_{out} = \frac{width - kernel\_size}{stride} + 1 \end{align} \end{split}\]Examples
>>> import numpy as np >>> x = Tensor(xp.random.rand(2, 3, 10, 10)) # shape: (batch, channels, height, width) >>> op = StridedWindows() >>> windows = x.strided_windows(x, kernel_size=3, stride=1) >>> print(windows.shape) (8, 8, 2, 3, 3, 3)
- Parameters:
kernel_size (int) – The size of each window.
stride (int) – The stride between windows.
- Returns:
Tensor – A tensor representing the strided windows.
- roll(shifts: int, dims: int) Tensor¶
Roll tensor elements along a given dimension. This operation shifts the elements of the input tensor along the given dimension by the specified number of positions. Elements that roll beyond the last position reappear at the beginning.
- Parameters:
shifts (int) – Number of places by which to shift.
dims (int) – Dimension along which to roll.
- Returns:
Tensor – The rolled tensor.
Example
>>> tensor = Tensor(xp.array([1, 2, 3, 4, 5])) >>> rolled_tensor = tensor.roll(shifts=2, dims=0) >>> print(rolled_tensor.data) [4, 5, 1, 2, 3]
- detach() Tensor¶
Detach this tensor from the computational graph, returning a new tensor with the same data but no gradient.
- Returns:
Tensor – A new tensor that does not track gradients.
Examples
>>> x = Tensor(xp.array([1, 2, 3])) >>> y = x.detach() >>> y.requires_grad False
- item() Any¶
Return this tensor as a host scalar.
- numpy() Any¶
Return this tensor as a host NumPy array.
- property ndim: int¶
Return the number of dimensions of this tensor.
- Returns:
int – The number of dimensions.
Examples
>>> x = Tensor(xp.array([[1,2],[3,4]])) >>> print(x.ndim) # Expected: 2
- property T: Tensor¶
Convenience property to transpose a 2D tensor. For higher dimensions, use transpose() with explicit dims.
- Returns:
Tensor – Transposed tensor.
- Raises:
ValueError – If the tensor is not 2D.
Examples
>>> x = Tensor(xp.array([[1,2],[3,4]])) >>> print(x.T.data) [[1, 3], [2, 4]]
- __repr__() str¶
Return a string representation of the tensor, showing its data and gradient.
Examples
>>> x = Tensor(xp.array([1,2,3])) >>> print(x) Tensor(data=[1. 2. 3.], grad=None)
- __hash__() int¶
Return hash(self).
- __annotations__ = {'_grad': "Optional['Tensor']"}¶
- __dict__ = mappingproxy({'__module__': 'autograd.tensor', '__doc__': '\n A `Tensor` is the core data structure of this autograd engine.\n\n It holds an an optional reference to a creator function, and gradient information.\n\n Examples:\n >>> import numpy as np\n >>> from autograd.tensor import Tensor\n >>> x = Tensor(xp.array([1.0, 2.0, 3.0])) # Expected: xp.array([1., 2., 3.], dtype=float32)\n ', '__init__': <function Tensor.__init__>, 'data': <property object>, 'grad': <property object>, 'view': <function Tensor.view>, 'stack': <staticmethod(<function Tensor.stack>)>, 'cat': <staticmethod(<function Tensor.cat>)>, '__add__': <function Tensor.__add__>, '__mul__': <function Tensor.__mul__>, '__matmul__': <function Tensor.__matmul__>, '__pow__': <function Tensor.__pow__>, '__iadd__': <function Tensor.__iadd__>, '_wrap_scalar_like_self': <function Tensor._wrap_scalar_like_self>, '__getitem__': <function Tensor.__getitem__>, '__setitem__': <function Tensor.__setitem__>, 'astype': <function Tensor.astype>, 'sum': <function Tensor.sum>, 'mean': <function Tensor.mean>, 'max': <function Tensor.max>, 'gather': <function Tensor.gather>, 'sqrt': <function Tensor.sqrt>, 'maximum': <function Tensor.maximum>, 'pad': <function Tensor.pad>, 'forward': <function Tensor.forward>, 'backward': <function Tensor.backward>, 'shape': <property object>, 'reshape': <function Tensor.reshape>, 'expand': <function Tensor.expand>, 'permute': <function Tensor.permute>, 'transpose': <function Tensor.transpose>, 'strided_windows': <function Tensor.strided_windows>, 'roll': <function Tensor.roll>, 'detach': <function Tensor.detach>, 'item': <function Tensor.item>, 'numpy': <function Tensor.numpy>, 'ndim': <property object>, 'T': <property object>, '_accumulate_grad': <function Tensor._accumulate_grad>, '__radd__': <function Tensor.__radd__>, '__rmul__': <function Tensor.__rmul__>, '__sub__': <function Tensor.__sub__>, '__rsub__': <function Tensor.__rsub__>, '__truediv__': <function Tensor.__truediv__>, '__neg__': <function Tensor.__neg__>, '__repr__': <function Tensor.__repr__>, '__lt__': <function Tensor.__lt__>, '__le__': <function Tensor.__le__>, '__gt__': <function Tensor.__gt__>, '__ge__': <function Tensor.__ge__>, '__eq__': <function Tensor.__eq__>, '__hash__': <function Tensor.__hash__>, '__dict__': <attribute '__dict__' of 'Tensor' objects>, '__weakref__': <attribute '__weakref__' of 'Tensor' objects>, '__annotations__': {'_grad': "Optional['Tensor']"}})¶
- __module__ = 'autograd.tensor'¶
- __weakref__¶
list of weak references to the object
- class autograd.tensor.Add(*tensors: Tensor)¶
Bases:
FunctionElement-wise addition of two tensors. See
autograd.tensor.Tensor.__add__()functionExamples
>>> x = Tensor(xp.array([1,2,3])) >>> y = Tensor(xp.array([4,5,6])) >>> z = Add.apply(x, y) # Expected: [5, 7, 9]
- forward(x: Any, y: Any) Any¶
Compute the element-wise sum of two tensors.
- Parameters:
x (xp.ndarray) – The first input tensor.
y (xp.ndarray) – The second input tensor.
- Returns:
xp.ndarray – The element-wise sum of
xandy.
- backward(grad: Tensor) Tuple[Any | None, Any | None]¶
Compute the gradient for the addition operation.
Since addition is linear, the gradient with respect to both inputs is the same as the incoming gradient.
- Parameters:
grad (Tensor) – The gradient of the loss with respect to the output.
- Returns:
Tuple[Optional[xp.ndarray], Optional[xp.ndarray]] – The gradients with respect to
xandy.
Examples
>>> x = Tensor(xp.array([1,2,3])) >>> y = Tensor(xp.array([4,5,6])) >>> z = x + y >>> # During backprop, the gradient for both x and y would be the same as grad.
- __annotations__ = {}¶
- __module__ = 'autograd.tensor'¶
- class autograd.tensor.Mul(*tensors: Tensor)¶
Bases:
FunctionElement-wise multiplication of two tensors. See
autograd.tensor.Tensor.__mul__()functionExamples
>>> x = Tensor(xp.array([1,2,3])) >>> y = Tensor(xp.array([4,5,6])) >>> z = Mul.apply(x, y) # Expected: [4, 10, 18]
- forward(x: Any, y: Any) Any¶
Compute the element-wise product of two tensors.
- Parameters:
x (xp.ndarray) – The first input tensor.
y (xp.ndarray) – The second input tensor.
- Returns:
xp.ndarray – The element-wise product of
xandy.
- backward(grad: Tensor) Tuple[Any | None, Any | None]¶
Compute the gradient for the multiplication operation.
The gradients are computed as:
\[\begin{split} \begin{align} \frac{\partial z}{\partial x} = y \\ \frac{\partial z}{\partial y} = x \end{align} \end{split}\]and then multiplied by the incoming gradient.
- Parameters:
grad (Tensor) – The gradient of the loss with respect to the output.
- Returns:
Tuple[Optional[xp.ndarray], Optional[xp.ndarray]] – The gradients with respect to
xandy.
Examples
>>> x = Tensor(xp.array([1,2,3])) >>> y = Tensor(xp.array([4,5,6])) >>> z = x * y >>> # Backpropagated gradients for x would be y, and for y would be x.
- __annotations__ = {}¶
- __module__ = 'autograd.tensor'¶
- class autograd.tensor.Pow(*tensors: Tensor)¶
Bases:
FunctionElement-wise power operation. See
autograd.tensor.Tensor.__pow__()functionExamples
>>> x = Tensor(xp.array([2, 3])) >>> y = x ** 3 # Expected: [8, 27]
- forward(x: Any, y: Any) Any¶
Compute the element-wise power operation.
- Parameters:
x (xp.ndarray) – The base tensor.
y (xp.ndarray) – The exponent tensor.
- Returns:
xp.ndarray – The result of raising
xto the powery.
- backward(grad: Tensor) Tuple[Any | None, Any | None]¶
Compute the gradient for the power operation.
The derivatives are given by:
\[\begin{split} \begin{align} \frac{\partial (x^y)}{\partial x} = y \cdot x^{y-1} \\ \frac{\partial (x^y)}{\partial y} = x^y \cdot \ln(x) \end{align} \end{split}\]These derivatives are multiplied by the incoming gradient.
- Parameters:
grad (Tensor) – The gradient of the loss with respect to the output.
- Returns:
Tuple[Optional[xp.ndarray], Optional[xp.ndarray]] – The gradients with respect to
xandy.
Examples
>>> x = Tensor(xp.array([2, 3])) >>> y = Tensor(xp.array([3, 2])) >>> z = x ** y >>> # Gradients for x: y * x^(y-1) and for y: x^y * ln(x)
- __annotations__ = {}¶
- __module__ = 'autograd.tensor'¶
- class autograd.tensor.Matmul(*tensors: Tensor)¶
Bases:
FunctionMatrix multiplication of two tensors. See
autograd.tensor.Tensor.__matmul__()functionExamples
>>> x = Tensor(xp.array([[1, 2], [3, 4]])) >>> y = Tensor(xp.array([[5, 6], [7, 8]])) >>> z = Matmul.apply(x, y) # Expected: [[19, 22], [43, 50]]
- forward(x: Any, y: Any) Any¶
Compute the matrix multiplication of two tensors.
The operation uses
xp.matmul, which handles broadcasting and batching.- Parameters:
x (xp.ndarray) – The first tensor.
y (xp.ndarray) – The second tensor.
- Returns:
xp.ndarray – The result of matrix multiplying
xandy.
- backward(grad: Tensor) Tuple[Any | None, Any | None]¶
Compute the gradient for the matrix multiplication operation.
For matrix multiplication:
\(z = x \cdot y\)
- the gradients are computed as:
$$ \text{grad}_x = \text{grad} \cdot y^T
\[\]\text{grad}_y = x^T \cdot \text{grad} $$
Special handling is provided for the vector @ vector case and for batched multiplications.
- Parameters:
grad (Tensor) – The gradient of the loss with respect to the output.
- Returns:
Tuple[Optional[xp.ndarray], Optional[xp.ndarray]] – The gradients with respect to
xandy.
Examples
>>> x = Tensor(xp.array([[1, 2], [3, 4]])) >>> y = Tensor(xp.array([[5, 6], [7, 8]])) >>> z = x @ y >>> # Backpropagation would compute gradients: >>> grad_x, grad_y = Matmul.apply(x, y).creator.backward(Tensor(xp.ones_like(z.data)))
- __annotations__ = {}¶
- __module__ = 'autograd.tensor'¶
- class autograd.tensor.IAdd(*tensors: Tensor)¶
Bases:
FunctionIn-place addition of two tensors. See
autograd.tensor.Tensor.__iadd__()functionExamples
>>> x = Tensor(xp.array([1, 2, 3])) >>> y = Tensor(xp.array([4, 5, 6])) >>> IAdd.apply(x, y) # Expected: [5, 7, 9]
- forward(x: Any, y: Any) Any¶
Perform in-place addition on the input tensor.
- Parameters:
x (xp.ndarray) – The tensor to be updated.
y (xp.ndarray) – The tensor to add.
- Returns:
xp.ndarray – The updated tensor
xafter addition.
- backward(grad: Tensor) Tuple[Any, Any]¶
Compute the gradient for the in-place addition operation.
Both inputs receive the same gradient as in the standard addition.
- Parameters:
grad (Tensor) – The gradient of the loss with respect to the output.
- Returns:
Tuple[xp.ndarray, xp.ndarray] – The gradients with respect to
xandy.
Examples
>>> x = Tensor(xp.array([1,2,3])) >>> y = Tensor(xp.array([4,5,6])) >>> z = x # In-place addition: x += y >>> z = IAdd.apply(x, y) >>> # Gradients for both x and y would be identical to grad.
- __annotations__ = {}¶
- __module__ = 'autograd.tensor'¶
- class autograd.tensor.GetItem(*tensors: Tensor)¶
Bases:
FunctionRetrieve an item from a tensor using numpy-style indexing. See
autograd.tensor.Tensor.__getitem__()functionExamples
>>> x = Tensor(xp.array([10, 20, 30])) >>> y = GetItem.apply(x, idx=1) # Expected: 20
- forward(x: Any, idx: Any) Any¶
Return a subset of the tensor based on the specified index.
- Parameters:
x (xp.ndarray) – The input tensor.
idx (Any) – The index used to retrieve a subset of
x(e.g., slices, integers).
- Returns:
xp.ndarray – The indexed subset of the tensor.
- backward(grad: Tensor) Any¶
Propagate gradients through the indexing operation.
A zero tensor of the original shape is created and the gradient is placed in the correct location corresponding to the index.
- Parameters:
grad (Tensor) – The gradient of the loss with respect to the output.
- Returns:
xp.ndarray – The gradient with respect to the input tensor.
Examples
>>> x = Tensor(xp.array([10, 20, 30])) >>> y = x[1] >>> # During backprop, only index 1 receives the gradient.
- __annotations__ = {}¶
- __module__ = 'autograd.tensor'¶
- class autograd.tensor.SetItem(*tensors: Tensor)¶
Bases:
FunctionIn-place assignment to a tensor using numpy-style indexing. See
autograd.tensor.Tensor.__setitem__()functionExamples
>>> x = Tensor(xp.array([1, 2, 3])) >>> SetItem.apply(x, Tensor(10, requires_grad=False), idx=1) # Expected: [1, 10, 3]
- forward(x: Any, value: Any, idx: Any) Any¶
Perform in-place assignment on the input tensor.
- Parameters:
x (xp.ndarray) – The input tensor.
idx (Any) – The indices at which to assign the new value.
value (xp.ndarray) – The value to assign.
- Returns:
xp.ndarray – The tensor after assignment.
- backward(grad: Tensor) Any¶
Compute the gradient for the in-place assignment operation.
The gradient is extracted only from the region specified by the index.
- Parameters:
grad (Tensor) – The gradient of the loss with respect to the output.
- Returns:
xp.ndarray – The gradient with respect to the input tensor.
Examples
>>> x = Tensor(xp.array([1, 2, 3])) >>> _ = SetItem.apply(x, Tensor(10, requires_grad=False), idx=1) >>> # During backprop, only index 1 will contribute to the gradient.
- __annotations__ = {}¶
- __module__ = 'autograd.tensor'¶
- class autograd.tensor.Cast(*tensors: Tensor)¶
Bases:
Function- forward(x: Any, dtype: Any) Any¶
Perform the forward pass of this operation.
This method should be overridden by subclasses to define the specific behavior of the operation. It receives NumPy arrays corresponding to the data of the input tensors.
- Parameters:
*args (xp.ndarray) – Data arrays for the input tensors.
**kwargs (Any) – Additional keyword arguments.
- Returns:
xp.ndarray – The result of the forward pass as a NumPy array.
- Raises:
NotImplementedError – If this method is not implemented in a subclass.
- backward(grad: Tensor) Any¶
Perform the backward pass of this operation.
This method should be overridden by subclasses to define how gradients are computed and propagated back to the input tensors.
In this context: - “grad” (the method argument) is the gradient of the loss function with respect to the output of this operation (dL/d[out]). - The return value should be the gradient of the loss function with respect to the input of this operation (dL/d[input]), so it can be passed further back along the computational graph.
- Parameters:
grad (Tensor) – The gradient with respect to the output of this operation.
- Returns:
xp.ndarray – The gradient with respect to the input(s).
- Raises:
NotImplementedError – If this method is not implemented in a subclass.
- __annotations__ = {}¶
- __module__ = 'autograd.tensor'¶
- class autograd.tensor.Sqrt(*tensors: Tensor)¶
Bases:
FunctionCompute the element-wise square root of a tensor. See
autograd.tensor.Tensor.sqrt()functionExamples
>>> x = Tensor(xp.array([4, 9, 16])) >>> y = Sqrt.apply(x) # Expected: [2, 3, 4]
- forward(x: Any) Any¶
Compute the square root of each element in the input tensor.
- Parameters:
x (xp.ndarray) – The input tensor.
- Returns:
xp.ndarray – The element-wise square root of
x.
- backward(grad: Tensor) Any¶
Compute the gradient for the square root operation.
The derivative of the square root is given by:
\[ \frac{d}{dx}\sqrt{x} = \frac{1}{2\sqrt{x}} \]The gradient is computed by multiplying the incoming gradient
gradby this derivative.- Parameters:
grad (Tensor) – The gradient of the loss with respect to the output.
- Returns:
xp.ndarray – The gradient of the loss with respect to the input tensor.
Examples
>>> x = Tensor(xp.array([4, 9, 16])) >>> y = x.sqrt() >>> # If grad is ones, the gradient should be 0.5 / sqrt(x)
- __annotations__ = {}¶
- __module__ = 'autograd.tensor'¶
- class autograd.tensor.Sum(*tensors: Tensor)¶
Bases:
FunctionCompute the sum of tensor elements. See
autograd.tensor.Tensor.sum()functionExamples
>>> x = Tensor(xp.array([[1, 2], [3, 4]])) >>> s = Sum.apply(x, axis=0, keepdims=True) # Expected: Tensor with data [[4, 6]]
- forward(x: Any, axis: int | Tuple[int, ...] | None = None, keepdims: bool = False) Any¶
Compute the forward pass for the sum operation.
- Parameters:
x (xp.ndarray) – Input tensor.
axis (int or tuple of ints, optional) – Axis or axes along which the sum is performed. If None, the sum of all elements is computed.
keepdims (bool, optional) – If True, the reduced axes are kept in the output as dimensions with size one.
- Returns:
xp.ndarray – The sum of the tensor elements.
- backward(grad: Tensor) Any¶
Compute the backward pass for the sum operation.
This method computes the gradient of the sum operation by broadcasting the gradient to the shape of the input tensor.
- Parameters:
grad (Tensor) – The gradient of the loss with respect to the output of the sum operation.
- Returns:
xp.ndarray – The gradient of the loss with respect to the input tensor.
Examples
>>> x = Tensor(xp.array([[1, 2], [3, 4]])) >>> s = x.sum(axis=0) >>> # During backprop, the gradient is broadcast back to shape (2,2)
- __annotations__ = {}¶
- __module__ = 'autograd.tensor'¶
- class autograd.tensor.Max(*tensors: Tensor)¶
Bases:
FunctionSee
autograd.tensor.Tensor.max()functionExamples
>>> x = Tensor(xp.array([[1, 5], [3, 4]])) >>> m = Max.apply(x, axis=0, keepdims=True) # Expected: [[3, 5]]
- forward(x: Any, axis: int | Tuple[int, ...] | None = None, keepdims: bool = False) Any¶
Compute the maximum of tensor elements. :param x: Input tensor. :type x: xp.ndarray :param axis: Axis or axes along which the maximum is computed. If None (default), the maximum of all elements is computed. :type axis: int or tuple of ints, optional :param keepdims: If True, the reduced axes are kept in the output as dimensions with size one. :type keepdims: bool, optional
- Returns:
xp.ndarray – The maximum values computed along the specified axis.
- backward(grad: Tensor) Any¶
Compute the gradient of the maximum operation.
The backward pass for the maximum operation is computed using the chain rule:
\[ \frac{\partial \text{loss}}{\partial x} = \frac{\partial \text{loss}}{\partial \max(x)} \cdot \frac{\partial \max(x)}{\partial x} \]where
\[\begin{split} \frac{\partial \max(x)}{\partial x} = \begin{cases} 1, & \text{if } x = \max(x) \\ 0, & \text{otherwise} \end{cases} \end{split}\]In cases where multiple elements are equal to the maximum, the gradient is distributed equally or assigned to the first occurrence along the specified axis.
- Parameters:
grad (Tensor) – The gradient of the loss with respect to the output of the maximum operation.
- Returns:
xp.ndarray – The gradient of the loss with respect to the input tensor.
Examples
>>> x = Tensor(xp.array([[1, 5], [3, 4]])) >>> m = x.max(axis=0, keepdims=True) >>> # During backprop, gradient is distributed to the positions where x equals the max.
- __annotations__ = {}¶
- __module__ = 'autograd.tensor'¶
- class autograd.tensor.Maximum(*tensors: Tensor)¶
Bases:
FunctionCompute the element-wise maximum between two tensors. See
autograd.tensor.Tensor.maximum()functionExamples
>>> x = Tensor(xp.array([1, 5, 3])) >>> y = Tensor(xp.array([2, 4, 3])) >>> z = Maximum.apply(x, y) # Expected: [2, 5, 3]
- forward(x: Any, y: Any) Any¶
Compute the element-wise maximum of two tensors.
- Parameters:
x (xp.ndarray) – First input tensor.
y (xp.ndarray) – Second input tensor.
- Returns:
xp.ndarray – The element-wise maximum of the two input tensors.
- backward(grad: Tensor) Tuple[Any | None, Any | None]¶
Compute the gradient of the element-wise maximum operation.
During the backward pass, the gradient is distributed to the inputs according to the rule:
\[\begin{split} \frac{\partial \text{loss}}{\partial x} = \text{grad} \times \begin{cases} 1, & \text{if } x > y \\ 0.5, & \text{if } x = y \\ 0, & \text{otherwise} \end{cases} \end{split}\]and similarly for \(y\).
- Parameters:
grad (Tensor) – The gradient of the loss with respect to the output of the maximum operation.
- Returns:
Tuple[Optional[xp.ndarray], Optional[xp.ndarray]] – Gradients of the loss with respect to the input tensors x and y.
Examples
>>> x = Tensor(xp.array([1, 5, 3])) >>> y = Tensor(xp.array([2, 4, 3])) >>> z = x.maximum(y) >>> # Backpropagation would distribute the gradient to x and y based on the maximum rule.
- __annotations__ = {}¶
- __module__ = 'autograd.tensor'¶
- class autograd.tensor.Mean(*tensors: Tensor)¶
Bases:
FunctionCompute the mean of tensor elements. See
autograd.tensor.Tensor.mean()functionExamples
>>> x = Tensor(xp.array([[1, 2], [3, 4]])) >>> m = Mean.apply(x, axis=0) # Expected: [2, 3]
- forward(x: Any, axis: int | Tuple[int, ...] | None = None, keepdims: bool = False) Any¶
Compute the forward pass for the mean operation.
- Parameters:
x (xp.ndarray) – Input tensor.
axis (int or tuple of ints, optional) – Axis or axes along which the mean is computed. If None, the mean of all elements is computed.
keepdims (bool, optional) – If True, the reduced axes are retained in the output as dimensions with size one.
- Returns:
xp.ndarray – The mean of the tensor elements.
- backward(grad: Tensor) Any¶
Compute the gradient of the mean operation.
The gradient is computed by broadcasting the gradient to the shape of the input tensor and scaling it by the number of elements that were averaged:
\[ \frac{\partial \text{loss}}{\partial x} = \frac{\text{grad}}{N} \]where N is the number of elements over which the mean was computed.
- Parameters:
grad (Tensor) – The gradient of the loss with respect to the output of the mean operation.
- Returns:
xp.ndarray – The gradient of the loss with respect to the input tensor.
Examples
>>> x = Tensor(xp.array([[1, 2], [3, 4]])) >>> m = x.mean() >>> # During backprop, the gradient is divided by the number of elements.
- __annotations__ = {}¶
- __module__ = 'autograd.tensor'¶
- class autograd.tensor.Gather(*tensors: Tensor)¶
Bases:
FunctionGather operation for 2D tensors along axis 0 using integer indices. See
autograd.tensor.Tensor.gather()functionExamples
>>> x = Tensor(xp.array([[10, 20], [30, 40], [50, 60]])) >>> g = Gather.apply(x, index=xp.array([0, 2])) >>> print(g.data) [[10, 20], [50, 60]]
- forward(x: Any, index: Any) Any¶
Perform the forward pass of the gather operation.
- Parameters:
x (xp.ndarray) – The input 2D tensor.
index (xp.ndarray) – An array of integer indices specifying the rows to gather.
- Returns:
xp.ndarray – A tensor containing the gathered rows.
- backward(grad: Tensor) Tuple[Any, None]¶
Perform the backward pass of the gather operation.
The backward pass accumulates the gradients from the output back into the corresponding rows of the input tensor using numpy’s in-place addition.
- Parameters:
grad (Tensor) – The gradient of the loss with respect to the output.
- Returns:
Tuple[xp.ndarray, None] – A tuple where the first element is the gradient with respect to the input tensor, and the second element is None. (since indices are not differentiable).
Examples
>>> x = Tensor(xp.array([[10, 20], [30, 40], [50, 60]])) >>> g = x.gather(xp.array([0, 2])) >>> # Backpropagated gradient will be placed in rows 0 and 2 of a zero tensor.
- __annotations__ = {}¶
- __module__ = 'autograd.tensor'¶
- class autograd.tensor.View(*tensors: Tensor)¶
Bases:
FunctionView the tensor with a new shape without copying data. See
autograd.tensor.Tensor.view()functionExamples
>>> x = Tensor(xp.array([1, 2, 3, 4])) >>> v = View.apply(x, new_shape=(2,2)) >>> print(v.data.shape) # Expected: (2, 2)
- forward(x: Any, new_shape: Tuple[int, ...] | List[int] = (1,)) Any¶
Reshape the input tensor to a new view with the specified shape.
- Parameters:
x (xp.ndarray) – The input tensor.
new_shape (Union[Tuple[int, ...], List[int]], optional) – The desired new shape. If a -1 is present, that dimension is inferred from the size of the input tensor. Defaults to (1,).
- Returns:
xp.ndarray – A view of the tensor with the specified new shape.
- Raises:
ValueError – If more than one -1 is specified or if the new shape is incompatible with the total number of elements in x.
- backward(grad: Tensor | None) Any | None¶
Reshape the gradient to match the original tensor shape.
- Parameters:
grad (Tensor, optional) – The gradient of the loss with respect to the output.
- Returns:
Optional[xp.ndarray] – The gradient reshaped to the original tensor shape, or None if grad is None.
Examples
>>> x = Tensor(xp.array([1,2,3,4])) >>> v = x.view(2,2) >>> # Backward pass would reshape grad from (2,2) back to original shape.
- __annotations__ = {}¶
- __module__ = 'autograd.tensor'¶
- class autograd.tensor.Expand(*tensors: Tensor)¶
Bases:
FunctionExpand the tensor to a given shape without copying data (broadcasting). See
autograd.tensor.Tensor.expand()functionExamples
>>> x = Tensor(xp.array([1,2,3])) >>> e = Expand.apply(x, shape=(3,3)) # Expected: array where each row is [1,2,3]
- forward(x: Any, shape: Tuple[int, ...] | List[int] = (1,)) Any¶
Broadcast the input tensor to the specified shape.
- Parameters:
x (xp.ndarray) – The input tensor.
shape (Union[Tuple[int, ...], List[int]], optional) – The target shape for broadcasting. Defaults to (1,).
- Returns:
xp.ndarray – A new tensor broadcast to the specified shape.
- backward(grad: Tensor) Any¶
Compute the gradient of the expand operation.
The gradient is reduced by summing over the broadcast dimensions so that its shape matches the original input tensor.
- Parameters:
grad (Tensor) – The gradient of the loss with respect to the output.
- Returns:
xp.ndarray – The gradient of the loss with respect to the input tensor.
Examples
>>> x = Tensor(xp.array([1,2,3])) >>> e = x.expand(3, 3) >>> # Backward pass would sum gradients over broadcasted dimensions.
- __annotations__ = {}¶
- __module__ = 'autograd.tensor'¶
- class autograd.tensor.Reshape(*tensors: Tensor)¶
Bases:
FunctionReshape the tensor to a new shape without changing its data content. See
autograd.tensor.Tensor.reshape()functionExamples
>>> x = Tensor(xp.array([[1,2],[3,4]])) >>> r = Reshape.apply(x, shape=(4,)) >>> print(r.data) # Expected: [1, 2, 3, 4]
- forward(x: Any, shape: Tuple[int, ...] | List[int] = (1,)) Any¶
Reshape the input tensor to the specified new shape.
- Parameters:
x (xp.ndarray) – The input tensor.
shape (Union[Tuple[int, ...], List[int]], optional) – The new shape for the tensor. If a nested tuple or list is provided, it will be flattened. Defaults to (1,).
- Returns:
xp.ndarray – The reshaped tensor.
- backward(grad: Tensor | None) Any | None¶
Reshape the gradient to match the original tensor shape.
- Parameters:
grad (Tensor, optional) – The gradient of the loss with respect to the reshaped output.
- Returns:
Optional[xp.ndarray] – The gradient reshaped to the original tensor shape, or None if grad is None.
Examples
>>> x = Tensor(xp.array([[1,2],[3,4]])) >>> r = x.reshape(4) >>> # Backward would reshape grad from shape (4,) to (2,2)
- __annotations__ = {}¶
- __module__ = 'autograd.tensor'¶
- class autograd.tensor.Transpose(*tensors: Tensor)¶
Bases:
FunctionTranspose operation for swapping any two dimensions of a tensor. See
autograd.tensor.Tensor.transpose()functionExamples
>>> x = Tensor(xp.array([[1, 2], [3, 4]])) >>> t = Transpose.apply(x, dim0=0, dim1=1) >>> print(t.data) # Expected: [[1, 3], [2, 4]]
- forward(x: Any, dim0: int = 0, dim1: int = 1) Any¶
Transpose the input tensor by swapping two specified dimensions.
- Parameters:
x (xp.ndarray) – The input tensor.
dim0 (int, optional) – The first dimension to swap. Defaults to 0.
dim1 (int, optional) – The second dimension to swap. Defaults to 1.
- Returns:
xp.ndarray – The transposed tensor.
- Raises:
ValueError – If the specified dimensions are out of range for the input tensor.
- backward(grad: Tensor) Any¶
Transpose the gradient tensor to match the original input tensor’s dimension order.
- Parameters:
grad (Tensor) – The gradient of the loss with respect to the output tensor.
- Returns:
xp.ndarray – The gradient with dimensions swapped back to their original order.
Examples
>>> x = Tensor(xp.array([[1,2],[3,4]])) >>> t = x.transpose(0,1) >>> # Backward would apply the inverse transpose.
- __annotations__ = {}¶
- __module__ = 'autograd.tensor'¶
- class autograd.tensor.Pad(*tensors: Tensor)¶
Bases:
FunctionPad the tensor with a specified padding. See
autograd.tensor.Tensor.pad()functionExamples
>>> x = Tensor(xp.array([[1, 2], [3, 4]])) >>> p = Pad.apply(x, pad_width=1, mode="constant", constant_values=0) # Expected padded tensor with zeros around the original data.
- forward(x: Any, pad_width: int | Tuple[int, int] | Tuple[int, int, int, int] | Tuple[Tuple[int, int], ...], mode: str = 'constant', constant_values: int | float = 0) Any¶
Pad the input tensor according to the specified pad width and mode.
- Parameters:
x (xp.ndarray) – The input tensor.
pad_width (int or tuple) – Padding specification. See class docstring for details.
mode (str, optional) – Padding mode. Defaults to “constant”.
constant_values (int or float, optional) – Value for constant padding. Defaults to 0.
- Returns:
xp.ndarray – The padded tensor.
- backward(grad: Tensor) Any¶
Extract the unpadded region from the gradient.
This method removes the padding from the gradient tensor, returning only the region corresponding to the original input tensor.
- Parameters:
grad (Tensor) – The gradient of the loss with respect to the padded output.
- Returns:
xp.ndarray – The gradient corresponding to the unpadded input.
Examples
>>> x = Tensor(xp.array([[1,2],[3,4]])) >>> p = x.pad(1, mode="constant", constant_values=0) >>> # During backprop, the gradient will be unpadded to match x.
- __annotations__ = {}¶
- __module__ = 'autograd.tensor'¶
- class autograd.tensor.Cat(*tensors: Tensor)¶
Bases:
FunctionConcatenate a sequence of tensors along a specified axis. See
autograd.tensor.Tensor.cat()functionExamples
>>> x = Tensor(xp.array([[1, 2]])) >>> y = Tensor(xp.array([[3, 4]])) >>> c = Cat.apply(x, y, axis=0) # Expected: [[1,2],[3,4]]
- forward(*tensors: Any, axis: int = 0) Any¶
Concatenate input tensors along the specified axis.
- Parameters:
*tensors (Tensor) – A sequence of tensors to concatenate.
axis (int, optional) – The axis along which to concatenate. Defaults to 0.
- Returns:
xp.ndarray – The concatenated tensor.
- backward(grad: Tensor) Tuple[Any | None, ...]¶
Split the gradient among the concatenated tensors.
The gradient is divided along the concatenation axis based on the original shapes of the input tensors.
- Parameters:
grad (Tensor) – The gradient of the loss with respect to the concatenated output.
- Returns:
Tuple[Optional[xp.ndarray], …] – A tuple of gradients corresponding to each input tensor.
Examples
>>> x = Tensor(xp.array([[1, 2]])) >>> y = Tensor(xp.array([[3, 4]])) >>> c = Tensor.cat([x, y], axis=0) >>> # Backward pass would split the gradient along axis 0.
- __annotations__ = {}¶
- __module__ = 'autograd.tensor'¶
- class autograd.tensor.Permute(*tensors: Tensor)¶
Bases:
FunctionReorder the dimensions of a tensor. See
autograd.tensor.Tensor.permute()functionExamples
>>> x = Tensor(xp.array([[[1,2],[3,4]], [[5,6],[7,8]]])) # shape (2,2,2) >>> p = Permute.apply(x, dims=(1,0,2)) >>> print(p.data.shape) # Expected shape: (2,2,2) with dimensions permuted.
- forward(x: Any, dims: Sequence[int]) Any¶
Permute the dimensions of the input tensor.
- Parameters:
x (xp.ndarray) – The input tensor.
dims (Sequence[int]) – The new order of dimensions. If a single element that is a tuple or list is provided, it will be unpacked.
- Returns:
xp.ndarray – The tensor with permuted dimensions.
- backward(grad: Tensor) Any¶
Compute the gradient for the permutation operation.
The gradient is transposed using the inverse permutation of the forward pass.
- Parameters:
grad (Tensor) – The gradient of the loss with respect to the permuted output.
- Returns:
xp.ndarray – The gradient with dimensions restored to their original order.
Examples
>>> x = Tensor(xp.array([[1,2],[3,4]])) >>> p = x.permute(1,0) >>> # Backward would transpose the gradient back.
- __annotations__ = {}¶
- __module__ = 'autograd.tensor'¶
- class autograd.tensor.Stack(*tensors: Tensor)¶
Bases:
FunctionStack a sequence of tensors along a new axis. See
autograd.tensor.Tensor.stack()functionExamples
>>> x = Tensor(xp.array([1,2])) >>> y = Tensor(xp.array([3,4])) >>> s = Stack.apply(x, y, axis=0) # Expected: [[1,2],[3,4]]
- forward(*tensors: Any, axis: int = 0) Any¶
Stack input tensors along a new axis.
This method expands the dimensions of each input tensor along the specified axis and concatenates them.
- Parameters:
*tensors (Tensor) – A sequence of tensors to be stacked.
axis (int, optional) – The axis along which to stack the tensors. Defaults to 0.
- Returns:
xp.ndarray – The stacked tensor.
- Raises:
ValueError – If no tensors are provided.
- backward(grad: Tensor) Tuple[Any | None, ...]¶
Split the gradient among the stacked tensors.
The gradient is divided along the stacking axis and reshaped to match each input tensor’s original shape.
- Parameters:
grad (Tensor) – The gradient of the loss with respect to the stacked tensor.
- Returns:
Tuple[Optional[xp.ndarray], …] – A tuple of gradients corresponding to each input tensor.
Examples
>>> x = Tensor(xp.array([1,2])) >>> y = Tensor(xp.array([3,4])) >>> s = Tensor.stack([x, y], axis=0) >>> # Backward pass would split grad along the new axis.
- __annotations__ = {}¶
- __module__ = 'autograd.tensor'¶
- class autograd.tensor.StridedWindows(*tensors: Tensor)¶
Bases:
FunctionCreate a strided windows view of a tensor. See
autograd.tensor.Tensor.strided_windows()functionExamples
>>> x = Tensor(xp.random.rand(2, 3, 10, 10)) >>> windows = StridedWindows.apply(x, kernel_size=3, stride=1) >>> print(windows.shape) (8, 8, 2, 3, 3, 3)
- forward(x: Any, kernel_size: int, stride: int) Any¶
Create a strided windows view of the input tensor.
- Parameters:
x (xp.ndarray) – The input tensor of shape (batch_size, channels, height, width).
kernel_size (int) – The size of each window.
stride (int) – The stride between windows.
- Returns:
xp.ndarray – A view of the tensor with shape
\((H_{out}, W_{out}, batch\_size, channels, kernel\_size, kernel\_size)\), where \(H_{out} = \frac{height - kernel\_size}{stride} + 1\) and \(W_{out} = \frac{width - kernel\_size}{stride} + 1\).
- backward(grad: Tensor) Any¶
Reconstruct the gradient for the input tensor from the strided windows gradient.
This method reshapes and transposes the gradient of the strided windows view back to the original input tensor shape by accumulating overlapping gradients.
- Parameters:
grad (Tensor) – The gradient of the loss with respect to the strided windows output.
- Returns:
xp.ndarray – The gradient of the loss with respect to the original input tensor.
Examples
>>> x = Tensor(xp.random.rand(2, 3, 10, 10)) >>> windows = x.strided_windows(kernel_size=3, stride=1) >>> # Backward pass would accumulate gradients from overlapping windows.
- __annotations__ = {}¶
- __module__ = 'autograd.tensor'¶
- class autograd.tensor.Roll(*tensors: Tensor)¶
Bases:
FunctionRoll tensor elements along a specified dimension. See
autograd.tensor.Tensor.roll()functionExamples
>>> x = Tensor(xp.array([1,2,3,4,5])) >>> r = Roll.apply(x, shifts=2, dims=0) # Expected: [4,5,1,2,3]
- __annotations__ = {}¶
- __module__ = 'autograd.tensor'¶
- forward(x: Any, shifts: int, dims: int | None = None) Any¶
Roll the elements of the input tensor.
- Parameters:
x (xp.ndarray) – The input tensor.
shifts (int) – The number of positions to shift the elements.
dims (int, optional) – The axis along which to roll the elements. If None, the tensor is flattened before rolling.
- Returns:
xp.ndarray – The tensor with its elements rolled along the specified dimension.
- backward(grad: Tensor) Any¶
Perform the backward pass for the roll operation.
The gradient is rolled in the opposite direction (by negating the shift) to reverse the forward roll.
- Parameters:
grad (Tensor) – The gradient of the loss with respect to the rolled output.
- Returns:
xp.ndarray – The gradient of the loss with respect to the input tensor.
Examples
>>> x = Tensor(xp.array([1,2,3,4,5])) >>> r = x.roll(shifts=2, dims=0) >>> # Backward would roll grad in the opposite direction.
autograd.nn module¶
- class autograd.nn.Module(*args, **kwargs)¶
Bases:
objectBase class for all neural network modules.
This class provides mechanisms for registering parameters, submodules, and states, and implements common functionality such as zero_grad, forward, and state dict management.
Note that we don’t implement the backward() function in this Module class, because all the backward() functions are implemented at the tensor-level operations. And the forward functions are just piecing together tensor-level operations like lego.
- _states¶
Dictionary of non-trainable states/buffers.
- Type:
Dict[str, Any]
- _is_training¶
Flag indicating training mode.
- Type:
Optional[bool]
Examples
>>> # Define a simple custom module by subclassing Module. >>> class MyModule(Module): ... def forward(self, x): ... return x * 2 >>> module = MyModule() >>> import cupy as np >>> from autograd.tensor import Tensor >>> input_tensor = Tensor(xp.array([1, 2, 3])) >>> output = module(input_tensor) # Expected output: [2, 4, 6]
- zero_grad() None¶
Zero the gradients for all parameters in the module and its submodules.
Examples
>>> # Assuming module has trainable parameters with gradients. >>> module.zero_grad()
- abstractmethod forward(x: Any) Tensor¶
Perform the forward pass.
- Parameters:
x (Any) – Input data.
- Returns:
Tensor – The output tensor after going through the forward pass
- Raises:
NotImplementedError – If the method is not overridden by a subclass.
Examples
>>> class MyModule(Module): ... def forward(self, x): ... return x + 1 >>> module = MyModule() >>> from autograd.tensor import Tensor >>> import cupy as np >>> x = Tensor(xp.array([1, 2, 3])) >>> y = module(x) # Expected: [2, 3, 4]
- apply(func: Callable) None¶
Apply a function recursively to every submodule in-place. This can be useful for dynamically adjusting the gradient or parameters of the model. E.g. Clipping gradient norms, setting parameters to a specific value, etc.
- Parameters:
func (Callable) – A function that takes a Module and applies some operation.
Examples
>>> # Example: print the type of each module. >>> def print_module(m): ... print(type(m)) >>> module.apply(print_module)
- property parameters: Dict[str, Any]¶
Get a flattened dictionary of all trainable parameters from the module and its submodules.
{ "weight": "Tensor", "submodule1.weight": "Tensor" }
- Returns:
Dict[str, Any] – A dictionary mapping parameter names to Tensor objects.
Examples
>>> # Assuming module has parameters 'weight' and a submodule with 'bias' >>> params = module.parameters >>> print(params.keys())
- property states: Dict[str, Any]¶
Get a flattened dictionary of all non-trainable states or buffers from the module and its submodules.
{ "some_state": "array", "submodule1.running_var": "array" }
- Returns:
Dict[str, Any] – A dictionary mapping state names to their values.
Examples
>>> # Assuming module has a state 'running_mean' in a BatchNorm submodule. >>> states = module.states >>> print(states)
- state_dict() Dict[str, Dict[str, Any]]¶
Return a state dictionary of the module.
- The state dictionary contains two keys:
“parameters”: A dictionary mapping parameter names to their raw arrays.
“states”: A dictionary mapping state names to their values.
- Returns:
Dict[str, Dict[str, Any]] – The state dictionary.
{ "parameters": { "weight": "array", "bias": "array" }, "states": { "stateful_states": "array" } }
Examples
>>> state = module.state_dict() >>> print(state.keys()) # Expected output: dict_keys(['parameters', 'states'])
- load_state_dict(state_dict: Dict[str, Any], strict: bool = True) None¶
Load the module’s state from a state dictionary.
Expects a dict of the form:
{ "parameters": { "weight": "array", "bias": "array" }, "states": { "stateful_states": "array" } }
- Parameters:
state_dict (Dict[str, Any]) – A dictionary containing the module’s parameters and states.
strict (bool) – If True, parameter/state keys must match the current module.
Examples
>>> # Save a state dictionary and later load it into the module. >>> state = module.state_dict() >>> module.load_state_dict(state)
- num_parameters() int¶
Calculate the total number of trainable parameters in the module and its submodules.
- Returns:
int – The total number of parameters.
Examples
>>> print(module.num_parameters())
- train() None¶
Set the module and all its submodules to training mode.
Examples
>>> module.train()
- eval() None¶
Set the module and all its submodules to evaluation mode.
Examples
>>> module.eval()
- class autograd.nn.ModuleList(modules=None)¶
Bases:
ModuleA container for holding submodules in a list-like structure.
This container registers each submodule so that they are included in the module’s parameters and state dictionaries.
Examples
>>> # Create a ModuleList with two simple modules. >>> class MyModule(Module): ... def forward(self, x): ... return x + 1 >>> ml = ModuleList([MyModule(), MyModule()]) >>> for m in ml: ... print(m.forward(Tensor(xp.array([1]))).data) [2] [2]
- class autograd.nn.Linear(input_size: int, output_size: int, **kwargs: Any)¶
Bases:
ModuleA linear (fully connected) layer.
- This layer performs a linear transformation:
- \[ y = xW + b \]
where \(W\) is the weight matrix and \(b\) is the bias.
Examples
>>> linear = Linear(4, 2) >>> import cupy as np >>> from autograd.tensor import Tensor >>> x = Tensor(xp.random.randn(3, 4)) >>> y = linear(x) # Expected shape: (3, 2)
- forward(x: Tensor | Any | Sequence[Any] | int | float | bool) Tensor¶
Compute the forward pass of the Linear layer.
- Parameters:
x (Union[Tensor, xp.ndarray]) – The input tensor.
- Returns:
Tensor – The result of the linear transformation.
Examples
>>> linear = Linear(5, 3) >>> import cupy as np >>> x = Tensor(xp.random.randn(10, 5)) >>> y = linear(x) # Expected: (10, 3)
- class autograd.nn.Conv2d(in_channels: int, out_channels: int, kernel_size: int, stride: int = 1, padding_mode: str = 'valid', bias: bool = True, **kwargs: Any)¶
Bases:
ModuleA 2D convolutional layer.
This layer applies a convolution operation over a 4D input tensor with shape (N, in_channels, H, W) and produces an output tensor with shape (N, out_channels, H_out, W_out).
Examples
>>> conv = Conv2d(in_channels=3, out_channels=8, kernel_size=3, stride=1, padding_mode="same") >>> import cupy as np >>> from autograd.tensor import Tensor >>> x = Tensor(xp.random.randn(2, 3, 32, 32)) >>> y = conv(x) # Expected shape: (2, 8, 32, 32)
- forward(x: Tensor | Any | Sequence[Any] | int | float | bool) Tensor¶
Compute the forward pass of the Conv2d layer.
- Parameters:
x (Union[Tensor, xp.ndarray]) – Input tensor of shape (N, in_channels, H, W).
- Returns:
Tensor – Output tensor after applying the convolution and bias addition.
Examples
>>> conv = Conv2d(3, 8, kernel_size=3, stride=1, padding_mode="same") >>> import cupy as np >>> from autograd.tensor import Tensor >>> x = Tensor(xp.random.randn(2, 3, 32, 32)) >>> y = conv(x) # Expected: (2, 8, 32, 32)
- class autograd.nn.MaxPool2d(kernel_size: int, stride: int | None = None, padding_mode: str = 'valid', **kwargs: Any)¶
Bases:
ModuleA 2D max pooling layer.
This layer performs max pooling over a sliding window of the input tensor.
Examples
>>> pool = MaxPool2d(kernel_size=2, stride=2, padding_mode="valid") >>> import cupy as np >>> from autograd.tensor import Tensor >>> x = Tensor(xp.random.randn(1, 3, 32, 32)) >>> y = pool(x) # Expected: (1, 3, 16, 16)
- forward(x: Tensor | Any | Sequence[Any] | int | float | bool) Tensor¶
Compute the forward pass of the MaxPool2d layer.
- Parameters:
x (Union[Tensor, xp.ndarray]) – Input tensor.
- Returns:
Tensor – Tensor after applying max pooling.
Examples
>>> pool = MaxPool2d(kernel_size=2, stride=2) >>> import cupy as np >>> from autograd.tensor import Tensor >>> x = Tensor(xp.random.randn(1, 3, 32, 32)) >>> y = pool(x) # Expected: (1, 3, 16, 16)
- class autograd.nn.ResidualBlock(in_channels: int, out_channels: int, stride: int = 1)¶
Bases:
ModuleResidual Block.
- Implements a residual block that computes:
- \[ H(x) = F(x) + x \]
where x is the identity mapping. H(x) = F(x) + x, where x is the identity mapping. Paper: https://arxiv.org/abs/1512.03385
Currently this wraps the Convolution block inside. TODO: Remove the convolutional block
Examples
>>> res_block = ResidualBlock(16, 16, stride=1) >>> import cupy as np >>> from autograd.tensor import Tensor >>> x = Tensor(xp.random.randn(1, 16, 32, 32)) >>> y = res_block(x) # Expected: (1, 16, 32, 32)
- forward(x: Tensor | Any | Sequence[Any] | int | float | bool) Tensor¶
Compute the forward pass of the ResidualBlock.
- Parameters:
x (Union[Tensor, xp.ndarray]) – Input tensor.
- Returns:
Tensor – Output tensor after applying the residual block.
Examples
>>> res_block = ResidualBlock(16, 16) >>> import cupy as np >>> from autograd.tensor import Tensor >>> x = Tensor(xp.random.randn(1, 16, 32, 32)) >>> y = res_block(x) # Expected: (1, 16, 32, 32)
- class autograd.nn.RecurrentBlock(input_size: int, hidden_size: int, output_size: int | None = None, dropout_prob: float | None = None)¶
Bases:
ModuleRecurrent Neural Network (RNN) block.
Implements a simple RNN that processes a sequence and returns either the final hidden state or an output computed from the final hidden state if output_size is specified. Paper: https://arxiv.org/abs/1308.0850
Examples
>>> rnn = RecurrentBlock(input_size=4, hidden_size=8, output_size=2) >>> import cupy as np >>> from autograd.tensor import Tensor >>> # Create a random sequence: batch_size=3, sequence_length=5, input_size=4 >>> x = Tensor(xp.random.randn(3, 5, 4)) >>> y = rnn(x) # Expected: (3, 2)
- forward(x: Tensor | Any | Sequence[Any] | int | float | bool) Tensor¶
Perform the forward pass of the RNN.
- Parameters:
x (Union[Tensor, xp.ndarray]) – Input tensor of shape (batch_size, sequence_length, input_size).
- Returns:
Tensor – Output tensor computed from the final hidden state or the hidden state itself.
Examples
>>> rnn = RecurrentBlock(input_size=4, hidden_size=8, output_size=3) >>> import cupy as np >>> from autograd.tensor import Tensor >>> x = Tensor(xp.random.randn(3, 5, 4)) >>> y = rnn(x) # Expected: (3, 3)
- class autograd.nn.LongShortTermMemoryBlock(input_size: int, hidden_size: int, output_size: int | None = None, dropout_prob: float | None = None)¶
Bases:
ModuleLong Short-Term Memory (LSTM) block.
Implements an LSTM that processes a sequence and returns the final output and cell state.
Paper: https://www.bioinf.jku.at/publications/older/2604.pdf
Examples
>>> lstm = LongShortTermMemoryBlock(input_size=4, hidden_size=8, output_size=3) >>> import cupy as np >>> from autograd.tensor import Tensor >>> x = Tensor(xp.random.randn(3, 5, 4)) >>> output, cell_state = lstm(x) >>> print(output.data.shape) # Expected: (3, 3) >>> print(cell_state.data.shape) # Expected: (3, 8)
- forward(x: Tensor | Any | Sequence[Any] | int | float | bool, hidden_state: Tensor | None = None, C_t: Tensor | None = None) Tuple[Tensor, Tensor]¶
Perform the forward pass of the LSTM.
- Parameters:
- Returns:
Tuple[Tensor, Tensor] – A tuple containing the output and the final cell state.
Examples
>>> lstm = LongShortTermMemoryBlock(input_size=4, hidden_size=8, output_size=3) >>> import cupy as np >>> from autograd.tensor import Tensor >>> x = Tensor(xp.random.randn(3, 5, 4)) >>> output, cell_state = lstm(x) >>> print(output.data.shape) # Expected: (3, 3) >>> print(cell_state.data.shape) # Expected: (3, 8)
- class autograd.nn.Embedding(input_size: int, embedding_size: int)¶
Bases:
ModuleEmbedding layer that projects an arbitrary input_size down to embedding_size.
Examples
>>> embed = Embedding(input_size=100, embedding_size=16) >>> import cupy as np >>> from autograd.tensor import Tensor >>> # Create a batch of indices with shape (batch_size, seq_len) >>> x = Tensor(xp.array([[1, 5, 20], [2, 10, 30]])) >>> y = embed(x) # Expected: (2, 3, 16)
- forward(x: Tensor | Any | Sequence[Any] | int | float | bool) Tensor¶
Perform the forward pass of the Embedding layer.
- Parameters:
x (Union[Tensor, xp.ndarray]) – Input tensor of shape (batch_size, seq_len).
- Returns:
Tensor – Output tensor of shape (batch_size, seq_len, embedding_size).
Examples
>>> embed = Embedding(input_size=50, embedding_size=8) >>> import cupy as np >>> from autograd.tensor import Tensor >>> x = Tensor(xp.array([[0, 1, 2], [3, 4, 5]])) >>> y = embed(x) # Expected: (2, 3, 8)
- class autograd.nn.LayerNorm(input_size: int, epsilon: float = 1e-05, **kwargs: Any)¶
Bases:
ModuleLayer Normalization.
Normalizes the summed inputs to neurons for each training example. Paper: https://arxiv.org/abs/1607.06450
Examples
>>> ln = LayerNorm(input_size=10) >>> import cupy as np >>> from autograd.tensor import Tensor >>> x = Tensor(xp.random.randn(4, 10)) >>> y = ln(x) # Expected: (4, 10)
- forward(x: Tensor) Tensor¶
Perform the forward pass of LayerNorm.
- Parameters:
x (Tensor) – Input tensor.
- Returns:
Tensor – Normalized tensor scaled and shifted by learnable parameters.
Examples
>>> ln = LayerNorm(input_size=10) >>> import cupy as np >>> from autograd.tensor import Tensor >>> x = Tensor(xp.random.randn(2, 10)) >>> y = ln(x) # Expected: (2, 10)
- class autograd.nn.BatchNorm(input_size: int, momentum: float = 0.1, epsilon: float = 1e-05, **kwargs: Any)¶
Bases:
ModuleBatch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift.
Normalizes the input tensor by subtracting the batch mean and dividing by the batch standard deviation. Paper: http://arxiv.org/abs/1502.03167
Examples
>>> bn = BatchNorm(input_size=10) >>> import cupy as np >>> from autograd.tensor import Tensor >>> x = Tensor(xp.random.randn(4, 10)) >>> y = bn(x) # Expected: (4, 10)
- forward(x: Tensor) Tensor¶
Perform the forward pass of BatchNorm.
Note that the backward pass is implemented via primitive operations in the Tensor class. The operations in the forward pass have all been implemented as Tensor-level operations.
- Parameters:
x (Tensor) – Input tensor.
- Returns:
Tensor – Normalized tensor with learnable scaling and shifting.
Examples
>>> bn = BatchNorm(input_size=10) >>> import cupy as np >>> from autograd.tensor import Tensor >>> x = Tensor(xp.random.randn(4, 10)) >>> y = bn(x) # Expected: (4, 10)
- class autograd.nn.Dropout(p: float = 0.5, **kwargs: Any)¶
Bases:
ModuleDropout layer.
Randomly sets a fraction of input units to 0 during training to prevent overfitting. “It prevents overfitting and provides a way of approximately combining exponentially many different neural network architectures efficiently.” Paper: https://arxiv.org/abs/1207.0580
Examples
>>> dropout = Dropout(p=0.5) >>> import cupy as np >>> from autograd.tensor import Tensor >>> x = Tensor(xp.ones((4, 4))) >>> dropout.train() # Set to training mode to apply dropout >>> y = dropout(x) # Approximately half of the elements should be 0
- forward(x: Tensor) Tensor¶
Perform the forward pass of Dropout.
- Parameters:
x (Tensor) – Input tensor.
- Returns:
Tensor – Tensor after applying dropout (only during training).
Examples
>>> dropout = Dropout(p=0.5) >>> dropout.train() >>> import cupy as np >>> from autograd.tensor import Tensor >>> x = Tensor(xp.ones((2, 2))) >>> y = dropout(x) # Approximately half of the values in y should be zero
- class autograd.nn.ScaledDotProductAttention(dropout_prob: float = 0.1)¶
Bases:
ModuleScaled Dot-Product Attention layer.
Computes attention scores as:
\[ \text{Attention}(Q, K, V) = \text{softmax}\left(\frac{QK^T}{\sqrt{key\_dim}}\right) V \]Implements the Scaled Dot-Product Attention in Section 3.2.1 in paper: https://arxiv.org/abs/1706.03762
Examples
>>> attn = ScaledDotProductAttention(dropout_prob=0.1) >>> import cupy as np >>> from autograd.tensor import Tensor >>> # Create dummy query, key, value tensors with shape (batch_size, num_heads, seq_len, key_dim) >>> query = Tensor(xp.random.randn(2, 2, 4, 8)) >>> key = Tensor(xp.random.randn(2, 2, 4, 8)) >>> value = Tensor(xp.random.randn(2, 2, 4, 8)) >>> y = attn(query, key, value) # Expected shape: (2, 2, 4, 8)
- forward(query: Tensor, key: Tensor, value: Tensor, mask: Tensor | Any | Sequence[Any] | int | float | bool | None = None, is_causal: bool = False) Tensor¶
Compute the scaled dot-product attention.
- Parameters:
query (Tensor) – Query tensor.
key (Tensor) – Key tensor.
value (Tensor) – Value tensor.
mask (Optional[Union[Tensor, ArrayLike]], optional) – Attention mask. The dense repo contract uses additive float masks where 1.0 means forbidden and 0.0 means allowed. Raw backend bool masks are also accepted and routed through the implementation-specific gating logic before falling back to dense when unsupported. Defaults to None.
is_causal (bool, optional) – Whether to apply structural causal masking when no explicit mask is supplied. Defaults to False.
- Returns:
Tensor – The attended output.
Examples
>>> attn = ScaledDotProductAttention() >>> import cupy as np >>> from autograd.tensor import Tensor >>> query = Tensor(xp.random.randn(2, 2, 4, 8)) >>> key = Tensor(xp.random.randn(2, 2, 4, 8)) >>> value = Tensor(xp.random.randn(2, 2, 4, 8)) >>> output = attn(query, key, value) # Expected: (2, 2, 4, 8)
- class autograd.nn.MultiHeadAttention(num_heads: int, hidden_size: int, dropout_prob: float = 0.1)¶
Bases:
ModuleMulti-Head Attention layer.
Instead of performing a single attention with hidden_size keys, query, and values, we project them “num_heads” times with different learned linear projects Implements the Multi-Head Attention in Section 3.2.2 in the paper: https://arxiv.org/abs/1706.03762
Examples
>>> mha = MultiHeadAttention(num_heads=2, hidden_size=16, dropout_prob=0.1) >>> import cupy as np >>> from autograd.tensor import Tensor >>> # Create dummy input tensors with shape (batch_size, seq_len, hidden_size) >>> x = Tensor(xp.random.randn(2, 5, 16)) >>> output = mha(x, x, x) # Expected: (2, 5, 16)
- forward(query: Tensor, key: Tensor, value: Tensor, mask: Tensor | None = None, is_causal: bool = False) Tensor¶
Compute the forward pass of the MultiHeadAttention layer.
- Parameters:
- Returns:
Tensor – Output tensor after multi-head attention.
Examples
>>> mha = MultiHeadAttention(num_heads=2, hidden_size=16) >>> import cupy as np >>> from autograd.tensor import Tensor >>> x = Tensor(xp.random.randn(2, 5, 16)) >>> output = mha(x, x, x) # Expected: (2, 5, 16)
- class autograd.nn.AbstractLLMForwardFn¶
Bases:
ABCAbstract interface for a language modeling forward function.
Subclasses should implement the sample and train methods.
The trainer treats batch_data as opaque and relies on the forward function to interpret architecture-specific batch objects. This keeps the LM training loop shared across decoder-only and encoder-decoder models without forcing a universal batch dict or tuple shape.
Examples
>>> # Example subclass implementing the abstract methods. >>> class DummyLLMForward(AbstractLLMForwardFn): ... def sample(self, model, batch_data): ... return model(batch_data) ... def train(self, model, batch_data): ... return model(batch_data.input_ids) >>> forward_fn = DummyLLMForward() >>> # Now forward_fn can be used as: forward_fn(model, data, mode="train")
- abstractmethod sample(model: Any, batch_data: Any) Any¶
Generate samples from the model.
- Parameters:
model (Any) – The model to sample from.
batch_data (Any) – Data for the current batch.
- Returns:
Any – Model outputs for sampling mode.
- abstractmethod train(model: Any, batch_data: Any) Any¶
Compute the forward pass for training.
- Parameters:
model (Any) – The model to train.
batch_data (Any) – Data for the current batch.
- Returns:
Any – Training-mode model outputs, typically logits.
- autograd.nn.extract_windows(x: Tensor | Any | Sequence[Any] | int | float | bool, kernel_size: int, stride: int, padding_mode: str = 'valid') Tuple[Tensor, Tuple[int, int]]¶
Extract sliding windows from the input tensor while maintaining the computational graph.
- Parameters:
x (Union[Tensor, xp.ndarray]) – Input tensor of shape (batch_size, channels, height, width).
kernel_size (int) – Size of the sliding window.
stride (int) – Step size between windows.
padding_mode (str, optional) – Padding mode (“valid” or “same”). Defaults to “valid”.
- Returns:
Tuple[Tensor, Tuple[int, int]] – - windows: Stacked tensor of windows with shape (H_out, W_out, batch_size, channels, kernel_size, kernel_size). - output_shape: A tuple (H_out, W_out) representing the spatial dimensions of the output.
Examples
>>> import cupy as np >>> from autograd.tensor import Tensor >>> x = Tensor(xp.random.randn(2, 3, 32, 32)) >>> windows, output_shape = extract_windows(x, kernel_size=3, stride=1, padding_mode="same") >>> print(windows.data.shape) # Expected: (H_out, W_out, 2, 3, 3, 3) >>> print(output_shape) # Expected: (32, 32) when padding_mode is "same"
autograd.optim module¶
- class autograd.optim.LRScheduler¶
Bases:
objectInterface for a learning rate scheduler.
Subclasses should implement the __call__ method.
- class autograd.optim.CosineScheduler(warmup_steps: int = 100, lr_decay_iters: int = 200, min_lr: float = 0.0001, **kwargs)¶
Bases:
LRSchedulerCosine learning rate scheduler with warmup.
Implements Section 3 in “SGDR: Stochastic Gradient Descent with Warm Restarts”. Paper: https://arxiv.org/abs/1608.03983
- class autograd.optim.Optimizer(model_parameters: Dict[str, Tensor], lr: float, lr_scheduler_kwargs: dict | None = None, **kwargs: Any)¶
Bases:
objectBase Optimizer Class.
Usage Example:
optimizer = Optimizer(model.parameters(), lr=0.01, lr_scheduler_kwargs={ "lr_scheduler_cls": CosineScheduler, "warmup_steps": 100, "lr_decay_iters": 5000, "min_lr": 1e-4 }) for input, target in dataset: optimizer.zero_grad() output = model(input) loss = loss_fn(output, target) loss.backward() optimizer.step()
- property lr: float¶
Get the current learning rate.
- Returns:
float – The current learning rate.
- property timestep: int¶
Get the current global timestep.
- Returns:
int – The current timestep.
- update_lr() None¶
Update the learning rate using the provided scheduler and the global step.
- clip_grad_norm(max_norm: float, norm_type: float = 2.0) Any¶
Scale the gradients of all parameters in-place so that their norm is at most max_norm.
Implements Section 10.11.1 “Clipping Gradients” in the Deep Learning Book by Goodfellow et al.
The scaling is done according to:
\[ \frac{\text{max\_norm} \cdot g}{\|g\|_n} \]where \(n\) is the norm type.- Parameters:
max_norm (float) – The maximum allowed norm of the gradients.
norm_type (float, optional) – The type of norm to use (default is 2, Euclidean norm a.k.a. L2 norm).
- zero_grad() None¶
Set the gradients of all optimized tensors to zero.
- scale_gradients(scale: Any) None¶
Scale all parameter gradients in-place by
scale.
- grad_l2_norm() float¶
Return the L2 norm of all current parameter gradients.
- gradient_arrays() Dict[str, Any]¶
Current accumulated gradient arrays, keyed by parameter name.
- state_dict() Dict[str, Any]¶
Return a dictionary representing the optimizer’s state for checkpointing.
The returned dictionary has the following structure:
{ "hyperparams": { "lr": 0.01, }, "states": { "module1.weight": {"m": "...", "v": "..." }, "module1.bias": "..." } }
- Returns:
Dict[str, Any] – The state dictionary of the optimizer.
- load_state_dict(state_dict: Dict[str, Any]) None¶
Load the optimizer state from a checkpoint.
This performs an in-place update of the optimizer’s internal state and hyperparameters.
- Parameters:
state_dict (Dict[str, Any]) – The state dictionary read from a checkpoint.
- step() None¶
Perform a single optimization step.
- class autograd.optim.SGD(model_parameters: Any, lr: float, **kwargs: Any)¶
Bases:
OptimizerStochastic Gradient Descent (SGD) Optimizer.
- step() None¶
Perform a single optimization step using SGD.
This method updates each parameter by subtracting the product of the learning rate and the parameter’s gradient.
- class autograd.optim.Adam(model_parameters: Any, lr: float, beta1: float = 0.9, beta2: float = 0.999, epsilon: float = 1e-07, weight_decay: float = 0.0, **kwargs: Any)¶
Bases:
OptimizerAdam Optimizer.
Implements stochastic gradient descent with first and second order momentum. Paper: https://arxiv.org/abs/1412.6980
The weight_decay parameter implements decoupled weight decay as described in: “Decoupled Weight Decay Regularization” (https://arxiv.org/abs/1711.05101).
When weight_decay is set to 0, AdamW is equivalent to Adam.
- step() None¶
Perform a single optimization step using the Adam algorithm.
This method updates the biased first and second order momentum estimates, applies bias correction, performs a decoupled weight decay step if specified, and updates the parameters accordingly.
autograd.functional module¶
- autograd.functional.relu(x: Tensor) Tensor¶
Applies the Rectified Linear Unit (ReLU) activation function.
- Parameters:
x (Tensor) – The input tensor.
- Returns:
Tensor – The tensor after applying the ReLU function.
Examples
>>> from autograd.tensor import Tensor >>> x = Tensor([-1, 0, 2]) >>> y = relu(x) # Expected output: [0, 0, 2]
- autograd.functional.sigmoid(x: Tensor) Tensor¶
Applies the sigmoid activation function.
- Parameters:
x (Tensor) – The input tensor.
- Returns:
Tensor – The tensor after applying the sigmoid function.
Examples
>>> from autograd.tensor import Tensor >>> x = Tensor([0, 2]) >>> y = sigmoid(x) # Expected output: [0.5, ~0.88]
- autograd.functional.softmax(x: Tensor) Tensor¶
Applies the softmax activation function.
- Parameters:
x (Tensor) – The input tensor containing logits.
- Returns:
Tensor – The tensor with softmax probabilities.
Examples
>>> from autograd.tensor import Tensor >>> import cupy as np >>> x = Tensor(xp.array([2.0, 1.0, 0.1])) >>> y = softmax(x) # Expected output: probabilities that sum to 1
- autograd.functional.log_softmax(x: Tensor, dim: int = -1) Tensor¶
Applies the log-softmax function.
- Parameters:
x (Tensor) – The input tensor containing logits.
dim (int) – The dimension along which logprobs are computed.
- Returns:
Tensor – The tensor with token logprobs.
Examples
>>> from autograd.tensor import Tensor >>> x = Tensor(xp.array([2.0, 1.0, 0.1])) >>> y = log_softmax(x) # Expected output: logprobs that exponentiate to probabilities summing to 1
- autograd.functional.tanh(x: Tensor) Tensor¶
Applies the hyperbolic tangent (tanh) activation function.
- Parameters:
x (Tensor) – The input tensor.
- Returns:
Tensor – The tensor after applying the tanh function.
Examples
>>> from autograd.tensor import Tensor >>> x = Tensor([0, 1]) >>> y = tanh(x) # Expected output: [0, tanh(1)]
- autograd.functional.gelu(x: Tensor) Tensor¶
Applies the Gaussian Error Linear Unit (GELU) activation function.
This function uses the approximate formula:
\[ 0.5 * x * \left(1 + \tanh\left(\sqrt{\frac{2}{\pi}} \, (x + 0.044715*x^3)\right)\right) \]- Parameters:
x (Tensor) – The input tensor.
- Returns:
Tensor – The tensor after applying the GELU function.
Examples
>>> from autograd.tensor import Tensor >>> x = Tensor([1.0, -1.0]) >>> y = gelu(x) # Expected output: approximate GELU values for the inputs
- autograd.functional.scaled_dot_product_attention_mlx_custom(query: Tensor, key: Tensor, value: Tensor, *, is_training: bool | None = None, dropout_prob: float = 0.0) Tensor¶
Custom-implemented MLX kernel causal attention calculation
- class autograd.functional.Relu(*tensors: Tensor)¶
Bases:
FunctionRectified Linear Unit (ReLU) activation function.
- The ReLU function is defined as:
- \[ ReLU(x) = \max(0, x) \]
Note
This class is used internally. For applying ReLU, use the relu function.
Examples
>>> from autograd.tensor import Tensor >>> x = Tensor([-3, 0, 3]) >>> y = Relu.apply(x) # Expected output: [0, 0, 3]
- forward(x: Any) Any¶
Computes the forward pass of the ReLU activation function.
- Parameters:
x (xp.ndarray) – Input array.
- Returns:
xp.ndarray – The result of applying ReLU to the input.
- class autograd.functional.Gelu(*tensors: Tensor)¶
Bases:
FunctionGaussian Error Linear Unit (GELU) activation function. GELU(x) = x * P(X le x) where X ~ N(0, 1)
This activation function approximates:
\[ 0.5 * x * \left(1 + \tanh\left(\sqrt{\frac{2}{\pi}} \, (x + 0.044715*x^3)\right)\right) \]Paper: https://arxiv.org/abs/1606.08415
Note
Use the gelu function to apply this activation.
Examples
>>> from autograd.tensor import Tensor >>> x = Tensor([0.5, -0.5]) >>> y = Gelu.apply(x) # Expected output: approximate GELU values
- forward(x: Any) Any¶
Computes the forward pass of the GELU activation function.
- Parameters:
x (xp.ndarray) – Input array.
- Returns:
xp.ndarray – The output array after applying GELU.
- backward(grad: Any) Any¶
Computes the backward pass of the GELU activation function.
The gradient is computed as:
\[ \frac{d\,GELU}{dx} = 0.5 \left(1 + tanh(\alpha)\right) + 0.5 \, x \, \left(1 - tanh^2(\alpha)\right) \alpha' \]where\[ \alpha = \sqrt{\frac{2}{\pi}} (x + 0.044715*x^3) \]and\[ \alpha' = \sqrt{\frac{2}{\pi}} \left(1 + 3*0.044715*x^2\right) \]- Parameters:
grad (xp.ndarray) – Upstream gradient.
- Returns:
xp.ndarray – The gradient of the loss with respect to the input.
- class autograd.functional.Sigmoid(*tensors: Tensor)¶
Bases:
FunctionSigmoid activation function.
- The sigmoid function is defined as:
- \[ sigmoid(x) = \frac{1}{1 + e^{-x}} \]
Note
Use the sigmoid function to apply this activation.
Examples
>>> from autograd.tensor import Tensor >>> x = Tensor([0, 2]) >>> y = Sigmoid.apply(x) # Expected output: [0.5, ~0.88]
- forward(x: Any) Any¶
Computes the forward pass of the sigmoid function.
- Parameters:
x (xp.ndarray) – Input array.
- Returns:
xp.ndarray – The output after applying the sigmoid function.
- class autograd.functional.Softmax(*tensors: Tensor)¶
Bases:
FunctionSoftmax activation function.
- The softmax function is defined as:
- \[ softmax(x)_i = \frac{e^{x_i}}{\sum_j e^{x_j}} \]
Note
Use the softmax function to apply this activation.
Examples
>>> from autograd.tensor import Tensor >>> import cupy as np >>> x = Tensor(xp.array([1.0, 2.0, 3.0])) >>> y = Softmax.apply(x) # Expected output: probabilities that sum to 1
- forward(x: Any) Any¶
Computes the forward pass of the softmax activation function.
- Parameters:
x (xp.ndarray) – Input array of logits.
- Returns:
xp.ndarray – The softmax probabilities.
- backward(grad: Tensor) Any¶
Computes the backward pass of the softmax activation function.
This function computes the gradient of the softmax output with respect to the input logits.
- Parameters:
grad (Tensor) – Upstream gradient.
- Returns:
xp.ndarray – The gradient of the loss with respect to the input logits.
- class autograd.functional.LogSoftmax(*tensors: Tensor)¶
Bases:
FunctionLog-softmax activation function.
- The log-softmax function is defined as:
- \[ \log \pi_i = x_i - \log \sum_j e^{x_j} \]
Note
Use log_softmax when logprobs are needed; it is more stable than computing log(softmax(x)).
- forward(x: Any, *, dim: int = -1) Any¶
Computes the forward pass of the log-softmax activation function.
- Parameters:
x (xp.ndarray) – Input array of logits.
dim (int) – Dimension along which logprobs are computed.
- Returns:
xp.ndarray – The logprobs.
- class autograd.functional.Tanh(*tensors: Tensor)¶
Bases:
FunctionHyperbolic tangent (tanh) activation function.
- The tanh function is defined as:
- \[ \tanh(x) = \frac{e^x - e^{-x}}{e^x + e^{-x}} \]
Note
Use the tanh function to apply this activation.
Examples
>>> from autograd.tensor import Tensor >>> x = Tensor([0, 1]) >>> y = Tanh.apply(x) # Expected output: [0, tanh(1)]
- forward(x: Any) Any¶
Computes the forward pass of the tanh activation function.
- Parameters:
x (xp.ndarray) – Input array.
- Returns:
xp.ndarray – The output after applying the tanh function.
- class autograd.functional.ScaledDotProductAttentionMLXCustom(*tensors: Tensor)¶
Bases:
Function- static build_dropout_scale_mask(*, is_training: bool | None, dropout_prob: float, query_shape: Tuple[int, ...], key_shape: Tuple[int, ...]) Any | None¶
- static validate(query: Any, key: Any, value: Any, *, dropout_scale_mask: Any | None = None) None¶
- forward(query: Any, key: Any, value: Any, *, dropout_scale_mask: Any | None = None) Any¶
Perform the forward pass of this operation.
This method should be overridden by subclasses to define the specific behavior of the operation. It receives NumPy arrays corresponding to the data of the input tensors.
- Parameters:
*args (xp.ndarray) – Data arrays for the input tensors.
**kwargs (Any) – Additional keyword arguments.
- Returns:
xp.ndarray – The result of the forward pass as a NumPy array.
- Raises:
NotImplementedError – If this method is not implemented in a subclass.
- backward(grad: Tensor) Tuple[Any, Any, Any]¶
The reason we have to define this backward function explicitly is because the kernel’s forward function is defined not with our Tensor ops, but with a lower-level kernel ops. That’s why we don’t get the backward implementation for free like other Function classes.
Backpropagate through the fused causal attention path.
The no-dropout forward contract is:
\[ \text{Attention}(Q, K, V) = \text{softmax}\left(\frac{QK^T}{\sqrt{key\_dim}}\right) V \]Train mode keeps the repo’s post-softmax dropout contract:
\[ \widetilde{P} = P \odot M \]\[ \text{Attention}_{\text{dropout}}(Q, K, V) = \widetilde{P}V \]where \(M\) is the already-scaled Bernoulli mask sampled in Python.We still recompute the causal softmax probabilities inside backward instead of saving dense logits/probabilities from the fused forward kernel. We will use these intermediate names:
\[ \text{attention\_scores} = \frac{QK^T}{\sqrt{key\_dim}} \]\[ P = \operatorname{softmax}(\text{attention\_scores}_{\text{causal}}) \]\[\begin{split} \widetilde{P} = \begin{cases} P & \text{if dropout is disabled} \\ P \odot M & \text{if dropout is enabled} \end{cases} \end{split}\]\[ \text{attention\_output} = \widetilde{P}V \]Let loss be the final scalar training objective, and let the upstream gradient be:
\[ \text{upstream\_grad} = \frac{\partial \text{loss}}{\partial \text{attention\_output}} \]1. Derivative of loss with respect to V:
\[ \frac{\partial \text{loss}}{\partial V} = \frac{\partial \text{loss}}{\partial \text{attention\_output}} \frac{\partial \text{attention\_output}}{\partial V} = \widetilde{P}^T \, \text{upstream\_grad} \]2. Derivative of loss with respect to the pre-dropout probabilities:
\[\begin{split} \frac{\partial \text{loss}}{\partial P} = \left(\text{upstream\_grad} \, V^T\right) \odot \begin{cases} 1 & \text{if dropout is disabled} \\ M & \text{if dropout is enabled} \end{cases} \end{split}\]3. Derivative of loss with respect to attention_scores: Softmax is applied independently to each query row, so we apply the softmax derivative row by row along the key dimension.
\[ \frac{\partial \text{loss}}{\partial \text{attention\_scores}} = \frac{\partial \text{loss}}{\partial P} \frac{\partial P}{\partial \text{attention\_scores}} = P \odot \left( \frac{\partial \text{loss}}{\partial P} - \sum_k \left( \frac{\partial \text{loss}}{\partial P_k} P_k \right) \right) \]4. Derivative of loss with respect to Q and K, using
\[ \text{attention\_scores} = \frac{QK^T}{\sqrt{key\_dim}} \]\[ \frac{\partial \text{loss}}{\partial Q} = \frac{\partial \text{loss}}{\partial \text{attention\_scores}} \frac{\partial \text{attention\_scores}}{\partial Q} = \frac{\partial \text{loss}}{\partial \text{attention\_scores}} K \cdot \frac{1}{\sqrt{key\_dim}} \]\[ \frac{\partial \text{loss}}{\partial K} = \frac{\partial \text{loss}}{\partial \text{attention\_scores}} \frac{\partial \text{attention\_scores}}{\partial K} = \left( \frac{\partial \text{loss}}{\partial \text{attention\_scores}} \right)^T Q \cdot \frac{1}{\sqrt{key\_dim}} \]
- class autograd.functional.BinaryCrossEntropy(*tensors: Tensor)¶
Bases:
FunctionBinary Cross Entropy (BCE) Loss.
This loss function assumes that \(y_{pred}\) contains probabilities rather than logits. If the input is logits, use
binary_cross_entropy_with_logits().The loss is computed as:
\[ BCE = -\left( y_{true} \cdot \log(y_{pred}) + (1 - y_{true}) \cdot \log(1 - y_{pred}) \right) \]Examples
>>> from autograd.tensor import Tensor >>> y_pred = Tensor([0.9, 0.2, 0.1]) >>> y_true = Tensor([1, 0, 0]) >>> loss = BinaryCrossEntropy.apply(y_pred, y_true) # Expected output: a small loss value
- forward(y_pred: Any, y_true: Any, **kwargs: Any) Any¶
Computes the binary cross entropy loss.
- Parameters:
y_pred (xp.ndarray) – Predicted probabilities.
y_true (xp.ndarray) – True binary labels.
**kwargs – Additional keyword arguments.
- Returns:
float – The computed binary cross entropy loss.
- backward(grad: Tensor) Tuple[Any, None]¶
Computes the gradient of the binary cross entropy loss with respect to \(y_{pred}\).
The gradient is given by:
\[ \frac{\partial L}{\partial y_{pred}} = -\left(\frac{y_{true}}{y_{pred}} - \frac{1-y_{true}}{1-y_{pred}}\right) \]- Parameters:
grad (Tensor) – Upstream gradient.
- Returns:
Tuple[xp.ndarray, None] – A tuple containing the gradient with respect to \(y_{pred}\) and None for \(y_{true}\).
- class autograd.functional.BinaryCrossEntropyWithLogits(*tensors: Tensor)¶
Bases:
FunctionBinary Cross Entropy Loss with logits.
This implementation is numerically stable for logits input.
Examples
>>> from autograd.tensor import Tensor >>> y_pred = Tensor([2.0, -1.0, -2.0]) # logits >>> y_true = Tensor([1, 0, 0]) >>> loss = BinaryCrossEntropyWithLogits.apply(y_pred, y_true) # Expected output: a loss value computed using logits
- forward(y_pred: Any, y_true: Any) Any¶
Computes the binary cross entropy loss with logits input.
- Parameters:
y_pred (xp.ndarray) – shape (N, …) Unbounded real-valued logits.
y_true (xp.ndarray) – True binary labels (0 or 1), same shape as y_pred.
- Returns:
float – The computed binary cross entropy loss.
- backward(grad: Tensor) Tuple[Any, None]¶
Computes the gradient of the binary cross entropy loss with logits with respect to \(y_{pred}\).
The gradient is given by:
\[ \frac{\partial L}{\partial y_{pred}} = sigmoid(y_{pred}) - y_{true} = -(\frac{y_{true}}{y_{pred}} - \frac{1-y_{true}}{1-y_{pred}}) \]Where\[ sigmoid = 1 / (1 + exp(-y_{pred})) \]- Parameters:
grad (Tensor) – Upstream gradient.
- Returns:
Tuple[xp.ndarray, None] – A tuple containing the gradient with respect to \(y_{pred}\) and None for \(y_{true}\).
- class autograd.functional.CrossEntropy(*tensors: Tensor)¶
Bases:
FunctionCross-Entropy Loss for multi-dimensional predictions with optional ignored targets and label smoothing.
This function accepts raw logits (not probabilities) and computes a stable log-softmax internally.
Examples
>>> import cupy as np >>> from autograd.tensor import Tensor >>> y_pred = Tensor(xp.array([[2.0, 1.0, 0.1]])) >>> y_true = Tensor(xp.array([0])) >>> loss = CrossEntropy.apply(y_pred, y_true, ignore_index=-100, label_smoothing=0.1)
- forward(y_pred: Any, y_true: Any, ignore_index: int = -100, label_smoothing: float = 0.0, reduction: str = 'mean') Any | float¶
Computes the cross-entropy loss with optional ignored targets and label smoothing.
- Parameters:
y_pred (xp.ndarray) – Raw logits. Shape can be \((batch\_size, feature\_dim)\) or \((batch\_size, seq\_len, feature\_dim)\).
y_true (Union[xp.ndarray, Tensor]) – True class indices. If \(y_{pred}\) is 2D, shape is \((batch\_size,)\); if 3D, shape is \((batch\_size, seq\_len)\).
ignore_index (int, optional) – Target value to ignore in the loss and gradient. Defaults to -100.
label_smoothing (float, optional) – Label smoothing factor. Defaults to 0.0. Label smoothing is applied if \(label\_smoothing > 0\)
reduction (str, optional) – Either
"mean"or"sum"."mean"divides by the total non-ignored target weight;"sum"returns the summed loss over non-ignored targets.smoothing (For label)
notation. (we follow the Inception paper)
Here
example (- \(x\) is the current training)
\(x\) (- \(y\) is the ground-truth class index for)
index (- \(k\) is a class)
classes (- \(K\) is the total number of)
$delta_{k (-)
delta (y}$ is the Kronecker)
otherwise (equal to \(1\) when \(k=y\) and \(0\))
$u (-)
$$
q' (k mid x) = (1 - epsilon),delta_{k,y} + epsilon,u(k)
$$
paper (and for the uniform prior used in the)
:param : :param
\[: :param u: :type u: k :param \]: :param so the smoothed target distribution becomes: :param\[: :param q': :type q': k \mid x) = (1 - \epsilon :param \]: :param In per-example / per-class notation: :param where \(y_{i: :param j}\) is the one-hot: :param target entry for example \(i\) and class \(j\): :param this is: :param\[: :param T_{i: :type T_{i: 1 - \epsilon :param j} =: :type j} =: 1 - \epsilon :param \]:(Ref: “Rethinking the Inception Architecture for Computer Vision”, https://arxiv.org/abs/1512.00567)
- Returns:
Union[xp.array, float] – The average cross-entropy loss over non-ignored positions.
- backward(grad: Tensor) Tuple[Any, None]¶
Computes the backward pass for the cross-entropy loss with label smoothing.
The gradient with respect to the logits is given by:
\[ \frac{\partial L}{\partial logits_{i,j}} = p_{i,j} - T_{i,j} \]where \(p_{i,j}\) is the stored model probability for example \(i\) and class \(j\), and the target distribution \(T_{i,j}\) is defined as:\[ T_{i,j} = (1 - \epsilon)\,y_{i,j} + \frac{\epsilon}{K} \]The gradient is zeroed out for ignored positions and scaled by the upstream gradient divided by the number of non-ignored positions.- Parameters:
grad (Tensor) – Upstream gradient.
- Returns:
Tuple[xp.ndarray, None] – A tuple containing the gradient with respect to the logits and None for \(y_{true}\).
- class autograd.functional.HingeLoss(*tensors: Tensor)¶
Bases:
FunctionHinge Loss.
- The hinge loss is defined as:
- \[ loss = \max(0, 1 - y_{true} \cdot y_{pred}) \]
For correctly classified points (\(y_{true} \cdot y_{pred} \geq 1\)), the loss is 0; otherwise, it is \(1 - y_{true} \cdot y_{pred}\). This is because loss functions typically don’t go into the negatives so we take the max of 0 and 1 - y_true * y_pred)
- The objective function typically includes a regularization term:
- \[ \|w\|^2 + C \sum max(0, 1 - y_{true} \cdot y_{pred}) \]
where \(C\) is a hyperparameter controlling the trade-off between maximizing the margin (through regularization) and minimizing the loss, and \(w\) is the weight vector. (\(\|w\|^2\) is the regularization term)
Paper: https://ieeexplore.ieee.org/document/708428
Examples
>>> from autograd.tensor import Tensor >>> y_pred = Tensor([0.8, -0.5, 0.3]) >>> y_true = Tensor([1, -1, 1]) >>> loss = HingeLoss.apply(y_pred, y_true, reduction="mean") # Expected output: average hinge loss
- forward(y_pred: Any, y_true: Any, reduction: str = 'none', **kwargs: Any) Any | float¶
Computes the hinge loss.
- Parameters:
y_pred (xp.ndarray) – Predicted scores.
y_true (Union[xp.ndarray, Tensor]) – True labels.
reduction (str, optional) – “none”, “mean”, or “sum”. Defaults to “none”.
**kwargs – Additional keyword arguments.
- Returns:
Union[xp.array, float] – The computed hinge loss.
- backward(grad: Tensor) Tuple[Any, None]¶
Computes the gradient of the hinge loss with respect to the predictions.
For each element, the gradient is:
\[\begin{split} \begin{align} \frac{\partial loss}{\partial y_{pred}} \\ &= \frac{d(C * sum(max(0, 1 - y_{true} * y_{pred})))}{dw} \\ &= C * max(0, 1 - y_{true} * y_{pred}) \\ &=\begin{cases} -y_{true}, & \text{if } y_{true} \cdot y_{pred} < 1 \\ 0, & \text{otherwise} \end{cases} \end{align} \end{split}\]For the gradient of w in the regularization term,\[\frac{d(\frac{1}{2}\|w\|^2)}{dw} = w\](we multiple 1/2 because it makes the gradient calculation easier)If the reduction is “mean”, the gradient is averaged over the number of elements.
- Parameters:
grad (Tensor) – Upstream gradient.
- Returns:
Tuple[xp.ndarray, None] – A tuple containing the gradient with respect to \(y_{pred}\) and None for \(y_{true}\).
- class autograd.functional.MeanSquaredLoss(*tensors: Tensor)¶
Bases:
FunctionMean Squared Error (MSE) Loss.
- The MSE loss is defined as:
- \[ MSE = \frac{1}{N} \sum (y_{pred} - y_{true})^2 \]
Examples
>>> from autograd.tensor import Tensor >>> y_pred = Tensor([3.0, 5.0]) >>> y_true = Tensor([2.0, 5.0]) >>> loss = MeanSquaredLoss.apply(y_pred, y_true) # Expected output: 0.5
- forward(y_pred: Any, y_true: Any, **kwargs: Any) Any¶
Computes the Mean Squared Error loss.
- Parameters:
y_pred (xp.ndarray) – Predicted values.
y_true (xp.ndarray) – True values.
**kwargs – Additional keyword arguments.
- Returns:
float – The computed MSE loss.
- backward(grad: Tensor) Any¶
Computes the gradient of the Mean Squared Error loss with respect to the predictions.
The gradient is given by:
\[ \frac{\partial L}{\partial y_{pred}} = \frac{2}{N} (y_{pred} - y_{true}) \]- Parameters:
grad (Tensor) – Upstream gradient.
- Returns:
xp.ndarray – The gradient with respect to y_pred.
- autograd.functional.binary_cross_entropy(y_pred: Tensor, y_true: Tensor | Any | Sequence[Any] | int | float | bool, **kwargs: Any) Tensor¶
Computes the binary cross entropy loss given predicted probabilities.
This function wraps the
BinaryCrossEntropyoperation.- Parameters:
- Returns:
Tensor – The computed binary cross entropy loss.
Examples
>>> from autograd.tensor import Tensor >>> y_pred = Tensor([0.9, 0.2, 0.1]) >>> y_true = [1, 0, 0] >>> loss = binary_cross_entropy(y_pred, y_true)
- autograd.functional.binary_cross_entropy_with_logits(y_pred: Tensor, y_true: Tensor | Any | Sequence[Any] | int | float | bool, **kwargs: Any) Tensor¶
Computes the binary cross entropy loss using logits input for improved numerical stability.
If \(y_{pred}\) contains probabilities, use
binary_cross_entropy()instead.- The loss is computed as:
- \[ -\left(y_{true} \cdot \log(y_{pred}) + (1 - y_{true}) \cdot \log(1 - y_{pred})\right) \]
- Parameters:
- Returns:
Tensor – The computed binary cross entropy loss.
Examples
>>> from autograd.tensor import Tensor >>> y_pred = Tensor([2.0, -1.0, -2.0]) >>> y_true = [1, 0, 0] >>> loss = binary_cross_entropy_with_logits(y_pred, y_true)
- autograd.functional.cross_entropy(y_pred: Tensor, y_true: Tensor | Any | Sequence[Any] | int | float | bool, ignore_index: int = -100, label_smoothing: float = 0.0, reduction: str = 'mean') Tensor¶
Computes the cross-entropy loss for multi-class classification with logits.
This function expects \(y_{pred}\) to be raw logits and \(y_{true}\) to be class indices (not one-hot vectors).
- Parameters:
y_pred (Tensor) – Raw logits.
y_true (Union[Tensor, ArrayLike]) – True class indices.
ignore_index (int, optional) – Target value to ignore in the loss and gradient. Defaults to -100.
label_smoothing (float, optional) – Label smoothing factor. Defaults to 0.0.
reduction (str, optional) – Either
"mean"or"sum". Defaults to"mean".
- Returns:
Tensor – The computed cross-entropy loss.
Examples
>>> import cupy as np >>> from autograd.tensor import Tensor >>> y_pred = Tensor(xp.array([[2.0, 1.0, 0.1]])) >>> y_true = Tensor(xp.array([0])) >>> loss = cross_entropy(y_pred, y_true, ignore_index=-100, label_smoothing=0.1)
- autograd.functional.hinge_loss(y_pred: Tensor, y_true: Tensor | Any | Sequence[Any] | int | float | bool, reduction: str = 'none', **kwargs: Any) Tensor¶
Computes the hinge loss for binary classification.
- Parameters:
- Returns:
Tensor – The computed hinge loss.
Examples
>>> from autograd.tensor import Tensor >>> y_pred = Tensor([0.8, -0.5, 0.3]) >>> y_true = [1, -1, 1] >>> loss = hinge_loss(y_pred, y_true, reduction="mean")
- autograd.functional.mean_squared_loss(y_pred: Tensor, y_true: Tensor | Any | Sequence[Any] | int | float | bool, **kwargs: Any) Tensor¶
Computes the Mean Squared Error (MSE) loss.
- Parameters:
- Returns:
Tensor – The computed MSE loss.
Examples
>>> from autograd.tensor import Tensor >>> y_pred = Tensor([3.0, 5.0]) >>> y_true = [2.0, 5.0] >>> loss = mean_squared_loss(y_pred, y_true) # Expected output: 0.5
autograd.init module¶
Weight initialization methods for neural network parameters.
- autograd.init.xavier_uniform(tensor: Tensor) Tensor¶
Applies in-place Xavier Uniform Initialization to the given tensor.
This method initializes the weights of a neural network using the Xavier (Glorot) uniform initialization technique, as described in this paper: https://proceedings.mlr.press/v9/glorot10a/glorot10a.pdf
- The weight tensor is assumed to have the shape:
(input_size, output_size, additional_dimensions…)
The limits for the uniform distribution are computed using the number of input and output tensor counts of the given tensor, where the limit is given by:
\[ \text{limit} = \sqrt{\frac{6}{\text{\# of input tensor count} + \text{\# of output tensor count}}} \]- Parameters:
tensor (Tensor) – The tensor to initialize. Its underlying data should be an array.
- Returns:
Tensor – The same tensor after in-place initialization.
Examples
>>> from autograd.backend import xp >>> from autograd.tensor import Tensor >>> # Create an uninitialized tensor with shape (3, 4) >>> tensor = Tensor(xp.empty((3, 4))) >>> # Initialize the tensor using Xavier Uniform initialization >>> tensor = xavier_uniform(tensor)
- autograd.init.compute_in_out_tensor_count(tensor: Tensor) tuple[int, int]¶
Computes the number of input and output tensor counts for the given tensor.
- For convolution kernels:
tensor.shape[0] is assumed to represent the number of output channels.
tensor.shape[1] is assumed to represent the number of input channels.
The remaining dimensions correspond to the spatial kernel sizes (e.g., kernel height, kernel width).
The counts are computed as follows:
\[\begin{split} \begin{align} \text{\# of input tensor count} &= \text{tensor.shape}[0] \times \prod_{i=2}^{n} \text{tensor.shape}[i] \\ \text{\# of output tensor count} &= \text{tensor.shape}[-1] \times \prod_{i=2}^{n} \text{tensor.shape}[i] \end{align} \end{split}\]where \( n \) is the number of dimensions in the tensor.- Parameters:
tensor (Tensor) – The tensor for which to compute the number of input and output tensor counts. The tensor must have at least 2 dimensions.
- Returns:
Tuple[int, int] – A tuple containing (input_tensor_count, output_tensor_count).
- Raises:
ValueError – If the tensor has fewer than 2 dimensions.
Examples
>>> from autograd.backend import xp >>> from autograd.tensor import Tensor >>> # Example for a fully-connected layer weight matrix with shape (fan_in, fan_out) >>> tensor_fc = Tensor(xp.empty((5, 10))) >>> compute_in_out_tensor_count(tensor_fc.data) (5, 10) >>> # Example for a convolution kernel with shape >>> # (output_channels, input_channels, kernel_height, kernel_width) >>> tensor_conv = Tensor(xp.empty((16, 3, 3, 3))) >>> # The receptive field size is 3*3 = 9 >>> # So, input tensor count = 16 * 9 = 144, output tensor count = 3 * 9 = 27 >>> compute_in_out_tensor_count(tensor_conv.data) (144, 27)
autograd.logger module¶
- class autograd.logger.ColorFormatter(fmt=None, datefmt=None, style='%', validate=True, *, defaults=None)¶
Bases:
FormatterA logging formatter that adds ANSI color codes to log messages based on their severity level.
This formatter maps each logging level to a specific color for improved readability in the console output.
Examples
>>> import logging >>> from your_module import ColorFormatter # Replace 'your_module' with your actual module name. >>> # Create a logger and attach a stream handler with the ColorFormatter. >>> logger = logging.getLogger("example") >>> handler = logging.StreamHandler() >>> handler.setFormatter(ColorFormatter()) >>> logger.addHandler(handler) >>> logger.setLevel(logging.DEBUG) >>> logger.debug("This is a debug message.") >>> logger.info("This is an info message.") >>> logger.warning("This is a warning message.") >>> logger.error("This is an error message.") >>> logger.critical("This is a critical message.") # Each message will appear in a color corresponding to its log level.
- grey = '\x1b[38;20m'¶
- yellow = '\x1b[33;20m'¶
- red = '\x1b[31;20m'¶
- bold_red = '\x1b[31;1m'¶
- cyan = '\x1b[36;20m'¶
- green = '\x1b[32;20m'¶
- reset = '\x1b[0m'¶
- FORMATS = {10: '\x1b[36;20m', 20: '\x1b[32;20m', 30: '\x1b[33;20m', 40: '\x1b[31;20m', 50: '\x1b[31;1m'}¶
- format(record)¶
Format the specified record as a colored log message.
The method selects a color based on the log record’s level and applies it to the formatted message.
- Parameters:
record (logging.LogRecord) – The log record to be formatted.
- Returns:
str – The formatted log message with ANSI color codes.
- autograd.logger.setup_logger(name=None)¶
Set up and configure a logger with colored console output.
This function creates a logger with the given name, sets its logging level to DEBUG if the environment variable DEBUG is set; otherwise, it defaults to INFO level. It then attaches a console handler with a color formatter and returns the configured logger.
- Parameters:
name (str, optional) – The name of the logger. Defaults to None.
- Returns:
logging.Logger – The configured logger instance.
Examples
>>> import os >>> # Optionally set the DEBUG environment variable to enable debug logging. >>> os.environ["DEBUG"] = "1" >>> from your_module import setup_logger # Replace 'your_module' with your actual module name. >>> logger = setup_logger("my_logger") >>> logger.info("This is an informational message.") >>> logger.error("This is an error message.") # The output in the console will display the messages in colors corresponding to their log levels.
Module contents¶
Subpackages¶
- autograd.text package
- Submodules
- autograd.text.tokenizer module
BytePairEncoderBytePairEncoder.SPECIAL_TOKENSBytePairEncoder.ENCODE_CHUNK_CACHE_MAX_SIZEBytePairEncoder.WORD_FREQ_BATCH_SIZEBytePairEncoder.WORD_FREQ_LOG_INTERVALBytePairEncoder.n_vocabBytePairEncoder.prepare_data()BytePairEncoder.train_vocabulary()BytePairEncoder.encode()BytePairEncoder.decode()BytePairEncoder.load_encoded()
- autograd.text.utils module
GenerationResultOpenWebTextSourceformat_document_for_causal_lm()generate()generate_text()teacher_force()create_vocabulary()text_to_one_hot_and_sparse()create_causal_mask()prepare_mlx_attention_mask()clean_and_tokenize()validate_batches()token_batch_to_indices()load_wiki_simple()load_shakespeare_mini()load_openwebtext()
- Module contents