您好,登錄后才能下訂單哦!
本篇文章給大家分享的是有關TensorFlow中如何自定義梯度,小編覺得挺實用的,因此分享給大家學習,希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。
1. 重寫梯度法
重寫梯度法指的是通過tensorflow自帶的機制,將某個節點的梯度重寫(override),這種方法的適用性最廣。我們這里舉個例子[3].
符號函數的前向傳播采用的是階躍函數y=sign(x) y = \rm{sign}(x)y=sign(x),如下圖所示,我們知道階躍函數不是連續可導的,因此我們在反向傳播時,將其替代為一個可以連續求導的函數y=Htanh(x) y = \rm{Htanh(x)}y=Htanh(x),于是梯度就是大于1和小于-1時為0,在-1和1之間時是1。
使用重寫梯度的方法如下,主要是涉及到tf.RegisterGradient()和tf.get_default_graph().gradient_override_map(),前者注冊新的梯度,后者重寫圖中具有名字name='Sign'的操作節點的梯度,用在新注冊的QuantizeGrad替代。
#使用修飾器,建立梯度反向傳播函數。其中op.input包含輸入值、輸出值,grad包含上層傳來的梯度@tf.RegisterGradient("QuantizeGrad")def sign_grad(op, grad): input = op.inputs[0] # 取出當前的輸入 cond = (input>=-1)&(input<=1) # 大于1或者小于-1的值的位置 zeros = tf.zeros_like(grad) # 定義出0矩陣用于掩膜 return tf.where(cond, grad, zeros) # 將大于1或者小于-1的上一層的梯度置為0#使用with上下文管理器覆蓋原始的sign梯度函數def binary(input): x = input with tf.get_default_graph().gradient_override_map({"Sign":'QuantizeGrad'}): #重寫梯度 x = tf.sign(x) return x#使用x = binary(x)
其中的def sign_grad(op, grad):是注冊新的梯度的套路,其中的op是當前操作的輸入值/張量等,而grad指的是從反向而言的上一層的梯度。
通常來說,在tensorflow中自定義梯度,函數tf.identity()是很重要的,其API手冊如下:
tf.identity( input, name=None)
其會返回一個形狀和內容都和輸入完全一樣的輸出,但是你可以自定義其反向傳播時的梯度,因此在梯度反轉等操作中特別有用。
這里再舉個反向梯度[2]的例子,也就是梯度為 而不是
import tensorflow as tfx1 = tf.Variable(1)x2 = tf.Variable(3)x3 = tf.Variable(6)@tf.RegisterGradient('CustomGrad')def CustomGrad(op, grad):# tf.Print(grad) return -gradg = tf.get_default_graph()oo = x1+x2with g.gradient_override_map({"Identity": "CustomGrad"}): output = tf.identity(oo)grad_1 = tf.gradients(output, oo)with tf.Session() as sess: sess.run(tf.global_variables_initializer()) print(sess.run(grad_1))
因為-grad,所以這里的梯度輸出是[-1]而不是[1]。有一個我們需要注意的是,在自定義函數def CustomGrad()中,返回的值得是一個張量,而不能返回一個參數,比如return 0,這樣會報錯,如:
AttributeError: 'int' object has no attribute 'name'
顯然,這是因為tensorflow的內部操作需要取返回值的名字而int類型沒有名字。
PS:def CustomGrad()這個函數簽名是隨便你取的。
2. stop_gradient法
對于自定義梯度,還有一種比較簡潔的操作,就是利用tf.stop_gradient()函數,我們看下例子[1]:
t = g(x)y = t + tf.stop_gradient(f(x) - t)
這里,我們本來的前向傳遞函數是f(x),但是想要在反向時傳遞的函數是g(x),因為在前向過程中,tf.stop_gradient()不起作用,因此+t和-t抵消掉了,只剩下f(x)前向傳遞;而在反向過程中,因為tf.stop_gradient()的作用,使得f(x)-t的梯度變為了0,從而只剩下g(x)在反向傳遞。
我們看下完整的例子:
import tensorflow as tfx1 = tf.Variable(1)x2 = tf.Variable(3)x3 = tf.Variable(6)f = x1+x2*x3t = -fy1 = t + tf.stop_gradient(f-t)y2 = fgrad_1 = tf.gradients(y1, x1)grad_2 = tf.gradients(y2, x1)with tf.Session(config=config) as sess: sess.run(tf.global_variables_initializer()) print(sess.run(grad_1)) print(sess.run(grad_2))
第一個輸出為[-1],第二個輸出為[1],顯然也實現了梯度的反轉。
以上就是TensorFlow中如何自定義梯度,小編相信有部分知識點可能是我們日常工作會見到或用到的。希望你能通過這篇文章學到更多知識。更多詳情敬請關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。