Régression linéaire simple dans Keras

12

Après avoir regardé cette question: en essayant d'émuler la régression linéaire en utilisant Keras , j'ai essayé de rouler mon propre exemple, juste à des fins d'étude et pour développer mon intuition.

J'ai téléchargé un simple ensemble de données et utilisé une colonne pour en prédire une autre. Les données ressemblent à ceci:

télévision-données

Maintenant, je viens de créer un modèle de kéros simple avec une seule couche linéaire à un nœud et j'ai procédé à une descente en gradient sur celui-ci:

from keras.layers import Input, Dense
from keras.models import Model

inputs = Input(shape=(1,))
preds = Dense(1,activation='linear')(inputs)

model = Model(inputs=inputs,outputs=preds)
sgd=keras.optimizers.SGD()
model.compile(optimizer=sgd ,loss='mse',metrics=['mse'])
model.fit(x,y, batch_size=1, epochs=30, shuffle=False)

Faire tourner le modèle comme ça me fait nanperdre à chaque époque.

Lien vers le carnet jupyter

J'ai donc décidé de commencer à essayer des trucs et je n'obtiens un modèle décent que si j'utilise un taux d'apprentissage ridiculement petit sgd=keras.optimizers.SGD(lr=0.0000001) :

télévision équipée de données

Maintenant, pourquoi cela se produit-il? Dois-je régler manuellement le taux d'apprentissage comme celui-ci pour chaque problème que je rencontre? Est-ce que je fais quelque chose de mal ici? C'est censé être le problème le plus simple possible, non?

Merci!

Felipe Almeida
la source

Réponses:

11

C'est probablement parce qu'aucune normalisation n'a été effectuée. Les réseaux de neurones sont très sensibles aux données non normalisées.

Une certaine intuition: lorsque nous essayons de trouver notre minimum global multidimensionnel (comme dans le modèle de descente de gradient stochastique), à ​​chaque itération, chaque caractéristique "tire" dans sa dimension (direction du vecteur) avec une certaine force (la longueur du vecteur ). Lorsque les données ne sont pas normalisées, un petit pas de valeur pour la colonne A peut provoquer un énorme changement dans la colonne B.

Votre code a fait face à cela en utilisant votre taux d'apprentissage très bas, qui a "normalisé" l'effet sur chaque colonne, mais a provoqué un processus d'apprentissage retardé, nécessitant beaucoup plus d'époques pour terminer.

Ajoutez ce code de normalisation:

from sklearn.preprocessing import StandardScaler

sc = StandardScaler()
x = sc.fit_transform(x)
y = sc.fit_transform(y)

Et laissez simplement tomber le paramètre de taux d'apprentissage (lr) - en le laissant choisir judicieusement une valeur automatique pour vous. J'ai le même graphique souhaité que vous maintenant :)

mork
la source
Ça a l'air bien ... la seule chose que je n'aime pas, c'est que j'aurai besoin d'appliquer cette standardisation de la même manière pour tester les entrées, puis la sortie que j'obtiendrai sera également dans un autre ensemble d'unités.
Felipe Almeida
2
C'est vrai @Felipe Almeida, le résultat de sortie devrait être "inversé", mais cela est généralement intégré dans les bibliothèques. Jetez un œil à inverse_transform scikit-learn.org/stable/modules/generated/… et quelques autres méthodes de prétraitement scikit-learn.org/stable/modules/preprocessing.html
mork
2

La normalisation est plus importante lorsque vous avez plusieurs variables dépendantes. Si vous regardez le nuage de points, vous pouvez voir des valeurs aberrantes. Un réseau neuronal sans couches cachées est identique à un modèle de régression linéaire. Ainsi, il s'adapte à la meilleure ligne pour minimiser la distance des résidus. Supprimez les valeurs aberrantes et cela semblera plus approprié.

Samuel Sherman
la source