总说
先附加几个有用的。
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的用法还是有很大区别的。
类似的还有PairewiseDistance
和DotProduct
.
每个输入进行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