I'm new to CNN implementation in Python. I need to use a specific template to create a convolutional layer. While trying to run I get an error that I don't know how to fix.
RuntimeError: Can't call NumPy() on Tensor that requires grad. Use tensor.detach().numpy() instead.
It seems that the problem is that Numpy can't execute the dot product of two tensors. Any suggestion for how can I fix the problem?
This is the code:
import torch
import numpy as np
import torch.nn as nn
from time import time
class MyConv2d(nn.Module):
""" Custom Convolution layer should have similar behavior as nn.Conv2D """
def __init__(self, in_channels, out_channels, kernel_size): # in_channel = the first
super().__init__() # Inherit nn.Module fields and methods (basic neuronal network class)
# assume a symmetric kernel, no padding, and no stride
self.c_in, self.c_out, self.kernel = in_channels, out_channels, kernel_size # Creat fields
# self.weights: Filter weights of shape (self.cout, self.c_in, self.kernel, self.kernel)
weights = torch.Tensor(out_channels, in_channels, kernel_size, kernel_size)
self.weights = nn.Parameter(weights) # nn.Parameter is a Tensor that's a module parameter.
# self.bias: bias weights of dim (self.out)
bias = torch.zeros(out_channels)
self.bias = nn.Parameter(bias)
def set_weights(self, w, b):
# before assigning the weights make sure they are of the correct dimensions (use the assert)
# give a proper error to the user
##########################################
assert self.weights.shape == w.shape, "Weights are in the wrong dimension"
assert self.bias.shape == b.shape, "Bias are in the wrong dimension"
###########################################
self.weights = w # The fields will get the values of w,b
self.bias = b
def forward(self, x):
# Input:
N, C_in, H, W = x.shape
# check input dimension ?
###########################################
self.x = x
assert self.x.shape == (N, C_in, H, W)
#########################################
out_H = (self.x.shape[2] - self.kernel) + 1 # = 6
out_W = (self.x.shape[3] - self.kernel) + 1 # = 4
# print(f"Output's height: {out_H}, Output's width: {out_W}")
#########################################
# Now implement the convolution:
# run the filter on all the input pixels (on all the channels) to produce an output tensor
########################################
out = np.dot(self.x, self.weights) + self.bias # x tensor: (3,3,8,6), weights tensor: (16,3,3,3)
#########################################
return out
#### Now let's compare the custom implementation with that of torch
IN_CHANNELS = 3
OUT_CHANNELS = 16
KERNEL_SIZE = 3
BATCH_NUM = 3
HEIGHT = 8
WIDTH = 6
# define our layer and the official pytorch layer
my_conv_layer = MyConv2d(IN_CHANNELS, OUT_CHANNELS, KERNEL_SIZE)
pt_conv = nn.Conv2d(in_channels=IN_CHANNELS, out_channels=OUT_CHANNELS, kernel_size=KERNEL_SIZE)
# assign torch weights into your implementation to allow comparison
my_conv_layer.set_weights(pt_conv.weight, pt_conv.bias)
# generate random input
x = torch.randn(BATCH_NUM, IN_CHANNELS, HEIGHT, WIDTH)
# call the forward function
start_time = time()
m = my_conv_layer(x) # Here is the problem: RuntimeError: Can't call numpy() on Tensor that requires grad. Use tensor.detach().numpy() instead.
t1 = time()
p = pt_conv(x)
t2 = time()
# if average is smaller than e-7 then you are doing fine
print("Average difference between implementations: \n", (torch.sum(m-p)/p.nelement()).item())
print("Your implementation is ", (t1-start_time)/(t2-t1), " slower than pytorch implementation.")
This is the Traceback:
Traceback (most recent call last):
File "C:\Python\Deep_learning\Exercises\pythonProject1\A2_conv_layer.py", line 85, in <module>
m = my_conv_layer(x) # Here is the problem: RuntimeError: Can't call numpy() on Tensor that requires grad. Use tensor.detach().numpy() instead.
File "C:\Python\lib\site-packages\torch\nn\modules\module.py", line 1190, in _call_impl
return forward_call(*input, **kwargs)
File "C:\Python\Deep_learning\Exercises\pythonProject1\A2_conv_layer.py", line 56, in forward
out = np.dot(self.x, self.weights) + self.bias # x tensor: (3,3,8,6), weights tensor: (16,3,3,3)
File "<__array_function__ internals>", line 5, in dot
File "C:\Python\lib\site-packages\torch\_tensor.py", line 955, in __array__
return self.numpy()
RuntimeError: Can't call numpy() on Tensor that requires grad. Use tensor.detach().numpy() instead.
Process finished with exit code 1