Torch实现ReQU,和梯度验证
重写函数
我们使用torch实现我们自己的ReQU模块。在实现一个新的layer之前,我们必须了解,我们并不是重写forward和backward方法,而是重写里面调用的其它方法。
1)又一次updataOutput方法。从而实现forward方法。
2)重写updataGradInput方法实现部分backward,计算loss函数相对于layer输入的导数,dloss/dx, 依据loss函数相对于layer输出的导数dloss: 
 
3)重写accGradParameters方法实现backward其余部分,计算loss函数相对于权重的导数。
ReQU模块
Rectified Quadratic Unit(ReQU)与sigmoid和ReLU非常类似,这个模块作用于每个元素上: 
 
用矩阵的方式来表达就是: 
 
括号中假设是trues就返回1s,假设是falses就返回0s,中间的符号代表元素级别的乘积
重写updateOutput和updateGradInput模块
在重写模块之前,我们先推导公式,dloss/dx=dloss/dz.*dz/dx=dloss/dz.*2*(x>0).*x 
我们首先重写updateOutput函数。这个函数主要计算输入为input时的输出:
function ReQU:updateOutput(input)
  self.output:resizeAs(input):copy(input)
  self.output:gt(input,0):cmul(input):cmul(input)
  return self.output
end
当中self.output:gt(input,0):cmul(input):cmul(input)这一步比較重要,self.output:gt(input,0)目的把input里面值与0比較,大于0设为1,否则设为0,然后通过两次cmul(input),计算得到正确的输出。 
我们然后重写updateGradInput函数。这个函数的目的是计算loss函数相对于输入的导数:
function ReQU:updateGradInput(input, gradOutput)
  self.gradInput:resizeAs(gradOutput):copy(gradOutput)
  self.gradInput:cmul(self.gradInput:gt(input,0):mul(2):cmul(input),gradOutput)
  return self.gradInput
end
输入是input和gradOutput。通过我们上面推到的公式。通过代码: 
self.gradInput:cmul(self.gradInput:gt(input,0):mul(2):cmul(input),gradOutput)计算得到
构建一个简单神经网络
我们构建一个简单的神经网络,用来训练iris.data.csv里面的数据。我们定义一个function叫做create_model,创建model以及criterion。这个model包含: 
Input——>linear——>non-linearity——>linear——>log softmax——>cross-entropy loss 
Input一共同拥有4个维度。non-linearity选择使用sigmoid或者ReQU。以下是model核心代码:
local model = nn.Sequential()
model:add(nn.Linear(n_inputs, embedding_dim))
if opt.nonlinearity_type == 'requ' then
  model:add(nn.ReQU())
elseif opt.nonlinearity_type == 'sigmoid' then
  model:add(nn.Sigmoid())
else
  error('undefined nonlinearity_type ' .. tostring(opt.nonlinearity_type))
end
model:add(nn.Linear(embedding_dim, n_classes))
local criterion = nn.ClassNLLCriterion()
測试gradient
我们最后得到的cost function为E(w1,…,wn),那么梯度就是分别针对wi求导数,公式例如以下: 
 
所以当计算梯度的时候,我们须要计算所有的偏导数。
我们能够近似的计算偏导数例如以下: 
 
我们使用这个思想来測试我们的神经网络。我们把整个神经网络看成一个方程E(x;w)。然后随机生成x和w,然后利用上述公式预计梯度值,然后我们也使用公式求得觉得正确的梯度值。假设这两个值类似,那么就能够推断我们写的“ReQU”是正确的。推断公式例如以下: 
 
gi是使用两种方式求得的梯度,求得的值假设和ϵ的度相近。那么觉得求得的梯度是正确的。 
代码细节例如以下: 
1)  求正确的梯度:
-- returns dloss(params)/dparams
local g = function(x)
  if x ~= parameters then
    parameters:copy(x)
  end
  gradParameters:zero()
  local outputs = model:forward(data.inputs)
  criterion:forward(outputs, data.targets)
  model:backward(data.inputs, criterion:backward(outputs, data.targets))
  return gradParameters
end
2) 求近似的梯度:
-- compute numeric approximations to gradient
local eps = eps or 1e-4
local grad_est = torch.DoubleTensor(grad:size())
for i = 1, grad:size(1) do
  x[i] = x[i] + eps
  local loss_a = f(x)
  x[i] = x[i] - 2*eps
  local loss_b = f(x)
  x[i] = x[i] + eps
  grad_est[i] = (loss_a-loss_b)/(2*eps)
end
3) 计算两个方法求得的梯度的差:
-- computes (symmetric) relative error of gradient
local diff = torch.norm(grad - grad_est) / torch.norm(grad + grad_est)
測试Jacobian
这里我们測试dz/dx计算的是否正确,我们计算Jacobian矩阵,我们假设有m个样本,每个样本为n维,那么这个Jacobian矩阵就是mxn的矩阵: 
 
第i行是关于第i个样本input的梯度,当中fi表示输出output。我们怎样获得Jacobian矩阵呢?这个矩阵是在backward的updateGradInput中隐性计算的: 
 
为了获得Jacobian矩阵。我们须要构造我们gradOutput vector,使当中一个为1,其余的所有为0,这样就能获得Jacobian一整行,torch代码例如以下:
local z = module:forward(x):clone()
local jac = torch.DoubleTensor(z:size(1), x:size(1))
-- get true Jacobian, ROW BY ROW
local one_hot = torch.zeros(z:size())
for i = 1, z:size(1) do
  one_hot[i] = 1
  jac[i]:copy(module:backward(x, one_hot))
  one_hot[i] = 0
end
我们使用与上一节类似的方法计算近似值: 
 
Torch代码例如以下:
-- compute finite-differences Jacobian, COLUMN BY COLUMN
local jac_est = torch.DoubleTensor(z:size(1), x:size(1))
for i = 1, x:size(1) do
  x[i] = x[i] + eps
  z_offset = module:forward(x):clone()
  x[i] = x[i] - 2*eps
  z_offset=z_offset-module:forward(x)
  x[i] = x[i] + eps
  jac_est[{{},i}]:copy(z_offset):div(2*eps)
end
-- computes (symmetric) relative error of gradient
local abs_diff = (jac - jac_est):abs()
Torch实现ReQU,和梯度验证的更多相关文章
- 《神经网络的梯度推导与代码验证》之CNN前向和反向传播过程的代码验证
		
在<神经网络的梯度推导与代码验证>之CNN的前向传播和反向梯度推导 中,我们学习了CNN的前向传播和反向梯度求导,但知识仍停留在纸面.本篇章将基于深度学习框架tensorflow验证我们所 ...
 - Pytorch实现UNet例子学习
		
参考:https://github.com/milesial/Pytorch-UNet 实现的是二值汽车图像语义分割,包括 dense CRF 后处理. 使用python3,我的环境是python3. ...
 - 深度学习之PyTorch实战(2)——神经网络模型搭建和参数优化
		
上一篇博客先搭建了基础环境,并熟悉了基础知识,本节基于此,再进行深一步的学习. 接下来看看如何基于PyTorch深度学习框架用简单快捷的方式搭建出复杂的神经网络模型,同时让模型参数的优化方法趋于高效. ...
 - Pytorch 之 backward
		
首先看这个自动求导的参数: grad_variables:形状与variable一致,对于y.backward(),grad_variables相当于链式法则dz/dx=dz/dy × dy/dx 中 ...
 - pytorch adam 源码   关于优化函数的调整 optimizer 调参  重点
		
关于优化函数的调整拆下包:https://ptorch.com/docs/1/optim class torch.optim.Optimizer(params, defaults)所有优化的基类. 参 ...
 - PyTorch基础——词向量(Word Vector)技术
		
一.介绍 内容 将接触现代 NLP 技术的基础:词向量技术. 第一个是构建一个简单的 N-Gram 语言模型,它可以根据 N 个历史词汇预测下一个单词,从而得到每一个单词的向量表示. 第二个将接触到现 ...
 - [PyTorch入门之60分钟入门闪击战]之神经网络
		
神经网络 来源于这里. 神经网络可以使用torch.nn包构建. 现在你对autograd已经有了初步的了解,nn依赖于autograd定义模型并区分它们.一个nn.Module包含了层(layers ...
 - 多层感知机及其BP算法(Multi-Layer Perception)
		
Deep Learning 近年来在各个领域都取得了 state-of-the-art 的效果,对于原始未加工且单独不可解释的特征尤为有效,传统的方法依赖手工选取特征,而 Neural Network ...
 - (六)6.4 Neurons Networks Autoencoders and Sparsity
		
BP算法是适合监督学习的,因为要计算损失函数,计算时y值又是必不可少的,现在假设有一系列的无标签train data: ,其中 ,autoencoders是一种无监督学习算法,它使用了本身作为标签以 ...
 
随机推荐
- 数学图形(2.13)Spherical trochoid曲线
			
该曲线与上一节的herical cycloid球面外摆曲线 很相似,难道这是球面内摆曲线? #http://www.mathcurve.com/courbes3d/cycloidspheric/tro ...
 - UTC 转本地时间
			
String dateStr = "Wed Dec 10 00:00:00 UTC 0800 2014"; //Wed Dec 10 00:00:00 UTC 0800 2014 ...
 - Scurm 术语
			
角色 Product Owner Scrum Master Team 工件(Backlog) Product Backlog Sprint Backlog Burndown Backlog 活动 Sp ...
 - Thinkphp学习笔记1-URL模式
			
PATHINFO模式 PATHINFO模式是系统的默认URL模式,提供了最好的SEO支持,系统内部已经做了环境的兼容处理,所以能够支持大多数的主机环境.对应上面的URL模式,PATHINFO模式下面的 ...
 - windows下读取Linux分区软件
			
导读 ext3等日志型文件系统是Linux中被广泛应用的,通常是许多流行Linux发行版默认的文件系统.etx4也是Linux下的日志型文件系统,被设计作为ext3的继任者.他消除了64位存储限制,是 ...
 - (转) 问题解决:Apache: You don't have permission to access / on this server
			
问题解决:Apache: You don't have permission to access / on this server 转自:http://blog.csdn.net/crazyboy20 ...
 - 如何用 js 递归输出树型
			
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <m ...
 - html中块注释<!--[if IE]>….<![endif]--> (<!--[if !IE]>||<![endif]
			
1. <!--[if !IE]><!--> 除IE外都可识别 <!--<![endif]-->2. <!--[if IE]> 所有的IE可识别 & ...
 - 关于CPU的运行队列与系统负载
			
在linux操作系统中,我们一般查看系统的cpu负载情况常用的命令可以是uptime,top,还有vmstat等这些个都是可以有的.每个工具所提供的信息各不相同, 我这里要讨论的仅说cpu部分.使用u ...
 - Spring 的ioc
			
Spring的两个非常重要的功能ioc和aop 依赖反转:依赖对象的获得被反转:很多非凡的应用都是由两个或多个类通过彼此的合作来上线业务逻辑.这使得每一个对象都须要与其它对象合作,也就是说 一个对象获 ...