Curve_fit返回 numpy 数组的函数



我知道scipy的库curve_fit及其拟合曲线的能力。我在这里和文档中阅读了许多示例,但我无法解决我的问题。 例如,我有 10 个文件(化学结构,但没关系)和 10 个实验能量值。我在一个类中有一个函数,它为每个结构计算某些参数的理论能量,并返回一个包含理论能量值的 numpy 数组。

我想找到最佳参数,使理论值最接近实验值。我将在这里提供我的代码的最小示例

这是一个类函数,用于读取实验能量文件,提取正确的子字符串并将值作为 numpy 数组返回。self.path只是目录和self.nPoints = 10。这不是那么重要,但为了完整起见,我提供

def experimentalValues(self):
os.chdir(self.path)
energy = np.zeros(self.nPoints)
for i in range(1, self.nPoints):
f = open("p_" + str(i + 1) + ".xyz", "r")
energy[i] = float(f.readlines()[1].split()[1])
f.close()
os.chdir('..')
return energy

我用这个类函数计算理论值,该函数将两个 numpy 数组作为参数,比如说

sigma = np.full(nSubstrate, 2.)
epsilon = np.full(nSubstrate, 0.15)

哪里nSubstrate = 9

这里有类函数。它读取文件并执行两个嵌套循环,为每个文件计算理论值并将其返回到 numpy 数组。

def theoreticalEnergy(self, epsilon, sigma):
os.chdir(self.path)
cE = np.zeros(self.nPoints)
for n in range(0, self.nPoints):
filenameXYZ = "p_" + str(n + 1) + "_extended.xyz"
allCoordinates = np.loadtxt(filenameXYZ, skiprows = 0, usecols = (1, 2, 3))
substrate = allCoordinates[0:self.nSubstrate]
surface = allCoordinates[self.nSubstrate:]
for i in range(0, substrate.shape[0]):
positionAtomI = np.array(substrate[i][:])
for j in range(0, surface.shape[0]):
positionAtomJ = np.array(surface[j][:])
distanceIJ = self.distance(positionAtomI, positionAtomJ)
cE[n] += self.LennardJones(distanceIJ, epsilon[i], sigma[i])

os.chdir('..')
return cE

同样,为了完整起见,伦纳德·琼斯类函数被定义为

def LennardJones(self, distance, epsilon, sigma):
repulsive = (sigma/distance) ** 12.
attractive = (sigma/distance) ** 6.
potential = 4. * epsilon* (repulsive - attractive)
return potential

在这种情况下,所有参数都是标量作为返回值。 为了结束问题演示,我有 3 个要素:

  • 包含实验数据的 numpy 数组
  • 两个 Numpy 数组,用于猜测参数 Sigma 和 epsilon
  • 一个函数,它采用最后一个参数并返回包含要拟合的值的 Numpy 向量。

如何像文档 https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.curve_fit.html 中描述的方法一样解决此问题?

曲线拟合

该curve_fit通过查找最小化sum((f(w, x[i] - y[i])**2 for i in range(n))w来拟合f(w, x[i])y[i]的函数。正如您将在函数定义后的第一行中读到的那样

[它使用]非线性最小二乘法将函数 f 拟合到数据。

它指的是它所说的least_squares

给定残差 f(x)(n 个实变量的 m-D 实函数)和损失函数 rho(s)(标量函数),least_squares找到成本函数 F(x) 的局部最小值

曲线拟合是一种凸成本多目标优化。由于每个单独的成本都是凸的,因此您可以将所有这些成本相加,这仍然是一个凸函数。请注意,决策变量(要优化的参数)在每个点上都是相同的。

您的问题

根据我的理解,对于每个能级,您都有一组不同的参数,如果您将其编写为曲线拟合问题,则目标函数可以表示为sum((f(w[i], x[i]) - y[i])**2 ...), wherey[i]is determined by the energy level. Since each of the terms in the sum is independent on the other terms, this is equivalent to finding each group of parametersw[i]separately minimizing(f(w[i], x[i]) - y[i])**2'。

凸性

凸性是一个非常方便的优化属性,因为它确保参数空间中只有一个最小值。我不是在做详细的分析,但对你的能量函数的凸性有合理的怀疑。

  1. 伦纳德·琼斯函数具有排斥力和吸引力的区别,两者在距离上都是负的甚至指数,仅此一项就不太可能是凸的。

  2. 以不同位置为中心的多个局部函数的总和没有定义的凸性。

  3. 众所周知,分子能量、晶体能量或蛋白质折叠是非凸的。

几天前(骑自行车)我在想这个问题,分子将如何以全球最小能量进行配置,我想知道它是否因为量子隧穿效应而如此迅速地找到这种配置。

非凸优化

非凸(全局)优化不同于(非线性)最小二乘优化,从某种意义上说,当找到局部最小值时,该过程不会立即返回,它开始在搜索空间的不同区域进行新的尝试。如果函数是平滑的,您仍然可以利用基于梯度的局部优化方法,但复杂度仍然是NP。

一个经典的全局优化方法是模拟退火,如果你有化学背景,我想你会有一些见解阅读它。曾几何时,scipy.optimize提供了模拟退火。

您可以在scipy.optimize中找到一些全局优化方法。我鼓励您尝试盆地跳跃,因为它已成功应用于类似的问题,您可以在参考文献中阅读。

我希望这能让您找到正确的解决方案。但是,请注意,您可能需要花钱,学习如何使用该功能,并需要做出一些决定。您需要在准确性、简单性和效率之间找到平衡。

如果你想要更好的解决方案,请花时间推导出成本函数的梯度(你可以返回两个值f和df,其中df是f相对于决策变量的梯度)。

最新更新