How to define pytorch fullyconnect model more simple and convenient?
i am a beginner of pytorch, and i want to build a fully connect model using Pytorch;
the model is very simple like:
def forward(self, x):
    x = self.relu(self.fc1(x))
    x = self.relu(self.fc2(x))
    return self.fc3(x)

but when i want to add some layers or adjust the hidden layers, i found i have to write lots of Redundant code like:
def forward(self, x):
    x = self.relu(self.fc1(x))
    x = self.relu(self.fc2(x))
    x = self.relu(self.fc3(x))
    x = self.relu(self.fc4(x))
    x = self.relu(self.fc5(x))
    ...
    return self.fcn(x)

besides, if i want to change some layer's feature nums, i have to change the layer adjacent
so i want to know a way which is more grace(maybe more pythonic and more easy to adjust hyper parameter).
i tried to write code like:
def __init__(self):
        super().__init__()
        self.hidden_num = [2881, 5500, 2048, 20] # i just want to change here! to try some new structure
        self.fc = [nn.Linear(self.hidden_num[i], self.hidden_num[i + 1]).to(DEVICE)  for i in range(len(self.hidden_num) - 1)] 
        self.relu = nn.ReLU()

    def forward(self, x):
        for i in range(len(self.fc)):
            x = self.fc[i](x)
            if i != (len(self.fc) - 1):
                x = self.relu(x)
        return x

but i found this way doesn't work, the model can't be built
so could any bro tell me, how to define a fullyconnect model like above??
(so i can adjust the model layers only by adjust the list named hidden_num )

If you want to keep the same approach then you can use nn.ModuleList to properly register all linear layers inside the module's __init__:
class Model(nn.Module):
    def __init__(self, hidden_num=[2881, 5500, 2048, 20]):
        super().__init__()
        self.fc = nn.ModuleList([
            nn.Linear(hidden_num[i], hidden_num[i+1]) 
               for i in range(len(hidden_num) - 1)])

    def forward(self, x):
        for i, m in enumerate(self.fc.children()):
            x = m(x)
            print(i)
            if i != len(self.fc) - 1:
                x = torch.relu(x)
        return x


However, you may want to handle the logic inside the __init__ function once. One alternative is to use nn.Sequential.
class Model(nn.Module):
    def __init__(self, hidden_num=[2881, 5500, 2048, 20]):
        super().__init__()

        fc = []
        for i in range(len(hidden_num) - 1):
            fc.append(nn.Linear(hidden_num[i], hidden_num[i+1]))
            if i != len(self.fc) - 1:
                fc.append(nn.ReLU())

        self.fc = nn.Sequential(fc)

    def forward(self, x):
        x = self.fc(x)
        return x

Ideally, you would inherit from nn.Sequential directly to avoid re-writing the forward function which is unnecessary in this case:
class Model(nn.Sequential):
    def __init__(self, hidden_num=[2881, 5500, 2048, 20]):
        fc = []
        for i in range(len(hidden_num) - 1):
            fc.append(nn.Linear(hidden_num[i], hidden_num[i+1]))
            if i != len(self.fc) - 1:
                fc.append(nn.ReLU())

        super().__init__(fc)

