Torch7入门续集(四)----利用Table layers构建灵活的网络

总说

先附加几个有用的。

replace(function)

这个可以是将function应用到net中每一层上。比如,我们可以将model中的nn.Dropout替换成nn.Identity(),显然传入的参数module随便写成什么变量,都指某一层。

model:replace(function(module)
   if torch.typename(module) == 'nn.Dropout' then
      return nn.Identity()
   else
      return module
   end
end)

apply(function)

这个和上面的类似,也是对每一层进行操作。

local function weights_init(m)
   local name = torch.type(m)
   if name:find('Convolution') then
      m.weight:normal(0.0, 0.02)
      m.bias:fill(0)
   elseif name:find('BatchNormalization') then
      if m.weight then m.weight:normal(1.0, 0.02) end
      if m.bias then m.bias:fill(0) end
   end
end

-- define net
...
net:apply(weights_init)  --这样就把net的每一层自定义初始化参数了

remove和insert

有时候我们想直接移除某一层,或是中间添加一层。

model = nn.Sequential()
model:add(nn.Linear(10, 20))
model:add(nn.Linear(20, 20))
model:add(nn.Linear(20, 30))

-- 直接写移除的层的index即可
model:remove(2)
> model
nn.Sequential {
  [input -> (1) -> (2) -> output]
  (1): nn.Linear(10 -> 20)
  (2): nn.Linear(20 -> 30)
}

对于insert,

model = nn.Sequential()
model:add(nn.Linear(10, 20))
model:add(nn.Linear(20, 30))
-- 希望插入的Linear(20,20)在model中的第二层
model:insert(nn.Linear(20, 20), 2)
> model
nn.Sequential {
  [input -> (1) -> (2) -> (3) -> output]
  (1): nn.Linear(10 -> 20)
  (2): nn.Linear(20 -> 20)      -- The inserted layer
  (3): nn.Linear(20 -> 30)
}

training()和evaluate()

对于Dropout和BN之类的层,训练和测试的操作不一样。
这时候可以用
model:training()或是model:evaluate()进行。
apply函数类似上面的replace函数。
下面是training()的实现方式。

model:apply(function(module)
   module.train = true
end)

convolution

一般来说用的最多的还是SpatialConvolution和反卷积SpatialFullConvolution. 当然你可能会加点SpatialBatchNormalization之类的。
我们也可以用convolution的方式来单独padding。分为0 padding,’反射 padding’以及和复制 padding.
module = nn.SpatialZeroPadding(padLeft, padRight, padTop, padBottom)
module = nn.SpatialReflectionPadding(padLeft, padRight, padTop, padBottom)
module = nn.SpatialReplicationPadding(padLeft, padRight, padTop, padBottom)
对于这3种中的任意一种,我们可以直接通过pad的值为负数,从而实现裁剪的功能。
比如
module = nn.SpatialZeroPadding(-1,0,-1,0)就是左边和上面分别裁去一个像素。

Table Layers

正因为由table layers才能使得Torch能够构建非常灵活强大的网络。

ConcatTable与ParrelTable

对于ConcatTable就是,将一个输入喂入每一个成员里,每个成员接收到的内容都是一样的。相当于复制了n份。

                  +-----------+
             +----> {member1, |
+-------+    |    |           |
| input +----+---->  member2, |
+-------+    |    |           |
   or        +---->  member3} |
 {input}          +-----------+
mlp = nn.ConcatTable()
-- 可以看到下面的nn.Linear都是接受5个维度的输入,因为
-- 两个member都接受相同的一个输入。
mlp:add(nn.Linear(5, 2))
mlp:add(nn.Linear(5, 3))

pred = mlp:forward(torch.randn(5))
for i, k in ipairs(pred) do print(i, k) end
-- 可以看到
1
-0.4073
 0.0110
[torch.Tensor of dimension 2]

2
 0.0027
-0.0598
-0.1189
[torch.Tensor of dimension 3]

对应的是ParallelTable,它是输入是几份,就要有几个成员,是按顺序一一对应的!而ConcatTable是输入是一份,但是成员是n个,输入是”复制成n份“,然后给每个成员一份的。

+----------+         +-----------+
| {input1, +---------> {member1, |
|          |         |           |
|  input2, +--------->  member2, |
|          |         |           |
|  input3} +--------->  member3} |
+----------+         +-----------+
mlp = nn.ParallelTable()
-- 可以看到,ParallelTable中,每个input是独立的。
-- 每个memberi接受对应的输入inputi
mlp:add(nn.Linear(10, 2))
mlp:add(nn.Linear(5, 3))

x = torch.randn(10)
y = torch.rand(5)

-- parallelTable后面添加了2个member,因此输入也是2个。用table的形式输入{x,y}
pred = mlp:forward{x, y} 
for i, k in pairs(pred) do print(i, k) end

1
 0.0331
 0.7003
[torch.Tensor of dimension 2]

2
 0.0677
-0.1657
-0.7383
[torch.Tensor of dimension 3]

JoinTable

这个主要是将多个输出联合起来,那自然就要指定联合的维度。

module = JoinTable(dimension, nInputDims)

第一个参数是在第几个维度上联合,第二个参数表示每个输入的维度大小
值得注意的是,联合起来的table必须在除了第dimension的维度之外,其他维度必须相同!这个,显然的。否则就乱套了。

x = torch.randn(5, 1)
y = torch.randn(5, 1)
z = torch.randn(2, 1)

print(nn.JoinTable(1):forward{x, y})
print(nn.JoinTable(2):forward{x, y})
print(nn.JoinTable(1):forward{x, z})

 1.3965
 0.5146
-1.5244
-0.9540
 0.4256
 0.1575
 0.4491
 0.6580
 0.1784
-1.7362
[torch.DoubleTensor of dimension 10x1]

 1.3965  0.1575
 0.5146  0.4491
-1.5244  0.6580
-0.9540  0.1784
 0.4256 -1.7362
[torch.DoubleTensor of dimension 5x2]

-- x,z 在第一个维度上联合,其余维度是相同的。
 1.3965
 0.5146
-1.5244
-0.9540
 0.4256
-1.2660
 1.0869
[torch.Tensor of dimension 7x1]

常用的应该就是这3个,当然还有其他很多。
table和tensor之间相互转换的除了JoinTable。还有SplitTable等。

每个输入的相似性度量

CosineDistance

这个属于module之间相互计算测量值的一种层。

mlp = nn.CosineDistance()
x = torch.Tensor({{1,2,3},{1,2,-3}})
y = torch.Tensor({{4,5,6},{-4,5,6}})
print(mlp:forward({x,y}))

-- {1 2 3}{4 5 6}
-- {1 2 -3}{-4 5 6}
 0.9746
-0.3655
[torch.DoubleTensor of size 2]

这个和Simple Layers的Cosine的用法还是有很大区别的。
类似的还有PairewiseDistanceDotProduct.

每个输入进行element-wise 操作

就是加减乘除以及最大最小,6种运算。
比如CAddTable,…, CDivTable(),以及CMaxTable和CMinTable。

-- 显然两个操作的输入的维度要相同。
m = nn.CDivTable()
a = torch.randn(4,5):mul(4):floor()
b = torch.Tensor(a:size()):fill(2)

th> a
 1  2 -6  0  1
 5  0 -2  8 -8
-1 -1  4  9  7
-7 -5 -4  0  5
[torch.DoubleTensor of size 4x5]

 >th m:forward({a,b})
 0.5000  1.0000 -3.0000  0.0000  0.5000
 2.5000  0.0000 -1.0000  4.0000 -4.0000
-0.5000 -0.5000  2.0000  4.5000  3.5000
-3.5000 -2.5000 -2.0000  0.0000  2.5000
[torch.DoubleTensor of size 4x5]

CriterionTable

mlp = nn.CriterionTable(nn.MSECriterion())
x = torch.randn(5)
y = torch.randn(5)
print(mlp:forward{x, x})
print(mlp:forward{x, y})

0
1.9028918413199

你可能感兴趣的:(Lua,Torch7入门教程)