簡體   English   中英

超出范圍時scipy.optimize.minimize(method ='SLSQP')內存問題

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

我正在使用scipy.optimize.minimize(method='SLSQP') ,函數和約束是通過scipy.interpolate.LinearNDInterpolator進行插值的。 起始值為邊界內的隨機數。

我正在與:

  1. scipy 0.13.3
  2. cython 0.20.1

優化有時會運行並給出合理的結果,但有時優化器會開始請求高達20GB的大量內存,然后我的計算機停止工作。 這總是發生在邊界之外的值。

scipy.interpolate.LinearNDInterpolator是否有可能無法與scipy.optimize.minimize(method='SLSQP') 在邊界之外,我沒有模擬數據,因此插值給出fill_Value = 0或fill_value = 1e10。

當我使用scipy.optimize.fmin_slsqp時,會發生相同的行為

不幸的是我的代碼很大,但是有了這個數據集,我總是遇到內存問題:

#########################################
###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})

到目前為止,我自己的解決方案不是使用scipy.interpolate.LinearNDInterpolator,而是將其替換為多個一維插值。 對於3D問題和帶有scipy.interpolate.UnivariateSpline的三次插值,我需要在矩形網格上放置64個數據點。 在第一步中,我僅在坐標方向1上進行插值(16次),然后將問題簡化為具有16個點的2D模型。 在下一步中,我在坐標方向2上進行插值(4次),並進一步減少到剩下4個點的1D問題。 最后一步是在坐標方向3上進行一維插值。使用此過程,即使在邊界之外,scipy.optimize.minimize(method ='SLSQP')也不會遇到內存問題。 插值代碼如下:

#!/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
#

測試4D二次方

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)

但是,為什么插值始終超出變量的定義范圍?

好像您為變量定義了maxmin范圍。

我知道,根據我使用的scipy的版本,有時最小化函數將不接受我的界限,除非它們以浮點數給出(這是一個非常可怕的錯誤)。

您可以嘗試將邊界重新定義為

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

這通常對我有用。

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

徹底解決了問題

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM