a-f-a
a-f-a

Reputation: 147

Pytorch 'Tensor' object is not callable

I am trying to apply sobel filter to my network. I am getting this error : "'Tensor' object is not callable" Here is my code:

class SobelFilter(nn.Module):
    def __init__(self):
        super(SobelFilter, self).__init__()

        kernel1=torch.Tensor([[1, 0, -1],[2,0,-2],[1,0,-1]])
        kernela=kernel1.expand((1,1,3,3))

        kernel2=torch.Tensor([[1, 2, 1],[0,0,0],[-1,-2,-1]])
        kernelb=kernel2.expand((1,1,3,3))

        inputs = torch.randn(1,1,64,128)

        self.conv1 = F.conv2d(inputs,kernela,stride=1,padding=1)
        self.conv2 = F.conv2d(inputs,kernelb,stride=1,padding=1)

    def forward(self, x ):

        print(x.shape)
        G_x = self.conv1(x)    %GIVES ERROR AT THIS LINE
        G_y = self.conv2(x)
        out = torch.sqrt(torch.pow(G_x,2)+ torch.pow(G_y,2))

        return out
class EXP(nn.Module):
    def __init__(self, maxdisp):
        super(EXP, self).__init__()
        self.device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
        self.SobelFilter = SobelFilter()

    def forward(self, im):
        % just think "im" to be [1,32,64,128]

        for i in range(im.shape[1]):
            out1= im[:,i,:,:].unsqueeze(1)
            im[:,i,:,:] = self.SobelFilter(out1)

what can cause the problem? Thank you!

Upvotes: 0

Views: 4353

Answers (1)

Manuel Lagunas
Manuel Lagunas

Reputation: 2751

I think your issue is that you are using torch.nn.functional instead of just torch. The purpose of the functional API is to perform the operations (in this case the conv2d) directly, without creating a class instance and then calling its forward method. Therefore, the statement self.conv1 = F.conv2d(inputs,kernela,stride=1,padding=1) is already doing the convolution between the input and kernela and what you have in self.conv1is the result of such convolution. There are two approaches here to fix the problem. Use torch.Conv2d inside __init__, where inputs is the channel of the input and not a tensor with the same shape as your real input. And the second approach is to stick with the functional API but move it to the forward() method. What you want to achieve can be done by changing the forward to:

def forward(self, x ):
  print(x.shape)
  G_x = F.conv2d(x,self.kernela,stride=1,padding=1)
  G_y = F.conv2d(x,self.kernelb,stride=1,padding=1)
  out = torch.sqrt(torch.pow(G_x,2)+ torch.pow(G_y,2))
  return out

Note that I made kernela and kernelb class attributes. Thus you should also change the __init__() to

def __init__(self):
  super(SobelFilter, self).__init__()

  kernel1=torch.Tensor([[1, 0, -1],[2,0,-2],[1,0,-1]])
  self.kernela=kernel1.expand((1,1,3,3))

  kernel2=torch.Tensor([[1, 2, 1],[0,0,0],[-1,-2,-1]])
  self.kernelb=kernel2.expand((1,1,3,3))

Upvotes: 1

Related Questions