Тензорный выход из последнего слоя имеет неправильную форму в PyTorch - PullRequest
2 голосов
/ 05 марта 2020

Я строю классификатор последовательности для метки, где входные данные являются текстовыми последовательностями, а выходные метки являются двоичными. Модель очень проста, со скрытыми слоями GRU и входным слоем Word Embeddings. Я хочу, чтобы вход [n, 60] выводил метку [n, 1], но модель Torch возвращает вывод [n, 60].

Моя модель с минимальными слоями:

class Model(nn.Module):
    def __init__(self, weights_matrix, hidden_size, num_layers):
        super(Model, self).__init__()
        self.embedding, num_embeddings, embedding_dim = create_emb_layer(weights_matrix, True)
        self.hidden_size = hidden_size
        self.num_layers = num_layers
        self.gru = nn.GRU(embedding_dim, hidden_size, num_layers, batch_first=True)
        self.out = nn.Linear(hidden_size, 1)
    def forward(self, inp, hidden):
        emb = self.embedding(inp);
        out, hidden = self.gru(emb, hidden)
        out = self.out(out);
        return out, hidden;

    def init_hidden(self, batch_size):
        return torch.zeros(self.num_layers, batch_size, self.hidden_size).to(device);

Слои модели :

Model(
  (embedding): Embedding(184901, 100)
  (gru): GRU(100, 60, num_layers=3, batch_first=True)
  (out): Linear(in_features=60, out_features=1, bias=True)
)

Форма ввода моих данных: X: torch.Size([64, 60]) и Y: torch.Size([64, 1]) для одной партии размером 64.

Когда я пропустите тензор X через модель, он должен вывести одну метку, однако вывод из классификатора будет torch.Size([64, 60, 1]). Чтобы запустить модель, я делаю следующее:

for epoch in range(1):
    running_loss = 0.0;

    batch_size = 64;
    hidden = model.init_hidden(batch_size)
    for ite, data in enumerate(train_loader, 0):
        x, y = data[:,:-1], data[:,-1].reshape(-1,1)

        optimizer.zero_grad();

        outputs, hidden = model(x, hidden);

        hidden = Variable(hidden.data).to(device);
        loss = criterion(outputs, y);

        loss.backward();
        optimizer.step();

        running_loss = running_loss + loss.item();
        if ite % 2000 == 1999:
            print('[%d %5d] loss: %.3f'%(epoch+1, ite+1, running_loss / 2000))
        running_loss = 0.0;

Когда я печатаю shape из outputs, это 64x60x1, а не 64x1. Чего я также не понимаю, так это то, как функция criterion может рассчитывать потери, когда формы выходных данных и меток несовместимы. С Tensorflow это всегда выдает ошибку, но не с Torch.

1 Ответ

1 голос
/ 05 марта 2020

Выходные данные вашей модели имеют форму torch.Size([64, 60, 1]), т. Е. 64 - размер партии, а (60, 1) соответствует [n, 1], как и ожидалось.

Предполагается, что вы используете nn.CrossEntropy(input, target), ожидалось, что входное значение будет (N,C), а целевое значение будет (N), где C - это число классов.

Ваш вывод соответствует и, следовательно, потери оцениваются.

Например,

outputs = torch.randn(3, 2, 1)
target = torch.empty(3, 1, dtype=torch.long).random_(2)

criterion = nn.CrossEntropyLoss(reduction='mean')
print(outputs)
print(target)
loss = criterion(outputs, target)
print(loss)

# outputs
tensor([[[ 0.5187],
         [ 1.0320]],

        [[ 0.2169],
         [ 2.4480]],

        [[-0.4895],
         [-0.6096]]])
tensor([[0],
        [1],
        [0]])
tensor(0.5731)

Подробнее здесь .

...