如何处理用于 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 可以为我提供完整的预测输入行。
笔记:
- 这是使用 Python SDK
在 Amazon Sagemaker 上完成的
- BATCH_TRANSFORM_INPUT 是 data.csv.
的路径
- 我可以加载 model.tar.gz 中的内容并使用它们在我的本地机器上使用 tensorflow 进行推理,并且日志显示
2020-08-04 13:35:01.123557: I tensorflow_serving/core/loader_harness.cc:87] Successfully loaded servable version {name: model version: 1}
所以模型似乎已经训练并保存正确。
- data.csv 与训练数据的格式完全相同,这意味着每个“预测”一行,其中该行中的所有列代表不同的特征。
- 将参数策略更改为 'MultiRecord' 给出相同的错误
- [s3 中的路径] 是真实路径的替代品,因为我不想透露任何存储桶信息。
- TensorFlow 模型服务器:2.0.0+dev.sha.ab786af
- TensorFlow 库:2.0.2
其中 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用标签导出只是一个空单元格。当它得到一个空字符串而不是浮点值时,它感到困惑。
信息: 我正在从 S3 存储桶加载现有的经过训练的 model.tar.gz,并希望使用包含输入数据的 .csv 执行批量转换。 data.csv 的结构使得将其读入 pandas DataFrame 可以为我提供完整的预测输入行。
笔记:- 这是使用 Python SDK 在 Amazon Sagemaker 上完成的
- BATCH_TRANSFORM_INPUT 是 data.csv. 的路径
- 我可以加载 model.tar.gz 中的内容并使用它们在我的本地机器上使用 tensorflow 进行推理,并且日志显示
2020-08-04 13:35:01.123557: I tensorflow_serving/core/loader_harness.cc:87] Successfully loaded servable version {name: model version: 1}
所以模型似乎已经训练并保存正确。 - data.csv 与训练数据的格式完全相同,这意味着每个“预测”一行,其中该行中的所有列代表不同的特征。
- 将参数策略更改为 'MultiRecord' 给出相同的错误
- [s3 中的路径] 是真实路径的替代品,因为我不想透露任何存储桶信息。
- TensorFlow 模型服务器:2.0.0+dev.sha.ab786af
- TensorFlow 库:2.0.2
其中 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用标签导出只是一个空单元格。当它得到一个空字符串而不是浮点值时,它感到困惑。