如何将 L1 正则化添加到 PyTorch NN 模型?
How to add L1 Regularization to PyTorch NN Model?
在寻找在 PyTorch 模型中实现 L1 正则化的方法时,我遇到了 ,现在已经 2 岁了,所以我想知道这个主题是否有任何新内容?
我还发现 this recent approach 处理缺失的 l1 函数。但是我不明白如何将它用于基本的神经网络,如下所示。
class FFNNModel(nn.Module):
def __init__(self, input_dim, output_dim, hidden_dim, dropout_rate):
super(FFNNModel, self).__init__()
self.input_dim = input_dim
self.output_dim = output_dim
self.hidden_dim = hidden_dim
self.dropout_rate = dropout_rate
self.drop_layer = nn.Dropout(p=self.dropout_rate)
self.fully = nn.ModuleList()
current_dim = input_dim
for h_dim in hidden_dim:
self.fully.append(nn.Linear(current_dim, h_dim))
current_dim = h_dim
self.fully.append(nn.Linear(current_dim, output_dim))
def forward(self, x):
for layer in self.fully[:-1]:
x = self.drop_layer(F.relu(layer(x)))
x = F.softmax(self.fully[-1](x), dim=0)
return x
我希望在训练之前简单地把这个放好:
model = FFNNModel(30,5,[100,200,300,100],0.2)
regularizer = _Regularizer(model)
regularizer = L1Regularizer(regularizer, lambda_reg=0.1)
和
out = model(inputs)
loss = criterion(out, target) + regularizer.__add_l1()
有谁知道如何应用这些 'ready to use' 类?
我没有 运行 有问题的代码,所以如果有什么不正确的地方请联系我。一般来说,我会说您 link 编辑的代码不必要地复杂(可能是因为它试图通用并允许以下所有类型的正则化)。我想它的使用方式是
model = FFNNModel(30,5,[100,200,300,100],0.2)
regularizer = L1Regularizer(model, lambda_reg=0.1)
然后
out = model(inputs)
loss = criterion(out, target) + regularizer.regularized_all_param(0.)
您可以检查 regularized_all_param
将仅 iterate 覆盖您模型的参数,如果它们的名称以 weight
结尾,它将累加它们的绝对值之和。由于某种原因,缓冲区要手动初始化,这就是我们传入 0.
.
的原因
但实际上,如果您希望有效地正则化 L1 并且不需要任何花里胡哨的东西,更手动的方法,类似于您的第一个 link,将更具可读性。它会像这样
l1_regularization = 0.
for param in model.parameters():
l1_regularization += param.abs().sum()
loss = criterion(out, target) + l1_regularization
这确实是两种方法的核心所在。您使用 Module.parameters
方法迭代所有模型参数,然后将它们的 L1 范数求和,然后成为损失函数中的一项。而已。您 linked 的回购提出了一些奇特的机制来将其抽象化,但是根据您的问题判断,它失败了:)
您可以使用以下代码将 L1 正则化应用于损失函数:
loss = loss_fn(outputs, labels)
l1_lambda = 0.001
l1_norm = sum(p.abs().sum() for p in model.parameters())
loss = loss + l1_lambda*l1_norm
来源:Deep Learning with PyTorch (8.5.2)
对于遇到此问题的任何人的简单解决方案:
上面 link 中的正则化器_ 类 总是存在一些问题,所以我使用正则函数解决了这个问题,同时添加了正交正则化器:
def l1_regularizer(model, lambda_l1=0.01):
lossl1 = 0
for model_param_name, model_param_value in model.named_parameters():
if model_param_name.endswith('weight'):
lossl1 += lambda_l1 * model_param_value.abs().sum()
return lossl1
def orth_regularizer(model, lambda_orth=0.01):
lossorth = 0
for model_param_name, model_param_value in model.named_parameters():
if model_param_name.endswith('weight'):
param_flat = model_param_value.view(model_param_value.shape[0], -1)
sym = torch.mm(param_flat, torch.t(param_flat))
sym -= torch.eye(param_flat.shape[0])
lossorth += lambda_orth * sym.sum()
return lossorth
并在训练期间做:
loss = criterion(outputs, y_data)\
+l1_regularizer(model, lambda_l1=lambda_l1)\
+orth_regularizer(model, lambda_orth=lambda_orth)
在寻找在 PyTorch 模型中实现 L1 正则化的方法时,我遇到了
我还发现 this recent approach 处理缺失的 l1 函数。但是我不明白如何将它用于基本的神经网络,如下所示。
class FFNNModel(nn.Module):
def __init__(self, input_dim, output_dim, hidden_dim, dropout_rate):
super(FFNNModel, self).__init__()
self.input_dim = input_dim
self.output_dim = output_dim
self.hidden_dim = hidden_dim
self.dropout_rate = dropout_rate
self.drop_layer = nn.Dropout(p=self.dropout_rate)
self.fully = nn.ModuleList()
current_dim = input_dim
for h_dim in hidden_dim:
self.fully.append(nn.Linear(current_dim, h_dim))
current_dim = h_dim
self.fully.append(nn.Linear(current_dim, output_dim))
def forward(self, x):
for layer in self.fully[:-1]:
x = self.drop_layer(F.relu(layer(x)))
x = F.softmax(self.fully[-1](x), dim=0)
return x
我希望在训练之前简单地把这个放好:
model = FFNNModel(30,5,[100,200,300,100],0.2)
regularizer = _Regularizer(model)
regularizer = L1Regularizer(regularizer, lambda_reg=0.1)
和
out = model(inputs)
loss = criterion(out, target) + regularizer.__add_l1()
有谁知道如何应用这些 'ready to use' 类?
我没有 运行 有问题的代码,所以如果有什么不正确的地方请联系我。一般来说,我会说您 link 编辑的代码不必要地复杂(可能是因为它试图通用并允许以下所有类型的正则化)。我想它的使用方式是
model = FFNNModel(30,5,[100,200,300,100],0.2)
regularizer = L1Regularizer(model, lambda_reg=0.1)
然后
out = model(inputs)
loss = criterion(out, target) + regularizer.regularized_all_param(0.)
您可以检查 regularized_all_param
将仅 iterate 覆盖您模型的参数,如果它们的名称以 weight
结尾,它将累加它们的绝对值之和。由于某种原因,缓冲区要手动初始化,这就是我们传入 0.
.
但实际上,如果您希望有效地正则化 L1 并且不需要任何花里胡哨的东西,更手动的方法,类似于您的第一个 link,将更具可读性。它会像这样
l1_regularization = 0.
for param in model.parameters():
l1_regularization += param.abs().sum()
loss = criterion(out, target) + l1_regularization
这确实是两种方法的核心所在。您使用 Module.parameters
方法迭代所有模型参数,然后将它们的 L1 范数求和,然后成为损失函数中的一项。而已。您 linked 的回购提出了一些奇特的机制来将其抽象化,但是根据您的问题判断,它失败了:)
您可以使用以下代码将 L1 正则化应用于损失函数:
loss = loss_fn(outputs, labels)
l1_lambda = 0.001
l1_norm = sum(p.abs().sum() for p in model.parameters())
loss = loss + l1_lambda*l1_norm
来源:Deep Learning with PyTorch (8.5.2)
对于遇到此问题的任何人的简单解决方案:
上面 link 中的正则化器_ 类 总是存在一些问题,所以我使用正则函数解决了这个问题,同时添加了正交正则化器:
def l1_regularizer(model, lambda_l1=0.01):
lossl1 = 0
for model_param_name, model_param_value in model.named_parameters():
if model_param_name.endswith('weight'):
lossl1 += lambda_l1 * model_param_value.abs().sum()
return lossl1
def orth_regularizer(model, lambda_orth=0.01):
lossorth = 0
for model_param_name, model_param_value in model.named_parameters():
if model_param_name.endswith('weight'):
param_flat = model_param_value.view(model_param_value.shape[0], -1)
sym = torch.mm(param_flat, torch.t(param_flat))
sym -= torch.eye(param_flat.shape[0])
lossorth += lambda_orth * sym.sum()
return lossorth
并在训练期间做:
loss = criterion(outputs, y_data)\
+l1_regularizer(model, lambda_l1=lambda_l1)\
+orth_regularizer(model, lambda_orth=lambda_orth)