天天看點

[程式設計經驗] Tensorflow中的共享變量機制小結

今天說一下tensorflow的變量共享機制,首先為什麼會有變量共享機制? 這個還是要扯一下生成對抗網絡GAN,我們知道GAN由兩個網絡組成,一個是生成器網絡G,一個是判别器網絡D。G的任務是由輸入的隐變量z生成一張圖像G(z)出來,D的任務是區分G(z)和訓練資料中的真實的圖像(real images)。是以這裡D的輸入就有2個,但是這兩個輸入是共享D網絡的參數的,簡單說,也就是權重和偏置。而TensorFlow的變量共享機制,正好可以解決這個問題。但是我現在不能确定,TF的這個機制是不是因為GAN的提出才有的,還是本身就存在。

是以變量共享的目的就是為了在對網絡第二次使用的時候,可以使用同一套模型參數。TF中是由Variable_scope來實作的,下面我通過幾個栗子,徹底弄明白到底該怎麼使用,以及使用中會出現的錯誤。栗子來源于文檔,然後我寫了不同的情況,希望能幫到你。

# - * - coding:utf-8 - * -
import tensorflow as tf
import os

os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3'


def fc_variable():
    v1 = tf.Variable(
        initial_value=tf.random_normal(
            shape=[2, 3], mean=0., stddev=1.),
        dtype=tf.float32,
        name='variable_1')
    print v1
    print "- v1 - * " * 5
    return v1

"""
<tf.Variable 'variable_1:0' shape=(2, 3) dtype=float32_ref>
- v1 - * - v1 - * - v1 - * - v1 - * - v1 - * 
"""

def variable_value(variables):
    with tf.Session() as sess:
        sess.run(tf.global_variables_initializer())
        # 如果沒有這句會報錯,是以tf在調用變量之前主要
        # 先初始化
        """
        tensorflow.python.framework.errors_impl.
        FailedPreconditionError: Attempting to use
         uninitialized value variable_1
        """
        print '- * - value: - * - ' * 3
        print sess.run(variables)
        """
        [[ 0.00556329  0.20311342 -0.79569227]
         [ 0.1700473   0.9499892  -0.46801034]]
        """


def fc_variable_scope():
    with tf.variable_scope("foo"):
        v = tf.get_variable("v", [1])
        print v.name
        w = tf.get_variable("w", [1])
        print w.name

    with tf.variable_scope("foo", reuse=True):
        v1 = tf.get_variable("v")
        print v1.name

"""
foo/v:0
foo/w:0
foo/v:0
"""
# 解釋:
# 這裡說明v1和v的相同的,還有這裡用的是
# get_variable定義的變量,這個和Variable
# 定義變量的差別是,如果變量存在get_variable
# 會獲得他的值,如果不存在則建立變量


def fc_variable_scope_v2():
    with tf.variable_scope("foo"):
        v = tf.get_variable("v", [1])
        print v.name
        w = tf.get_variable("w", [1])
        print w.name

    with tf.variable_scope("foo", reuse=False):
        v1 = tf.get_variable("v")
        print v1.name


"""
ValueError: Variable foo/v already exists, disallowed. 
Did you mean to set reuse=True in VarScope? Originally
 defined at:
"""
# 解釋:
# 當reuse為False的時候由于v1在'fool'這個scope裡面,
# 是以和v的name是一樣的,而reuse為False,變量命名就起了沖突。


def fc_variable_scope_v3():
    with tf.variable_scope("foo"):
        v = tf.get_variable("v", [1])
        print v.name
        w = tf.get_variable("w", [1])
        print w.name

    with tf.variable_scope("foo", reuse=True):
        v1 = tf.get_variable("u", [1])
        print v1.name


"""
ValueError: Variable foo/u does not exist, 
or was not created with tf.get_variable().
 Did you mean to set reuse=None in VarScope?
"""
# 解釋:
# 當reuse為True時時候,而這裡定義了新變量u,
# 之前不存在,這樣也無法reuse。


def fc_variable_scope_v4():
    with tf.variable_scope("foo"):
        v = tf.get_variable("v", [1])
        print v.name
        w = tf.get_variable("w", [1])
        print w.name

    with tf.variable_scope("foo", reuse=False):
        v1 = tf.get_variable("u")
        print v1.name

"""
ValueError: Shape of a new variable (foo/u)
 must be fully defined, but instead was <unknown>.

"""
# 解釋:
# 這裡reuse為Flase,但是定義新變量的時候,
# 必須define fully變量,也就是要指定變量
# 的shape或者初始值等。


def fc_variable_scope_v5():
    with tf.variable_scope("foo"):
        v = tf.get_variable("v", [1])
        print dir(v)
        print v.name
        w = tf.get_variable("w", [1])
        print w.name

    with tf.variable_scope("foo", reuse=False):
        v1 = tf.get_variable("u", [1])
        print v1.name


"""
foo/v:0
foo/w:0
foo/u:0
"""
# 這樣就沒錯了


def fc_variable_scope_v6():
    with tf.variable_scope("foo"):
        v1 = tf.Variable(tf.random_normal(
            shape=[2, 3], mean=0., stddev=1.),
            dtype=tf.float32, name='v1')
        print v1.name
        v2 = tf.get_variable("v2", [1])
        print v2.name

    with tf.variable_scope("foo", reuse=True):
        v3 = tf.get_variable('v2')
        print v3.name
        v4 = tf.get_variable('v1')
        print v4.name


"""
foo/v1:0
foo/v2:0
foo/v2:0

ValueError: Variable foo/v1 does not exist, or
 was not created with tf.get_variable(). Did 
 you mean to set reuse=None in VarScope?

"""

# 解釋:
# 這裡雖然reuse為True,但是v1是由Variable定義的,
# 不能被get。


def compare_name_and_variable_scope():
    with tf.name_scope("hello") as ns:
        arr1 = tf.get_variable(
            "arr1", shape=[2, 10], dtype=tf.float32)
        print (arr1.name)

    print " - * -" * 5
    with tf.variable_scope("hello") as vs:
        arr1 = tf.get_variable(
            "arr1", shape=[2, 10], dtype=tf.float32)
        print (arr1.name)

"""
arr1:0
 - * - - * - - * - - * - - * -
hello/arr1:0
"""
#解釋:
# 這裡除了name_scope和variable_scope不同,
# 其他都相同,但是從他們的name,也能看出來差別了。

if __name__ == "__main__":
    fc_variable_scope_v6()
    # # 需要測試那個函數,直接寫在這裡。           

複制

簡單總結一下,今天的内容主要是變量定義的兩種方法,Variable個get_variable,還有變量的範圍以及reuse是什麼鬼。通過幾個栗子,應該明白了。

明天要說的是用TensorFlow實作Kmeans聚類,歡迎關注~

============End============