我想将 L1 正则化器添加到 ReLU 的激活输出中。更一般地说,如何将正则化器 仅添加到网络中的特定层?
相关资料:
这篇类似的文章 提到了添加 L2 正则化,但它似乎将正则化惩罚添加到网络的 所有 层。
nn.modules.loss.L1Loss()
似乎相关,但我还不明白如何使用它。遗留模块
L1Penalty
似乎也相关,但为什么它被弃用了?
原文由 Bull 发布,翻译遵循 CC BY-SA 4.0 许可协议
所有(其他当前)响应在某种程度上都是不正确的,因为问题是关于向激活添加正则化。 这个 最接近,因为它建议对输出的范数求和,这是正确的,但代码对权重的范数求和,这是不正确的。
正确的方法不是修改网络代码,而是通过 forward hook 捕获输出,就像在 OutputHook
类中一样。从那里开始,输出范数的总和很简单,但需要注意在每次迭代时清除捕获的输出。
import torch
class OutputHook(list):
""" Hook to capture module outputs.
"""
def __call__(self, module, input, output):
self.append(output)
class MLP(torch.nn.Module):
def __init__(self):
super(MLP, self).__init__()
self.linear1 = torch.nn.Linear(128, 32)
self.linear2 = torch.nn.Linear(32, 16)
self.linear3 = torch.nn.Linear(16, 2)
# Instantiate ReLU, so a hook can be registered to capture its output.
self.relu = torch.nn.ReLU()
def forward(self, x):
layer1_out = self.relu(self.linear1(x))
layer2_out = self.relu(self.linear2(layer1_out))
out = self.linear3(layer2_out)
return out
batch_size = 4
l1_lambda = 0.01
model = MLP()
optimizer = torch.optim.SGD(model.parameters(), lr=1e-4)
# Register hook to capture the ReLU outputs. Non-trivial networks will often
# require hooks to be applied more judiciously.
output_hook = OutputHook()
model.relu.register_forward_hook(output_hook)
inputs = torch.rand(batch_size, 128)
targets = torch.ones(batch_size).long()
optimizer.zero_grad()
outputs = model(inputs)
cross_entropy_loss = torch.nn.functional.cross_entropy(outputs, targets)
# Compute the L1 penalty over the ReLU outputs captured by the hook.
l1_penalty = 0.
for output in output_hook:
l1_penalty += torch.norm(output, 1)
l1_penalty *= l1_lambda
loss = cross_entropy_loss + l1_penalty
loss.backward()
optimizer.step()
output_hook.clear()
原文由 ndronen 发布,翻译遵循 CC BY-SA 4.0 许可协议
2 回答5.2k 阅读✓ 已解决
2 回答1.1k 阅读✓ 已解决
4 回答1.4k 阅读✓ 已解决
3 回答1.3k 阅读✓ 已解决
3 回答1.3k 阅读✓ 已解决
2 回答895 阅读✓ 已解决
1 回答1.8k 阅读✓ 已解决
这是你如何做到这一点:
loss
变量将是输出 wrt 目标和 L1 惩罚的交叉熵损失之和。这是一个示例代码