Scipy Optimize无法在具有强起始参数的情况下进行优化。

huangapple go评论82阅读模式
英文:

Scipy Optimize unable to optimize even with strong starting parameters

问题

I have a fairly simple function that I would like to optimize the parameters for but I cannot get scipy.optimize.minimize to succeed.

Here's a simplified version of the data and the problem:

  1. ref = np.array([0.586, 0.659, 0.73 , 0.799, 0.865, 0.929, 0.991, 1.05 , 1.107, 1.162])
  2. input = np.array([70.0, 77.0, 82.0, 87.0, 93.0, 98.0, 98.0, 102.0, 106.0, 109.0])
  3. x = np.array([6.96, 9.24, 10.92, 12.24, 13.92, 15.24, 15.24, 16.32, 17.64, 18.96])
  4. ## Function
  5. def fun(beta, x):
  6. return ((input**beta[0])*beta[2])*(x**beta[1])
  7. ## Starting parameters
  8. initial_guess = [0.15, 0.9475, 0.0427]
  9. ## Objective to be minimized
  10. def objective(beta, model, x, ref):
  11. return sum(((np.log(model(beta, x))-np.log(ref)))**2)
  12. minimize(objective, initial_guess, args = (fun, x, ref))

I know that these starting parameters are almost correct as print(fun(initial_guess, x)) returns estimates close to the reference data (and they're much closer in my real situation than in this minimal reproducible example).

I've tried many combinations of starting parameters and cannot find any that lead to successful optimization.

I've tried making the function more basic (e.g., removing the additional beta terms and x, leaving only beta[0]). This successfully optimizes (success: True) however the predictions are inadequate (presumably because the function is not complex enough to convert the input a desirable output with respect to the reference).

I've minimized functions apparently more complex than this in recent times (and used the same approach in this instance as in previous ones), so I am confused as to why this one is not working.

英文:

I have a fairly simple function that I would like to optimize the parameters for but I cannot get scipy.optimize.minimize to succeed.

Here's a simplified version of the data and the problem:

  1. ref = np.array([0.586, 0.659, 0.73 , 0.799, 0.865, 0.929, 0.991, 1.05 , 1.107, 1.162])
  2. input = np.array([70.0, 77.0, 82.0, 87.0, 93.0, 98.0, 98.0, 102.0, 106.0, 109.0])
  3. x = np.array([6.96, 9.24, 10.92, 12.24, 13.92, 15.24, 15.24, 16.32, 17.64, 18.96])
  4. ## Function
  5. def fun(beta, x):
  6. return ((input**beta[0])*beta[2])*(x**beta[1])
  7. ## Starting parameters
  8. initial_guess = [0.15, 0.9475, 0.0427]
  9. ## Objective to be minimized
  10. def objective(beta, model, x, ref):
  11. return sum(((np.log(model(beta, x))-np.log(ref)))**2)
  12. minimize(objective, initial_guess, args = (fun, x, ref))

I know that these starting parameters are almost correct as print(fun(initial_guess, x)) returns estimates close to the reference data (and they're much closer in my real situation than in this minimal reproducible example).

I've tried many combinations of starting parameters and cannot find any that lead to successful optimization.

I've tried making the function more basic (e.g., removing the additional beta terms and x, leaving only beta[0]). This successfully optimizes (success: True) however the predictions are inadequate (presumably because the function is not complex enough to convert the input a desirable output with respect to the reference).

I've minimized functions apparently more complex than this in recent times (and used the same approach in this instance as in previous ones), so I am confused as to why this one is not working.

答案1

得分: 1

minimize不是正确的函数调用。使用curve_fit,即使没有您的对数步骤,它也能正常工作。此外,始终为minimize(或curve_fit)提供合理的边界;如果您过去“使用相同方法”并且没有边界也能正常工作,那只是巧合。

在某种意义上,这实际上是对三个维度的曲面拟合,如果按这种方式解释,它没有足够的输入数据。我会期望在xinput中有多个非单调跃迁的情况。以下是应该是什么样子的(具有不同的ix值):

  1. import numpy as np
  2. from matplotlib import pyplot as plt
  3. from scipy.optimize import curve_fit
  4. def fun(ix: np.ndarray, b0: float, b1: float, b2: float) -> np.ndarray:
  5. input_, x = ix
  6. return input_**b0 * b2 * x**b1
  7. ref = np.array([0.586, 0.659, 0.73, 0.799, 0.865, 0.929, 0.991, 1.05, 1.107, 1.162])
  8. ix = np.array((
  9. [70.0, 77.0, 82.0, 87.0, 93.0, 98.0, 98.0, 102.0, 106.0, 109.0],
  10. [6.96, 9.24, 10.92, 12.24, 13.92, 15.24, 15.24, 16.32, 17.64, 18.96],
  11. ))
  12. initial_guess = (2, -0.5, 4e-4)
  13. fit_param, _ = curve_fit(
  14. f=fun, xdata=ix, ydata=ref, p0=initial_guess,
  15. bounds=((-1,-1,0), (10, 10, 10)),
  16. )
  17. print(fit_param)
  18. fig, ax = plt.subplots()
  19. ax.plot(ix[0], ref, label='experiment')
  20. ax.plot(ix[0], fun(ix, *initial_guess), label='guess')
  21. ax.plot(ix[0], fun(ix, *fit_param), label='fit')
  22. ax.legend()
  23. plt.show()

Scipy Optimize无法在具有强起始参数的情况下进行优化。

  1. [![猜测和拟合][1]][1]
  2. <details>
  3. <summary>英文:</summary>
  4. `minimize` is not the right function call. Use `curve_fit`, and it works fine even without your log step. Further, always give `minimize` (or `curve_fit`) sane bounds; if you&#39;ve &quot;used the same approach&quot; and it worked without bounds in the past that&#39;s only by coincidence.
  5. In one sense this is really a surface fit over three dimensions, and interpreted as such it doesn&#39;t have enough input data. I would expect multiple non-monotonic jumps in one of `x` or `input` for such a scheme. What this _should_ look like (with different values in `ix`):
  6. ```python
  7. import numpy as np
  8. from matplotlib import pyplot as plt
  9. from scipy.optimize import curve_fit
  10. def fun(ix: np.ndarray, b0: float, b1: float, b2: float) -&gt; np.ndarray:
  11. input_, x = ix
  12. return input_**b0 * b2 * x**b1
  13. ref = np.array([0.586, 0.659, 0.73, 0.799, 0.865, 0.929, 0.991, 1.05, 1.107, 1.162])
  14. ix = np.array((
  15. [70.0, 77.0, 82.0, 87.0, 93.0, 98.0, 98.0, 102.0, 106.0, 109.0],
  16. [6.96, 9.24, 10.92, 12.24, 13.92, 15.24, 15.24, 16.32, 17.64, 18.96],
  17. ))
  18. initial_guess = (2, -0.5, 4e-4)
  19. fit_param, _ = curve_fit(
  20. f=fun, xdata=ix, ydata=ref, p0=initial_guess,
  21. bounds=((-1,-1,0), (10, 10, 10)),
  22. )
  23. print(fit_param)
  24. fig, ax = plt.subplots()
  25. ax.plot(ix[0], ref, label=&#39;experiment&#39;)
  26. ax.plot(ix[0], fun(ix, *initial_guess), label=&#39;guess&#39;)
  27. ax.plot(ix[0], fun(ix, *fit_param), label=&#39;fit&#39;)
  28. ax.legend()
  29. plt.show()

Scipy Optimize无法在具有强起始参数的情况下进行优化。

huangapple
  • 本文由 发表于 2023年5月7日 17:28:51
  • 转载请务必保留本文链接:https://go.coder-hub.com/76193092.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定