Добавление метаграфа {serve} к существующей модели Tensorflow - PullRequest
1 голос
/ 06 июня 2019

Ситуация:

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

Модели былисохранено с использованием функции

def save_graph_to_file(sess, graph, graph_file_name):
    """Saves an graph to file, creating a valid quantized one if necessary."""
    output_graph_def = graph_util.convert_variables_to_constants(sess, graph.as_graph_def(), [final_tensor_name])
    with gfile.FastGFile(graph_file_name, 'wb') as f:
        f.write(output_graph_def.SerializeToString())

Теперь при попытке развертывания в обслуживающей среде (Sagemaker, используя правильную структуру каталогов и соглашение об именах файлов), система возвращает

2019-06-04 22:38:53.794056: I external/org_tensorflow/tensorflow/cc/saved_model/reader.cc:54] Reading meta graph with tags { serve }
2019-06-04 22:38:53.798096: I external/org_tensorflow/tensorflow/cc/saved_model/loader.cc:259] SavedModel load for tags { serve }; Status: fail. Took 83297 microseconds.
2019-06-04 22:38:53.798132: E tensorflow_serving/util/retrier.cc:37] Loading servable: {name: model version: 1} failed: Not found: Could not find meta graph def matching supplied tags: { serve }. To inspect available tag-sets in the SavedModel, please use the SavedModel CLI: `saved_model_cli`

Все Iесть файлы *.pb и их текстовые файлы меток.Они прекрасно работают на нескольких компьютерах в локальной среде.

def load_graph(model_file):
    """
    Code from v1.6.0 of Tensorflow's label_image.py example
    """
    graph = tf.Graph()
    graph_def = tf.GraphDef()
    with open(model_file, "rb") as f:
        graph_def.ParseFromString(f.read())
    with graph.as_default():
        tf.import_graph_def(graph_def)
    return graph

inputLayer = "Mul"
outputLayer = "final_result"
inputName = "import/" + inputLayer
outputName = "import/" + outputLayer
graph = load_graph(modelPath)
inputOperation = graph.get_operation_by_name(inputName)
outputOperation = graph.get_operation_by_name(outputName)
with tf.Session(graph= graph) as sess:
    # ... make a tensor t
    results = sess.run(outputOperation.outputs[0], {
        inputOperation.outputs[0]: t
    })
    # lovely functional results here

Все, что я хочу сделать, это взять эти существующие файлы, добавить необходимый тег «serve» и заново сохранить их, но все, что я вижу, похоже, связано с этим с нуля.

Я пытался использовать конструктор для добавления графика к модели, например:

# Load the graph
graph = load_graph(modelPath)
import shutil
if os.path.exists(exportDir):
    shutil.rmtree(exportDir)
# Add the serving metagraph tag
builder = tf.saved_model.builder.SavedModelBuilder(exportDir)
from tensorflow.saved_model import tag_constants
with tf.Session(graph= graph) as sess:
    builder.add_meta_graph_and_variables(sess, [tag_constants.SERVING, tag_constants.GPU], strip_default_attrs= True)
builder.save()
print("Built a SavedModel")

, но получил ту же ошибку.

1 Ответ

0 голосов
/ 14 июня 2019

Наконец-то решил. Он содержит некоторый специфический код S3 и вызовы экземпляра S3 (команды !), но вы должны в значительной степени урезать его для выполнения этого.

#!python3
"""
Assumes we've defined:

- A directory for our working files to live in, CONTAINER_DIR
- an arbitrary integer VERSION_INT
- We have established local and S3 paths for our model and their labels as variables
"""

# Create a versioned path for the models to live in
# See https://stackoverflow.com/a/54014480/1877527
modelVersionPath = os.path.join(CONTAINER_DIR, VERSION_INT)
if os.path.exists(modelVersionPath):
    shutil.rmtree(modelVersionPath)
os.mkdir(modelVersionPath)
import tensorflow as tf
def load_graph(model_file, returnElements= None):
    """
    Code from v1.6.0 of Tensorflow's label_image.py example
    """
    graph = tf.Graph()
    graph_def = tf.GraphDef()
    with open(model_file, "rb") as f:
        graph_def.ParseFromString(f.read())
    returns = None
    with graph.as_default():
        returns = tf.import_graph_def(graph_def, return_elements= returnElements)
    if returnElements is None:
        return graph
    return graph, returns
# Set up dirs
exportDir = modelVersionPath
# Clean up any existing one
import shutil
if os.path.exists(exportDir):
    shutil.rmtree(exportDir)
# Add the serving metagraph tag
# We need the inputLayerName; in Inception we're feeding the resized tensor
# corresponding to resized_input_tensor_name
# May be able to get away with auto-determining this if not using Inception,
# but for Inception this is the 11th layer
inputLayerName = "Mul:0"
# Load the graph
if inputLayerName is None:
    graph = load_graph(modelPath)
    inputTensor = None
else:
    graph, returns = load_graph(modelPath, returnElements= [inputLayerName])
    inputTensor = returns[0]
with tf.Session(graph= graph) as sess:
    # Read the layers
    try:
        from tensorflow.compat.v1.saved_model import simple_save
    except (ModuleNotFoundError, ImportError):
        from tensorflow.saved_model import simple_save
    with graph.as_default():
        layers = [n.name for n in graph.as_graph_def().node]
        outName = layers.pop() + ":0"
        if inputLayerName is None:
            inputLayerName = layers.pop(0) + ":0"
    print("Checking outlayer", outName)
    outLayer = tf.get_default_graph().get_tensor_by_name(outName)
    if inputTensor is None:
        print("Checking inlayer", inputLayerName)
        inputTensor = tf.get_default_graph().get_tensor_by_name(inputLayerName)
    inputs = {
        inputLayerName: inputTensor
    }
    outputs = {
        outName: outLayer
    }
    simple_save(sess, exportDir, inputs, outputs)
print("Built a SavedModel")
# Put the model label into the artifact dir
modelLabelDest = os.path.join(exportDir, "saved_model.txt")
!cp {modelLabel} {modelLabelDest}
# Prep for serving
modelName = f"livemodel_{dt.datetime.now().timestamp()}.tar.gz"
# Copy the version directory here to package
!cp -R {modelVersionPath} ./
# gziptar it
!tar -czvf {modelName} {VERSION_INT}
# Shove it back to S3 for serving
!aws s3 cp {modelName} {bucketPath}
shutil.rmtree(VERSION_INT) # Cleanup
shutil.rmtree(os.path.join(CONTAINER_DIR, VERSION_INT)) # Cleanup

Затем эту модель можно развернуть в качестве конечной точки Sagemaker (и любой другой обслуживающей среды Tensorflow)

...