web-dev-qa-db-fra.com

Le réseau neuronal produit toujours des sorties identiques / similaires pour toute entrée

J'ai un problème où j'essaie de créer un réseau de neurones pour TIC-TAC-TOE. Cependant, pour une raison quelconque, la formation du réseau neuronal le fait produire près de la même sortie pour une entrée donnée.

J'ai examiné - Benchmark de réseaux de neurones artificiels , mais mon implémentation de réseau est construite pour les neurones ayant la même fonction d'activation pour chaque neurone, c'est-à-dire pas de neurones constants.

Pour vous assurer que le problème n'était pas simplement dû à mon choix d'entraînement (1218 États du conseil d'administration et déplacements générés par un algorithme génétique), j'ai essayé de former le réseau pour reproduire Xor. La fonction d'activation logistique a été utilisée. Au lieu d'utiliser le dérivé, j'ai multiplié l'erreur par output*(1-output) Comme certaines sources suggèrent que cela équivalait à l'utilisation du dérivé. Je peux mettre la source de haskell sur hpaste, mais c'est un peu embarrassant de regarder. Le réseau comporte 3 couches: la première couche comporte 2 entrées et 4 sorties, la seconde comporte 4 entrées et 1 sortie, et la troisième a 1 sortie. Augmentation de 4 neurones dans la deuxième couche n'a pas aidé et n'a pas eu augmenté à 8 sorties dans la première couche.

J'ai ensuite calculé les erreurs, la sortie de réseau, les mises à jour de biais et les mises à jour de poids à la main en fonction de http://hebb.mit.edu/courses/9.641/2002/lectures/lectrecture04.pdf pour vous assurer que Il n'y avait pas une erreur dans ces parties du code (il n'y avait pas, mais je le ferai probablement tout simplement pour m'assurer). Parce que j'utilise une formation par lots, je n'ai pas multiplié par x dans l'équation (4) là-bas. J'ajoute le changement de poids, cependant http://www.faqs.org/faqs/ai-faq/neual-nets/part2/section-2.html suggère de soustraire la place à la place.

Le problème persistait, même dans ce réseau simplifié. Par exemple, ce sont les résultats après 500 époques d'entraînement par lots et de formation incrémentielle.

Input    |Target|Output (Batch)      |Output(Incremental)
[1.0,1.0]|[0.0] |[0.5003781562785173]|[0.5009731800870864]
[1.0,0.0]|[1.0] |[0.5003740346965251]|[0.5006347214672715]
[0.0,1.0]|[1.0] |[0.5003734471544522]|[0.500589332376345]
[0.0,0.0]|[0.0] |[0.5003674110937019]|[0.500095157458231]

La soustraction au lieu de l'ajout produit le même problème, sauf que tout est égal à 0,99 quelque chose au lieu de 0,50 quelque chose. 5000 EPOCHS génère le même résultat, à l'exception du réseau formé par lots revient exactement 0,5 pour chaque cas. (Heck, même 10 000 époques n'ont pas fonctionné pour la formation des lots.)

Y a-t-il quelque chose en général qui pourrait produire ce comportement?

De plus, j'ai examiné les erreurs intermédiaires pour une formation incrémentielle et, bien que les entrées des couches cachées/entrées varient variaient, l'erreur du neuron de sortie était toujours +/- 0.12. Pour la formation des lots, les erreurs augmentaient, mais extrêmement lentement et que les erreurs étaient toutes extrêmement petites (X10 ^ -7). Différents poids aléatoires initiaux et biais ne font aucune différence, non plus.

Notez qu'il s'agit d'un projet d'école, de sorte que les indications/guides seraient plus utiles. Bien que réinventer la roue et faire mon propre réseau (dans une langue que je ne connais pas bien!) Était une idée horrible, je sentais que ce serait plus approprié pour un projet d'école (alors je sais ce qui se passe ... en théorie, au moins. Il ne semble pas y avoir un professeur d'informatique à mon école).

Edit: Deux couches, une couche d'entrée de 2 entrées à 8 sorties et une couche de sortie de 8 entrées à 1 sortie, produit beaucoup de même résultats: 0,5 +/- 0,2 (ouc.) pour chaque cas de formation. Je joue également avec Pybrain, voyant si une structure de réseau, il y aura du travail.

Edit 2: J'utilise un taux d'apprentissage de 0,1. Désolé d'avoir oublié à ce sujet.

Edit 3: "TraintilConvergence" de Pybrain ne me reçoit pas un réseau entièrement formé, mais également, mais 20000 Epochs, avec 16 neurones de la couche cachée. 10000 époques et 4 neurones, pas tellement, mais près. Donc, à Haskell, avec la couche d'entrée ayant 2 entrées et 2 sorties, couche cachée avec 2 entrées et 8 sorties, et couche de sortie avec 8 entrées et 1 sortie ... Je reçois le même problème avec 10000 époques. Et avec 20000 époques.

EDIT 4: J'ai couru le réseau à nouveau à la main en fonction de la MIT PDF ci-dessus et que les valeurs correspondent, le code doit donc être correct à moins que je ne comprends pas mal compris ces équations.

Une partie de mon code source est à http://hpaste.org/42453/neural_network__not_working; Je travaille quelque peu sur le nettoyage de mon code et le mettant dans un référentiel GitHub (plutôt qu'un Bitbucket privé).

Tout le code source concerné est maintenant à https://github.com/l33tnerd/hsann .

33
li.davidm

Je ne l'ai pas testé avec le XOR problème dans la question, mais pour mon jeu de données original basé sur TIC-TAC-TOE, je pense que j'ai eu le réseau de s'entraîner quelque peu (je seulement Ran 1000 Epochs, qui ne suffisait pas): le réseau QuickPropagation peut gagner/attacher la moitié de ses jeux; la ponte-braft peut obtenir environ 41%. Les problèmes sont descendus aux erreurs de mise en œuvre (petites) et ne comprenant pas la différence entre l'erreur dérivé (qui est par -forme par poids) et l'erreur de chacun Neuron, que je n'ai pas pris dans mes recherches. @ DarkCanuck's Réponse sur la formation du biais de la même manière à un le poids aurait probablement aidé, bien que je ne l'ai pas impliqué. J'ai aussi réécrit mon code dans Python afin que je puisse plus facilement pirater avec elle. Par conséquent, bien que je n'ai pas reçu le réseau. Pour faire correspondre l'efficacité de l'algorithme minimax, je pense que j'ai réussi à résoudre le problème.

0
li.davidm

J'ai eu des problèmes similaires, mais j'ai pu résoudre en changeant ces:

  • Échelle sur le problème de la taille gérable. J'ai d'abord essayé trop d'entrées, avec trop d'unités de couche cachées. Une fois que j'ai réduit le problème, je pouvais voir si la solution au faible problème fonctionnait. Cela fonctionne également parce que lorsqu'il est réduit, les temps pour calculer les poids tombent de manière significative, afin que je puisse essayer de nombreuses choses différentes sans attendre.
  • Assurez-vous d'avoir assez d'unités cachées. C'était un problème majeur pour moi. J'avais environ 900 entrées de connexion à environ 10 unités dans la couche cachée. C'était beaucoup trop petit pour converger rapidement. Mais est également devenu très lent si j'ai ajouté des unités supplémentaires. Réduire le nombre d'entrées a beaucoup aidé.
  • Modifiez la fonction d'activation et ses paramètres. J'utilisais Tanh au début. J'ai essayé d'autres fonctions: Sigmoïde, sigmoïde normalisé, gaussien, etc. J'ai également trouvé cela modifiant les paramètres de fonction pour que les fonctions plus profondes ou moins profondes ont affecté la rapidité avec laquelle le réseau s'est convergé.
  • Modifier les paramètres d'algorithme d'apprentissage. Essayez différents taux d'apprentissage (0,01 à 0,9). Essayez également différents paramètres de l'élan, si votre algo prend en charge (0,1 à 0,9).

J'espère que cela aide ceux qui trouvent ce fil sur Google!

25
Justas

Donc, je me rends compte que cela est extrêmement en retard pour le poste d'origine, mais je suis tombé sur cela parce que j'avais un problème similaire et que rien des raisons affichées ici ne couvrent ce qui n'allait pas dans mon cas.

Je travaillais sur un simple problème de régression, mais chaque fois que j'ai entraîné le réseau, il convergerait un point où il me donnait la même sortie (ou parfois quelques sorties différentes) pour chaque entrée. J'ai joué avec le taux d'apprentissage, le nombre de couches/nœuds cachés, l'algorithme d'optimisation, etc. mais cela n'a fait aucune différence. Même lorsque j'ai examiné un exemple ridiculement simple, essayez de prédire la sortie (1D) de deux entrées différentes (1D):

    import numpy as np
    import torch
    import torch.nn as nn
    import torch.nn.functional as F

    class net(nn.Module):
        def __init__(self, obs_size, hidden_size):
            super(net, self).__init__()
            self.fc = nn.Linear(obs_size, hidden_size)
            self.out = nn.Linear(hidden_size, 1)

        def forward(self, obs):
            h = F.relu(self.fc(obs))
            return self.out(h)

    inputs = np.array([[0.5],[0.9]])
    targets = torch.tensor([3.0, 2.0], dtype=torch.float32)

    network = net(1,5)
    optimizer = torch.optim.Adam(network.parameters(), lr=0.001)

    for i in range(10000):
        out = network(torch.tensor(inputs, dtype=torch.float32))
        loss = F.mse_loss(out, targets)
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        print("Loss: %f outputs: %f, %f"%(loss.data.numpy(), out.data.numpy()[0], out.data.numpy()[1]))

mais il émet toujours toujours la valeur moyenne des sorties pour les deux entrées. Il s'avère que la raison est que les dimensions de mes sorties et de mes objectifs n'étaient pas identiques: les cibles étaient la taille [2], et les sorties étaient la taille [2,1], et pour une raison quelconque, Pytorch diffusait les sorties pour être la taille. [2,2] Dans la perte MSE, qui désactive complètement tout. Une fois que j'ai changé:

targets = torch.tensor([3.0, 2.0], dtype=torch.float32)

à

targets = torch.tensor([[3.0], [2.0]], dtype=torch.float32)

Cela a fonctionné comme il le devrait. Cela a évidemment été fait avec Pytorch, mais je soupçonne peut-être d'autres bibliothèques diffusent des variables de la même manière.

2
Henry

Il est difficile de dire sans voir un échantillon de code, mais un bogue de biais peut avoir cet effet (par exemple, oublier d'ajouter le biais à l'entrée), donc je vais examiner de plus près cette partie du code.

0
finnw

Pour moi, cela se produisait exactement comme dans votre cas, la production du réseau de neurones était toujours la même quel que soit la formation et le nombre de couches, etc.

S'éteint mon algorithme de propagation de retour a eu un problème. Au même endroit, je multiplié par -1 où ce n'était pas nécessaire.

Il pourrait y avoir un autre problème comme celui-ci. La question est de savoir comment le déboguer?

Étapes pour déboguer:

Step1 : Write the algorithm such that it can take variable number of input layers and variable number of input & output nodes.
Step2 : Reduce the hidden layers to 0. Reduce input to 2 nodes, output to 1 node.
Step3 : Now train for binary-OR-Operation.
Step4 : If it converges correctly, go to Step 8.
Step5 : If it doesn't converge, train it only for 1 training sample
Step6 : Print all the forward and prognostication variables (weights, node-outputs, deltas etc)
Step7 : Take pen&paper and calculate all the variables manually.
Step8 : Cross verify the values with algorithm.
Step9 : If you don't find any problem with 0 hidden layers. Increase hidden layer size to 1. Repeat step 5,6,7,8

Cela ressemble à beaucoup de travail, mais cela fonctionne très bien imho.

0
user18853

Je rencontrais le même problème avec mon modèle lorsque le nombre de couches est grand. J'utilisais un taux d'apprentissage de 0,0001. Lorsque je baisse le taux d'apprentissage à 0,0000001, le problème semble résolu. Je pense que des algorithmes coincés sur des minumums locaux lorsque le taux d'apprentissage est trop bas

0
arslanbenzer

Basé sur vos commentaires, je suis d'accord avec @Finnw que vous avez un problème de biais. Vous devez traiter le biais comme une "1" constante (ou -1 si vous préférez) entrer dans chaque neurone. Chaque neurone aura également son propre poids pour le biais, de sorte que la production de neurone doit être la somme des entrées pondérées, ainsi que des temps de biais de manière de son poids, passés à travers la fonction d'activation. Les poids de biais sont mis à jour lors de la formation, tout comme les autres poids.

Les "fondamentaux des réseaux de neurones" de Fausett (P.300) ont un exemple XOR à l'aide d'entrées binaires et d'un réseau avec 2 entrées, 1 couche cachée de 4 neurones et un neurone de sortie. Les poids sont initialisés de manière aléatoire entre +0,5 et -0,5. Avec un taux d'apprentissage de 0,02, l'exemple réseau converge après environ 3 000 époques. Vous devriez pouvoir obtenir un résultat dans le même Ballpark si vous obtenez les problèmes de biais (et tous les autres bugs) repassés.

Notez également que vous ne pouvez pas résoudre le problème XOR sans une couche cachée dans votre réseau.

0
darkcanuck

Il est difficile de dire sans voir un échantillon de code, mais il est possible de créer un net, car son nombre de neron caché.avec en nombre de Néron et nombre de cachettes, il n'est pas possible de former un réseau avec un petit ensemble de données de formation. Jusqu'à ce qu'il soit possible de faire un filet avec une couche plus petite et des nerons, il n'est pas nécessaire d'utiliser un net plus grand. Il est donc possible de résoudre votre problème avec attention à cette question.

0
mohammad