2017-09-18 5 views
1

Dans un certain but, dans une partie de mon code, je veux deviner polynom 5ème degré, qui correspond le mieux à mes données et ne diminue pas dans certains points.Scipy optimiser minimiser la conjecture initiale en utilisant SLSQP

L'exemple de code est:

import numpy as np 
import scipy.optimize as optimize 

def make_const(points): 
    constr = [] 
    for point in points: 
     c = {'type' : 'ineq', 'fun' : der, 'args' : (point,)} 
     constr.append(c) 
    return constr 

def der(args_pol, bod): 
    a, b, c, d, e, f = args_pol 
    return (5*a*bod**4 + 4*b*bod**3 + 3*c*bod**2 + 2*d*bod + e) 


def squares(args_pol, x, y): 
    a, b, c, d, e, f = args_pol 
    return ((y-(a*x**5 + b*x**4 + c*x**3 + d*x**2 + e*x + f))**2).sum() 

def ecdf(arr): 
    arr = np.array(arr) 
    F = [len(arr[arr<=t])/len(arr) for t in arr] 
    return np.array(F) 

pH = np.array([8,8,8,7,7,7,7,7,7,7,7,6,3,2,2,2,1]) 
pH = np.sort(pH) 
e = ecdf(pH) 
ppoints = [ 1., 2.75, 4.5, 6.25, 8. ] 
constraints1 = make_const(ppoints) 

p1 = optimize.minimize(squares, [1.0, 1.0, 1.0, 1.0, 1.0, 1.0], 
         method = 'SLSQP', args = (pH, e), constraints = constraints1) 

p2 = optimize.minimize(squares, [-1.0, -1.0, -1.0, -1.0, -1.0, -1.0], 
         method = 'SLSQP', args = (pH, e), constraints = constraints1) 

Ici p1 ne parvient pas à optimiser, p2 se termine avec succès. En outre, si je n'ai pas de contraintes, donc si ppoints = [], p1 termites avec succès tandis que p2 échoue. Le message si optimisations échoue toujours:

'Inequality constraints incompatible' 

Le problème est évidemment initial guess dans optimize.minimize. Je pense que les paramètres de cette supposition doivent rencontrer mes contraintes. Mais ici, la première estimation [1.0, 1.0, 1.0, 1.0, 1.0, 1.0] répond à mes contsraints. Quelqu'un peut-il expliquer, où est le problème? Oui, votre point initial satisfait aux contraintes.

Répondre

2

Mais SLSQP fonctionne avec des contraintes linéarisées et recherche une direction de recherche compatible avec toutes les linéarisations (described here). Celles-ci peuvent s'avérer soit incompatibles, soit peu compatibles dans le sens où il n'y a qu'un petit nombre de directions qui se qualifient, et la recherche ne parvient pas à les trouver.

Le point de départ [1, 1, 1, 1, 1, 1] n'est pas bon. Considérons qu'en x = 8 la contribution du premier coefficient 1 au polynôme est 8**5, et puisque son carré est dans la fonction objectif, vous obtenez environ 8**10. Ceci éclipse la contribution des coefficients d'ordre inférieur, qui sont néanmoins importants pour satisfaire les contraintes aux points proches de 0. Ainsi, l'algorithme est présenté avec un problème mal dimensionné lorsque le point initial est tout-un.

L'utilisation de np.zeros((6,)) comme point de départ est une meilleure idée; la recherche réussit à partir de là. La mise à l'échelle du point initial comme [7**(d-5) for d in range(6)] fonctionne également mais à peine (remplacer 7 par 6 ou 8 donne un autre type d'erreur, "Dérivé directionnel positif pour la recherche de lignes"). Donc, le résumé est le suivant: le problème d'optimisation a une mauvaise mise à l'échelle, ce qui rend la recherche difficile; et le message d'erreur n'est pas très explicite sur ce qui s'est vraiment mal passé. En plus de changer le point initial, vous pouvez essayer de fournir les Jacobiens de la fonction objective et des contraintes (les deux sont importants, car la méthode fonctionne avec le lagrangien).

+0

Votre solution est excellente, mais j'ai eu les mêmes problèmes avec différents ensembles de données. Alors j'ai réécrit mon code pour travailler avec la 4ème fonction polynomiale, et indépendamment de ce que j'ai d'autres problèmes, le problème de supposition initiale est résolu. – Bobesh