J'ai un simple problème convexe J'essaie d'accélérer la solution de. Je résous le argmin (thêta) deOptimisation rapide de la fonction convexe "pathologique"
où thêta et rt est Nx1.
Je peux résoudre ce facilement avec 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]])
Mais pour une plus grande R
cela devient trop lent, donc je suis en train une méthode basée sur gradient avec l » fmin_cg
scipy
:
goalfun
est un fonction conviviale qui renvoie la valeur de la fonction et le gradient.
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
assuré que la fonction et les gradients sont corrects:
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]))
Mais résoudre cela donne juste des ordures, quel que soit method
, itérations, etc. (Les seules choses que les rendements Optimization terminated successfully
est si x0
est pratiquement égale à la optimale thêta)
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])
Ie Ce problème apparemment inoffensif, que l'on peut facilement traiter, s'avère complètement pathologique pour un solveur non-convexe. Ce problème est vraiment méchant, ou est-ce que je manque quelque chose? Quelle serait une alternative pour accélérer cela?
Avez-vous essayé le solveur [SCS] (https: // github.com/cvxgrp/scs) (dans cvxpy), probablement avec le mode '' 'use_indirect = True'''? – sascha
Non, je n'ai pas défini d'options de résolution, tout ce que j'ai exécuté est tel qu'il est dans l'exemple ci-dessus, j'ai supposé que les options par défaut étaient correctes ici? – luffe
Bien sûr, par défaut utilise ECOS qui est bon. SCS est parfois ** beaucoup ** plus rapide tout en étant un peu moins précis (méthode basée sur ADMM). Il y a deux modes, où l'on est quelque chose comme une méthode tronquée-newton. (SCS compilé à partir des sources sera beaucoup plus rapide que celui par défaut, multithreading). Il y a même un support GPU. ** UPDATE ** ecos: 90secs; scs = 3 secs pour 5000x500 (installation de la source avec MT, use_indirect = True). – sascha