torch.nn.Sequential的等效Split方法?

一个Sequential模块的示例代码是

self._encoder = nn.Sequential(        # 1, 28, 28        nn.Conv2d(in_channels=1, out_channels=32, kernel_size=3, stride=3, padding=1),        # 32, 10, 10 = 16, (1//3)(28 + 2 * 1 - 3) + 1, (1//3)(28 + 2*1 - 3) + 1        nn.ReLU(True),        nn.MaxPool2d(kernel_size=2, stride=2),        # 32, 5, 5        nn.Conv2d(in_channels=32, out_channels=64, kernel_size=3, stride=2, padding=1),        # 64, 3, 3        nn.ReLU(True),        nn.MaxPool2d(kernel_size=2, stride=1),        # 64, 2, 2)

是否有类似于nn.Sequential的结构,可以并行地放置模块?

我想定义类似这样的内容

self._mean_logvar_layers = nn.Parallel(    nn.Conv2d(in_channels=64, out_channels=64, kernel_size=2, stride=1, padding=0),    nn.Conv2d(in_channels=64, out_channels=64, kernel_size=2, stride=1, padding=0),)

其输出应该是两条数据流 – 每条对应self._mean_logvar_layers中的一个元素,然后可以喂给网络的其余部分。有点像多头网络。


我当前的实现是:

self._mean_layer = nn.Conv2d(in_channels=64, out_channels=64, kernel_size=2, stride=1, padding=0)self._logvar_layer = nn.Conv2d(in_channels=64, out_channels=64, kernel_size=2, stride=1, padding=0)

def _encode(self, x: torch.Tensor) -> Tuple[torch.Tensor, torch.Tensor]:    for i, layer in enumerate(self._encoder):        x = layer(x)    mean_output = self._mean_layer(x)    logvar_output = self._logvar_layer(x)    return mean_output, logvar_output

我想将并行结构视为一个层。

在PyTorch中这是可行的吗?


回答:

Sequential的分裂

你可以创建一个Parallel模块(尽管我会给它起一个不同的名字,因为它暗示了代码实际上是并行运行的,可能Split会是一个好名字),如下所示:

class Parallel(torch.nn.Module):    def __init__(self, *modules: torch.nn.Module):        super().__init__()        self.modules = modules    def forward(self, inputs):        return [module(inputs) for module in self.modules]

现在你可以按你想要的方式定义它:

self._mean_logvar_layers = Parallel(    nn.Conv2d(in_channels=64, out_channels=64, kernel_size=2, stride=1, padding=0),    nn.Conv2d(in_channels=64, out_channels=64, kernel_size=2, stride=1, padding=0),)

并像这样使用它:

mean, logvar = self._mean_logvar_layers(x)

单层和分裂

@***所建议,我们可以使用单一层并按通道进行分裂,使用以下模块:

class Split(torch.nn.Module):    def __init__(self, module, parts: int, dim=1):        super().__init__()        self.parts        self.dim = dim        self.module = module    def forward(self, inputs):        output = self.module(inputs)        chunk_size = output.shape[self.dim] // self.parts        return torch.split(output, chunk_size, dim=self.dim)

这在你的神经网络中(注意128个通道,这些将被分成2部分,每部分大小为64):

self._mean_logvar_layers = Split(    nn.Conv2d(in_channels=64, out_channels=128, kernel_size=2, stride=1, padding=0),    parts=2,)

并像之前一样使用它:

mean, logvar = self._mean_logvar_layers(x)

为什么选择这种方法?

一切都会一次性完成,而不是顺序进行,因此更快,但如果你的GPU内存不够,可能会太宽。

可以与Sequential一起工作吗?

是的,它仍然是一个层。但接下来的层必须处理tuple(torch.Tensor, torch.Tensor)作为输入。

Sequential也是一个层,相当简单的一个,让我们看看forward

def forward(self, inp):    for module in self:        inp = module(inp)    return inp

它只是将前一个模型的输出传递给下一个模型,仅此而已。

Related Posts

使用LSTM在Python中预测未来值

这段代码可以预测指定股票的当前日期之前的值,但不能预测…

如何在gensim的word2vec模型中查找双词组的相似性

我有一个word2vec模型,假设我使用的是googl…

dask_xgboost.predict 可以工作但无法显示 – 数据必须是一维的

我试图使用 XGBoost 创建模型。 看起来我成功地…

ML Tuning – Cross Validation in Spark

我在https://spark.apache.org/…

如何在React JS中使用fetch从REST API获取预测

我正在开发一个应用程序,其中Flask REST AP…

如何分析ML.NET中多类分类预测得分数组?

我在ML.NET中创建了一个多类分类项目。该项目可以对…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注