如何更简单方便的定义pytorch fullyconnect模型?

How to define pytorch fullyconnect model more simple and convenient?

我是pytorch初学者,想用Pytorch搭建一个全连接模型

模型非常简单,如:

def forward(self, x):
    x = self.relu(self.fc1(x))
    x = self.relu(self.fc2(x))
    return self.fc3(x)

但是当我想添加一些层或调整隐藏层时,我发现我必须写很多冗余代码,例如:

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)

此外,如果我想改变某些层的特征数,我必须改变相邻的层

所以我想知道一种更优雅的方法(可能更像pythonic并且更容易调整超参数)。

我尝试编写如下代码:

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

但是我发现这种方式不行,模型建不出来

哪位兄弟能告诉我,如何定义一个像上面那样的全连接模型??

(所以我只能通过调整名为hidden_num的列表来调整模型层

如果你想保持相同的方法,那么你可以使用 nn.ModuleList 在模块的 __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

但是,您可能希望处理 __init__ 函数中的逻辑 once。一种替代方法是使用 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

理想情况下,您可以直接继承 nn.Sequential 以避免重写在这种情况下不必要的前向函数:

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)