【问题标题】:How to apply bounds on a variable when performing optimisation in Pytorch?在 Pytorch 中执行优化时如何对变量应用边界?
【发布时间】:2019-12-05 10:08:35
【问题描述】:

我正在尝试使用 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")

任何关于如何强加边界的建议都将不胜感激,无论是使用钳位还是其他方式。或者一般建议使用 Pytorch 进行非凸优化。这是我正在解决的问题的一个更简单且按比例缩小的版本,因此如果可能的话,我试图找到一个轻量级的解决方案。我正在考虑使用一种解决方法,例如使用指数函数转换 x 变量,但是您必须缩放函数以避免正值变为无限,并且我希望能够设置约束具有一定的灵活性。

【问题讨论】:

  • clamp 没问题,你只需要在with torch.no_grad():里面做就行了
  • clamp 很好,你只需要在with torch.no_grad(): 里面做它并使用x[:]=x.clamp( 而不是x=x.clamp(

标签: optimization pytorch clamp non-convex


【解决方案1】:

我遇到了同样的问题。 我也想在 PyTorch 中的变量上应用边界。 而我通过下面的Way3解决了这个问题。

您的示例有点复杂,但我仍在学习英语。 所以我在下面举一个更简单的例子。

比如有一个可训练变量v,它的边界是(-1, 1)

v = torch.tensor((0.5, ), require_grad=True)
v_loss = xxxx
optimizer.zero_grad()
v_loss.backward()
optimizer.step()

方式 1。 RuntimeError: 一个需要 grad 的叶变量已在就地操作中使用。

v.clamp_(-1, 1)             

方式 2。 RuntimeError: 试图第二次向后遍历图形,但缓冲区已被释放。

v = torch.clamp(v, -1, +1)  # equal to v = v.clamp(-1, +1)  

方式 3。 NotError。我在 Way3 中解决了这个问题。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-04-12
    • 1970-01-01
    • 1970-01-01
    • 2014-11-26
    • 2020-08-10
    • 2021-07-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多