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()
时间: 2024-11-04 08:41:26

Torch实现ReQU,和梯度验证的相关文章

Deep Learning 调参

整理一下如何调参,开始是准备翻译,后来加入了一些自己的理解,有少部分不是很确定的没有写出来,如果有问题可以看原文,在末尾有写出.水平有限,如果有错误请指出. 获取数据:确保有足够多的高质量输入-输出的数据集,而且要有代表性. 有时并没有这么大的数据集,比如字符识别中对mnist数据库的训练,很容易就可以达到98%的识别率,但是真正用在实际中会发现效果并没有那么好,把数据库的图片存到硬盘看一下,会发现几乎所有字体都在图片正中,大小几乎一样,而且没有大幅度的旋转,所以这里图片的代表性就不够强,有必要

Pytorch 之 backward

首先看这个自动求导的参数: grad_variables:形状与variable一致,对于y.backward(),grad_variables相当于链式法则dz/dx=dz/dy × dy/dx 中的 dz/dy.grad_variables也可以是tensor或序列. retain_graph:反向传播需要缓存一些中间结果,反向传播之后,这些缓存就被清空,可通过指定这个参数不清空缓存,用来多次反向传播. create_graph:对反向传播过程再次构建计算图,可通过backward of b

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

神经网络 来源于这里. 神经网络可以使用torch.nn包构建. 现在你对autograd已经有了初步的了解,nn依赖于autograd定义模型并区分它们.一个nn.Module包含了层(layers),和一个用来返回output的方法forward(input). 以下面这个区分数字图像的网络为例: 上图是一个简单的前馈网络.它接受输入,一个层接一层地通过几层网络,最后给出输出. 典型的神经网络训练程序如下: 定义具有一些可学习参数(或权重)的神经网络 迭代输入的数据集 通过网络处理输入 计算

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

一.介绍 内容 将接触现代 NLP 技术的基础:词向量技术. 第一个是构建一个简单的 N-Gram 语言模型,它可以根据 N 个历史词汇预测下一个单词,从而得到每一个单词的向量表示. 第二个将接触到现代词向量技术常用的模型 Word2Vec.在实验中将以小说<三体>为例,展示了小语料在 Word2Vec 模型中能够取得的效果. 在最后一个将加载已经训练好的一个大规模词向量,并利用这些词向量来做一些简单的运算和测试,以探索词向量中包含的语义信息. 知识点 N-Gram(NPLM) 语言模型 Wo

七、Sparse Autoencoder介绍

目前为止,我们已经讨论了神经网络在有监督学习中的应用.在有监督学习中,训练样本是有类别标签的.现在假设我们只有一个没有带类别标签的训练样本集合  ,其中  .自编码神经网络是一种无监督学习算法,它使用了反向传播算法,并让目标值等于输入值,比如  .下图是一个自编码神经网络的示例. 自编码神经网络尝试学习一个  的函数.换句话说,它尝试逼近一个恒等函数,从而使得输出  接近于输入  .恒等函数虽然看上去不太有学习的意义,但是当我们为自编码神经网络加入某些限制,比如限定隐藏神经元的数量,我们就可以从

神经网络学习笔记-入门篇*

1简单模型 vs 复杂模型 对于一个崭新的机器学习的任务,在模型选取和特征向量获取上通常我们会有两种选择方式:a. 简单模型 + 复杂特征项:b. 复杂模型 + 简单特征项.这两种方式各有各的优缺点: 1.1 简单模型 对于简单模型来说,其优点是容易理解.可解释性较强,但是为了达到相对好的预测效果,我们通常会考虑对原始特征进一步抽象,增加大量的特征项来弥补model在处理非线性问题上的缺陷: 假设我们现在有一个学习任务,首先我们抽取出100个不相关的特征属性,然后我们想要尝试使用逻辑回归(LR)

PyTorch 1.0 中文官方教程:使用 PyTorch 进行图像风格转换

译者:bdqfork 作者: Alexis Jacq 简介 本教程主要讲解如何实现由Leon A. Gatys,Alexander S. Ecker和Matthias Bethge提出的 Neural-Style 算法.Neural-Style或者叫Neural-Transfer,可以让你使用一种新的风格将指定的图片进行重构.这个算法使用三张图片,一张输入图片,一张内容图片和一张风格图片,并将输入的图片变得与内容图片相似,且拥有风格图片的优美风格. 基本原理 原理很简单:我们定义两个间距,一个用

用Pytorch训练线性回归模型

假定我们要拟合的线性方程是:\(y=2x+1\) \(x\):[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14] \(y\):[1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29] import torch import torch.nn as nn from torch.autograd import Variable import numpy as np import matplotli

百面机器学习

百面机器学习是一本记录面试问题的书,一方面,学习里面的问题和解答有助于我们更好的掌握机器学习,另一方面,以目录为索引,可以扩展我们的知识面,掌握应届生从事机器学习必备的技能.下面以章节为单位,记录书本的大纲内容. 第1章 特征工程 01 为什么要对数值类型的特征做归一化? 对数值类型的特征做归一化可以将所有特征统一到一个大致相同的区间,加快梯度下降更新速度.最常用的有:线性函数归一化(Min-Max Scaling)(将原始数据映射到[0,1]的范围)以及零均值归一化(Z-Score Norma