二次回归拟合结果异常咨询:Numpy与显式公式结果差异
二次回归实现差异的问题解析
让我逐个拆解你遇到的这三个问题,帮你理清背后的数值计算原理:
1. 自定义显式公式的微小误差与优化方向
你第一版自定义行列式实现出现0.55%的误差,核心原因是手动求解过程没处理病态矩阵的数值稳定性问题。
二次回归的最小二乘本质是求解这个线性方程组:
n*c₀ + (Σx)*c₁ + (Σx²)*c₂ = Σy (Σx)*c₀ + (Σx²)*c₁ + (Σx³)*c₂ = Σxy (Σx²)*c₀ + (Σx³)*c₁ + (Σx⁴)*c₂ = Σx²y
你的x取值非常接近(6.23~6.26),导致系数矩阵的列(x的0次、1次、2次幂)高度相关,形成病态矩阵——矩阵的条件数极大,直接计算行列式会放大浮点运算的舍入误差。
优化方案:
- 中心化x数据:把x转换为
x' = x - mean(x),这样Σx'=0,能大幅降低系数矩阵的条件数,减少误差 - 使用高精度浮点类型:将变量替换为
np.float64或np.longdouble,缩小舍入误差 - 放弃行列式求解:改用QR分解、LU分解等数值稳定的线性代数方法(这也是numpy用的思路)
2. Numpy polyfit的高精度原因
Numpy的polyfit根本没用到显式行列式求解,它靠的是QR分解法处理最小二乘问题,这种方法在应对病态矩阵时的稳定性远高于手动行列式计算。
具体流程是:
- 构造范德蒙德矩阵(每一行是
[1, x_i, x_i²]) - 对该矩阵做QR分解,将其分解为正交矩阵Q和上三角矩阵R
- 通过回代求解
Rc=Qᵀy得到系数c
QR分解能有效避免病态矩阵带来的误差放大,再加上numpy底层依赖高度优化的BLAS/LAPACK库,用双精度浮点运算,精度和稳定性自然碾压手动实现。
3. 展开行列式括号导致大幅偏差的原因
这个问题的核心是浮点运算顺序引发的数值稳定性灾难。
你可能以为展开行列式括号只是数学等价变换,但实际浮点运算中,计算顺序会极大影响精度:
- 第二版实现里,你先计算括号内的小差值(比如
e*i - f*h,也就是Σx²*Σx⁴ - (Σx³)²,这是一个非常小的数),再和外面的系数相乘,这种方式能保留小差值的有效精度 - 第三版实现里,你直接展开成大数相乘再相减(比如
a*e*i - a*f*h,也就是n*Σx²*Σx⁴ - n*(Σx³)²),两个超大数相减时,浮点运算的舍入误差会被彻底放大——原本的小差值可能被完全淹没在误差里,导致行列式结果完全错误,最终系数计算彻底偏离真实值。
补充说明:你的行列式展开式在数学上是正确的,但浮点运算的“等价”和数学上的等价是两回事,尤其是涉及到接近相等的大数相减时,必须优先计算小差值来保证稳定性。
内容的提问来源于stack exchange,提问作者Eular
相关产品推荐
相关产品推荐

