import torch
x = torch.ones(2, 2)
print(x)
print(x.requires_grad)
x = torch.ones(2, 2, requires_grad=True)
print(x)
print(x.requires_grad)
tensor([[1., 1.], [1., 1.]]) False tensor([[1., 1.], [1., 1.]], requires_grad=True) True
#x = torch.ones(2, 2, requires_grad=True)
x = torch.randn(2,2, requires_grad=True)
print(x)
y = x + 2
print(y)
z = 3 * (y ** 2)
print(z)
out = z.mean()
print(out)
out.backward() # equivalent to out.backward(torch.tensor(1.)) since out contains a single scalar
print(x.grad)
tensor([[ 0.4599, -2.4081], [ 0.4585, -0.3363]], requires_grad=True) tensor([[ 2.4599, -0.4081], [ 2.4585, 1.6637]], grad_fn=<AddBackward0>) tensor([[18.1530, 0.4996], [18.1327, 8.3038]], grad_fn=<MulBackward0>) tensor(11.2723, grad_fn=<MeanBackward0>) tensor([[ 3.6898, -0.6121], [ 3.6878, 2.4956]])
print('y:', y)
print('y.grad:', y.grad)
print('y.requires_grad:', y.requires_grad)
print('y.grad_fn:', y.grad_fn)
print('z:', z)
print('z.grad:', z.grad)
print('z.requires_grad:', z.requires_grad)
print('z.grad_fn:', z.grad_fn)
y: tensor([[ 2.4599, -0.4081], [ 2.4585, 1.6637]], grad_fn=<AddBackward0>) y.grad: None y.requires_grad: True y.grad_fn: <AddBackward0 object at 0x7f97c28b84d0> z: tensor([[18.1530, 0.4996], [18.1327, 8.3038]], grad_fn=<MulBackward0>) z.grad: None z.requires_grad: True z.grad_fn: <MulBackward0 object at 0x7f97c28b82d0>
/usr/local/lib/python3.7/dist-packages/ipykernel_launcher.py:2: UserWarning: The .grad attribute of a Tensor that is not a leaf Tensor is being accessed. Its .grad attribute won't be populated during autograd.backward(). If you indeed want the gradient for a non-leaf Tensor, use .retain_grad() on the non-leaf Tensor. If you access the non-leaf Tensor by mistake, make sure you access the leaf Tensor instead. See github.com/pytorch/pytorch/pull/30531 for more informations. /usr/local/lib/python3.7/dist-packages/ipykernel_launcher.py:7: UserWarning: The .grad attribute of a Tensor that is not a leaf Tensor is being accessed. Its .grad attribute won't be populated during autograd.backward(). If you indeed want the gradient for a non-leaf Tensor, use .retain_grad() on the non-leaf Tensor. If you access the non-leaf Tensor by mistake, make sure you access the leaf Tensor instead. See github.com/pytorch/pytorch/pull/30531 for more informations. import sys
x = torch.randn(3, requires_grad=True)
print(x.requires_grad)
print((x ** 2).requires_grad)
with torch.no_grad():
print((x ** 2).requires_grad)
True True False
print(x.requires_grad)
y = x.detach()
print(y.requires_grad)
print(x.eq(y).all())
True False tensor(True)
# First lets try to code only a single step of gradient descent
x = torch.randn(1, requires_grad=True)
print('x:', x)
y = (x - 4) ** 2
y.backward()
learning_rate = 0.1
print('x.grad:', x.grad)
print('x - x.grad:', x - learning_rate * x.grad)
with torch.no_grad():
x = x - learning_rate * x.grad
print('x:', x)
x.requires_grad = True
print('x:', x)
x: tensor([0.2818], requires_grad=True) x.grad: tensor([-7.4363]) x - x.grad: tensor([1.0255], grad_fn=<SubBackward0>) x: tensor([1.0255]) x: tensor([1.0255], requires_grad=True)
# Gradient Descent till convergence
x = torch.randn(1, requires_grad=True)
print('Initial x:', x)
max_iter = 100
learning_rate = 0.1
eps = 1e-6
for _ in range(max_iter):
y = (x - 4) ** 2
y.backward()
with torch.no_grad():
prev_x = x
x = x - learning_rate * x.grad
if torch.norm(prev_x - x) < eps:
break
x.requires_grad = True
print('Soln x:', x)
Initial x: tensor([-1.2967], requires_grad=True) Soln x: tensor([4.0000])