1

解を高速化しようとしている単純な凸の問題があります。の argmin ( theta ) を解いています

式

ここで、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これが大きくなると遅くなりすぎるので、scipy'sを使用してグラデーションベースの方法を試していますfmin_cg:

goalfunscipy.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 は、が実質的に最適なthetax0に等しい場合のみです) 。

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は簡単に処理できますが、非凸ソルバーにとっては完全に病的であることが判明します。この問題は本当に厄介ですか、それとも何か不足していますか? これをスピードアップするための代替手段は何ですか?

4

1 に答える 1