Почему простая двоичная классификация не работает в нейронной сети с прямой связью? - PullRequest
0 голосов
/ 16 июня 2020

Я новичок в Pytorch. Я пытался смоделировать двоичный классификатор на наборе данных Kepler. Ниже приведен мой класс набора данных.

class KeplerDataset(Dataset):
    def __init__(self, test=False):
        self.dataframe_orig = pd.read_csv(koi_cumm_path)

        if (test == False):
            self.data = df_numeric[( df_numeric.koi_disposition == 1 ) | ( df_numeric.koi_disposition == 0 )].values
        else:
            self.data = df_numeric[~(( df_numeric.koi_disposition == 1 ) | ( df_numeric.koi_disposition == 0 ))].values

        self.X_data = torch.FloatTensor(self.data[:, 1:])
        self.y_data = torch.FloatTensor(self.data[:, 0])

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

    def __getitem__(self, index):
        return self.X_data[index], self.y_data[index]

Здесь я создал настраиваемый класс классификатора с одним скрытым слоем и одним выходным блоком, который дает сигмоидальную вероятность нахождения в классе 1 (pl anet).

class KOIClassifier(nn.Module):
    def __init__(self, input_dim, out_dim):
        super(KOIClassifier, self).__init__()
        self.linear1 = nn.Linear(input_dim, 32)

        self.linear2 = nn.Linear(32, 32)

        self.linear3 = nn.Linear(32, out_dim)


    def forward(self, xb):
        out = self.linear1(xb)
        out = F.relu(out)
        out = self.linear2(out)
        out = F.relu(out)
        out = self.linear3(out)
        out = torch.sigmoid(out)

        return out

Затем я создал функцию train_model для оптимизации потерь с помощью SGD.

def train_model(X, y):
    criterion = nn.BCELoss()

    optim = torch.optim.SGD(model.parameters(), lr=0.001)

    n_epochs = 100
    losses = []

    for epoch in range(n_epochs):
        y_pred = model.forward(X)
        loss = criterion(y_pred, y)
        losses.append(loss.item())
        optim.zero_grad()
        loss.backward()
        optim.step()

losses = []
for X, y in train_loader:
    losses.append(train_model(X, y))

Но после выполнения оптимизации с помощью train_loader, когда я пытаюсь предсказать на самом trainn_loader, значения прогнозов намного хуже.

for features, y in train_loader:
    y_pred = model.predict(features)
    break

y_pred


> tensor([[4.5436e-02],
        [1.5024e-02],
        [2.2579e-01],
        [4.2279e-01],
        [6.0811e-02],
        .....

Почему моя модель не работает должным образом? Это проблема с набором данных или я что-то делаю не так с реализацией Neural net? Я свяжу мою записную книжку Kaggle, потому что может быть полезно больше контекста. Пожалуйста, помогите.

1 Ответ

2 голосов
/ 16 июня 2020

Вы оптимизируете много раз (100 шагов) для первого пакета (первые образцы), а затем переходите к следующим образцам. Это означает, что ваша модель будет соответствовать вашим нескольким образцам перед переходом к следующей партии. Тогда ваше обучение будет очень негладким, расходящимся и go далеким от вашего глобального оптимума.

Обычно на тренировке l oop вы должны:

  1. go по всем образцам (это одна эпоха)
  2. перетасуйте ваш набор данных, чтобы просмотреть образцы в другом порядке (соответственно установите загрузчик обучения pytorch)
  3. go обратно в 1. пока вы не достигнете максимального количества эпох

Также вам не следует каждый раз определять свой оптимизатор (или ваш критерий).

Ваше обучение l oop должно выглядеть так:

criterion = nn.BCELoss()
optim = torch.optim.SGD(model.parameters(), lr=0.001)
n_epochs = 100

def train_model():
    for X, y in train_loader:
        optim.zero_grad()
        y_pred = model.forward(X)
        loss = criterion(y_pred, y)
        loss.backward()
        optim.step()

for epoch in range(n_epochs):
    train_model()
...