Tensorflow tf.train.Saver 不保存所有变量

Posted

技术标签:

【中文标题】Tensorflow tf.train.Saver 不保存所有变量【英文标题】:Tensorflow tf.train.Saver not saving all variables 【发布时间】:2018-12-03 14:12:40 【问题描述】:

我认为 Tensorflow 保护程序会保存此处所述的所有变量

如果不向 tf.train.Saver() 传递任何参数,则保存程序 处理图中的所有变量。每个变量都保存在 创建变量时传递的名称。

https://www.tensorflow.org/programmers_guide/saved_model

但是,我下面代码中的变量 epochCount 似乎没有得到保存。此变量用于跟踪模型在数据上训练的总时期。

当我恢复一个图形时,它会重置为它的初始值设定项,而不是上次保存检查点时的值。

在我看来,它只是保存用于计算损失的变量。

这是我的代码。

这是我声明我的图表的地方:

graph = tf.Graph()

with graph.as_default(): 

  valid_examples = np.array(random.sample(range(1, valid_window), valid_size)) #put inside graph to get new words each time

  train_dataset = tf.placeholder(tf.int32, shape=[batch_size, cbow_window*2 ])
  train_labels = tf.placeholder(tf.int32, shape=[batch_size, 1])
  valid_dataset = tf.constant(valid_examples, dtype=tf.int32)
  valid_datasetSM = tf.constant(valid_examples, dtype=tf.int32)

  epochCount = tf.get_variable( 'epochCount', initializer= 0) #to store epoch count to total # of epochs are known

  embeddings = tf.get_variable( 'embeddings', 
    initializer= tf.random_uniform([vocabulary_size, embedding_size], -1.0, 1.0))

  softmax_weights = tf.get_variable( 'softmax_weights',
    initializer= tf.truncated_normal([vocabulary_size, embedding_size],
                         stddev=1.0 / math.sqrt(embedding_size)))
  softmax_biases = tf.get_variable('softmax_biases', 
    initializer= tf.zeros([vocabulary_size]),  trainable=False )

  embed = tf.nn.embedding_lookup(embeddings, train_dataset) #train data set is
  embed_reshaped = tf.reshape( embed, [batch_size*cbow_window*2, embedding_size] )
  segments= np.arange(batch_size).repeat(cbow_window*2)
  averaged_embeds = tf.segment_mean(embed_reshaped, segments, name=None)

  loss = tf.reduce_mean(
    tf.nn.sampled_softmax_loss(weights=softmax_weights, biases=softmax_biases, inputs=averaged_embeds,
                               labels=train_labels, num_sampled=num_sampled, num_classes=vocabulary_size))

  optimizer = tf.train.AdagradOptimizer(1.0).minimize(loss) #Original learning rate was 1.0

  norm = tf.sqrt(tf.reduce_sum(tf.square(embeddings), 1, keepdims=True))
  normalized_embeddings = embeddings / norm
  valid_embeddings = tf.nn.embedding_lookup(
    normalized_embeddings, valid_dataset) 
  similarity = tf.matmul(valid_embeddings, tf.transpose(normalized_embeddings)) 

  saver = tf.train.Saver()

如果我从检查点恢复图形,则嵌入和 softmax_biases 会恢复,但 epochCount 会重置为其初始化值。 (请注意,我没有调用 tf.global_variables_initializer().run() 行,这是在恢复检查点后错误地重置变量的常见原因)

这是运行图表的代码

num_steps = 1000001

with tf.Session(graph=graph) as session:

  saver.restore(session, './checkpointsBook2VecCbowWindow2Downloaded/bookVec.ckpt' )
  average_loss = 0
  saveIteration = 1
  for step in range(1, num_steps):

    batch_data, batch_labels = generate_batch(
      batch_size, cbow_window)
    feed_dict = train_dataset : batch_data, train_labels : batch_labels
    _, l = session.run([optimizer, loss], feed_dict=feed_dict) 

    if step % 20000 == 0:
      recEpoch_indexA =  epoch_index - recEpoch_indexA
      epochCount = tf.add(  epochCount, recEpoch_indexA, name=None )
      recEpoch_indexA = epoch_index

      save_path = saver.save(session, "checkpointsBook2VecCbowWindow2/bookVec.ckpt") 
      chptName = 'B2VCbowW2Embed256ckpt'+str(saveIteration)
      zipfolder(chptName, 'checkpointsBook2VecCbowWindow2')
      uploadModel.SetContentFile(chptName+".zip")
      uploadModel.Upload()

      print("Checkpoint uploaded to Google Drive")
      saveIteration += 1

这是我用来打印训练后保存在检查点中的所有变量的代码。我恢复图表并打印出所有保存的变量。

with tf.Session() as sess:
  saver = tf.train.import_meta_graph('./MODEL/bookVec.ckpt.meta')
  saver.restore(sess, './MODEL/bookVec.ckpt' )
  for v in tf.get_default_graph().get_collection("variables"):
    print('From variables collection ', v)

这是上面代码的输出

From variables collection  <tf.Variable 'embeddings:0' shape=(10001, 256) dtype=float32_ref>
From variables collection  <tf.Variable 'softmax_weights:0' shape=(10001, 256) dtype=float32_ref>
From variables collection  <tf.Variable 'softmax_biases:0' shape=(10001,) dtype=float32_ref>

如所见,epochCount 尚未保存。

【问题讨论】:

可能是因为它从未在图中实际使用过。您只在训练循环中使用它。顺便说一句,在会话启动后调用 TF ops(在本例中为 tf.add)被认为是不好的做法,尤其是在训练循环中。 哇,感谢您提供此信息! “顺便说一句,在会话启动后,尤其是在训练循环中调用 TF ops(在这种情况下为 tf.add)被认为是不好的做法”为什么会这样?另外,是否有更成熟的方法来跟踪 epoch 的总数? 请参阅我的回答 here 以了解 TF 问题(在您的情况下,它并不那么引人注目,因为您每个时期只执行一次)。至于如何跟踪时代,我将把它放在一个答案中。 【参考方案1】:

变量恢复为 0 的原因是因为它实际上从未更新(即它正确恢复)!您在会话期间通过tf.add 调用覆盖epochCount,它只返回操作,没有实际值。也就是说,变量(在 Tensorflow 意义上)是“孤立的”,将永远保持为 0。

您可以改用tf.assign 来更新变量。它可能看起来像这样:

# where you define the graph
epochCount = tf.get_variable( 'epochCount', initializer= 0)
update_epoch = tf.assign(epochCount, epochCount + 1)
...
# after you launched the session
for step in range(1, num_steps):
    if step % 20000 == 0:
        sess.run(update_epoch)

【讨论】:

谢谢!还有1个问题:这是否消除了您之前提到的关于“在会话启动后,特别是在训练循环中调用TF ops(在这种情况下为tf.add)”的问题,因为该操作是使用sess.run(update_epoch)调用的)?我的解释是,在我的原始代码中,我试图直接在 python 环境中更改 tensorflow 变量,而会话正在定义该变量的同一个图表上运行。在您的代码中,现在正在运行的同一会话中更改了变量。还是别的什么? 我对您问题的原始评论实际上有点误导,抱歉。一个问题是您只调用了tf.add 函数,它只“创建”了要添加的操作,但没有实际添加。通过使用sess.run,我们实际上进行了添加。但是,由于用其他东西覆盖了tf.Variable,您的原始公式也被破坏了。即使您要使用run tf.add,这也会用另一个值覆盖保存tf.VariablePython 变量,而不是更新 TF 变量。根据经验,如果要更新 TF 变量,请使用 tf.assign

以上是关于Tensorflow tf.train.Saver 不保存所有变量的主要内容,如果未能解决你的问题,请参考以下文章

机器学习与Tensorflow——tf.train.Saver()inception-v3的应用

tf.train.Saver()-tensorflow中模型的保存及读取

跟我学算法- tensorflow模型的保存与读取 tf.train.Saver()

tensorflow-训练检查点tf.train.Saver

图融合之加载子图:Tensorflow.contrib.slim与tf.train.Saver之坑

TensorFlow模型保存和提取方法