TENSORFLOW變量作用域(VARIABLE SCOPE)
舉例說(shuō)明
TensorFlow中的變量一般就是模型的參數(shù)。當(dāng)模型復(fù)雜的時(shí)候共享變量會(huì)無(wú)比復(fù)雜。
官網(wǎng)給了一個(gè)case,當(dāng)創(chuàng)建兩層卷積的過(guò)濾器時(shí),每輸入一次圖片就會(huì)創(chuàng)建一次過(guò)濾器對(duì)應(yīng)的變量,但是我們希望所有圖片都共享同一過(guò)濾器變量,一共有4個(gè)變量:conv1_weights,conv1_biases,conv2_weights, and conv2_biases。
通常的做法是將這些變量設(shè)置為全局變量。但是存在的問(wèn)題是打破封裝性,這些變量必須文檔化被其他代碼文件引用,一旦代碼變化,調(diào)用方也可能需要變化。
還有一種保證封裝性的方式是將模型封裝成類(lèi)。
不過(guò)TensorFlow提供了Variable Scope 這種獨(dú)特的機(jī)制來(lái)共享變量。這個(gè)機(jī)制涉及兩個(gè)主要函數(shù):
tf.get_variable(<name>, <shape>, <initializer>) 創(chuàng)建或返回給定名稱(chēng)的變量 tf.variable_scope(<scope_name>) 管理傳給get_variable()的變量名稱(chēng)的作用域
在下面的代碼中,通過(guò)tf.get_variable()創(chuàng)建了名稱(chēng)分別為weights和biases的兩個(gè)變量。
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_initializer(0.0)) conv = tf.nn.conv2d(input, weights, strides=[1, 1, 1, 1], padding='SAME') return tf.nn.relu(conv + biases)
但是我們需要兩個(gè)卷積層,這時(shí)可以通過(guò)tf.variable_scope()指定作用域進(jìn)行區(qū)分,如with tf.variable_scope("conv1")這行代碼指定了第一個(gè)卷積層作用域?yàn)閏onv1,
在這個(gè)作用域下有兩個(gè)變量weights和biases。
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])
最后在image_filters這個(gè)作用域重復(fù)使用第一張圖片輸入時(shí)創(chuàng)建的變量,調(diào)用函數(shù)reuse_variables(),代碼如下:
with tf.variable_scope("image_filters") as scope: result1 = my_image_filter(image1) scope.reuse_variables() result2 = my_image_filter(image2)
tf.get_variable()工作機(jī)制
tf.get_variable()工作機(jī)制是這樣的:
當(dāng)tf.get_variable_scope().reuse == False,調(diào)用該函數(shù)會(huì)創(chuàng)建新的變量
with tf.variable_scope("foo"): v = tf.get_variable("v", [1]) assert v.name == "foo/v:0"
當(dāng)tf.get_variable_scope().reuse == True,調(diào)用該函數(shù)會(huì)重用已經(jīng)創(chuàng)建的變量
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 is v
變量都是通過(guò)作用域/變量名來(lái)標(biāo)識(shí),后面會(huì)看到作用域可以像文件路徑一樣嵌套。
tf.variable_scope理解
tf.variable_scope()用來(lái)指定變量的作用域,作為變量名的前綴,支持嵌套,如下:
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)前環(huán)境的作用域可以通過(guò)函數(shù)tf.get_variable_scope()獲取,并且reuse標(biāo)志可以通過(guò)調(diào)用reuse_variables()設(shè)置為T(mén)rue,這個(gè)非常有用,如下
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 is v
作用域中的resuse默認(rèn)是False,調(diào)用函數(shù)reuse_variables()可設(shè)置為T(mén)rue,一旦設(shè)置為T(mén)rue,就不能返回到False,并且該作用域的子空間reuse都是True。如果不想重用變量,那么可以退回到上層作用域,相當(dāng)于exit當(dāng)前作用域,如
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
一個(gè)作用域可以作為另一個(gè)新的作用域的參數(shù),如:
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 is v assert w1 is w
不管作用域如何嵌套,當(dāng)使用with tf.variable_scope()打開(kāi)一個(gè)已經(jīng)存在的作用域時(shí),就會(huì)跳轉(zhuǎn)到這個(gè)作用域。
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.
variable scope的Initializers可以創(chuàng)遞給子空間和tf.get_variable()函數(shù),除非中間有函數(shù)改變,否則不變。
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.
算子(ops)會(huì)受變量作用域(variable scope)影響,相當(dāng)于隱式地打開(kāi)了同名的名稱(chēng)作用域(name scope),如+這個(gè)算子的名稱(chēng)為foo/add
with tf.variable_scope("foo"): x = 1.0 + tf.get_variable("v", [1]) assert x.op.name == "foo/add"
除了變量作用域(variable scope),還可以顯式打開(kāi)名稱(chēng)作用域(name scope),名稱(chēng)作用域僅僅影響算子的名稱(chēng),不影響變量的名稱(chēng)。另外如果tf.variable_scope()傳入字符參數(shù),創(chuàng)建變量作用域的同時(shí)會(huì)隱式創(chuàng)建同名的名稱(chēng)作用域。如下面的例子,變量v的作用域是foo,而算子x的算子變?yōu)閒oo/bar,因?yàn)橛须[式創(chuàng)建名稱(chēng)作用域foo
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"
注意: 如果tf.variable_scope()傳入的不是字符串而是scope對(duì)象,則不會(huì)隱式創(chuàng)建同名的名稱(chēng)作用域。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
通過(guò)案例解析python鴨子類(lèi)型相關(guān)原理
這篇文章主要介紹了通過(guò)案例解析python鴨子類(lèi)型相關(guān)原理,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-10-10利用python爬取斗魚(yú)app中照片方法實(shí)例
最近在學(xué)習(xí)python,通過(guò)實(shí)踐是學(xué)習(xí)的一個(gè)好辦法,下面這篇文章就來(lái)給大家介紹了關(guān)于利用python爬取斗魚(yú)app中照片的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友下面來(lái)一起看看吧。2017-12-12Python設(shè)計(jì)模式之工廠模式簡(jiǎn)單示例
這篇文章主要介紹了Python設(shè)計(jì)模式之工廠模式,簡(jiǎn)單說(shuō)明了工廠模式的原理,并結(jié)合實(shí)例形式給出了Python實(shí)現(xiàn)工廠模式的具體操作技巧,需要的朋友可以參考下2018-01-01淺談python 讀excel數(shù)值為浮點(diǎn)型的問(wèn)題
今天小編就為大家分享一篇淺談python 讀excel數(shù)值為浮點(diǎn)型的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-12-12python?pip安裝庫(kù)下載源更換(清華源、阿里源、中科大源、豆瓣源)
為了提高Python包的下載速度和穩(wěn)定性,可以配置國(guó)內(nèi)的鏡像源,如清華源、阿里源、中科大源和豆瓣源,設(shè)置方法簡(jiǎn)單,只需更改pip的配置文件或使用命令行即可,需要的朋友可以參考下2024-10-10