Неизвестно: KeyError: 'pyfunc_0'

Я экспортирую saveModel, который принимает заполнитель строки в качестве входного тензора. Я ввел граф, чтобы предварительно обработать этот тензор строки, чтобы он мог быть передан в модель. Тем не менее, я использую py_func выполнить мои строковые операции над тензором.

Вот input_text является входным тензором в подписи сохраненной модели. Я создал другой заполнитель по умолчанию input_ints который инициализируется с результатом выполнения py_func на input_text, У меня изначально был input_text как операция (input_ints =tf.py_func(preprocess, [input_text], tf.int64)) но потом tf.nn.dynamic_rnn не принимал тензор с неопределенной формой.

    # Create the graph object
with tf.name_scope('inputs'):
    input_text = tf.placeholder(tf.string, name="input_text")
    input_ints = tf.placeholder_with_default(
        tf.py_func(preprocess, [input_text], tf.int64), shape=[None, None])

def lstm_cell():
    # Your basic LSTM cell
    lstm = tf.contrib.rnn.BasicLSTMCell(lstm_size, reuse=tf.get_variable_scope().reuse)
    # Add dropout to the cell
    return tf.contrib.rnn.DropoutWrapper(lstm, output_keep_prob=keep_prob)


# def create_rnn():
with tf.name_scope("Embeddings"):
    embedding = tf.Variable(tf.random_uniform((vocab_size, embed_size), -1, 1))
    embed = tf.nn.embedding_lookup(embedding, input_ints)
with tf.name_scope("RNN_layers"):
    cell = tf.contrib.rnn.MultiRNNCell([lstm_cell() for _ in range(lstm_layers)])
initial_state = cell.zero_state(batch_size, tf.float32)
with tf.name_scope("RNN_forward"):
    outputs, final_state = tf.nn.dynamic_rnn(cell, embed, initial_state=initial_state)
with tf.name_scope('predictions'):
    predictions = tf.contrib.layers.fully_connected(outputs[:, -1], 1, activation_fn=tf.sigmoid)

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

2017-11-23 17:29:14.600184: W tensorflow/core/framework/op_kernel.cc:1192] Unknown: KeyError: 'pyfunc_0'
Traceback (most recent call last):
  File "/Users/sakibarrahman/anaconda/lib/python3.6/site-packages/tensorflow/python/client/session.py", line 1327, in _do_call
    return fn(*args)
  File "/Users/sakibarrahman/anaconda/lib/python3.6/site-packages/tensorflow/python/client/session.py", line 1306, in _run_fn
    status, run_metadata)
  File "/Users/sakibarrahman/anaconda/lib/python3.6/contextlib.py", line 89, in __exit__
    next(self.gen)
  File "/Users/sakibarrahman/anaconda/lib/python3.6/site-packages/tensorflow/python/framework/errors_impl.py", line 466, in raise_exception_on_not_ok_status
    pywrap_tensorflow.TF_GetCode(status))
tensorflow.python.framework.errors_impl.UnknownError: KeyError: 'pyfunc_0'
     [[Node: inputs/PyFunc = PyFunc[Tin=[DT_STRING], Tout=[DT_INT64], token="pyfunc_0", _device="/job:localhost/replica:0/task:0/cpu:0"](_arg_inputs/input_text_0_0)]]

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "neural_load_model.py", line 85, in <module>
    result = sess.run(output_tensor, {input_tensor: "Charter Communications, Inc. (CHTR) Stock Rating Reaffirmed by Goldman Sachs Group, Inc. (The)"})
  File "/Users/sakibarrahman/anaconda/lib/python3.6/site-packages/tensorflow/python/client/session.py", line 895, in run
    run_metadata_ptr)
  File "/Users/sakibarrahman/anaconda/lib/python3.6/site-packages/tensorflow/python/client/session.py", line 1124, in _run
    feed_dict_tensor, options, run_metadata)
  File "/Users/sakibarrahman/anaconda/lib/python3.6/site-packages/tensorflow/python/client/session.py", line 1321, in _do_run
    options, run_metadata)
  File "/Users/sakibarrahman/anaconda/lib/python3.6/site-packages/tensorflow/python/client/session.py", line 1340, in _do_call
    raise type(e)(node_def, op, message)
tensorflow.python.framework.errors_impl.UnknownError: KeyError: 'pyfunc_0'
     [[Node: inputs/PyFunc = PyFunc[Tin=[DT_STRING], Tout=[DT_INT64], token="pyfunc_0", _device="/job:localhost/replica:0/task:0/cpu:0"](_arg_inputs/input_text_0_0)]]

Caused by op 'inputs/PyFunc', defined at:
  File "neural_load_model.py", line 74, in <module>
    model = tf.saved_model.loader.load(sess, [tf.saved_model.tag_constants.SERVING], import_path)
  File "/Users/sakibarrahman/anaconda/lib/python3.6/site-packages/tensorflow/python/saved_model/loader_impl.py", line 216, in load
    saver = tf_saver.import_meta_graph(meta_graph_def_to_load, **saver_kwargs)
  File "/Users/sakibarrahman/anaconda/lib/python3.6/site-packages/tensorflow/python/training/saver.py", line 1698, in import_meta_graph
    **kwargs)
  File "/Users/sakibarrahman/anaconda/lib/python3.6/site-packages/tensorflow/python/framework/meta_graph.py", line 656, in import_scoped_meta_graph
    producer_op_list=producer_op_list)
  File "/Users/sakibarrahman/anaconda/lib/python3.6/site-packages/tensorflow/python/framework/importer.py", line 313, in import_graph_def
    op_def=op_def)
  File "/Users/sakibarrahman/anaconda/lib/python3.6/site-packages/tensorflow/python/framework/ops.py", line 2630, in create_op
    original_op=self._default_original_op, op_def=op_def)
  File "/Users/sakibarrahman/anaconda/lib/python3.6/site-packages/tensorflow/python/framework/ops.py", line 1204, in __init__
    self._traceback = self._graph._extract_stack()  # pylint: disable=protected-access

UnknownError (see above for traceback): KeyError: 'pyfunc_0'
     [[Node: inputs/PyFunc = PyFunc[Tin=[DT_STRING], Tout=[DT_INT64], token="pyfunc_0", _device="/job:localhost/replica:0/task:0/cpu:0"](_arg_inputs/input_text_0_0)]]

Я посмотрел на этот вопрос, размещенный на Github, но я не уверен, как это реализовать. Кроме того, я просто загружаю модель и передаю строку для ввода, а не использую 'freeze_graph'.

Мой код для сохранения модели:

saver = tf.train.Saver()

#Define new functions
def preprocess(text):
.
.
.
tf.reset_default_graph()
.
.
.
#Define new placeholder that was not in the original model graph
#Define new placeholder with default value initialized with py_func that was not in the original model graph
with tf.name_scope('inputs'):
    input_text = tf.placeholder(tf.string, name="input_text")
    input_ints = tf.placeholder_with_default(
        tf.py_func(preprocess, [input_text], tf.int64), shape=[None, None])
.
.
.
#Define placeholders and ops that I need and were in the original graph



saver = tf.train.Saver()
#Serving the model
with tf.Session() as sess:


#Restore from old checkpoint
saver.restore(sess, import_path)

print ('Exporting trained model to %s'%(export_path))

builder = saved_model_builder.SavedModelBuilder(export_path)

original_assets_directory = export_path + '/assets'
original_assets_filename = "vocabulary.pickle"
original_assets_filepath = write_vocab(original_assets_directory,
                                         original_assets_filename)

# Set up the assets collection.
assets_filepath = tf.constant(original_assets_filepath)
tf.add_to_collection(tf.GraphKeys.ASSET_FILEPATHS, assets_filepath)
filename_tensor = tf.Variable(
    original_assets_filename,
    name="vocab_tensor",
    trainable=False,
    collections=[])
assign_filename_op = filename_tensor.assign(original_assets_filename)


# Build the signature_def_map.
classification_inputs = utils.build_tensor_info(input_text)
classification_outputs_classes = utils.build_tensor_info(predictions)
classification_signature = signature_def_utils.build_signature_def(
    inputs={signature_constants.CLASSIFY_INPUTS: classification_inputs},
    outputs={
      signature_constants.CLASSIFY_OUTPUT_CLASSES:
          classification_outputs_classes,
    },
  method_name=signature_constants.CLASSIFY_METHOD_NAME)

legacy_init_op = tf.group(
    tf.tables_initializer(), name='legacy_init_op')
#add the sigs to the servable
builder.add_meta_graph_and_variables(
    sess, [tag_constants.SERVING],
    signature_def_map={
        signature_constants.DEFAULT_SERVING_SIGNATURE_DEF_KEY:
            classification_signature
    },
    assets_collection=tf.get_collection(tf.GraphKeys.ASSET_FILEPATHS),
    legacy_init_op=tf.group(assign_filename_op))
print ("added meta graph and variables")

builder.save()
print("model saved")

Мой код для загрузки модели. Не определение функции или заполнителей приводит к ошибке "pyfunc_0":

#Define preprocess function
def preprocess(text_bin):

#Define new placeholders
with tf.name_scope('inputs'):
    input_text = tf.placeholder(tf.string, name="input_text")
    input_ints = tf.placeholder_with_default(
        tf.py_func(preprocess, [input_text], tf.int64), shape=[None, None])

with tf.Session(graph=tf.Graph()) as sess:
    # restore save model
    model = tf.saved_model.loader.load(sess, [tf.saved_model.tag_constants.SERVING], import_path)
    print("model restored")
    loaded_graph = tf.get_default_graph()

    # get necessary tensors by name
    input_tensor_name = model.signature_def[signature_constants.DEFAULT_SERVING_SIGNATURE_DEF_KEY].inputs[signature_constants.CLASSIFY_INPUTS].name
    input_tensor = loaded_graph.get_tensor_by_name(input_tensor_name)
    output_tensor_name = model.signature_def[signature_constants.DEFAULT_SERVING_SIGNATURE_DEF_KEY].outputs[signature_constants.CLASSIFY_OUTPUT_CLASSES].name
    output_tensor = loaded_graph.get_tensor_by_name(output_tensor_name)

    result = sess.run(output_tensor, {input_tensor: "Some String"})
    print (result)

Обновить:

Определение функций и заполнителей при загрузке saveModel, кажется, работает. Тем не менее, я не знаю, почему они не добавляются в график до использования построителя для сохранения модели

2 ответа

Решение

Используемая функция предварительной обработки на самом деле не была частью графика, поэтому py_func() не знала, какую функцию использовать при загрузке saveModel. В настоящее время нет простого способа выполнить предварительную обработку в потоке Tensorflow Serve. Это должно быть сделано на стороне клиента перед использованием модели, или может потребоваться создание пользовательской операции, чтобы она могла быть частью модели. Другой альтернативой может быть создание настраиваемого обслуживаемого объекта.

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

Другие вопросы по тегам