我正在尝试使用Pytorch进行非凸优化,试图最大限度地实现我的目标(在SGD中最小化)。我希望绑定我的因变量x> 0,并且我的x值之和小于1000。
我认为我的惩罚是正确的,以坡道惩罚的形式实现,但我正在与x变量的界限斗争。在Pytorch中,您可以使用clamp设置边界,但在这种情况下似乎不合适。我认为这是因为optim需要在引擎盖下自由的渐变。完整的工作示例:
import torch
from torch.autograd import Variable
import numpy as np
def objective(x, a, b, c): # Want to maximise this quantity (so minimise in SGD)
d = 1 / (1 + torch.exp(-a * (x)))
# Checking constraint
exceeded_limit = constraint(x).item()
#print(exceeded_limit)
obj = torch.sum(d * (b * c - x))
# If overlimit add ramp penalty
if exceeded_limit < 0:
obj = obj - (exceeded_limit * 10)
print("Exceeded limit")
return - obj
def constraint(x, limit = 1000): # Must be > 0
return limit - x.sum()
N = 1000
# x is variable to optimise for
x = Variable(torch.Tensor([1 for ii in range(N)]), requires_grad=True)
a = Variable(torch.Tensor(np.random.uniform(0,100,N)), requires_grad=True)
b = Variable(torch.Tensor(np.random.rand(N)), requires_grad=True)
c = Variable(torch.Tensor(np.random.rand(N)), requires_grad=True)
# Would like to include the clamp
# x = torch.clamp(x, min=0)
# Non-convex methodf
opt = torch.optim.SGD([x], lr=.01)
for i in range(10000):
# Zeroing gradients
opt.zero_grad()
# Evaluating the objective
obj = objective(x, a, b, c)
# Calculate gradients
obj.backward()
opt.step()
if i%1000==0: print("Objective: %.1f" % -obj.item())
print("\nObjective: {}".format(-obj))
print("Limit: {}".format(constraint(x).item()))
if torch.sum(x<0) > 0: print("Bounds not met")
if constraint(x).item() < 0: print("Constraint not met")任何关于如何施加边界的建议都将受到欢迎,无论是使用夹子还是其他方式。或一般建议的非凸优化使用毕道尔。这是一个简单得多的缩小版本的问题,我正在努力寻找一个轻量级的解决方案,如果可能的话。我正在考虑使用一种解决方法,比如使用指数函数来转换x变量,但是您必须缩放这个函数,以避免正值变得无限,而且我希望能够设置约束具有一定的灵活性。
发布于 2020-09-16 03:03:08
我和你遇到了同样的问题。我也想在PyTorch中应用变量的边界。我通过下面的Way3解决了这个问题。
你的例子有点顺从,但我还在学英语。下面我举一个简单的例子。
例如,有一个可训练变量v,其边界为(-1,1)
v = torch.tensor((0.5, ), require_grad=True)
v_loss = xxxx
optimizer.zero_grad()
v_loss.backward()
optimizer.step()Way1。RuntimeError:要求梯度的叶变量已在就地操作中使用.
v.clamp_(-1, 1) Way2。RuntimeError:尝试第二次向后遍历图形,但是缓冲区已经被释放了。
v = torch.clamp(v, -1, +1) # equal to v = v.clamp(-1, +1) Way3。NotError.我在Way3中解决了这个问题。
with torch.no_grad():
v[:] = v.clamp(-1, +1) # You must use v[:]=xxx instead of v=xxxhttps://stackoverflow.com/questions/59192705
复制相似问题