web-dev-qa-db-fra.com

Le réseau de neurones prédit toujours la même classe

J'essaie d'implémenter un réseau de neurones qui classe les images dans l'une des deux catégories distinctes. Le problème, cependant, est qu’il prédit toujours 0 pour chaque entrée et je ne sais pas trop pourquoi.

Voici ma méthode d'extraction de fonctionnalités:

def extract(file):
    # Resize and subtract mean pixel
    img = cv2.resize(cv2.imread(file), (224, 224)).astype(np.float32)
    img[:, :, 0] -= 103.939
    img[:, :, 1] -= 116.779
    img[:, :, 2] -= 123.68
    # Normalize features
    img = (img.flatten() - np.mean(img)) / np.std(img)

    return np.array([img])

Voici ma routine de descente de gradient:

def fit(x, y, t1, t2):
    """Training routine"""
    ils = x.shape[1] if len(x.shape) > 1 else 1
    labels = len(set(y))

    if t1 is None or t2 is None:
        t1 = randweights(ils, 10)
        t2 = randweights(10, labels)

    params = np.concatenate([t1.reshape(-1), t2.reshape(-1)])
    res = grad(params, ils, 10, labels, x, y)
    params -= 0.1 * res

    return unpack(params, ils, 10, labels)

Voici mes propagations avant et arrière (dégradé):

def forward(x, theta1, theta2):
    """Forward propagation"""

    m = x.shape[0]

    # Forward prop
    a1 = np.vstack((np.ones([1, m]), x.T))
    z2 = np.dot(theta1, a1)

    a2 = np.vstack((np.ones([1, m]), sigmoid(z2)))
    a3 = sigmoid(np.dot(theta2, a2))

    return (a1, a2, a3, z2, m)

def grad(params, ils, hls, labels, x, Y, lmbda=0.01):
    """Compute gradient for hypothesis Theta"""

    theta1, theta2 = unpack(params, ils, hls, labels)

    a1, a2, a3, z2, m = forward(x, theta1, theta2)
    d3 = a3 - Y.T
    print('Current error: {}'.format(np.mean(np.abs(d3))))

    d2 = np.dot(theta2.T, d3) * (np.vstack([np.ones([1, m]), sigmoid_prime(z2)]))
    d3 = d3.T
    d2 = d2[1:, :].T

    t1_grad = np.dot(d2.T, a1.T)
    t2_grad = np.dot(d3.T, a2.T)

    theta1[0] = np.zeros([1, theta1.shape[1]])
    theta2[0] = np.zeros([1, theta2.shape[1]])

    t1_grad = t1_grad + (lmbda / m) * theta1
    t2_grad = t2_grad + (lmbda / m) * theta2

    return np.concatenate([t1_grad.reshape(-1), t2_grad.reshape(-1)])

Et voici ma fonction de prédiction:

def predict(theta1, theta2, x):
    """Predict output using learned weights"""
    m = x.shape[0]

    h1 = sigmoid(np.hstack((np.ones([m, 1]), x)).dot(theta1.T))
    h2 = sigmoid(np.hstack((np.ones([m, 1]), h1)).dot(theta2.T))

    return h2.argmax(axis=1)

Je peux voir que le taux d'erreur diminue progressivement à chaque itération, convergeant généralement autour de 1,26e-05.

Ce que j'ai essayé jusqu'à présent:

  1. PCA
  2. Différents ensembles de données (Iris de nombres apprenants et manuscrits du cours Coursera ML, avec une précision d’environ 95% sur les deux). Cependant, ces deux processus ont été traités par lot. Je peux donc supposer que mon implémentation générale est correcte, mais il y a un problème avec la façon dont j'extrais les fonctionnalités ou dont je forme le classificateur.
  3. J'ai essayé le SGDClassifier de sklearn et ses performances n'ont pas été meilleures, ce qui m'a donné une précision d'environ 50%. Donc, quelque chose ne va pas avec les fonctionnalités, alors?

Edit : Une sortie moyenne de h2 se présente comme suit:

[0.5004899   0.45264441]
[0.50048522  0.47439413]
[0.50049019  0.46557124]
[0.50049261  0.45297816]

Donc, des sorties sigmoïdes très similaires pour tous les exemples de validation.

25
Yurii Dolhikh

Après une semaine et demie de recherche, je pense comprendre le problème. Il n'y a rien de mal avec le code lui-même. Les deux seuls problèmes qui empêchent ma mise en œuvre de classer avec succès sont le temps passé à apprendre et le choix approprié des paramètres de cadence d'apprentissage/de régularisation.

La routine d'apprentissage est en cours depuis un certain temps déjà, et elle pousse déjà à 75% de précision, bien qu'il y ait encore beaucoup de place pour l'amélioration.

8
Yurii Dolhikh

Mon réseau prédit toujours la même classe. Quel est le problème?

J'ai eu cela plusieurs fois. Bien que je sois actuellement trop paresseux pour consulter votre code, je pense pouvoir vous donner quelques conseils généraux qui pourraient également aider d'autres personnes ayant le même symptôme, mais probablement différents problèmes sous-jacents.

Débogage des réseaux de neurones

Ajustement des ensembles de données d'un élément

Pour chaque classe i que le réseau devrait pouvoir prévoir, essayez ce qui suit:

  1. Créez un jeu de données d'un seul point de données de la classe i.
  2. Adapter le réseau à cet ensemble de données.
  3. Le réseau apprend-il à prédire la "classe i"?

Si cela ne fonctionne pas, il existe quatre sources d'erreur possibles:

  1. Algorithme d'apprentissage de buggy: essayez un modèle plus petit, imprimez un grand nombre de valeurs calculées entre les deux et vérifiez si celles-ci correspondent à vos attentes .
    1. Division par 0: Ajouter un petit nombre au dénominateur
    2. Logarithme de 0/nombre négatif: Comme divisant par 0
  2. Data: il est possible que le type de vos données soit incorrect. Par exemple, il peut être nécessaire que vos données soient de type float32 mais qu’il s’agisse d’un nombre entier.
  3. Model: Il est également possible que vous veniez de créer un modèle qui ne puisse prédire ce que vous voulez. Cela devrait être révélé lorsque vous essayez des modèles plus simples.
  4. Initialisation/Optimisation: selon le modèle, votre initialisation et votre algorithme d'optimisation peuvent jouer un rôle crucial. Pour les débutants qui utilisent une descente de gradient stochastique standard, je dirais qu’il est principalement important d’initialiser les poids de manière aléatoire (chaque poids ayant une valeur différente). - voir aussi: cette question/réponse

Courbe d'apprentissage

Voir sklearn pour plus de détails.

enter image description here

L'idée est de commencer avec un petit ensemble de données d'apprentissage (probablement un seul élément). Ensuite, le modèle devrait pouvoir adapter les données à la perfection. Si cela fonctionne, vous créez un jeu de données légèrement plus grand. Votre erreur d’entraînement devrait légèrement augmenter jusqu’à Cela révèle la capacité de vos modèles à modéliser les données.

L'analyse des données

Vérifiez la fréquence à laquelle les autres classes apparaissent. Si une classe domine les autres (par exemple, une classe représente 99,9% des données), cela pose un problème. Rechercher des techniques de "détection des valeurs aberrantes".

Plus

  • Taux d’apprentissage: si votre réseau ne s’améliore pas et ne gagne que légèrement mieux que le hasard, essayez de réduire le taux d’apprentissage. Pour la vision par ordinateur, un taux d’apprentissage de 0.001 est souvent utilisé/fonctionnel. Ceci est également pertinent si vous utilisez Adam comme optimiseur.
  • Prétraitement: veillez à utiliser le même prétraitement pour la formation et les tests. Vous pourriez voir des différences dans la matrice de confusion (voir cette question )

Erreurs fréquentes

Ceci est inspiré par reddit :

  • Vous avez oublié d'appliquer le prétraitement
  • Dying ReLU
  • Taux d'apprentissage trop petit/trop grand
  • Fonction d'activation incorrecte dans la couche finale:
    • Vos cibles ne sont pas en somme une? -> N'utilisez pas softmax
    • Les éléments individuels de vos cibles sont négatifs -> N'utilisez pas Softmax, ReLU, Sigmoid. Tanh pourrait être une option
  • Réseau trop profond: vous ne parvenez pas à vous entraîner. Essayez d’abord un réseau de neurones plus simple.
  • Données extrêmement déséquilibrées: vous voudrez peut-être regarder dans imbalanced-learn
54
Martin Thoma

Incase juste quelqu'un d'autre rencontre ce problème. Le mien était avec une architecture deeplearning4jLenet (CNN), il continuait à donner le résultat final du dernier dossier de formation pour chaque test. J'ai réussi à le résoudre par increasing my batchsize et shuffling the training data afin que chaque lot contienne au moins un échantillon de plusieurs dossiers. Ma classe de données avait une taille de lot de 1 qui était vraiment dangerous.

Edit: Bien que l’une des choses que j’ai récemment constatée, c’est le nombre limité d’échantillons d’entraînement par classe, malgré un dataset important. eg formant un neural-network à reconnaître human faces mais n'ayant qu'un maximum de dire 2 faces différentes pour 1person moyenne alors que le jeu de données consiste en: 10,000persons donc un dataset de 20 000faces au total. Une meilleure dataset serait 1000 différente faces pour 10 000persons soit une dataset de 10 000 000faces au total. Ceci est relativement nécessaire si vous voulez éviter surcharger les données dans une classe} afin que votre network puisse facilement généraliser et produire une meilleure prédiction. 

0
LiNKeR