结果与二次回归相混淆

时间:2019-06-09 06:17:49

标签: python numpy regression curve-fitting smoothing

因此,我试图通过二次回归拟合一些x,y数据对,可以在node property override找到示例公式。 以下是我的代码,该代码使用该显式公式和numpy内置函数进行回归,

import numpy as np 
x = [6.230825,6.248279,6.265732]
y = [0.312949,0.309886,0.306639472]
toCheck = x[2]


def evaluateValue(coeff,x):
    c,b,a = coeff
    val = np.around( a+b*x+c*x**2,9)
    act = 0.306639472
    error=  np.abs(act-val)*100/act
    print "Value = {:.9f} Error = {:.2f}%".format(val,error)



###### USing numpy######################
coeff = np.polyfit(x,y,2)
evaluateValue(coeff, toCheck)



################# Using explicit formula
def determinant(a,b,c,d,e,f,g,h,i):
    # the matrix is [[a,b,c],[d,e,f],[g,h,i]]
    return a*(e*i - f*h) - b*(d*i - g*f) + c*(d*h - e*g)

a = b = c = d = e = m = n = p = 0
a = len(x)
for i,j in zip(x,y):
        b += i
        c += i**2
        d += i**3
        e += i**4
        m += j
        n += j*i
        p += j*i**2
det = determinant(a,b,c,b,c,d,c,d,e)
c0 = determinant(m,b,c,n,c,d,p,d,e)/det
c1 = determinant(a,m,c,b,n,d,c,p,e)/det
c2 = determinant(a,b,m,b,c,n,c,d,p)/det

evaluateValue([c2,c1,c0], toCheck)




######Using another explicit alternative
def determinantAlt(a,b,c,d,e,f,g,h,i):
    return a*e*i - a*f*h - b*d*i +b*g*f + c*d*h - c*e*g # <- barckets removed

a = b = c = d = e = m = n = p = 0
a = len(x)
for i,j in zip(x,y):
        b += i
        c += i**2
        d += i**3
        e += i**4
        m += j
        n += j*i
        p += j*i**2
det = determinantAlt(a,b,c,b,c,d,c,d,e)
c0 = determinantAlt(m,b,c,n,c,d,p,d,e)/det
c1 = determinantAlt(a,m,c,b,n,d,c,p,e)/det
c2 = determinantAlt(a,b,m,b,c,n,c,d,p)/det

evaluateValue([c2,c1,c0], toCheck)

此代码给出了此输出

Value = 0.306639472 Error = 0.00%
Value = 0.308333580 Error = 0.55%
Value = 0.585786477 Error = 91.03%

作为,您可以看到它们彼此不同,并且第三个完全错误。现在我的问题是:
1.为什么显式公式给出的结果略有错误,以及如何改进呢?
2. numpy如何给出如此准确的结果?
3.在第三种情况下,仅通过打开括号,结果如何发生如此大的变化?

1 个答案:

答案 0 :(得分:1)

因此,不幸的是,这里发生的一些事情困扰着您的做事方式。看一下这段代码:

for i,j in zip(x,y):
        b += i
        c += i**2
        d += i**3
        e += i**4
        m += j
        n += j*i
        p += j*i**2

您正在构建功能,使得x值不仅是平方,而且是三次方和四次幂。

如果在将这些值放入3 x 3矩阵中进行求解之前先打印出每个值,则

In [35]: a = b = c = d = e = m = n = p = 0
    ...: a = len(x)
    ...: for i,j in zip(xx,y):
    ...:         b += i
    ...:         c += i**2
    ...:         d += i**3
    ...:         e += i**4
    ...:         m += j
    ...:         n += j*i
    ...:         p += j*i**2
    ...: print(a, b, c, d, e, m, n, p)
    ...:
    ...:
3 18.744836 117.12356813829001 731.8283056811686 4572.738547313946 0.9294744720000001 5.807505391292503 36.28641270376207

在处理浮点运算时,尤其是对于小数值时,运算的顺序确实很重要。这里发生的是,偶然的是,已经计算出的小值和大值的混合导致一个非常小的值。因此,在使用分解形式和扩展形式计算行列式时,请注意如何获得略有不同的结果,但还要看一下值的精度:

In [36]: det = determinant(a,b,c,b,c,d,c,d,e)

In [37]: det
Out[37]: 1.0913403514223319e-10

In [38]: det = determinantAlt(a,b,c,b,c,d,c,d,e)

In [39]: det
Out[39]: 2.3283064365386963e-10

行列式为10 -10 !之所以存在差异,是因为使用浮点算法,理论上两种行列式方法都应产生相同的结果,但不幸的是,实际上它们给出的结果略有不同,这是由于错误传播引起的。由于可以表示浮点数的位数有限,因此操作顺序会更改错误的传播方式,因此,即使您删除括号并且公式基本匹配,操作顺序也可以得出。现在的结果有所不同。对于定期处理浮点算术的任何软件开发人员,本文都是必读的文章:What Every Computer Scientist Should Know About Floating-Point Arithmetic

因此,当您尝试使用Cramer规则求解系统时,不可避免地会用代码中的主要行列式除以偶数,即使更改约为10 -10 ,两种方法之间的变化可以忽略不计,但是您会得到非常不同的结果,因为求解系数时要用该数字除。

NumPy不存在此问题的原因是因为它们通过最小二乘和pseudo-inverse而不是使用Cramer规则来求解系统。我不建议使用Cramer法则来找到回归系数,主要是因为经验丰富,并且有更强大的方法可以做到这一点。

但是,要解决您的特定问题,最好对数据进行规范化,以使动态范围现在位于0的中心。因此,用于构造系数矩阵的特征更加合理,因此计算过程可以更轻松地处理数据。在您的情况下,应该可以执行一些简单的操作,例如用x的平均值减去数据即可。这样,如果您要预测新的数据点,则必须在进行预测之前先减去x数据的平均值。

因此,在代码开头,请对该数据执行均值减和回归。我已经向您展示了我在上面给出的源代码中修改代码的位置:

import numpy as np 
x = [6.230825,6.248279,6.265732]
y = [0.312949,0.309886,0.306639472]

# Calculate mean
me = sum(x) / len(x)
# Make new dataset that is mean subtracted
xx = [pt - me for pt in x]

#toCheck = x[2]

# Data point to check is now mean subtracted
toCheck = x[2] - me



def evaluateValue(coeff,x):
    c,b,a = coeff
    val = np.around( a+b*x+c*x**2,9)
    act = 0.306639472
    error=  np.abs(act-val)*100/act
    print("Value = {:.9f} Error = {:.2f}%".format(val,error))



###### USing numpy######################
coeff = np.polyfit(xx,y,2) # Change
evaluateValue(coeff, toCheck)



################# Using explicit formula
def determinant(a,b,c,d,e,f,g,h,i):
    # the matrix is [[a,b,c],[d,e,f],[g,h,i]]
    return a*(e*i - f*h) - b*(d*i - g*f) + c*(d*h - e*g)

a = b = c = d = e = m = n = p = 0
a = len(x)
for i,j in zip(xx,y): # Change
        b += i
        c += i**2
        d += i**3
        e += i**4
        m += j
        n += j*i
        p += j*i**2
det = determinant(a,b,c,b,c,d,c,d,e)
c0 = determinant(m,b,c,n,c,d,p,d,e)/det
c1 = determinant(a,m,c,b,n,d,c,p,e)/det
c2 = determinant(a,b,m,b,c,n,c,d,p)/det

evaluateValue([c2,c1,c0], toCheck)




######Using another explicit alternative
def determinantAlt(a,b,c,d,e,f,g,h,i):
    return a*e*i - a*f*h - b*d*i +b*g*f + c*d*h - c*e*g # <- barckets removed

a = b = c = d = e = m = n = p = 0
a = len(x)
for i,j in zip(xx,y): # Change
        b += i
        c += i**2
        d += i**3
        e += i**4
        m += j
        n += j*i
        p += j*i**2
det = determinantAlt(a,b,c,b,c,d,c,d,e)
c0 = determinantAlt(m,b,c,n,c,d,p,d,e)/det
c1 = determinantAlt(a,m,c,b,n,d,c,p,e)/det
c2 = determinantAlt(a,b,m,b,c,n,c,d,p)/det
evaluateValue([c2,c1,c0], toCheck)

运行此命令后,我们会得到:

In [41]: run xor
Value = 0.306639472 Error = 0.00%
Value = 0.306639472 Error = 0.00%
Value = 0.306639472 Error = 0.00%

作为对您的最终阅读,这是我在他们的问题Fitting a quadratic function in python without numpy polyfit中解决的其他人遇到的类似问题。总结是,我建议他们不要使用Cramer规则,而应通过伪逆使用最小二乘法。我向他们展示了如何在不使用numpy.polyfit的情况下获得完全相同的结果。另外,使用最小二乘可概括出如果您拥有3个以上点的地方,则仍然可以对所有点进行二次拟合,以使模型具有最小的误差。

相关问题