【发布时间】:2017-02-21 15:39:00
【问题描述】:
我有一个简单的凸问题,我正在尝试加快解决速度。我正在解决 argmin (theta) of
其中 theta 和 rt 是 Nx1。
我可以用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,这太慢了,所以我正在尝试使用scipy 的fmin_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