即使猜测非常接近,Scipy.optimise.curvefit也不会收敛于测量数据

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

我有大量的二极管测量数据集,我正在尝试提取理论参数以进行进一步建模。我之前已经通过更简单的函数成功使用了 scipy curvefit,但目前它没有返回任何接近测量数据的内容。

这是我正在运行的代码:

import numpy as np
from scipy.special import lambertw as W
import scipy.optimize
import matplotlib
matplotlib.use('TkAgg')
import matplotlib.pyplot as plt

def shockley(Is, v_arr, Rs, n, Vt):
    i_fit = ((n*Vt)/Rs)*W(((Is*Rs)/(n*Vt))*(np.exp(v_arr/(n*Vt))))
    i_fit = i_fit.real
    return i_fit

v_arr = np.array((0,0.01,0.02,0.03,0.04,0.05,0.06,0.07,0.08,0.09,0.1,0.11,0.12,0.13,0.14,0.15,0.16,0.17,0.18,0.19,0.2,
                  0.21,0.22,0.23,0.24,0.25,0.26,0.27,0.28,0.29,0.3,0.31,0.32,0.33,0.34,0.35,0.36,0.37,0.38,0.39,0.4,
                  0.41,0.42,0.43,0.44,0.45,0.46,0.47,0.48,0.49,0.5,0.51,0.52,0.53,0.54,0.55,0.56,0.57,0.58,0.59,0.6,
                  0.61,0.62,0.63,0.64,0.65,0.66,0.67,0.68,0.69,0.7,0.71,0.72,0.73,0.74,0.75,0.76,0.77,0.78,0.79,0.8,
                  0.81,0.82,0.83,0.84,0.85,0.86,0.87,0.88,0.89,0.9,0.91,0.92,0.93,0.94,0.95,0.96,0.97,0.98,0.99,1,1.01,
                  1.02,1.03,1.04,1.05,1.06,1.07,1.08,1.09,1.1,1.11,1.12,1.13,1.14,1.15,1.16,1.17,1.18,1.19,1.2,1.21,
                  1.22,1.23,1.24,1.25,1.26,1.27,1.28,1.29,1.3,1.31,1.32,1.33,1.34,1.35,1.36,1.37,1.38,1.39,1.4,1.41,
                  1.42,1.43,1.44,1.45,1.46,1.47,1.48,1.49,1.5,1.51,1.52,1.53,1.54,1.55,1.56,1.57,1.58,1.59))

i_arr = np.array((-3.76E-11,5.83E-11,-1.05E-10,1.25E-10,-2.45E-11,-1.75E-11,-1.26E-11,-1.01E-11,-9.41E-12,-1.04E-11,
                  -9.47E-12,-9.03E-12,-1.03E-11,-9.54E-12,-7.91E-12,-9.89E-12,-1.65E-11,1.59E-10,-5.90E-11,-1.17E-11,
                  -1.09E-11,-7.61E-12,-2.86E-12,-8.39E-12,-7.87E-12,-7.91E-12,-6.43E-12,-6.87E-12,1.48E-12,-7.25E-12,
                  -6.58E-12,-5.73E-12,-5.39E-12,-3.99E-12,-2.34E-12,-1.08E-12,2.06E-12,3.01E-12,8.24E-12,1.36E-11,
                  2.26E-11,2.99E-11,4.11E-11,6.32E-11,8.54E-11,1.16E-10,1.53E-10,2.09E-10,2.73E-10,3.65E-10,4.93E-10,
                  6.32E-10,8.46E-10,1.09E-09,1.42E-09,1.85E-09,2.41E-09,3.09E-09,3.98E-09,5.16E-09,6.61E-09,8.36E-09,
                  1.10E-08,1.43E-08,1.84E-08,2.39E-08,3.11E-08,4.05E-08,5.41E-08,6.95E-08,9.13E-08,1.19E-07,1.57E-07,
                  2.08E-07,2.79E-07,3.71E-07,4.94E-07,6.57E-07,8.83E-07,1.19E-06,1.61E-06,2.19E-06,3.00E-06,4.12E-06,
                  5.72E-06,7.91E-06,1.10E-05,1.54E-05,2.16E-05,3.03E-05,4.23E-05,5.87E-05,8.09E-05,0.000110276,
                  0.000148352,0.00019647,0.000256439,0.000329539,0.000416616,0.000519519,0.000638944,0.000775399,
                  0.000930671,0.001105803,0.001299725,0.001514556,0.001750505,0.002006911,0.00228582,0.002586988,
                  0.002909377,0.003255466,0.003622608,0.004013351,0.004426898,0.004860486,0.005317697,0.005796602,
                  0.006294098,0.006813415,0.007352292,0.007908308,0.008483431,0.009075115,0.009680456,0.01030162,
                  0.01094043,0.01158479,0.01224334,0.01290703,0.01358056,0.01426283,0.01494866,0.01564087,0.01633509,
                  0.01703126,0.01773028,0.01843017,0.01912786,0.01982758,0.0205251,0.02121851,0.02191115,0.0226002,
                  0.02328385,0.02396644,0.02464198,0.02531404,0.02598236,0.02664429,0.02730172,0.02795239,0.02859697,
                  0.02923778,0.02987059,0.02999878,0.02999881,0.02999872,0.02999867,0.02999871))

guessIs = 3e-9
guessRs = 11
guessn = 1.7
guessVt = 0.044

guess_fit = shockley(guessIs, v_arr, guessRs, guessn,guessVt)

plt.plot(v_arr, guess_fit)
plt.plot(v_arr, i_arr)

guess = np.array([guessIs, guessRs, guessn, guessVt])

popt, pcov = scipy.optimize.curve_fit(shockley, v_arr, i_arr, p0=guess, bounds=((2e-9, 0, 1, 0),(1, 20, 2, 1)),method = 'tlm')
Is, Rs, n, Vt = popt
print(f'Is={Is}, Rs={Rs}, n={n}, Vt={Vt}')

test = shockley(Is, v_arr, Rs, n, Vt)

fit = shockley(Is, v_arr, Rs, n , Vt)
plt.plot(v_arr, fit)
plt.show()

这些图显示最初的猜测非常接近,但拟合总是发散。我添加了一些有帮助的界限,但我不知道我的结果会有什么变化,所以我不能让它们太紧。

我尝试将“方法”更改为“dogbox”和“lm”(按照此示例)。 “dogbox”最接近,但似乎只是遵循猜测。

如有任何帮助,我们将不胜感激

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

根据文档

scipy.optimize.curve_fit
期望函数签名为
f(x, a, b, c, d)
,但您已将其定义为
f(a, x, b, c, d)
。更正顺序(并修复使用它的其他位置),它将按预期工作。

import numpy as np
from scipy.special import lambertw as W
import scipy.optimize
import matplotlib.pyplot as plt

def shockley(v_arr, Is, Rs, n, Vt):
    i_fit = ((n*Vt)/Rs)*W(((Is*Rs)/(n*Vt))*(np.exp(v_arr/(n*Vt))))
    i_fit = i_fit.real
    return i_fit

guessIs = 3e-9
guessRs = 11
guessn = 1.7
guessVt = 0.044

guess_fit = shockley(v_arr, guessIs, guessRs, guessn,guessVt)

plt.plot(v_arr, i_arr, label="Data")
plt.plot(v_arr, guess_fit, label="Guess")

guess = np.array([guessIs, guessRs, guessn, guessVt])

popt, pcov = scipy.optimize.curve_fit(shockley, v_arr, i_arr, 
                                      p0=guess, 
                                      bounds=((2e-9, 0, 1, 0), (1, 20, 2, 1)))
Is, Rs, n, Vt = popt
print(f'Is={Is}, Rs={Rs}, n={n}, Vt={Vt}')

test = shockley(v_arr, Is, Rs, n, Vt)

fit = shockley(v_arr, Is, Rs, n , Vt)
plt.plot(v_arr, fit, label="Fit")
plt.legend()
plt.show()

打印输出:

Is=2.904220083107052e-09, Rs=10.900911685026195, n=1.700117900138838, Vt=0.04438584374368413

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