在 NN 训练期间最大化一种损失并最小化另一种损失的正确方法是什么?
What is the correct way to maximize one loss and minimize another during NN training?
我有一个简单的神经网络:
import torch
import torch.nn as nn
import torch.optim as optim
class Model(nn.Module):
def __init__(self):
super(Model, self).__init__()
self.fc1 = nn.Linear(1, 5)
self.fc2 = nn.Linear(5, 10)
self.fc3 = nn.Linear(10, 1)
def forward(self, x):
x = self.fc1(x)
x = torch.relu(x)
x = torch.relu(self.fc2(x))
x = self.fc3(x)
return x
net = Model()
opt = optim.Adam(net.parameters())
我还有一些输入功能:
features = torch.rand((3,1))
我可以用一个会最小化的简单损失函数正常训练它:
for i in range(10):
opt.zero_grad()
out = net(features)
loss = torch.mean(torch.square(torch.tensor(5) - torch.sum(out)))
print('loss:', loss)
loss.backward()
opt.step()
但是,如果我向其中添加另一个我想要最大化的损失分量--loss2
:
loss2s = []
for i in range(10000):
opt.zero_grad()
out = net(features)
loss1 = torch.mean(torch.square(torch.tensor(5) - torch.sum(out)))
loss2 = torch.sum(torch.tensor([torch.sum(w_arr) for w_arr in net.parameters()]))
loss2s.append(loss2)
loss = loss1 + loss2
loss.backward()
opt.step()
由于 2 个损失的规模不同,它变得看似不稳定。另外,我不确定这是正确的方法,因为损失如何知道最大化一个部分并最小化另一个部分。请注意,这只是一个示例,显然增加权重没有意义。
import matplotlib.pyplot as plt
plt.plot(loss2s, c='r')
plt.plot(loss1s, c='b')
而且我认为最小化函数是 ML 训练的常用方法,所以我不确定以某种方式将最大化问题转换为最小化问题是否会更好。
表示“最小化”和“最大化”的标准方法是改变符号。 PyTorch 总是 最小化 a loss
如果完成以下操作
loss.backward()
因此,如果另一个 loss2
需要最大化,我们添加它的负值
overall_loss = loss + (- loss2)
overall_loss.backward()
因为最小化负数等同于最大化原始正数。
关于“比例”,是的,比例很重要。通常执行以下操作以匹配比例
overall_loss = loss + alpha * (- loss2)
其中 alpha
是一个分数,表示一种损失 w.r.t 相对于另一种损失的相对重要性。它是一个超参数,需要进行试验。
撇开技术细节不谈,由此产生的损失是否稳定在很大程度上取决于所涉及的具体问题和损失函数。如果损失 相互矛盾 ,您可能会遇到不稳定的情况。如何处理它们本身就是一个研究问题,远远超出了这个问题的范围。
我有一个简单的神经网络:
import torch
import torch.nn as nn
import torch.optim as optim
class Model(nn.Module):
def __init__(self):
super(Model, self).__init__()
self.fc1 = nn.Linear(1, 5)
self.fc2 = nn.Linear(5, 10)
self.fc3 = nn.Linear(10, 1)
def forward(self, x):
x = self.fc1(x)
x = torch.relu(x)
x = torch.relu(self.fc2(x))
x = self.fc3(x)
return x
net = Model()
opt = optim.Adam(net.parameters())
我还有一些输入功能:
features = torch.rand((3,1))
我可以用一个会最小化的简单损失函数正常训练它:
for i in range(10):
opt.zero_grad()
out = net(features)
loss = torch.mean(torch.square(torch.tensor(5) - torch.sum(out)))
print('loss:', loss)
loss.backward()
opt.step()
但是,如果我向其中添加另一个我想要最大化的损失分量--loss2
:
loss2s = []
for i in range(10000):
opt.zero_grad()
out = net(features)
loss1 = torch.mean(torch.square(torch.tensor(5) - torch.sum(out)))
loss2 = torch.sum(torch.tensor([torch.sum(w_arr) for w_arr in net.parameters()]))
loss2s.append(loss2)
loss = loss1 + loss2
loss.backward()
opt.step()
由于 2 个损失的规模不同,它变得看似不稳定。另外,我不确定这是正确的方法,因为损失如何知道最大化一个部分并最小化另一个部分。请注意,这只是一个示例,显然增加权重没有意义。
import matplotlib.pyplot as plt
plt.plot(loss2s, c='r')
plt.plot(loss1s, c='b')
而且我认为最小化函数是 ML 训练的常用方法,所以我不确定以某种方式将最大化问题转换为最小化问题是否会更好。
表示“最小化”和“最大化”的标准方法是改变符号。 PyTorch 总是 最小化 a loss
如果完成以下操作
loss.backward()
因此,如果另一个 loss2
需要最大化,我们添加它的负值
overall_loss = loss + (- loss2)
overall_loss.backward()
因为最小化负数等同于最大化原始正数。
关于“比例”,是的,比例很重要。通常执行以下操作以匹配比例
overall_loss = loss + alpha * (- loss2)
其中 alpha
是一个分数,表示一种损失 w.r.t 相对于另一种损失的相对重要性。它是一个超参数,需要进行试验。
撇开技术细节不谈,由此产生的损失是否稳定在很大程度上取决于所涉及的具体问题和损失函数。如果损失 相互矛盾 ,您可能会遇到不稳定的情况。如何处理它们本身就是一个研究问题,远远超出了这个问题的范围。