重写函数

我们使用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,和梯度验证的更多相关文章

  1. 《神经网络的梯度推导与代码验证》之CNN前向和反向传播过程的代码验证

    在<神经网络的梯度推导与代码验证>之CNN的前向传播和反向梯度推导 中,我们学习了CNN的前向传播和反向梯度求导,但知识仍停留在纸面.本篇章将基于深度学习框架tensorflow验证我们所 ...

  2. Pytorch实现UNet例子学习

    参考:https://github.com/milesial/Pytorch-UNet 实现的是二值汽车图像语义分割,包括 dense CRF 后处理. 使用python3,我的环境是python3. ...

  3. 深度学习之PyTorch实战(2)——神经网络模型搭建和参数优化

    上一篇博客先搭建了基础环境,并熟悉了基础知识,本节基于此,再进行深一步的学习. 接下来看看如何基于PyTorch深度学习框架用简单快捷的方式搭建出复杂的神经网络模型,同时让模型参数的优化方法趋于高效. ...

  4. Pytorch 之 backward

    首先看这个自动求导的参数: grad_variables:形状与variable一致,对于y.backward(),grad_variables相当于链式法则dz/dx=dz/dy × dy/dx 中 ...

  5. pytorch adam 源码 关于优化函数的调整 optimizer 调参 重点

    关于优化函数的调整拆下包:https://ptorch.com/docs/1/optim class torch.optim.Optimizer(params, defaults)所有优化的基类. 参 ...

  6. PyTorch基础——词向量(Word Vector)技术

    一.介绍 内容 将接触现代 NLP 技术的基础:词向量技术. 第一个是构建一个简单的 N-Gram 语言模型,它可以根据 N 个历史词汇预测下一个单词,从而得到每一个单词的向量表示. 第二个将接触到现 ...

  7. [PyTorch入门之60分钟入门闪击战]之神经网络

    神经网络 来源于这里. 神经网络可以使用torch.nn包构建. 现在你对autograd已经有了初步的了解,nn依赖于autograd定义模型并区分它们.一个nn.Module包含了层(layers ...

  8. 多层感知机及其BP算法(Multi-Layer Perception)

    Deep Learning 近年来在各个领域都取得了 state-of-the-art 的效果,对于原始未加工且单独不可解释的特征尤为有效,传统的方法依赖手工选取特征,而 Neural Network ...

  9. (六)6.4 Neurons Networks Autoencoders and Sparsity

    BP算法是适合监督学习的,因为要计算损失函数,计算时y值又是必不可少的,现在假设有一系列的无标签train data:  ,其中 ,autoencoders是一种无监督学习算法,它使用了本身作为标签以 ...

随机推荐

  1. jeecms运行出现 Expected to read 4 bytes, read 0 bytes before connection was unexpectedly lost.解决

    在/WEB-INF/config/application-context.xml中添加红色字体内容: <bean id="dataSource" class="co ...

  2. 集成禅道和svn

    转载:http://www.zentao.net/book/zentaopmshelp/137.html 说明:svn集成功能配置会比较复杂,我们会尽量通过文档来帮助大家配置成功!如果实在配置不成功的 ...

  3. Nginx安装及配置文件解释

    安装nginx,还是在mac上面用brew比较方便. 首先,brew install nginx,提示改权限 sudo chown -R $(whoami) /usr/local 然后brew ins ...

  4. 设置tomcat配置文件,在Myeclipse中修改jsp文件之后不用重启tomcat

    在Myeclipse中创建的Web程序在修改类或者jsp页面后需要重动ttomcat的,要重新加载一次的,即重新启动tomcat一次.重启时比较慢,及浪费资源及时间, 设置tomcat配置文件,在My ...

  5. 友元程序集(C# 和 Visual Basic)

    友元程序集(C# 和 Visual Basic) Visual Studio 2013 “友元程序集”是一种能够访问其他程序集的 Friend (Visual Basic) 或 internal (C ...

  6. data目录和binlog目录搬迁的方法

    刚开始安装时使用了默认目录,使用一段时间,数据慢慢变在,发现当前设置的目录空间不够时,就要搬迁数据到另一个目录了 如果全过程使用的是Mysql用户,应该可以正常启动. 如果用的ROOT用户,可能不能正 ...

  7. windows下安装msysgit 及ruby

    一:安装msysgit git是目前最流行的软件版本控制软件,在window下通常使用msysgit 下载:http://msysgit.github.io/ 安装:基本上一路默认下一步就行 安装之后 ...

  8. input 禁止 复制 粘贴 剪切 操作

    1.代码 <Input onCopy={(e)=>{ // 禁止拷贝 e.preventDefault(); }} onPaste={(e)=>{ // 禁止粘贴 e.prevent ...

  9. CLightLock:一个简单AutoLock

    原理: 标准的RAII, 利用构造函数进行加锁,利用析构函数进行解锁. #ifndef _C_LIGTHT_LOCK_HPP #define _C_LIGTHT_LOCK_HPP class CLig ...

  10. 〖Linux〗proc的一些文件读取操作

    /* * ===================================================================================== * * Filen ...