[英]Weight Normalization in PyTorch
本文介绍了一种重要的权重归一化技术,并已包含在 PyTorch 中,如下所示:
from torch.nn.utils import weight_norm
weight_norm(nn.Conv2d(in_channles, out_channels))
从我了解到的文档中, weight_norm
在每次forward()
传递之前都会重新参数化。 但是我不确定当一切都在内部with torch.no_grad()
运行并且 model 设置为eval()
模式时,这种重新参数化是否也在推理过程中发生。
有人可以帮我知道weight_norm
是否仅在训练期间或如上所述的推理模式期间有效?
谢谢
我测试了“no_gard”,它有效!
对于“remove_weight_norm”,我仍然感到困惑。 我在 model 中经常使用 WeightNorm(conv1d)。 要导出 model,我使用以下代码,有或没有“remove_weight_norm”功能,它调用 function“nn.utils.remove_weight_norm”到所有相关的。
model.load_state_dict(checkpoint)
model = model.eval()
model.remove_weight_norm(); //with and without this code
remove_hooks(model)
scripted_module = torch.jit.script(model)
torch.jit.save(scripted_module, 'model.pt')
然后我使用 C++ 代码和 libtorch 测试了两个模型。 但结果并不相同。
我想知道 weight_norm 在推理中做了什么? 有用吗?
我终于弄清楚了问题所在。
批量归一化在训练期间学习两个参数并将它们用于推理。 因此,有必要使用eval()
来更改其行为,以告知不要进一步修改它们。
然后,我仔细检查了权重归一化论文,发现它“本质上是确定性的”。 它只是将原始权重向量解耦为两个量的乘积,如下所示。
w = g . v
显然,您使用 LHS 来计算 output 或 RHS 都没有关系。 然而,通过将其解耦为两个向量并将它们传递给优化器并删除w
参数,可以实现更好的训练。 出于原因,请参阅对事物进行了很好描述的论文。
因此,在测试期间是否删除了权重归一化并不重要。 为了验证这一点,我尝试了以下小代码。
import torch
import torch.nn as nn
from torch.nn.utils import weight_norm as wn
from torch.nn.utils import remove_weight_norm as wnr
# define the model 'm'
m = wn(nn.Conv2d(in_channels=1, out_channels=1, kernel_size=3, padding=1, bias=True))
ip = torch.rand(1,1,5,5)
target = torch.rand(1,1,5,5)
l1 = torch.nn.L1Loss()
optimizer = torch.optim.Adam(m.parameters())
# begin training
for _ in range(5):
out = m(ip)
loss = l1(out,target)
loss.backward()
optimizer.step()
with torch.no_grad():
m.eval()
print('\no/p after training with wn: {}'.format(m(ip)))
wnr(m)
print('\no/p after training without wn: {}'.format(m(ip)))
# begin testing
m2 = nn.Conv2d(in_channels=1, out_channels=1, kernel_size=3,padding=1, bias=True)
m2.load_state_dict(m.state_dict())
with torch.no_grad():
m2.eval()
out = m2(ip)
print('\nOutput during testing and without weight_norm: {}'.format(out))
下面是output,
o/p after training with wn:
tensor([[[[0.0509, 0.3286, 0.4612, 0.1795, 0.0307],
[0.1846, 0.3931, 0.5713, 0.2909, 0.4026],
[0.1716, 0.5971, 0.4297, 0.0845, 0.6172],
[0.2938, 0.2389, 0.4478, 0.5828, 0.6276],
[0.1423, 0.2065, 0.5024, 0.3979, 0.3127]]]])
o/p after training without wn:
tensor([[[[0.0509, 0.3286, 0.4612, 0.1795, 0.0307],
[0.1846, 0.3931, 0.5713, 0.2909, 0.4026],
[0.1716, 0.5971, 0.4297, 0.0845, 0.6172],
[0.2938, 0.2389, 0.4478, 0.5828, 0.6276],
[0.1423, 0.2065, 0.5024, 0.3979, 0.3127]]]])
Output during testing and without weight_norm:
tensor([[[[0.0509, 0.3286, 0.4612, 0.1795, 0.0307],
[0.1846, 0.3931, 0.5713, 0.2909, 0.4026],
[0.1716, 0.5971, 0.4297, 0.0845, 0.6172],
[0.2938, 0.2389, 0.4478, 0.5828, 0.6276],
[0.1423, 0.2065, 0.5024, 0.3979, 0.3127]]]])
请注意,所有值都与仅发生重新参数化完全相同。
关于,
然后我使用 C++ 代码和 libtorch 测试了两个模型。 但结果并不相同。
请参阅报告 TorchScript 错误的https://github.com/pytorch/pytorch/issues/21275 。
而关于,
我想知道 weight_norm 在推理中做了什么? 有用吗?
答案是它什么都不做。 你做x * 2
或x * (1+1)
没关系。 它没有用,但也无害。 所以最好去掉。
它应该是活跃的。 .eval() 影响您的网络层(例如 Dropout 和 BatchNorm 层)。 评估文档
.no_grad() 减少 memory 并在推理过程中加快计算速度。 no_grad 文档我认为 weight_norm 不受任何影响。
问候
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.