2

J'essaie d'utiliser BatchNorm dans Keras. La précision de l'entraînement augmente avec le temps. De 12% à 20%, lentement mais sûrement. La précision du test diminue cependant de 12% à 0%. La base de référence aléatoire est de 12%. Je suppose que cela est dû à la couche batchnorm (la suppression de la couche batchnorm donne une précision de test d'environ 12%), ce qui n'initialise peut-être pas suffisamment les paramètres gamma et beta. Dois-je considérer quelque chose de spécial lors de l'application de batchnorm? Je ne comprends pas vraiment quoi d'autre aurait pu mal tourner. Je le modèle suivant:Keras BatchNorm: La précision de l'entraînement augmente tandis que la précision des tests diminue

modèle

= séquentiel()

model.add(BatchNormalization(input_shape=(16, 8))) 
model.add(Reshape((16, 8, 1))) 

#1. Conv (64 filters; 3x3 kernel) 
model.add(default_Conv2D()) 
model.add(BatchNormalization(axis=3)) 
model.add(Activation('relu')) 

#2. Conv (64 filters; 3x3 kernel) 
model.add(default_Conv2D()) 
model.add(BatchNormalization(axis=3)) 
model.add(Activation('relu')) 

... 

#8. Affine (NUM_GESTURES units) Output layer 
model.add(default_Dense(NUM_GESTURES)) 
model.add(Activation('softmax')) 


sgd = optimizers.SGD(lr=0.1) 
model.compile(loss='categorical_crossentropy', optimizer=sgd, metrics=['accuracy']) 

default_Conv2D et default_Dense sont définies comme suit:

def default_Conv2D(): 
    return Conv2D(
     filters=64, 
     kernel_size=3, 
     strides=1, 
     padding='same', 
     # activation=None, 
     # use_bias=True, 
     # kernel_initializer=RandomNormal(mean=0.0, stddev=0.01, seed=None), #RandomUniform(), 
     kernel_regularizer=regularizers.l2(0.0001), 
     # bias_initializer=RandomNormal(mean=0.0, stddev=0.01, seed=None), # RandomUniform(), 
     # bias_regularizer=None 
    ) 

def default_Dense(units): 

    return Dense(
     units=units, 
     # activation=None, 
     # use_bias=True, 
     # kernel_initializer=RandomNormal(mean=0.0, stddev=0.01, seed=None),#RandomUniform(), 
     # bias_initializer=RandomNormal(mean=0.0, stddev=0.01, seed=None),#RandomUniform(), 
     kernel_regularizer=regularizers.l2(0.0001), 
     # bias_regularizer=None 
    ) 

Répondre

0

Il semble qu'il y avait quelque chose de cassé avec Keras lui-même.

Un naïf

pip install git+git://github.com/fchollet/keras.git --upgrade --no-deps 

a fait l'affaire.

@wontonimo, merci beaucoup pour votre très bonne réponse!

+0

Content que vous l'ayez trouvé! – Wontonimo

3

La question est surapprentissage.

Ceci est soutenu par vos 2 premières observations:

  1. La précision formation augmente au fil du temps. De 12% à 20%, .. la précision du test diminue cependant de 12% à 0%
  2. enlever les résultats de la couche batchnorm dans ~ 12% la précision des tests

La première déclaration me dit que votre réseau est la mémorisation de l'ensemble d'entraînement. La deuxième déclaration me dit que lorsque vous empêchez le réseau de mémoriser l'ensemble d'apprentissage (ou même d'apprentissage), il arrête de faire une erreur de mémorisation.

Il existe quelques solutions pour sur-monter, mais c'est un problème plus important que cet article. S'il vous plaît traiter la liste suivante comme « top » liste et non exhaustive:

  • ajouter un régularisateur comme Dropout juste avant votre couche finale entièrement connecté.
  • ajouter une L1 ou L2 régularisateur sur le poids de la matrice
  • ajouter un régularisateur comme Dropout entre CONV
  • votre réseau peut avoir trop de paramètres libres. Essayez de réduire les couches à seulement 1 CONV, et ajoutez une couche de plus à la fois en recyclant et en testant chaque fois.

lente augmentation de la précision

Comme une note de côté, vous a laissé entendre que votre précision n'augmente pas aussi vite que vous aimez en disant lentement mais sûrement. J'ai eu beaucoup de succès quand j'ai fait toutes les étapes suivantes

  • changez votre fonction de perte à la perte moyenne de toutes les prédictions pour tous les articles dans le mini-lot.Cela rend votre fonction de perte indépendante de la taille de votre lot. Vous découvrirez que si vous modifiez la taille de votre lot et que votre fonction de perte change, vous devrez modifier votre taux d'apprentissage dans SGD.
  • votre perte est un nombre unique qui est la moyenne de la perte pour toutes les classes prédites et tous les échantillons, utilisez donc un taux d'apprentissage de 1,0. Pas besoin de l'escalader plus.
  • utiliser tf.train.MomentumOptimizer avec learning_rate = 1.0 et momentum = 0.5. MomentumOptimizer a été montré pour être beaucoup plus robuste que GradientDescent.
+0

Merci beaucoup pour la réponse! Cependant, le problème est que le même code fonctionne si je le déploie sur tensorflow. Ai-je utilisé BatchNorm correctement? Ou y a-t-il des bugs connus avec? – DaveTheAl

+0

Quand vous dites * fonctionne si je le déploie sur tensorflow *, où le déployiez-vous avant? – Wontonimo

+0

Désolé, j'aurais dû être plus clair. Ma précédente implémentation était du tensorflow pur. Maintenant, je le déploie sur Keras avec un backend tensorflow. Le modèle tensorflow a la même architecture ** exacte **. J'ai eu ce même problème auparavant, et il s'est avéré que les variables dans tensorflow devaient être initialisées d'une manière spéciale (comme [ici] (https://www.tensorflow.org/versions/master/api_docs/python/tf/ layers/batch_normalization)). Donc je suppose que je dois initialiser quelque chose dans Keras aussi, mais cela ne semble pas être le cas .. – DaveTheAl