我有一个包含三个并行分支的网络,我希望共享它们的全部参数,以便在训练结束时它们是相同的。假设some_model
是一个标准的nn.Sequential
模块,由cudnn.SpatialConvolution
、nn.PReLU
、nn.SpatialBatchNormalization
组成。另外,还有一个nn.SpatialDropout
,但其概率设置为0
,因此没有效果。
ptb=nn.ParallelTable()ptb:add(some_model) ptb:add(some_model:clone('weight','bias', 'gradWeight','gradBias'))ptb:add(some_model:clone('weight','bias', 'gradWeight','gradBias'))triplet=nn.Sequential()triplet:add(ptb)
我认为损失函数并不相关,但以防万一,我使用了nn.DistanceRatioCriterion。为了检查所有权重是否正确共享,我将一个包含三个相同例子的表{A,A,A}
传递给网络。显然,如果权重正确共享,那么所有三个分支的输出应该是相同的。这在网络初始化时是成立的,但是一旦参数被更新(比如在一次小批量迭代之后),三个分支的结果就会变得不同。通过逐层检查,我注意到这种输出差异来自some_model
中的nn.SpatialBatchNormalization
层。因此,这些层的参数似乎没有正确共享。根据这个讨论,我尝试使用额外的参数running_mean
和running_std
调用clone
,但批归一化层的输出仍然不同。此外,这似乎也取消了所有其他网络参数的共享。如何正确地在nn.SpatialBatchNormalization
模块之间共享参数呢?
回答:
好的,我找到了解决方案!似乎自从我在问题中链接的讨论以来,参数running_std
已更改为running_var
。使用以下构造函数调用
ptb:add(some_model:clone('weight','bias', 'gradWeight','gradBias','running_mean','running_var'))
解决了这个问题。