Как использовать Pytorch для создания многозадачного DNN, например, для более чем 100 задач? - PullRequest
2 голосов
/ 16 января 2020

Ниже приведен пример кода для использования pytorch для создания DNN для двух задач регрессии. Функция forward возвращает два выхода (x1, x2). Как насчет сети для множества задач регрессии / классификации? например, 100 или 1000 выходов. Определенно не очень хорошая идея жестко закодировать все выходные данные (например, x1, x2, ..., x100). Есть ли простой способ сделать это? Спасибо.

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

class mynet(nn.Module):
    def __init__(self):
        super(mynet, self).__init__()
        self.lin1 = nn.Linear(5, 10)
        self.lin2 = nn.Linear(10, 3)
        self.lin3 = nn.Linear(10, 4)

    def forward(self, x):
        x = self.lin1(x)
        x1 = self.lin2(x)
        x2 = self.lin3(x)
        return x1, x2

if __name__ == '__main__':
    x = torch.randn(1000, 5)
    y1 = torch.randn(1000, 3)
    y2 = torch.randn(1000,  4)
    model = mynet()
    optimizer = torch.optim.Adam(model.parameters(), lr=0.001, weight_decay=1e-4)
    for epoch in range(100):
        model.train()
        optimizer.zero_grad()
        out1, out2 = model(x)
        loss = 0.2 * F.mse_loss(out1, y1) + 0.8 * F.mse_loss(out2, y2)
        loss.backward()
        optimizer.step()

1 Ответ

2 голосов
/ 16 января 2020

Вы можете (и должны) использовать nn контейнеры , такие как nn.ModuleList или nn.ModuleDict для управления произвольным количеством субмодулей.

Например (с использованием nn.ModuleList):

class MultiHeadNetwork(nn.Module):
    def __init__(self, list_with_number_of_outputs_of_each_head):
        super(MultiHeadNetwork, self).__init__()
        self.backbone = ...  # build the basic "backbone" on top of which all other heads come
        # all other "heads"
        self.heads = nn.ModuleList([])
        for nout in list_with_number_of_outputs_of_each_head:
            self.heads.append(nn.Sequential(
              nn.Linear(10, nout * 2),
              nn.ReLU(inplace=True),
              nn.Linear(nout * 2, nout)))

    def forward(self, x):
        common_features = self.backbone(x)  # compute the shared features
        outputs = []
        for head in self.heads:
            outputs.append(head(common_features))
        return outputs

Обратите внимание, что в этом примере каждая головка сложнее, чем один nn.Linear слой.
Количество различных «головок» (и количество выходов) определяется длиной аргумента list_with_number_of_outputs_of_each_head.


Важное замечание: крайне важно использовать nn контейнеры , а не простые списки / словарь pythoni c для хранения всех подмодулей. В противном случае pytorch будет трудно управлять всеми подчиненными модулями.
См., Например, этот ответ , этот вопрос и этот .

...