我有一组数据;每列对应于特定时间的光谱。我想将通用时间(t_i)的频谱拟合为时间0(在第一列),时间5(在第30列)和时间35(在第210列)中频谱的线性组合。所以我想拟合的方程是:
其中:
0 <= a,b,c <= 1
a + b + c = 1
我发现这个问题的解决方案(Minimizing Least Squares with Algebraic Constraints and Bounds)非常有用。但是当我用我的数据集尝试时,结果显然是错误的。我尝试将方法修改为“ Nelder-Mead”,但它不遵守我的约束,因此得到负值。
这是我的脚本:
t0= df.iloc[:,0] #Spectrum at time 0
t5 = df.iloc[:,30] # Spectrum at time 5
t35 = df.iloc[:,120] # Spectrum at time 35
ti= df.iloc[:,20]
# Bounds that make every coefficient be between 0 and 1
bnds = [(0, 1), (0, 1), (0, 1)]
# Constrain the sum of the coefficient to 1
cons = [{"type": "eq", "fun": lambda x: x[0] + x[1] + x[2] - 1}]
xinit = np.array([1, 0, 0])
fun = lambda x: np.sum((ti -(x[0] * t0 + x[1] * t5 + x[2] * t35))**2)
res = minimize(fun, xinit,method='Nelder-Mead', bounds=bnds, constraints=cons)
print(res.x)
[如果使用Nelder-Mead方法,则会得到:Out: [ 0.02732053 1.01961422 -0.04504698]
,如果未指定方法,则会得到:[1. 0. 0.]
(我相信在这种情况下,将使用SLSQP方法)。
我所指的数据类似于以下内容:
0 3.333 5 35.001
0.001045089 0.001109701 0.001169798 0.000725486
0.001083051 0.001138815 0.001176665 0.000713021
0.001090994 0.001142676 0.001186642 0.000716149
0.001096258 0.001156476 0.001190218 0.00071286
您能找出问题所在吗?您可以提出其他解决此问题的方法吗?我也尝试使用least_squares
,但失败。
局部优化的结果很强ly取决于初始值。
对于您在上述情况下,它可能返回[1, 0, 0]
,因为优化器根本不可能找到[0. 1. 0.]
的“仅下坡”方式。实际上,您可能曾经在当地的最低要求中走出低谷。因此,优化器选择保留。
但是这些优化器就是这样工作的。尝试
xinit = np.array([1, 0, 0])
对于t_i = t5
,我很确定优化器将返回初始值。
对于您的情况,请执行我所说的here:多次运行优化器,每次选择您边界内的随机初始值。您可以选择此处发布的代码,然后添加约束,使用SLSQP或trust-constr。