Esempio n. 1
0
def subtract(left: Tensor, right: Tensor):
    left, right = coalesce(left, right)
    return Tensor.from_numpy(
        data=left.data - right.data,
        backward=lambda gradient: Gradients.accumulate(
            Gradient(tensor=left, gradient=gradient),
            Gradient(tensor=right, gradient=-gradient),
        ),
    )
Esempio n. 2
0
def divide(left: Tensor, right: Tensor):
    left, right = coalesce(left, right)
    return Tensor.from_numpy(
        data=left.data / right.data,
        backward=lambda gradient: Gradients.accumulate(
            Gradient(tensor=left, gradient=gradient / right.data),
            Gradient(
                tensor=right,
                gradient=-gradient * left.data / np.square(right.data),
            ),
        ),
    )
Esempio n. 3
0
def matrix_multiply(left: Tensor, right: Tensor):
    left = coalesce(left)
    right = coalesce(right)
    assert len(left.shape) == 2
    assert len(right.shape) == 2
    assert left.shape[1] == right.shape[0]
    return Tensor.from_numpy(
        data=np.matmul(left.data, right.data),
        backward=lambda gradient: Gradients.accumulate(
            Gradient(tensor=left, gradient=np.matmul(gradient, right.data.T)),
            Gradient(tensor=right, gradient=np.matmul(left.data.T, gradient)),
        ),
    )
Esempio n. 4
0
def negate(tensor: Tensor):
    tensor = coalesce(tensor)
    return Tensor.from_numpy(
        data=-tensor.data,
        backward=lambda gradient: Gradients.accumulate(
            Gradient(tensor=tensor, gradient=-gradient)),
    )
Esempio n. 5
0
def exp(tensor: Tensor):
    tensor = coalesce(tensor)
    return Tensor.from_numpy(
        data=np.exp(tensor.data),
        backward=lambda gradient: Gradients.accumulate(
            Gradient(tensor=tensor, gradient=gradient * np.exp(tensor.data))),
    )
Esempio n. 6
0
def squeeze(tensor: Tensor, axes: Union[None, int, Tuple[int]] = None):
    tensor = coalesce(tensor)
    axes = () if axes is None else tuplify(axes)
    return Tensor.from_numpy(
        data=np.squeeze(tensor.data, axes),
        backward=lambda gradient: Gradients.accumulate(
            Gradient(tensor=tensor, gradient=np.expand_dims(gradient, axes))),
    )
Esempio n. 7
0
def sum(tensor: Tensor, axes=None):
    tensor = coalesce(tensor)
    axes = tuplify(range(len(tensor.shape)) if axes is None else axes)
    return Tensor.from_numpy(
        data=tensor.data.sum(axes),
        backward=lambda gradient: Gradients.accumulate(
            Gradient(
                tensor=tensor,
                gradient=np.tile(
                    np.expand_dims(gradient, axes),
                    [
                        dim if idx in axes or idx - len(tensor.shape) in axes else 1
                        for idx, dim in enumerate(tensor.shape)
                    ],
                ),
            )
        ),
    )
Esempio n. 8
0
def tile(tensor: Tensor, tiling: Tuple[int]):
    tensor = coalesce(tensor)
    tiling = tuple(tiling)
    assert len(tensor.shape) == len(tiling)
    return Tensor.from_numpy(
        data=np.tile(tensor.data, tiling),
        backward=lambda gradient: Gradients.accumulate(
            Gradient(
                tensor=tensor,
                gradient=np.reshape(
                    gradient,
                    [
                        value for idx, dim in enumerate(tensor.shape)
                        for value in [tiling[idx], dim]
                    ],
                ).sum(tuple(range(0,
                                  len(tiling) * 2, 2))),
            )),
    )
Esempio n. 9
0
 def backward(gradient: np.ndarray):
     result = gradient.copy()
     result[(tensor.data < low.data) | (tensor.data > high.data)] = 0
     return Gradients.accumulate(Gradient(tensor=tensor, gradient=result))