优化具有多个数据集的数值模型(scipy.minimize / scipy.optimise,pymoo 或 ??)
Optimisation of a numerical model with several data sets (scipy.minimize / scipy.optimise, pymoo or ??)
所以我有一个问题,此时我有点迷茫。所以任何意见都将不胜感激,因为我现在真的很挣扎!
我有一个模型,我想 check/optimise 使用我得到的一些实验数据。
一般来说,我的模型有两个输入(我们称之为:时间和温度)并且有 8 个变量 (x0-x7)。该模型生成两个输出(out1 和 out2)。
我的每组实验数据都为我提供了 4 组可用于优化的信息:2 个输入(时间和温度)和 2 个实验结果(result1 和 result2)。
最终我想最小化 result1 & out1 和 result2 & out2 之间的差异。所以基本上用几组数据最小化两个残差,这些数据受 8 个参数的影响,它们都有共同点 (x0-x7)。
我对参数 x0-x7 有一些限制,这可以提供帮助,但除此之外没有真正的限制。
到目前为止,我已经尝试使用 scipy.minimize
对我的实验结果数据集进行迭代,如下所示(非常示意性):
import numpy as np
from scipy.optimize import minimize
Experiment=[['Set 1','Set 2',
'Set 3','Set 4'],
[Out 1-1,Out 1-2,
Out 1-3,Out 1-4],
[Out 2-1,Out 2-2,
Out 2-3,Out 2-4],
]
global curr_case
curr_case=0 #just for debugging in the first place
def objective_fcn(x):
SetFitParameters(x) #x0-x7
#---------probably totally dumb: iteration-----------
global curr_case #number of experimental set
curr_case=curr_case+1
if curr_case==len(Experiment):
curr_case=0
#----------------------------------------------------
getTemp(curr_case) # function that gets time and temperature from experimental data as two arrays - time and temperature
RefVariables(x) #sets some global variabales needed for ModelCal using x0-x7
ModelCal(time,Temperature) #gives Out1 and Out2
f1 = abs(Out1[Upper_index-1]-Experiment[1][curr_case]) #compares Out1 with result1 (from experimental data)
f2 = abs(Out2[Upper_index-1]-Experiment[2][curr_case]) #compares Out2 with result2 (from experimental data)
# some weighting factors for the future - maybe?
A=1
B=1
return A*f1+B*f2
bounds_x1=(1450,1700) #upper and lower bonds of x0
bounds_x2=(0.1,1)
bounds_x3=(1450,1700)
bounds_x4=(0.1,7)
bounds_x5=(1450,1700)
bounds_x6=(0.1,7)
bounds_x7=(1450,1700)
bounds_x8=(0.1,7)
bounds=[bounds_x1,bounds_x2,bounds_x3,bounds_x4,bounds_x5,bounds_x6,bounds_x7,bounds_x8]
x0=[1663,0.156,1523,6.37,1663,4.38,1523,2.2] #some initial guesses
result=minimize(objective_fcn, x0,bounds=bounds)
这显然行不通,因为我只是遍历了不同的案例。在 Whosebug 上搜索已经产生了一些结果,但是,它们似乎都优化了一个给定的函数,而我没有!
第一个问题是:您会推荐哪种优化?这甚至接近有用的东西吗?
第二个问题:如何在优化时考虑多个实验数据集?我获取输入的方法似乎相当粗糙。我还尝试用已经实现为数组元素的数据创建两个列表,但也无济于事。
最后:任何对优化有一点了解的人都可以看出,我在这个领域还很新手 - 所以我提前道歉,但如果有人能指出我正确的方向或可以提供帮助 - 将不胜感激!
我已经找到的来源:
-Fitting multiple data sets using scipy.optimize with the same parameters
-
共享对象函数的基本思想很好。我并没有真正详细介绍 OP 尝试,因为这可能会产生误导。该过程将定义可用于最小二乘拟合的适当残差函数。在 Python 中有几种可能性可以做到这一点。我将展示 scipy.optimize.leastsq
和密切相关的 scipy.optimize.least_squares
.
import numpy as np
from scipy.optimize import least_squares ## allows bounds and has given loss functions but provides only Jacobian
from scipy.optimize import leastsq ## provides scaled covariance matrix
"""
some arbitrary test function taking two inputs and providing
two correlated outputs with shared parameters - only three for testing.
"""
def test_function( time, temp, x0, x1, x2 ):
s = np.sqrt( time/x0 ) * np.log( ( temp - x1 ) / x2 )
t = np.exp( - time/x0 ) * np.sqrt( (time/x0)**2 + ( ( temp - x1 ) / x2 )**2 )
return s, t
### make some data with noise
indata = list()
for _ in range( 60 ):
a = 50 * np.random.random()
b = 10 + 25 * np.random.random()
indata.append( [a,b] )
outdata = list()
for a,b in indata:
s,t = test_function( a, b, 3.78, 5.33, 12.88 )
noise1 = np.random.normal( scale=0.01 )
noise2 = np.random.normal( scale=0.01 )
outdata.append( [s + noise1, t + noise2 ] )
indata = np.array( indata)
outdata = np.array( outdata)
#########################################################################
### define the residuals function for fitting This is the important part!
#########################################################################
def residuals( params, xdata, ydata, weightA=1, weightB=1 ):
x0, x1, x2 = params
diff = list()
for ab, st in zip( indata, outdata ):
a, b = ab
s, t = st
sf, tf = test_function( a, b, x0,x1, x2 )
diff.append( weightA * ( s - sf ) )
diff.append( weightB * ( t - tf ) )
return diff
### Fit
solx, cov, info, msg, ier = leastsq(
residuals, [ 3.8, 5.0, 12.5],
args=( indata, outdata ), full_output=True
)
print solx
print cov
sol = least_squares( residuals, [ 3.8, 5.0, 12.5 ], args=( indata, outdata ))
print sol.x
根据 OP 的需要修改它应该很容易。
所以我有一个问题,此时我有点迷茫。所以任何意见都将不胜感激,因为我现在真的很挣扎!
我有一个模型,我想 check/optimise 使用我得到的一些实验数据。
一般来说,我的模型有两个输入(我们称之为:时间和温度)并且有 8 个变量 (x0-x7)。该模型生成两个输出(out1 和 out2)。
我的每组实验数据都为我提供了 4 组可用于优化的信息:2 个输入(时间和温度)和 2 个实验结果(result1 和 result2)。
最终我想最小化 result1 & out1 和 result2 & out2 之间的差异。所以基本上用几组数据最小化两个残差,这些数据受 8 个参数的影响,它们都有共同点 (x0-x7)。
我对参数 x0-x7 有一些限制,这可以提供帮助,但除此之外没有真正的限制。
到目前为止,我已经尝试使用 scipy.minimize
对我的实验结果数据集进行迭代,如下所示(非常示意性):
import numpy as np
from scipy.optimize import minimize
Experiment=[['Set 1','Set 2',
'Set 3','Set 4'],
[Out 1-1,Out 1-2,
Out 1-3,Out 1-4],
[Out 2-1,Out 2-2,
Out 2-3,Out 2-4],
]
global curr_case
curr_case=0 #just for debugging in the first place
def objective_fcn(x):
SetFitParameters(x) #x0-x7
#---------probably totally dumb: iteration-----------
global curr_case #number of experimental set
curr_case=curr_case+1
if curr_case==len(Experiment):
curr_case=0
#----------------------------------------------------
getTemp(curr_case) # function that gets time and temperature from experimental data as two arrays - time and temperature
RefVariables(x) #sets some global variabales needed for ModelCal using x0-x7
ModelCal(time,Temperature) #gives Out1 and Out2
f1 = abs(Out1[Upper_index-1]-Experiment[1][curr_case]) #compares Out1 with result1 (from experimental data)
f2 = abs(Out2[Upper_index-1]-Experiment[2][curr_case]) #compares Out2 with result2 (from experimental data)
# some weighting factors for the future - maybe?
A=1
B=1
return A*f1+B*f2
bounds_x1=(1450,1700) #upper and lower bonds of x0
bounds_x2=(0.1,1)
bounds_x3=(1450,1700)
bounds_x4=(0.1,7)
bounds_x5=(1450,1700)
bounds_x6=(0.1,7)
bounds_x7=(1450,1700)
bounds_x8=(0.1,7)
bounds=[bounds_x1,bounds_x2,bounds_x3,bounds_x4,bounds_x5,bounds_x6,bounds_x7,bounds_x8]
x0=[1663,0.156,1523,6.37,1663,4.38,1523,2.2] #some initial guesses
result=minimize(objective_fcn, x0,bounds=bounds)
这显然行不通,因为我只是遍历了不同的案例。在 Whosebug 上搜索已经产生了一些结果,但是,它们似乎都优化了一个给定的函数,而我没有!
第一个问题是:您会推荐哪种优化?这甚至接近有用的东西吗?
第二个问题:如何在优化时考虑多个实验数据集?我获取输入的方法似乎相当粗糙。我还尝试用已经实现为数组元素的数据创建两个列表,但也无济于事。
最后:任何对优化有一点了解的人都可以看出,我在这个领域还很新手 - 所以我提前道歉,但如果有人能指出我正确的方向或可以提供帮助 - 将不胜感激!
我已经找到的来源:
-Fitting multiple data sets using scipy.optimize with the same parameters
-
共享对象函数的基本思想很好。我并没有真正详细介绍 OP 尝试,因为这可能会产生误导。该过程将定义可用于最小二乘拟合的适当残差函数。在 Python 中有几种可能性可以做到这一点。我将展示 scipy.optimize.leastsq
和密切相关的 scipy.optimize.least_squares
.
import numpy as np
from scipy.optimize import least_squares ## allows bounds and has given loss functions but provides only Jacobian
from scipy.optimize import leastsq ## provides scaled covariance matrix
"""
some arbitrary test function taking two inputs and providing
two correlated outputs with shared parameters - only three for testing.
"""
def test_function( time, temp, x0, x1, x2 ):
s = np.sqrt( time/x0 ) * np.log( ( temp - x1 ) / x2 )
t = np.exp( - time/x0 ) * np.sqrt( (time/x0)**2 + ( ( temp - x1 ) / x2 )**2 )
return s, t
### make some data with noise
indata = list()
for _ in range( 60 ):
a = 50 * np.random.random()
b = 10 + 25 * np.random.random()
indata.append( [a,b] )
outdata = list()
for a,b in indata:
s,t = test_function( a, b, 3.78, 5.33, 12.88 )
noise1 = np.random.normal( scale=0.01 )
noise2 = np.random.normal( scale=0.01 )
outdata.append( [s + noise1, t + noise2 ] )
indata = np.array( indata)
outdata = np.array( outdata)
#########################################################################
### define the residuals function for fitting This is the important part!
#########################################################################
def residuals( params, xdata, ydata, weightA=1, weightB=1 ):
x0, x1, x2 = params
diff = list()
for ab, st in zip( indata, outdata ):
a, b = ab
s, t = st
sf, tf = test_function( a, b, x0,x1, x2 )
diff.append( weightA * ( s - sf ) )
diff.append( weightB * ( t - tf ) )
return diff
### Fit
solx, cov, info, msg, ier = leastsq(
residuals, [ 3.8, 5.0, 12.5],
args=( indata, outdata ), full_output=True
)
print solx
print cov
sol = least_squares( residuals, [ 3.8, 5.0, 12.5 ], args=( indata, outdata ))
print sol.x
根据 OP 的需要修改它应该很容易。