Наивная классификация с одинарными метками в 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 ответ
Я обнаружил, что проблема заключалась в последнем релейном слое, перед сигмовидной. Как указано здесь, этот слой будет:
выбрасывать информацию без добавления каких-либо дополнительных преимуществ
Сняв слой, сеть узнала, как и ожидалось, с любым начальным числом.