import torch
n = 5
A = torch.randn((n, n), requires_grad=True)
b = torch.randn((n,))
x = torch.randn((n,), requires_grad=True)
f = 0.5 * x @ A @ x - b @ x
f.backward()
print(f)
print(f.item())
tensor(-7.4333, grad_fn=<SubBackward0>) -7.433262825012207
manual_grad_x = 0.5 * (A + A.t()) @ x - b
print(manual_grad_x.data)
print(x.grad.data)
print(x.grad)
tensor([-0.0997, -3.0563, 5.3020, 1.2093, -4.0723]) tensor([-0.0997, -3.0563, 5.3020, 1.2093, -4.0723]) tensor([-0.0997, -3.0563, 5.3020, 1.2093, -4.0723])
manual_grad_A = 0.5 * torch.ger(x, x)
print(manual_grad_A.data)
print(A.grad.data)
print(torch.norm(manual_grad_A.data - A.grad.data).item())
tensor([[ 0.5078, 0.7830, -1.0070, -0.1017, 0.4298], [ 0.7830, 1.2074, -1.5528, -0.1568, 0.6628], [-1.0070, -1.5528, 1.9971, 0.2017, -0.8524], [-0.1017, -0.1568, 0.2017, 0.0204, -0.0861], [ 0.4298, 0.6628, -0.8524, -0.0861, 0.3639]]) tensor([[ 0.5078, 0.7830, -1.0070, -0.1017, 0.4298], [ 0.7830, 1.2074, -1.5528, -0.1568, 0.6628], [-1.0070, -1.5528, 1.9971, 0.2017, -0.8524], [-0.1017, -0.1568, 0.2017, 0.0204, -0.0861], [ 0.4298, 0.6628, -0.8524, -0.0861, 0.3639]]) 0.0