37 votes

Tensorflow: restaurer un graphique et un modèle, puis exécuter une évaluation sur une seule image

Je pense qu'il serait extrêmement utile à la Tensorflow de la communauté s'il y a bien la solution de la tâche cruciale de l'essai d'une nouvelle image sur le modèle créé par le convnet dans l'ICRA-10 tutoriel.

J'ai peut-être tort, mais cette étape critique qui rend le modèle appris utilisable dans la pratique semble être en manque. Il y a un "chaînon manquant" dans le tutoriel-un script qui permettrait de charger directement une seule image (sous forme de tableau ou binaire), la comparaison avec le modèle appris, et le retour d'une classification.

Avant donner des réponses à des solutions partielles qui expliquent l'approche globale, mais aucun de qui j'ai été en mesure de mettre en œuvre avec succès. D'autres morceaux peuvent être trouvés ici et là, mais, malheureusement, n'ont pas ajouté à une solution de travail. Veuillez considérer les recherches que j'ai fait, avant de marquage ce des doublons ou déjà répondu.

Tensorflow: comment sauvegarder/restaurer un modèle?

La restauration de TensorFlow modèle

Incapable de restaurer les modèles dans tensorflow v0.8

https://gist.github.com/nikitakit/6ef3b72be67b86cb7868

La réponse la plus populaire est la première, dans laquelle @RyanSepassi et @YaroslavBulatov décrire le problème et une approche: on a besoin de "construire manuellement un graphique avec les mêmes noms de nœud, et l'utilisation de l'Économiseur de charger le poids en elle". Bien que les deux réponses sont utiles, il n'est pas évident comment on allait faire à propos de cela branchant dans l'ICRA-10 du projet.

Entièrement fonctionnelle d'une solution serait hautement souhaitable de sorte que nous pourrions porter sur d'autres de l'image unique, les problèmes de classification. Il y a plusieurs questions DONC, à cet égard, que demander cela, mais toujours pas de réponse complète (par exemple la Charge de point de contrôle et évaluer une seule image avec tensorflow DNN).

J'espère que nous pourrons aboutir à un travail de script que tout le monde pourrait utiliser.

Le script ci-dessous n'est pas encore fonctionnelle, et je serais heureux de vous entendre sur la façon dont cela peut être amélioré pour offrir une solution unique de classification des images à l'aide de l'ICRA-10 TF tutoriel modèle appris.

Assumer toutes les variables, les noms de fichiers etc. sont intacts de la didacticiel d'origine.

Nouveau fichier: cifar10_eval_single.py

import cv2
import tensorflow as tf

FLAGS = tf.app.flags.FLAGS

tf.app.flags.DEFINE_string('eval_dir', './input/eval',
                           """Directory where to write event logs.""")
tf.app.flags.DEFINE_string('checkpoint_dir', './input/train',
                           """Directory where to read model checkpoints.""")

def get_single_img():
    file_path = './input/data/single/test_image.tif'
    pixels = cv2.imread(file_path, 0)
    return pixels

def eval_single_img():

    # below code adapted from @RyanSepassi, however not functional
    # among other errors, saver throws an error that there are no
    # variables to save
    with tf.Graph().as_default():

        # Get image.
        image = get_single_img()

        # Build a Graph.
        # TODO

        # Create dummy variables.
        x = tf.placeholder(tf.float32)
        w = tf.Variable(tf.zeros([1, 1], dtype=tf.float32))
        b = tf.Variable(tf.ones([1, 1], dtype=tf.float32))
        y_hat = tf.add(b, tf.matmul(x, w))

        saver = tf.train.Saver()

        with tf.Session() as sess:
            sess.run(tf.initialize_all_variables())
            ckpt = tf.train.get_checkpoint_state(FLAGS.checkpoint_dir)

            if ckpt and ckpt.model_checkpoint_path:
                saver.restore(sess, ckpt.model_checkpoint_path)
                print('Checkpoint found')
            else:
                print('No checkpoint found')

            # Run the model to get predictions
            predictions = sess.run(y_hat, feed_dict={x: image})
            print(predictions)

def main(argv=None):
    if tf.gfile.Exists(FLAGS.eval_dir):
        tf.gfile.DeleteRecursively(FLAGS.eval_dir)
    tf.gfile.MakeDirs(FLAGS.eval_dir)
    eval_single_img()

if __name__ == '__main__':
    tf.app.run()

10voto

bigdata2 Points 626

Il existe deux méthodes pour nourrir une seule nouvelle image à la cifar10 modèle. La première méthode est plus propre approche, mais nécessite une modification dans le fichier principal, auront donc besoin de reconversion. La seconde méthode est applicable lorsqu'un utilisateur ne souhaite pas modifier les fichiers de modèle et cherche à utiliser les check-point/méta-graphe de fichiers.

Le code pour la première approche est la suivante:

import tensorflow as tf
import numpy as np
import cv2

sess = tf.Session('', tf.Graph())
with sess.graph.as_default():
    # Read meta graph and checkpoint to restore tf session
    saver = tf.train.import_meta_graph("/tmp/cifar10_train/model.ckpt-200.meta")
    saver.restore(sess, "/tmp/cifar10_train/model.ckpt-200")

    # Read a single image from a file.
    img = cv2.imread('tmp.png')
    img = np.expand_dims(img, axis=0)

    # Start the queue runners. If they are not started the program will hang
    # see e.g. https://www.tensorflow.org/programmers_guide/reading_data
    coord = tf.train.Coordinator()
    threads = []
    for qr in sess.graph.get_collection(tf.GraphKeys.QUEUE_RUNNERS):
        threads.extend(qr.create_threads(sess, coord=coord, daemon=True,
                                         start=True))

    # In the graph created above, feed "is_training" and "imgs" placeholders.
    # Feeding them will disconnect the path from queue runners to the graph 
    # and enable a path from the placeholder instead. The "img" placeholder will be 
    # fed with the image that was read above.
    logits = sess.run('softmax_linear/softmax_linear:0', 
                     feed_dict={'is_training:0': False, 'imgs:0': img})

    #Print classifiction results.
    print(logits) 

Le script nécessite qu'un utilisateur crée deux espaces réservés et une exécution conditionnelle déclaration pour que cela fonctionne.

Les espaces réservés et de l'exécution conditionnelle de déclaration sont ajoutés dans cifar10_train.py comme indiqué ci-dessous:

def train():   
"""Train CIFAR-10 for a number of steps."""   
    with tf.Graph().as_default():
        global_step = tf.contrib.framework.get_or_create_global_step()

    with tf.device('/cpu:0'):
        images, labels = cifar10.distorted_inputs()

    is_training = tf.placeholder(dtype=bool,shape=(),name='is_training')
    imgs = tf.placeholder(tf.float32, (1, 32, 32, 3), name='imgs')
    images = tf.cond(is_training, lambda:images, lambda:imgs)
    logits = cifar10.inference(images)

Les entrées dans cifar10 modèle sont connectés à la file d'attente coureur de l'objet, qui est un processus à plusieurs étapes de la file d'attente qui peut prefetch de données à partir de fichiers en parallèle. Voir une belle animation de file de coureur ici

Alors que la file d'attente des coureurs sont efficaces dans le pré-chargement de grand jeu de données pour la formation, ils sont un overkill pour l'inférence/test où un seul fichier qui est nécessaire pour être classés, ils sont aussi un peu plus compliqué à modifier ou à maintenir. Pour cette raison, j'ai ajouté un espace réservé "is_training", qui est défini à False, alors qu'une formation comme indiqué ci-dessous:

 import numpy as np
 tmp_img = np.ndarray(shape=(1,32,32,3), dtype=float)
 with tf.train.MonitoredTrainingSession(
     checkpoint_dir=FLAGS.train_dir,
     hooks=[tf.train.StopAtStepHook(last_step=FLAGS.max_steps),
            tf.train.NanTensorHook(loss),
            _LoggerHook()],
     config=tf.ConfigProto(
         log_device_placement=FLAGS.log_device_placement)) as mon_sess:
   while not mon_sess.should_stop():
     mon_sess.run(train_op, feed_dict={is_training: True, imgs: tmp_img})

Un autre espace réservé "dim" est titulaire d'un tenseur de forme (1,32,32,3) de l'image qui seront introduits lors de l'inférence -- la première dimension est la taille du lot qui est dans ce cas. J'ai modifié l'icra modèle d'accepter 32x32 au lieu de 24x24 que l'original cifar10 images sont de 32x32.

Enfin, l'instruction conditionnelle se nourrit de l'espace réservé en file d'attente ou coureur de sortie pour le graphique. Le "is_training" espace réservé est définie sur False lors de l'inférence et "img" de l'espace réservé est nourri d'un tableau numpy -- le tableau numpy est de passer de 3 à 4 dimensions vecteur pour se conformer à l'entrée du tenseur à l'inférence de la fonction dans le modèle.

C'est tout là est à lui. N'importe quel modèle peut être déduit avec un seul/défini par l'utilisateur des données de test comme indiqué dans le script ci-dessus. Essentiellement lire le graphique, les données de flux pour les noeuds d'un graphe et d'exécuter le graphe pour obtenir le résultat final.

Maintenant, la deuxième méthode. L'autre approche consiste à pirater cifar10.py et cifar10_eval.py pour modifier la taille du lot de l'un et de remplacer les données provenant de la file d'attente de coureur avec la lecture à partir d'un fichier.

Définir la taille du lot de 1:

tf.app.flags.DEFINE_integer('batch_size', 1,
                             """Number of images to process in a batch.""")

Appel d'inférence avec une image de lecture de fichier.

def evaluate():   with tf.Graph().as_default() as g:
    # Get images and labels for CIFAR-10.
    eval_data = FLAGS.eval_data == 'test'
    images, labels = cifar10.inputs(eval_data=eval_data)
    import cv2
    img = cv2.imread('tmp.png')
    img = np.expand_dims(img, axis=0)
    img = tf.cast(img, tf.float32)

    logits = cifar10.inference(img)

Puis passer les logits de eval_once et modifier eval une fois pour évaluer les logits:

def eval_once(saver, summary_writer, top_k_op, logits, summary_op): 
    ...
    while step < num_iter and not coord.should_stop():
        predictions = sess.run([top_k_op])
        print(sess.run(logits))

Il n'y a pas de script pour exécuter cette méthode d'inférence, il suffit d'exécuter cifar10_eval.py qui va lire un fichier à partir de l'emplacement défini par l'utilisateur avec une taille de lot de l'un.

6voto

Steven Points 3487

Voici comment j'ai couru une seule image à la fois. Je vais vous avouer que cela semble un peu hacky avec la réutilisation de l'obtention de la portée.

C'est une fonction d'assistance

def restore_vars(saver, sess, chkpt_dir):
    """ Restore saved net, global score and step, and epsilons OR
    create checkpoint directory for later storage. """
    sess.run(tf.initialize_all_variables())

    checkpoint_dir = chkpt_dir

    if not os.path.exists(checkpoint_dir):
        try:
            os.makedirs(checkpoint_dir)
        except OSError:
            pass

    path = tf.train.get_checkpoint_state(checkpoint_dir)
    #print("path1 = ",path)
    #path = tf.train.latest_checkpoint(checkpoint_dir)
    print(checkpoint_dir,"path = ",path)
    if path is None:
        return False
    else:
        saver.restore(sess, path.model_checkpoint_path)
        return True

Ici est la partie principale du code qui s'exécute une seule image à la fois dans la boucle for.

to_restore = True
with tf.Session() as sess:

    for i in test_img_idx_set:

            # Gets the image
            images = get_image(i)
            images = np.asarray(images,dtype=np.float32)
            images = tf.convert_to_tensor(images/255.0)
            # resize image to whatever you're model takes in
            images = tf.image.resize_images(images,256,256)
            images = tf.reshape(images,(1,256,256,3))
            images = tf.cast(images, tf.float32)

            saver = tf.train.Saver(max_to_keep=5, keep_checkpoint_every_n_hours=1)

            #print("infer")
            with tf.variable_scope(tf.get_variable_scope()) as scope:
                if to_restore:
                    logits = inference(images)
                else:
                    scope.reuse_variables()
                    logits = inference(images)


            if to_restore:
                restored = restore_vars(saver, sess,FLAGS.train_dir)
                print("restored ",restored)
                to_restore = False

            logit_val = sess.run(logits)
            print(logit_val)

Voici une alternative de mise en œuvre de la ci-dessus en utilisant les détenteurs de place c'est un peu plus propre à mon avis. mais je vais laisser l'exemple ci-dessus, pour des raisons historiques.

imgs_place = tf.placeholder(tf.float32, shape=[my_img_shape_put_here])
images = tf.reshape(imgs_place,(1,256,256,3))

saver = tf.train.Saver(max_to_keep=5, keep_checkpoint_every_n_hours=1)

#print("infer")
logits = inference(images)

restored = restore_vars(saver, sess,FLAGS.train_dir)
print("restored ",restored)

with tf.Session() as sess:
    for i in test_img_idx_set:
        logit_val = sess.run(logits,feed_dict={imgs_place=i})
        print(logit_val)

4voto

Noah Smith Points 78

ça marche avec ça

 softmax = gn.inference(image)
saver = tf.train.Saver()
ckpt = tf.train.get_checkpoint_state(FLAGS.checkpoint_dir)
with tf.Session() as sess:
  saver.restore(sess, ckpt.model_checkpoint_path)
  softmaxval = sess.run(softmax)
  print(softmaxval)
 

sortie

 [[  6.73550041e-03   4.44930716e-04   9.92570221e-01   1.00681427e-06
    3.05406687e-08   2.38927707e-04   1.89839399e-12   9.36238484e-06
    1.51646684e-09   3.38977535e-09]]
 

2voto

Pete Warden Points 2328

Je n'ai pas le code qui fonctionne pour vous, j'ai peur, mais voici comment nous avons souvent de résoudre ce problème dans la production:

  • Enregistrer les GraphDef sur le disque, en utilisant quelque chose comme write_graph.

  • Utilisation freeze_graph pour charger le GraphDef et des points de contrôle, et d'enregistrer un GraphDef avec les Variables convertis en des Constantes.

  • Charger le GraphDef dans quelque chose comme label_image ou classify_image.

Pour votre exemple, c'est exagéré, mais j'aurais au moins suggérer la sérialisation sur le graphe de l'exemple original comme un GraphDef, puis de le charger dans votre script (si vous n'avez pas à dupliquer le code générer le graphique). Avec le même graphique que vous avez créé, vous devriez être en mesure de l'alimenter à partir d'un SaverDef, et la freeze_graph script peut aider comme un exemple.

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