Skip to content

Pourquoi TensorFlow 2 est-il beaucoup plus lent que TensorFlow 1 ?

Nous passons en revue de manière exhaustive chaque publication de notre espace dans le but de vous montrer à tout moment des informations exactes et à jour.

Solution :

MISE À JOUR 8/17 30/2020: TF 2.3 l'a enfin fait : tous les cas s'exécutent aussi vite, ou notablement plus vite, que toute version précédente.

En outre, ma mise à jour précédente était injuste pour TF ; mon GPU était à blâmer, a surchauffé ces derniers temps. Si vous voyez un graphique à tige croissante des temps d'itération, c'est un symptôme fiable. Enfin, voir la note d'un dev sur Eager vs Graph.

Cela pourrait être ma dernière mise à jour sur cette réponse. Les vraies statistiques sur votre de votre modèle ne peuvent être trouvées que par vous, sur votre appareil.


MISE A JOUR 5/19/2020: TF 2.2, en utilisant les mêmes tests : seulement une amélioration mineure de la vitesse d'Eager. Tracés pour Numpy Large-Large train_on_batch cas ci-dessous, l'axe des abscisses représente les itérations d'ajustement successives ; mon GPU n'est pas proche de sa pleine capacité, donc doute qu'il soit throttling, mais les itérations deviennent effectivement plus lentes avec le temps.

enter image description here

Selon ce qui précède, Graph et Eager sont 1.56x et 1.97x plus lent que leurs homologues de TF1, respectivement. Pas sûr que je vais déboguer cela plus loin, car j'envisage de passer à Pytorch par le faible support de TensorFlow pour les fonctionnalités personnalisées / de bas niveau. J'ai cependant ouvert un Issue pour obtenir le feedback des devs.


MISE À JOUR 18/02/2020: J'ai testé les versions 2.1 et 2.1-nightly ; les résultats sont mitigés. Toutes les configurations sauf une (modèle et taille des données) sont aussi rapides ou beaucoup plus rapides que les meilleures de TF2 et TF1. La configuration la plus lente, et la plus lente de façon spectaculaire, est Large-Large, surtout en exécution graphique (1.6x à 2.5x plus lent).

En outre, il y a extrêmes différences de reproductibilité entre Graph et Eager pour un grand modèle que j'ai testé - une qui n'est pas explicable via le hasard/le parallélisme des ordinateurs. Je ne peux pas actuellement présenter un code reproductible pour ces revendications par contraintes de temps, donc à la place je recommande fortement de tester cela pour vos propres modèles.

Je n'ai pas encore ouvert une question Git sur ceux-ci, mais j'ai fait un commentaire sur l'original - pas encore de réponse. Je mettrai à jour la ou les réponses une fois que des progrès seront réalisés.


VERDICT: il n'est pas si vous savez ce que vous faites. Mais si vous ne le faites pas, cela pourrait vous coûter, beaucoup - par quelques mises à niveau de GPU en moyenne, et par plusieurs GPU dans le pire des cas.


CETTE RÉPONSE: vise à fournir une description de haut niveau de la question, ainsi que des lignes directrices sur la façon de décider de la configuration de formation spécifique à vos besoins. Pour une description détaillée de bas niveau, qui inclut tous les résultats de benchmarking + le code utilisé, voir mon autre réponse.

Je mettrai à jour ma (mes) réponse(s) w / plus d'infos si j'en apprends - peut mettre en signet / "étoile" cette question pour référence.


RÉSUMÉ DE LA QUESTION: comme l'a confirmé un développeur de TensorFlow, Q. Scott Zhu, TF2 a concentré le développement sur l'exécution Eager & l'intégration étroite avec Keras, ce qui a impliqué des changements radicaux dans la source TF - y compris au niveau du graphe. Avantages : des capacités de traitement, de distribution, de débogage et de déploiement considérablement étendues. Le coût de certaines d'entre elles, cependant, est la vitesse.

La question, cependant, est assez plus complexe. Il ne s'agit pas seulement de TF1 contre TF2 - les facteurs donnant lieu à des différences significatives dans la vitesse des trains comprennent :

  1. TF2 vs. TF1
  2. Mode Eager vs. mode Graph
  3. keras vs. tf.keras
  4. numpy vs. tf.data.Dataset vs. ...
  5. train_on_batch() contre. fit()
  6. GPU vs. CPU
  7. model(x) vs. model.predict(x) vs. ...

Malheureusement, presque aucun des éléments ci-dessus n'est indépendant des autres, et chacun peut au moins doubler le temps d'exécution par rapport à un autre. Heureusement, vous pouvez déterminer ce qui fonctionnera le mieux systématiquement, et avec quelques raccourcis - comme je vais le montrer.


QUE DOIS-JE FAIRE ? Actuellement, le seul moyen est - d'expérimenter pour votre modèle spécifique, vos données, et votre matériel. Aucune configuration unique ne fonctionnera toujours au mieux - mais il y a... sont des choses à faire et à ne pas faire pour simplifier votre recherche :

> FAIRE :

  • train_on_batch() + numpy + tf.keras + TF1 + Eager/Graph
  • train_on_batch() + numpy + tf.keras + TF2 + Graphique
  • fit() + numpy + tf.keras + TF1/TF2 + Graphique + grand modèle et données

> NE PAS FAIRE :

  • fit() + numpy + keras pour les petits et moyens modèles et données

  • fit() + numpy + tf.keras + TF1/TF2 + Eager

  • train_on_batch() + numpy + keras + TF1 + Eager

  • [Major]tf.python.keras; il peut fonctionner 10-100x plus lentement, et avec de nombreux bugs ; plus d'infos

    • Ceci comprend layers, models, optimizerset les importations d'usage " hors-boîte " connexes ; ops, utils et les importations " privées " connexes sont acceptables - mais pour être sûr, vérifiez les alts et vérifiez s'ils sont utilisés dans les éléments suivants tf.keras

Référez-vous au code au bas de mon autre réponse pour un exemple de configuration de benchmarking. La liste ci-dessus est basée principalement sur les tableaux "BENCHMARKS" dans l'autre réponse.


LIMITATIONS de la liste ci-dessus des choses à faire et à ne pas faire :

  • Cette question s'intitule "Pourquoi TF2 est beaucoup plus lent que TF1 ?", et si son corps concerne explicitement l'entraînement, la question ne s'y limite pas ; inférence, elle aussi, est sujette à d'importantes différences de vitesse, même au sein d'une même version de TF, d'une même importation, d'un même format de données, etc. - voir cette réponse.
  • Les RNN sont susceptibles de modifier notablement la grille de données dans l'autre réponse, car ils ont été améliorés dans TF2.
  • Modèles principalement utilisés Conv1D et Dense - pas de RNN, données/cibles éparses, entrées 4/5D, et autres configurations
  • Données d'entrée limitées à numpy et tf.data.Datasetalors que de nombreux autres formats existent ; voir autre réponse
  • GPU était noused; résultats sera différer sur un CPU. En fait, lorsque j'ai posé la question, mon CUDA n'était pas correctement configuré, et certains des résultats étaient basés sur le CPU.

Pourquoi TF2 a-t-il sacrifié la qualité la plus pratique, la vitesse, pour une exécution rapide ? Il ne l'a pas fait, clairement - le graphique est toujours disponible. Mais si la question est "pourquoi eager à tous" :

  • Débogage supérieur: vous avez probablement rencontré des multitudes de questions demandant "comment obtenir les sorties des couches intermédiaires" ou "comment inspecter les poids" ; avec eager, c'est (presque) aussi simple que... .__dict__. Graph, en revanche, nécessite une familiarité avec les fonctions spéciales du backend - compliquant grandement tout le processus de débogage et d'introspection.
  • Prototypage plus rapide: par des idées similaires à above; compréhension plus rapide = plus de temps laissé pour la DL réelle.

COMMENT ACTIVER/DÉSACTIVER EAGER ?

tf.enable_eager_execution()  # TF1; must be done before any model/tensor creation
tf.compat.v1.disable_eager_execution() # TF2; above holds

Trompeur dans TF2; voir ici.


INFORMATIONS SUPPLÉMENTAIRES:

  • Attention à _on_batch() méthodes dans TF2; selon le dev TF, ils utilisent toujours une implémentation plus lente, mais pas intentionnellement - c'est à dire que c'est à corriger. Voir autre réponse pour les détails.

DEMANDES AUX DEVS DE TENSORFLOW:

  1. S'il vous plaît fixer train_on_batch(), et l'aspect performance de l'appel fit() itérativement ; les boucles de train personnalisées sont importantes pour beaucoup, surtout pour moi.
  2. Ajouter une documentation / docstring mentionnant ces différences de performance pour la connaissance des utilisateurs.
  3. Améliorer la vitesse d'exécution générale pour garder les peeps de sauter à Pytorch.

REMERCIEMENTS: Merci à

  • Q. Scott Zhu, développeur de TensorFlow, pour sa clarification détaillée sur la question.
  • P. Andrey pour le partage de tests utiles, et la discussion.

MISES À JOUR:

  • 11/14/19 - trouvé un modèle (dans mon application réelle) qui fonctionne plus lentement sur TF2. pour toutes* les configurations avec des données d'entrée Numpy. Les différences varient de 13 à 19 %, avec une moyenne de 17 %. Différences entre keras et tf.kerasétaient toutefois plus spectaculaires : 18-40%, moyenne de 32% (TF1 et 2). (* - sauf Eager, pour lequel TF2 a fait une erreur)

  • 11/17/19 - devs mis à jour on_batch() dans un récent commit, déclarant avoir amélioré la vitesse - à paraître dans TF 2.1, ou disponible maintenant comme tf-nightly. Comme je ne suis pas en mesure de faire fonctionner cette dernière, je vais retarder le benching jusqu'à la 2.1.

  • 2/20/20 - les performances de prédiction valent également la peine d'être benchées ; dans TF2, par exemple, les temps de prédiction du CPU peuvent impliquer des pics périodiques

CETTE RÉPONSE: vise à fournir une description détaillée, au niveau du graphique/matériel, du problème - y compris les boucles de train TF2 vs TF1, les processeurs de données d'entrée, et les exécutions en mode Eager vs Graph. Pour un résumé du problème & des directives de résolution, voir mon autre réponse.


VERDICT SUR LES PERFORMANCES: parfois l'un est plus rapide, parfois l'autre, selon la configuration. En ce qui concerne TF2 vs TF1, ils sont à peu près à égalité en moyenne, mais des différences significatives basées sur la configuration existent, et TF1 l'emporte sur TF2 plus souvent que l'inverse. Voir "BENCHMARKING" ci-dessous.


EAGER VS. GRAPH: la viande de cette réponse entière pour certains : L'empressé de TF2 est plus lent que celui de TF1, d'après mes tests. Détails plus bas.

La différence fondamentale entre les deux est la suivante : Le graphique met en place un réseau de calcul de manière proactive et exécute quand on lui dit de le faire, alors que Eager exécute tout dès sa création. Mais l'histoire ne fait que commencer ici :

  • Eager n'est PAS dépourvu de Graph, et peut en fait être principalement Graphique, contrairement à ce que l'on attendait. Ce qu'il est en grande partie, c'est Graphique exécuté - cela inclut les poids du modèle et de l'optimiseur, constituant une grande partie du graphique.

  • Eager reconstruit une partie de son propre graphe à l'exécution.; conséquence directe du fait que le graphe n'est pas entièrement construit -- voir les résultats du profileur. Cela a une surcharge de calcul.

  • Eager est plus lent avec les entrées Numpy.; selon ce commentaire Git et ce code, les entrées Numpy dans Eager incluent le coût de surcharge de la copie des tenseurs du CPU au GPU. En parcourant le code source, les différences de traitement des données sont claires ; Eager passe directement Numpy, tandis que Graph passe des tenseurs qui sont ensuite évalués en Numpy ; incertain du processus exact, mais ce dernier devrait impliquer des optimisations au niveau du GPU.

  • TF2 Eager est plus lent que TF1 Eager - c'est... inattendu. Voir les résultats du benchmarking ci-dessous. Les différences vont de négligeables à significatives, mais sont cohérentes. Je ne sais pas pourquoi c'est le cas - si un dev dev TF clarifie, je mettrai à jour la réponse.


TF2 vs. TF1 Je cite les parties pertinentes de la réponse d'un dev TF, Q. Scott Zhu - avec un peu de mon emphase et de reformulation :

Dans eager, le runtime doit exécuter les ops et retourner la valeur numérique pour chaque ligne de code python. La nature de l'exécution en une seule étape fait qu'elle est lente.

Dans TF2, Keras exploite tf.function pour construire son graphe pour la formation, l'évaluation et la prédiction. Nous les appelons "fonction d'exécution" pour le modèle. Dans TF1, la "fonction d'exécution" était un FuncGraph, qui partageait certains composants communs avec TF function, mais dont l'implémentation était différente.

Au cours du processus, nous avons en quelque sorte laissé un implémentation incorrecte pour train_on_batch(), test_on_batch() et predict_on_batch().. Ils sont toujours numériquement correctes, mais la fonction d'exécution de x_on_batch est une fonction python pure, plutôt qu'une fonction python enveloppée de tf.function. Cela va causer de la lenteur

Dans TF2, nous convertissons toutes les données d'entrée en un tf.data.Dataset, par lequel nous pouvons unifier notre fonction d'exécution pour gérer le type unique des entrées. Il peut y avoir des surcharge dans la conversion du dataset et je pense que c'est un surcoût unique, plutôt qu'un coût par lot.

Avec la dernière phrase du dernier paragraphe ci-dessus, et la dernière clause du paragraphe ci-dessous :

Pour surmonter la lenteur en mode avide, nous avons @tf.function, qui va transformer une fonction python en un graphique. Lorsque l'on alimente une valeur numérique comme un tableau np, le corps de la fonction tf.function est converti en graphe statique, en étant optimisé, et renvoie la valeur finale, ce qui est rapide et devrait avoir des performances similaires au mode graphique de TF1.

Je ne suis pas d'accord - selon mes résultats de profilage, qui montrent que le traitement des données d'entrée d'Eager est sensiblement plus lent que celui de Graph. Aussi, je ne suis pas sûr de tf.data.Dataset en particulier, mais Eager appelle de manière répétée plusieurs des mêmes méthodes de conversion de données - voir le profileur.

Enfin, le commit lié de dev : Un nombre important de changements pour supporter les boucles Keras v2.


Boucles d'entraînement: selon (1) Eager vs Graph ; (2) le format des données d'entrée, l'entraînement dans se déroulera avec une boucle d'entraînement distincte - dans TF2, _select_training_loop(), training.py, l'un de :

training_v2.Loop()
training_distributed.DistributionMultiWorkerTrainingLoop(
              training_v2.Loop()) # multi-worker mode
# Case 1: distribution strategy
training_distributed.DistributionMultiWorkerTrainingLoop(
            training_distributed.DistributionSingleWorkerTrainingLoop())
# Case 2: generator-like. Input is Python generator, or Sequence object,
# or a non-distributed Dataset or iterator in eager execution.
training_generator.GeneratorOrSequenceTrainingLoop()
training_generator.EagerDatasetOrIteratorTrainingLoop()
# Case 3: Symbolic tensors or Numpy array-like. This includes Datasets and iterators 
# in graph mode (since they generate symbolic tensors).
training_generator.GeneratorLikeTrainingLoop() # Eager
training_arrays.ArrayLikeTrainingLoop() # Graph

Chacun traite l'allocation des ressources différemment, et porte des conséquences sur la performance et la capacité.


Former des boucles : fit vs train_on_batch, keras vs. tf.keras chacun des quatre utilise des boucles de train différentes, mais peut-être pas dans toutes les combinaisons possibles. keras' fitpar exemple, utilise une forme de fit_looppar exemple. training_arrays.fit_loop(), et son train_on_batch peut utiliser K.function(). tf.keras a une hiérarchie plus sophistiquée décrite en partie dans la section précédente.


Boucles de train : documentation -- docstring source pertinente sur certaines des différentes méthodes d'exécution :

Contrairement à d'autres opérations TensorFlow, nous ne convertissons pas les entrées numériques python
entrées numériques en tenseurs. De plus, un nouveau graphe est généré pour chaque
valeur numérique python distincte

functioninstancie un graphe séparé pour chaque ensemble unique d'entrées.
formes et de types de données
.

Un seul objet tf.function peut avoir besoin de correspondre à plusieurs graphes de calcul
sous le capot. Cela devrait être visible uniquement en tant que performance (le traçage des graphes a
a coût de calcul et de mémoire non nul)


Processeurs de données d'entrée: similaire au précédent, le processeur est sélectionné au cas par cas, en fonction de drapeaux internes mis en place selon les configurations d'exécution (mode d'exécution, format de données, stratégie de distribution). Le cas le plus simple est celui d'Eager, qui travaille directement avec les tableaux Numpy. Pour quelques exemples spécifiques, voir cette réponse.


TAILLE DU MODÈLE, TAILLE DES DONNÉES :

  • Est décisife; aucune configuration ne s'est imposée au sommet de toutes les tailles de modèles et de données.
  • La taille des données relative à La taille du modèle est importante ; pour les données et les modèles de petite taille, les frais généraux de transfert de données (par exemple, du CPU au GPU) peuvent dominer. De même, les processeurs à faible surcharge peuvent fonctionner plus lentement sur les grandes données par temps de conversion des données dominant (voir. convert_to_tensor dans "PROFILER")
  • La vitesse diffère par les moyens différents de traitement des ressources des boucles de train et des processeurs de données d'entrée.

BENCHMARKS: la viande hachée. -- Document Word -- Feuille de calcul Excel


Terminologie:

  • Les chiffres sans % sont tous secondes
  • % calculées comme (1 - longer_time / shorter_time)*100; justification : nous sommes intéressés par quel facteur l'un est plus rapide que l'autre ; shorter / longer est en fait une relation non linéaire, non utile pour une comparaison directe.
  • détermination du signe de % :
    • TF2 vs TF1 : + si TF2 est plus rapide
    • GvE (Graphique contre Eager) : + si Graph est plus rapide
  • TF2 = TensorFlow 2.0.0 + Keras 2.3.1; TF1 = TensorFlow 1.14.0 + Keras 2.2.5

PROFILER:


PROFILER - Explication: Profileur de l'IDE Spyder 3.3.6.

  • Certaines fonctions sont répétées dans des nids d'autres fonctions ; ainsi, il est difficile de repérer la séparation exacte entre les fonctions de "traitement des données" et de "formation", il y aura donc un certain chevauchement - comme prononcé dans le tout dernier résultat.

  • % de chiffres calculés par rapport au temps d'exécution. moins le temps de construction

  • Temps de construction calculé en additionnant tous les temps d'exécution (uniques) qui ont été appelés 1 ou 2 fois.
  • Temps de train calculé en additionnant tous les runtimes (uniques) qui ont été appelés le même nombre de fois que le nombre d'itérations, et certains des runtimes de leurs nids.
  • Les fonctions sont profilées en fonction de leur original noms, malheureusement (c'est-à-dire _func = func sera profilé comme func), ce qui mélange le temps de construction - d'où la nécessité de l'exclure

ENVIRONNEMENT DE TEST:

  • Code exécuté en bas avec des tâches de fond minimales en cours d'exécution.
  • GPU a été "chauffé" avec quelques itérations avant les itérations de chronométrage, comme suggéré dans ce post.
  • CUDA 10.0.130, cuDNN 7.6.0, TensorFlow 1.14.0 et TensorFlow 2.0.0 construits à partir des sources, plus Anaconda.
  • Python 3.7.4, IDE Spyder 3.3.6
  • GTX 1070, Windows 10, 24GB DDR4 2.4-MHz RAM, i7-7700HQ 2.8-GHz CPU

MÉTHODOLOGIE:

  • Benchmark " petit ", " moyen " et " grand " modèle et taille des données.
  • Fixer # de paramètres pour chaque taille de modèle, indépendamment de la taille des données d'entrée.
  • Le modèle "plus grand" a plus de paramètres et de couches.
  • Les données "plus grandes" ont une séquence plus longue, mais identique. batch_size et num_channels
  • Les modèles utilisent seulement Conv1D, Dense couches "apprenables" ; RNNs évités par les différences d'implémentation de la version TF.
  • Toujours exécuter un ajustement de train en dehors de la boucle de benchmarking, pour omettre la construction du graphique du modèle et de l'optimiseur.
  • Pas d'utilisation de données éparses (par ex. layers.Embedding()) ou des cibles éparses (par ex. SparseCategoricalCrossEntropy()

LIMITATIONS: une réponse "complète" expliquerait chaque boucle de train & itérateur possible, mais c'est sûrement au-delà de ma capacité de temps, de mon salaire inexistant, ou de la nécessité générale. Les résultats sont seulement aussi bons que la méthodologie - interprétez avec un esprit ouvert.


CODE:

import numpy as np
import tensorflow as tf
import random
from termcolor import cprint
from time import time

from tensorflow.keras.layers import Input, Dense, Conv1D
from tensorflow.keras.layers import Dropout, GlobalAveragePooling1D
from tensorflow.keras.models import Model
from tensorflow.keras.optimizers import Adam
import tensorflow.keras.backend as K
#from keras.layers import Input, Dense, Conv1D
#from keras.layers import Dropout, GlobalAveragePooling1D
#from keras.models import Model 
#from keras.optimizers import Adam
#import keras.backend as K

#tf.compat.v1.disable_eager_execution()
#tf.enable_eager_execution()

def reset_seeds(reset_graph_with_backend=None, verbose=1):
    if reset_graph_with_backend is not None:
        K = reset_graph_with_backend
        K.clear_session()
        tf.compat.v1.reset_default_graph()
        if verbose:
            print("KERAS AND TENSORFLOW GRAPHS RESET")

    np.random.seed(1)
    random.seed(2)
    if tf.__version__[0] == '2':
        tf.random.set_seed(3)
    else:
        tf.set_random_seed(3)
    if verbose:
        print("RANDOM SEEDS RESET")

print("TF version: {}".format(tf.__version__))
reset_seeds()

def timeit(func, iterations, *args, _verbose=0, **kwargs):
    t0 = time()
    for _ in range(iterations):
        func(*args, **kwargs)
        print(end='.'*int(_verbose))
    print("Time/iter: %.4f sec" % ((time() - t0) / iterations))

def make_model_small(batch_shape):
    ipt   = Input(batch_shape=batch_shape)
    x     = Conv1D(128, 40, strides=4, padding='same')(ipt)
    x     = GlobalAveragePooling1D()(x)
    x     = Dropout(0.5)(x)
    x     = Dense(64, activation='relu')(x)
    out   = Dense(1,  activation='sigmoid')(x)
    model = Model(ipt, out)
    model.compile(Adam(lr=1e-4), 'binary_crossentropy')
    return model

def make_model_medium(batch_shape):
    ipt = Input(batch_shape=batch_shape)
    x = ipt
    for filters in [64, 128, 256, 256, 128, 64]:
        x  = Conv1D(filters, 20, strides=1, padding='valid')(x)
    x     = GlobalAveragePooling1D()(x)
    x     = Dense(256, activation='relu')(x)
    x     = Dropout(0.5)(x)
    x     = Dense(128, activation='relu')(x)
    x     = Dense(64,  activation='relu')(x)
    out   = Dense(1,   activation='sigmoid')(x)
    model = Model(ipt, out)
    model.compile(Adam(lr=1e-4), 'binary_crossentropy')
    return model

def make_model_large(batch_shape):
    ipt   = Input(batch_shape=batch_shape)
    x     = Conv1D(64,  400, strides=4, padding='valid')(ipt)
    x     = Conv1D(128, 200, strides=1, padding='valid')(x)
    for _ in range(40):
        x = Conv1D(256,  12, strides=1, padding='same')(x)
    x     = Conv1D(512,  20, strides=2, padding='valid')(x)
    x     = Conv1D(1028, 10, strides=2, padding='valid')(x)
    x     = Conv1D(256,   1, strides=1, padding='valid')(x)
    x     = GlobalAveragePooling1D()(x)
    x     = Dense(256, activation='relu')(x)
    x     = Dropout(0.5)(x)
    x     = Dense(128, activation='relu')(x)
    x     = Dense(64,  activation='relu')(x)    
    out   = Dense(1,   activation='sigmoid')(x)
    model = Model(ipt, out)
    model.compile(Adam(lr=1e-4), 'binary_crossentropy')
    return model

def make_data(batch_shape):
    return np.random.randn(*batch_shape), 
           np.random.randint(0, 2, (batch_shape[0], 1))

def make_data_tf(batch_shape, n_batches, iters):
    data = np.random.randn(n_batches, *batch_shape),
    trgt = np.random.randint(0, 2, (n_batches, batch_shape[0], 1))
    return tf.data.Dataset.from_tensor_slices((data, trgt))#.repeat(iters)

batch_shape_small  = (32, 140,   30)
batch_shape_medium = (32, 1400,  30)
batch_shape_large  = (32, 14000, 30)

batch_shapes = batch_shape_small, batch_shape_medium, batch_shape_large
make_model_fns = make_model_small, make_model_medium, make_model_large
iterations = [200, 100, 50]
shape_names = ["Small data",  "Medium data",  "Large data"]
model_names = ["Small model", "Medium model", "Large model"]

def test_all(fit=False, tf_dataset=False):
    for model_fn, model_name, iters in zip(make_model_fns, model_names, iterations):
        for batch_shape, shape_name in zip(batch_shapes, shape_names):
            if (model_fn is make_model_large) and (batch_shape == batch_shape_small):
                continue
            reset_seeds(reset_graph_with_backend=K)
            if tf_dataset:
                data = make_data_tf(batch_shape, iters, iters)
            else:
                data = make_data(batch_shape)
            model = model_fn(batch_shape)

            if fit:
                if tf_dataset:
                    model.train_on_batch(data.take(1))
                    t0 = time()
                    model.fit(data, steps_per_epoch=iters)
                    print("Time/iter: %.4f sec" % ((time() - t0) / iters))
                else:
                    model.train_on_batch(*data)
                    timeit(model.fit, iters, *data, _verbose=1, verbose=0)
            else:
                model.train_on_batch(*data)
                timeit(model.train_on_batch, iters, *data, _verbose=1)
            cprint(">> {}, {} done <

Section des critiques et des évaluations

Si notre publication vous a été utile, il serait très utile que vous la partagiez avec le reste des juniors, vous contribuerez ainsi à diffuser cette information.



Utilisez notre moteur de recherche

Ricerca
Generic filters

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée.