1. 程式人生 > >pytorch與torch的關係

pytorch與torch的關係

分享一篇關於pytorch和torch關係的文章,講的很清楚。

                                                                                      

Pytorch釋出已經有一段時間了,我們在使用中也發現了其獨特的動態圖設計,讓我們可以高效地進行神經網路的構造、實現我們的想法。那麼Pytorch是怎麼來的,追根溯源,pytorch可以說是torch的python版,然後增加了很多新的特性,那麼pytorch和torch的具體區別是什麼,這篇文章大致對兩者進行一下簡要分析,有一個巨集觀的瞭解。

《淺談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語言那還有C++了,因為Pytorch吸收結合了caffe2,進行了很多程式碼合併,現在Pytorch的底層雖然大部分還是C語言,但是介面什麼的也逐漸向C++過渡。

目前來看,兩者的底層庫的C語言部分區別還是不大,儘管Pytorch使用了C++介面,但是由於程式碼的相容性,使用torch拓展的底層程式碼在Pytorch中照樣可以編譯使用。

《淺談Pytorch與Torch的關係》

編寫模型方面的區別

我們來簡單說一下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,__initupdateOutput和上面對應的__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:

《淺談Pytorch與Torch的關係》

torch:

《淺談Pytorch與Torch的關係》

依賴庫區別

Pytorch藉助於Python強大的第三方庫,已經存在的庫可以直接使用,利用我們的影象讀取直接使用Python自帶的PIL影象庫或者python-opencv都可以,其他各種想要實現的功能都可以利用python強大的第三方庫實現:

而在torch中同樣有很多Lua語言下開發的很多包:

《淺談Pytorch與Torch的關係》

torch可以很方便地拓展cuda和c程式碼實現更加豐富的自定義層和演算法操作。

後記

暫且說這麼多,Pytorch和Torch都很優秀,現在仍然有很多優秀的專案是使用torch來編寫,Pytorch和torch的思想都值得我們去借鑑,閒暇之餘,我們也可以看看Torch的程式碼,體驗一下其優秀的構架和設計。