【TensorFlow】两种方式restore训练好的模型预测图片

训练神经网络模型并不是我们的最终目的,我们想要实现的是用训练好的模型来预测未知图片。深度学习领域框架众多,本文仅讨论TensorFlow框架及其生成的ckpt模型。如何实现网络模型的restore呢?简单来说,restore训练好的模型有两种思路:

思路一:恢复网络结构 + 参数


1.1 思路解析

先从已经训练好的模型的默认图中得到模型的输入输出计算节点,也就是x节点和y(也即logits),然后使用sess.run的方式启动运算过程计算y的输出,期间将需要预测的图片feedx节点。这种思路将图片数据输入到训练好的模型结构中进行计算,得到一个预测值,该方式不需要重建网络结构,但要求训练模型时为输入输出节点分别命名,以便restore期间使用get_tensor_by_name方法获取这些节点。该种思路如下图所示:

在这里插入图片描述

1.2 示例代码

以训练一个仅有两层卷积层、两层池化层和两个全连接层,输入维度为[20, 20, 1],结果分为3类的简单网络为例具体阐释以上思路。首先是训练网络的脚本train.py

# ================================ #
# 网络结构定义
# 输入层:[None, 20, 20, 1]
# 卷积层一:[None, 20, 20, 6]
# 池化层一:[None, 10, 10, 6]
# 卷积层二:[None, 10, 10, 16]
# 池化层二:[None, 5, 5, 16]
# 全连接层一:[None, 120]
# 全连接层二:[None, 3]
# ================================ #

x = tf.placeholder(tf.float32, shape=[None, 20, 20, 1], name='x-input')

with tf.variable_scope('layer1-conv1'):
	conv1_weights = tf.get_variable('weight', [5,5,1,6], 
									initializer=tf.truncated_normal_initializer(stddev=0.1))
	conv1_biases = tf.get_variable('bias',[6],
									initializer=tf.constant_initializer(0.0))
	conv1 = tf.nn.conv2d(x, conv1_weights, strides=[1, 1, 1, 1], padding='SAME')
	relu1 = tf.nn.relu(tf.nn.bias_add(conv1, conv1_biases))

with tf.name_scope('layer2-pool1'):
	pool1 = tf.nn.max_pool(relu1, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')

with tf.variable_scope('layer3-conv2'):
	conv2_weights = tf.get_variable('weight', [5,5,6,16], 
									initializer=tf.truncated_normal_initializer(stddev=0.1))
	conv2_biases = tf.get_variable('bias',[16],
									initializer=tf.constant_initializer(0.0))
	conv2 = tf.nn.conv2d(pool1, conv1_weights, strides=[1, 1, 1, 1], padding='SAME')
	relu2 = tf.nn.relu(tf.nn.bias_add(conv2, conv2_biases))

with tf.name_scope('layer4-pool2'):
	pool2 = tf.nn.max_pool(relu2, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')

pool2_shape = pool2.get_shape().as_list()                   # 得到池化层二的维度信息,如[10, 5, 5, 16],用于计算一维张量长度
nodes = pool2_shape[1] * pool2_shape[2] * pool2_shape[3]    # 每一张图被展开为长度5 * 5 * 16的一维张量

reshaped = tf.reshape(pool2, [-1, nodes])                   # reshape成行数不定,长度为400的张量

with tf.variable_scope('layer5-fc1'):
	fc1_weights = tf.get_variable('weight', [400, 120],
                              initializer=tf.truncated_normal_initializer(stddev=0.1))
   	tf.add_to_collection('losses', regularizer(fc1_weights))
	fc1_biases = tf.get_variable('bias', [120],
                             initializer=tf.constant_initializer(0.0))
	fc1 = tf.nn.relu(tf.matmul(reshaped, fc1_weights) + fc1_biases)
 
with tf.variable_scope('layer6-fc2'):
	fc2_weights = tf.get_variable('weight', [120, 3],
                                  initializer=tf.truncated_normal_initializer(stddev=0.1))
	tf.add_to_collection('losses', regularizer(fc2_weights))
	fc2_biases = tf.get_variable('bias', [3],
								initializer=tf.constant_initializer(0.0))
	logit = tf.add(tf.matmul(fc1, fc2_weights), fc2_biases, name='logit')    # 这个logit即我们想要的计算结果     

上述网络经过一定迭代次数的训练,可以得到训练完成的模型文件ckpt,我们可以使用下列代码restore网络的结构和权重,进而完成图片的预测predict.py

import tensorflow as tf

with tf.Session() as sess:
    saver = tf.train.import_meta_graph('./model/model3.ckpt-10000.meta')    # 得到模型的网络结构
    saver.restore(sess, tf.train.latest_checkpoint('./model'))              # 从checkpoint中得到最新模型的权重文件路径进而恢复权重

	graph = tf.get_default_graph()                        # 加载默认图
	x = graph.get_tensor_by_name("x-input:0")             # 张量名称构成为<op_name>:<output_index>
    y = graph.get_tensor_by_name("layer6-fc2/logit:0")    # 注意,如果网络结构中有variable_scope时,需要在name之前加上scope名作为前缀
	
	for img_path in imgs_path:                            # 遍历所有图片
		img_array = get_one_image(img_path)
		logits = sess.run(y, feed_dict={x: img_array})   # 得到预测值
		y = np.argmax(logits, axis=1)[0]

思路二:恢复网络参数


2.1 思路解析

重建训练期间使用的网络结构,restore时将各个参数恢复至相应的计算节点,然后sess.run想要预测的结果。这种思路适用于:1)模型训练期间未给输入输出计算节点命名的;2)模型模块化封装较好的,如把网络结构封装成了一个函数model或者函数inference。该种思路示意图如下:

在这里插入图片描述

2.2 示例代码

网络结构和思路一中基本相同,但是这里在构建网络时做了一些封装工作,将网络作为一个函数inference,如下model.py

def inference(input_tensor, train_or_eval, regularizer):
	with tf.variable_scope('layer1-conv1'):
		conv1_weights = tf.get_variable('weight', [5,5,1,6], 
										initializer=tf.truncated_normal_initializer(stddev=0.1))
		conv1_biases = tf.get_variable('bias',[6],
										initializer=tf.constant_initializer(0.0))
		conv1 = tf.nn.conv2d(input_tensor, conv1_weights, strides=[1, 1, 1, 1], padding='SAME')
		relu1 = tf.nn.relu(tf.nn.bias_add(conv1, conv1_biases))
	
	with tf.name_scope('layer2-pool1'):
		pool1 = tf.nn.max_pool(relu1, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')
	
	with tf.variable_scope('layer3-conv2'):
		conv2_weights = tf.get_variable('weight', [5,5,6,16], 
										initializer=tf.truncated_normal_initializer(stddev=0.1))
		conv2_biases = tf.get_variable('bias',[16],
										initializer=tf.constant_initializer(0.0))
		conv2 = tf.nn.conv2d(pool1, conv1_weights, strides=[1, 1, 1, 1], padding='SAME')
		relu2 = tf.nn.relu(tf.nn.bias_add(conv2, conv2_biases))
	
	with tf.name_scope('layer4-pool2'):
		pool2 = tf.nn.max_pool(relu2, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')
	
	pool2_shape = pool2.get_shape().as_list()                   # 得到池化层二的维度信息,如[10, 5, 5, 16],用于计算一维张量长度
	nodes = pool2_shape[1] * pool2_shape[2] * pool2_shape[3]    # 每一张图被展开为长度5 * 5 * 16的一维张量
	
	reshaped = tf.reshape(pool2, [-1, nodes])                   # reshape成行数不定,长度为400的张量
	
	with tf.variable_scope('layer5-fc1'):
		fc1_weights = tf.get_variable('weight', [400, 120],
	                              initializer=tf.truncated_normal_initializer(stddev=0.1))
	    if regularizer != None:
	   		tf.add_to_collection('losses', regularizer(fc1_weights))
		fc1_biases = tf.get_variable('bias', [120],
	                             initializer=tf.constant_initializer(0.0))
		fc1 = tf.nn.relu(tf.matmul(reshaped, fc1_weights) + fc1_biases)
		if train_or_eval:
            fc1 = tf.nn.dropout(fc1, 0.5)    # drop
	 
	with tf.variable_scope('layer6-fc2'):
		fc2_weights = tf.get_variable('weight', [120, 3],
	                                  initializer=tf.truncated_normal_initializer(stddev=0.1))
	    if regularizer != None:
	   		tf.add_to_collection('losses', regularizer(fc1_weights))
		tf.add_to_collection('losses', regularizer(fc2_weights))
		fc2_biases = tf.get_variable('bias', [3],
									initializer=tf.constant_initializer(0.0))
		logits = tf.add(tf.matmul(fc1, fc2_weights), fc2_biases)    
	
	return logits    # 这个logit即我们想要的计算结果 

同样,训练完成会得到ckpt模型文件,这里不同于思路一我们的网络结构作为一个提供公共服务的函数接口并没有对输入输出节点设置特别的名字,那么如何使用训练好的模型呢?答案是再次使用inference构建出原来的网络结构,然后恢复模型的权重值,最后把图片喂给它,predict.py

import tensorflow as tf
import model

with tf.Graph().as_default():
	x = tf.placeholder(tf.float32, [1,20,20,1])          # 每次只预测一张图
	# 也可以在此使用tf接口定义图片预处理节点
	# image = tf.cast(image_array, tf.float32)             # 图片转为float32
    # image = tf.image.per_image_standardization(image)    # 图片标准化
    # image = tf.reshape(image, [1, 20, 20, 1])            # 图片转为指定的维度
	y = model.inference(x, False, None)
        
	with tf.Session() as sess:
		saver = tf.train.Saver()
		ckpt = tf.train.get_checkpoint_state('./model')
		if ckpt and ckpt.model_checkpoint_path:
			saver.restore(sess, ckpt.model_checkpoint_path)
			print('模型加载成功!')
		else:
			print('模型不存在!')

		for img_path in imgs_path:                            # 遍历所有图片
			img_array = get_one_image(img_path)
			logits = sess.run(y, feed_dict={x: img_array})   # 得到预测值
			y = np.argmax(logits, axis=1)[0]
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 下面是 TensorFlow 中使用 session.run() 训练预测的代码示例: 训练代码: ``` # 创建 TensorFlow session with tf.Session() as sess: # 初始化变量 sess.run(tf.global_variables_initializer()) for i in range(num_steps): # 获取训练数据 x_batch, y_batch = get_next_batch(batch_size) # 运行训练操作 sess.run(train_op, feed_dict={x: x_batch, y: y_batch}) if i % 100 == 0: # 计算损失 loss_value = sess.run(loss, feed_dict={x: x_batch, y: y_batch}) print("Step: %d, Loss: %f" % (i, loss_value)) ``` 预测代码: ``` # 创建 TensorFlow session with tf.Session() as sess: # 加载模型参数 saver.restore(sess, "path/to/model.ckpt") # 获取预测数据 x_test = get_test_data() # 运行预测操作 predictions = sess.run(pred, feed_dict={x: x_test}) ``` 注意:需要对于训练预测的部分要先定义x,y,train_op,loss,pred,saver等变量或者操作 ### 回答2: 在TensorFlow中,sess.run()是一个非常重要的函数,用于执行计算图中的节点。训练预测过程都会涉及到sess.run()函数的使用。 在训练代码中,我们首先需要定义一个优化器(如AdamOptimizer),并使用它来最小化我们的损失函数。然后,我们会创建一个会话(session),并使用sess.run()函数来初始化变量。接下来,我们会迭代训练数据,每次迭代都会使用sess.run()函数来计算一个或多个节点的值,并将其用于更新模型参数。最后,我们可以使用sess.run()函数来计算训练过程中的评估指标。 在预测代码中,我们也会创建一个会话,并使用sess.run()函数来初始化变量。接着,我们会将待预测的数据输入到模型中,并使用sess.run()函数来计算输出节点的值。对于分类问题,我们可以通过sess.run()函数将输出节点的值转化为概率分布或预测结果。对于回归问题,我们可以直接使用sess.run()函数得到预测的结果。 需要注意的是,在sess.run()函数中,我们可以指定要计算的节点,也可以同时计算多个节点的值。当使用sess.run()函数计算多个节点的值时,TensorFlow会自动处理节点之间的依赖关系,并按照正确的顺序计算它们。 总结起来,sess.run()函数在TensorFlow中用于执行计算图中的节点,训练过程中可以用来计算损失函数和评估指标,预测过程中可以用来计算输出节点的值并进行结果的转化。 ### 回答3: 在使用tensorflow进行训练预测时,我们通常会使用`sess.run()`函数来执行相应的操作。 在进行训练时,`sess.run()`函数通常会用来执行训练操作,例如`sess.run(train_op)`,其中`train_op`表示训练操作,可以是优化器的`minimize`函数或其他自定义的训练操作。当执行`sess.run(train_op)`时,tensorflow会自动计算并更新变量的值,以使得模型能够逐渐收敛到最优解。这样,我们就可以利用`sess.run()`来进行模型训练,通过多次调用这个函数,逐渐迭代参数,提升模型的性能。 而在进行预测时,`sess.run()`函数通常会用来执行模型预测操作,例如`sess.run(y_pred, feed_dict={x: input_data})`,其中`y_pred`表示模型预测结果,`x`表示输入数据的占位符,`input_data`表示输入数据的实际值。通过在`feed_dict`参数中提供实际的输入数据,`sess.run()`会根据模型的计算图和输入数据,运行并返回预测结果。这样,我们就可以利用`sess.run()`来获取模型预测结果,并根据需要进行进一步的处理和分析。 总的来说,`sess.run()`是tensorflow中非常重要的一个函数,通过它我们可以执行模型训练操作和预测操作,根据需要获取模型的输出结果,并对其进行进一步处理。在使用`sess.run()`时,我们通常需要明确指定待执行的操作和提供相应的输入数据,以使得tensorflow能够正确地执行计算图中定义的操作,获得所需的结果。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值