Наивная классификация с одинарными метками в PyTorch со слоем внедрения не удалась

Я новичок в PyTorch, и я пробую слой встраивания.

Я написал простую классификационную задачу, где все входные данные равны, а все метки установлены на 1,0. Поэтому я ожидаю, что модель быстро научится прогнозировать 1,0.

Вход всегда равен 0, который подается в слой nn.Embedding(1,32), за ним следуют nn.Linear(32,1) и nn.Relu().

Однако происходит неожиданное и нежелательное поведение: результат обучения отличается для разных времен, когда я запускаю код. Например,

  • установка случайного начального числа в 10, модель сходится: потери уменьшаются, и модель всегда предсказывает 1,0
  • при установке случайного начального числа на 1111 модель не сходится: потери не уменьшаются, и модель всегда прогнозирует 0,5. В этих случаях параметры не обновляются

Вот минимальный, воспроизводимый код:

from torch.nn import BCEWithLogitsLoss
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import DataLoader
from torch.autograd import Variable
from torch.utils.data import Dataset
import torch


class MyModel(nn.Module):

    def __init__(self):
        super(MyModel, self).__init__()
        self.vgg_fc = nn.Linear(32, 1)
        self.relu = nn.ReLU()
        self.embeddings = nn.Embedding(1, 32)

    def forward(self, data):
        emb = self.embeddings(data['index'])
        return self.relu(self.vgg_fc(emb))


class MyDataset(Dataset):

    def __init__(self):
        pass
    def __len__(self):
        return 1000
    def __getitem__(self, idx):
        return {'label': 1.0, 'index': 0}


def train():
    model = MyModel()
    db = MyDataset()
    dataloader = DataLoader(db, batch_size=256, shuffle=True, num_workers=16)

    loss_function = BCEWithLogitsLoss()
    optimizer_rel = optim.SGD(model.parameters(), lr=0.1)

    for epoch in range(50):
        for i_batch, sample_batched in enumerate(dataloader):

            model.zero_grad()
            out = model({'index': Variable(sample_batched['index'])})

            labels = Variable(sample_batched['label'].type(torch.FloatTensor).view(sample_batched['label'].shape[0], 1))

            loss = loss_function(out, labels)
            loss.backward()
            optimizer_rel.step()
            print 'Epoch:', epoch, 'batch', i_batch, 'Tr_Loss:', loss.data[0]
    return model


if __name__ == '__main__':

    # please, try seed 10 (converge) and seed 1111 (fails)
    torch.manual_seed(10)
    train()

Без указания случайного начального числа разные прогоны имеют разные результаты.

Почему в этих случаях модель не может выучить такую ​​простую задачу? Есть ли какая-либо ошибка в том, как я использую слой nn.Embedding?

Спасибо

1 ответ

Я обнаружил, что проблема заключалась в последнем релейном слое, перед сигмовидной. Как указано здесь, этот слой будет:

выбрасывать информацию без добавления каких-либо дополнительных преимуществ

Сняв слой, сеть узнала, как и ожидалось, с любым начальным числом.

Другие вопросы по тегам