我的问题与此处提出的问题非常相似:https://github.com/tensorflow/hub/issues/269。但是这些问题仍然没有答案,因此我将在这里提出。重现步骤:
tensorflow 1.14.0 tensorflow-hub 0.5.0 Python 3.7.4 Windows 10
以下是示例笔记本,其中出现了问题: https://colab.research.google.com/drive/1PKUyoQRP3othu6cu7v7N7yn8K2pjkuKP
module_spec = hub.load_module_spec('https://tfhub.dev/google/imagenet/inception_v3/feature_vector/3')
height, width = hub.get_expected_image_size(module_spec)
with tf.Graph().as_default() as graph:
resized_input_tensor = tf.compat.v1.placeholder(tf.float32, [None, height, width, 3])
module = hub.Module(module_spec, trainable=True, tags={"train"})
bottleneck_tensor = module(inputs=dict(images=resized_input_tensor, batch_norm_momentum=0.997),signature="image_feature_vector_with_bn_hparams")
将此时创建的所有Trainable / Model / Global变量保存到单独的“基本模型”列表中(3个列表) 变量示例: base_model trainable_variables vars :188,['module / InceptionV3 / Conv2d_1a_3x3 / weights:0','module / InceptionV3 / Conv2d_1a_3x3 / BatchNorm / beta:0'。 base_model model_variables vars :188,['module / InceptionV3 / Conv2d_1a_3x3 / BatchNorm / moving_mean:0','module / InceptionV3 / Conv2d_1a_3x3 / BatchNorm / moving_variance:0 base_model变量vars :0,[]#空列表
在模型顶部添加自定义分类层:
batch_size, previous_tensor_size = bottleneck_tensor.get_shape().as_list()
ground_truth_input = tf.compat.v1.placeholder(tf.int64, [batch_size], name='GroundTruthInput')
initial_value = tf.random.truncated_normal([previous_tensor_size, class_count], stddev=0.001)
layer_weights = tf.Variable(initial_value, name='final_weights')
layer_biases = tf.Variable(tf.zeros([class_count]), name='final_biases')
logits = tf.matmul(hidden_layer, layer_weights) + layer_biases
final_tensor = tf.nn.softmax(logits, name=final_tensor_name)
同样,将所有新添加的变量名放入3个新的“自定义”列表中:
自定义trainable_variables变量:2,['final_weights:0','final_biases:0'] 自定义model_variables变量:0,[] 自定义变量vars:0,[]
添加列车运行。由于基本模型具有批量标准化功能,因此我们必须关心更新操作。这就是为什么我使用tf.contrib.training.create_train_op:
cross_entropy_all = tf.compat.v1.losses.sparse_softmax_cross_entropy(labels=ground_truth_input, logits=logits)
optimizer = tf.compat.v1.train.AdamOptimizer()
#the update ops are set to the contents of the tf.GraphKeys.UPDATE_OPS collection.
#variables to train will default to all tf.compat.v1.trainable_variables().
train_step = tf.contrib.training.create_train_op(cross_entropy_mean, optimizer)
现在进行常规培训:
with tf.compat.v1.Session(graph=graph) as sess:
# Initialize all weights: for the module to their pretrained values,
# and for the newly added retraining layer to random initial values.
init = tf.compat.v1.global_variables_initializer()
sess.run(init)
#dump the checkssum for all the variables lists collected during graph building
for i in range(1000):
# Get a batch of input resized images values, calculated fresh
(train_data, train_ground_truth) = get_random_batch_data(sess, image_lists....)
#dump the checksum for all the variables lists collected during graph building
# Feed the input placeholder and ground truth into the graph, and run a training
# step.
sess.run([train_step], feed_dict = {
resized_input_tensor: train_data,
ground_truth_input: train_ground_truth})
#dump now again the checksum for all the variables lists collected during graph building
因此,在每个训练步骤之后,仅针对两个变量列表(自定义可训练和全局优化器)更改校验和:
base_model trainable_variables, 2697202.0, cf4682249fc1f48e9a346149f84e503d unchanged
base_model model_variables,
2936996.0, 6f995f5f0f032604a49a96ceec576cf7 unchanged
base_model variables, 0, d41d8cd98f00b204e9800998ecf8427e unchanged
custom trainable_variables, -0.7915199408307672, 889c333a56b9496d412eacdcbeb3bef1 **changed**
custom model_variables, 0, d41d8cd98f00b204e9800998ecf8427e unchanged
custom variables, 0, d41d8cd98f00b204e9800998ecf8427e unchanged
optimizer trainable_variables, 0, d41d8cd98f00b204e9800998ecf8427e unchanged
optimizer model_variables, 0, d41d8cd98f00b204e9800998ecf8427e unchanged
optimizer variables,
5580902.81437762, d2cb2d4b253a1c12452f560eea35ac42 **changed**
所以,问题是,为什么基本模型的可训练变量没有更改? 它们是BatchNorm / moving_mean,BatchNorm / moving_variance,Conv2d_1a_3x3 /权重,在培训期间绝对应该对其进行更新。更重要的是,moving_variance也应该更改,因为UPDATE_OPS作为tf.contrib.training.create_train_op调用内的火车步骤的依赖项包括在内。我检查了UPDATE_OPS列表,它包含有效的值,例如: 更新操作: tf.Operation'module_apply_image_feature_vector_with_bn_hparams / InceptionV3 / InceptionV3 / Conv2d_1a_3x3 / BatchNorm / AssignMovingAvg / AssignSubVariableOp'type = AssignSubVariableOp>,
答案 0 :(得分:0)
好的,在对问题进行深入调试后,我发现问题出在以下方面: 仅从全局变量列表中获取变量并使用eval()获取其值是不够的:它将返回一些值,但它不是当前值(至少这是对于dtype = resource的导入模型的变量所发生的情况)。
要计算当前值,我们必须首先使用变量 value()或变量 read_value()并执行 eval()< / strong>(用于返回的“值”张量)。
这可以解决问题。