強大的PyTorch:10分鍾讓你了解深度學習領域新流行的框架
更多深度文章,請關注:https://yq.aliyun.com/cloud
PyTorch由於使用了強大的GPU加速的Tensor計算(類似numpy)和基於tape的autograd係統的深度神經網絡。這使得今年一月份被開源的PyTorch成為了深度學習領域新流行框架,許多新的論文在發表過程中都加入了大多數人不理解的PyTorch代碼。這篇文章我們就來講述一下我對PyTorch代碼的理解,希望能幫助你閱讀PyTorch代碼。整個過程是基於賈斯汀·約翰遜的偉大教程。如果你想了解更多或者有超過10分鍾的時間,建議你去讀下整篇代碼。
PyTorch由4個主要包裝組成:
- Torch:類似於Numpy的通用數組庫,可以在將張量類型轉換為(torch.cuda.TensorFloat)並在GPU上進行計算。
- torch.autograd:用於構建計算圖形並自動獲取漸變的包
- torch.nn:具有共同層和成本函數的神經網絡庫
- torch.optim:具有通用優化算法(如SGD,Adam等)的優化包
1.導入工具
你可以這樣導入PyTorch:
import torch # arrays on GPU
import torch.autograd as autograd #build a computational graph
import torch.nn as nn # neural net library
import torch.nn.functional as F # most non-linearities are here
import torch.optim as optim # optimization package
2.torch數組取代了numpy ndarray - >在GPU支持下提供線性代數
第一個特色,PyTorch提供了一個像Numpy數組一樣的多維數組,當數據類型被轉換為(torch.cuda.TensorFloat)時,可以在GPU上進行處理。這個數組和它的關聯函數是一般的科學計算工具。
從下麵的代碼中,我們可以發現,PyTorch提供的這個包的功能可以將我們常用的二維數組變成GPU可以處理的三維數組。這極大的提高了GPU的利用效率,提升了計算速度。
大家可以自己比較 Torch和numpy ,從而發現他們的優缺點。
# 2 matrices of size 2x3 into a 3d tensor 2x2x3
d=[[[1., 2.,3.],[4.,5.,6.]],[[7.,8.,9.],[11.,12.,13.]]]
d=torch.Tensor(d) # array from python list
print "shape of the tensor:",d.size()
# the first index is the depth
z=d[0]+d[1]
print "adding up the two matrices of the 3d tensor:",z
shape of the tensor: torch.Size([2, 2, 3])
adding up the two matrices of the 3d tensor:
8 10 12
15 17 19
[torch.FloatTensor of size 2x3]
# a heavily used operation is reshaping of tensors using .view()
print d.view(2,-1) #-1 makes torch infer the second dim
1 2 3 4 5 6
7 8 9 11 12 13
[torch.FloatTensor of size 2x6]
3.torch.autograd可以生成一個計算圖 - >自動計算梯度
第二個特色是autograd包,其提供了定義計算圖的能力,以便我們可以自動計算漸變梯度。在計算圖中,一個節點是一個數組,邊(edge)是on數組的一個操作。要做一個計算圖,我們需要在(torch.aurograd.Variable())函數中通過包裝數組來創建一個節點。那麼我們在這個節點上所做的所有操作都將被定義為邊,它們將是計算圖中新的節點。圖中的每個節點都有一個(node.data)屬性,它是一個多維數組和一個(node.grad)屬性,這是相對於一些標量值的漸變(node.grad也是一個.Variable()) 。在定義計算圖之後,我們可以使用單個命令(loss.backward())來計算圖中所有節點的損耗梯度。
-
使用torch.autograd.Variable()將張量轉換為計算圖中的節點。
- 使用x.data訪問其值。
- 使用x.grad訪問其漸變。
- 在.Variable()上執行操作,繪製圖形的邊緣。
# d is a tensor not a node, to create a node based on it:
x= autograd.Variable(d, requires_grad=True)
print "the node's data is the tensor:", x.data.size()
print "the node's gradient is empty at creation:", x.grad # the grad is empty right now
the node's data is the tensor: torch.Size([2, 2, 3])
the node's gradient is empty at creation: None
# do operation on the node to make a computational graph
y= x+1
z=x+y
s=z.sum()
print s.creator
<torch.autograd._functions.reduce.Sum object at 0x7f1e59988790>
# calculate gradients
s.backward()
print "the variable now has gradients:",x.grad
the variable now has gradients: Variable containing:
(0 ,.,.) =
2 2 2
2 2 2
(1 ,.,.) =
2 2 2
2 2 2
[torch.FloatTensor of size 2x2x3]
4.torch.nn包含各種NN層(張量行的線性映射)+
第三個特色是高級神經網絡庫(torch.nn),其抽象出了神經網絡層中的所有參數處理,以便於在通過幾個命令(例如torch.nn.conv)就很容易地定義NN。這個包也帶有流行的損失函數的功能(例如torch.nn.MSEloss)。我們首先定義一個模型容器,例如使用(torch.nn.Sequential)的層序列的模型,然後在序列中列出我們期望的層。這個高級神經網絡庫也可以處理其他的事情,我們可以使用(model.parameters())訪問參數(Variable())
# linear transformation of a 2x5 matrix into a 2x3 matrix
linear_map=nn.Linear(5,3)
print "using randomly initialized params:", linear_map.parameters
using randomly initialized params: <bound method Linear.parameters of Linear (5 -> 3)>
# data has 2 examples with 5 features and 3 target
data=torch.randn(2,5) # training
y=autograd.Variable(torch.randn(2,3)) # target
# make a node
x=autograd.Variable(data, requires_grad=True)
# apply transformation to a node creates a computational graph
a=linear_map(x)
z=F.relu(a)
o=F.softmax(z)
print "output of softmax as a probability distribution:", o.data.view(1,-1)
# loss function
loss_func=nn.MSELoss() #instantiate loss function
L=loss_func(z,y) # calculateMSE loss between output and target
print "Loss:", L
output of softmax as a probability distribution:
0.2092 0.1979 0.5929 0.4343 0.3038 0.2619
[torch.FloatTensor of size 1x6]
Loss: Variable containing:
2.9838
[torch.FloatTensor of size 1]
我們還可以通過子類(torch.nn.Module)定義自定義層,並實現接受(Variable())作為輸入的(forward())函數,並產生(Variable())作為輸出。我們也可以通過定義一個時間變化的層來做一個動態網絡。
-
定義自定義層時,需要實現2個功能:
- _ init_函數必須始終被繼承,然後層的所有參數必須在這裏定義為類變量(self.x)
- 正向函數是我們通過層傳遞輸入的函數,使用參數對輸入進行操作並返回輸出。輸入需要是一個autograd.Variable(),以便pytorch可以構建圖層的計算圖。
class Log_reg_classifier(nn.Module):
def __init__(self, in_size,out_size):
super(Log_reg_classifier,self).__init__() #always call parent's init
self.linear=nn.Linear(in_size, out_size) #layer parameters
def forward(self,vect):
return F.log_softmax(self.linear(vect)) #
5.torch.optim
torch.nn構建一個nn計算圖,使用torch.autograd來計算梯度,然後將它們提供給torch.optim來更新網絡參數。
第四個特色是與NN庫一起工作的優化軟件包(torch.optim)。該庫包含複雜的優化器,如Adam,RMSprop等。我們定義一個優化器並傳遞網絡參數和學習率(opt = torch.optim.Adam(model.parameters(),lr = learning_rate)),然後我們調用(opt.step())對我們的參數進行近一步更新。
optimizer=optim.SGD(linear_map.parameters(),lr=1e-2) # instantiate optimizer with model params + learning rate
# epoch loop: we run following until convergence
optimizer.zero_grad() # make gradients zero
L.backward(retain_variables=True)
optimizer.step()
print L
Variable containing:
2.9838
[torch.FloatTensor of size 1]
建立神經網絡很容易,但是如何協同工作並不容易。這是一個示例顯示如何協同工作:
# define model
model = Log_reg_classifier(10,2)
# define loss function
loss_func=nn.MSELoss()
# define optimizer
optimizer=optim.SGD(model.parameters(),lr=1e-1)
# send data through model in minibatches for 10 epochs
for epoch in range(10):
for minibatch, target in data:
model.zero_grad() # pytorch accumulates gradients, making them zero for each minibatch
#forward pass
out=model(autograd.Variable(minibatch))
#backward pass
L=loss_func(out,target) #calculate loss
L.backward() # calculate gradients
optimizer.step() # make an update step
希望上述的介紹能夠幫你更好的閱讀PyTorch代碼。
本文由北郵@愛可可-愛生活老師推薦,阿裏雲雲棲社區組織翻譯。
文章原標題《Understand PyTorch code in 10 minutes》,
作者: Hamidreza Saghir,機器學習研究員 - 多倫多大學博士生 譯者:袁虎 審閱:阿福
文章為簡譯,更為詳細的內容,請查看原文
最後更新:2017-07-02 11:27:13