在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 教程/ 人工智能/ 共享變量<a class="md-anchor" id="AUTOGENERATED-sharing-variables"></
BibTex 引用<a class="md-anchor" id="AUTOGENERATED-bibtex-citation"
術(shù)語表
自定義數(shù)據(jù)讀取 <a class="md-anchor" id="AUTOGENERATED-custom-data-reade
使用 GPUs <a class="md-anchor" id="AUTOGENERATED-using-gpus"></a>
Vector Representations of Words <a class="md-anchor" id="AUTOGEN
TensorFlow 個(gè)人學(xué)習(xí)心得
共享變量<a class="md-anchor" id="AUTOGENERATED-sharing-variables"></
應(yīng)用實(shí)例 <a class="md-anchor" id="AUTOGENERATED-example-uses"></a>
其他資源 <a class="md-anchor" id="AUTOGENERATED-additional-resources
偏微分方程 <a class="md-anchor" id="AUTOGENERATED-partial-differentia
TensorBoard:可視化學(xué)習(xí) <a class="md-anchor" id="AUTOGENERATED-tensorb
TensorFlow運(yùn)作方式入門 <a class="md-anchor" id="AUTOGENERATED-tensorfl
常見問題 <a class="md-anchor" id="AUTOGENERATED-frequently-asked-que
MNIST機(jī)器學(xué)習(xí)入門 <a class="md-anchor" id="AUTOGENERATED-mnist-for-ml-
曼德布洛特(Mandelbrot)集合 <a class="md-anchor" id="AUTOGENERATED-mande
變量:創(chuàng)建、初始化、保存和加載
TensorBoard: 圖表可視化 <a class="md-anchor" id="AUTOGENERATED-tensor
簡介 <a class="md-anchor" id="AUTOGENERATED-introduction"></a>
張量的階、形狀、數(shù)據(jù)類型<a class="md-anchor" id="AUTOGENERATED-tensor-ranks-
線程和隊(duì)列 <a class="md-anchor" id="AUTOGENERATED-threading-and-queue
下載與安裝 <a class="md-anchor" id="AUTOGENERATED-download-and-setup"
常見問題匯總
綜述
綜述 Overview
TensorFlow 相關(guān)資源
數(shù)據(jù)讀取 <a class="md-anchor" id="AUTOGENERATED-reading-data"></a>
遞歸神經(jīng)網(wǎng)絡(luò) <a class="md-anchor" id="AUTOGENERATED-recurrent-neural-n
深入MNIST <a class="md-anchor" id="AUTOGENERATED-deep-mnist-for-ex
增加一個(gè)新 Op <a class="md-anchor" id="AUTOGENERATED-adding-a-new-op"
卷積神經(jīng)網(wǎng)絡(luò) <a class="md-anchor" id="AUTOGENERATED-convolutional-neur
基本使用 <a class="md-anchor" id="AUTOGENERATED-basic-usage"></a>
MNIST 數(shù)據(jù)下載 <a class="md-anchor" id="AUTOGENERATED-mnist-data-dow

共享變量<a class="md-anchor" id="AUTOGENERATED-sharing-variables"></

你可以在怎么使用變量中所描述的方式來創(chuàng)建,初始化,保存及加載單一的變量.但是當(dāng)創(chuàng)建復(fù)雜的模塊時(shí),通常你需要共享大量變量集并且如果你還想在同一個(gè)地方初始化這所有的變量,我們又該怎么做呢.本教程就是演示如何使用tf.variable_scope()tf.get_variable()兩個(gè)方法來實(shí)現(xiàn)這一點(diǎn).

問題

假設(shè)你為圖片過濾器創(chuàng)建了一個(gè)簡單的模塊,和我們的卷積神經(jīng)網(wǎng)絡(luò)教程模塊相似,但是這里包括兩個(gè)卷積(為了簡化實(shí)例這里只有兩個(gè)).如果你僅使用tf.Variable變量,那么你的模塊就如怎么使用變量里面所解釋的是一樣的模塊.

def my_image_filter(input_images):
    conv1_weights = tf.Variable(tf.random_normal([5, 5, 32, 32]),
        name="conv1_weights")
    conv1_biases = tf.Variable(tf.zeros([32]), name="conv1_biases")
    conv1 = tf.nn.conv2d(input_images, conv1_weights,
        strides=[1, 1, 1, 1], padding='SAME')
    relu1 = tf.nn.relu(conv1 + conv1_biases)

    conv2_weights = tf.Variable(tf.random_normal([5, 5, 32, 32]),
        name="conv2_weights")
    conv2_biases = tf.Variable(tf.zeros([32]), name="conv2_biases")
    conv2 = tf.nn.conv2d(relu1, conv2_weights,
        strides=[1, 1, 1, 1], padding='SAME')
    return tf.nn.relu(conv2 + conv2_biases)

你很容易想到,模塊集很快就比一個(gè)模塊變得更為復(fù)雜,僅在這里我們就有了四個(gè)不同的變量:conv1_weights,conv1_biases, conv2_weights, 和conv2_biases. 當(dāng)我們想重用這個(gè)模塊時(shí)問題還在增多.假設(shè)你想把你的圖片過濾器運(yùn)用到兩張不同的圖片, image1image2.你想通過擁有同一個(gè)參數(shù)的同一個(gè)過濾器來過濾兩張圖片,你可以調(diào)用my_image_filter()兩次,但是這會(huì)產(chǎn)生兩組變量.

# First call creates one set of variables.
result1 = my_image_filter(image1)
# Another set is created in the second call.
result2 = my_image_filter(image2)

通常共享變量的方法就是在單獨(dú)的代碼塊中來創(chuàng)建他們并且通過使用他們的函數(shù).如使用字典的例子:

variables_dict = {
    "conv1_weights": tf.Variable(tf.random_normal([5, 5, 32, 32]),
        name="conv1_weights")
    "conv1_biases": tf.Variable(tf.zeros([32]), name="conv1_biases")
    ... etc. ...
}

def my_image_filter(input_images, variables_dict):
    conv1 = tf.nn.conv2d(input_images, variables_dict["conv1_weights"],
        strides=[1, 1, 1, 1], padding='SAME')
    relu1 = tf.nn.relu(conv1 + variables_dict["conv1_biases"])

    conv2 = tf.nn.conv2d(relu1, variables_dict["conv2_weights"],
        strides=[1, 1, 1, 1], padding='SAME')
    return tf.nn.relu(conv2 + variables_dict["conv2_biases"])

# The 2 calls to my_image_filter() now use the same variables
result1 = my_image_filter(image1, variables_dict)
result2 = my_image_filter(image2, variables_dict)

雖然使用上面的方式創(chuàng)建變量是很方便的,但是在這個(gè)模塊代碼之外卻破壞了其封裝性:

  • 在構(gòu)建試圖的代碼中標(biāo)明變量的名字,類型,形狀來創(chuàng)建.
  • 當(dāng)代碼改變了,調(diào)用的地方也許就會(huì)產(chǎn)生或多或少或不同類型的變量.

解決此類問題的方法之一就是使用類來創(chuàng)建模塊,在需要的地方使用類來小心地管理他們需要的變量. 一個(gè)更高明的做法,不用調(diào)用類,而是利用TensorFlow 提供了變量作用域 機(jī)制,當(dāng)構(gòu)建一個(gè)視圖時(shí),很容易就可以共享命名過的變量.

變量作用域?qū)嵗?a class="md-anchor" id="AUTOGENERATED-variable-scope-example">

變量作用域機(jī)制在TensorFlow中主要由兩部分組成:

  • tf.get_variable(<name>, <shape>, <initializer>): 通過所給的名字創(chuàng)建或是返回一個(gè)變量.
  • tf.variable_scope(<scope_name>): 通過 tf.get_variable()為變量名指定命名空間.

方法 tf.get_variable() 用來獲取或創(chuàng)建一個(gè)變量,而不是直接調(diào)用tf.Variable.它采用的不是像`tf.Variable這樣直接獲取值來初始化的方法.一個(gè)初始化就是一個(gè)方法,創(chuàng)建其形狀并且為這個(gè)形狀提供一個(gè)張量.這里有一些在TensorFlow中使用的初始化變量:

  • tf.constant_initializer(value) 初始化一切所提供的值,
  • tf.random_uniform_initializer(a, b)從a到b均勻初始化,
  • tf.random_normal_initializer(mean, stddev) 用所給平均值和標(biāo)準(zhǔn)差初始化均勻分布.

為了了解tf.get_variable()怎么解決前面所討論的問題,讓我們?cè)趩为?dú)的方法里面創(chuàng)建一個(gè)卷積來重構(gòu)一下代碼,命名為conv_relu

def conv_relu(input, kernel_shape, bias_shape):
    # Create variable named "weights".
    weights = tf.get_variable("weights", kernel_shape,
        initializer=tf.random_normal_initializer())
    # Create variable named "biases".
    biases = tf.get_variable("biases", bias_shape,
        initializer=tf.constant_intializer(0.0))
    conv = tf.nn.conv2d(input, weights,
        strides=[1, 1, 1, 1], padding='SAME')
    return tf.nn.relu(conv + biases)

這個(gè)方法中用了"weights""biases"兩個(gè)簡稱.而我們更偏向于用conv1conv2這兩個(gè)變量的寫法,但是不同的變量需要不同的名字.這就是tf.variable_scope() 變量起作用的地方.他為變量指定了相應(yīng)的命名空間.

def my_image_filter(input_images):
    with tf.variable_scope("conv1"):
        # Variables created here will be named "conv1/weights", "conv1/biases".
        relu1 = conv_relu(input_images, [5, 5, 32, 32], [32])
    with tf.variable_scope("conv2"):
        # Variables created here will be named "conv2/weights", "conv2/biases".
        return conv_relu(relu1, [5, 5, 32, 32], [32])

現(xiàn)在,讓我們看看當(dāng)我們調(diào)用 my_image_filter() 兩次時(shí)究竟會(huì)發(fā)生了什么.

result1 = my_image_filter(image1)
result2 = my_image_filter(image2)
# Raises ValueError(... conv1/weights already exists ...)

就像你看見的一樣,tf.get_variable()會(huì)檢測(cè)已經(jīng)存在的變量是否已經(jīng)共享.如果你想共享他們,你需要像下面使用的一樣,通過reuse_variables()這個(gè)方法來指定.

with tf.variable_scope("image_filters") as scope:
    result1 = my_image_filter(image1)
    scope.reuse_variables()
    result2 = my_image_filter(image2)

用這種方式來共享變量是非常好的,輕量級(jí)而且安全.

變量作用域是怎么工作的?

理解 tf.get_variable()

為了理解變量作用域,首先完全理解tf.get_variable()是怎么工作的是很有必要的. 通常我們就是這樣調(diào)用tf.get_variable 的.

v = tf.get_variable(name, shape, dtype, initializer)

此調(diào)用做了有關(guān)作用域的兩件事中的其中之一,方法調(diào)入.總的有兩種情況.

  • 情況1:當(dāng)tf.get_variable_scope().reuse == False時(shí),作用域就是為創(chuàng)建新變量所設(shè)置的.

這種情況下,v將通過tf.Variable所提供的形狀和數(shù)據(jù)類型來重新創(chuàng)建.創(chuàng)建變量的全稱將會(huì)由當(dāng)前變量作用域名+所提供的名字所組成,并且還會(huì)檢查來確保沒有任何變量使用這個(gè)全稱.如果這個(gè)全稱已經(jīng)有一個(gè)變量使用了,那么方法將會(huì)拋出ValueError錯(cuò)誤.如果一個(gè)變量被創(chuàng)建,他將會(huì)用initializer(shape)進(jìn)行初始化.比如:

with tf.variable_scope("foo"):
    v = tf.get_variable("v", [1])
assert v.name == "foo/v:0"
  • 情況1:當(dāng)tf.get_variable_scope().reuse == True時(shí),作用域是為重用變量所設(shè)置

這種情況下,調(diào)用就會(huì)搜索一個(gè)已經(jīng)存在的變量,他的全稱和當(dāng)前變量的作用域名+所提供的名字是否相等.如果不存在相應(yīng)的變量,就會(huì)拋出ValueError 錯(cuò)誤.如果變量找到了,就返回這個(gè)變量.如下:

with tf.variable_scope("foo"):
    v = tf.get_variable("v", [1])
with tf.variable_scope("foo", reuse=True):
    v1 = tf.get_variable("v", [1])
assert v1 == v

tf.variable_scope() 基礎(chǔ)

知道tf.get_variable()是怎么工作的,使得理解變量作用域變得很容易.變量作用域的主方法帶有一個(gè)名稱,它將會(huì)作為前綴用于變量名,并且?guī)в幸粋€(gè)重用標(biāo)簽來區(qū)分以上的兩種情況.嵌套的作用域附加名字所用的規(guī)則和文件目錄的規(guī)則很類似:

with tf.variable_scope("foo"):
    with tf.variable_scope("bar"):
        v = tf.get_variable("v", [1])
assert v.name == "foo/bar/v:0"

當(dāng)前變量作用域可以用tf.get_variable_scope()進(jìn)行檢索并且reuse 標(biāo)簽可以通過調(diào)用tf.get_variable_scope().reuse_variables()設(shè)置為True .

with tf.variable_scope("foo"):
    v = tf.get_variable("v", [1])
    tf.get_variable_scope().reuse_variables()
    v1 = tf.get_variable("v", [1])
assert v1 == v

注意你不能設(shè)置reuse標(biāo)簽為False.其中的原因就是允許改寫創(chuàng)建模塊的方法.想一下你前面寫得方法my_image_filter(inputs).有人在變量作用域內(nèi)調(diào)用reuse=True 是希望所有內(nèi)部變量都被重用.如果允許在方法體內(nèi)強(qiáng)制執(zhí)行reuse=False,將會(huì)打破內(nèi)部結(jié)構(gòu)并且用這種方法使得很難再共享參數(shù).

即使你不能直接設(shè)置 reuseFalse ,但是你可以輸入一個(gè)重用變量作用域,然后就釋放掉,就成為非重用的變量.當(dāng)打開一個(gè)變量作用域時(shí),使用reuse=True 作為參數(shù)是可以的.但也要注意,同一個(gè)原因,reuse 參數(shù)是不可繼承.所以當(dāng)你打開一個(gè)重用變量作用域,那么所有的子作用域也將會(huì)被重用.

with tf.variable_scope("root"):
    # At start, the scope is not reusing.
    assert tf.get_variable_scope().reuse == False
    with tf.variable_scope("foo"):
        # Opened a sub-scope, still not reusing.
        assert tf.get_variable_scope().reuse == False
    with tf.variable_scope("foo", reuse=True):
        # Explicitly opened a reusing scope.
        assert tf.get_variable_scope().reuse == True
        with tf.variable_scope("bar"):
            # Now sub-scope inherits the reuse flag.
            assert tf.get_variable_scope().reuse == True
    # Exited the reusing scope, back to a non-reusing one.
    assert tf.get_variable_scope().reuse == False

獲取變量作用域

在上面的所有例子中,我們共享參數(shù)只因?yàn)樗麄兊拿质且恢碌?,那是因?yàn)槲覀冮_啟一個(gè)變量作用域重用時(shí)剛好用了同一個(gè)字符串.在更復(fù)雜的情況,他可以通過變量作用域?qū)ο髞硎褂?,而不是通過依賴于右邊的名字來使用.為此,變量作用域可以被獲取并使用,而不是僅作為當(dāng)開啟一個(gè)新的變量作用域的名字.

with tf.variable_scope("foo") as foo_scope:
    v = tf.get_variable("v", [1])
with tf.variable_scope(foo_scope)
    w = tf.get_variable("w", [1])
with tf.variable_scope(foo_scope, reuse=True)
    v1 = tf.get_variable("v", [1])
    w1 = tf.get_variable("w", [1])
assert v1 == v
assert w1 == w

當(dāng)開啟一個(gè)變量作用域,使用一個(gè)預(yù)先已經(jīng)存在的作用域時(shí),我們會(huì)跳過當(dāng)前變量作用域的前綴而直接成為一個(gè)完全不同的作用域.這就是我們做得完全獨(dú)立的地方.

with tf.variable_scope("foo") as foo_scope:
    assert foo_scope.name == "foo"
with tf.variable_scope("bar")
    with tf.variable_scope("baz") as other_scope:
        assert other_scope.name == "bar/baz"
        with tf.variable_scope(foo_scope) as foo_scope2:
            assert foo_scope2.name == "foo"  # Not changed.

變量作用域中的初始化器

使用tf.get_variable()允許你重寫方法來創(chuàng)建或者重用變量,并且可以被外部透明調(diào)用.但是如果我們想改變創(chuàng)建變量的初始化器那要怎么做呢?是否我們需要為所有的創(chuàng)建變量方法傳遞一個(gè)額外的參數(shù)呢?那在大多數(shù)情況下,當(dāng)我們想在一個(gè)地方并且為所有的方法的所有的變量設(shè)置一個(gè)默認(rèn)初始化器,那又改怎么做呢?為了解決這些問題,變量作用域可以攜帶一個(gè)默認(rèn)的初始化器.他可以被子作用域繼承并傳遞給tf.get_variable() 調(diào)用.但是如果其他初始化器被明確地指定,那么他將會(huì)被重寫.

with tf.variable_scope("foo", initializer=tf.constant_initializer(0.4)):
    v = tf.get_variable("v", [1])
    assert v.eval() == 0.4  # Default initializer as set above.
    w = tf.get_variable("w", [1], initializer=tf.constant_initializer(0.3)):
    assert w.eval() == 0.3  # Specific initializer overrides the default.
    with tf.variable_scope("bar"):
        v = tf.get_variable("v", [1])
        assert v.eval() == 0.4  # Inherited default initializer.
    with tf.variable_scope("baz", initializer=tf.constant_initializer(0.2)):
        v = tf.get_variable("v", [1])
        assert v.eval() == 0.2  # Changed default initializer.

tf.variable_scope()中ops的名稱

我們討論 tf.variable_scope 怎么處理變量的名字.但是又是如何在作用域中影響到 其他ops的名字的呢?ops在一個(gè)變量作用域的內(nèi)部創(chuàng)建,那么他應(yīng)該是共享他的名字,這是很自然的想法.出于這樣的原因,當(dāng)我們用with tf.variable_scope("name")時(shí),這就間接地開啟了一個(gè)tf.name_scope("name").比如:

with tf.variable_scope("foo"):
    x = 1.0 + tf.get_variable("v", [1])
assert x.op.name == "foo/add"

名稱作用域可以被開啟并添加到一個(gè)變量作用域中,然后他們只會(huì)影響到ops的名稱,而不會(huì)影響到變量.

with tf.variable_scope("foo"):
    with tf.name_scope("bar"):
        v = tf.get_variable("v", [1])
        x = 1.0 + v
assert v.name == "foo/v:0"
assert x.op.name == "foo/bar/add"

當(dāng)用一個(gè)引用對(duì)象而不是一個(gè)字符串去開啟一個(gè)變量作用域時(shí),我們就不會(huì)為ops改變當(dāng)前的名稱作用域.

使用實(shí)例

這里有一些指向怎么使用變量作用域的文件.特別是,他被大量用于 時(shí)間遞歸神經(jīng)網(wǎng)絡(luò)sequence-to-sequence模型,

File What's in it?
models/image/cifar10.py 圖像中檢測(cè)對(duì)象的模型.
models/rnn/rnn_cell.py 時(shí)間遞歸神經(jīng)網(wǎng)絡(luò)的元方法集.
models/rnn/seq2seq.py 為創(chuàng)建sequence-to-sequence模型的方法集.

原文:Sharing Variables 翻譯:nb312校對(duì):Wiki