使用numpy进行多项式外推遇两类错误,求技术解决方案
问题解决思路
1. 解决'numpy.ndarray' object is not callable错误
- 错误原因:
f = poly.polyval(x, z)执行后,f是拟合得到的原始x对应的y值数组,不是可调用的函数。你试图用f(x2)把数组当函数调用,自然会报错。 - 解决方法:直接用
poly.polyval(x2, z)计算扩展x轴x2对应的拟合外推值,不需要先赋值给f。
2. 解决阶数≥21时的SVD did not converge in Linear Least Squares错误
- 错误原因:
- 高次多项式拟合本身容易导致矩阵病态:当多项式阶数接近甚至超过样本点数量时,最小二乘求解的系数矩阵会变得极端奇异,奇异值分解(SVD)无法收敛。
- 你的x值量级是
1e12,高次项(比如x^21)的数值会爆炸式增长,进一步加剧数值不稳定,触发SVD收敛失败。
- 解决方法:
- 优先降低多项式阶数:先尝试5-10阶的多项式,观察拟合效果,外推不需要过高阶数,高阶反而容易在边界出现剧烈波动(龙格现象)。
- 对x做归一化处理:将x转换为小范围数值(比如减去均值再除以标准差),消除大数值带来的数值不稳定,代码里可以用
x_normalized = (np.array(x) - np.mean(x)) / np.std(x),拟合后再用归一化的逆变换计算外推值。 - 换用更适合外推的方法:比如分段低阶多项式拟合、样条插值(但样条外推效果有限),或者使用专门的趋势外推模型。
修正后的代码示例
import numpy as np import matplotlib.pyplot as plt import numpy.polynomial.polynomial as poly y = [9.996651009,10.13327408,10.27003353,10.43754263,10.60523071,10.71136134,10.81753489,10.92299416,11.02853271,11.10093835,11.17349619,11.16565259,11.15787539,11.16191795,11.16626826,11.16087842,11.15561384,11.16940196,11.18346164,11.22434472,11.26537218,11.35981126,11.45427174,11.6102862,11.76633923,11.89058563,12.01486743,12.21133227,12.40782023,12.55682327,12.7059072,12.88910065,13.07234341,13.20139753,13.33048759,13.46960371,13.60875466,13.71956075,13.83042354,13.91157425,13.99277241,14.08548465,14.17824161,14.26091536,14.34364144,14.43504833,14.52651725,14.59548578,14.66449439,14.73751377,14.81058218,14.88687742,14.96322511,15.038278,15.11342222,15.1644832,15.21556914,15.31798775,15.42044285,15.51000031,15.59959896,15.68089263,15.76229354,15.86213633,15.96214484,16.0269976,16.0923806,16.16483146,16.23762336,16.24233076,16.24719576,16.26116812,16.27543692,16.28311024,16.29128992,16.23458771,16.17830522,16.12636211,16.07478778] y.reverse() # 生成原始x轴并转为numpy数组 x = [] i = 192.1e12 while i <= 196e12: x.append(i) i += 50e9 x = np.array(x) # 生成扩展x轴并转为numpy数组 x2 = [] i1 = 191.325e12 while i1 <= 196.125e12: x2.append(i1) i1 += 50e9 x2 = np.array(x2) # 多项式拟合(这里用10阶,可根据效果调整) z = poly.polyfit(x, y, 10) # 计算原始x的拟合值和扩展x的外推值 f_original = poly.polyval(x, z) f_extrapolate = poly.polyval(x2, z) # 绘图 plt.plot(x, y, label='原始数据') plt.plot(x, f_original, label='拟合曲线') plt.plot(x2, f_extrapolate, linestyle='--', label='外推曲线') plt.legend() plt.show()
内容的提问来源于stack exchange,提问作者MRR
相关产品推荐
相关产品推荐

