tensorflow中的共享變量(sharing variables)
阿新 • • 發佈:2017-07-04
圖像濾波 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>): 創建或返回一個給定名字的變量
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)