Восстановление модели, обученной с помощью tf.estimator, и ввод данных через feed_dict

Я тренировал реснет с tf.estimator, модель сохранялась в процессе обучения. Сохраненные файлы состоят из .data, .index и .meta. Я хочу загрузить эту модель обратно и получить прогнозы для новых изображений. Данные были переданы модели во время обучения с использованием tf.data.Dataset. Я внимательно следил за реализацией реснета, представленной здесь.

Я хотел бы восстановить модель и передать входные данные узлам с помощью feed_dict.

Первая попытка

  #rebuild input pipeline
  images, labels = input_fn(data_dir, batch_size=32, num_epochs=1)

  #rebuild graph
  prediction= imagenet_model_fn(images,labels,{'batch_size':32,'data_format':'channels_first','resnet_size':18},mode = tf.estimator.ModeKeys.EVAL).predictions 

  saver  = tf.train.Saver()
  with tf.Session() as sess:
    ckpt = tf.train.get_checkpoint_state(r'./model')
    saver.restore(sess, ckpt.model_checkpoint_path)
    while True:
    try:
        pred,im= sess.run([prediction,images])
        print(pred)
    except tf.errors.OutOfRangeError:
      break

Я передал набор данных, который был оценен на той же модели с использованием classifier.evaluate, но описанный выше метод дает неверные прогнозы. Модель дает одинаковый класс и вероятность 1,0 для всех изображений.

Вторая попытка

saver = tf.train.import_meta_graph(r'.\resnet\model\model-3220.meta')
sess = tf.Session()
saver.restore(sess,tf.train.latest_checkpoint(r'.\resnet\model'))
graph = tf.get_default_graph()
inputImage = graph.get_tensor_by_name('image:0')
logits= graph.get_tensor_by_name('logits:0')

#Get prediction
print(sess.run(logits,feed_dict={inputImage:newimage}))

Это также дает неверные прогнозы по сравнению с classifier.evaluate. Я даже могу запустить sess.run(logits) без feed_dict!

Третья попытка

def serving_input_fn():
  receiver_tensor = {'feature': tf.placeholder(shape=[None, 384, 256, 3], dtype=tf.float32)}
  features = {'feature': receiver_tensor['images']}
return tf.estimator.export.ServingInputReceiver(features, receiver_tensor)

Это терпит неудачу с

Traceback (most recent call last):
  File "imagenet_main.py", line 213, in <module>
    tf.app.run(argv=[sys.argv[0]] + unparsed)
  File "C:\Users\Photogauge\Anaconda3\envs\tensorflow\lib\site-packages\tensorflow\python\platform\app.py", line 124, in run
    _sys.exit(main(argv))
  File "imagenet_main.py", line 204, in main
    resnet.resnet_main(FLAGS, imagenet_model_fn, input_fn)
  File "C:\Users\Photogauge\Desktop\iprings_images\models-master\models-master\official\resnet\resnet.py", line 527, in resnet_main
    classifier.export_savedmodel(export_dir_base=r"C:\Users\Photogauge\Desktop\iprings_images\models-master\models-master\official\resnet\export", serving_input_receiver_fn=serving_input_fn)
  File "C:\Users\Photogauge\Anaconda3\envs\tensorflow\lib\site-packages\tensorflow\python\estimator\estimator.py", line 528, in export_savedmodel
    config=self.config)
  File "C:\Users\Photogauge\Anaconda3\envs\tensorflow\lib\site-packages\tensorflow\python\estimator\estimator.py", line 725, in _call_model_fn
    model_fn_results = self._model_fn(features=features, **kwargs)
  File "imagenet_main.py", line 200, in imagenet_model_fn
    loss_filter_fn=None)
  File "C:\Users\Photogauge\Desktop\iprings_images\models-master\models-master\official\resnet\resnet.py", line 433, in resnet_model_fn
    tf.argmax(labels, axis=1), predictions['classes'])
  File "C:\Users\Photogauge\Anaconda3\envs\tensorflow\lib\site-packages\tensorflow\python\util\deprecation.py", line 316, in new_func
    return func(*args, **kwargs)
  File "C:\Users\Photogauge\Anaconda3\envs\tensorflow\lib\site-packages\tensorflow\python\ops\math_ops.py", line 208, in argmax
    return gen_math_ops.arg_max(input, axis, name=name, output_type=output_type)
  File "C:\Users\Photogauge\Anaconda3\envs\tensorflow\lib\site-packages\tensorflow\python\ops\gen_math_ops.py", line 508, in arg_max
    name=name)
  File "C:\Users\Photogauge\Anaconda3\envs\tensorflow\lib\site-packages\tensorflow\python\framework\op_def_library.py", line 528, in _apply_op_helper
    (input_name, err))
ValueError: Tried to convert 'input' to a tensor and failed. Error: None values not supported.

Код, который я использовал для обучения и построения модели, выглядит следующим образом:

Спецификация для разбора набора данных:

def parse_record(raw_record, is_training):
  keys_to_features = {
      'image/encoded':
          tf.FixedLenFeature((), tf.string, default_value=''),
      'image/class/label':
          tf.FixedLenFeature([], dtype=tf.int64, default_value=-1),
  }
  parsed = tf.parse_single_example(raw_record, keys_to_features)
  image = tf.image.decode_image(
      tf.reshape(parsed['image/encoded'], shape=[]),3)
  image = tf.image.convert_image_dtype(image, dtype=tf.float32)
  label = tf.cast(
      tf.reshape(parsed['image/class/label'], shape=[]),
      dtype=tf.int32)
  return image, tf.one_hot(label,2)

Следующая функция анализирует данные и создает пакеты для обучения.

def input_fn(is_training, data_dir, batch_size, num_epochs=1):
  dataset = tf.data.Dataset.from_tensor_slices(
      filenames(is_training, data_dir))
  if is_training:
     dataset = dataset.shuffle(buffer_size=_FILE_SHUFFLE_BUFFER)
  dataset = dataset.flat_map(tf.data.TFRecordDataset)
  dataset = dataset.map(lambda value: parse_record(value, is_training),
                        num_parallel_calls=5)
  dataset = dataset.prefetch(batch_size)
  if is_training:
      dataset = dataset.shuffle(buffer_size=_SHUFFLE_BUFFER)
  dataset = dataset.repeat(num_epochs)
  dataset = dataset.batch(batch_size)

  iterator = dataset.make_one_shot_iterator()
  images, labels = iterator.get_next()
  return images, labels

Классификатор создается, как показано ниже, для обучения на наборе поездов и оценки на наборе проверки.

classifier = tf.estimator.Estimator(
      model_fn=model_function, model_dir=flags.model_dir, config=run_config,
      params={
          'resnet_size': flags.resnet_size,
          'data_format': flags.data_format,
          'batch_size': flags.batch_size,
      })

    #Training cycle
     classifier.train(
         input_fn=lambda: input_function(
             training_phase=True, flags.data_dir, flags.batch_size, flags.epochs_per_eval),
         hooks=[logging_hook])
    # Evaluate the model 
    eval_results = classifier.evaluate(input_fn=lambda: input_function(
        training_phase=False, flags.data_dir, flags.batch_size))

Вот как я пытался загрузить и получить прогнозы от модели.

Как правильно восстановить сохраненную модель и сделать на ней вывод. Я хочу передавать изображения напрямую, не используя tf.data.Dataset.

Обновить

  1. Значение ckpt после запуска ckpt = tf.train.get_checkpoint_state(r'./model') равно

    model_checkpoint_path: "./model\model.ckpt-5980" all_model_checkpoint_paths: "./model\model.ckpt-5060" all_model_checkpoint_paths: "./model\model.ckpt-5061" all_model_checkpoint_paths: "./model\model.ckpt- 5520" all_model_checkpoint_paths: "./model\model.ckpt-5521" all_model_checkpoint_paths: "./model\model.ckpt-5980"

  2. Вывод такой же, когда я пытаюсь `saver.restore(sess, tf.train.latest_checkpoint(r'.\resnet\model'))

  3. Передача полного пути к saver.restore дает тот же результат Во всех случаях была восстановлена ​​одна и та же модель, model.ckpt-5980


person Effective_cellist    schedule 08.02.2018    source источник
comment
О первой попытке: каково значение ckpt после ckpt = tf.train.get_checkpoint_state(r'./model')? Что произойдет, если вместо этого вы восстановите через saver.restore(sess, tf.train.latest_checkpoint(r'.\resnet\model'))? А что если вместо restore передать строку с полным путем к контрольной точке?   -  person GPhilo    schedule 09.02.2018
comment
@GPhilo, я обновил вопрос   -  person Effective_cellist    schedule 09.02.2018
comment
Спасибо. Поскольку Tensorflow не выдает никаких ошибок во время восстановления, а ваше обновление показывает, что загружаемый вами файл контрольной точки должен быть правильным, мое следующее предположение — это данные в самой контрольной точке. Я просматриваю ваш поток ввода для обучения и не вижу shuffle. Ваши данные где-то перемешиваются?   -  person GPhilo    schedule 09.02.2018
comment
Еще одна интересная вещь: у вашей контрольной точки очень низкий номер. 5980 — это значение global_step при сохранении контрольной точки, поэтому, если я что-то не упустил, ваша сеть увидела в общей сложности 32*5980 = 191360 семплов... этого вряд ли достаточно для обучения реснета. Вы уверены, что контрольная точка действительно содержит веса обученной сети?   -  person GPhilo    schedule 09.02.2018
comment
@GPhilo Да, данные перемешиваются во время обучения как if is_training: dataset = dataset.shuffle(buffer_size=_FILE_SHUFFLE_BUFFER). Внутри классификатора есть метод classifier.evaluate, который обычно принимает в качестве входных данных проверочный набор. Я попробовал набор тестов для этого метода после того, как модель была обучена и сохранена, т. Е. Я закомментировал classifier.train и указал каталог набора данных проверки на тестовый каталог. Я мог видеть, что восстанавливается та же модель, model.ckpt-5980, и я получил точность 84%.   -  person Effective_cellist    schedule 09.02.2018
comment
Извините, я не видел этого shuffle. Дело в том, что там вы только перетасовываете имена файлов, а не сами сэмплы в файлах. Если у вас нет одного сэмпла на файл tfrecord (что, как я предполагаю, не так), все сэмплы в каждом файле будут в одном и том же порядке в каждую эпоху.   -  person GPhilo    schedule 09.02.2018
comment
@GPhilo Извините, я пропустил строку кода. После разбора записей происходит еще одна перетасовка.   -  person Effective_cellist    schedule 09.02.2018
comment
Вот подробный пример с последней версией тензорного потока 1.7 stackoverflow.com/a/52222383/5904928   -  person Aaditya Ura    schedule 07.09.2018


Ответы (2)


Примечание. Этот ответ будет изменен, как только появится дополнительная информация. Я не уверен, что это самый подходящий способ сделать это, но это лучше, чем просто комментарии. Не стесняйтесь оставлять комментарий к ответу, если это неуместно.

О вашей второй попытке:

У меня нет большого опыта работы с методом import_meta_graph, но если sess.run(logits) работает без жалоб, я думаю, что метаграф содержит также ваш входной конвейер.

Быстрый тест, который я только что провел, подтверждает, что конвейер действительно восстанавливается при загрузке метаграфа. Это означает, что вы на самом деле ничего не передаете через feed_dict, потому что входные данные берутся из конвейера на основе Dataset, который использовался при взятии контрольной точки. Из моего исследования я не могу найти способ предоставить другую входную функцию для графика.

О первой попытке:

Ваш код выглядит правильно для меня, поэтому я подозреваю, что файл контрольной точки, который загружается, как-то не так. Я попросил некоторые разъяснения в комментарии, я обновлю эту часть, как только эта информация будет доступна.

person GPhilo    schedule 09.02.2018
comment
Как вы проверили, восстанавливается ли входной конвейер при загрузке метаграфа? - person Effective_cellist; 10.02.2018
comment
Я получаю операции в графе через tf.get_default_graph().get_operations(), а затем проверяю список. Первые элементы — это операции, связанные с набором данных. - person GPhilo; 10.02.2018

Если у вас есть модель pb или pb.txt, сделать вывод легко. Используя модуль предиктора, мы можем сделать вывод. Ознакомьтесь с здесь для получения дополнительной информации. Для данных изображения это будет что-то похожее на приведенный ниже пример. Надеюсь это поможет !!

Пример кода:

import numpy as np
import matplotlib.pyplot as plt

def extract_data(index=0, filepath='data/cifar-10-batches-bin/data_batch_5.bin'):
    bytestream = open(filepath, mode='rb')
    label_bytes_length = 1
    image_bytes_length = (32 ** 2) * 3
    record_bytes_length = label_bytes_length + image_bytes_length
    bytestream.seek(record_bytes_length * index, 0)
    label_bytes = bytestream.read(label_bytes_length)
    image_bytes = bytestream.read(image_bytes_length)
    label = np.frombuffer(label_bytes, dtype=np.uint8)  
    image = np.frombuffer(image_bytes, dtype=np.uint8)
    image = np.reshape(image, [3, 32, 32])
    image = np.transpose(image, [1, 2, 0])
    image = image.astype(np.float32)
   result = {
     'image': image,
     'label': label,
   }
   bytestream.close()
   return result


    predictor_fn = tf.contrib.predictor.from_saved_model(
  export_dir = saved_model_dir, signature_def_key='predictions')
    N = 1000
    labels = []
    images = []
    for i in range(N):
       result = extract_data(i)
       images.append(result['image'])
       labels.append(result['label'][0])
    output = predictor_fn(
      {
        'images': images,
      }
    )
person Kishore Karunakaran    schedule 10.02.2018
comment
У меня нет файла .pb или .pbtxt. Как я уже упоминал в вопросе, у меня есть .meta. .index и .data файлы, а также контрольную точку. Чтобы использовать функцию predictor, мне нужно экспортировать модель как estimator.export_savedmodel(my_export_dir, serving_input_fn). Это serving_input_fn я не могу понять - person Effective_cellist; 10.02.2018
comment
Вот пример, как бы я поступил. Дайте мне знать, если это работает для вас. gist.github.com/kishorenayar/b9991b673b06b449703c07e3626982e5 - person Kishore Karunakaran; 11.02.2018
comment
Спасибо, Кишор. Я обновил свой вопрос. Пожалуйста, ознакомьтесь с разделом Третья попытка. - person Effective_cellist; 11.02.2018
comment
Я открыл еще один вопрос, связанный с этим - person Effective_cellist; 11.02.2018
comment
@dpk, вы используете tf-record в качестве входного набора данных для модели оценки? - person Kishore Karunakaran; 12.02.2018
comment
Набор данных хранится в виде файла tfrecord. Входной конвейер построен с помощью tf.data.Dataset - person Effective_cellist; 12.02.2018
comment
Найдите его здесь - person Effective_cellist; 12.02.2018