我对使用Python来拟合数据还比较陌生,所以请原谅我缺乏编程技巧。然而,我一直无法找到解决我当前曲线拟合尝试所带来的错误的解决方案。我相信这些误差是由于我的模型函数对两个变量中的一个参数(即Kd)的复杂依赖性造成的。我将非常感谢您能深入了解是什么导致了这个问题,以及如何调整我的定义或适合的软件包来避免它。应遵循的最小工作示例:
# Import libraries
import scipy as scipy
from scipy import stats
import numpy as np
from scipy.optimize import curve_fit
np.set_printoptions(precision=4)
ConcSyringeTotal = 9.5 ## total monomer concentration in the syringe [M]tot, in mM
Vinj = 10 ## volume injected in each injection, in uL
Vinit = 1250 ## volume of solvent initially in the sample cell, in uL
Vcell = 1000 ## cell volume, in uL (only the heat change within this volume is measured)
Injections = np.arange(2.00,26.00,1.00)
print Injections
Energy = np.array([136.953, 105.119, 84.414, 69.373, 60.898, 52.813, 46.187, 39.653, 33.894, 29.975, 27.315, 24.200, 21.643, 19.080, 16.158, 13.454, 13.218, 11.568, 10.742, 9.547, 8.693, 7.334, 6.111, 4.741])
print Energy
def DimerDissociation(injection, Kd, DHd): ## a dimer dissociation model for an ITC dilution experiment
## returns the heat flow (y-data, in ucal) per injection (x-data, unitless)
## fit for the dissociation constant (Kd, in mM = mmol/L, umol/mL, nmol/uL)
## and the enthalpy of dissociation (DHd, in ucal/nmol = kcal/mol)
##
## concentration (in mM) of the free monomer in the cell after equilibration of the i-th injection
VolumeAdded = 6+(injection-1)*Vinj ## in uL
VolumeTotal = Vinit + VolumeAdded ## in uL
CellTotal = ConcSyringeTotal*VolumeAdded ## Total in the cell after the i-th injection, in nmol
ConcCellTotal = CellTotal/VolumeTotal ## Total concentration in the cell after the i-th injection, in mM
ConcCellMonomer_roots = np.roots([1, Kd/2, -Kd*ConcCellTotal/2])
ConcCellMonomer_real = ConcCellMonomer_roots.real[abs(ConcCellMonomer_roots.imag)<1e-5]
ConcCellMonomer_positive = ConcCellMonomer_real[ConcCellMonomer_real>0]
ConcCellMonomer = ConcCellMonomer_positive[ConcCellMonomer_positive<ConcCellTotal]
##
## concentration (in mM) of the free monomer in the syringe
ConcSyringeMonomer_roots = np.roots([1, Kd/2, -Kd*ConcSyringeTotal/2])
ConcSyringeMonomer_real = ConcSyringeMonomer_roots.real[abs(ConcSyringeMonomer_roots.imag)<1e-5]
ConcSyringeMonomer_positive = ConcSyringeMonomer_real[ConcSyringeMonomer_real>0]
ConcSyringeMonomer = ConcSyringeMonomer_positive[ConcSyringeMonomer_positive<ConcSyringeTotal]
## nmol of the free monomer injected from the syringe
SyringeMonomerInjected = Vinj*ConcSyringeMonomer[0]
##
## concentration (in mM) of the free monomer in the cell before the i-th injection
VolumeAddedPre = 6+(injection-2)*Vinj
VolumeTotalPre = Vinit + VolumeAddedPre
CellTotalPre = ConcSyringeTotal*VolumeAddedPre
ConcCellTotalPre = CellTotalPre/VolumeTotalPre
ConcCellMonomerPre_roots = np.roots([1, Kd/2, -Kd*ConcCellTotalPre/2])
ConcCellMonomerPre_real = ConcCellMonomerPre_roots.real[abs(ConcCellMonomerPre_roots.imag)<1e-5]
ConcCellMonomerPre_positive = ConcCellMonomerPre_real[ConcCellMonomerPre_real>0]
ConcCellMonomerPre = ConcCellMonomerPre_positive[ConcCellMonomerPre_positive<ConcCellTotalPre]
## nmol of the free monomer in the cell before the i-th injection
CellMonomerPre = VolumeTotalPre*ConcCellMonomerPre[0]
##
## concentration of the free monomer before equilibration of the i-th injection, in mM
ConcCellMonomerBefore = (CellMonomerPre+SyringeMonomerInjected)/VolumeAdded
## concentration of the free monomer after equilibration of the i-th injection, in mM
ConcCellMonomerAfter = ConcCellMonomer[0]
## change in concentration of the free monomer over the equilibration of the i-th injection, in mM
ConcCellMonomerChange = ConcCellMonomerAfter - ConcCellMonomerBefore
##
return Vcell*DHd*ConcCellMonomerChange
DimerDissociation_opt, DimerDissociation_cov = curve_fit(DimerDissociation, Injections, Energy, p0=[0.4,10])
DimerDissociation_stdev = np.sqrt(np.diag(DimerDissociation_cov))
print "optimized parameters:", DimerDissociation_opt
print "covariance matrix:", DimerDissociation_cov
print "standard deviation of fit parameters:", DimerDissociation_stdev
以及相关错误:
^{pr2}$
我无法重现你的错误。我注意到的第一个问题是您使用}。第三个系数,
np.roots
。roots(p)
返回由p
中的系数指定的多项式的根,特别是{-Kd*ConcCellTotal/2
是injections
的函数,它是一个数组。对于np.roots
没有文档化的签名,它允许将数组作为p
的一个成员传递。在你能编辑和澄清吗?在
-拉维
另外,一个演示
curve_fit
如何工作的玩具示例:目标函数以x值数组和一个或多个参数作为参数。
curve_fit
以目标函数为参数,中的x值数组x,而中的y值数组y作为参数。然后为参数a和b构造一些值,并计算x_in上的目标函数,从而得到一个数组y\u out。它计算出y_in和y\u out之间的均方根误差,然后调整a和b的值,直到均方根误差最小化。在问题在于如何选择a和b的初始值(如果没有提供,就像操作一样)以及如何调整它们的细节。这很复杂,但对于我们
scipy.optimize
用户来说,这并不是绝对必要的。在问题是
numpy.curve_fit
将扩展数据作为数组传递给目标函数。这意味着DimerDissociation
中对injection
的所有操作实际上都是数组操作。因此,ConcCellTotal
也是一个数组(通过在代码的第27行插入print type(ConcCellTotal)
来检查这一点)。这意味着对np.roots
的调用看起来像np.roots([scalar, scalar, array])
,这是错误的根源。在当我处理这些事情时,我总是会被扭转,但我认为优化程序的目标函数应该完全矢量化;每次调用它,它都需要返回一个数组,其中每个注入值都有一个能量值。在
我通过显式地使
ConcCellMonomer_roots
成为一个数组修复了上面的错误,还添加了一些关于变量状态的天真报告:我还使用
^{pr2}$np.asarray
对ConcCellMonomerPre_roots
进行了相应的更正。通过这些编辑,我让优化器迭代几次,直到ConcCellMonomer_roots
包含一些虚数。一旦发生这种情况,ConCellMonomer_real
就不再是ConcCellTotal
的同一个形状,因此ConcCellMonomer_positive[ConcCellMonomer_positive<ConcCellTotal]
行抛出一个广播错误。对DimerDissociation
的调用给出以下输出:直到最后一次迭代:
希望这能让你走上正轨,虽然我不是这里的专家,其他人可能会有更好的主意。在
相关问题 更多 >
编程相关推荐