如何处理用于 Tensorflow Serving 批量转换的 .csv 输入?

How to handle a .csv input for use in Tensorflow Serving batch transform?

信息: 我正在从 S3 存储桶加载现有的经过训练的 model.tar.gz,并希望使用包含输入数据的 .csv 执行批量转换。 data.csv 的结构使得将其读入 pandas DataFrame 可以为我提供完整的预测输入行。

笔记:

其中 1-5 是特征,文件 data.csv 看起来像:

+------+-------------------------+---------+----------+---------+----------+----------+
| UNIT | TS                      | 1       | 2        | 3       | 4        | 5        |
+------+-------------------------+---------+----------+---------+----------+----------+
| 110  | 2018-01-01 00:01:00.000 | 1.81766 | 0.178043 | 1.33607 | 25.42162 | 12.85445 |
+------+-------------------------+---------+----------+---------+----------+----------+
| 110  | 2018-01-01 00:02:00.000 | 1.81673 | 0.178168 | 1.30159 | 25.48204 | 12.87305 |
+------+-------------------------+---------+----------+---------+----------+----------+
| 110  | 2018-01-01 00:03:00.000 | 1.8155  | 0.176242 | 1.38399 | 25.35309 | 12.47222 |
+------+-------------------------+---------+----------+---------+----------+----------+
| 110  | 2018-01-01 00:04:00.000 | 1.81530 | 0.176398 | 1.39781 | 25.18216 | 12.16837 |
+------+-------------------------+---------+----------+---------+----------+----------+
| 110  | 2018-01-01 00:05:00.000 | 1.81505 | 0.151682 | 1.38451 | 25.22351 | 12.41623 |
+------+-------------------------+---------+----------+---------+----------+----------+

inference.py 目前看起来像:

def input_handler(data, context):
    import pandas as pd
    if context.request_content_type == 'text/csv':
        payload = pd.read_csv(data)
        instance = [{"dataset": payload}]
        return json.dumps({"instances": instance})
    else:
        _return_error(416, 'Unsupported content type "{}"'.format(context.request_content_type or 'Unknown'))

问题:

当以下代码在我的 jupyter Notebook 中运行时:

sagemaker_model = Model(model_data = '[path in s3]/savedmodel/model.tar.gz'),  
                        sagemaker_session=sagemaker_session,
                        role = role,
                        framework_version='2.0',
                        entry_point = os.path.join('training', 'inference.py')
                        )

tf_serving_transformer = sagemaker_model.transformer(instance_count=1,
                                                     instance_type='ml.p2.xlarge',
                                                     max_payload=1,
                                                     output_path=BATCH_TRANSFORM_OUTPUT_DIR,
                                                     strategy='SingleRecord')


tf_serving_transformer.transform(data=BATCH_TRANSFORM_INPUT, data_type='S3Prefix', content_type='text/csv')
tf_serving_transformer.wait()

模型似乎已加载,但我最终遇到以下错误: 2020-08-04T09:54:27.415:[sagemaker logs]: MaxConcurrentTransforms=1, MaxPayloadInMB=1, BatchStrategy=SINGLE_RECORD 2020-08-04T09:54:27.503:[sagemaker logs]: [path in s3]/data.csv: ClientError: 400 2020-08-04T09:54:27.503:[sagemaker logs]: [path in s3]/data.csv: 2020-08-04T09:54:27.503:[sagemaker logs]: [path in s3]/data.csv: Message: 2020-08-04T09:54:27.503:[sagemaker logs]: [path in s3]/data.csv: { "error": "Failed to process element: 0 of 'instances' list. Error: Invalid argument: JSON Value: \"\" Type: String is not of expected type: float" }

更清楚错误:

客户端错误:400 消息:{“错误”:“无法处理元素:'instances' 列表的 0。错误:无效参数:JSON 值:“”类型:字符串不是预期类型:float”}

如果我对这个错误的理解正确,那么我的数据结构有问题,因此 sagemaker 无法将输入数据传递给 TFS 模型。我想我的 inference.py 中缺少一些“输入处理”。也许 csv 数据必须以某种方式转换为兼容的 JSON,以便 TFS 使用它?在 input_handler() 中究竟需要做什么?

感谢所有帮助,对于这个令人困惑的案例,我深表歉意。如果需要任何其他信息,请询问,我很乐意提供我所能提供的信息。

解决方案: 通过使用参数 header=False、index=False 将数据帧保存为 .csv 解决了这个问题。这使得保存的 csv 不包含数据帧索引标签。 TFS 接受了一个只有浮点值(没有标签)的干净的 .csv。我假设错误消息 Invalid argument: JSON Value: "" Type: String is not of expected type: float 指的是 csv 中的第一个单元格,如果 csv用标签导出只是一个空单元格。当它得到一个空字符串而不是浮点值时,它感到困惑。