张量流:在完成图形后分配权重

tensorflow: assigning weights after finalizing graph

下面的解决方案

如果你只是对解决这个问题感兴趣,可以跳到下面我的回答。

原题

我正在使用 tensorflow 进行强化学习。一组代理并行使用该模型,一个中央实体根据收集的数据对其进行训练。

我在这里发现:tensorflow 会话是线程安全的。所以我干脆让预测和更新运行并行。

但现在我想更改设置。我现在需要保留两个模型,而不是在一个模型上进行更新和训练。一个用于预测,第二个用于训练。在一些训练步骤之后,第二个的权重被复制到第一个。下面是 keras 中的一个最小示例。对于multiprocessing,建议finalize graph,但是我不能copy weights:

# the usual imports
import numpy as np
import tensorflow as tf

from keras.models import *
from keras.layers import *

# set up the first model
i = Input(shape=(10,))
b = Dense(1)(i)
prediction_model = Model(inputs=i, outputs=b)

# set up the second model
i2 = Input(shape=(10,))
b2 = Dense(1)(i2)
training_model = Model(inputs=i2, outputs=b2)

# look at this code, to check if the weights are the same
# here the output is different
prediction_model.predict(np.ones((1, 10)))
training_model.predict(np.ones((1, 10)))

# now to use them in multiprocessing, the following is necessary
prediction_model._make_predict_function()
training_model._make_predict_function()
sess = tf.Session()
sess.run(tf.global_variables_initializer())
default_graph = tf.get_default_graph()

# the following line is the critical part
# if this is uncommented, the two options below both fail
# default_graph.finalize()

# option 1, use keras methods to update the weights
prediction_model.set_weights(training_model.get_weights())

# option 2, use tensorflow to update the weights
update_ops = [tf.assign(to_var, from_var) for to_var, from_var in
              zip(prediction_model.trainable_weights, training_model.trainable_weights)]
sess.run(update_ops)

# now the predictions are the same
prediction_model.predict(np.ones((1, 10)))
training_model.predict(np.ones((1, 10)))

根据上面的问题,建议敲定图。如果未最终确定,可能会出现内存泄漏(!?),因此这似乎是一个强烈的建议。

但是如果我最终确定了,我就不能再更新权重了。 令我困惑的是:可以训练网络,因此允许更改权重。赋值在我看来就像权重被覆盖了,为什么这与应用优化器步骤不同?

简而言之,我的问题是为最终图的权重赋值。如果这个赋值是在 finalization 之后完成的,tensorflow 会抱怨图不能再被改变。

我很困惑为什么这是被禁止的。毕竟,允许通过反向传播改变权重。

但问题与改变权重无关。 Keras set_weights() 令人困惑,因为它看起来好像权重被简单地覆盖了(就像在反向传播中一样)。实际上,在幕后,添加并执行了赋值操作。这些新操作代表图中的变化,而这种变化是被禁止的。

所以解决方案是在最终确定图形之前设置赋值操作。您必须重新排序代码:

# the usual imports
import numpy as np
import tensorflow as tf

from keras.models import *
from keras.layers import *

# set up the first model
i = Input(shape=(10,))
b = Dense(1)(i)
prediction_model = Model(inputs=i, outputs=b)

# set up the second model
i2 = Input(shape=(10,))
b2 = Dense(1)(i2)
training_model = Model(inputs=i2, outputs=b2)

# set up operations to move weights from training to prediction
update_ops = [tf.assign(to_var, from_var) for to_var, from_var in
              zip(prediction_model.trainable_weights, training_model.trainable_weights)]

# now to use them in multiprocessing, the following is necessary
prediction_model._make_predict_function()
training_model._make_predict_function()
sess = tf.Session()
sess.run(tf.global_variables_initializer())
default_graph = tf.get_default_graph()

default_graph.finalize()

# this can be executed now
sess.run(update_ops)

# now the predictions are the same
prediction_model.predict(np.ones((1, 10)))
training_model.predict(np.ones((1, 10)))