torch.optim

1、

用optim来减少损失

首先需要给出一个函数,给定当前的weight作为参数,可以输出损失和损失对应的梯度

optim希望他们优化的weight和对应的梯度是一个一维的Tensor,但是整个网络有很多层,每一层都有很多的参数,怎么做才能成为一维的Tensor呢?用getParameters()函数即可

params, gradParams = model:getParameters()
这个函数返回params,包含了weight和bias,组成一个全新的Tensor。对于梯度则是由gradParams来承担,组成一个全新的连续的Tensor。我们想要优化的参数全都包含在了这个one-dimension的Tensor里面了

print(self.params:size())
print(self.gradParams:size())

require 'optim'

for epoch = 1, 50 do
   -- local function we give to optim
   -- it takes current weights as input, and outputs the loss
   -- and the gradient of the loss with respect to the weights
   -- gradParams is calculated implicitly by calling 'backward',
   -- because the model's weight and bias gradient tensors
   -- are simply views onto gradParams
   function feval(params)
      gradParams:zero()

      local outputs = model:forward(batchInputs)
      local loss = criterion:forward(outputs, batchLabels)
      local dloss_doutputs = criterion:backward(outputs, batchLabels)
      model:backward(batchInputs, dloss_doutputs)

      return loss, gradParams
   end
   optim.sgd(feval, params, optimState)
end
现在分析一下optim的具体使用细节
feval是一个函数,接受的参数是weight和bias的一维Tensor,返回loss,和参数梯度

optim本身需要接受weight和bias的一维Tensor

optimState是关于更新的一系列的参数

2、

解析一下通常的训练流程运用optim

local function evalFn(x) return criterion.output, gradparam end
local output = model:forward(input)
local err = criterion:forward(output, label)
model:zeroGradParameters()
model:backward(input, criterion:backward(output, label))
optfn(evalFn, param, optimState)
在torch里面有两个状态变量( output  and  gradInput .

1)定义evalFn

2) 前传计算输出,更新output状态变量

3)利用criterion来计算损失,self.output更新(criterion的作用是给定输入和目标,根据损失计算梯度)

4)将参数对应的梯度全部置零

5)model反传,给定input和gradOutput,这里的gradOutput是由criterion进行backward计算得来的,计算关于output的梯度,backward函数接受input和gradOutput,计算关于input的梯度,也即gradInput,这时候会调用两个函数




6)然后用文章一开始的optim进行优化,evalFn返回criterion.output,也即损失,gradparam也即梯度,这是evalFn对参数的要求,然后进行更性参数即可
注:需要注意的是,criterion也有output和gradinput两个状态变量,只不过引用的时候要用criterion.output...和model的output是分开的


另外一种写法,和上文表达的意思是相同的

local function feval()
      return self.criterion.output, self.gradParams
end
local output = self.model:forward(self.input)
local loss = self.criterion:forward(self.model.output, self.target)
self.model:zeroGradParameters()
self.criterion:backward(self.model.output, self.target)               --这一步计算的结果保存在
self.criterion.gradInput中
self.model:backward(self.input, self.criterion.gradInput) --利用上一步计算出来的损失,计算相对于输入的梯度 optim[self.opt.optMethod](feval, self.params, self.optimState)

下面以输入为3*3*256*256输入为例,看看这几个梯度和到底是什么样子

output和loss

print(output)
print(loss)
print(self.model.output)
print(self.criterion.output)


    
print(self.criterion.gradInput)                #gradInput里面计算的是关于output的梯度


    
print(self.model.gradInput:size())           #model里面的gradInput则是关于图像输入的梯度


几个概念:gradInput,gradOutput,gradParam

https://zhuanlan.zhihu.com/p/21550685,里面有详细介绍,再添加新的层的时候必须要做的几个工作


我们平时可以调用的四个变量,model.output, model.gradInput, criterion.output, criterion.gradInput

那么gradParam是通过getParameters来获得的,他不是状态变量,那他是什么时候更新的呢???

前面提到model.backward的时候会计算两个梯度,关于输入的梯度和关于参数的梯度




这里的更新的gradParameters会保留下供未来使用,用于更新参数

当然如果不用optim,可以直接用updateParameters来更新参数的

function gradUpdate(mlp, x, y, criterion, learningRate)
   local pred = mlp:forward(x)
   local err = criterion:forward(pred, y)
   local gradCriterion = criterion:backward(pred, y)
   mlp:zeroGradParameters()
   mlp:backward(x, gradCriterion)
   mlp:updateParameters(learningRate)
end



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值