Tensorflow:层大小取决于批量大小?
Tensorflow: Layer size dependent on batch size?
我目前正在尝试熟悉 Tensorflow 库,但我有一个相当基本的问题困扰着我。
在为 MNIST 分类构建卷积神经网络时,我尝试使用自己的 model_fn。其中通常会出现以下行以重塑输入特征。
x = tf.reshape(x, shape=[-1, 28, 28, 1])
,-1 指的是输入批量大小。
因为我使用这个节点作为我的卷积层的输入,
x = tf.reshape(x, shape=[-1, 28, 28, 1])
conv1 = tf.layers.conv2d(x, 32, 5, activation=tf.nn.relu)
这是否意味着我所有网络层的大小都取决于批量大小?
我尝试在单个测试输入上冻结和 运行 图形,这只有在我提供 n=batch_size 测试图像时才有效。
你能给我一个提示,告诉我如何在预测时在任何输入批量大小上构建我的网络 运行 吗?
此外,我猜想在网络定义中使用 tf.reshape 节点(请参阅 cnn_layout 中的第一个节点)并不是服务的最佳输入。
我将附加我的网络层和 model_fn
def cnn_layout(features,reuse,is_training):
with tf.variable_scope('cnn',reuse=reuse):
# resize input to [batchsize,height,width,channel]
x = tf.reshape(features['x'], shape=[-1,30,30,1], name='input_placeholder')
# conv1, 32 filter, 5 kernel
conv1 = tf.layers.conv2d(x, 32, 5, activation=tf.nn.relu, name='conv1')
# pool1, 2 stride, 2 kernel
pool1 = tf.layers.max_pooling2d(conv1, 2, 2, name='pool1')
# conv2, 64 filter, 3 kernel
conv2 = tf.layers.conv2d(pool1, 64, 3, activation=tf.nn.relu, name='conv2')
# pool2, 2 stride, 2 kernel
pool2 = tf.layers.max_pooling2d(conv2, 2, 2, name='pool2')
# flatten pool2
flatten = tf.contrib.layers.flatten(pool2)
# fc1 with 1024 neurons
fc1 = tf.layers.dense(flatten, 1024, name='fc1')
# 75% dropout
drop = tf.layers.dropout(fc1, rate=0.75, training=is_training, name='dropout')
# output logits
output = tf.layers.dense(drop, 1, name='output_logits')
return output
def model_fn(features, labels, mode):
# setup two networks one for training one for prediction while sharing weights
logits_train = cnn_layout(features=features,reuse=False,is_training=True)
logits_test = cnn_layout(features=features,reuse=True,is_training=False)
# predictions
predictions = tf.round(tf.sigmoid(logits_test),name='predictions')
if mode == tf.estimator.ModeKeys.PREDICT:
return tf.estimator.EstimatorSpec(mode, predictions=predictions)
# define loss and optimizer
loss = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(logits=logits_train,labels=labels),name='loss')
optimizer = tf.train.AdamOptimizer(learning_rate=LEARNING_RATE, name='optimizer')
train = optimizer.minimize(loss, global_step=tf.train.get_global_step(),name='train')
# accuracy for evaluation
accuracy = tf.metrics.accuracy(labels=labels,predictions=predictions,name='accuracy')
# summarys for tensorboard
tf.summary.scalar('loss',loss)
# return training and evalution spec
return tf.estimator.EstimatorSpec(
mode=mode,
predictions=predictions,
loss=loss,
train_op=train,
eval_metric_ops={'accuracy':accuracy}
)
谢谢!
典型情况下features['x']
的rank已经是4了,外层维度实际batch size,所以没必要调整大小。
让我试着解释一下。
您还没有展示您的 serving_input_receiver_fn
,有几种方法可以做到这一点,尽管最终原则在所有方法中都是相似的。如果您使用的是 TensorFlow Serving,那么您可能会使用 build_parsing_serving_input_receiver_fn
。看看源码很有参考意义:
def build_parsing_serving_input_receiver_fn(feature_spec,
default_batch_size=None):
serialized_tf_example = array_ops.placeholder(
dtype=dtypes.string,
shape=[default_batch_size],
name='input_example_tensor')
receiver_tensors = {'examples': serialized_tf_example}
features = parsing_ops.parse_example(serialized_tf_example, feature_spec)
return ServingInputReceiver(features, receiver_tensors)
因此,在您的客户端中,您将准备一个包含一个或多个 Example
的请求(假设长度为 N
)。服务器将序列化示例视为将 "fed" 放入 input_example_tensor
占位符的字符串列表。形状(None
)动态填充为列表的大小(N
)。
然后 parse_example
op 解析占位符中的每个项目,并为每个外部维度为 N
的特征弹出一个张量。在你的情况下,你将有 x
和 shape=[N, 30, 30, 1].
(注意其他服务系统,如CloudML Engine,不对Example
对象进行操作,但原理是一样的)
我只想简要提供我找到的解决方案。因为我不想构建可扩展的生产级模型,而是 运行ner in python 的简单模型来在本地执行我的 CNN。
要导出我使用的模型,
input_size = 900
def serving_input_receiver_fn():
inputs = {"x": tf.placeholder(shape=[None, input_size], dtype=tf.float32)}
return tf.estimator.export.ServingInputReceiver(inputs, inputs)
model.export_savedmodel(
export_dir_base=model_dir,
serving_input_receiver_fn=serving_input_receiver_fn)
加载并 运行 它(不需要再次定义模型)我使用了 tensorflow 预测器 class。
from tensorflow.contrib import predictor
class TFRunner:
""" runs a frozen cnn graph """
def __init__(self,model_dir):
self.predictor = predictor.from_saved_model(model_dir)
def run(self, input_list):
""" runs the input list through the graph, returns output """
if len(input_list) > 1:
inputs = np.vstack(input_list)
predictions = self.predictor({"x": inputs})
elif len(input_list) == 1:
predictions = self.predictor({"x": input_list[0]})
else:
predictions = []
return predictions
我目前正在尝试熟悉 Tensorflow 库,但我有一个相当基本的问题困扰着我。
在为 MNIST 分类构建卷积神经网络时,我尝试使用自己的 model_fn。其中通常会出现以下行以重塑输入特征。
x = tf.reshape(x, shape=[-1, 28, 28, 1])
,-1 指的是输入批量大小。
因为我使用这个节点作为我的卷积层的输入,
x = tf.reshape(x, shape=[-1, 28, 28, 1])
conv1 = tf.layers.conv2d(x, 32, 5, activation=tf.nn.relu)
这是否意味着我所有网络层的大小都取决于批量大小?
我尝试在单个测试输入上冻结和 运行 图形,这只有在我提供 n=batch_size 测试图像时才有效。
你能给我一个提示,告诉我如何在预测时在任何输入批量大小上构建我的网络 运行 吗? 此外,我猜想在网络定义中使用 tf.reshape 节点(请参阅 cnn_layout 中的第一个节点)并不是服务的最佳输入。
我将附加我的网络层和 model_fn
def cnn_layout(features,reuse,is_training):
with tf.variable_scope('cnn',reuse=reuse):
# resize input to [batchsize,height,width,channel]
x = tf.reshape(features['x'], shape=[-1,30,30,1], name='input_placeholder')
# conv1, 32 filter, 5 kernel
conv1 = tf.layers.conv2d(x, 32, 5, activation=tf.nn.relu, name='conv1')
# pool1, 2 stride, 2 kernel
pool1 = tf.layers.max_pooling2d(conv1, 2, 2, name='pool1')
# conv2, 64 filter, 3 kernel
conv2 = tf.layers.conv2d(pool1, 64, 3, activation=tf.nn.relu, name='conv2')
# pool2, 2 stride, 2 kernel
pool2 = tf.layers.max_pooling2d(conv2, 2, 2, name='pool2')
# flatten pool2
flatten = tf.contrib.layers.flatten(pool2)
# fc1 with 1024 neurons
fc1 = tf.layers.dense(flatten, 1024, name='fc1')
# 75% dropout
drop = tf.layers.dropout(fc1, rate=0.75, training=is_training, name='dropout')
# output logits
output = tf.layers.dense(drop, 1, name='output_logits')
return output
def model_fn(features, labels, mode):
# setup two networks one for training one for prediction while sharing weights
logits_train = cnn_layout(features=features,reuse=False,is_training=True)
logits_test = cnn_layout(features=features,reuse=True,is_training=False)
# predictions
predictions = tf.round(tf.sigmoid(logits_test),name='predictions')
if mode == tf.estimator.ModeKeys.PREDICT:
return tf.estimator.EstimatorSpec(mode, predictions=predictions)
# define loss and optimizer
loss = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(logits=logits_train,labels=labels),name='loss')
optimizer = tf.train.AdamOptimizer(learning_rate=LEARNING_RATE, name='optimizer')
train = optimizer.minimize(loss, global_step=tf.train.get_global_step(),name='train')
# accuracy for evaluation
accuracy = tf.metrics.accuracy(labels=labels,predictions=predictions,name='accuracy')
# summarys for tensorboard
tf.summary.scalar('loss',loss)
# return training and evalution spec
return tf.estimator.EstimatorSpec(
mode=mode,
predictions=predictions,
loss=loss,
train_op=train,
eval_metric_ops={'accuracy':accuracy}
)
谢谢!
典型情况下features['x']
的rank已经是4了,外层维度实际batch size,所以没必要调整大小。
让我试着解释一下。
您还没有展示您的 serving_input_receiver_fn
,有几种方法可以做到这一点,尽管最终原则在所有方法中都是相似的。如果您使用的是 TensorFlow Serving,那么您可能会使用 build_parsing_serving_input_receiver_fn
。看看源码很有参考意义:
def build_parsing_serving_input_receiver_fn(feature_spec,
default_batch_size=None):
serialized_tf_example = array_ops.placeholder(
dtype=dtypes.string,
shape=[default_batch_size],
name='input_example_tensor')
receiver_tensors = {'examples': serialized_tf_example}
features = parsing_ops.parse_example(serialized_tf_example, feature_spec)
return ServingInputReceiver(features, receiver_tensors)
因此,在您的客户端中,您将准备一个包含一个或多个 Example
的请求(假设长度为 N
)。服务器将序列化示例视为将 "fed" 放入 input_example_tensor
占位符的字符串列表。形状(None
)动态填充为列表的大小(N
)。
然后 parse_example
op 解析占位符中的每个项目,并为每个外部维度为 N
的特征弹出一个张量。在你的情况下,你将有 x
和 shape=[N, 30, 30, 1].
(注意其他服务系统,如CloudML Engine,不对Example
对象进行操作,但原理是一样的)
我只想简要提供我找到的解决方案。因为我不想构建可扩展的生产级模型,而是 运行ner in python 的简单模型来在本地执行我的 CNN。
要导出我使用的模型,
input_size = 900
def serving_input_receiver_fn():
inputs = {"x": tf.placeholder(shape=[None, input_size], dtype=tf.float32)}
return tf.estimator.export.ServingInputReceiver(inputs, inputs)
model.export_savedmodel(
export_dir_base=model_dir,
serving_input_receiver_fn=serving_input_receiver_fn)
加载并 运行 它(不需要再次定义模型)我使用了 tensorflow 预测器 class。
from tensorflow.contrib import predictor
class TFRunner:
""" runs a frozen cnn graph """
def __init__(self,model_dir):
self.predictor = predictor.from_saved_model(model_dir)
def run(self, input_list):
""" runs the input list through the graph, returns output """
if len(input_list) > 1:
inputs = np.vstack(input_list)
predictions = self.predictor({"x": inputs})
elif len(input_list) == 1:
predictions = self.predictor({"x": input_list[0]})
else:
predictions = []
return predictions