[英]scipy.optimize.minimize(method=‘SLSQP’) memory issues when outside the bounds
I am working with scipy.optimize.minimize(method='SLSQP')
, the function and constraints are interpolated with scipy.interpolate.LinearNDInterpolator
. 我正在使用
scipy.optimize.minimize(method='SLSQP')
,函数和约束是通过scipy.interpolate.LinearNDInterpolator
进行插值的。 The start values are random numbers inside the bounds. 起始值为边界内的随机数。
I am working with: 我正在与:
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. 优化有时会运行并给出合理的结果,但有时优化器会开始请求高达20GB的大量内存,然后我的计算机停止工作。 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')
? scipy.interpolate.LinearNDInterpolator
是否有可能无法与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. 在边界之外,我没有模拟数据,因此插值给出fill_Value = 0或fill_value = 1e10。
Same behavior occurs when I am working with scipy.optimize.fmin_slsqp 当我使用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})
My own solution up to now is not to use the scipy.interpolate.LinearNDInterpolator but to replace it with several one-dimensional interpolations. 到目前为止,我自己的解决方案不是使用scipy.interpolate.LinearNDInterpolator,而是将其替换为多个一维插值。 For a 3D Problem and a cubic interpolation with scipy.interpolate.UnivariateSpline I need 64 data points on a rectangular grid.
对于3D问题和带有scipy.interpolate.UnivariateSpline的三次插值,我需要在矩形网格上放置64个数据点。 In the first step I only interpolate (16 times) in coordinate direction 1 and reduce my problem to a 2D-one with 16 points.
在第一步中,我仅在坐标方向1上进行插值(16次),然后将问题简化为具有16个点的2D模型。 In the next step I interpolate (4 times) in coordinate direction 2 and reduce further to a 1D promlem with 4 points left.
在下一步中,我在坐标方向2上进行插值(4次),并进一步减少到剩下4个点的1D问题。 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.
最后一步是在坐标方向3上进行一维插值。使用此过程,即使在边界之外,scipy.optimize.minimize(method ='SLSQP')也不会遇到内存问题。 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
#
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)
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. 好像您为变量定义了
max
和min
范围。
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 ). 我知道,根据我使用的
scipy
的版本,有时最小化函数将不接受我的界限,除非它们以浮点数给出(这是一个非常可怕的错误)。
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. 这通常对我有用。
sudo -H pip install --upgrade scipy
sudo -H pip install --upgrade numpy
solved the problem completely 彻底解决了问题
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.