【发布时间】:2017-04-30 16:25:38
【问题描述】:
我一直在研究这个问题。我找到了很多文章;但没有一个真正将张量流推理显示为简单的推理。它总是“使用服务引擎”或使用预编码/定义的图表。
问题是:我有一台设备偶尔会检查更新的模型。然后它需要加载该模型并通过模型运行输入预测。
在 keras 中,这很简单:构建模型;训练模型并调用 model.predict()。在 scikit-learn 中也是一样的。
我可以抓取一个新模型并加载它;我可以打印出所有的重量;但是我到底要如何对它进行推理呢?
加载模型和打印权重的代码:
with tf.Session() as sess:
new_saver = tf.train.import_meta_graph(MODEL_PATH + '.meta', clear_devices=True)
new_saver.restore(sess, MODEL_PATH)
for var in tf.trainable_variables():
print(sess.run(var))
我打印了我所有的收藏,我有: ['queue_runners', 'variables', 'losses', 'summaries', 'train_op', 'cond_context', 'trainable_variables']
我尝试使用sess.run(train_op);然而,这才刚刚开始完整的培训课程;这不是我想做的。我只想对我提供的一组不同的输入进行推理,这些输入不是 TF 记录。
再详细一点:
设备可以使用C++或Python;只要我能生成一个.exe。如果我想为系统提供信息,我可以设置一个提要字典。我用TFRecords 训练过;但在生产中我不会使用TFRecords;它是一个实时/接近实时的系统。
感谢您的任何意见。我将示例代码发布到此 repo:https://github.com/drcrook1/CIFAR10/TensorFlow,它会执行所有训练和示例推理。
非常感谢任何提示!
------------编辑----- 我将模型重建如下:
def inference(images):
'''
Portion of the compute graph that takes an input and converts it into a Y output
'''
with tf.variable_scope('Conv1') as scope:
C_1_1 = ld.cnn_layer(images, (5, 5, 3, 32), (1, 1, 1, 1), scope, name_postfix='1')
C_1_2 = ld.cnn_layer(C_1_1, (5, 5, 32, 32), (1, 1, 1, 1), scope, name_postfix='2')
P_1 = ld.pool_layer(C_1_2, (1, 2, 2, 1), (1, 2, 2, 1), scope)
with tf.variable_scope('Dense1') as scope:
P_1 = tf.reshape(C_1_2, (CONSTANTS.BATCH_SIZE, -1))
dim = P_1.get_shape()[1].value
D_1 = ld.mlp_layer(P_1, dim, NUM_DENSE_NEURONS, scope, act_func=tf.nn.relu)
with tf.variable_scope('Dense2') as scope:
D_2 = ld.mlp_layer(D_1, NUM_DENSE_NEURONS, CONSTANTS.NUM_CLASSES, scope)
H = tf.nn.softmax(D_2, name='prediction')
return H
请注意,我将名称 'prediction' 添加到 TF 操作中,以便稍后检索它。
在训练时,我使用tfrecords 的输入管道和输入队列。
GRAPH = tf.Graph()
with GRAPH.as_default():
examples, labels = Inputs.read_inputs(CONSTANTS.RecordPaths,
batch_size=CONSTANTS.BATCH_SIZE,
img_shape=CONSTANTS.IMAGE_SHAPE,
num_threads=CONSTANTS.INPUT_PIPELINE_THREADS)
examples = tf.reshape(examples, [CONSTANTS.BATCH_SIZE, CONSTANTS.IMAGE_SHAPE[0],
CONSTANTS.IMAGE_SHAPE[1], CONSTANTS.IMAGE_SHAPE[2]])
logits = Vgg3CIFAR10.inference(examples)
loss = Vgg3CIFAR10.loss(logits, labels)
OPTIMIZER = tf.train.AdamOptimizer(CONSTANTS.LEARNING_RATE)
我试图在图中的加载操作上使用feed_dict;但是现在它只是简单地挂起......
MODEL_PATH = 'models/' + CONSTANTS.MODEL_NAME + '.model'
images = tf.placeholder(tf.float32, shape=(1, 32, 32, 3))
def run_inference():
'''Runs inference against a loaded model'''
with tf.Session() as sess:
#sess.run(tf.global_variables_initializer())
new_saver = tf.train.import_meta_graph(MODEL_PATH + '.meta', clear_devices=True)
new_saver.restore(sess, MODEL_PATH)
pred = tf.get_default_graph().get_operation_by_name('prediction')
rand = np.random.rand(1, 32, 32, 3)
print(rand)
print(pred)
print(sess.run(pred, feed_dict={images: rand}))
print('done')
run_inference()
我认为这不起作用,因为原始网络是使用 TFRecords 训练的。在样本 CIFAR 数据集中,数据很小;我们的真实数据集非常庞大,我认为 TFRecords 是训练网络的默认最佳实践。从生产的角度来看,feed_dict 非常完美;我们可以启动一些线程并从我们的输入系统中填充那个东西。
所以我猜我有一个经过训练的网络,我可以得到预测操作;但是我如何告诉它停止使用输入队列并开始使用feed_dict?请记住,从生产的角度来看,我无法获得科学家们为制造它所做的任何事情。他们做他们的事;我们使用任何商定的标准将其投入生产。
-------输入操作--------
tf.Operation 'input/input_producer/Const' type=Const, tf.Operation 'input/input_producer/Size' type=Const, tf.Operation 'input/input_producer/Greater/y' type=Const, tf.Operation 'input/input_producer/Greater' type=Greater, tf.Operation 'input/input_producer/Assert/Const' type=Const, tf.Operation 'input/input_producer/Assert/Assert/data_0' type=Const, tf.Operation 'input /input_producer/Assert/Assert' type=Assert, tf.Operation 'input/input_producer/Identity' type=Identity, tf.Operation 'input/input_producer/RandomShuffle' type=RandomShuffle, tf.Operation 'input/input_producer' type=FIFOQueueV2 , tf.Operation 'input/input_producer/input_producer_EnqueueMany' type=QueueEnqueueManyV2, tf.Operation 'input/input_producer/input_producer_Close' type=QueueCloseV2, tf.Operation 'input/input_producer/input_producer_Close_1' type=QueueCloseV2, tf.Operation 'input/input_producer /input_producer_Size' type=QueueSizeV2, tf.Operation 'input/input_producer/Cast' type=Cast, tf.Operation 'input/input_pro ducer/mul/y' type=Const, tf.Operation 'input/input_producer/mul' type=Mul, tf.Operation 'input/input_producer/fraction_of_32_full/tags' type=Const, tf.Operation 'input/input_producer/fraction_of_32_full' type=ScalarSummary, tf.Operation 'input/TFRecordReaderV2' type=TFRecordReaderV2, tf.Operation 'input/ReaderReadV2' type=ReaderReadV2,
-----结束输入操作-----
----更新 3----
我相信我需要做的是终止使用 TF Records 训练的图形的输入部分,并将第一层的输入重新连接到新的输入。有点像做手术;但如果我使用 TFRecords 进行训练,就像听起来一样疯狂,这是我能找到的唯一推理方法……
全图:
要杀死的部分:
所以我认为问题变成了:如何杀死图表的输入部分并将其替换为feed_dict?
对此的跟进是:这真的是正确的方法吗?这看起来很疯狂。
----结束更新 3----
---链接到检查点文件---
--结束检查点文件的链接---
-----更新 4 -----
我屈服了,只是试了一下“正常”的推理方式,假设我可以让科学家们简单地腌制他们的模型,然后我们就可以抓住模型腌制;解压它,然后对其进行推理。所以为了测试我尝试了正常的方法,假设我们已经解压了它......它也不值得一个豆子......
import tensorflow as tf
import CONSTANTS
import Vgg3CIFAR10
import numpy as np
from scipy import misc
import time
MODEL_PATH = 'models/' + CONSTANTS.MODEL_NAME + '.model'
imgs_bsdir = 'C:/data/cifar_10/train/'
images = tf.placeholder(tf.float32, shape=(1, 32, 32, 3))
logits = Vgg3CIFAR10.inference(images)
def run_inference():
'''Runs inference against a loaded model'''
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
new_saver = tf.train.import_meta_graph(MODEL_PATH + '.meta')#, import_scope='1', input_map={'input:0': images})
new_saver.restore(sess, MODEL_PATH)
pred = tf.get_default_graph().get_operation_by_name('prediction')
enq = sess.graph.get_operation_by_name(enqueue_op)
#tf.train.start_queue_runners(sess)
print(rand)
print(pred)
print(enq)
for i in range(1, 25):
img = misc.imread(imgs_bsdir + str(i) + '.png').astype(np.float32) / 255.0
img = img.reshape(1, 32, 32, 3)
print(sess.run(logits, feed_dict={images : img}))
time.sleep(3)
print('done')
run_inference()
Tensorflow 最终使用来自加载模型的推理函数构建了一个新图;然后它将其他图表中的所有其他内容附加到它的末尾。因此,当我填充 feed_dict 期望得到推论时;我只是得到一堆随机垃圾,好像是第一次通过网络......
再次;这看起来很疯狂;我真的需要编写自己的框架来序列化和反序列化随机网络吗?这必须在之前完成......
-----更新 4 -----
再次;谢谢!
【问题讨论】:
标签: python c++ tensorflow