pytorch與torch的關係
分享一篇關於pytorch和torch關係的文章,講的很清楚。
Pytorch釋出已經有一段時間了,我們在使用中也發現了其獨特的動態圖設計,讓我們可以高效地進行神經網路的構造、實現我們的想法。那麼Pytorch是怎麼來的,追根溯源,pytorch可以說是torch的python版,然後增加了很多新的特性,那麼pytorch和torch的具體區別是什麼,這篇文章大致對兩者進行一下簡要分析,有一個巨集觀的瞭解。
上面的對比圖來源於官網,官方認為,這兩者最大的區別就是Pytorch重新設計了model模型和intermediate中間變數的關係,在Pytorch中所有計算的中間變數都存在於計算圖中,所有的model都可以共享中間變數。而在torch中的中間變數則在每一個模組中,想要呼叫其他模組的引數就必須首先複製這個模組然後再呼叫。
當然,Python有很多特性是lua語言不具備的,Python的debug功能比lua強大很多,所以效率也就提升了。
Pytorch與Torch
接下來讓我們稍微稍微具體談一下兩者的區別(ps:torch是火炬的意思)。
我們都知道Pytorch採用python語言介面來實現程式設計,而torch是採用lua語言,Lua是一個什麼樣的語言,可以這樣說,Lua相當於一個小型加強版的C,支援類和麵向物件,執行效率極高,與C語言結合“特別默契”,也就是說在Lua中使用C語言非常容易也很舒服。
因此,torch是採用C語言作為底層,然後lua語言為介面的深度學習庫。而Pytorch呢,Pytorch其實也是主要採用C語言為介面(
目前來看,兩者的底層庫的C語言部分區別還是不大,儘管Pytorch使用了C++介面,但是由於程式碼的相容性,使用torch拓展的底層程式碼在Pytorch中照樣可以編譯使用。
編寫模型方面的區別
我們來簡單說一下pytorch和torch在編寫模型上一些簡單的區別,pytorch在編寫模型的時候最大的特點就是利用autograd技術來實現自動求導,也就是不需要我們再去麻煩地寫一些反向的計算函式,這點上繼承了torch。
舉個例子:
pytorch中,我們通過繼承nn.Module
設計一個層,然後定義我們平常使用的成員函式:__init__
和forward
,這兩個函式相比我們都很熟悉,另外content_hook
是一個hook函式,通常在需要讀取中間引數的時候使用:
# 這個層是風格遷移中的內容層
class ContentLoss(nn.Module):
def __init__(self, target, weight):
super(ContentLoss, self).__init__()
self.target = target.detach()
self.weight = weight
self.loss = 0
def forward(self, input):
self.loss = F.mse_loss(input, self.target) * self.weight
return input
# 這個hook通過register_backward_hook後進行繫結才能使用
# 通過繫結後,這裡的函式在這個層進行backward的時候會執行
# 在裡面我們可以自定義一些操作實現其他的功能,比如修改grad_input
def content_hook(self, module, grad_input, grad_output):
return grad_input
而在torch中是這樣設計的,我們利用lua語言的特定來設計class,__init
和updateOutput
和上面對應的__init__
和forward
功能相同。其實torch也是有forward
函式實現,但是由於torch的侷限性,不建議直接修改forward
,我們需要修改updateOutput
函式來實現forward操作:
local ContentLoss, parent = torch.class('nn.ContentLoss', 'nn.Module')
function ContentLoss:__init(strength, target)
parent.__init(self)
self.strength = strength
self.target = target
self.loss = 0
self.crit = nn.MSECriterion()
end
-- 就是得到輸入輸出output
function ContentLoss:updateOutput(input)
if input:nElement() == self.target:nElement() then
self.loss = self.crit:forward(input, self.target) * self.strength
else
print('WARNING: Skipping content loss')
end
self.output = input
return self.output
end
-- 這裡的函式在backward的時候會執行
function ContentLoss:updateGradInput(input, gradOutput)
if input:nElement() == self.target:nElement() then
self.gradInput = self.crit:backward(input, self.target)
end
self.gradInput:mul(self.strength)
self.gradInput:add(gradOutput)
return self.gradInput
end
我們通過對比Pytorch和Torch自頂層的設計大概分析了一下兩者的區別,其實兩者的很多功能函式的操作方式和命名都是類似的:
pytorch:
torch:
依賴庫區別
Pytorch藉助於Python強大的第三方庫,已經存在的庫可以直接使用,利用我們的影象讀取直接使用Python自帶的PIL影象庫或者python-opencv都可以,其他各種想要實現的功能都可以利用python強大的第三方庫實現:
而在torch中同樣有很多Lua語言下開發的很多包:
torch可以很方便地拓展cuda和c程式碼實現更加豐富的自定義層和演算法操作。
後記
暫且說這麼多,Pytorch和Torch都很優秀,現在仍然有很多優秀的專案是使用torch來編寫,Pytorch和torch的思想都值得我們去借鑑,閒暇之餘,我們也可以看看Torch的程式碼,體驗一下其優秀的構架和設計。