Применение любой оптимизации приводит к значению NaN - PullRequest
0 голосов
/ 20 января 2019

Я работаю над моделью классификатора для этого набора данных: https://archive.ics.uci.edu/ml/datasets/ILPD+%28Indian+Liver+Patient+Dataset%29 и я придумал этот код в pytorch:

import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from sklearn import preprocessing
from sklearn.model_selection import train_test_split
import pandas as pd
import numpy as np


ILPDataset = pd.read_csv('preprocessed-ilpd.csv')
ILPDataset["Age"] = pd.to_numeric(ILPDataset["Age"])
LabelEncoder = preprocessing.LabelEncoder()
LabelEncoder.fit(ILPDataset["Gender"])
ILPDataset["Gender"] = LabelEncoder.transform(ILPDataset["Gender"])
print(ILPDataset["Gender"].describe())
ILPDataset["AAP"] = preprocessing.scale(ILPDataset["AAP"])
ILPDataset["SgAlAm"] = preprocessing.scale(ILPDataset["SgAlAm"])
ILPDataset["SgApAm"] = preprocessing.scale(ILPDataset["SgApAm"])
Features = ["Age","Gender","TB","DB","AAP","SgAlAm","SgApAm","TP","ALB","A/G"]
ILPDFeatures = ILPDataset[Features]
ILPDTarget = ILPDataset["Selector"]

X_Train, X_Test, Y_Train, Y_Test = train_test_split(ILPDFeatures,ILPDTarget,test_size=0.2,random_state=0)

print(X_Train.shape)
print(Y_Train.shape)
print(X_Test.shape)
print(Y_Test.shape)
torch.set_default_tensor_type(torch.DoubleTensor)
TrainX = torch.from_numpy(X_Train.values).double()
TestX = torch.from_numpy(X_Test.values).double()


TrainY = torch.from_numpy(Y_Train.values).long().view(1,-1)[0]
TestY = torch.from_numpy(Y_Test.values).long().view(1,-1)[0]
TrainY.reshape(TrainY.shape[0],1)
TestY.reshape(TestY.shape[0],1)
print(X_Train.shape[1])
input_layers = X_Train.shape[1]
output_layers = 2
hidden = 100

class Net(nn.Module):
    def __init__(self):
        super(Net,self).__init__()
        self.fc1 = nn.Linear(input_layers,hidden)
        self.fc2 = nn.Linear(hidden,hidden)
        self.fc3 = nn.Linear(hidden,output_layers)

    def forward(self,x):
        x = torch.sigmoid(self.fc1(x))
        x = torch.sigmoid(self.fc2(x))
        x = self.fc3(x)
        return F.softmax(x,dim=-1)

model = Net()
optimizer = torch.optim.SGD(model.parameters(),lr = 0.0001,momentum = 0.9)
loss_fn = nn.NLLLoss()
epochs_data = []
epochs = 601
print(TrainX.shape)
print(TestY.shape)
for epoch in range(1,3):
    optimizer.zero_grad()
    Ypred = model(TrainX)
    loss = loss_fn(Ypred,TrainY)
    loss.backward()
    optimizer.step()
    print(Ypred)
    if epoch%100==0:
        print("Epoch - %d, (%d%%) "%(epoch,epoch/epochs*100))

YPred_Test = model(TestX)
Loss_Test = loss_fn(YPred_Test,TestY)
print(Loss_Test.item())
print(YPred_Test)
print(YPred_Test)
print(TestY)

Я использовал разные оптимизаторы с разными значениями LR и Momentum, но при применении каждого из них после loss.backward () он превращает значения в тензоре в NaN. Я посмотрел разные ответы на SO, но даже попробовав их, я не смог устранить ошибку.

Ответы [ 2 ]

0 голосов
/ 03 февраля 2019

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

0 голосов
/ 21 января 2019

Проблема в том, что вы используете softmax с NLLLoss, который не работает вместе. Документация на softmax гласит:

Этот модуль не работает напрямую с NLLLoss, который ожидает журнал рассчитываться между Softmax и собой. Вместо этого используйте LogSoftmax (это быстрее и имеет лучшие числовые свойства).

Используйте log_softmax в последнем слое с NLLLoss следующим образом:

def forward(self,x):
    ...
    return F.log_softmax(x,dim=-1)
...
loss_fn = nn.NLLLoss()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...