Scipy优化好像不能正确适配

问题描述 投票:0回答:1

我有两个数据数组,我需要在它们上拟合非线性曲线。我正在使用

scipy.optimize
,它返回如此奇怪的结果,当我将其绘制在数据点旁边时,曲线看起来完全错误。我在 stackoverflow 或 youtube 上没有找到任何有用的东西,这是我最后的手段。

我正在尝试在我的数据点上拟合形状为

y = Asin^2(Bx^2 + C/2)
的曲线。 我当前的代码如下所示:

import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit

I3 = np.array([12.5, 73.2, 99.5, 96.8, 73.2, 50, 27.1, 10.6, 3.1, 1.31, 0.40, 0.33, 0.41, 0.47, 0.55, 0.56, 0.55, 0.54])
U = np.array([951, 888, 808, 737, 683, 639, 581, 508, 437, 392, 232, 255, 201, 166, 93, 68, 4.5, 3.4])

def fit_func3(x, a, b, c):
    return a * (np.sin(b* x ** 2) + c/2) ** 2

popt, _ = curve_fit(fit_func3, U, I3)
a, b, c = popt

I3_fit = fit_func3(U, a, b, c)


plt.xlabel('Voltage [$\mu$V]')
plt.ylabel('Current [$\mu$A]')
plt.plot(U, I3_fit, color='red', label=f'y = I$_0$ sin$^2$($\pi$BLU$^2$/d$^2$ + C/2)')
plt.scatter(U, I3, color='black', label='podatki')
plt.errorbar(U, I3, xerr=U_err, yerr=I3_err, fmt='o', capsize=5, color='black')
plt.legend(loc='upper left')
plt.savefig('graph3.png')
plt.show()

生成的曲线如下所示:

The graph

我知道正常的

y = sin^2(x^2)
看起来非常接近数据点,但不知何故拟合无法正常工作。我还没有找到任何方法来限制域以使数据正确适合。

我什至尝试人为地添加数据点以提高拟合质量,但这只是让它稍微不那么混乱和狂野(如果这对发布在这里有帮助的话):

I3_fill = []
U_fill = []

for i in range(len(I3) - 1):
    I3_fill.extend(np.linspace(I3[i], I3[i+1], 12)[0:-1])
    U_fill.extend(np.linspace(U[i], U[i+1], 12)[0:-1])

I3_fill.append(I3[-1])
U_fill.append(U[-1])

I3_fill = np.array(I3_fill)
U_fill = np.array(U_fill)

我也尝试将参数减少到只有 2 个,如

y = a * (np.sin(b * x ** 2)) ** 2
所示,但这根本没有帮助。

我尝试了2个在线试衣工具,无论我如何修改它们,它们都返回相同的结果。

我猜 scipy 用于优化的方法在这种情况下不好?

python scipy data-analysis curve-fitting
1个回答
0
投票

我们可能会质疑具有以下通用形式的模型:

通过选择适当的猜测,可以以某种方式强制拟合该模型:

popt, pcov = optimize.curve_fit(model, U, I3, p0=[100., 1e-7, 0.])
#(array([ 1.51118541e+02,  2.59631991e-06, -4.73406696e-01]),
# array([[ 4.74332686e+02, -2.01357369e-08, -1.82194008e+00],
#        [-2.01357369e-08,  5.83657181e-15,  1.68952039e-10],
#        [-1.82194008e+00,  1.68952039e-10,  8.38560358e-03]]))

这会带来更多的健身效果:

但显然并不令人满意。问题不是

curve_fit
,而是你的数据集或模型。

以下模型可以更好地捕获数据的行为:

def model(x, a, b, c):
    return a * (np.sin(b * (x - c) ** 2)) ** 2

但这在小规模来说并不完美

U
:

© www.soinside.com 2019 - 2024. All rights reserved.