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:
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:
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)
Réponses:
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/width 2/heightwidth n n/heightwidth height∗width les 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:
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
SGD
optimiseur simple avec des valeurs par défaut.Ainsi, vous pouvez effectuer plusieurs optimisations:
LinearRegression
partir de scikit-learn. OK, ce n'est pas ce que vous voulez, mais je veux juste illustrer la complexité excessive de ce modèle.Dense
calques masquésSGD
optimiseur par défautsigmoid
activation. Vous pouvez penser à chacun des nœuds de la couche cachée comme détectant si un carré est à un certain endroit.Ps
Je pense que vous aimerez cet article de blog d'Adit Deshpande.
la source
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.
la source
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.
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.
la source
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.
la source