Tensorflow:如何在范围之间交换变量,并在另一个范围内设置变量

时间:2017-01-31 04:27:08

标签: python scope tensorflow

我有不同的范围,并且它们具有相同名称但具有不同值的变量。我想在范围之间交换这些变量的值。 示例:

with tf.variable_scope('sc1'):
   a1 = tf.Variable(0, name='test_var1')
   b1 = tf.Variable(1, name='test_var2')
with tf.variable_scope('sc2'):
   a2 = tf.Variable(2, name='test_var1')
   b2 = tf.Variable(3, name='test_var2')   

我想将a2设置为0,将b2设置为1,将a1设置为2,将b1设置为3。

我正在考虑使用tf.get_collection_ref获取所需的变量,但我无法看到如何更改变量的范围,因此我可能需要更改变量的值。在这种情况下,我需要在临时变量中存储一个值,然后删除该临时变量。 我不确定它会起作用,这似乎太复杂了。 有简单的方法吗?

UPD1:此外,我还需要在另一个集合中设置一个集合中的所有变量。我认为这是类似的问题。 例如,在上面的代码中,将a2设置为等于0,将b2设置为1。

UPD2 :此代码不起作用:

with tf.variable_scope('sc1'):
    a1 = tf.get_variable(name='test_var1', initializer=0.)
    b1 = tf.Variable(0, name='test_var2')

with tf.variable_scope('sc2'):
    a2 = tf.get_variable(name='test_var1', initializer=1.)
    b2 = tf.Variable(1, name='test_var2')


def swap_tf_scopes(col1, col2):
    col1_dict = {}
    col2_dict = {}
    for curr_var in col1:
        curr_var_name = curr_var.name.split('/')[-1]
        col1_dict[curr_var_name] = curr_var

    for curr_var in col2:
        curr_var_name = curr_var.name.split('/')[-1]
        curr_col1_var = col1_dict[curr_var_name]
        tmp_t = tf.identity(curr_col1_var)
        assign1 = curr_col1_var.assign(curr_var)
        assign2 = curr_var.assign(tmp_t)
    return [assign1, assign2]


col1 = tf.get_collection(tf.GraphKeys.VARIABLES, scope='sc1')
col2 = tf.get_collection(tf.GraphKeys.VARIABLES, scope='sc2')

tf_ops_t = swap_tf_collections(col1, col2)
sess = tf.Session()
sess.run(tf.initialize_all_variables())
sess.run(tf_ops_t)
print sess.run(col1) #prints [0.0, 1] but I expect [1.0, 1]
print sess.run(col2) #prints [1.0, 1] but I expect [0.0, 0]

2 个答案:

答案 0 :(得分:0)

我想交换相对较小的范围,因此交换的临时范围不是问题。我做了工作原型。它看起来并不酷,实际上很丑陋,但却有效。

def swap_tf_collections(col1, col2, tmp_col):
    col2_dict = {}
    for i in xrange(len(col1)):
        curr_var_name = col2[i].name.split('/')[-1]
        col2_dict[curr_var_name] = col2[i]

    col1_dict = {}
    for i in xrange(len(col1)):
        curr_var_name = col1[i].name.split('/')[-1]
        col1_dict[curr_var_name] = col1[i]

    # set values from second scope to tmp_dict 
    tmp_dict = {}
    assigns_arr = []
    for i in xrange(len(tmp_col)):
        curr_var_name = tmp_col[i].name.split('/')[-1]
        tmp_dict[curr_var_name] = tmp_col[i]
        assign0 = tmp_dict[curr_var_name].assign(col2_dict[curr_var_name])
        assigns_arr.append(assign0)

    for i in xrange(len(col2)):
        curr_var_name = col2[i].name.split('/')[-1]
        curr_col1_var = col1_dict[curr_var_name]
        tmp_t = tmp_dict[curr_var_name]
        with tf.control_dependencies(assigns_arr):
            assign1 = col2[i].assign(curr_col1_var)
            assigns_arr.append(assign1)
            with tf.control_dependencies(assigns_arr):
                assign2 = curr_col1_var.assign(tmp_t)
                assigns_arr.append(assign2)
    return assigns_arr



# first scope
with tf.variable_scope('sc1'):
    a1 = tf.get_variable(name='test_var1', initializer=0.)
    b1 = tf.Variable(0, name='test_var2')
# second scope    
with tf.variable_scope('sc2'):
    a2 = tf.get_variable(name='test_var1', initializer=1.)
    b2 = tf.Variable(1, name='test_var2')

# getting them as collections
col1 = tf.get_collection(tf.GraphKeys.VARIABLES, scope='sc1')
col2 = tf.get_collection(tf.GraphKeys.VARIABLES, scope='sc2')

# creating temporary scope. It MUST have same variables names as our scopes but it doesn't have to have same data as second scope
with tf.variable_scope('tmp_scope_for_scopes_swap'):
    for i in xrange(len(col2)):
        col2_var = col2[i]
        col2_var_name = col2[i].name.split('/')[-1].split(':')[0]
        var = tf.Variable(col2_var.initialized_value(), name=col2_var_name)
        tmp_col.append(var)

# exec
sess = tf.Session()
with sess.as_default():
    sess.run(tf.initialize_all_variables())
    tf_ops_t = swap_tf_collections(col1, col2, tmp_col) 
    sess.run(tf_ops_t)  # swap will not work without this line

col1_dict = {i.name:i for i in col1}
col2_dict = {i.name:i for i in col2}
print sess.run(col1_dict)
print sess.run(col2_dict)

请注意,我使用依赖控制!没有它,功能结果将是不确定的。

尽管函数名称是swap_tf_collections,但我认为它不适用于任意集合(公平地说我甚至对范围有疑问)。

答案 1 :(得分:0)

import tensorflow as tf
import numpy as np

with tf.variable_scope('sc1'):
    a1 = tf.get_variable(name='test_var1', initializer=0.)
    b1 = tf.Variable(0, name='test_var2')

with tf.variable_scope('sc2'):
    a2 = tf.get_variable(name='test_var1', initializer=1.)
    b2 = tf.Variable(1, name='test_var2')


def swap_tf_scopes(col1, col2):
    col1_dict = {}
    for curr_var in col1:
        curr_var_name = curr_var.name.split('/')[-1]
        col1_dict[curr_var_name] = curr_var
    for curr_var in col2:
        curr_var_name = curr_var.name.split('/')[-1]
        curr_col1_var = col1_dict[curr_var_name]
        tmp_t =tf.Variable(curr_col1_var.initialized_value()) 
        sess.run(tmp_t.initializer)
        sess.run(tf.assign(curr_col1_var,curr_var))
        sess.run(tf.assign(curr_var,tmp_t))

col1 = tf.get_collection(tf.GraphKeys.VARIABLES, scope='sc1')
col2 = tf.get_collection(tf.GraphKeys.VARIABLES, scope='sc2')
sess = tf.Session()
sess.run(tf.initialize_all_variables())
swap_tf_scopes(col1, col2)
print(sess.run(col1)) 
print(sess.run(col2))

您好!尝试这个。我想它将起作用。