1. 程式人生 > >tensorflow中的共享變量(sharing variables)

tensorflow中的共享變量(sharing variables)

圖像濾波 ted div 復雜 模型 當我 管理 重構 har

為什麽要使用共享變量? 當訓練復雜模型時,可能經常需要共享大量的變量。例如,使用測試集來測試已訓練好的模型性能表現時,需要共享已訓練好模型的變量,如全連接層的權值。 而且我們還會遇到以下問題: 比如,我們創建了一個簡單的圖像濾波器模型。如果只使用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, and conv2_biases

當我們想再次使用這個模型的時候出現問題了:在兩個不同的圖片image1和image2上應用以上模型,當然,我們想這兩張圖片被相同參數的同一個濾波器處理。如果我們兩次調用my_image_filter()的話,則會創建兩個不同的變量集,每個變量集中各4個變量。

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

共享變量的一種常見方法是在單獨的代碼段中創建它們,並將它們傳遞給使用它們的函數。 例如通過使用字典:

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

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

但是像上面這樣在代碼外面創建變量很方便, 破壞了封裝

  • 構建圖形的代碼必須記錄要創建的變量的名稱,類型和形狀。
  • 代碼更改時,調用者可能必須創建更多或更少或不同的變量。

解決問題的一種方法是使用類創建一個模型,其中類負責管理所需的變量。 一個較簡便的解決方案是,使用TensorFlow提供variable scope機制,通過這個機制,可以讓我們在構建模型時輕松共享命名變量。

如何實現? tensorflow中的變量共享是通過 tf.variab_scope() 和 tf.get_variable() 來實現的
  • tf.variable_scope(<scope_name>): 管理傳遞給tf.get_variable()的names的命名空間
  • tf.get_variable(<name>, <shape>, <initializer>): 創建或返回一個給定名字的變量
為了看下tf.get_variable()如何解決以上問題,我們在一個單獨的函數裏重構創建一個卷積的代碼,並命名為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_initializer(0.0))
    conv = tf.nn.conv2d(input, weights,
        strides=[1, 1, 1, 1], padding=SAME)
    return tf.nn.relu(conv + biases)

此這個函數使用“weights”和“biases”命名變量。 我們希望將它用於conv1和conv2,但變量需要具有不同的名稱。 這就是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])

現在,我們來看下兩次調用my_image_filter()會怎樣:

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

如你所見,tf.get_variable() 會檢查已存在的變量是不是意外地共享。如果你想共享它們,你需要通過如下設置reuse_variables()來指定它。

tensorflow中的共享變量(sharing variables)