scipy.optimize.minimize(method=‘SLSQP’) memory issues when outside the bounds

泪湿孤枕 提交于 2019-12-11 08:25:47

问题


I am working with scipy.optimize.minimize(method=‘SLSQP’), the function and constraints are interpolated with scipy.interpolate.LinearNDInterpolator. The start values are random numbers inside the bounds.

I am working with:

  1. scipy 0.13.3
  2. cython 0.20.1

The optimizations sometimes runs and gives a reasonable results but sometimes the optimizer begins to request huge amounts of memory up to 20GB then my computer stops working. This always occurs with values outside the boundary.

Is it possible that the scipy.interpolate.LinearNDInterpolator cannot be used with scipy.optimize.minimize(method=‘SLSQP’)? Outside the bounds I have no simulation data so the interpolation gives a fill_Value=0 or fill_value=1e10.

Same behavior occurs when I am working with scipy.optimize.fmin_slsqp

Unfortunately my code is very large but with this data set I always get memory issues:

#########################################
###Memory Leak scipy.optimize.minimize###
#########################################
import numpy as np
from scipy.optimize import minimize
from scipy.interpolate import LinearNDInterpolator
def objfun(x):
    print x
    return x[1]

points = np.array([[  0.00000000e+00,   0.00000000e+00],[  0.00000000e+00,   1.00334000e+00],[  0.00000000e+00,   2.00669000e+00],[  7.07700000e+02,   0.00000000e+00],[  7.07700000e+02,   1.00334000e+00],[  7.07700000e+02,   2.00669000e+00],[  1.56890000e+03,   0.00000000e+00],[  1.56890000e+03,   1.00334000e+00],[  1.56890000e+03,   2.00669000e+00],[  2.50080000e+03,   0.00000000e+00],[  2.50080000e+03,   1.00334000e+00],[  2.50080000e+03,   2.00669000e+00],[  3.47090000e+03,   0.00000000e+00],[  3.47090000e+03,   1.00334000e+00],[  3.47090000e+03,   2.00669000e+00],[  4.46380000e+03,   0.00000000e+00],[  4.46380000e+03,   1.00334000e+00],[  4.46380000e+03,   2.00669000e+00],[  5.47130000e+03,   0.00000000e+00],[  5.47130000e+03,   1.00334000e+00],[  5.47130000e+03,   2.00669000e+00],[  6.48890000e+03,   0.00000000e+00],[  6.48890000e+03,   1.00334000e+00],[  6.48890000e+03,   2.00669000e+00],[  7.51360000e+03,   0.00000000e+00],[  7.51360000e+03,   1.00334000e+00],[  7.51360000e+03,   2.00669000e+00],[  8.54350000e+03,   0.00000000e+00],[  8.54350000e+03,   1.00334000e+00],[  8.54350000e+03,   2.00669000e+00],[  9.57740000e+03,   0.00000000e+00],[  9.57740000e+03,   1.00334000e+00],[  9.57740000e+03,   2.00669000e+00],[  1.06143000e+04,   0.00000000e+00],[  1.06143000e+04,   1.00334000e+00],[  1.06143000e+04,   2.00669000e+00],[  1.16535000e+04,   0.00000000e+00],[  1.16535000e+04,   1.00334000e+00],[  1.16535000e+04,   2.00669000e+00],[  1.26945000e+04,   0.00000000e+00],[  1.26945000e+04,   1.00334000e+00],[  1.26945000e+04,   2.00669000e+00],[  1.37369000e+04,   0.00000000e+00],[  1.37369000e+04,   1.00334000e+00],[  1.37369000e+04,   2.00669000e+00],[  1.47804000e+04,   0.00000000e+00],[  1.47804000e+04,   1.00334000e+00],[  1.47804000e+04,   2.00669000e+00],[  1.58248000e+04,   0.00000000e+00],[  1.58248000e+04,   1.00334000e+00],[  1.58248000e+04,   2.00669000e+00],[  1.68698000e+04,   0.00000000e+00],[  1.68698000e+04,   1.00334000e+00],[  1.68698000e+04,   2.00669000e+00],[  1.79153000e+04,   0.00000000e+00],[  1.79153000e+04,   1.00334000e+00],[  1.79153000e+04,   2.00669000e+00],[  1.89612000e+04,   0.00000000e+00],[  1.89612000e+04,   1.00334000e+00],[  1.89612000e+04,   2.00669000e+00],[  2.00074000e+04,   0.00000000e+00],[  2.00074000e+04,   1.00334000e+00],[  2.00074000e+04,   2.00669000e+00]])
values = np.array([  0.00000000e+00,   0.00000000e+00,   0.00000000e+00,4.29730000e+01,   5.72947500e-01,  -5.35464000e-01,9.11676000e+01,   1.31063500e+00,  -1.05937500e+00,1.38660750e+02,   2.11484000e+00,  -1.50850500e+00,1.84497000e+02,   2.96052000e+00,  -1.88466000e+00,2.28622000e+02,   3.83846000e+00,  -2.19702000e+00,2.71163000e+02,   4.74426500e+00,  -2.45397000e+00,3.12274500e+02,   5.67547500e+00,  -2.66222500e+00,3.52102000e+02,   6.63058000e+00,  -2.82711000e+00,3.90774000e+02,   7.60858000e+00,  -2.95286000e+00,4.28399500e+02,   8.60879000e+00,  -3.04289000e+00,4.65074500e+02,   9.63071000e+00,  -3.10001500e+00,5.00881500e+02,   1.06739850e+01,  -3.12655500e+00,5.35893000e+02,   1.17383500e+01,  -3.12444000e+00,5.70166500e+02,   1.28235000e+01,  -3.09540500e+00,6.03760000e+02,   1.39293500e+01,  -3.04082500e+00,6.36721500e+02,   1.50557500e+01,  -2.96194500e+00,6.69093500e+02,   1.62026000e+01,  -2.85982000e+00,7.00915000e+02,   1.73698000e+01,  -2.73539500e+00,7.32222000e+02,   1.85573500e+01,  -2.58950000e+00,7.63042500e+02,   1.97651000e+01,  -2.42286000e+00])

S22_Adh1Ad_inter = LinearNDInterpolator(points,values,1e10)
def Fsigcon(x):
    rf1_int = x[1]
    rf_eval=[]
    x_eval=[]
    interval = np.linspace(0,x[0],x[0]/0.01)
    if interval.size == 0:
        interval=np.array([x[0]])
    for xcoord in interval:
        rf_eval.append(rf1_int)
        x_eval.append(xcoord)
    val_interp = S22_Adh1Ad_inter(rf_eval,x_eval) #'nearest' #'linear' #'cubic'
    out = (val_interp.min()-39.45)
    return out 

points = np.array([[  0.00000000e+00,   0.00000000e+00],[  0.00000000e+00,   1.99997000e-01],[  0.00000000e+00,   4.00002000e-01],[  7.07700000e+02,   1.39999000e-01],[  7.07700000e+02,   3.39996000e-01],[  1.56890000e+03,   8.00020000e-02],[  1.56890000e+03,   2.79999000e-01],[  2.50080000e+03,   1.99970000e-02],[  2.50080000e+03,   2.20001000e-01],[  2.50080000e+03,   1.90000200e+00],[  3.47090000e+03,   1.60004000e-01],[  3.47090000e+03,   3.60001000e-01],[  4.46380000e+03,   9.99980000e-02],[  4.46380000e+03,   3.00003000e-01],[  5.47130000e+03,   4.00010000e-02],[  5.47130000e+03,   2.39998000e-01],[  5.47130000e+03,   3.00000000e+00],[  6.48890000e+03,   1.80000000e-01],[  6.48890000e+03,   3.79997000e-01],[  7.51360000e+03,   1.20003000e-01],[  7.51360000e+03,   3.20000000e-01],[  8.54350000e+03,   5.99980000e-02],[  8.54350000e+03,   2.60002000e-01],[  9.57740000e+03,   0.00000000e+00],[  9.57740000e+03,   1.99997000e-01],[  9.57740000e+03,   4.00002000e-01],[  1.06143000e+04,   1.39999000e-01],[  1.06143000e+04,   3.39996000e-01],[  1.16535000e+04,   8.00020000e-02],[  1.16535000e+04,   2.79999000e-01],[  1.26945000e+04,   1.99970000e-02],[  1.26945000e+04,   2.20001000e-01],[  1.26945000e+04,   1.90000200e+00],[  1.37369000e+04,   1.60004000e-01],[  1.37369000e+04,   3.60001000e-01],[  1.47804000e+04,   9.99980000e-02],[  1.47804000e+04,   3.00003000e-01],[  1.58248000e+04,   4.00010000e-02],[  1.58248000e+04,   2.39998000e-01],[  1.58248000e+04,   3.00000000e+00],[  1.68698000e+04,   1.80000000e-01],[  1.68698000e+04,   3.79997000e-01],[  1.79153000e+04,   1.20003000e-01],[  1.79153000e+04,   3.20000000e-01],[  1.89612000e+04,   5.99980000e-02],[  1.89612000e+04,   2.60002000e-01],[  2.00074000e+04,   0.00000000e+00],[  2.00074000e+04,   1.99997000e-01],[  2.00074000e+04,   4.00002000e-01]])

values = np.array([ 0.      ,  0.      ,  0.      ,  0.010168,  0.010055,  0.046252,0.045731,  0.092687,  0.107056,  0.11196 ,  0.19232 ,  0.190859,0.29924 ,  0.295611,  0.401297,  0.42018 ,  0.450553,  0.564416,0.561699,  0.727387,  0.719631,  0.883825,  0.894486,  0.      ,1.087256,  1.084631,  1.298136,  1.287209,  1.507127,  1.505308,1.424393,  1.740491,  1.839568,  1.993769,  1.981605,  2.251336,2.238475,  2.330676,  2.511822,  2.723058,  2.803453,  2.792818,3.104855,  3.08533 ,  3.29549 ,  3.393902,  0.      ,  3.721085,3.714504])

G_Adh1Ad_inter = LinearNDInterpolator(points,values,0)
def Gcon(x):
    val_interp = G_Adh1Ad_inter(x[1],x[0])
    out = (val_interp.min()-0.33)
    return out

cons = (
    {'type': 'ineq',
    'fun' : Fsigcon},
    {'type': 'ineq',
    'fun' : Gcon}
    )
amin = 0.0
amax = 3.0
bounds=[(amin,amax),(0.0, 20007.400000000001)]
a_start=  1.5343936873636999
rf1_start= 6824.9659188661817
res_int = minimize(objfun, [a_start,rf1_start],method='SLSQP',jac=None,bounds=bounds,constraints=cons,tol =1e-4,options={'iprint':2,  'disp': True , 'maxiter':1e2})

回答1:


My own solution up to now is not to use the scipy.interpolate.LinearNDInterpolator but to replace it with several one-dimensional interpolations. For a 3D Problem and a cubic interpolation with scipy.interpolate.UnivariateSpline I need 64 data points on a rectangular grid. In the first step I only interpolate (16 times) in coordinate direction 1 and reduce my problem to a 2D-one with 16 points. In the next step I interpolate (4 times) in coordinate direction 2 and reduce further to a 1D promlem with 4 points left. The last step is one 1D interpolation in coordinate direction 3. With this procedure scipy.optimize.minimize(method=‘SLSQP’) does not run into memory issues even when outside the bounds. The interpolation code is the following:

#!/usr/bin/python
# coding: utf8
# Filename: N1Dsplines.py
import numpy as np
from scipy.interpolate import UnivariateSpline
from scipy.interpolate import LinearNDInterpolator

def sort2lists(list1=[],list2=[]):
    '''
    Lists must be equal size
    sorts after list1
    '''
    list1list2 = [(list1[i1],list2[i1]) for i1 in range(len(list1))]
    list1list2 = sorted(list1list2, key=lambda x:x[0])
    list1 = [i1[0] for i1 in list1list2]
    list2 = [i1[1] for i1 in list1list2]
    return list1,list2


def sortdictkeysandreturnvalues(dictionary):
    keyvalues = [[i1,dictionary[i1]] for i1 in dictionary]
    keyvalues = sorted(keyvalues, key= lambda x: x[0])
    points = [i1[1] for i1 in keyvalues]
    return points

def meshgrid2(*arrs):
    if len(arrs)==1:
    arrs = tuple(arrs[0])

    # list with entries= length of the input arrays
    lens = map(len, arrs)
    # dim = number of arrays
    dim = len(arrs)

    # sz is the multiplication of the length of the *arrs
    sz = 1
    for s in lens:
    sz*=s

    ans = []    
    for i, arr in enumerate(arrs):
    slc = [1]*dim
    slc[i] = lens[i]
    arr2 = np.asarray(arr).reshape(slc)
    for j, sz in enumerate(lens):
        if j!=i:
        arr2 = arr2.repeat(sz, axis=j) 
    ans.append(arr2)
    return tuple(ans)


def arr2points(*arrs):
    '''
    arrs = ([list1], [list2], ...)
    ans = [[x1,y1,z1...],[x1,y1,z2,...],...,[x1,y2,z1,...],...[x2,y1,z1]
    '''
    if len(arrs)==1:
    arrs = tuple(arrs[0])
    # list with entries= length of the input arrays
    lens = map(len, arrs)
    # dim = number of arrays
    dim = len(arrs)

    # sz is the multiplication of the length of the *arrs
    sz = 1
    for s in lens:
    sz*=s

    ans = [[] for i1 in range(sz)]    

    for i1, arr in enumerate(arrs):
    count = 0
    sz2 = 1
    for s in lens[i1+1:]:
        sz2*=s

    for i4 in range(sz/(lens[i1]*sz2)):
        for i2 in arr:
        for i3 in range(sz2):
            ans[count].append(i2)
            count+=1
    return ans

#





def N1Dsplines(pointsvaluesdict={}, point =(), scheme = (1,0), k=3):
    '''
    Geht nur für reguläre Grids nicht für scattered data points
    pointsvaluesdict = {(x,y,z):value , (x,y,z):value ....}
    point = (x,y,z)
    k = interpolation order
    scheme = (2,1,0) bedeutet erst wird in Richtung z=2 dann in Richtung y=1 und als letztes in Richtung x=0 interpoliert
    '''

    #Find the closest Datapoints to the point coordinates
    closest = {i1:[] for i1 in scheme}
    for i1 in scheme:    
    for count in range(k+1):
        points = [i2 for i2 in pointsvaluesdict.keys() if i2[i1] not in closest[i1]]
        closest[i1].append(min(points, key=lambda x:abs(x[i1]-point[i1]))[i1])

    #Make pointgrid from closest points
    liste = sortdictkeysandreturnvalues(closest)  
    pointsgrid = arr2points(liste)
    pointsgrid = [tuple(i1) for i1 in pointsgrid]
    valuesgrid = [pointsvaluesdict[i1] for i1 in pointsgrid]
    griddict = {pointsgrid[i1]:valuesgrid[i1] for i1 in range(len(pointsgrid))}

    #Get 1D Splines by letting scheme[>0]=const and vary scheme[0]
    for i1 in scheme:
    pointsinter = []
    valuesinter = []
    temp = closest.copy()
    del temp[i1]
    points = sortdictkeysandreturnvalues(temp)
    points = arr2points(points)
    for coords in points:

        points2inter=[]
        for i2 in pointsgrid:
        i2red = list(i2)
        del i2red[i1]
        if coords == i2red:
            points2inter.append(i2)
        values2inter = [griddict[i2] for i2 in points2inter]
        points2inter = [i2[i1] for i2 in points2inter]
        points2inter,values2inter = sort2lists(list1=points2inter,list2=values2inter)

        coords.insert(i1,point[i1])
        pointsinter.append(coords)
        s = UnivariateSpline(points2inter, values2inter,k=k, s=0)
        value = s(point[i1])
        valuesinter.append(value)

        closest[i1]=[point[i1]]

    pointsgrid = pointsinter
    pointsgrid = [tuple(i1) for i1 in pointsgrid]
    valuesgrid = valuesinter
    griddict = {pointsgrid[i1]:valuesgrid[i1] for i1 in range(len(pointsgrid))}
    return griddict
#

Test 4D quadratic

x = np.array([1, 2, 3, 4, 5, 6, 7 ,8 ,9, 10])
y = x
z= x
w = x

xx, yy, zz, ww = meshgrid2(x, y,z,w)
v= xx**2 + yy**2 +zz**2 +ww**2
xx = xx.flatten()
yy = yy.flatten()
zz = zz.flatten()
ww = ww.flatten()
v = v.flatten()
pointsvalues = [((xx[i1],yy[i1],zz[i1], ww[i1]),v[i1]) for i1 in range(len(v))]
pointsvaluesdict = {key: value for (key, value) in pointsvalues}
pointsvaluesdict.keys()
pointsvaluesdict.values()

point = (5.5,4.5,3.5,2.5)
5.5**2 + 4.5**2 + 3.5**2 +2.5**2== 69
N1Dsplines(pointsvaluesdict=pointsvaluesdict, point =(5.5,4.5,3.5,2.5), scheme = (0,1,2,3), k=3)

#Outside Bounds
N1Dsplines(pointsvaluesdict=pointsvaluesdict, point =(0,0,0,0), scheme = (0,1,2,3), k=3)



回答2:


Still, why was your interpolation going outside your defined bounds for your variables in the first place?

It seems like you defined your max and min bounds for your variables.

I know that depending on the version of scipy I use, sometimes the minimize function will not accept my bounds, unless they are given in floats ( it's a really terrible bug ).

You could try redefining your bounds as

bnds = np.array( [ [min_var1, max_var1], [min_var2, max_var2] ], dtype = float )

This usually works for me.




回答3:


sudo -H pip install --upgrade scipy
sudo -H pip install --upgrade numpy

solved the problem completely



来源:https://stackoverflow.com/questions/22375171/scipy-optimize-minimizemethod-slsqp-memory-issues-when-outside-the-bounds

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!