Let’s write a Linear Regression using PyTorch
. We will train it on some dummy data.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
import torch
from torch import nn
from torch.autograd import Variable
from torch import optim
# Preparing data for regression
x = Variable(torch.Tensor([[-1. ], [-0.9], [-0.8], [-0.7], [-0.6], [-0.5],
[-0.4], [-0.3], [-0.2], [-0.1], [ 0. ], [ 0.1],
[ 0.2], [ 0.3], [ 0.4], [ 0.5], [ 0.6], [ 0.7],
[ 0.8], [ 0.9], [ 1. ]]), requires_grad=False)
y_true = Variable(torch.Tensor([[32.6 ], [31.62], [30.64], [29.66], [28.68],
[27.7 ], [26.72], [25.74], [24.76], [23.78],
[22.8 ], [21.82], [20.84], [19.86], [18.88],
[17.9 ], [16.92], [15.94], [14.96], [13.98],
[13. ]]), requires_grad=False)
# Creating a Linear Regression Module
# which just involves multiplying a weight
# with the feature value and adding a bias term
class LinearRegression(nn.Module):
def __init__(self):
super(LinearRegression, self).__init__()
# Since there is only a single feature value,
# and the output is a single value, we use
# the Linear module with dimensions 1 X 1.
# It adds a bias term by default
self.linear = nn.Linear(1, 1)
def forward(self, x):
return self.linear(x)
linreg = LinearRegression()
criterion = nn.MSELoss()
optimizer = optim.SGD(linreg.parameters(), lr=0.1)
for i in range(10):
y_pred = linreg(x)
loss = criterion(y_true, y_pred)
print('Loss:', loss.data, 'Parameters:',
list(map(lambda x: x.data, linreg.parameters())))
optimizer.zero_grad()
loss.backward()
optimizer.step()
When we run this code, we get the follwing stack trace:
1
2
3
4
5
6
7
8
9
10
Traceback (most recent call last):
File "/media/saqib/ni/Projects/PyTorch_Practice/LinearRegression-01.py", line 41, in <module>
loss = criterion(y_true, y_pred)
File "/usr/local/lib/python3.6/site-packages/torch/nn/modules/module.py", line 491, in __call__
result = self.forward(*input, **kwargs)
File "/usr/local/lib/python3.6/site-packages/torch/nn/modules/loss.py", line 371, in forward
_assert_no_grad(target)
File "/usr/local/lib/python3.6/site-packages/torch/nn/modules/loss.py", line 12, in _assert_no_grad
"nn criterions don't compute the gradient w.r.t. targets - please " \
AssertionError: nn criterions don't compute the gradient w.r.t. targets - please mark these tensors as not requiring gradients
So, it seems that the error is in line 41. Hmm, but we did say requires_grad=False
when we declared y_true
. So, why did the error occur? Well, let’s try swapping y_true
and y_pred
.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
import torch
from torch import nn
from torch.autograd import Variable
from torch import optim
# Preparing data for regression
x = Variable(torch.Tensor([[-1. ], [-0.9], [-0.8], [-0.7], [-0.6], [-0.5],
[-0.4], [-0.3], [-0.2], [-0.1], [ 0. ], [ 0.1],
[ 0.2], [ 0.3], [ 0.4], [ 0.5], [ 0.6], [ 0.7],
[ 0.8], [ 0.9], [ 1. ]]), requires_grad=False)
y_true = Variable(torch.Tensor([[32.6 ], [31.62], [30.64], [29.66], [28.68],
[27.7 ], [26.72], [25.74], [24.76], [23.78],
[22.8 ], [21.82], [20.84], [19.86], [18.88],
[17.9 ], [16.92], [15.94], [14.96], [13.98],
[13. ]]), requires_grad=False)
# Creating a Linear Regression Module
# which just involves multiplying a weight
# with the feature value and adding a bias term
class LinearRegression(nn.Module):
def __init__(self):
super(LinearRegression, self).__init__()
# Since there is only a single feature value,
# and the output is a single value, we use
# the Linear module with dimensions 1 X 1.
# It adds a bias term by default
self.linear = nn.Linear(1, 1)
def forward(self, x):
return self.linear(x)
linreg = LinearRegression()
criterion = nn.MSELoss()
optimizer = optim.SGD(linreg.parameters(), lr=0.1)
for i in range(10):
y_pred = linreg(x)
loss = criterion(y_pred, y_true)
print('Loss:', loss.data, 'Parameters:',
list(map(lambda x: x.data, linreg.parameters())))
optimizer.zero_grad()
loss.backward()
optimizer.step()
Output:
1
2
3
4
5
6
7
8
9
10
Loss: tensor(543.1290) Parameters: [tensor([[ 0.9388]]), tensor([ 0.4204])]
Loss: tensor(356.8506) Parameters: [tensor([[ 0.1513]]), tensor([ 4.8964])]
Loss: tensor(236.3258) Parameters: [tensor([[-0.5785]]), tensor([ 8.4771])]
Loss: tensor(158.0679) Parameters: [tensor([[-1.2547]]), tensor([ 11.3417])]
Loss: tensor(107.0193) Parameters: [tensor([[-1.8814]]), tensor([ 13.6333])]
Loss: tensor(73.5209) Parameters: [tensor([[-2.4621]]), tensor([ 15.4667])]
Loss: tensor(51.3714) Parameters: [tensor([[-3.0002]]), tensor([ 16.9333])]
Loss: tensor(36.5856) Parameters: [tensor([[-3.4989]]), tensor([ 18.1067])]
Loss: tensor(26.5988) Parameters: [tensor([[-3.9609]]), tensor([ 19.0453])]
Loss: tensor(19.7574) Parameters: [tensor([[-4.3891]]), tensor([ 19.7963])]
It works! It seems that the second argument in criterion expects a Variable
with requires_grad=False
. Since the Variable
computed by by our model, linreg
requires gradients for backpropagation, passing it as a second argument to our MSELoss
criterion caused the error.
Comments