La formation d'un réseau de neurones pour la régression prédit toujours la moyenne

9

Je forme un réseau neuronal convolutionnel simple pour la régression, où la tâche consiste à prédire l'emplacement (x, y) d'une boîte dans une image, par exemple:

entrez la description de l'image ici

entrez la description de l'image ici

entrez la description de l'image ici

entrez la description de l'image ici

entrez la description de l'image ici

La sortie du réseau a deux nœuds, un pour x et un pour y. Le reste du réseau est un réseau neuronal convolutif standard. La perte est une erreur quadratique moyenne standard entre la position prévue de la boîte et la position de vérité au sol. Je m'entraîne sur 10000 de ces images, et valide sur 2000.

Le problème que j'ai, c'est que même après un entraînement important, la perte ne diminue pas vraiment. Après avoir observé la sortie du réseau, je remarque que le réseau a tendance à produire des valeurs proches de zéro, pour les deux nœuds de sortie. En tant que tel, la prédiction de l'emplacement de la boîte est toujours le centre de l'image. Il y a une certaine déviation dans les prédictions, mais toujours autour de zéro. Ci-dessous montre la perte:

entrez la description de l'image ici

J'ai exécuté cela pendant beaucoup plus d'époques que ce qui est montré dans ce graphique, et la perte ne diminue toujours jamais. Fait intéressant ici, la perte augmente en fait à un moment donné.

Il semble donc que le réseau prédit simplement la moyenne des données de formation, plutôt que d'apprendre un bon ajustement. Des idées sur pourquoi cela peut être? J'utilise Adam comme optimiseur, avec un taux d'apprentissage initial de 0,01, et relus comme activations


Si vous êtes intéressé par certains de mes codes (Keras), c'est ci-dessous:

# Create the model
model = Sequential()
model.add(Convolution2D(32, 5, 5, border_mode='same', subsample=(2, 2), activation='relu', input_shape=(3, image_width, image_height)))
model.add(Convolution2D(64, 5, 5, border_mode='same', subsample=(2, 2), activation='relu'))
model.add(Convolution2D(128, 5, 5, border_mode='same', subsample=(2, 2), activation='relu'))
model.add(Flatten())
model.add(Dense(100, activation='relu'))
model.add(Dense(2, activation='linear'))


# Compile the model
adam = Adam(lr=0.01, beta_1=0.9, beta_2=0.999, epsilon=1e-08, decay=0.0)
model.compile(loss='mean_squared_error', optimizer=adam)


# Fit the model
model.fit(images, targets, batch_size=128, nb_epoch=1000, verbose=1, callbacks=[plot_callback], validation_split=0.2, shuffle=True)
Karnivaurus
la source
Les images sur les meilleurs exemples de vos échantillons réels? S'agit-il de 5 échantillons distincts? Il ne semble pas y avoir d'informations dans les images qui pourraient aider à généraliser. Je veux dire, vous n'avez pas besoin d'un réseau neuronal pour trouver l'emplacement x, y du carré blanc, vous pouvez simplement analyser l'image et rechercher un pixel blanc. Expliquez un peu plus votre vision de ce modèle. Existe-t-il un schéma temporel selon lequel vous prédisez le prochain emplacement?
photox
Salut, et oui, les images sont 5 échantillons séparés. Je ne sais pas comment ils sont rendus pour vous, mais ils devraient être 5 images carrées individuelles (j'ai légèrement changé la disposition pour vous aider ...). Oui, je me rends compte que vous n'avez pas besoin d'un réseau de neurones pour cette tâche, mais ce n'est qu'une expérience de test pour m'aider à apprendre à faire une régression avec un réseau de neurones. Je ne comprends pas ce que vous entendez par le fait qu'il n'y a aucune information pour aider à généraliser ... Chaque paire d'entraînement se compose d'une image carrée et d'un vecteur bidimensionnel de l'emplacement (x, y) du carré. Merci :)
Karnivaurus
1
1) Votre forme d'entrée sur la première couche conv utilise 3 canaux (rbg), mais vos données sont en niveaux de gris (1 canal) 2) Vous n'avez pas besoin de tant de couches conv et de filtres, en fait je pense qu'une seule couche, et une poignée de petits grains ira bien.
photox
Êtes-vous sûr que les images correspondent bien aux cibles?
user31264
1
Comme le dit @photox, vous n'avez pas besoin des couches conv. L'ajout de ces éléments rend plus difficile pour l'optimiseur de trouver une bonne solution. Si vous supprimez les 3 couches conv, je soupçonne que votre "modèle" fonctionnera.
Pieter

Réponses:

9

L'optimiseur ne parvient pas à converger vers une solution (sous-) optimale. Pourquoi? Votre problème est trop facile et / ou votre modèle est trop complexe.

Problème trop facile

Comme @photox l'a déjà dit, ce problème peut être résolu avec une seule couche cachée. Je soupçonne même que cela peut se faire sans couche cachée. C'est parce que ce problème est linéaire séparable .

Permettez-moi d'illustrer cela. Imaginez un réseau de neurones sans couches cachées et sans fonction d'activation linéaire (vous pourriez aussi l'appeler régression linéaire). Pour calculer l'emplacement x du carré, chaque pixel est connecté à la sortie x. La première colonne de pixels est liée au poids . La deuxième colonne est liée au poids . Cela continue jusqu'à la dernière colonne (par exemple la colonne ) qui est liée au poids . Depuis2 / hauteur largeur n n / hauteur largeur hauteur largeur1/height/width2/heightwidthnn/heightwidthheightwidthles pixels sont non nuls (par exemple, le biais est égal à la valeur de couleur grise) l'activation de la sortie x est égale au centre du carré. Par conséquent, une fonction linéaire peut calculer l'emplacement du carré.

Il existe plusieurs solutions:

  • Choisissez un problème plus difficile, par exemple la classification des images
  • Ajoutez du bruit, par exemple du sel et du poivre ou du bruit blanc
  • Rendre le problème plus difficile, par exemple en prédisant l'emplacement d'un carré rouge alors qu'il y a beaucoup de cercles de couleurs différentes en arrière-plan

Modèle trop complexe

Votre modèle comporte quelques parties qui ajoutent beaucoup de complexité sans aider l'optimiseur à trouver un optimum doux.

Par exemple, les couches convolutives. La première couche a 32 filtres convolutionnels de taille . Qu'attendez-vous de ces filtres? Dans la classification d'images, ces filtres apprennent à détecter les bords, les coins, les dégradés et les taches. Mais dans ce cas, seuls quelques filtres ont un sens. Je peux penser au bord de gauche à droite et vice-versa et de haut en bas et vice-versa. Dans votre cas, il y a donc environ 28 filtres qui ne font qu'ajouter du bruit aléatoire. La suppression de ceux-ci (ou de la totalité du calque) permet à l'optimiseur de trouver beaucoup plus facilement l'optimum qui fonctionne.5×5

Un autre exemple est l'optimiseur Adam avec beaucoup de paramètres supplémentaires. L'optimiseur Adam pourrait bien fonctionner avec ces paramètres, mais pourquoi ne pas simplement commencer avec un SGDoptimiseur simple avec des valeurs par défaut.

Ainsi, vous pouvez effectuer plusieurs optimisations:

  • utiliser à LinearRegressionpartir de scikit-learn. OK, ce n'est pas ce que vous voulez, mais je veux juste illustrer la complexité excessive de ce modèle.
  • Supprimer les couches conv
  • Diminue la taille des Densecalques masqués
  • Utilisez l' SGDoptimiseur par défaut
  • Si vous utilisez une couche cachée, vous devriez essayer une sigmoidactivation. Vous pouvez penser à chacun des nœuds de la couche cachée comme détectant si un carré est à un certain endroit.
  • Si tout cela ne fonctionne pas, expérimentez un peu le taux d'apprentissage pour savoir s'il est trop élevé ou trop faible.

Ps

Je pense que vous aimerez cet article de blog d'Adit Deshpande.

Pieter
la source
Faites-moi savoir si ces solutions ont changé le comportement des optimiseurs.
Pieter
Merci, c'est très utile. Je travaille à essayer vos suggestions. Cependant, je ne comprends pas votre premier point. Je ne comprends pas pourquoi, si le problème est trop simple, il est plus difficile à optimiser qu'un problème plus complexe. Pour un réseau donné, pourquoi un problème plus simple serait-il plus difficile à optimiser qu'un problème plus complexe? Dans un problème simple, j'aurais pensé qu'il y aurait de très forts gradients et un fort optimum global. Mais votre premier point dit que la simplicité du problème rend l'optimisation difficile, suggérant qu'un problème plus complexe aiderait l'optimisation ...
Karnivaurus
0

Cela ressemble à un problème de sur-ajustement typique. Vos données ne fournissent pas suffisamment d'informations pour obtenir le meilleur résultat. Vous choisissez le NN complexe avec votre train pour vous souvenir de toutes les nuances des données du train . La perte ne peut jamais être un zéro, comme c'est le cas sur votre graphique. BTW Il semble que votre validation comporte un bogue ou un ensemble de validation n'est pas bon pour la validation car la perte de validation devient également nulle.

Leonid Ganeline
la source
4
La question indique que le réseau produit presque toujours zéro. Ce serait un cas de sous- ajustement sévère , pas de sur-ajustement. Il n'y a pas non plus d'écart entre la formation et l'erreur de validation sur la courbe d'apprentissage, ce qui indique que le sur-ajustement n'est pas le problème (l'erreur n'est pas nulle, l'échelle est logarithmique)
user20160
0

Je suis confronté au même problème avec mon ensemble de données. Il s'avère que dans mon cas les prédicteurs sont très concentrés avec une très petite variance. Vous devriez vérifier la variance de vos variables de prédiction et voir comment elle est distribuée.Distribution de la variable que j'essaie de prédire

Cependant, certaines transformations sur la variable de sortie peuvent être effectuées pour modifier ou changer son échelle. Cela pourrait entraîner une distribution de type plus uniforme. Par exemple, dans les tâches de reconnaissance d'image, l'égalisation de l'histogramme ou l'amélioration du contraste fonctionne parfois en faveur d'une prise de décision correcte.

Ravi Shankar
la source
-1

Je travaillais en fait sur un problème très similaire. Fondamentalement, j'avais un tas de points sur un fond blanc et j'entraînais un NN à reconnaître le point qui avait été placé sur le fond en premier. La façon dont j'ai trouvé à travailler était d'utiliser simplement une couche de neurones entièrement connectée (donc un NN à une couche). Par exemple, pour une image 100x100, j'aurais 10 000 neurones d'entrée (les pixels) directement connectés à 2 neurones de sortie (les coordonnées). Dans PyTorch, lorsque j'ai converti les valeurs des pixels en un tenseur, cela normalisait automatiquement mes données, en soustrayant la moyenne et en divisant par l'écart-type. Dans les problèmes d'apprentissage automatique normaux, c'est bien, mais pas pour une image où il pourrait y avoir une disparité dans le nombre de pixels colorés dans une image (c'est-à-dire la vôtre où il n'y a que quelques pixels blancs). Donc, J'ai normalisé manuellement en divisant toutes les valeurs d'intensité de pixels par 255 (donc elles sont maintenant dans la plage de 0-1 sans la technique de normalisation typique qui essaie d'ajuster toutes les valeurs d'intensité à une distribution normale). Ensuite, j'ai toujours eu des problèmes car il prédisait la coordonnée moyenne des pixels dans l'ensemble d'entraînement. Donc, ma solution a été de définir un taux d'apprentissage très élevé, ce qui va à l'encontre de presque tous les instructeurs et tutoriels ML. Au lieu d'utiliser 1e-3, 1e-4, 1e-5, comme la plupart des gens le disent, j'utilisais un taux d'apprentissage de 1 ou 0,1 avec descente de gradient stochastique. Cela a résolu mes problèmes et mon réseau a finalement appris à mémoriser mon ensemble de formation. Cela ne se généralise pas trop bien à un ensemble de tests, mais au moins cela fonctionne quelque peu, ce qui est une meilleure solution que la plupart des autres ont suggéré sur votre question. re maintenant dans la plage de 0-1 sans la technique de normalisation typique qui essaie d'ajuster toutes les valeurs d'intensité à une distribution normale). Ensuite, j'ai toujours eu des problèmes car il prédisait la coordonnée moyenne des pixels dans l'ensemble d'entraînement. Donc, ma solution a été de définir un taux d'apprentissage très élevé, ce qui va à l'encontre de presque tous les instructeurs et tutoriels ML. Au lieu d'utiliser 1e-3, 1e-4, 1e-5, comme la plupart des gens le disent, j'utilisais un taux d'apprentissage de 1 ou 0,1 avec descente de gradient stochastique. Cela a résolu mes problèmes et mon réseau a finalement appris à mémoriser mon ensemble de formation. Cela ne se généralise pas trop bien à un ensemble de tests, mais au moins cela fonctionne quelque peu, ce qui est une meilleure solution que la plupart des autres ont suggéré sur votre question. re maintenant dans la plage de 0-1 sans la technique de normalisation typique qui essaie d'ajuster toutes les valeurs d'intensité à une distribution normale). Ensuite, j'ai toujours eu des problèmes car il prédisait la coordonnée moyenne des pixels dans l'ensemble d'entraînement. Donc, ma solution a été de définir un taux d'apprentissage très élevé, ce qui va à l'encontre de presque tous les instructeurs et tutoriels ML. Au lieu d'utiliser 1e-3, 1e-4, 1e-5, comme la plupart des gens le disent, j'utilisais un taux d'apprentissage de 1 ou 0,1 avec descente de gradient stochastique. Cela a résolu mes problèmes et mon réseau a finalement appris à mémoriser mon ensemble de formation. Cela ne se généralise pas trop bien à un ensemble de tests, mais au moins cela fonctionne quelque peu, ce qui est une meilleure solution que la plupart des autres ont suggéré sur votre question.

Bob
la source