2017-05-07 46 views
16

的各部分的計算梯度範數假設我有以下損失函數:複合損失函數

loss_a = tf.reduce_mean(my_loss_fn(model_output, targets)) 
loss_b = tf.reduce_mean(my_other_loss_fn(model_output, targets)) 
loss_final = loss_a + tf.multiply(alpha, loss_b) 

爲了顯現梯度WRT的範數來loss_final一個可以這樣做:

optimizer = tf.train.AdamOptimizer(learning_rate=0.001) 
grads_and_vars = optimizer.compute_gradients(loss_final) 
grads, _ = list(zip(*grads_and_vars)) 
norms = tf.global_norm(grads) 
gradnorm_s = tf.summary.scalar('gradient norm', norms) 
train_op = optimizer.apply_gradients(grads_and_vars, name='train_op') 

但是,我想分別繪製loss_aloss_b的梯度範圍。我怎樣才能在效率最高的方式做到這一點?是否需要分別撥打loss_aloss_b上的compute_gradients(..),然後將這兩個梯度相加,然後將它們傳遞給optimizer.apply_gradients(..)?我知道,由於求和規則,這在數學上是正確的,但它看起來有點麻煩,我也不知道如何正確實現梯度求和。另外,loss_final相當簡單,因爲它只是一個總和。如果loss_final更復雜,例如一個部門?

我使用的是Tensorflow 0.12。

回答

11

你說得對,結合漸變可能會變得混亂。相反,只需計算每個損失的梯度以及最終的損失。由於tensorflow在編譯前優化了directed acyclic graph (DAG),所以這不會導致重複工作。

例如:

import tensorflow as tf 

with tf.name_scope('inputs'): 
    W = tf.Variable(dtype=tf.float32, initial_value=tf.random_normal((4, 1), dtype=tf.float32), name='W') 
    x = tf.random_uniform((6, 4), dtype=tf.float32, name='x') 

with tf.name_scope('outputs'): 
    y = tf.matmul(x, W, name='y') 

def my_loss_fn(output, targets, name): 
    return tf.reduce_mean(tf.abs(output - targets), name=name) 

def my_other_loss_fn(output, targets, name): 
    return tf.sqrt(tf.reduce_mean((output - targets) ** 2), name=name) 

def get_tensors(loss_fn): 

    loss = loss_fn(y, targets, 'loss') 
    grads = tf.gradients(loss, W, name='gradients') 
    norm = tf.norm(grads, name='norm') 

    return loss, grads, norm 

targets = tf.random_uniform((6, 1)) 

with tf.name_scope('a'): 
    loss_a, grads_a, norm_a = get_tensors(my_loss_fn) 

with tf.name_scope('b'): 
    loss_b, grads_b, norm_b = get_tensors(my_loss_fn) 

with tf.name_scope('combined'): 
    loss = tf.add(loss_a, loss_b, name='loss') 
    grad = tf.gradients(loss, W, name='gradients') 

with tf.Session() as sess: 
    tf.global_variables_initializer().run(session=sess) 

    writer = tf.summary.FileWriter('./tensorboard_results', sess.graph) 
    res = sess.run([norm_a, norm_b, grad]) 

    print(*res, sep='\n') 

編輯:在回答你的評論...你可以check the DAG of a tensorflow model using tensorboard。我更新了代碼來存儲圖形。

在終端中運行tensorboard --logdir $PWD/tensorboard_results並導航到命令行上打印的URL(通常爲http://localhost:6006/)。然後點擊GRAPH選項卡查看DAG。您可以遞歸地擴展張量,操作符,命名空間以查看子圖來查看單個操作及其輸入。

tensorboard DAG example

+0

感謝您的回答。你怎麼知道這是通過張量流優化的,真的沒有重複的工作?我們可以驗證什麼優化適用於DAG嗎?我知道我可以進行一些測試,但是有沒有某種保證,這種可能的優化確實每次都應用,或者我們是否依靠「盡力而爲」的行爲? – kaufmanu

+0

@ kaufmanu更新了答案以顯示如何捕獲圖。 – Alex