【问题标题】:Inconsistency in solutions using CVXPY使用 CVXPY 的解决方案不一致
【发布时间】:2021-10-28 13:31:36
【问题描述】:

请考虑以下优化问题。具体来说,x 和 b 是 (1,n) 向量,C 是 (n,n) 对称矩阵,k 是任意常数,i 是 (1,n) 向量。

请同时考虑以下等效优化问题。在这种情况下,k 是在优化过程中确定的,因此无需对x 中的值进行缩放以获得解决方案y。

请同时考虑以下代码来解决cvxpy 的两个问题。

import cvxpy as cp
import numpy as np

def problem_1(C):
    n, t = np.shape(C)
    
    x = cp.Variable(n)
    b = np.array([1 / n] * n)
    
    obj =  cp.quad_form(x, C)
    constraints = [b.T @ cp.log(x)>=0.5, x >= 0]
    cp.Problem(cp.Minimize(obj), constraints).solve()

    return (x.value / (np.ones(n).T @ x.value))

def problem_2(C):
    n, t = np.shape(C)
    
    y = cp.Variable(n)
    k = cp.Variable()
    b = np.array([1 / n] * n)
    
    obj =  cp.quad_form(y, C)
    constraints = [b.T @ cp.log(y)>=k, np.ones(n)@y.T==1, y >= 0]
    cp.Problem(cp.Minimize(obj), constraints).solve()
    
    return y.value

虽然第一个函数确实为我正在使用的一组数据样本提供了正确的解决方案,但第二个函数却没有。具体来说,y 中的值在使用第二个函数时差异很大,其中一些等于零(这不可能,因为b 中的所有值都是正数且大于零)。我想知道第二个函数是否也最小化k。它的值不应该被最小化,相反,它应该在优化问题期间被确定为导致最小化目标函数的解决方案。

UPDATE_1

我刚刚发现,我用问题的第二个公式得到的解等于用以下方程和函数得出的解。似乎忽略了对数障碍和k 变量的约束。

def problem_3(C):
    n, t = np.shape(C)
    
    y = cp.Variable(n)
    k = cp.Variable()
    b = np.array([1 / n] * n)
    
    obj =  cp.quad_form(y, C)
    constraints = [np.ones(n)@y.T==1, y >= 0]
    cp.Problem(cp.Minimize(obj), constraints).solve()
    
    return y.value

UPDATE_2

这里是示例输入 C - https://www.dropbox.com/s/kaa7voufzk5k9qt/matrix_.csv?dl=0 的链接。在这种情况下,problem_1 和problem_2 的正确输出大约等于[0.0659 0.068 0.0371 0.1188 0.1647 0.3387 0.1315 0.0311 0.0441],因为它们在定义上是等效的。我只能通过解决problem_1 来获得正确的输出。解决problem_2 导致[0.0227 0. 0. 0.3095 0.3392 0.3286 0. 0. 0. ] 这是错误的,因为它恰好是problem_3 的正确输出。

UPDATE_3

需要明确的是,根据定义,problem_2 的解等于 problem_3 的解,当参数 k 变为负无穷大时。

UPDATE_4

请考虑使用 SciPy Optimize 而不是 CVXPY 解决 problem_1 的以下代码。通过强加k=9仍然可以获得正确的最优解,这与problem_1独立于参数一致。

import scipy.optimize as opt

def obj(x, C):
    return x.T @ C @ x

def problem_1_1(C):
    n, t = np.shape(C)

    b = np.array([1 / n] * n)
        
    constraints = [{"type": "eq", "fun": lambda x: (b * np.log(x)).sum() - 9}]
    
    res = opt.minimize(
        obj,
        x0 = np.array([1 / n] * n),
        args = (C),
        bounds = ((0, None),) * n, 
        constraints = constraints
    )
    
    return (res['x'] / (np.ones(n).T @ res['x']))

UPDATE_5

通过考虑 UPDATE_4 中的代码,每当 k 设置为等于 10 时,仍然可以实现正确的解决方案,但是会出现以下警告。我想这是由于优化过程中可能出现的舍入误差。

Untitled.py:56: RuntimeWarning: divide by zero encountered in
log {"type": "eq", "fun": lambda x: (b * np.log(x)).sum() - 10}

我想知道是否有办法对 CVXPY 施加严格的不等式约束或在对数参数上应用条件。请考虑为problem_1_1 修改以下代码。

import scipy.optimize as opt

def obj(x, C):
    return x.T @ C @ x

def problem_1_1(C):
    n, t = np.shape(C)

    b = np.array([1 / n] * n)
        
    constraints = [{"type": "eq", "fun": lambda x: (b * np.log(x if x.all() > 0 else 1e-100)).sum() - 10}]
    
    res = opt.minimize(
        obj,
        x0 = np.array([1 / n] * n),
        args = (C),
        bounds = ((0, None),) * n, 
        constraints = constraints
    )
    
    return (res['x'] / (np.ones(n).T @ res['x']))

UPDATE_6

为了彻底,最佳k 的正确值近似为-2.4827186402337564。

【问题讨论】:

  • 方程式很难阅读; codecogs?...也许可以从渲染良好的 PDF 中截取您的 LaTeX。此外,如果您可以提供用于测试和实验的示例输入/输出,即使是合成的,也将是非常棒的。
  • 是 codecogs,因为如果我没记错的话,堆栈溢出不支持 LaTex。我刚刚编辑了帖子,包括方程式和示例输入和输出的屏幕截图。
  • 一些cmets/问题:(1)我可以重现你的结果。 (2)如果我在问题1中选择更大的ks(例如k=9),cvxpy计算失败,那么问题就不是独立于k了(为什么要这样,影响可行解空间)? (3) 那么为什么允许在问题 2 中使 ka 变量。 (4) 显然,问题 2 和 3 产生相同的结果:如果 k 是(不受限制的)变量,则 k=-inf 是“合理的”选择,因为它只会增加可行的优化空间。 (5) 为什么你认为(或你如何证明)这两个问题是等价的?
  • 非常感谢您提供详细的 cmets。最欣赏。 (2) 请考虑UPDATE_4。 (3) 它被认为是一个变量,因为根据定义存在一个且只有一个k 的值,它导致正确的解决方案被缩放为一(请考虑 1.2 和 1.1)。 (4)我刚刚检查了problem_2中k的值,用CVXPY优化后等于-14.173735793850643,看起来不大。 (5) 在少数学术论文中已经证明这些问题是等价的。

标签: python numpy optimization cvxpy


【解决方案1】:

如果你让 是任意的,那么你基本上是在说 大于或等于某个任意数字,这是微不足道的,因此约束变得无关紧要。

我认为您应该修复 的值,或者通过确定最大化 和最小化 之间的平衡来将此问题变成一个极小极大问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-02-07
    • 2021-07-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-16
    • 1970-01-01
    • 2012-03-31
    相关资源
    最近更新 更多