Torch7入门续集(三)----Simple Layers的妙用
来源:互联网 发布:简阳市环保局何知云 编辑:程序博客网 时间:2024/05/16 13:51
总说
先看一段代码,一般来说传入VGG的数据要先经过预处理,无非是先将BGR变成RGB,然后减去整个训练集的平均RGB值。写的最精简的可能是下面这样写。
function preprocess(img) local mean_pixel = torch.FloatTensor({103.939, 116.779, 123.68}):type(img:type()) local perm = torch.LongTensor{3, 2, 1} img = img:index(1, perm):mul(255.0) mean_pixel = mean_pixel:view(3, 1, 1):expandAs(img) img:add(-1, mean_pixel) return imgend
然而。。请看下面的这种写法:
function getPreprocessConv() local mean_pixel = torch.Tensor({103.939, 116.779, 123.68}) local conv = nn.SpatialConvolution(3,3, 1,1) conv.weight:zero() conv.weight[{1,3}] = 255 conv.weight[{2,2}] = 255 conv.weight[{3,1}] = 255 conv.bias = -mean_pixel conv.gradBias = nil conv.gradWeight = nil conv.parameters = function() --[[nop]] end conv.accGradParameters = function() --[[nop]] end return convend
没错,直接用内置的卷积层进行操作!这启发我们一件事情:很多常见操作,我们都可以用内置的已有的各种层进行!而不是自己单独写,这就相当于nn层式编码!。。自创的词,大概知道就行。
Simple Layers就是一些常见的层操作,利用这些函数可以便捷的在某层后面加入各种操作层,这些操作层可以直接进行反向传播。
Simple Layers主要分为4个部分:
带参的Module—-> 基本Tensor变换——->数学Tensor运算——>其他Module
前面两篇写的就是Tensor和Math的,而在这里第二三正是利用这些简单层来替代Tensor变换和Math操作。
Parameterized Modules
- Linear
- Bilinear
- Dropout
- Abs
- Add
- CAdd
- Mul
- CMul
- Euclidean
- WeightedEuclidean
- Cosine
从名字就可以大概看出这些层的作用,比如Linear就是全连接层。Bilinear就是进行双线性插值。
Dropout
module= nn.Dropout(p)
训练前向:使得输入每个值按照p的概率丢弃,即使得该位置的值为0。同时输出大小的值被放大1/(1-p)
,主要是用来进行正规化的。
训练反向:被前向丢弃的位置仍旧为0,gradOutput
和input
都被放大1/(1-p)
倍。
module = nn.Dropout()> module:forward(x) 0 4 0 0 10 12 0 16[torch.DoubleTensor of dimension 2x4]> module:backward(x, x:clone():fill(1)) 0 2 0 0 2 2 0 2[torch.DoubleTensor of dimension 2x4]
evaluation时:直接将输入的东西原封不动传出
> module:evaluate()> module:forward(x) 1 2 3 4 5 6 7 8[torch.DoubleTensor of dimension 2x4]
Cosine
文档竟然这么简洁,Euclidean ,Cosine用法一个例子都没有。 module=nn.Cosine(inputSize, outputSize)
require "nn"require "torch"local t = torch.randn(6):mul(3):floor()print('input:')print(t)local net = nn.Sequential()modual = nn.Cosine(6,4)net:add(modual)local w = torch.randn(4,6):mul(3):floor()net:get(1).weight = wprint('weight:')print(net:get(1).weight)local result = net:forward(t)print('result:')print(result)for i = 1,(#w)[1] do print('time:'..i) local tm = t:norm() local wm = net:get(1).weight[i]:norm() print('input'..i..'\tnorm:'..tm) print('weight'..i..'\tnorm:'..wm) print(torch.dot(t,w[i])/(tm*wm)) print(result[i]) assert((torch.dot(t,w[i])/(tm*wm) - result[i]) < 1e-10) print('')endinput:-2-5-4-2 0-1[torch.DoubleTensor of size 6]weight:-2 6 -1 -1 4 1 5 2 0 -2 4 2 2 6 1 -4 1 5 1 0 0 -2 -1 -3[torch.DoubleTensor of size 4x6]result:-0.3866-0.3497-0.5433 0.1826[torch.DoubleTensor of size 4]time:1input1 norm:7.0710678118655weight1 norm:7.6811457478686-0.3866413395173-0.38664133951719time:2input2 norm:7.0710678118655weight2 norm:7.2801098892805-0.34966291044862-0.34966291044852time:3input3 norm:7.0710678118655weight3 norm:9.1104335791443-0.54330536799443-0.5433053679943
Input是6x1,必须是vector; Cosine层的weight是N*6, 然后每个weight[i]与input进行内积,然后再normalize一下。简单来说就是:
inputDim: aweightDim: N*aouput: N
基本Tensor变换
Identity
这个是输入什么,直接输出什么。在用ParallelTable或是ConcatTable时特别有用。
-- Returns a network that computes the CxC Gram matrix from inputs-- of size C x H x Wfunction GramMatrix() local net = nn.Sequential() net:add(nn.View(-1):setNumInputDims(2)) local concat = nn.ConcatTable() concat:add(nn.Identity()) concat:add(nn.Identity()) net:add(concat) net:add(nn.MM(false, true)) return netend
Replicate
module = nn.Replicate(nFeature [, dim, ndim])
默认在第一维度进行复制,这个和以前的Tensor操作一样,没有内存的复制,只是将stride置为0了。
> x = torch.linspace(1, 5, 5) 1 2 3 4 5[torch.DoubleTensor of dimension 5]> m = nn.Replicate(3)> o = m:forward(x) 1 2 3 4 5 1 2 3 4 5 1 2 3 4 5[torch.DoubleTensor of dimension 3x5]
Reshape/View
Reshape可以被View代替
> x = torch.Tensor(4, 4)> for i = 1, 4 do> for j = 1, 4 do> x[i][j] = (i-1)*4+j> end> end> print(x) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16[torch.Tensor of dimension 4x4]> print(nn.View(2, 8):forward(x)) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16[torch.DoubleTensor of dimension 2x8]-- size可以是numbers或是LongStorage都行。> print(nn.View(torch.LongStorage{8,2}):forward(x)) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16[torch.DoubleTensor of dimension 8x2]> print(nn.View(16):forward(x)) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16[torch.DoubleTensor of dimension 16]
不想说什么了,Torch的文档真垃圾!写都写不明白!看的我火大!
View的功能更加强大,其中setNumInputDims()可以指定希望输入的维度的数量,一般是和view(-1)连用,这样可以实现minibatch 的输入
> input = torch.Tensor(2, 3)> minibatch = torch.Tensor(5, 2, 3)> m = nn.View(-1):setNumInputDims(2)> print(#m:forward(input)) 6[torch.LongStorage of size 1]> print(#m:forward(minibatch)) 5 6[torch.LongStorage of size 2]
重点:
View(-1):setNumInputDims(2)这两个是连用的!
应该这样考虑,
1. 首先获取原始输入的维度,view(-1)是将输入全部变成1维的,相当于1*6.
2. 再根据setNumInputDims(2)知道,要把原始大小为2x3的input的倒数2个维度看成是一个sample。
3. 然后我input被拉成向量后总共就1x6个数,这里把倒数2个维度看成是一个sample,也就是每个sample是6个数,所以input就一个sample,或是说batchsize=1
再看看minibatch,minibatch是5x2x3,setNumInputDims(2)是将2x3看成一个sample,所以,这里有5个sample。输出的大小就变成 5x6。
Unsqueeze/Squeeze
module = nn.Unsqueeze(pos [, numInputDims])
unsqueeze是在pos位置插入1.
pos = 1: 1 x p x q x rpos = 2: p x 1 x q x rpos = 3: p x q x 1 x rpos = 4: p x q x r x 1
一般来说在第一个位置进行Unsqueeze,同时要指定numInputDims才可以实现minibatch
b = 5 -- batch size 5input = torch.Tensor(b, 2, 4, 3) -- input: b x 2 x 4 x 3numInputDims = 3 -- input feature map should be the last 3 dimsm = nn.Unsqueeze(4, numInputDims)m:forward(input) -- output: b x 2 x 4 x 3 x 1m = nn.Unsqueeze(2):setNumInputDims(numInputDims)m:forward(input) -- output: b x 2 x 1 x 4 x 3
MM/Clamp等略
- Torch7入门续集(三)----Simple Layers的妙用
- Torch7入门续集(四)----利用Table layers构建灵活的网络
- Torch7入门续集(二)---- 更好的使用Math函数
- Torch7入门续集补充(2)--- 每一层设置不同的学习率(finetuning有用)
- Torch7入门续集补充--- nngraph包的使用
- Torch7入门续集(一)----- 更加深入理解Tensor
- Torch7入门续集(六)----多GPU运行程序
- Torch7入门续集(七)--- clone与net替换某一层
- Torch7入门续集(八)---终结篇----不再写Torch博客了,反正就是难受
- torch7入门
- Torch7深度学习教程(三)
- 第一章 JAVA入门(Eclipse续集)
- 我是如何入门Git(续集)?
- 我是如何入门Git(续续集)?
- Torch7学习(三)——学习神经网络包的用法(1)
- 算法笔记(三):floyd的妙用
- Pytorch学习入门(一)--- 从torch7跳坑至pytorch --- Tensor
- Spring MVC 入门续集
- 求一个整数的位数,输出它,以及逆序
- hdu 1002大数加法
- 入门Webpack,看这篇就够了
- SQL概述—JDBC学习笔记
- java中compareTo和compare方法之比较
- Torch7入门续集(三)----Simple Layers的妙用
- 用户自动建立脚本
- hihocoder 1329 splay 伸展树
- 常用汇编串指令
- socket实现Ping命令
- 如何设置MathType下标的正斜体
- dubbo框架源码剖析- 环境准备[磨刀不误砍柴工]
- 《Effective C++》资源管理章节
- Hugepages介绍和配置