0

J'ai modifié le code que j'ai trouvé sur le github de Pytorch pour convenir à mes données, mais mes résultats de perte sont énormes et à chaque itération ils grossissent et deviennent plus tard nan.Code ne me donne pas toutes les erreurs, juste ni les résultats de perte et aucune prédiction. J'ai un autre code qui traite de la régression linéaire simple et tout fonctionne bien. Je suppose qu'il me manque quelque chose de simple ici, mais je suis incapable de le voir. Toute aide serait appréciée.Pytorch et régression linéaire polynomiale numéro

code:

import sklearn.linear_model as lm 
from sklearn.preprocessing import PolynomialFeatures 
import torch 
import torch.autograd 
import torch.nn.functional as F 
from torch.autograd import Variable 


train_data = torch.Tensor([ 
    [40, 6, 4], 
    [44, 10, 4], 
    [46, 12, 5], 
    [48, 14, 7], 
    [52, 16, 9], 
    [58, 18, 12], 
    [60, 22, 14], 
    [68, 24, 20], 
    [74, 26, 21], 
    [80, 32, 24]]) 
test_data = torch.Tensor([ 
    [6, 4], 
    [10, 5], 
    [4, 8]]) 

x_train = train_data[:,1:3] 
y_train = train_data[:,0] 

POLY_DEGREE = 3 
input_size = 2 
output_size = 1 

poly = PolynomialFeatures(input_size * POLY_DEGREE, include_bias=False) 
x_train_poly = poly.fit_transform(x_train.numpy()) 


class Model(torch.nn.Module): 

    def __init__(self): 
     super(Model, self).__init__() 
     self.fc = torch.nn.Linear(poly.n_output_features_, output_size) 

    def forward(self, x): 
     return self.fc(x) 

model = Model()  
criterion = torch.nn.MSELoss() 
optimizer = torch.optim.SGD(model.parameters(), lr=0.001) 

losses = [] 

for i in range(10): 
    optimizer.zero_grad() 
    outputs = model(Variable(torch.Tensor(x_train_poly))) 
    print(outputs) 
    loss = criterion(outputs, Variable(y_train)) 
    print(loss.data[0]) 
    losses.append(loss.data[0]) 
    loss.backward()  
    optimizer.step() 
    if loss.data[0] < 1e-4: 
     break  

print('n_iter', i) 
print(loss.data[0]) 
plt.plot(losses) 
plt.show() 

sortie:

[393494300459008,0, inf, inf, inf, nan, nan, nan, nan, nan, nan]

n_iter

9 nan

Répondre

0

Il y a deux ou trois choses qui contribuent au problème. Changer tout ou partie d'entre eux vous donnera des résultats raisonnables et rendra l'apprentissage possible.

  1. Certaines de vos fonctions (polynomiales) ont une grande variance et prennent de très grandes valeurs. Consultez np.max(x_train_poly). Lorsque votre matrice de poids est initialisée de manière aléatoire, les prédictions initiales sont largement désactivées et la perte se rapproche rapidement de l'infini. Pour contrecarrer cela, vous pouvez d'abord standardiser vos caractéristiques (c'est-à-dire faire 0 moyen et variance 1 pour chaque fonctionnalité). Notez que dans les réseaux très profonds, une idée similaire est utilisée, appelée «normalisation par lots». Si vous êtes intéressé, vous pouvez en lire plus ici: https://arxiv.org/abs/1502.03167 Vous pouvez faire ce qui suit pour fixer votre exemple:

    means = np.mean(x_train_poly,axis=0,keepdims=True) 
    std = np.std(x_train_poly,axis=0,keepdims=True) 
    x_train_poly = (x_train_poly - means)/std 
    
  2. Votre modèle actuel, n'a pas de couches cachées, qui est en quelque sorte le point de un réseau de neurones et la construction d'un régresseur/classificateur non linéaire. Ce que vous êtes en train de faire est d'appliquer une transformation linéaire aux 27 fonctions d'entrée pour obtenir quelque chose qui est proche de la sortie. Vous pouvez ajouter une couche supplémentaire comme ceci:

    hidden_dim = 50 
    
    class Model(torch.nn.Module): 
        def __init__(self): 
         super(Model, self).__init__() 
         self.layer1 = torch.nn.Linear(poly.n_output_features_, hidden_dim) 
         self.layer2 = torch.nn.Linear(hidden_dim, output_size) 
    
        def forward(self, x): 
         return self.layer2(torch.nn.ReLU()(self.layer1(x))) 
    

    Notez que j'ai ajouté une non-linéarité après la première transformation linéaire, car sinon il est inutile d'avoir plusieurs couches.

  3. Le problème des prédictions initiales qui sont fortement éteintes au début et conduisent à la perte approchant l'infini. Vous utilisez une perte au carré qui double l'ordre de grandeur de votre "erreur" initiale dans la fonction de perte. Et une fois que la perte est infinie, vous ne pourrez pas vous échapper, car les mises à jour de gradient sont essentiellement aussi infinies car vous utilisez la perte au carré. Une solution facile qui est parfois utile consiste à utiliser la perte L1 lisse à la place. Essentiellement MSE sur l'intervalle [0, 1] et perte L1 en dehors de cet intervalle. Modifier les éléments suivants:

    criterion = torch.nn.SmoothL1Loss() 
    
  4. qui vous obtient déjà quelque chose de sensible (à savoir pas infs plus), mais maintenant envisager de régler le taux d'apprentissage et l'introduction weight_decay. Vous pouvez également vouloir changer l'optimiseur. Voici quelques suggestions qui fonctionne bien:

    optimizer = torch.optim.SGD(model.parameters(), lr=0.01, weight_decay=1) 
    optimizer = torch.optim.Adam(model.parameters(), lr=0.01, weight_decay=0.1)