чтение protobuf, созданного с помощью TF2 с использованием TF1 - PullRequest
0 голосов
/ 03 мая 2020

У меня есть модель, хранящаяся в формате hdf5, которую я экспортирую в файл protobuf (PB) с помощью save_model.save, например:

from tensorflow import keras
import tensorflow as tf
model = keras.models.load_model("model.hdf5")
tf.saved_model.save(model, './output_dir/')

это работает нормально, и в результате получается файл save_model.pb который я могу позже просмотреть с другим программным обеспечением без проблем.

Однако, когда я пытаюсь импортировать этот файл PB, используя TensorFlow1, мой код завершается ошибкой. Так как PB должен быть универсальным форматом, это меня смущает.

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

import tensorflow as tf
curr_graph = tf.Graph()
curr_sess = tf.InteractiveSession(graph=curr_graph)
f = tf.gfile.GFile('model.hdf5','rb')
graph_def = tf.GraphDef()
graph_def.ParseFromString(f.read())
f.close()

Это исключение, которое я получаю:

Трассировка (последний вызов был последним): файл "read_pb.py", строка 14, в graph_def.ParseFromString (f.read ()) google.protobuf.message.DecodeError: Ошибка при синтаксическом анализе сообщения

У меня есть другая модель, хранящаяся в виде файла PB, на котором код чтения работает нормально.

Что происходит?

***** РЕДАКТИРОВАТЬ 1 *****

При использовании приведенного ниже кода Андреа Анджели я столкнулся со следующей ошибкой:

Обнаружена ошибка: NodeDef упоминает attr 'exponential_avg_factor', который отсутствует в действии: T, batch_mean: U, batch_variance: U, reserve_space_1: U, Reserve_space_2: U, Reserve_space_3: U; attr = T: тип, допустимый = [DT_HALF, DT_BFLOAT16, DT_FLOAT]; атр = U: тип, разрешено = [DT_FLOAT]; атр = эпсилон: поплавок, по умолчанию = 0,0001; attr = data_format: string, default = "NHW C", позволено = ["NHW C", "NCHW"]; атр = is_training: BOOL, по умолчанию = истина>; NodeDef: {узел u-mobilenetv2 / bn_Conv1 / FusedBatchNormV3}. (Проверьте, соответствует ли ваш двоичный файл, интерпретирующий GraphDef, вашему двоичному файлу, генерирующему GraphDef.).

Есть ли обходной путь для этого?

1 Ответ

1 голос
/ 04 мая 2020

Вы пытаетесь прочитать файл hdf5, а не файл protobuf, который вы сохранили с помощью tf.saved_model.save(..). Также имейте в виду, что экспортированный протобуф TF2 не совпадает с замороженным графом TF 1, поскольку он содержит только граф вычислений.

Edit 1: Если вы хотите экспортировать замороженный граф в стиле TF 1 из модели TF 2 это можно сделать с помощью следующего фрагмента кода:

from tensorflow.python.framework import convert_to_constants

def export_to_frozen_pb(model: tf.keras.models.Model, path: str) -> None:
    """
    Creates a frozen graph from a keras model.

    Turns the weights of a model into constants and saves the resulting graph into a protobuf file.

    Args:
        model: tf.keras.Model to convert into a frozen graph
        path: Path to save the profobuf file
    """
    inference_func = tf.function(lambda input: model(input))

    concrete_func = inference_func.get_concrete_function(tf.TensorSpec(model.inputs[0].shape, model.inputs[0].dtype))
    output_func = convert_to_constants.convert_variables_to_constants_v2(concrete_func)

    graph_def = output_func.graph.as_graph_def()
    graph_def.node[-1].name = 'output'

    with open(os.path.join(path, 'saved_model.pb'), 'wb') as freezed_pb:
        freezed_pb.write(graph_def.SerializeToString())

В результате будет создан файл protobuf (сохраненный_модель.pb) в месте, указанном в параметре path. Входной узел вашего графика будет иметь имя «input: 0» (это достигается лямбда-выражением) и выходной узел «output: 0».

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...