Skip to main content
 首页 » 编程设计

python之拥有具有不同权重的同一 TensorFlow 网络的 2 个版本,并从另一个版本更新一个

2024年08月16日34lyj

我正在尝试实现 DeepMind 用来训练 AI 玩 Atari 游戏的深度 q 学习程序。他们使用并在多个教程中提到的功能之一是拥有两个版本的神经网络;一个在你通过小批量训练数据循环时更新(称为 Q),另一个在你这样做时调用以帮助构建训练数据(Q')。然后定期(比如每 10k 个数据点)将 Q' 中的权重设置为 Q 的当前值。

我的问题是在 TensorFlow 中执行此操作的最佳方法是什么?既要同时存储两个相同架构的网络,又要定期更新彼此的权重?我当前的网络如下所示,目前仅使用默认图形和交互式 session 。

sess = tf.InteractiveSession() 
 
x = tf.placeholder(tf.float32, shape=[None, height, width, m]) 
y_ = tf.placeholder(tf.float32, shape=[None, env.action_space.n]) 
 
W_conv1 = weight_variable([8, 8, 4, 32]) 
b_conv1 = bias_variable([32]) 
h_conv1 = tf.nn.relu(conv2d(x, W_conv1, 4, 4) + b_conv1) 
 
W_conv2 = weight_variable([4, 4, 32, 64]) 
b_conv2 = bias_variable([64]) 
h_conv2 = tf.nn.relu(conv2d(h_conv1, W_conv2, 2, 2) + b_conv2) 
 
W_conv3 = weight_variable([3, 3, 64, 64]) 
b_conv3 = bias_variable([64]) 
h_conv3 = tf.nn.relu(conv2d(h_conv2, W_conv3, 1, 1) + b_conv3) 
 
# Flattern conv to dense 
flat_input_size = 14*10*64 
h_conv3_reshape = tf.reshape(h_conv3, [-1, flat_input_size]) 
 
# Dense layers 
W_fc1 = weight_variable([flat_input_size, 512]) 
b_fc1 = bias_variable([512]) 
h_fc1 = tf.nn.relu(tf.matmul(h_conv3_reshape, W_fc1) + b_fc1) 
 
W_fc2 = weight_variable([512, env.action_space.n]) 
b_fc2 = bias_variable([env.action_space.n]) 
y_conv = tf.matmul(h_fc1, W_fc2) + b_fc2 
 
accuracy = tf.squared_difference(y_, y_conv) 
loss = tf.reduce_mean(accuracy) 
optimizer = tf.train.AdamOptimizer(0.0001).minimize(loss) 
 
tf.global_variables_initializer().run() 

请您参考如下方法:

这里有一种安排方式。首先,您为每个网络制作一个单独的图表,以便在不同的 session 中并行运行它们:

graph1 = tf.Graph() 
with graph1.as_default(): 
  model1 = build_model() 
 
graph2 = tf.Graph() 
with graph2.as_default(): 
  model2 = build_model() 

... 其中 build_model() 定义了所有占位符、变量和训练操作。两个模型都应该对变量使用相同的命名,这将使它们能够轻松地交换状态。

每个网络都可以使用其他网络的快照作为目标进行训练(最新的或以前最好的,由您决定)。定期地,每个网络通过 tf.Saver() 保存到磁盘,并使用一个网络的权重恢复。例如,此代码会将第二个网络的权重加载到第一个图中:

with tf.Session(graph=graph1) as sess: 
  saver = tf.train.import_meta_graph('/tmp/model-2/network.meta') 
  saver.restore(sess, '/tmp/model-2/network') 
  ... continue training 

模型是这样保存的:

with tf.Session(graph=graph1) as sess: 
  ... do some training 
  save_path = saver.save(sess, '/tmp/model-1/network') 

有关保存和恢复的更多信息,请参阅 this question .您可以在同一个 session 中执行此操作或开始一个新 session 。

事实上,您甚至可以尝试为两个网络使用磁盘上的相同位置,以便从同一个文件保存和恢复。但这将强制您拥有最新的快照,而以前的方法更灵活。

您需要注意的一件事是 session 的使用:为 graph1 创建的 session 只能评估来自 graph1 的张量和操作。示例:

def build_model(): 
  x = tf.placeholder(tf.float32, name='x') 
  y = tf.placeholder(tf.float32, name='y') 
  z = x + y 
  return x, y, z 
 
graph1 = tf.Graph() 
with graph1.as_default(): 
  x1, y1 ,z1 = build_model() 
 
graph2 = tf.Graph() 
with graph2.as_default(): 
  x2, y2, z2 = build_model() 
 
with tf.Session(graph=graph1) as sess1: 
  with tf.Session(graph=graph2) as sess2: 
    # Good 
    print(sess1.run(z1, feed_dict={x1: 1, y1: 2}))  # 3.0 
    print(sess2.run(z2, feed_dict={x2: 3, y2: 1}))  # 4.0 
 
    # BAD! Wrong graph 
    # print(sess1.run(z2, feed_dict={x2: 3, y2: 1}))