人妖在线一区,国产日韩欧美一区二区综合在线,国产啪精品视频网站免费,欧美内射深插日本少妇

新聞動態(tài)

Pytorch自動求導函數詳解流程以及與TensorFlow搭建網絡的對比

發(fā)布日期:2021-12-17 00:07 | 文章來源:站長之家

一、定義新的自動求導函數

在底層,每個原始的自動求導運算實際上是兩個在Tensor上運行的函數。其中,forward函數計算從輸入Tensor獲得的輸出Tensors。而backward函數接收輸出,Tensors對于某個標量值得梯度,并且計算輸入Tensors相對于該相同標量值得梯度。
在Pytorch中,可以容易地通過定義torch.autograd.Function的子類實現(xiàn)forward和backward函數,來定義自動求導函數。之后就可以使用這個新的自動梯度運算符了。我們可以通過構造一個實例并調用函數,傳入包含輸入數據的tensor調用它,這樣來使用新的自動求導運算
以下例子,自定義一個自動求導函數展示ReLU的非線性,并調用它實現(xiàn)兩層網絡,如上一節(jié)

import torch
class myrelu(torch.autograd.Function):#自定義子類
 # 通過建立torch.autograd的子類來實現(xiàn)自定義的autograd函數,并完成張量的正向和反向傳播
 @staticmethod
 def forward(ctx, x):
  # 在正向傳播中,接受到一個上下文對象和一個包含輸入的張量,必須返回一個包含輸出的張量,可以使用上下文對象來緩存對象,以便在反向傳播中使用
  ctx.save_for_backward(x)
  return x.clamp(min=0)
 @staticmethod
 def backward(ctx, grad_output):
  """
  在反向傳播中,我們接收到上下文對象和一個張量,
  其包含了相對于正向傳播過程中產生的輸出的損失的梯度。
  我們可以從上下文對象中檢索緩存的數據,
  并且必須計算并返回與正向傳播的輸入相關的損失的梯度。
  """
  x, = ctx.saved_tensors
  grad_x = grad_output.clone()
  grad_x[x < 0] = 0
  return grad_x

調用自定義的類實現(xiàn)兩層網絡

#%%
device=torch.device('cuda' if torch.cuda.is_available() else 'cpu')
# n是批量大小,d_in是輸入維度
# h是隱藏的維度,d_out是輸出維度
n,d_in,h,d_out=64,1000,100,10
# 創(chuàng)建隨機輸入和輸出數據,requires_grad默認設置為False,表示不需要后期微分操作
x=torch.randn(n,d_in,device=device)
y=torch.randn(n,d_out,device=device)
# 隨機初始化權重,requires_grad默認設置為True,表示想要計算其微分
w1=torch.randn(d_in,h,device=device,requires_grad=True)
w2=torch.randn(h,d_out,device=device,requires_grad=True)
learning_rate=1e-6
for i in range(500):
 #前向傳播,使用tensor上的操作計算預測值y
  #調用自定義的myrelu.apply函數
 y_pred=myrelu.apply(x.mm(w1)).mm(w2)
 
 
 #使用tensor中的操作計算損失值,loss.item()得到loss這個張量對應的數值
 loss=(y_pred-y).pow(2).sum()
 print(i,loss.item())
 
 #使用autograd計算反向傳播,這個調用將計算loss對所有的requires_grad=True的tensor梯度,
 #調用之后,w1.grad和w2.grad將分別是loss對w1和w2的梯度張量
 loss.backward()
 #使用梯度下降更新權重,只想對w1和w2的值進行原地改變:不想更新構建計算圖
 #所以使用torch.no_grad()阻止pytorch更新構建計算圖
 with torch.no_grad():
  w1-=learning_rate*w1.grad
  w2-=learning_rate*w2.grad
  #反向傳播后手動將梯度置零
  w1.grad.zero_()
  w2.grad.zero_() 

運行結果


二、Pytorch 和 TensorFlow對比

  • PyTorch自動求導看似非常像TensorFlow:這兩個框架中,都定義了計算圖,使用自動微分來計算梯度,兩者最大的不同是TensorFlow的計算圖是靜態(tài)的,而PyTorch使用的是動態(tài)的計算圖。
  • 在TensorFlow中,定義計算圖一次,然后重復執(zhí)行相同的圖,可能會提供不同的輸入數據,而在PyTorch中,每一個前向通道定義一個新的計算圖。
  • **靜態(tài)圖的好處在于可以預先對圖進行優(yōu)化。**如:一個框架可以融合一些圖的運算來提升效率,或者產生一個策略來將圖分布到多個GPU或機器上。但是如果重復使用相同的圖,那么重復運行同一個圖時,前期潛在的代價高昂的預先優(yōu)化的消耗就會被分攤。
  • 靜態(tài)圖和動態(tài)圖的一個區(qū)別就是控制流。對于一些模型,對每個數據點執(zhí)行不同的計算。如:一個遞歸神經網絡可能對于每個數據點執(zhí)行不同的時間步數,這個展開可以作為一個循環(huán)來實現(xiàn)。對于一個靜態(tài)圖,循環(huán)結構要作為圖的一部分。因此,TensorFlow提供了運算符將循環(huán)嵌入到圖當中。對于動態(tài)圖來說,情況更加簡單:為每個例子即時創(chuàng)建圖,使用普通的命令式控制流來為每個輸入執(zhí)行不同的計算。

使用TensorFlow擬合一個簡單的兩層網絡(上面做對比):

#%%使用TensorFlow
import tensorflow.compat.v1 as tf#為了用placeholder不惜一切代價
tf.disable_v2_behavior()
import numpy as np
#%%
# 建立計算圖
# n是批量大小,d_in是輸入維度
# h是隱藏的維度,d_out是輸出維度
n,d_in,h,d_out=64,1000,100,10
# 為輸入和目標數據創(chuàng)建placeholder,在執(zhí)行計算圖時,他們將會被真實的數據填充
x=tf.placeholder(tf.float32,shape=(None,d_in))
y=tf.placeholder(tf.float32,shape=(None,d_out))
# 為權重創(chuàng)建variable并用隨機數據初始化,TensorFlow的variable在執(zhí)行計算圖時不會改變
w1 = tf.Variable(tf.random_normal((d_in,h)))
w2=tf.Variable(tf.random_normal((h,d_out)))
# 前向傳播:使用TensorFlow的張量運算計算預測值y(這段代碼不執(zhí)行任何數值運算,只是建立了稍后要執(zhí)行的計算圖)
h=tf.matmul(x,w1)
h_relu=tf.maximum(h,tf.zeros(1))
y_pred=tf.matmul(h_relu,w2)
# 使用TensorFlow的張量運算損失loss
loss=tf.reduce_sum((y-y_pred)**2.0)
# 計算loss對于權重w1和w2的導數
grad_w1,grad_w2=tf.gradients(loss,[w1,w2])
# 使用梯度下降更新權重,為了實際更新權重,我們需要在執(zhí)行計算圖時計算new_w1和new_w2
# 注:在TensorFlow中,更新權重值得行為是計算圖的一部分,但在Pytorch中發(fā)生在計算圖形之外
learning_rate=1e-6
new_w1=w1.assign(w1-learning_rate*grad_w1)
new_w2=w2.assign(w2-learning_rate*grad_w2)
# 現(xiàn)在搭建好了計算圖,開始一個TensorFlow回話來執(zhí)行計算圖
with tf.Session() as sess:
 # 運算一次計算圖來出事話variable w1和w2
 sess.run(tf.global_variables_initializer())
 # 創(chuàng)建numpy數組存儲輸入x和目標y的實際數據
 x_value=np.random.randn(n,d_in)
 y_value=np.random.randn(n,d_out)
 for i in range(500):
  # 多次運行計算圖,每次執(zhí)行時,都有feed_dict參數,
  # 將x_value綁定到x,將y_value綁定到y(tǒng).每次執(zhí)行計算圖都要計算損失,
  # new_w1和new_w2,這些張量的值以numpy數組的形式返回
  loss_value,i,i=sess.run([loss,new_w1,new_w2],
 feed_dict={x:x_value,y:y_value})
  print(loss_value)

運行結果


今日告一段落,重點是比較了TensorFlow和Pytorch在自動求導中的區(qū)別——計算圖前者是靜態(tài)的,后者是動態(tài)的。
再見啦,明天可能不更~因為下午晚上都有課,雖然我可能不去上(哈哈哈哈哈哈哈哈,別學我)后面一節(jié)來寫神經網絡,不見不散??!

到此這篇關于Pytorch自動求導函數詳解流程以及與TensorFlow搭建網絡的對比的文章就介紹到這了,更多相關Pytorch 自動求導函數內容請搜索本站以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持本站!

版權聲明:本站文章來源標注為YINGSOO的內容版權均為本站所有,歡迎引用、轉載,請保持原文完整并注明來源及原文鏈接。禁止復制或仿造本網站,禁止在非www.sddonglingsh.com所屬的服務器上建立鏡像,否則將依法追究法律責任。本站部分內容來源于網友推薦、互聯(lián)網收集整理而來,僅供學習參考,不代表本站立場,如有內容涉嫌侵權,請聯(lián)系alex-e#qq.com處理。

相關文章

實時開通

自選配置、實時開通

免備案

全球線路精選!

全天候客戶服務

7x24全年不間斷在線

專屬顧問服務

1對1客戶咨詢顧問

在線
客服

在線客服:7*24小時在線

客服
熱線

400-630-3752
7*24小時客服服務熱線

關注
微信

關注官方微信
頂部