Pertanyaan Tensorflow: memulihkan grafik dan model kemudian menjalankan evaluasi pada satu gambar


Saya pikir itu akan sangat membantu komunitas Tensorflow jika ada solusi yang terdokumentasi dengan baik untuk tugas penting menguji citra baru tunggal terhadap model yang dibuat oleh convnet dalam tutorial CIFAR-10.

Saya mungkin salah, tetapi langkah penting ini yang membuat model terlatih dapat digunakan dalam praktik tampaknya kurang. Ada "tautan yang hilang" dalam tutorial itu — skrip yang akan langsung memuat satu gambar (sebagai larik atau biner), membandingkannya dengan model yang dilatih, dan mengembalikan klasifikasi.

Jawaban sebelumnya memberikan solusi parsial yang menjelaskan pendekatan keseluruhan, tetapi tidak ada yang berhasil saya terapkan. Potongan dan potongan lain dapat ditemukan di sana-sini, tetapi sayangnya belum ditambahkan ke solusi yang berfungsi. Mohon pertimbangkan penelitian yang telah saya lakukan, sebelum menandai ini sebagai duplikat atau sudah dijawab.

Tensorflow: bagaimana cara menyimpan / mengembalikan model?

Memulihkan model TensorFlow

Tidak dapat memulihkan model di tensorflow v0.8

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

Jawaban yang paling populer adalah yang pertama, di mana @RyanSepassi dan @YaroslavBulatov mendeskripsikan masalah dan pendekatan: seseorang perlu "membuat grafik secara manual dengan nama node yang identik, dan menggunakan Saver untuk memuat bobot ke dalamnya". Meskipun kedua jawaban itu bermanfaat, tidak jelas bagaimana orang akan memasukkannya ke dalam proyek CIFAR-10.

Sebuah solusi yang berfungsi penuh akan sangat diinginkan sehingga kita bisa mem-port-nya ke masalah klasifikasi gambar tunggal lainnya. Ada beberapa pertanyaan di SO dalam hal ini yang meminta ini, tetapi masih tidak ada jawaban penuh (misalnya Muat pos pemeriksaan dan evaluasi gambar tunggal dengan tensorflow DNN).

Saya harap kita dapat menemukan naskah kerja yang dapat digunakan semua orang.

Skrip di bawah ini belum berfungsi, dan saya akan senang mendengar dari Anda tentang bagaimana ini dapat ditingkatkan untuk memberikan solusi untuk klasifikasi gambar tunggal menggunakan model pelatihan CIFAR-10 TF tutorial.

Asumsikan semua variabel, nama file dll tidak tersentuh dari tutorial asli.

File baru: 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()

32
2018-06-06 03:14


asal


Jawaban:


Ada dua metode untuk memberi makan satu gambar baru ke cifar10 model. Metode pertama adalah pendekatan yang lebih bersih tetapi membutuhkan modifikasi pada file utama, sehingga membutuhkan pelatihan ulang. Metode kedua berlaku ketika pengguna tidak ingin memodifikasi file model dan sebaliknya ingin menggunakan file check-point / meta-graph yang ada.

Kode untuk pendekatan pertama adalah sebagai berikut:

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) 

Skrip mengharuskan pengguna membuat dua placeholder dan pernyataan eksekusi bersyarat agar berfungsi.

Placeholder dan pernyataan eksekusi bersyarat ditambahkan dalam cifar10_train.py seperti yang ditunjukkan di bawah ini:

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)

Input dalam model cifar10 terhubung ke antrian objek antrian yang merupakan antrian multitahap yang dapat mengambil data dari file secara paralel. Lihat animasi pelari antrian yang bagus sini

Sementara pelari antrian efisien dalam mengambil kumpulan data besar untuk pelatihan, mereka adalah berlebihan untuk inferensi / pengujian di mana hanya satu file yang perlu diklasifikasikan, juga mereka sedikit lebih terlibat untuk memodifikasi / memelihara. Karena itu, saya telah menambahkan placeholder "is_training", yang disetel ke False saat pelatihan seperti yang ditunjukkan di bawah ini:

 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})

Placeholder lain "imgs" memegang tensor bentuk (1,32,32,3) untuk gambar yang akan diberi makan selama inferensi - dimensi pertama adalah ukuran batch yang merupakan salah satu dalam kasus ini. Saya telah memodifikasi model cifar untuk menerima gambar 32x32 alih-alih 24x24 karena gambar cifar10 asli adalah 32x32.

Akhirnya, pernyataan kondisional ini memberi masukan kepada placeholder atau queue runner ke grafik. The "is_training" placeholder diatur ke False selama inferensi dan "img" placeholder diberi makan array numpy - array numpy dibentuk kembali dari 3 hingga 4 vektor dimensi untuk menyesuaikan dengan input tensor ke fungsi inferensi dalam model.

Hanya itu saja. Setiap model dapat disimpulkan dengan data pengujian tunggal / pengguna yang ditentukan seperti yang ditunjukkan pada skrip di atas. Pada dasarnya membaca grafik, memberi umpan data ke node grafik dan menjalankan grafik untuk mendapatkan hasil akhir.

Sekarang metode kedua. Pendekatan lainnya adalah meretas cifar10.py dan cifar10_eval.py untuk mengubah ukuran bets menjadi satu dan mengganti data yang berasal dari antrian dengan yang dibaca dari sebuah file.

Setel ukuran bets menjadi 1:

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

Panggilan inferensi dengan file gambar dibaca.

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)

Lalu, kirimkan log ke eval_once dan ubah eval sekali untuk mengevaluasi log:

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))

Tidak ada skrip terpisah untuk menjalankan metode inferensi ini, jalankan cifar10_eval.py yang sekarang akan membaca file dari lokasi yang ditentukan pengguna dengan ukuran batch satu.


7
2017-07-10 05:04



Begini cara saya menjalankan satu gambar pada satu waktu. Saya akui bahwa tampaknya agak jijik dengan penggunaan kembali ruang lingkup.

Ini adalah fungsi pembantu

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

Berikut adalah bagian utama dari kode yang menjalankan satu gambar pada suatu waktu di dalam loop.

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)

Berikut ini adalah implementasi alternatif untuk penggunaan di atas menggunakan pemegang tempat itu sedikit lebih bersih menurut saya. tetapi saya akan meninggalkan contoh di atas karena alasan historis.

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)

5
2018-06-09 23:57



membuatnya bekerja dengan ini

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)

keluaran

[[  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]]

4
2017-12-27 19:33



Saya tidak memiliki kode kerja untuk Anda, saya khawatir, tetapi inilah cara kami sering menangani masalah ini dalam produksi:

  • Simpan keluar GraphDef ke disk, menggunakan sesuatu seperti write_graph.

  • Menggunakan freeze_graph untuk memuat GraphDef dan checkpoint, dan menyimpan GraphDef dengan Variabel diubah menjadi Konstanta.

  • Muat GraphDef dalam sesuatu seperti label_image atau classify_image.

Untuk contoh Anda ini berlebihan, tapi saya setidaknya akan menyarankan serialisasi grafik dalam contoh asli sebagai GraphDef, dan kemudian memuatnya di skrip Anda (sehingga Anda tidak perlu menggandakan kode yang menghasilkan grafik). Dengan grafik yang sama dibuat, Anda harus dapat mengisinya dari SaverDef, dan script freeze_graph dapat membantu sebagai contoh.


2
2018-06-07 01:38