【发布时间】:2017-12-22 07:09:42
【问题描述】:
我在 Python 中运行一个 REST 服务器,带有一个访问点来检索图像并使用 tensorflow 模型来预测该图像上的内容。启动服务器后,我将图像发送到 REST 端点。加载的模型是我自己训练的 Inception 模型。它从张量流检查点文件加载以恢复权重。这是构建图并执行分类的函数:
import os
import tensorflow as tf
from cnn_server.server import file_service as dirs
from slim.datasets import dataset_utils
from slim.nets import nets_factory as network_factory
from slim.preprocessing import preprocessing_factory as preprocessing_factory
def inference_on_image(bot_id, image_file, network_name='inception_v4', return_labels=1):
model_path = dirs.get_model_data_dir(bot_id)
# Get number of classes to predict
protobuf_dir = dirs.get_protobuf_dir(bot_id)
number_of_classes = dataset_utils.get_number_of_classes_by_labels(protobuf_dir)
# Get the preprocessing and network construction functions
preprocessing_fn = preprocessing_factory.get_preprocessing(network_name, is_training=False)
network_fn = network_factory.get_network_fn(network_name, number_of_classes)
# Process the temporary image file into a Tensor of shape [widht, height, channels]
image_tensor = tf.gfile.FastGFile(image_file, 'rb').read()
image_tensor = tf.image.decode_image(image_tensor, channels=0)
# Perform preprocessing and reshape into [network.default_width, network.default_height, channels]
network_default_size = network_fn.default_image_size
image_tensor = preprocessing_fn(image_tensor, network_default_size, network_default_size)
# Create an input batch of size one from the preprocessed image
input_batch = tf.reshape(image_tensor, [1, 299, 299, 3])
# Create the network up to the Predictions Endpoint
logits, endpoints = network_fn(input_batch)
restorer = tf.train.Saver()
with tf.Session() as sess:
tf.global_variables_initializer().run()
# Restore the variables of the network from the last checkpoint and run the graph
restorer.restore(sess, tf.train.latest_checkpoint(model_path))
sess.run(endpoints)
# Get the numpy array of predictions out of the
predictions = endpoints['Predictions'].eval()[0]
sess.close()
return map_predictions_to_labels(protobuf_dir, predictions, return_labels)
为了构建 Inception V4 模型的图表,我使用了 tf.model.slim,这是最先进 CCN 的 tensorflow 实现的集合。初始模型在这里构建:https://github.com/tensorflow/models/blob/master/slim/nets/inception_v4.py,并通过工厂方法提供:https://github.com/tensorflow/models/blob/master/slim/nets/nets_factory.py
对于第一张图片,一切都按预期工作:
2017-07-17 18:00:43.831365: I tensorflow/core/common_runtime/gpu/gpu_device.cc:908] DMA: 0
2017-07-17 18:00:43.831371: I tensorflow/core/common_runtime/gpu/gpu_device.cc:918] 0: Y
2017-07-17 18:00:43.831384: I tensorflow/core/common_runtime/gpu/gpu_device.cc:977] Creating TensorFlow device (/gpu:0) -> (device: 0, name: GeForce GTX 1080, pci bus id: 0000:01:00.0)
192.168.0.192 - - [17/Jul/2017 18:00:46] "POST /classify/4 HTTP/1.1" 200 -
第二张图片产生以下错误:
ValueError: Variable InceptionV4/Conv2d_1a_3x3/weights already exists, disallowed. Did you mean to set reuse=True in VarScope? Originally defined at:
我对此的理解是,图表是最初创建的,然后在某处继续存在。发送第二张图像会导致再次调用该函数,尝试重新创建现有图形,然后出现错误。现在我尝试了一些方法:
全面停止 TensorFlow:
我试图整体停止 tensorflow 并每次在 GPU 上重新创建设备。那将是最好的解决方案,因为这样在服务器运行时 GPU 不会被 Tensorflow 占用。我尝试使用sess.close() 来做到这一点,但没有成功。 nvidia-smi 在处理完第一张图片后仍然会在 GPU 上显示进程。然后我尝试以某种方式访问这些设备,但我能得到的只是通过device_lib.list_local_devices() 获得的可用设备列表。然而,这并没有导致在 GPU 上操纵 tensorflow 进程的任何选项。停止服务器,即启动 tensorflow 会话的初始 python 脚本也会杀死 GPU 上的 tensorflow。每次分类后重新启动服务器并不是一个优雅的解决方案。
重置或删除图表 我尝试以多种方式重置图表。一种方法是从我正在运行的张量中检索 Graph,遍历所有集合并清除它们:
graph = endpoints['Predictions'].graph
for key in graph.get_all_collection_keys():
graph.clear_collection(key)
调试后显示图形集合为空,但错误仍然存在。另一种方法是将端点的图形设置为默认图形with graph.as_default:,因为图形是在我之前创建的,我不希望这会在计算后删除图形。没有。
将变量范围设置为reuse=true
变量作用域有一个选项reuse,可以在inception_v4.py中设置。
def inception_v4(inputs, num_classes=1001, is_training=True,
dropout_keep_prob=0.8,
reuse=None,
scope='InceptionV4',
create_aux_logits=True):
将其设置为 true,会导致最初创建图表时出错,表示变量不存在。
加载模型一次,然后继续它
我想到的另一种方法是创建一次模型,然后重复使用它,即避免再次调用网络工厂。现在这是有问题的,因为服务器拥有多个模型,每个模型都适用于不同数量的类。这意味着,我必须为每个模型创建图表,让它们保持活力并以某种方式维护它们。虽然这是可能的,但它会导致大量开销并且有些多余,因为模型总是相同的,只是权重和最后一层不同。权重已存储在检查点文件中,tf.model.slim 中的实现允许轻松创建具有不同数量类的输出图。
我在这里没有想法。最理想的解决方案当然是完全终止 GPU 上的 tensorflow,并在每次调用函数时从头开始重新创建设备。
希望任何人都可以在这里提供帮助。
提前致谢。
【问题讨论】:
标签: python tensorflow