Значение потерь регрессии NN не уменьшается

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

from sklearn.datasets import load_boston
from torch.utils.data.dataset import Dataset
from torch.utils.data import DataLoader
import torch.nn.functional as F
import torch
import torch.nn as nn
import torch.optim as optim

class Net(nn.Module):
    def __init__(self):
        super().__init__()
        self.fc1 = nn.Linear(13, 128)
        self.fc2 = nn.Linear(128, 64)
        self.fc3 = nn.Linear(64, 32)
        self.fc4 = nn.Linear(32, 16)
        self.fc5 = nn.Linear(16,1)

    def forward(self, x):
       x = self.fc1(x)
       x = self.fc2(x)
       x = F.relu(x)
       x = self.fc3(x)
       x = F.relu(x)
       x = self.fc4(x)
       x = F.relu(x)
       return self.fc5(x)

И загрузчик данных:

class BostonData(Dataset):
    __xs = []
    __ys = []

    def __init__(self, train = True):
        df = load_boston()
        index = int(len(df["data"]) * 0.7)
        if train:
            self.__xs = df["data"][0:index]
            self.__ys = df["target"][0:index]
        else:
            self.__xs = df["data"][index:]
            self.__ys = df["target"][index:]

    def __getitem__(self, index):
        return self.__xs[index], self.__ys[index]

    def __len__(self):
        return len(self.__xs)

В своей первой попытке я не добавлял блоки ReLU, но после небольшого исследования я увидел, что их добавление - обычная практика, но для меня это не сработало.

Вот обучающий код:

dset_train = BostonData(train = True)
dset_test = BostonData(train = False)
train_loader = DataLoader(dset_train, batch_size=30, shuffle=True)
test_loader = DataLoader(dset_train, batch_size=30, shuffle=True)


optimizer = optim.Adam(net.parameters(), lr = 0.001)
criterion = torch.nn.MSELoss() 
EPOCHS = 10000

lloss = []

for epoch in range(EPOCHS):
    for trainbatch in train_loader:
        X,y = trainbatch
        net.zero_grad()
        output = net(X.float())
        loss = criterion(output, y)
        loss.backward()
        optimizer.step()
    lloss.append(loss)
    print(loss)

После 10 тыс. Эпох график потерь выглядит следующим образом

введите описание изображения здесь

где я не вижу явного снижения. Я не знаю, ошибаюсь ли я с torch.nn.MSELoss(), optimizer или, может быть, с сетевой топологией, поэтому любая помощь будет принята с благодарностью.

Изменить: изменение скорости обучения и нормализация данных для меня не сработало. Я добавил строку self.__xs = (self.__xs - self.__xs.mean()) / self.__xs.std() и изменение на lr = 0.01. Сюжет потерь очень похож на первый.

Тот же график для lr = 0,01 и нормализации после 1000 эпох:

введите описание изображения здесь


person Norhther    schedule 10.10.2019    source источник
comment
@Shai Я проверил ответ. Нормализация данных и изменение скорости обучения у меня не сработали.   -  person Norhther    schedule 10.10.2019
comment
@Norhther Вы пробовали использовать другие оптимизаторы (кроме Адама)?   -  person Mohammad Zeineldeen    schedule 10.10.2019
comment
@MohammadZeineldeen SGD работает очень похоже   -  person Norhther    schedule 10.10.2019
comment
@Norhther, а вы тоже настраивали скорость обучения для SGD?   -  person Mohammad Zeineldeen    schedule 10.10.2019
comment
@Norther Может быть, попробуйте более мелкую NN (меньшее количество слоев или размер).   -  person Mohammad Zeineldeen    schedule 10.10.2019
comment
@Shai Он утверждает, что выразительность глубокой линейной сети точно такая же, как у одного линейного слоя. Это именно то, что я сказал (укладка линейных слоев не принесет вам пользы). Единственное изменение будет с точки зрения оптимизации обратного распространения градиентов.   -  person Mohammad Zeineldeen    schedule 10.10.2019
comment
Вы пытались изменить скорость обучения?   -  person nikhilbalwani    schedule 14.10.2019
comment
@nikhilbalwani да, см. правку   -  person Norhther    schedule 14.10.2019


Ответы (1)


вы добавляете lloss один раз за эпоху, и это правильно, но вы добавляете с помощью loss (используя только последний пакет), где вы должны добавить с помощью avg_train_loss

Пытаться:

for epoch in range(EPOCHS):
    avg_train_loss = 0
    for trainbatch in train_loader:
        X,y = trainbatch
        net.zero_grad()
        output = net(X.float())
        loss = criterion(output, y)
        loss.backward()
        optimizer.step()
        avg_train_loss += loss.item() / len(train_loader)
    lloss.append(avg_train_loss)
person Ioannis Nasios    schedule 15.10.2019
comment
Большое спасибо! Также была проблема с несоответствием между размером output и criterion(output,y), добавление loss = criterion(output[:, -1], y) заставило его работать. - person Norhther; 15.10.2019