Optimization 在Pytork中执行优化时,如何对变量应用边界?

Optimization 在Pytork中执行优化时,如何对变量应用边界?,optimization,pytorch,clamp,non-convex,Optimization,Pytorch,Clamp,Non Convex,我正在尝试使用Pytorch进行非凸优化,尝试最大化我的目标(因此在SGD中最小化)。我想将我的因变量x绑定为>0,并且我的x值之和小于1000 我想我已经以斜坡惩罚的形式正确地实现了惩罚,但是我正在努力解决x变量的边界问题。在Pytorch中,您可以使用clamp设置边界,但在这种情况下似乎不合适。我认为这是因为optim需要引擎盖下的自由梯度。完整工作示例: import torch from torch.autograd import Variable import numpy as np

我正在尝试使用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")
导入火炬
从torch.autograd导入变量
将numpy作为np导入
def目标(x、a、b、c):#希望最大限度地增加该数量(因此尽量减少新加坡元)
d=1/(1+火炬试验(-a*(x)))
#检查约束
超出限制=约束(x)。项()
#打印(超出限制)
obj=火炬总数(d*(b*c-x))
#如果超出限制,则添加坡道处罚
如果超过\u限制<0:
obj=obj-(超出极限*10)
打印(“超出限制”)
返回-obj
def约束(x,限制=1000):#必须大于0
返回限制-x.sum()
N=1000
#x是一个变量,用于优化
x=变量(torch.张量([1表示范围(N)中的ii)],需要_梯度=真)
a=变量(火炬张量(np.随机.均匀(0100,N)),需要_梯度=真)
b=变量(torch.Tensor(np.random.rand(N)),需要_grad=True)
c=变量(torch.Tensor(np.random.rand(N)),需要_grad=True)
#我想包括夹钳
#x=焊炬夹钳(x,最小值=0)
#非凸方法
opt=torch.optim.SGD([x],lr=0.01)
对于范围(10000)内的i:
#归零梯度
选项0_梯度()
#评估目标
obj=目标(x、a、b、c)
#计算梯度
对象向后()
选择步骤()
如果i%1000==0:print(“目标:%.1f”%-obj.item())
打印(“\n目标:{}”。格式(-obj))
打印(“限制:{}”。格式(约束(x).item())
if torch.sum(x 0:打印(“未满足边界”)
如果约束(x).item()<0:打印(“未满足约束”)

任何关于如何施加边界的建议,无论是使用clamp还是其他方法,我们都将不胜感激。或者一般来说,对于使用Pytorch进行的非凸优化,我们将提供建议。这是一个更简单、缩小的问题版本,我正在努力寻找一个轻量级的解决方案,如果可能的话。我正在考虑使用transfo这样的解决方案使用指数函数重新定义x变量,但必须缩放函数以避免正值变为无穷大,我希望能够灵活设置约束。

我遇到了与您相同的问题。 我也想在PyTorch中对变量应用边界。 我用下面的方法解决了这个问题

你的例子有点复杂,但我还在学英语。 下面我举一个简单的例子

例如,有一个可训练变量
v
,其边界为(-1,1)

Way1.RuntimeError:要求grad的叶变量已在就地操作中使用

v.clamp_(-1, 1)             
运行时错误:尝试第二次向后遍历图形,但缓冲区已被释放

v = torch.clamp(v, -1, +1)  # equal to v = v.clamp(-1, +1)  
方法3.NotError。我用方法3解决了这个问题

with torch.no_grad():
    v[:] = v.clamp(-1, +1)  # You must use v[:]=xxx instead of v=xxx

夹钳
很好,你只需要用手电筒在
里面做就行了。no_grad():
夹钳
很好,你只需要用手电筒在
里面做就行了。no_grad():
x[:]=x.clamp(
代替
x=x.clamp(
with torch.no_grad():
    v[:] = v.clamp(-1, +1)  # You must use v[:]=xxx instead of v=xxx