如何在 Keras 模型中为新的仅推理端到端模型进行预处理
How to do preprocessing inside a Keras model for new inference-only end-to-end model
使用 Tensorflow 2.3,我已经使用 EfficientNet 训练了一个 tf.keras 模型,现在我想导出一个仅推理的端到端模型,该模型将包括预处理层(基本上解码图像编码作为 base64 字符串并可能处理规范化)。我定义训练模型和推理模型的代码:
imageSize = (224,224,3)
inputs = layers.Input(shape=imageSize)
eff_net_model = EfficientNetB0(input_tensor=inputs)
eff_net_model.compile(...)
eff_net_model.fit(...)
# training is finished now wrap the model with preprocessing for inference model
model = b64_image_model_wrapper(eff_net_model,imageSize)
我的包装函数如下:
def b64_image_model_wrapper(model,imageSize,method=tf.image.ResizeMethod.BILINEAR,
mean=0.0,std=1.0,input_name="b64_image"):
def preprocess_and_decode(img_str, new_shape=imageSize):
img = tf.io.decode_base64(img_str)
img = tf.image.decode_jpeg(img, channels=3)
img = tf.image.resize(img, new_shape, method=method)
return img
input64 = tf.keras.layers.Input(shape=(None,), dtype="string", name=input_name)
output_tensor = tf.keras.layers.Lambda(
lambda img: tf.map_fn(lambda im: preprocess_and_decode(im[0]), img, fn_output_signature=tf.float32,swap_memory=True))(input64)
x = (output_tensor - mean) / std
x = model(x)
new_model = tf.keras.Model(input64, x, name=model.name)
new_model.output_names = model.output_names
return new_model
稍后如果我想用这个新模型(将字符串编码图像作为输入的模型)进行预测,我会这样做:
model.predict(np.array(["hello"])) # just for testing purposes
我收到错误:
Exception has occurred: InvalidArgumentError
Expected image (JPEG, PNG, or GIF), got unknown format starting with '10_104570i7'
[[{{node EfficientNet/lambda/map/while/body/_1/EfficientNet/lambda/map/while/DecodeJpeg}}]]
同样,如果我保存这个新模型 (tf.saved_model.save(model)
) 并尝试将它与 Tensorflow Serving 一起使用,我会收到错误消息:
Error while reading resource variable block6c_bn/moving_mean from Container: localhost. This could mean that the variable was uninitialized. Not found: Container localhost does not exist. (Could not find resource: localhost/block6c_bn/moving_mean)\n\t [[{{node functional_1/EfficientNet/block6c_bn/FusedBatchNormV3/ReadVariableOp}}]]
不知道具体是什么意思,好像有些权重没有初始化?我是否以正确的方式包装模型?
调用 model.predict(np.array(["hello"]))
时出错的原因是:
- 输入格式不是base64字符串
- 您在
tf.io.decode_base64
之后的输入不是 .jpg
文件
以下代码向您展示了如何使用 .jpg
文件测试模型:
with open("./homersimpson.0.0.jpg", "rb") as imageFile:
base64_bytes = base64.urlsafe_b64encode(imageFile.read())
base64_strings = base64_bytes.decode('ascii')
img = tf.io.decode_base64(base64_strings)
prediction = model.predict(np.array([base64_strings]))
另外我用model.save('./test_save_model')
保存了整个模型,没有任何问题
使用 Tensorflow 2.3,我已经使用 EfficientNet 训练了一个 tf.keras 模型,现在我想导出一个仅推理的端到端模型,该模型将包括预处理层(基本上解码图像编码作为 base64 字符串并可能处理规范化)。我定义训练模型和推理模型的代码:
imageSize = (224,224,3)
inputs = layers.Input(shape=imageSize)
eff_net_model = EfficientNetB0(input_tensor=inputs)
eff_net_model.compile(...)
eff_net_model.fit(...)
# training is finished now wrap the model with preprocessing for inference model
model = b64_image_model_wrapper(eff_net_model,imageSize)
我的包装函数如下:
def b64_image_model_wrapper(model,imageSize,method=tf.image.ResizeMethod.BILINEAR,
mean=0.0,std=1.0,input_name="b64_image"):
def preprocess_and_decode(img_str, new_shape=imageSize):
img = tf.io.decode_base64(img_str)
img = tf.image.decode_jpeg(img, channels=3)
img = tf.image.resize(img, new_shape, method=method)
return img
input64 = tf.keras.layers.Input(shape=(None,), dtype="string", name=input_name)
output_tensor = tf.keras.layers.Lambda(
lambda img: tf.map_fn(lambda im: preprocess_and_decode(im[0]), img, fn_output_signature=tf.float32,swap_memory=True))(input64)
x = (output_tensor - mean) / std
x = model(x)
new_model = tf.keras.Model(input64, x, name=model.name)
new_model.output_names = model.output_names
return new_model
稍后如果我想用这个新模型(将字符串编码图像作为输入的模型)进行预测,我会这样做:
model.predict(np.array(["hello"])) # just for testing purposes
我收到错误:
Exception has occurred: InvalidArgumentError
Expected image (JPEG, PNG, or GIF), got unknown format starting with '10_104570i7'
[[{{node EfficientNet/lambda/map/while/body/_1/EfficientNet/lambda/map/while/DecodeJpeg}}]]
同样,如果我保存这个新模型 (tf.saved_model.save(model)
) 并尝试将它与 Tensorflow Serving 一起使用,我会收到错误消息:
Error while reading resource variable block6c_bn/moving_mean from Container: localhost. This could mean that the variable was uninitialized. Not found: Container localhost does not exist. (Could not find resource: localhost/block6c_bn/moving_mean)\n\t [[{{node functional_1/EfficientNet/block6c_bn/FusedBatchNormV3/ReadVariableOp}}]]
不知道具体是什么意思,好像有些权重没有初始化?我是否以正确的方式包装模型?
调用 model.predict(np.array(["hello"]))
时出错的原因是:
- 输入格式不是base64字符串
- 您在
tf.io.decode_base64
之后的输入不是.jpg
文件
以下代码向您展示了如何使用 .jpg
文件测试模型:
with open("./homersimpson.0.0.jpg", "rb") as imageFile:
base64_bytes = base64.urlsafe_b64encode(imageFile.read())
base64_strings = base64_bytes.decode('ascii')
img = tf.io.decode_base64(base64_strings)
prediction = model.predict(np.array([base64_strings]))
另外我用model.save('./test_save_model')
保存了整个模型,没有任何问题