Scipy selects nan as inputs while minimizing

2.4k views Asked by At

I have this objective function (in python) :

actions= [...] # some array
Na= len(actions)    
# maximize p0 * qr(s,a0,b0) + ... + pn * qr(s,an,bn)
def objective(x):
        p = x[:Na] # p is a probability distribution
        b = x[Na:2 * Na] # b is an array of positive unbounded scalars
        q = np.array([qr(s, actions[a], b[a]) for a in range(0, Na)]) # s is an array
        rez = - np.dot(p, q) # np stands for numpy library
        return rez

qr and qc are regression trees, these are functions mapping arrays to scalars.

I have these constraints :

# p0 * qc(s,a0,b0) + ... + pn * qc(s,an,bn) < beta
def constraint(x):
    p = x[:Na]
    b = x[Na:2 * Na]
    q = np.array([qc(s, actions[a], b[a]) for a in range(0, Na)])
    rez = beta - np.dot(p, q) # beta is a scalar        
    return rez

# elements of p should sum to 1
def constraint_proba_sum_1(x):
    p = x[:Na]
    rez = 0
    for i in range(0, Na):
        rez += p[i]
    rez = 1 - rez
    return rez

How I minimize :

constraints = ({'type': 'ineq', 'fun': constraint},
                   {'type': 'eq', 'fun': constraint_proba_sum_1})

res = opt.minimize(fun=objective, x0=np.array([0.5, 0.5, 10, 10]), constraints=constraints,
                       bounds=[(0, 1), (0, 1), (0, None), (0, None)])

The problem is opt.minimize uses nan arrays as inputs sometimes during its minimization process "slsqp". Thus the qr tree raises errors.Why would it evaluate such arrays, in what circumstances ?

I do realize this issue is the same as this post Scipy optimizations methods select nan for input parameter but it is not resolved and it looks like function dependent.

EDIT : It appears that if I remove the constraint constraint_proba_sum_1(x), I dont have NaN value as input anymore.

EDIT 2 : I tryed another API, pyOPT with SLSQP optimization and I have the same issue.

2

There are 2 answers

0
Imco van Gent On

I don't have a full answer to this question, but I have experienced the same behaviour as you in my own optimization script and wanted to share my way of fixing it.

First of all, also in my case it helped to remove one of the constraints. The reason that this helps is because Scipy.minimize cannot handle an optimization where you start with voilated constraints. So if c == 0.0 and c = 0.3 at the start point, then it will, at some point, set nan values for the design variables when it's optimizing. Of course, just removing a constraint is generally not an option, so what helped in my case was to set stricter bounds on the design variables such that it is less likely to start with a point that is invalid (hence, has constraint violations). Note that this assumes that you run the optimization multiple times at different start points (which is true for my set-up). In your case, I think it is just a matter of choosing a start point x0 which has an unviolated (valid) constraint_proba_sum_1(x).

So in conclusion, one way of avoiding this issue is to make sure that the start point of your optimization is a valid point in terms of the constraints that you have provided.

0
kossikater On

I observed a similar behavoir for scipy's differential_evolution optimizer, and I could trace this back to the polish argument, which runs a local minimization after the global optimization. Since this appeared only after the max iterations of the DE optimizer (apparently the parameters of my model cannot be identified from the data I have at hand), the init of the local minimizer from the DE opt object caused similiar effects as the other posts describe.

My fix was to catch within the objective function for occurence of NaN values and raising an exception, since this happens for my only when the DE optimizer could not find an optimium.