【问题标题】:Fast optimization of "pathological" convex function“病态”凸函数的快速优化
【发布时间】:2017-02-21 15:39:00
【问题描述】:

我有一个简单的凸问题,我正在尝试加快解决速度。我正在解决 argmin (theta) of

其中 thetartNx1

我可以用cvxpy 轻松解决这个问题

import numpy as np
from scipy.optimize import minimize
import cvxpy

np.random.seed(123)

T = 50
N = 5
R = np.random.uniform(-1, 1, size=(T, N))

cvtheta = cvxpy.Variable(N)
fn = -sum([cvxpy.log(1 + cvtheta.T * rt) for rt in R])

prob = cvxpy.Problem(cvxpy.Minimize(fn))
prob.solve()

prob.status
#'optimal'

prob.value
# -5.658335088091929

cvtheta.value
# matrix([[-0.82105079],
#         [-0.35475695],
#         [-0.41984643],
#         [ 0.66117397],
#         [ 0.46065358]])

但是对于较大的R,这太慢了,所以我正在尝试使用scipyfmin_cg 的基于渐变的方法:

goalfun 是一个 scipy.minimize 友好函数,它返回函数值和梯度。

def goalfun(theta, *args):
    R = args[0]
    N = R.shape[1]
    common = (1 + np.sum(theta * R, axis=1))**-1

    if np.any( common < 0 ):
        return 1e2, 1e2 * np.ones(N)

    fun = np.sum(np.log(common))

    thetaprime = np.tile(theta, (N, 1)).T
    np.fill_diagonal(thetaprime, np.ones(N))
    grad = np.sum(np.dot(R, thetaprime) * common[:, None], axis=0)

    return fun, grad

确保函数和渐变正确:

goalfun(np.squeeze(np.asarray(cvtheta.value)), R)
# (-5.6583350819293603,
#  array([ -9.12423065e-09,  -3.36854633e-09,  -1.00983679e-08,
#          -1.49619901e-08,  -1.22987872e-08]))

但解决这个问题只会产生垃圾,无论method、迭代等如何。(产生Optimization terminated successfully 的唯一因素是x0 实际上等于最佳theta

x0 = np.random.rand(R.shape[1])

minimize(fun=goalfun, x0=x0, args=R, jac=True, method='CG')
#   fun: 3.3690101669818775
#      jac: array([-11.07449021, -14.04017873, -13.38560561,  -5.60375334,  -2.89210078])
#  message: 'Desired error not necessarily achieved due to precision loss.'
#     nfev: 25
#      nit: 1
#     njev: 13
#   status: 2
#  success: False
#        x: array([ 0.00892177,  0.24404118,  0.51627475,  0.21119326, -0.00831957])

cvxpy 轻松处理这个看似无害的问题,结果证明对于非凸求解器来说是完全病态的。这个问题真的那么讨厌,还是我错过了什么?有什么办法可以加快速度?

【问题讨论】:

  • 您是否尝试过求解器 SCS(在 cvxpy 中),可能使用 use_indirect=True 模式?
  • 不,我没有设置任何求解器选项,我运行的一切都和上面的例子一样,我假设这里的默认选项很好?
  • 当然,默认使用 ECOS,这很好。 SCS 有时会快得多,但准确度稍差(基于 ADMM 的方法)。有两种模式,其中一种类似于截断牛顿法。 (从源代码编译的 SCS 将比默认的快得多;多线程)。甚至还有 GPU 支持。 更新 ecos:90secs; 5000x500 的 scs=3 秒(使用 MT 进行源安装;use_indirect=True)。
  • 谢谢 prob.solve(solver='SCS', use_indirect=True) 给了我一个加速,但它不在你的数量级(但我还没有尝试使用 mt 从源代码安装)

标签: python numpy scipy mathematical-optimization cvxopt


【解决方案1】:

我认为问题在于theta 可能会导致log 参数变为负数。您似乎已经发现了这个问题,并且在这种情况下让goalfun 返回元组(100,100*ones(N)),显然,作为一种启发式尝试,建议求解器这个“解决方案”不是首选。然而,必须强加一个更强的条件,即这个“解决方案”是不可行的。当然,这可以通过提供适当的约束来完成。 (有趣的是,cvxpy 似乎会自动处理这个问题。)

这是一个示例运行,无需提供衍生产品。注意使用可行的初始估计x0

np.random.seed(123)

T = 50
N = 5
R = np.random.uniform(-1, 1, size=(T, N))

def goalfun(theta, *args):
    R = args[0]
    N = R.shape[1]
    common = (1 + np.sum(theta * R, axis=1))**-1

    return np.sum(np.log(common))

def con_fun(theta, *args):
    R = args[0]

    return 1+np.sum(theta * R, axis=1)


cons = ({'type': 'ineq', 'fun': lambda x: con_fun(x, R)})

x0 = np.zeros(R.shape[1])
minimize(fun=goalfun, x0=x0, args=R, constraints=cons)
 fun: -5.658334806882614
 jac: array([ 0.0019, -0.0004, -0.0003,  0.0005, -0.0015,  0.    ])  message: 'Optimization terminated successfully.'
nfev: 92
 nit: 12
njev: 12   status: 0  success: True
   x: array([-0.8209, -0.3547, -0.4198,  0.6612,  0.4605])

请注意,当我运行此程序时,会收到 invalid value encountered in log 警告,表明在搜索中的某个时间点检查了几乎不满足约束条件的 theta 值。但是,结果与cvxpy 的结果相当接近。当在cvxpy.Problem 公式中明确施加约束时,检查cvxpy 解决方案是否发生变化会很有趣。

【讨论】:

  • 是的,对于不在有效域中的值,我返回一个很大的正数,我认为这对于这些类型的问题来说是常见的启发式方法?是的,cvxpy 要复杂得多,cvxpy.log 函数是一个复杂的对象,(据我所知)负责处理有效域
  • 那么使用cons_fun 执行此操作(限制域)是首选程序吗?谢谢
  • @luffe 您实际上是在应用“惩罚”方法,其中问题域是通过更改目标函数隐式施加的。但是,这是一种启发式方法,通常不能保证得到的解决方案与明确强加域的情况相同。当域规范很复杂(例如,许多非线性不等式)时,通常会应用惩罚方法。在这种情况下,域规范非常简单(线性不等式)。
  • 啊,我明白了。但是当我复制并粘贴您的示例时,我只得到Iteration limit exceeded'(重新启动了我的 IPython (2) sesson)。谢谢
  • @luffe 在 Python 2 和 Python 3 中都能正常工作 (scipy.__version__ 0.18.1)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-26
相关资源
最近更新 更多