在pytorch的神经网络中将参数约束为-1、0或1

Posted

技术标签:

【中文标题】在pytorch的神经网络中将参数约束为-1、0或1【英文标题】:Constrain parameters to be -1, 0 or 1 in neural network in pytorch 【发布时间】:2021-08-18 16:33:12 【问题描述】:

我想约束神经网络中中间层的参数,使其更喜欢离散值:-1、0 或 1。这个想法是添加一个自定义目标函数,如果参数采用任何其他值,则会增加损失价值。请注意,我想约束特定层的参数,而不是所有层。

如何在 pytorch 中实现这一点?我想将此自定义损失添加到训练循环中的总损失中,如下所示:

custom_loss = constrain_parameters_to_be_discrete 
loss = other_loss + custom_loss 

可能使用 Dirichlet 先验可能会有所帮助,任何指向此的指针?

【问题讨论】:

【参考方案1】:

在@Shai answer 上进行扩展并将其与this answer 混合使用可以更简单地通过自定义层来实现,您可以将特定层传递到该层中。

首先,从WolframAlpha(检查here)中计算得到的torch.abs(x**2 - torch.abs(x)) 的导数将放在regularize 函数中。

现在是Constrainer 层:

class Constrainer(torch.nn.Module):
    def __init__(self, module, weight_decay=1.0):
        super().__init__()
        self.module = module
        self.weight_decay = weight_decay

        # Backward hook is registered on the specified module
        self.hook = self.module.register_full_backward_hook(self._weight_decay_hook)

    # Not working with grad accumulation, check original answer and pointers there
    # If that's needed
    def _weight_decay_hook(self, *_):
        for parameter in self.module.parameters():
            parameter.grad = self.regularize(parameter)

    def regularize(self, parameter):
        # Derivative of the regularization term created by @Shia
        sgn = torch.sign(parameter)
        return self.weight_decay * (
            (sgn - 2 * parameter) * torch.sign(1 - parameter * sgn)
        )

    def forward(self, *args, **kwargs):
        # Simply forward and args and kwargs to module
        return self.module(*args, **kwargs)

使用非常简单(如果您需要对参数施加更多/更少的力,请使用您指定的weight_decay 超参数):

constrained_layer = Constrainer(torch.nn.Linear(20, 10), weight_decay=0.1)

现在你不用担心不同的损失函数,可以正常使用你的模型了。

【讨论】:

喜欢衍生品 ;)【参考方案2】:

你可以使用损失函数:

def custom_loss_function(x):
  loss = torch.abs(x**2 - torch.abs(x))
  return loss.mean()

此图绘制了单个元素的建议损失:

如您所见,x=-1, 0, 1 的建议损失为零,否则为正。

请注意,如果您想将此损失应用于特定层的权重,那么您的x 是权重,而不是层的激活。

【讨论】:

@dennlinger 您需要将其应用到 parameters 而不是 activations @Shai 可能值得一提,因为现在看起来x 是某种输出,其命名包含loss,IMO 有点混乱。 @Rakib 在这个之后你有批处理规范层吗?你如何初始化这一层的权重?您是否有可能以具有小方差的正态分布进行初始化,以使所有权重一开始都非常接近于零?您需要重新考虑在这种情况下初始化权重的方式 那你期待什么?权重初始值非常接近于零,您需要付出很大的代价才能在 -/+0.5 左右“越过障碍”。 将 lambda 设置为高值会使将值从零更改为 -/+1 变得更加困难。尝试将权重初始化为 -1, 0, 1 - 看看它如何影响收敛

以上是关于在pytorch的神经网络中将参数约束为-1、0或1的主要内容,如果未能解决你的问题,请参考以下文章

如何在 PyTorch 中将句子长度批量转换为掩码?

在 PyTorch 中将 5D 张量转换为 4D 张量

在给定约束的最小移动中将数组减少到 0

pytorch-04-激活函数

在 UITableView 标头中将标签约束设置为 0 时自动布局失败

Pytorch基础——使用 RNN 生成简单序列