Python中非线性最小二乘曲线拟合的R²值计算

时间:2016-07-18 14:42:48

标签: python scipy

我编写了一个代码,我希望通过给定的力 - 深度关系计算非线性拟合的R²值。

我用于给定x和y数据的代码是:

   ydata=npy.array(N)
   xdata=npy.array(depth)

   #Exponential Law

   def func1 (x,Bo,k):
       return Bo*npy.exp(x*k)
   popt, pcov, infodict, mesg, ier = curve_fit(func1, xdata, ydata,p0=(1.0,0.2),full_output=True)        
   Bo=popt[0]
   k=popt[1]

   SSR1=sum((func1(ydata,Bo,k)-xdata.mean())**2)
   SST1=sum((xdata-func1(ydata,Bo,k))**2)
   rsquared1=SSR1/SST1

对于exponentail法律和:

   #Power Law

   def func2(a,Bp,z):
       return Bp*a**z
   popt2, pcov2=curve_fit(func2,xdata,ydata,p0=(1,0.2),bounds=([-npy.inf,0],npy.inf))

   Bp=popt2[0]
   z=popt2[1]

   residuals2 = func2(ydata,Bp,z)-xdata.mean()
   fres2=sum(residuals2**2)
   ss_tot2=sum((xdata-func2(ydata,Bp,z))**2)
   rsquared2=(fres2/ss_tot2)

电力法。 根据rsquared = SSR / SST,这应该给出0到1之间的值。不幸的是,我得到一些值略大于1的rsquared。

r平方大于1的值的示例是:

XDATA(深度): [0. 2. 4. 6. 8. 10. 12. 14. 16. 18. 20. 22. 24. 26. 28。   30. 36. 38. 40. 42. 44. 46. 48. 50. 52. 54. 56. 58。]

YDATA(组): [0. 0. 0. 0. 0. 0. 4.4 8. 20. 36。    30.8 12.4 5.8 3.2 4. 3.8 54.6 15.6 37.2 39.6    76.8 81.2 111. 142.4 76.8 107.2 151.8 131.4]

我感谢每一次帮助

1 个答案:

答案 0 :(得分:1)

来自Wikipedia

  

在0到1范围之外的R2的值可以出现在用于测量观察值和建模值之间的一致性以及“建模”的位置的情况下。值不是通过线性回归得到的,而是取决于使用R2的配方。

我认为在您的情况下,您可能只是xy错误的方式...基于this回答您的数据,我知道,

import numpy as npy
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit

#Exponential Law
def func1(x,Bo,k):
   return Bo*npy.exp(x*k)

#Power Law
def func2(a, Bp, z):
   return Bp*npy.power(a, z)


def get_rsq(f, y, popt):

    ss_res = npy.dot((y - func1(x, *popt)),(y - func1(x, *popt)))
    ymean = npy.mean(y)
    ss_tot = npy.dot((y-ymean),(y-ymean))
    return 1-ss_res/ss_tot



x = npy.array([0., 2., 4., 6., 8., 10., 12., 14., 16., 18., 20., 22., 24., 26., 28., 30., 36., 38., 40., 42., 44., 46., 48., 50., 52., 54., 56., 58.])
y = npy.array([0., 0., 0., 0., 0., 0., 4.4, 8., 20., 36., 30.8, 12.4, 5.8, 3.2, 4., 3.8, 54.6, 15.6, 37.2, 39.6, 76.8, 81.2, 111., 142.4, 76.8, 107.2, 151.8, 131.4])


popt, pcov = curve_fit(func1, x, y, p0=(1.0,0.2))
popt2, pcov2 = curve_fit(func2, x, y,p0=[0.0008,3.0],bounds=([-npy.inf,0],npy.inf))


plt.figure()
plt.plot(x, y, 'ko', label="Data")
plt.plot(x, func1(x, *popt), 'r-', label="Exponential Law")
plt.plot(x, func2(x, *popt), 'b-', label="Power Law")
plt.legend()
plt.show()

print "Mean R Exponential:",  get_rsq(func1, y, popt)
print "Mean R Power:",  get_rsq(func2, y, popt2)

和exp拟合出来,

Mean R : 0.856908603298

幂律适合失败(-4.64462440385e+140),我认为这是基于类似的questions),我猜你为何添加了界限。我的scipy是0.17之前的,所以无法测试,但也许你在这里也会有更多的运气。