来自数据集的 curve_fit 普朗克定律的归一化值 *编辑*

Normalizing values in a curve_fit of Plancks Law from data set *Edit*

我有大量关于强度计数和波长的数据,我希望它们符合普朗克定律以确定温度的猜测参数。

数据集导入为文本文件

import numpy as np
import scipy as sp
from scipy.optimize import curve_fit

with open('Good_SolarRun2.txt') as g:
    data = g.read()
data = data.split('\n')
Wavle2 = [float(row.split()[0]) for row in data]   # Wavelength (nm)
Int2 = [float(row.split()[1]) for row in data]  # Intensity (counts)

所以我现在定义普朗克定律的拟合模型(根据波长) https://en.wikipedia.org/wiki/Planck%27s_law

--- 根据用户 Evert 的建议,我将常量设置为 1,因为在计算机上优化小数字很困难。

from scipy.constants import h,k,c

def Plancks_Law(lamb, T):
    return 1/np.power(lamb,5.0) * 1/( np.exp( 1/(lamb*T)) - 1 )

现在,我开始使用我的数据集设置 curve_fit 配置。

x = Wavle2

# This has the same shape as Wavle2, but these values are scaled by me.
# Also the same shape as Int2
y = np.array(Intscale2P)

p0_R = (500.) 
optR, pcovR = curve_fit(Plancks_Law, x, y, p0_R)
T_R = optR
T_Rp = pcovR
yM = Plancks_Law(x, T_R)

print T_Rreturns的值542.04628177

这是一些未知的单位。我现在对如何将所有内容转换为正确的单位感到困惑。尤其是正确单位的指数中的值。

有什么办法可以纠正这个问题吗?

这里你有一个稍微挑剔的问题:根据你的 x 值(波长),指数 1/(lamb*T) 通常可能太大而无法计算,你会得到溢出。 (或者太小,结果总是零。

尝试将普朗克函数分成三部分可能会更好:

  • lamb * T 较大的部分,例如 > 100。然后您可以使用 Rayleigh-Jeans 近似。
  • lamb * T 较小的部分,比如 < 1e-4。然后,您可以使用 Wien 近似。
  • 对于中间部分,使用函数本身。

这应该可以防止溢出。


为了获得良好的拟合结果,最好不要让参数和数据结果 运行 进入机器限制,无论是太大还是太小。由于拟合通常会导致远远超出输入(参数或数据)范围的中间结果,因此最安全的是一切都是统一的(这只是 "(hu)man(s) being the measure of all things" 的结果,计算机是由人类制造并为人类制造的).

从原来的普朗克函数开始:

alpha = 2*h*c*c
beta = h*c/k
return alpha/np.power(lamb,5.0) * 1/( np.exp( beta/(lamb*T)) - 1 )

请注意,alpha 只是一种标准化。将它留在此处,并在最后将其应用到您的合身结果中。在拟合过程中,你不会有任何大或小的 alpha 值,只有 1。那个很简单。

对于测试版,你不能真正做到这一点:你不能在指数之外调整它,并在事后应用它。上面的三部分功能就是为了这个,规避那里的问题。

不过,您也可以(并且可能应该)标准化您的 x 值。假设您的输入是 1e-9 阶,因此纳米以米表示。以纳米为单位,并将所有值乘以 1e9。现在 x 输入值是统一的。

当然,这意味着您的 alpha 会发生变化;那里有一个 lambd**-5 因素,所以如果 lambd 上升 1e9,那么这里的情况会改变 1/1e-(9*5) = 1e45。将 1e45 分解为 alpha。

对于测试版,有类似的东西:你将 beta 乘以 1e9。

最后,您还可以尝试 "normalize" T。 5000 与订单统一相差不远,但您可以将其转换为 5,并将因子 1000 放入 beta.
另外,将 alphabeta 放在函数之外 :它们本质上是常量,不需要在每次调用函数时都计算。这使得拟合更快。

注意:如果您从函数中删除了 alpha,并且仅在拟合后使用它,请不要忘记将其也从 Wien 和 Rayleigh-Jeans 近似值中取出。如下所述:测试(例如,手动比较从一种配方到另一种配方的区域周围的结果,并查看它是否匹配。或者简单地在对数对数图上绘制大范围的曲线)!


免责声明:我还没有测试过这个,可能有错误的迹象。三次检查您是否需要 1e45 而不是 1e-45,对于 1e9 或 1e-9 也是如此。简单检查:输入一些以米为单位的波长的适当数字,看看你得到的通量,然后输入以纳米为单位的波长和其他因素,看看你是否得到相同的通量。

另外:拿一张纸,一步一步地做出改变。在这里这样做,您也可以将相同的方法应用于其他函数和拟合问题。