2016-09-19 59 views
2

關於gihub: https://github.com/torch/tutorials/blob/master/2_supervised/4_train.lua 我們有一個定義培訓過程的腳本示例。我對這個腳本中的feval函數的構造感興趣。關於教程中的feval函數/ 2_supervised/4_train.lua

-- create closure to evaluate f(X) and df/dX 
local feval = function(x) 
     -- get new parameters 
     if x ~= parameters then 
     parameters:copy(x) 
     end 

     -- reset gradients 
     gradParameters:zero() 

     -- f is the average of all criterions 
     local f = 0 

     -- evaluate function for complete mini batch 
     for i = 1,#inputs do 
      -- estimate f 
      local output = model:forward(inputs[i]) 
      local err = criterion:forward(output, targets[i]) 
      f = f + err 

      -- estimate df/dW 
      local df_do = criterion:backward(output, targets[i]) 
      model:backward(inputs[i], df_do) 

      -- update confusion 
      confusion:add(output, targets[i]) 
     end 

     -- normalize gradients and f(X) 
     gradParameters:div(#inputs) 
     f = f/#inputs 

     -- return f and df/dX 
     return f,gradParameters 
     end 

我試圖通過抑制循環修改此功能: 對於i = 1,#投入做... 因此,而不是通過輸入做正向和反向輸入(輸入[1])我」爲整個小批量生產(投入)。這真的加快了這個過程。這是修改腳本:

-- create closure to evaluate f(X) and df/dX 
local feval = function(x) 
     -- get new parameters 
     if x ~= parameters then 
     parameters:copy(x) 
     end 

     -- reset gradients 
     gradParameters:zero() 

     -- f is the average of all criterions 
     local f = 0 
     -- evaluate function for complete mini batch 

     -- estimate f 
     local output = model:forward(inputs) 
     local f = criterion:forward(output, targets) 

     -- estimate df/dW 
     local df_do = criterion:backward(output, targets) 

     -- update weight 
     model:backward(inputs, df_do) 

     -- update confusion 
     confusion:batchAdd(output, targets) 

     -- return f and df/dX 
     return f,gradParameters 
     end 

但是當我詳細檢查feval(F,gradParameters)的迴歸對於給定的小批量,我們有不一樣的結果與循環和不循環。

所以我的問題是: 1 - 爲什麼我們有這個循環? 2 - 是否有可能得到相同的結果沒有這個循環?

問候 山姆

NB:我是初學者在Torch7

回答

0

我敢肯定,你注意到了獲得第二個方式工作需要的不僅僅是簡單地改變feval多一點。 在第二個示例中,輸入需要是4D張量,而不是3D張量表(除非自上次更新後發生了某些變化)。這些張量根據所使用的損失標準/模型而具有不同的尺寸。實施這個例子的人肯定會認爲這個循環是一個更簡單的方法。另外,ClassNLLCriterion看起來並不像批處理(通常使用CrossEntropy標準來解決這個問題)。

儘管如此,這兩種方法應該給出相同的結果。唯一的小的區別是,第一實施例使用平均誤差/梯度,和第二個使用的總和,這可以從參見:

    gradParameters:div(inputs:size(1)) 
        f = f/inputs:size(1) 

在第二種情況下,f和gradParameters應該從第一區別僅在一個因子opt.batchSize中。這些在數學上等同於優化目的。

+0

謝謝桑德的答案。我同意因爲抑制循環,我們需要在輸入中增加一個維度。我已經添加了CrossEntropy而不是ClassNLLCriterion,但它並沒有改變很多結果。但我已經添加其他的事情,似乎更好這兩種方法的結果收斂,但我真的不明白爲什麼,它序:nn.Sequencer(模型) 標準= nn.SequencerCriterion(nn.CrossEntropyCriterion(重量)) – user3542259

+0

嗨,山姆。我不確定我是否理解這個問題。 CrossEntropy應該和LogSoftMax + ClassNLLCriterion一樣,但支持批處理,所以你不會期望結果發生變化。 – Sander

+0

是CrossEntropy不會改變結果。但nn.Sequencer確實。 nn.Sequencer順序在輸入數據中很重要,並且結果似乎接近循環獲得的結果,但我不知道爲什麼。 – user3542259