如何計算一個變數相對于線性組合中使用的另一個變數的梯度?以下代碼在 TensorFlow Eager 模式下執行。
更多地挖掘舊問題,出現了類似的問題。但是,目前尚不清楚如何解決此問題。另一個相關的問題是this one,但這里相同的變數被重用和TensorFlow v1。
我還在這個問題中讀到tf.assign(v1?)不支持漸變,并且那里提供了一個潛在的解決方案。但是,我會將它應用于神經網路的內部模型權重,但我不知道如何在實踐中應用這種張量方法。
a = tf.Variable(1.0, name='a')
b = tf.Variable(2.0, name='b')
c = tf.Variable(3.0, name='c')
with tf.GradientTape() as tape:
c.assign(a b)
loss = tf.reduce_mean(c**2)
print(tape.gradient(loss, b)) # prints None
# or another attempt
with tf.GradientTape(watch_accessed_variables=False) as tape:
tape.watch([b,c])
c.assign(a b)
loss = tf.reduce_mean(c**2)
print(tape.gradient(loss, b)) # also outputs None
# Working, but c is a variable in my use case
with tf.GradientTape() as tape:
c = a b
loss = tf.reduce_mean(c**2)
print(tape.gradient(loss, b)) # Works
擴大:
import tensorflow as tf
a = [tf.Variable(1.0, name='a'), tf.Variable(4.0, name='aa')]
b = [tf.Variable(2.0, name='b'), tf.Variable(9.0, name='bb')]
c = [tf.Variable(3.0, name='c'), tf.Variable(0.0, name='cc')]
x = tf.Variable(0.01)
with tf.GradientTape(persistent=True) as tape:
c_ = tf.nest.map_structure(lambda _a, _b: (1-x)*_a x*_b, a, b)
tf.nest.map_structure(lambda x, y: x.assign(y), c, c_)
loss = tf.norm(c) # scalar
# This works as expected
print(tape.gradient(loss,c,output_gradients=tape.gradient(c_,b)))
# [<tf.Tensor: shape=(), dtype=float32, numpy=0.0024197185>, <tf.Tensor: shape=(), dtype=float32, numpy=0.009702832>]
# Here I would expect a 1D gradient to use the Gradient Descent method?
print(tape.gradient(loss,c,output_gradients=tape.gradient(c_,x)))
# [<tf.Tensor: shape=(), dtype=float32, numpy=1.4518311>, <tf.Tensor: shape=(), dtype=float32, numpy=5.8216996>]
# Example what I'd like to achieve;
with tf.GradientTape() as tape:
c_ = tf.nest.map_structure(lambda _a, _b: (1-x)*_a x*_b, a, b)
loss = tf.norm(c_) # scalar
print(tape.gradient(loss,x))
# tf.Tensor(5.0933886, shape=(), dtype=float32)
uj5u.com熱心網友回復:
也許你可以嘗試如下:
import tensorflow as tf
a = tf.Variable(1.0, name='a')
b = tf.Variable(2.0, name='b')
c = tf.Variable(3.0, name='c')
with tf.GradientTape(persistent=True) as tape:
c_ = a 2*b
c.assign(c_)
loss = tf.reduce_mean(c**2)
print(tape.gradient(loss,c,output_gradients=tape.gradient(c_,b)))
# tf.Tensor(20.0, shape=(), dtype=float32)
PSoutput_gradients是一個tf.GradientTape.gradient隱藏在角落里很少被發現的引數,可以用來手動構建級聯微分。
對于擴展:
import tensorflow as tf
a = [tf.Variable(1.0, name='a'), tf.Variable(4.0, name='aa')]
b = [tf.Variable(2.0, name='b'), tf.Variable(9.0, name='bb')]
c = [tf.Variable(3.0, name='c'), tf.Variable(0.0, name='cc')]
x = tf.Variable(0.0, name='x')
with tf.GradientTape(persistent=True) as tape:
c_ = tf.nest.map_structure(lambda _a, _b: (1-x)*_a x*_b, a, b)
tf.nest.map_structure(lambda x, y: x.assign(y), c, c_)
loss = tf.norm(c) # scalar
print(tape.gradient(loss,c[0],output_gradients=tape.gradient(c_[0],x)) \
tape.gradient(loss,c[1],output_gradients=tape.gradient(c_[1],x)))
# tf.Tensor(5.0932484, shape=(), dtype=float32)
解釋:
因為 tf.GradientTape 是基于matrix differential theory, 但會在.gradient(). 例如關于 推導 a vector,a scalar在矩陣理論中,我們會得到一個vector推導,但是在 中tf.GradientTape,areduce_sum like將被應用然后得到一個求和的標量。
這里tape.gradient(loss,c,output_gradients=tape.gradient(c_,x))
實際上做了:
tape.gradient(loss,c[0],output_gradients=tape.gradient(c_,x)[0]),
tape.gradient(loss,c[1],output_gradients=tape.gradient(c_,x)[1])
but
tape.gradient(c_,x)[0] != tape.gradient(c_[0],x)
tape.gradient(c_,x)[1] != tape.gradient(c_[1],x)
所以tape.gradient(loss,c,output_gradients=tape.gradient(c_,x))違背了我們的初衷。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/493870.html
