1. 程式人生 > >tensorflow使用的幾個點

tensorflow使用的幾個點

一、同一模型下裝載不同的權重引數

1.使用完一個模型後,在後邊加上程式碼tf.reset_default_graph()用於清除預設圖形堆疊並重置全域性預設圖形

2.對每個模型建立多個計算圖(Graph)

tf中可以定義多個計算圖,不同計算圖上的張量和運算是相互獨立的,不會共享。計算圖可以用來隔離張量和計算,同時提供了管理張量和計算的機制。計算圖可以通過Graph.device函式來指定執行計算的裝置,為TensorFlow充分利用GPU/CPU提供了機制。

二、 共享變數
當訓練複雜模型時,經常需要共享大量的變數,但我們經常會遇到以下問題:如建立一個簡單地影象濾波器模型,假如只是用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)

模型有4個不同的變數:conv1_weights, conv1_biases, conv2_weights, conv2_biases。

當我們想兩次呼叫模型時(模型引數相同),不會出現錯誤,但這兩次呼叫的模型會建立兩套不同的引數集。

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

而且當模型更加複雜時,我們會需要建立更多的變數,當代碼更改時,呼叫者需要建立更多或更少的不同變數。

為了實現共享變數,tensorflow採用了兩個函式:

tf.variable_scope(<scope_name>):  管理傳遞給tf.get_variable()的names的名稱空間
tf.get_variable(<name>, <shape>, <initializer>): 建立或返回一個給定名字的變數

實現過程的程式碼:

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)

在單獨的函式中建立卷積的程式碼,使用tf.get_variable()函式建立兩個變數“weights”和“biases”,在呼叫的過程中希望同一輸入資料進行不同卷積時建立不同的變數名稱。而不同資料輸入(多樣本訓練)獲取相同的引數,因此採用tf.variable_scope()函式為每個卷積建立各自的變數名稱空間。程式碼如下:

	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])

輸出的變數名稱帶有各自的名稱空間:conv1/weights,conv1/biases;conv2/weights,conv2/biases;
但是當我們直接兩次呼叫該方法時(對兩個測試集用同一個模型進行測試時,依次直接向模型送入資料時)就會產生以下錯誤:

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

這是因為tf.get_variable() 會檢查已存在的變數是不是意外地共享。為了避免該錯誤並且可以使用同一模型和引數,我們需要設定reuse_variables()

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

對於reuse_variables()的使用有兩種狀態:False和True,該過程是通過tf.get_variable()的檢查來工作的
1.當False 時,作用域就是為建立新變數所設定的。這種情況下會通過 tf.get_Variable() 所提供的形狀和資料型別來重新建立變數. 建立變數的全稱將會由當前變數作用域名 + 所提供的名字所組成 , 並且還會檢查來確保沒有任何變數使用這個全稱 . 如果這個全稱已經有一個變數使用了,那麼方法將會丟擲
ValueError 錯誤 .# Raises ValueError(… conv1/weights already exists …)------如上邊情況
情況 2 :當True 時,作用域是為重用變數所設定,這種情況下,呼叫就會搜尋一個已經存在的變數,他的全稱和當前變數的作用域名+ 所提供的名字是否相等。如果不存在相應的變數,就會丟擲 ValueError 錯誤。如果變數找到了,就返回這個變數。
tf.variable_scope(<scope_name>) 變數作用域的主方法帶有一個名稱,它將會作為字首用於變數名 , 並且帶有一個重用標籤來區分以上的兩種情況。當前變數作用域可以用 tf.get_variable_scope() 進行檢索並且 reuse 標籤可以通過呼叫 tf.get_variable_scope().reuse_variables() 設定為 True。

參考部落格: