Python Pytorch深度學習之核心小結
Pytorch的核心是兩個主要特征:
1.一個n維tensor,類似于numpy,但是tensor可以在GPU上運行
2.搭建和訓練神經網絡時的自動微分/求導機制
一、Numpy實現(xiàn)網絡
在總結Tensor之前,先使用numpy實現(xiàn)網絡。numpy提供了一個n維數(shù)組對象,以及許多用于操作這些數(shù)組的函數(shù)。
import numpy as np # n是批量大小,d_in是輸入維度 # h是隱藏的維度,d_out是輸出維度 n,d_in,h,d_out=64,1000,100,10 # 創(chuàng)建隨機輸入和輸出數(shù)據 x=np.random.randn(n,d_in) y=np.random.randn(n,d_out) # 隨機初始化權重 w1=np.random.randn(d_in,h) w2=np.random.randn(h,d_out) learning_rate=1e-6 for i in range(500): #前向傳播,計算預測值y h=x.dot(w1) h_relu=np.maximum(h,0) y_pred=h_relu.dot(w2) #計算損失值 loss=np.square(y_pred-y).sum() print(i,loss) #反向傳播,計算w1和w2對loss的梯度 grad_y_pred=2.0*(y_pred-y) grad_w2=h_relu.T.dot(grad_y_pred) grad_h_relu=grad_y_pred.dot(w2.T) grad_h=grad_h_relu.copy() grad_h[h<0]=0 grad_w1=x.T.dot(grad_h) # 更新權重 w1-=learning_rate*grad_w1 w2-=learning_rate*grad_w2
運行結果
可以明顯看到loss逐漸減小。
此處解釋一下上次發(fā)的一篇中,有猿友對其中的loss有疑問,其實我認為:損失值loss只是為了檢測網絡的學習情況(至少我在這幾篇中的loss就只有這個功能),在前面那一篇中迭代沒有清零,所以損失值是一直增加的,如果每次迭代以后置零,效果和現(xiàn)在是一樣的。至于其中的除以2000只是為了便于顯示,可以一目了然大小的變化所以那么寫的,所以可以自己定義合理的寫法。(僅個人的理解和看法)
二、Pytorch:Tensor
Tensor 在概念上和numpy中的array相同,tensor也是一個n維數(shù)組,pytorch提供了許多函數(shù)用于操作這些張量。所有使用numpy執(zhí)行的計算都可以使用pytorch的tensor完成。與numpy不同的是pytorch可以利用GPU加速數(shù)據的計算。實現(xiàn)和numpy相同的過程
#%%tensor實現(xiàn)網絡 import torch dtype=torch.float device=torch.device('cpu') # device=torch.device('cuda:0')#由GPU的可愛們享受吧,我不配,實驗室沒有給我高配置的電腦 # n是批量大小,d_in是輸入維度 # h是隱藏的維度,d_out是輸出維度 n,d_in,h,d_out=64,1000,100,10 # 創(chuàng)建隨機輸入和輸出數(shù)據 x=torch.randn(n,d_in,device=device,dtype=dtype) y=torch.randn(n,d_out,device=device,dtype=dtype) # 隨機初始化權重 w1=torch.randn(d_in,h,device=device,dtype=dtype) w2=torch.randn(h,d_out,device=device,dtype=dtype) learning_rate=1e-6 for i in range(500): #前向傳播,計算預測值y h=x.mm(w1) h_relu=h.clamp(min=0) y_pred=h_relu.mm(w2) #計算損失值 loss=(y_pred-y).pow(2).sum().item() print(i,loss) #反向傳播,計算w1和w2對loss的梯度 grad_y_pred=2.0*(y_pred-y) grad_w2=h_relu.t().mm(grad_y_pred) grad_h_relu=grad_y_pred.mm(w2.T) grad_h=grad_h_relu.clone() grad_h[h<0]=0 grad_w1=x.t().mm(grad_h) # 更新權重 w1-=learning_rate*grad_w1 w2-=learning_rate*grad_w2
運行結果
三、自動求導
1、PyTorch:Tensor和auto_grad
上面兩個例子中,我們自己手動實現(xiàn)了神經網絡的向前和向后傳遞。手動實現(xiàn)反向傳遞對小型雙層網絡來說沒有問題,但是對于大型復雜的網絡來說就會變得很繁瑣。
但是Pytorch中的autograd包提供了自動微分可以用來計算神經網絡中的后向傳遞。當使用autograd時候,網絡前后想傳播將定義一個計算圖,圖中的節(jié)點是tensor,邊是函數(shù),這些函數(shù)是輸出tensor到輸入tensor的映射。這張計算圖使得在網絡中反向傳播時梯度的計算十分簡單。
如果我們想要計算某些tensor的梯度,我們只需要在建立這個tensor時加上一句:requires_grad=True。這個tensor上的任何Pytorch的操作都將構造一個計算圖,從而允許我們在圖中執(zhí)行反向傳播。如果這個tensor的requires_grad=True,那么反向傳播之后x.grad將會是另外一個張量,其為關于某個標量值得梯度。
有時不需要構建這樣的計算圖,例如:在訓練神經網絡的過程中,通常不希望通過權重更新步驟進行反向傳播。在這種情況下,可以使用torch.no_grad()上下文管理器來防止構造計算圖——————(其實這些在之前的文章中都有詳細的寫過[我在這里],就不再贅述了)
下面例子中,使用Pytorch的Tensor和autograd來實現(xiàn)兩層的神經網絡,不需要再手動執(zhí)行網絡的反向傳播:
#%%使用tensor和auto_grad實現(xiàn)兩層神經網絡 import torch dtype=torch.float device=torch.device('cpu') # device=torch.device('cuda:0')#由GPU的可愛們享受吧,我不配,實驗室沒有給我高配置的電腦 # n是批量大小,d_in是輸入維度 # h是隱藏的維度,d_out是輸出維度 n,d_in,h,d_out=64,1000,100,10 # 創(chuàng)建隨機輸入和輸出數(shù)據,requires_grad默認設置為False,表示不需要后期微分操作 x=torch.randn(n,d_in,device=device,dtype=dtype) y=torch.randn(n,d_out,device=device,dtype=dtype) # 隨機初始化權重,requires_grad默認設置為True,表示想要計算其微分 w1=torch.randn(d_in,h,device=device,dtype=dtype,requires_grad=True) w2=torch.randn(h,d_out,device=device,dtype=dtype,requires_grad=True) learning_rate=1e-6 for i in range(500): #前向傳播,使用tensor上的操作計算預測值y # 由于w1和w2的requirea_grad=True,涉及這兩個張量的操作可以使pytorch構建計算圖 #即允許自動計算梯度,由于不需要手動實現(xiàn)反向傳播,所以不需要保存中間值 y_pred=x.mm(w1).clamp(min=0).mm(w2) #使用tensor中的操作計算損失值,loss.item()得到loss這個張量對應的數(shù)值 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_()
運行結果
總結
本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關注本站的更多內容!
版權聲明:本站文章來源標注為YINGSOO的內容版權均為本站所有,歡迎引用、轉載,請保持原文完整并注明來源及原文鏈接。禁止復制或仿造本網站,禁止在非www.sddonglingsh.com所屬的服務器上建立鏡像,否則將依法追究法律責任。本站部分內容來源于網友推薦、互聯(lián)網收集整理而來,僅供學習參考,不代表本站立場,如有內容涉嫌侵權,請聯(lián)系alex-e#qq.com處理。