scipy curve_fit系数与期望值不一致(与物理相关吗?) [英] scipy curve_fit coefficient does not align with expected value (physics relevant?)

查看:46
本文介绍了scipy curve_fit系数与期望值不一致(与物理相关吗?)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在处理论文的实验数据,并且遇到了scipy curve_fit问题.

背景

这是对LED发射的研究,其模型如下,描绘了特定LED组成/波长的吸收光谱.

模型是这样的:

基本思想是,我们获得了实验数据,我们希望对该方程进行拟合,以使我们能够最好地猜测出数据是由实验所用设备导致的垂直位移.为了获得垂直偏移,在 curve_fit 中使用的函数将采用 a + c * E * np.sqrt(E-bandE)* np.exp(-E * b).bandE/Eg是指将在代码部分中提供的材料的带隙能量.E是指光子能量.

我做了什么

我在熊猫数据框中使用的值作为列表保存,供您复制和粘贴(如果需要),

<预> <代码> photon_energy = [1.1271378805005456,1.1169834851807208,1.1070104183487501,1.0972138659739825,1.0875891829391229,1.0781318856961741,1.0688376453022415,1.0597022808124787,1.0507217530089832,1.0418921584458825,1.0332097237921667,1.0246708004550413,1.016271859467705,1.0080094866265041,0.9998803778633872,0.9918813348404801,0.9840092607544446,0.9762611563390552,0.9686341160551564,0.9611253244578295,0.9537320527312309,0.9464516553821375,0.939281567083788,0.9322192996621053,0.9252624392168658,0.918408643370815,0.9116556386401471,0.9050012179201461,0.898443238080145,0.8919796176623023,0.885608334679,0.8793274245039717,0.8731349778525352,0.8670291388135327180 0.8827,6370.63756372 0.8637 3756.7637S2C = 1.0711371944297785,1.0231329828975677,1.0994106908895496,1.5121380434280387,1.4362625879245816,1.6793735384201034,1.967376254925342,2.718958670464331,2.8657461347457933,3.2265806746948247,4.073118384895329,5.002080377098846,5.518310980392261,6.779117609004787,7.923629188601875,9.543272102194026,11.061716095291905,12.837722885549315,15.156654004011116,17.604461138085984,20.853321055852934,24.79640344112394,28.59835938028905,32.5257456,37.87676923906976,42.15321400245093,46.794297771521705,56.44267690099888,61.60473904566305,70.99822229568558,77.60736232076566,84.37513036736146,92.9038746946938,107.54475674330527,117.91910226690293,137.674816550298688816

适合

  bandE = 0.7435616030790153def exp_fit(E,a,b,c):#返回a + c * E * np.sqrt(E-bandE)* np.exp(-E/0.046)#Eg和k先前已定义返回a + c * E * np.sqrt(E-bandE)* np.exp(-E * b)E = np.linspace(np.min(new_df ['Photon Energy']),np.max(new_df ['Photon Energy']),1000)popt,pcov = curve_fit(exp_fit,new_df ['Photon Energy'],new_df ['S2c'],maxfev = 10000,p0 = [0,500/23,1e + 9])#最佳猜测a,b和c值plt.plot(new_df ['Photon Energy'],new_df ['S2c'],'o',label ='S2c')plt.plot(new_df ['Photon Energy'],exp_fit(new_df ['Photon Energy'],* popt),'-',label ='S2c fit')plt.ylabel('排放强度(a.u.)')plt.xlabel('光子能量(eV)')plt.yscale('log')plt.legend()plt.show() 

这就是我们最终得到的.

  out:[1.59739310e + 00 2.50268369e + 01 9.55186101e + 11] 

因此,在与我的工作人员进行了长时间的讨论之后(我们对python或数据科学的了解并不多),我们同意除 a 系数以外的所有内容都非常合适(b并不重要,因为它将在以后的步骤中进行显式计算.C非常重要,并且似乎是正确的数量级).因为这是垂直移动,所以我们希望 a 是一个常数,但由于此,曲线会发散.

问题

如问题标题和上一段落所述,我们期望 a 大约为 5e-4 或在该范围内,但我们得到的是对于这个实验来说太大了.如果有人精通scipy的curve_fit功能,请帮助我们!

其他信息,我们以前使用的是称为OriginLab的东西(一种更昂贵的Microsoft Excel),但是对于许可证而言却是非常昂贵的,因此我们尝试使用python.此方法在OriginLab上有效,并且不会导致拟合差异,因此我们认为它可能与curve_fit使用的算法有关.

解决方案

显然,该问题是由于不合适的拟合标准造成的.

LMSE(最小均方误差)可能已在您的软件中实现.如果数据持续数十年,这不是合适的选择标准.

对于您的数据,建议使用LMSRE(最小均方相对误差).

请参阅下面的结果比较.

注意:与从1到240的数据范围相比,大约a = 0.0005的期望值是荒谬的.这将无效,就像a = 0一样.可能是天平或单位的混乱?

I am currently processing experimental data for my thesis and am running into a problem with scipy curve_fit.

Background

This is a study of LED emission with the following model depicting the absorption spectra for a specific LED composition/wavelength.

The model is this:

The basic idea is, we got experimental data and we want to fit this equation to give us a best guess of a vertical shift in the data that is a result of the equipment used in the experiment. And to get that vertical shift, the function to be used in the curve_fit would take the form of a + c * E * np.sqrt(E-bandE) * np.exp(-E*b). bandE/Eg refers to the bandgap energy of the material which will be provided in the code section. E refers to the photon energy.

What I did

The values I am using in a pandas dataframe that I kept as a list for you to copy and paste (if you want it),

photon_energy = [1.1271378805005456, 1.1169834851807208, 1.1070104183487501, 1.0972138659739825, 1.0875891829391229, 1.0781318856961741, 1.0688376453022415, 1.0597022808124787, 1.0507217530089832, 1.0418921584458825, 1.0332097237921667, 1.0246708004550413, 1.016271859467705, 1.0080094866265041, 0.9998803778633872, 0.9918813348404801, 0.9840092607544446, 0.9762611563390552, 0.9686341160551564, 0.9611253244578295, 0.9537320527312309, 0.9464516553821375, 0.939281567083788, 0.9322192996621053, 0.9252624392168658, 0.918408643370815, 0.9116556386401471, 0.9050012179201461, 0.898443238080145, 0.8919796176623023, 0.885608334679, 0.8793274245039717, 0.8731349778525352, 0.8670291388465735, 0.8610081031601389, 0.8550701162417932, 0.8492134716100002, 0.8434365092180953, 0.8377376138855407, 0.8321152137923491, 0.8265677790337335]
s2c = 1.0711371944297785, 1.0231329828975677, 1.0994106908895496, 1.5121380434280387, 1.4362625879245816, 1.6793735384201034, 1.967376254925342, 2.718958670464331, 2.8657461347457933, 3.2265806746948247, 4.073118384895329, 5.002080377098846, 5.518310980392261, 6.779117609004787, 7.923629188601875, 9.543272102194026, 11.061716095291905, 12.837722885549315, 15.156654004011116, 17.604461138085984, 20.853321055852934, 24.79640344112394, 28.59835938028905, 32.5257456, 37.87676923906976, 42.15321400245093, 46.794297771521705, 56.44267690099888, 61.60473904566305, 70.99822229568558, 77.60736232076566, 84.37513036736146, 92.9038746946938, 107.54475674330527, 117.91910226690293, 137.67481655050688, 158.02001455302846, 176.37334256204952, 195.20886164268876, 215.87011902349641, 240.41535423461914]

The fit

bandE = 0.7435616030790153
def exp_fit(E, a, b, c): 
    # return  a + c * E * np.sqrt(E - bandE) * np.exp(-E/0.046)# Eg and k are already defined previously 
    return a + c  * E * np.sqrt(E-bandE) * np.exp(-E*b)

E = np.linspace(np.min(new_df['Photon Energy']), np.max(new_df['Photon Energy']),1000)

popt, pcov = curve_fit(exp_fit, new_df['Photon Energy'], new_df['S2c'],maxfev = 10000, p0=[0,500/23,1e+9]) # best guess of a,b, and c value
plt.plot(new_df['Photon Energy'], new_df['S2c'], 'o', label='S2c')
plt.plot(new_df['Photon Energy'], exp_fit(new_df['Photon Energy'], *popt), '-', label='S2c fit')
plt.ylabel('Emission Intensity (a.u.)')
plt.xlabel('Photon Energy (eV)')
plt.yscale('log')
plt.legend()
plt.show()

And this is what we end up getting.

out: [1.59739310e+00 2.50268369e+01 9.55186101e+11]

So after a long discussion with the person I am working with (we aren't that knowledgeable about python or data science), we agree that everything except for the a coefficient fits really well (b doesnt really matter because it will be explicitly calculated at a later step. C matters alot and it appears to be of the right order of magnitude). Because it is a vertical shift, we expect a to be a constant but the curve is diverging as a result of it.

The problem

As mentioned in the question title and the previous para, we are expecting a to be about 5e-4 or within that range of magnitude but we are getting something that is way too large for this experiment. If anyone is proficient with the curve_fit feature of scipy, do help us out!

Additional info, we used to use something called OriginLab (a more expensive microsoft excel), but it is hella expensive for the license, so we are trying to use python instead. This method does work on OriginLab and does not result in a divergence in the fit, so we figured it might have something to do with the algorithm that curve_fit uses.

解决方案

Apparently the trouble is due to a non convenient criteria of fitting.

LMSE (Least Mean Square Error) in probably implemented in your software. This is not a good choice of criteria of fitting in case of data extended on several decades.

LMSRE (Least Mean Square Relative Error) is recommended in the case of your data.

See below the comparison of results.

NOTE: The expected value of about a=0.0005 is absurd compared to the range of the data from 1. to 240. This would be with no effect, just like a=0. May be a muddle in scales or units ?

这篇关于scipy curve_fit系数与期望值不一致(与物理相关吗?)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆