4 votes

Taille attendue du modèle tensorflow à partir des variables apprises

Lors de la formation de réseaux de neurones convolutifs pour des tâches de classification d'images, nous souhaitons généralement que notre algorithme apprenne les filtres (et les biais) qui transforment une image donnée en son étiquette correcte. J'ai quelques modèles que j'essaie de comparer en termes de taille de modèle, de nombre d'opérations, de précision, etc. Cependant, la taille du modèle sorti de tensorflow, concrètement le modèle.ckpt.données qui stocke les valeurs de toutes les variables du graphique, n'est pas celui que j'attendais. En fait, il semble être trois fois plus gros.

Pour aller directement au problème, je vais baser ma question sur ce Bloc-notes Jupyter. Vous trouverez ci-dessous la section où les variables (poids et biais) sont définies :

# Store layers weight & bias
weights = {
# 5x5 conv, 1 input, 32 outputs
'wc1': tf.Variable(tf.random_normal([5, 5, 1, 32]),dtype=tf.float32),
# 5x5 conv, 32 inputs, 64 outputs
'wc2': tf.Variable(tf.random_normal([5, 5, 32, 64]),dtype=tf.float32),
# fully connected, 7*7*64 inputs, 1024 outputs
'wd1': tf.Variable(tf.random_normal([7*7*64, 1024]),dtype=tf.float32),
# 1024 inputs, 10 outputs (class prediction)
'out': tf.Variable(tf.random_normal([1024, num_classes]),dtype=tf.float32)
}

biases = {
'bc1': tf.Variable(tf.random_normal([32]),dtype=tf.float32),
'bc2': tf.Variable(tf.random_normal([64]),dtype=tf.float32),
'bd1': tf.Variable(tf.random_normal([1024]),dtype=tf.float32),
'out': tf.Variable(tf.random_normal([num_classes]),dtype=tf.float32)
}

J'ai ajouté quelques lignes afin de sauvegarder le modèle à la fin du processus de formation :

# Save the model
save_path = saver.save(sess, logdir+"model.ckpt")
print("Model saved in file: %s" % save_path)

En additionnant toutes ces variables, on s'attendrait à obtenir une modèle.ckpt.données d'une taille de 12,45 Mo (j'ai obtenu ce chiffre en calculant simplement le nombre d'éléments flottants que notre modèle apprend, puis en convertissant cette valeur en méga-octets). Mais ! .données Le fichier sauvegardé est de 39.3Mb. Comment cela se fait-il ?

J'ai suivi la même approche avec un réseau plus complexe (une variation de ResNet) et la taille attendue de mon modèle de données est également ~3x plus petite que la taille réelle du réseau. .données est.

Le type de données de toutes ces variables est float32.

3voto

Maxim Points 28843

En additionnant toutes ces variables, nous devrions obtenir un fichier model.ckpt.data d'une taille de 12,45 Mo.

Traditionnellement, la plupart des paramètres du modèle se trouvent dans la première couche entièrement connectée, dans ce cas-ci wd1 . En calculant uniquement sa taille, on obtient :

7*7*128 * 1024 * 4 = 25690112

... ou 25.6Mb . Note 4 car la variable dtype=tf.float32 c'est-à-dire 4 octets par paramètre. D'autres couches contribuent également à la taille du modèle, mais pas de manière aussi radicale.

Comme vous pouvez le constater, votre estimation 12.45Mb est un peu à l'écart (avez-vous utilisé 16 bits par paramètre ?). Le point de contrôle stocke également des informations générales, d'où un surcoût d'environ 25%, ce qui est toujours important, mais pas 300%.

[Mise à jour]

Le modèle en question a en fait FC1 couche de forme [7*7*64, 1024] comme cela a été précisé. Ainsi, la taille calculée ci-dessus devrait être 12.5Mb en effet. Cela m'a fait regarder plus attentivement le point de contrôle sauvegardé.

Après l'avoir inspecté, j'ai remarqué d'autres grandes variables qui m'avaient échappé à l'origine :

...
Variable_2 (DT_FLOAT) [3136,1024]
Variable_2/Adam (DT_FLOAT) [3136,1024]
Variable_2/Adam_1 (DT_FLOAT) [3136,1024]
...

Le site Variable_2 est exactement wd1 mais il y a 2 copies supplémentaires pour l'optimiseur Adam. Ces variables sont créées par l'optimiseur Adam ils sont appelés Machines à sous et tenir le m y v accumulateurs pour toutes les variables entraînables . Maintenant, la taille totale a un sens.

Vous pouvez exécuter le code suivant pour calculer la taille totale des variables du graphe - 37.47Mb :

var_sizes = [np.product(list(map(int, v.shape))) * v.dtype.size
             for v in tf.get_collection(tf.GraphKeys.GLOBAL_VARIABLES)]
print(sum(var_sizes) / (1024 ** 2), 'MB')

Donc les frais généraux sont en fait assez faibles. La taille supplémentaire est due à l'optimiseur.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X