天天看點

python interpreter 中沒有torch_博特智能|淺談Pytorch與Torch的關系

前言

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

python interpreter 中沒有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中照樣可以編譯使用。

python interpreter 中沒有torch_博特智能|淺談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,

__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:

python interpreter 中沒有torch_博特智能|淺談Pytorch與Torch的關系

torch:

python interpreter 中沒有torch_博特智能|淺談Pytorch與Torch的關系

依賴庫差別

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

https://oldpan.me/archives/pytorch-transforms-opencv-scikit-image https://oldpan.me/archives/pytorch-tensor-image-transform

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

python interpreter 中沒有torch_博特智能|淺談Pytorch與Torch的關系

torch可以很友善地拓展cuda和c代碼實作更加豐富的自定義層和算法操作。

而pytorch的可以看這裡:https://oldpan.me/archives/pytorch-combine-c-and-cuda

後記

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

繼續閱讀