【编者按】有几天没有更新,一直在学习和调试程序,其中有大量与ChatGPT的对话,遇到的每一个问题都找ChatGPT,再也没有用到百度和google。在ChatGPT的帮助下已完成Python下的花卉识别训练与预测,部署到网站,也可以通过网页识别花卉图片。移植到微信小程序中还有一点问题(在模型加载时,遇到微信小程序不支持"fetch"的问题)。在编写与调试过程中,遇到的坑太多,与ChatGPT对话太多,无法一一呈现,与大家分享,后续会选择有代表性的知识点来分享。针对踩坑的解决方法,后续再总结为一篇文章来呈现,不以围观ChatGPT的方式呈现。
下面是有关h5格式与SavedModel格式的问题。
1问:model.predict()与 model.signatures['serving_default']、infer(),这两种方法有什么区别?(说明:在ChatGPT推荐的代码中涉及两种方法,所以有此一问,同时引出了模型格式的问题)
ChatGPT
在TensorFlow中,model.predict()
和model.signatures['serving_default']
(或infer()
)是两种不同的方法来进行推理(推断)或预测。它们的区别主要在于使用场景和底层实现。
model.predict()
- 适用场景: 这是Keras模型的一个方法,主要用于在本地对数据进行预测。
- 使用简便: 该方法非常直观且易于使用,特别适合在训练和评估模型后进行批量预测。
- 输入数据格式: 需要符合模型的输入形状和类型,通常是一个NumPy数组或一个tf.data.Dataset对象。
- 底层实现: 这是一个高层次的Keras API,内部处理了很多细节,如数据预处理和批处理。
示例:
python
import tensorflow as tf
import numpy as np
# 假设model已经定义和训练好
# 输入数据
data = np.random.random((10, 224, 224, 3))
predictions = model.predict(data)
model.signatures['serving_default']
或 infer()
- 适用场景: 这种方法主要用于TensorFlow Serving或导出SavedModel后进行推理。
- 灵活性: 提供了更多的控制和灵活性,可以自定义输入和输出的签名。
- 输入数据格式: 输入是一个字典,键为签名中定义的输入张量名称,值为相应的张量。
- 底层实现: 这是一个低层次的API,通常在模型导出后用于TensorFlow Serving时使用。
示例:
python
import tensorflow as tf
import numpy as np
# 假设model已经定义和训练好,并导出为SavedModel
# 加载模型
loaded_model = tf.saved_model.load('path_to_saved_model')
# 获取签名
infer = loaded_model.signatures['serving_default']
# 输入数据
input_data = np.random.random((10, 224, 224, 3)).astype(np.float32)
tensor_input_data = tf.convert_to_tensor(input_data)
# 构建输入字典
input_dict = {'input_1': tensor_input_data}
# 推理
output_dict = infer(**input_dict)
predictions = output_dict['output_1'].numpy()
主要区别
-
接口和使用简便性:
model.predict()
是一个高层次的API,适合快速和方便地进行预测。model.signatures['serving_default']
提供了更低层次的控制,适合在模型部署或需要自定义签名的情况下使用。
-
输入和输出的处理:
model.predict()
处理输入和输出非常方便,用户只需提供符合要求的输入数据格式。model.signatures['serving_default']
需要用户手动构建输入和输出字典,这使得其更灵活但也稍微复杂一些。
-
使用场景:
model.predict()
主要用于本地模型预测,训练和评估后的快速推理。model.signatures['serving_default']
主要用于TensorFlow Serving或模型导出后的远程推理。
-
性能和优化:
- 在某些情况下,
model.signatures['serving_default']
可能会提供更好的性能,因为它可以利用TensorFlow Serving的优化和批处理能力。
- 在某些情况下,
总之,选择哪种方法取决于你的使用场景。如果是在本地进行快速预测,model.predict()
是更好的选择。如果是需要部署模型并在生产环境中进行推理,使用 model.signatures['serving_default']
会更合适。
2问:与训练模型格式有关吗?如h5,或SavedModel
ChatGPT
是的,model.predict()
和 model.signatures['serving_default']
在某种程度上与模型的保存格式有关。具体来说,它们对 h5
和 SavedModel
格式的支持有所不同:
model.predict()
- 适用格式 : 主要适用于
h5
和SavedModel
格式的 Keras 模型。 - 加载模型 : 无论是
h5
还是SavedModel
格式的模型,都可以使用tf.keras.models.load_model()
来加载。 - 使用方式 : 无论模型以何种格式保存,加载后都可以直接调用
model.predict()
进行预测。
示例:
python
import tensorflow as tf
import numpy as np
# 加载h5格式的模型
model_h5 = tf.keras.models.load_model('model.h5')
# 加载SavedModel格式的模型
model_saved = tf.keras.models.load_model('saved_model_directory')
# 输入数据
data = np.random.random((10, 224, 224, 3))
# 进行预测
predictions_h5 = model_h5.predict(data)
predictions_saved = model_saved.predict(data)
model.signatures['serving_default']
- 适用格式 : 主要适用于
SavedModel
格式的模型。 - 加载模型 : 使用
tf.saved_model.load()
来加载SavedModel
格式的模型。 - 使用方式: 需要访问模型的签名,并根据签名的要求准备输入和输出。
示例:
python
import tensorflow as tf
import numpy as np
# 加载SavedModel格式的模型
loaded_model = tf.saved_model.load('saved_model_directory')
# 获取签名
infer = loaded_model.signatures['serving_default']
# 输入数据
input_data = np.random.random((10, 224, 224, 3)).astype(np.float32)
tensor_input_data = tf.convert_to_tensor(input_data)
# 构建输入字典
input_dict = {'input_1': tensor_input_data} # 注意这里的 'input_1' 需要与模型签名匹配
# 推理
output_dict = infer(**input_dict)
predictions = output_dict['output_1'].numpy() # 注意这里的 'output_1' 需要与模型签名匹配
总结
-
model.predict()
:- 适用于
h5
和SavedModel
格式的 Keras 模型。 - 加载模型后直接使用,接口简单方便。
- 主要用于本地推理和评估。
- 适用于
-
model.signatures['serving_default']
:- 主要适用于
SavedModel
格式的模型。 - 需要通过签名访问和使用,更灵活但也更复杂。
- 主要用于部署和远程推理,如在 TensorFlow Serving 中使用。
- 主要适用于
因此,模型保存格式确实会影响你选择哪种方法来进行推理。对于 h5
格式的模型,只能使用 model.predict()
方法,而对于 SavedModel
格式的模型,你可以根据需要选择使用 model.predict()
或 model.signatures['serving_default']
方法。
3问:把h5与SavedModel模型转换为tensorflowjs后,是否还有model.predict()与model.signatures['serving_default']区别呢?在web中使用哪个更好呢?
ChatGPT
将 Keras 模型(无论是 h5
格式还是 SavedModel
格式)转换为 TensorFlow.js 格式后,主要使用 TensorFlow.js 提供的 API 进行推理。在 TensorFlow.js 中,使用模型进行推理的方式和在 TensorFlow(Python)中有所不同。
TensorFlow.js 中的模型推理
在 TensorFlow.js 中,加载和使用模型的方式主要有以下几种:
- 使用
tf.loadLayersModel()
和model.predict()
- 使用
tf.loadGraphModel()
和model.execute()
tf.loadLayersModel()
和 model.predict()
- 适用模型 : 主要适用于 Keras
h5
和通过tfjs.converters.save_keras_model
转换的模型。 - 使用方式 : 类似于在 Python 中的 Keras 模型,加载后可以直接调用
model.predict()
进行推理。
示例:
javascript
// 加载Keras模型
const model = await tf.loadLayersModel('path/to/model.json');
// 准备输入数据
const input = tf.tensor4d(data, [1, 224, 224, 3]);
// 进行预测
const predictions = model.predict(input);
predictions.print();
tf.loadGraphModel()
和 model.execute()
- 适用模型 : 主要适用于 TensorFlow SavedModel 和通过
tfjs.converters.convert_tf_saved_model
转换的模型。 - 使用方式 : 使用
model.execute()
进行推理,类似于在 Python 中使用model.signatures['serving_default']
。
示例:
javascript
// 加载Graph模型
const model = await tf.loadGraphModel('path/to/model.json');
// 准备输入数据
const input = tf.tensor4d(data, [1, 224, 224, 3]);
// 构建输入字典
const inputDict = { 'input_tensor_name': input }; // 'input_tensor_name'需要与模型的输入张量名称匹配
// 进行推理
const output = model.execute(inputDict, ['output_tensor_name']); // 'output_tensor_name'需要与模型的输出张量名称匹配
output.print();
选择哪个更好
在 Web 中选择哪个方法更好取决于以下因素:
-
模型类型:
- 如果模型是 Keras
h5
模型或通过tfjs.converters.save_keras_model
转换的模型,使用tf.loadLayersModel()
和model.predict()
更加简便。 - 如果模型是 TensorFlow SavedModel 或通过
tfjs.converters.convert_tf_saved_model
转换的模型,使用tf.loadGraphModel()
和model.execute()
更合适。
- 如果模型是 Keras
-
使用场景:
- 简单推理 : 对于简单的推理任务,使用
tf.loadLayersModel()
和model.predict()
更加直观和方便。 - 复杂推理 : 如果需要自定义输入和输出张量,或者使用特定的签名,
tf.loadGraphModel()
和model.execute()
提供了更多的灵活性。
- 简单推理 : 对于简单的推理任务,使用
-
性能:
- 一般来说,两者在性能上没有显著差异。选择时更多考虑的是模型类型和使用的简便性。
总结
在 Web 中使用 TensorFlow.js 进行模型推理时:
- 如果模型是 Keras
h5
或通过tfjs.converters.save_keras_model
转换的模型 ,建议使用tf.loadLayersModel()
和model.predict()
。 - 如果模型是 TensorFlow SavedModel 或通过
tfjs.converters.convert_tf_saved_model
转换的模型 ,建议使用tf.loadGraphModel()
和model.execute()
。
无论选择哪种方式,都要确保输入和输出的张量名称与模型签名一致。这样可以确保模型能够正确地进行推理。
4问:我是使用tensorflowjs_converter命令把h5和SavedModel转换为tensorflowjs模型的,没有涉及你提到的tfjs.converters.save_keras_model和tfjs.converters.convert_tf_saved_model。阐述一下这2个模块
ChatGPT
在 TensorFlow.js 中,tfjs.converters
模块提供了用于在 TensorFlow 和 TensorFlow.js 之间进行模型转换的工具。以下是对 tfjs.converters.save_keras_model
和 tfjs.converters.convert_tf_saved_model
两个函数的详细说明:
tfjs.converters.save_keras_model
这个函数用于将一个 Keras 模型保存为 TensorFlow.js 可用的格式。它在 Python 环境中运行,将现有的 Keras 模型(无论是 .h5
格式还是其他格式的 Keras 模型)转换为 TensorFlow.js 格式。
使用方法:
python
import tensorflow as tf
import tensorflowjs as tfjs
# 假设model是一个已经定义和训练好的Keras模型
model = tf.keras.models.load_model('model.h5')
# 将模型转换并保存为TensorFlow.js格式
tfjs.converters.save_keras_model(model, 'path/to/save/model')
示例:
python
import tensorflow as tf
import tensorflowjs as tfjs
# 创建一个简单的Keras模型
model = tf.keras.Sequential([
tf.keras.layers.Dense(10, activation='relu', input_shape=(784,)),
tf.keras.layers.Dense(10, activation='softmax')
])
# 编译和训练模型
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])
# model.fit(...)
# 将模型转换为TensorFlow.js格式
tfjs.converters.save_keras_model(model, 'path/to/save/model')
tfjs.converters.convert_tf_saved_model
这个函数用于将一个 TensorFlow SavedModel 格式的模型转换为 TensorFlow.js 格式。它同样在 Python 环境中运行,将 TensorFlow SavedModel 模型转换为 TensorFlow.js 格式。
使用方法:
python
import tensorflowjs as tfjs
# 将SavedModel转换并保存为TensorFlow.js格式
tfjs.converters.convert_tf_saved_model('path/to/saved_model', 'path/to/save/model')
示例:
python
import tensorflow as tf
import tensorflowjs as tfjs
# 假设已经有一个保存的SavedModel
# 将SavedModel加载
model = tf.saved_model.load('path/to/saved_model')
# 将SavedModel转换为TensorFlow.js格式
tfjs.converters.convert_tf_saved_model('path/to/saved_model', 'path/to/save/model')
tensorflowjs_converter
命令行工具
你提到使用 tensorflowjs_converter
命令行工具将 Keras .h5
模型和 SavedModel 转换为 TensorFlow.js 格式。这实际上是利用了 tfjs.converters
模块的功能,但以命令行的方式进行操作。
转换 Keras .h5
模型:
bash
tensorflowjs_converter --input_format keras path/to/model.h5 path/to/save/model
转换 TensorFlow SavedModel:
bash
tensorflowjs_converter --input_format=tf_saved_model --saved_model_tags=serve path/to/saved_model path/to/save/model
在 Web 中使用转换后的模型
不管你是使用 tfjs.converters.save_keras_model
、tfjs.converters.convert_tf_saved_model
,还是 tensorflowjs_converter
命令行工具来进行转换,转换后的模型在 Web 中的使用方式是相同的。
加载和使用 Keras 模型:
javascript
// 使用 tf.loadLayersModel() 加载模型
const model = await tf.loadLayersModel('path/to/model.json');
// 准备输入数据
const input = tf.tensor4d(data, [1, 224, 224, 3]);
// 进行预测
const predictions = model.predict(input);
predictions.print();
加载和使用 SavedModel:
javascript
// 使用 tf.loadGraphModel() 加载模型
const model = await tf.loadGraphModel('path/to/model.json');
// 准备输入数据
const input = tf.tensor4d(data, [1, 224, 224, 3]);
// 构建输入字典
const inputDict = { 'input_tensor_name': input }; // 'input_tensor_name'需要与模型的输入张量名称匹配
// 进行推理
const output = model.execute(inputDict, ['output_tensor_name']); // 'output_tensor_name'需要与模型的输出张量名称匹配
output.print();
总结
tfjs.converters.save_keras_model
: 用于在 Python 环境中将 Keras 模型转换为 TensorFlow.js 格式。tfjs.converters.convert_tf_saved_model
: 用于在 Python 环境中将 TensorFlow SavedModel 转换为 TensorFlow.js 格式。tensorflowjs_converter
: 命令行工具,提供了将 Keras.h5
模型和 TensorFlow SavedModel 转换为 TensorFlow.js 格式的便捷方法。
在 Web 中,使用 tf.loadLayersModel()
进行预测更适合简单的 Keras 模型,而使用 tf.loadGraphModel()
则更适合复杂的 TensorFlow SavedModel。选择哪种方法取决于你转换的模型类型以及使用场景。
至此,清楚了模型格式的一些问题。最后,编者选择了在训练的Python代码中直接保存为Tensorflow.js格式,而不需要在使用tensorflowjs_converter来转换,这样,部署到网站或微信小程序就更方便了。