关于教程/ 2_supervised / 4_train.lua上的feval函数

时间:2016-09-19 10:43:23

标签: lua torch

在gihub上: https://github.com/torch/tutorials/blob/master/2_supervised/4_train.lua 我们有一个定义训练过程的脚本示例。我对这个脚本中feval函数的构造很感兴趣。

-- 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,#输入做... 因此,不是通过输入(输入[i])进行前向和后向输入,而是为整个小批量(输入)执行此操作。这真的加快了这个过程。这是修改脚本:

-- 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 - 没有这个循环可以获得相同的结果吗?

此致 萨姆

注意:我是Torch7的初学者

1 个答案:

答案 0 :(得分:0)

我确定你注意到第二种工作方式需要的不仅仅是改变feval。 在第二个示例中,输入需要是4D张量,而不是3D张量表(除非自上次更新以来发生了某些变化)。根据所使用的损耗标准/模型,这些张量具有不同的尺寸。实施该示例的人必须认为循环是一种更容易的方式。此外,ClassNLLCriterion似乎不喜欢批处理(人们通常会使用CrossEntropy标准来解决这个问题)。

除此之外,这两种方法应该给出相同的结果。唯一的细微差别是第一个示例使用平均误差/渐变,第二个示例使用总和,如下所示:

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

在第二种情况下,f和gradParameters应该与opt.batchSize因子中的第一个不同。出于优化目的,这些在数学上是等效的。