在经过训练的本机Keras模型上提供输入的预处理功能

时间:2019-06-25 12:39:06

标签: python tensorflow-serving tensorflow-estimator

我的最终目标是使用张量板上的假设工具。为此,我需要在TensorflowServing上提供我的Keras模型,并在TFRecordFile中提供数据。因此必须将数据转换为tf.Examples。 该工具应该能够抓住网络对数据进行推理。 但是,网络无法处理tf.Examples作为输入。因此,服务的模型需要具有预处理功能。

根据张量流文档,一种方法是创建张量流估计器,并使用“ serving_input_receiver_fn”预处理数据。 除了无法将已经训练好的本机Keras模型制作为Estimator的情况之外,这将是完美的。似乎唯一的方法是从tf.keras模型(而不是像我这样的本地keras模型)中创建模型,并直接通过估算器对其进行训练。

另一种方法是使用tf.saved_model.simple_save函数,然后使用TensorflowServing,但我没有找到预处理tf的方法。示例为网络提供了正确的输入。

由于这不起作用,我不知道如何解决此问题。

编辑:我尝试将本机keras转换为tf.keras模型。我的模型很大,所以我建立了这个函数:

def create_tf_keras_model_from_native_keras(native_model):
    list_layers = []
    for i, layer in enumerate(native_model.layers):
        type_layer = str(layer).split('.')[2]
        second_type_layer = str(layer).split('.')[3].split(' ')[0]
        if type_layer == 'input_layer':
            new_layer = tf.keras.layers.InputLayer(**layer.get_config())
        elif type_layer == 'convolutional':
            new_layer = tf.keras.layers.Conv2D(**layer.get_config())
        elif type_layer == 'normalization':
            new_layer = tf.keras.layers.BatchNormalization(**layer.get_config())
        elif type_layer == 'core':
            if second_type_layer == 'Activation':
                new_layer = tf.keras.layers.Activation(**layer.get_config())
            elif second_type_layer == 'Dense':
                new_layer = tf.keras.layers.Dense(**layer.get_config())
            elif second_type_layer == 'Dropout':
                new_layer = tf.keras.layers.Dropout(**layer.get_config())
            elif second_type_layer == 'Lambda':
                config_lambda = layer.get_config()
                print(config_lambda)
                del config_lambda['function_type']
                del config_lambda['output_shape_type']
                new_layer = tf.keras.layers.Lambda(**config_lambda)
        elif type_layer == 'pooling':
            if second_type_layer == 'MaxPooling2D':
                new_layer = tf.keras.layers.MaxPooling2D(**layer.get_config())
            elif second_type_layer == 'AveragePooling2D':
                new_layer = tf.keras.layers.AveragePooling2D(**layer.get_config())
            elif second_type_layer == 'GlobalMaxPooling2D':
                new_layer = tf.keras.layers.GlobalMaxPooling2D(**layer.get_config())
        if new_layer == 'merge':
            new_layer = tf.keras.layers.Concatenate(**layer.get_config())
        list_layers.append(new_layer)
    model = tf.keras.Sequential(list_layers)
    return model

但是,由于Lambda层,这无法正常工作。在config层中,该函数现在以以下形式编写:

'function': ('4wIAAAAAAAAAAgAAAAMAAABTAAAAcxQAAAB8AGQBGQB8AGQC8ARQAFwBTACkDTukAAAAA6QEA\nAACpACkC2gZpbaBXNjYWxlcgMAAAByAwAAAPp/L2dwZnMvaGFpZmEtcDYvMDMvbXNpZXZl\nX2RldjMvdXNyL3BhdWxkYS9naXRfcmVwb0hJLUltYWdlQW5hbHl0aWNzL3Jlc291cmNlcy9y\ndW5fMTE3NC9jdXN0b21fcHJldHJhaW5lZF9JbmNlcHRpb25SZXNOZXRWMi5wedoIPGxhbWJkYT6d\nAAAA8wAAAAA=\n', None, None)

因此,我放弃了这种方法,希望可以通过其他方法来预处理我的服务模型的输入。

1 个答案:

答案 0 :(得分:0)

在我看来,如果您想使用Tensorflow Serving,使用Native Keras很难做到这一点。

如果您想为TrainingServing准备数据,则可以使用Tensorflow Transform执行相应的转换。

但是,如果您只想为Serving准备数据,最好的方法是您提到的方法,“ 看来,这是从tf.keras模型创建数据的唯一方法(而不是像我这样的本地keras模型),并直接通过估算器进行训练。

您正确地说过,无法使用tf.saved_model.simple_save函数。

下面显示了用于创建Keras模型并将其转换为Estimator的示例代码:

import tensorflow as tf
from tensorflow.python import keras
from tensorflow.python.keras import layers
from tensorflow.python.keras import models

def get_keras_model():
    inputs = layers.Input(shape=(INPUT_SHAPE,), name=INPUT_FEATURE)
    dense256 = layers.Dense(256, activation='relu')(inputs)
    dense32 = layers.Dense(32, activation='relu')(dense256)
    outputs = layers.Dense(NUM_CLASSES, activation='softmax')(dense32)
    model = models.Model(inputs, outputs)
    return model

然后使用以下代码将Keras模型转换为Estimator:

classifier = tf.keras.estimator.model_to_estimator(keras_model=model, model_dir=FLAGS.model_dir)

有关更多信息,请参阅链接, https://github.com/yu-iskw/tensorflow-serving-example/blob/master/python/train/mnist_keras_estimator.py