3.4tensorflow2.x自動求導原理函數詳解


自己開發了一個股票智能分析軟件,功能很強大,需要的點擊下面的鏈接獲取:

https://www.cnblogs.com/bclshuai/p/11380657.html

1.1  tensorflow2.x自動求導

1.1.1         自動求導GradientTape類

GradientTape的作用就是用於自動求導,需要有自變量x和因變量y,調用gradient(y,x)就可以求導,在GradientTape定義的上下文中,會默認觀察自變量x,並進行記錄,需要占用內存等資源,所以可以精確指定觀察變量,減少資源。自變量可以是多個,gradient(y,[x,p,g]) ,計算的結果就是多個變量的張量組合。也可以通過嵌套的方式實現高階求導。

1.1.2         GradientTape類定義

class GradientTape(object):

(1)初始化構造函數

 def __init__(self, persistent=False, watch_accessed_variables=True):

#persistent變量,默認情況下,調用一次求導之后,GradientTape所持有的資源就會被釋放,不能再執行,如果需要持續求導,persistent默認為False,,也就是g只能調用一次,如果指定persistent為true,則可以多次求導。

#watch_accessed_variables,是否要指定觀察的變量,默認為True,默認觀察並記錄上下文中的自變量,g.watch(x)可以不寫,自動觀察求導中的變量。如果要對監視變量進行精細控制,可以通過將watch_accessed_variables = False傳遞給tape,手動指定觀察變量,避免全部觀察記錄,減少不必要的資源消耗。

實例

x = tf.Variable(2.0)

w = tf.Variable(5.0)

with tf.GradientTape(

    watch_accessed_variables=False, persistent=True) as tape:

  tape.watch(x)

  y = x ** 2  # Gradients will be available for `x`.

  z = w ** 3  # No gradients will be available as `w` isn't being watched.

dy_dx = tape.gradient(y, x)

print(dy_dx)

 

# No gradients will be available as `w` isn't being watched.

dz_dy = tape.gradient(z, w)

print(dz_dy)

(2)進入和退出函數

輸入一個上下文,在該上下文中將操作記錄在此tape上

def __enter__(self):

退出記錄上下文,不再跟蹤其他操作

def __exit__(self, typ, value, traceback):

(3)觀察變量函數

指定觀察變量,默認自動觀察求導自變量,watch_accessed_variables = False時才需要手動指定。

def watch(self, tensor):

(1)   停止在tape上記錄操作

暫時停止在該tape上進行記錄操作。此上下文管理器處於活動狀態時執行的操作不會記錄在tape上。這對於減少通過跟蹤所有計算而使用的內存很有用。

def stop_recording(self):

實例:

import tensorflow as tf
x = tf.Variable(4.0)
with tf.GradientTape(persistent=True) as tape:
    y = tf.pow(x, 2)
    z=tape.gradient(y,x)
    #with tape.stop_recording():# The gradient computation below is not traced, saving memory.
    y+=x
    dy_dx = tape.gradient(y, x)
print(z)
print(dy_dx)

輸出結果:

tf.Tensor(8.0, shape=(), dtype=float32)

tf.Tensor(9.0, shape=(), dtype=float32)

 

如果加上stop_recording

import tensorflow as tf
x = tf.Variable(4.0)
with tf.GradientTape(persistent=True) as tape:
    y = tf.pow(x, 2)
    z=tape.gradient(y,x)
    with tape.stop_recording():# The gradient computation below is not traced, saving memory.
        y+=x
        dy_dx = tape.gradient(y, x)
print(z)
print(dy_dx)

輸出結果為

tf.Tensor(8.0, shape=(), dtype=float32)

None

可見stop_recording作用是停止記錄變量的計算,不記錄結果。求導結果為None;

(2)   重置求導記錄函數

清除此tape中存儲的所有信息。等效於退出並重新進入tape上下文管理器。

def reset(self):

import tensorflow as tf
x=tf.Variable(initial_value=[1.,2.,3,])
with tf.GradientTape() as t:
  loss = tf.pow(x,2)
with tf.GradientTape() as t:
  loss += x;
z=t.gradient(loss, x)  # Only differentiates other_loss_fn, not loss_fn
print(z)

# The following is equivalent to the above
with tf.GradientTape() as t:
  loss = tf.pow(x,2)#調用了reset,這里的記錄會被清除
  #t.reset()注釋,loss=x*x+x,不注釋,會將x*x的記錄清除,loss=x
  loss += x
z=t.gradient(loss, x)  # Only differentiates other_loss_fn, not loss_fn
print(z)

輸出結果

tf.Tensor([1. 1. 1.], shape=(3,), dtype=float32)# 調用reset清除記錄x*x

tf.Tensor([3. 5. 7.], shape=(3,), dtype=float32)# 不清除x*x

(6)返回觀察的變量

該函數監視要求導的變量,可以是一個tensor[x],也可以是多個參數組成的列表[x,y],如果watch_accessed_variables定義為True,則可以不調用該函數,可以自動求導。

def watched_variables(self):

(7)求導函數

    def gradient(self,

               target,# 求導的函數y,可以理解為要求導的因變量y

               sources,# 要對哪一個自變量x求導,可以是多個組合

               output_gradients=None,求導后輸出結果乘以的系數

               unconnected_gradients=UnconnectedGradients.NONE):# 它是一個可選參數,有兩個值,“none”和“zero”,none是它的默認值,表示當我們的target(因變量y)與sources(自變量x)之間沒有關系時,返回NONE

(8)雅克比矩陣

在向量微積分中,雅可比矩陣是一階偏導數以一定方式排列成的矩陣。

    def jacobian(self,

               target, #求導的函數y,可以理解為要求導的因變量y

               sources,自變量x,維度大於等於2的張量

               unconnected_gradients=UnconnectedGradients.NONE,

               parallel_iterations=None,# 控制並行調度的迭代次數,可以用來控制總的內存使用量

               experimental_use_pfor=True):

實例

with tf.GradientTape() as g:

  x = tf.constant([[1., 2.], [3., 4.]], dtype=tf.float32)

  g.watch(x)

  y = x * x#一階導數是2*x

batch_jacobian = g.batch_jacobian(y, x)

# batch_jacobian is [[[2,  0], [0,  4]], [[6,  0], [0,  8]]]

1.1.3         自動求導的步驟

(1)創建一個GradientTape對象:g=tf.GradientTape()

(2)監視watch要求導的變量:g.watch(x)

(3)對函數進行求導:g.gredient(y,x)

1.1.4         自動求導實例

(1)高階導數嵌套實例

先初始化一個變量,然后定義變量的函數,然后用tf.GradientTape()求一階導數和二階導數。

import tensorflow as tf
#定義並初始化變量
x=tf.Variable(initial_value=[[1.,2.,3.],[4.,5.,6.]])
#創建GradientTape對象
with tf.GradientTape() as g1:
    #指定觀察變量
   # g1.watch(x)
    with tf.GradientTape(persistent=True) as g2:#嵌套高階求導
       # g2.watch(x)
        y=x*x
        z=tf.sqrt(y+1)
    y1=g2.gradient(y,x)#一階導數
    z1x=g2.gradient(z,x)#z對於x的導數,因為g2的persistent參數設置為true,所以可以調用兩次,否則報錯。
y2=g1.gradient(y1,x)#二階導數

print(y)
print(y1)
print(y2)
print(z1x)

 

輸出結果:

tf.Tensor(

[[ 1.  4.  9.]

 [16. 25. 36.]], shape=(2, 3), dtype=float32)

tf.Tensor(

[[ 2.  4.  6.]

 [ 8. 10. 12.]], shape=(2, 3), dtype=float32)

tf.Tensor(

[[2. 2. 2.]

 [2. 2. 2.]], shape=(2, 3), dtype=float32)

tf.Tensor(

[[0.70710677 0.8944272  0.94868326]

 [0.97014254 0.9805807  0.9863939 ]], shape=(2, 3), dtype=float32)

(2)多變量和輸出系數求導實例

import tensorflow as tf

x = tf.Variable(initial_value=[1.0, 2.0, 3.0])
y = tf.Variable(initial_value=[2.0, 4.0, 6.0])

with tf.GradientTape(persistent=True) as g:
    g.watch(x)
    g.watch(y)
    z = tf.pow(x, 2) + tf.pow(y, 2)

output_gradients = tf.Variable([0.2, 0.6, 0.2])#輸出結果相乘的系數
dz = g.gradient(z, [x, y], output_gradients=output_gradients)  # 給每一個元素施加不同的權重
print(dz)
'''運行結果為:
[<tf.Tensor: id=64, shape=(3,), dtype=float32, numpy=array([0.4, 2.4, 1.2],
  dtype=float32)>,
 <tf.Tensor: id=40, shape=(3,), dtype=float32, numpy=array([0.8, 4.8, 2.4],
  dtype=float32)>]
'''
'''
本來的結果是dz_dx=[2,4,6], 分別乘以權重[0.2,0.6,0.2]之后,得到[0.4,2.4,1.2]
本來的結果是dz_dy=[4,8,12],分別乘以權重[0.2,0.6,0.2]之后,得到[0.8,4.8,2.4]
'''

 

1.1.5         參考文獻

https://dengbocong.blog.csdn.net/article/details/108044938

https://blog.csdn.net/qq_27825451/article/details/89556703

https://tensorflow.google.cn/api_docs/python/tf/GradientTape#reset


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM