pytorch里面一切自定义操作基本上都是继承nn.Module类来实现的

class Module(object):
    def __init__(self):
    def forward(self, *input):
 
    def add_module(self, name, module):
    def cuda(self, device=None):
    def cpu(self):
    def __call__(self, *input, **kwargs):
    def parameters(self, recurse=True):
    def named_parameters(self, prefix='', recurse=True):
    def children(self):
    def named_children(self):
    def modules(self):  
    def named_modules(self, memo=None, prefix=''):
    def train(self, mode=True):
    def eval(self):
    def zero_grad(self):
    def __repr__(self):
    def __dir__(self):
'''

我们在定义自已的网络的时候,需要继承nn.Module类,并重新实现构造函数__init__和forward这两个方法。但有一些注意技巧:

(1)一般把网络中具有可学习参数的层(如全连接层、卷积层等)放在构造函数__init__()中,当然我也可以吧不具有参数的层也放在里面;

(2)一般把不具有可学习参数的层(如ReLU、dropout、BatchNormanation层)可放在构造函数中,也可不放在构造函数中,如果不放在构造函数__init__里面,则在forward方法里面可以使用nn.functional来代替

(3)forward方法是必须要重写的,它是实现模型的功能,实现各个层之间的连接关系的核心。
执行y = model(x)时,由于LeNet类继承了Module类,而Module这个基类中定义了__call__方法,所以会执行__call__方法,而__call__方法中调用了forward()方法

只要定义类型的时候,实现__call__函数,这个类型就成为可调用的。 换句话说,我们可以把这个类型的对象当作函数来使用

定义__call__方法的类可以当作函数调用

class LeNet(nn.Module):
    def __init__(self):
        super(LeNet, self).__init__()
 
    layer1 = nn.Sequential()
    layer1.add_module('conv1', nn.Conv(1, 6, 3, padding=1))
    layer1.add_moudle('pool1', nn.MaxPool2d(2, 2))
    self.layer1 = layer1
 
    layer2 = nn.Sequential()
    layer2.add_module('conv2', nn.Conv(6, 16, 5))
    layer2.add_moudle('pool2', nn.MaxPool2d(2, 2))
    self.layer2 = layer2
 
    layer3 = nn.Sequential()
    layer3.add_module('fc1', nn.Linear(400, 120))
    layer3.add_moudle('fc2', nn.Linear(120, 84))
    layer3.add_moudle('fc3', nn.Linear(84, 10))
    self.layer3 = layer3
    

  def forward(self, x):
    x = self.layer1(x)
    x = self.layer2(x)
    x = x.view(x.size(0), -1)
    x = self.layer3(x)
    return x
model = LeNet()
y = model(x)