日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

autograd库测试笔记-(一个基于Numpy的自动求导库)

發布時間:2025/4/16 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 autograd库测试笔记-(一个基于Numpy的自动求导库) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

導入 autograd 庫,同時導入這個庫里的numpy(應該是作者自己把numpy放入了這個庫的命名空間里面)以及逐項求導elementwise_grad。

from autograd import grad import autograd.numpy as np from autograd import elementwise_grad

接下來定義第一個函數,這個函數非常簡單,其實就是一個線性變換:

yn×l=Xn×dwd×l\mathbf{y}_{n\times l} = \mathbf{X}_{n\times d} \mathbf{ w} _{d\times l} yn×l?=Xn×d?wd×l?

這個變換也常用于神經網絡的輸入層。

def lin_func(x,w):return np.dot(x,w)x = np.array([[1,2,3],[4,5,6]]) w = np.array([1,1,1]).astype(float)print(lin_func(x,w)) [ 6. 15.]

這里也要注意一個問題:autograd并不能支持numpy的所有操作。比如上面的線性變換其實也可以用 x.dot(w) 來實現,但這種方式下就不能再用autograd自動求導了。因此在使用時也要注意看看文檔。

接下來寫出這個函數的導數 ?y?X\frac{\partial \mathbf{y}}{\partial \mathbf{X}}?X?y?

用法很簡單,直接將函數名作為"參數"傳入 elementwise_grad 即可,得到的仍然是一個callable 的類型,這里命名為 lin_grads:

lin_grads = elementwise_grad(lin_func)dx = lin_grads(x,w)print(dx)print(dx.shape) [[1 1 1][1 1 1]] (2, 3)

這里其實存在一個問題,如果我們用標量求導來類推,那么此時導數應該是:

?y?X=wT\frac{\partial \mathbf{y}}{\partial \mathbf{X}} =\mathbf{w}^T ?X?y?=wT

而剛剛我們設好的 w\mathbf{w}w3×13 \times 13×1 維,那么上面的導數就應該是 1×31 \times 31×3維,而此時得到的結果卻是2×32 \times 32×3 維。這一點和我們直觀的認識是不一樣的。因為在矩陣對矩陣求導時,許多在標量求導時的結論是不存在的。 而如果要統一這些運算,則需要考慮 Kronecker 乘積。這個問題就相對復雜了,有空可以去看看這個:Kronecker Products and Matrix Calculus in System Theory

這里最簡單的解釋是:剛剛的導數,對于 X\mathbf{X}X 的每一行其實都是 wT\mathbf{w}^TwT,而此時 X\mathbf{X}X 有2行,因此結果出現了2列。

緊接著另外一個問題是:這個庫求導時,只是對elementwise_grad 中的第一個參數求導,下面這個例子演示了 ?y?w\frac{\partial \mathbf{y}}{\partial \mathbf{w}}?w?y? 的計算結果:

def lin_wx(w,x):return np.dot(x,w)print(lin_wx(w,x)) [ 6. 15.] lin_grad_wx = elementwise_grad(lin_wx)dw = lin_grad_wx(w,x)print(dw) print(dw.shape) [5. 7. 9.] (3,)

這里其實又出現了一個“反常”的現象:同樣地,如果按照標量求導的思路來看,此時的導數應該是:

?y?w=XT\frac{\partial \mathbf{y}}{\partial \mathbf{w}} =\mathbf{X}^T ?w?y?=XT

而事實卻是:

?y?w=∑i=1nXi,:T\frac{\partial \mathbf{y}}{\partial \mathbf{w}} = \sum_{i=1}^{n} \mathbf{X}_{i,:}^T ?w?y?=i=1n?Xi,:T?

這里Xi,:\mathbf{X}_{i,:}Xi,:?X\mathbf{X}X 的第 iii 行。 如果要想徹底弄明白這個問題還是建議去看這個:Kronecker Products and Matrix Calculus in System Theory。

當然,通常而言,我們只需要考慮 loss 對某個參數的導數就可以了,這個庫也做到了這一點:即對某個標量函數,其實是完全可以得到與某參數的shape一模一樣的導數,這樣在調用梯度做訓練時也就比較簡單了。

以下是官方的一個完整的logistic regression的例子。

from builtins import range import autograd.numpy as np from autograd import grad from autograd.test_util import check_gradsdef sigmoid(x):return 0.5*(np.tanh(x) + 1)def logistic_predictions(weights, inputs):# Outputs probability of a label being true according to logistic model.return sigmoid(np.dot(inputs, weights))def training_loss(weights):# Training loss is the negative log-likelihood of the training labels.preds = logistic_predictions(weights, inputs)label_probabilities = preds * targets + (1 - preds) * (1 - targets)return -np.sum(np.log(label_probabilities))# Build a toy dataset. inputs = np.array([[0.52, 1.12, 0.77],[0.88, -1.08, 0.15],[0.52, 0.06, -1.30],[0.74, -2.49, 1.39]]) targets = np.array([True, True, False, True])# Build a function that returns gradients of training loss using autograd. training_gradient_fun = grad(training_loss)# Check the gradients numerically, just to be safe. weights = np.array([0.0, 0.0, 0.0]) check_grads(training_loss, modes=['rev'])(weights)# Optimize weights using gradient descent. print("Initial loss:", training_loss(weights)) for i in range(100):weights -= training_gradient_fun(weights) * 0.01print("Trained loss:", training_loss(weights)) Initial loss: 2.772588722239781 Trained loss: 0.38900754315581143

總結

以上是生活随笔為你收集整理的autograd库测试笔记-(一个基于Numpy的自动求导库)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。