Обслуживающая модель TF с вводом переменной длины - PullRequest
0 голосов
/ 23 января 2020

Я пытаюсь обслуживать мою модель TF с помощью TF Serving. Вот входные данные модели, которые у меня есть:

raw_feature_spec = {
     'x': tf.io.VarLenFeature(tf.string),
     'y': tf.io.VarLenFeature(tf.string),
     'z': tf.io.FixedLenFeature([], tf.string)
}

Затем входной объект преобразуется с помощью преобразования TF с Beam в объект с формами x: (None, 20, 100), y: (None, 20, 5), z: (Нет, 3), которые применимы для исходной модели без включенного transform_funс (Transform Graph). Затем я экспортирую свою модель с помощью:

 import tensorflow as tf
 import tensorflow_transform as tft

 tf_transform_output = tft.TFTransformOutput('saved_transform_graph_folder')     
 estimator = tf.keras.estimator.model_to_estimator(keras_model_path='model_folder')
 estimator.export_saved_model('OUTPUT_MODEL_NAME',  make_serving_input_fn(tf_transform_output))

def make_serving_input_fn(tf_transform_output):
 raw_feature_spec = {
       'x': tf.io.VarLenFeature(tf.string),
       'y': tf.io.VarLenFeature(tf.string),
       'z': tf.io.FixedLenFeature([], tf.string)
   }

def serving_input_fn():
    raw_input_fn = tf.estimator.export.build_parsing_serving_input_receiver_fn(raw_feature_spec)
    raw_reatures = raw_input_fn().features
    features = {
        'x': tf.sparse.to_dense(raw_reatures["x"]),
        'y':  tf.sparse.to_dense(raw_reatures["y"]),
        'z': raw_reatures["z"]
    }

    # Apply the transform function that was used to generate the materialized data
    transformed_features = tf_transform_output.transform_raw_features(raw_reatures)
    return tf.estimator.export.ServingInputReceiver(transformed_features, features)

return serving_input_fn

Где transform_fun c - это забавный c, который преобразует входные тензоры в необходимые и включается в объект tf_transform_output. Поэтому, когда я обслуживаю экспортированную модель этим кодом, используя образ TFS из Docker Hub, отправляя HTTP-запрос GET в / model / metadata, я получаю:

{
"model_spec": {
    "name": "newModel",
    "signature_name": "",
    "version": "1579786077"
},
"metadata": {
    "signature_def": {
        "signature_def": {
            "serving_default": {
                "inputs": {
                    "x": {
                        "dtype": "DT_STRING",
                        "tensor_shape": {
                            "dim": [
                                {
                                    "size": "-1",
                                    "name": ""
                                },
                                {
                                    "size": "-1",
                                    "name": ""
                                }
                            ],
                            "unknown_rank": false
                        },
                        "name": "SparseToDense_1:0"
                    },
                    "y": {
                        "dtype": "DT_STRING",
                        "tensor_shape": {
                            "dim": [
                                {
                                    "size": "-1",
                                    "name": ""
                                },
                                {
                                    "size": "-1",
                                    "name": ""
                                }
                            ],
                            "unknown_rank": false
                        },
                        "name": "SparseToDense:0"
                    },
                    "z": {
                        "dtype": "DT_STRING",
                        "tensor_shape": {
                            "dim": [
                                {
                                    "size": "-1",
                                    "name": ""
                                }
                            ],
                            "unknown_rank": false
                        },
                        "name": "ParseExample/ParseExample:6"
                    }
                },
                "outputs": {
                    "main_output": {
                        "dtype": "DT_FLOAT",
                        "tensor_shape": {
                            "dim": [
                                {
                                    "size": "-1",
                                    "name": ""
                                },
                                {
                                    "size": "20",
                                    "name": ""
                                }
                            ],
                            "unknown_rank": false
                        },
                        "name": "main_output/Softmax:0"
                    }
                },
                "method_name": "tensorflow/serving/predict"
            }
        }
    }
}

Таким образом, входные данные верны (тем не менее я использовал tf.sparse.to_dense для оболочки VarLenFeature при экспорте). Но когда я отправляю HTTP-запрос POST в / model: прогноз с телом:

{ 
   "instances": 
   [
     {
        "x": ["text","text","text","text","text","text"],
        "y": ["test","test","test","test","test","test"],
        "z": "str"
     }
  ]
}

Я получаю сообщение об ошибке

{
    "error": "You must feed a value for placeholder tensor \'input_example_tensor\' with dtype string and shape [?]\n\t [[{{node input_example_tensor}}]]"
}

Кто-нибудь имеет представление о том, что я делаю неправильно или Как правильно создать переменную? Мне нужны формы Tensors, как у меня сейчас в метаданных, поэтому мне не нужна возможность доступа к API через сериализованный прото-пример, только через необработанные тензоры. Версия TF: 2.0, TF Serving и TF Transform - последние версии.

PS Также я попытался экспортировать модель, используя tf.keras.backend.placeholder с помощью build_raw_serving_input_receiver_fn вызова, чтобы не было приведения от разреженного к плотному тензору в serve_input_fn, но результаты те же.

...