Understanding how nn.Conv2d processes inputs

I was going through various examples in pytorch and was confused by the general implementation of the nn.Conv2d class. For example in the documentation it’s given:

import torch.nn as nn
import torch.nn.functional as F

class Model(nn.Module):
    def __init__(self):
        super(Model, self).__init__()
        self.conv1 = nn.Conv2d(1, 20, 5)
        self.conv2 = nn.Conv2d(20, 20, 5)

    def forward(self, x):
       x = F.relu(self.conv1(x))
       return F.relu(self.conv2(x))

I understand that self.conv1 is an instance of the Conv2d class. However how is the forward pass implemented as simply self.conv1(x)? Why isn’t it self.conv1.forward(x), as defined in the source code for Conv2d?

Because it uses the __call__ method implemented in any nn.Module that applies the forward method. For example:

class MulByFive():
    def __init__(self):
        self.x = 5

    def forward(self, input):
        return self.x * input
    def __call__(self, input):
        return self.forward(input)

module = MulByFive()



Thanks. I get it now.
Also, I just checked the source code, seems pretty complicated. Do you know what the hook function is? Seems to have been mentioned everywhere in the source code