Python中numpy.polyfit高次多项式拟合时SVD不收敛问题排查
排查numpy.polyfit拟合400次多项式时的ValueError与SystemError问题
核心原因
400次多项式属于极端过高阶数,会引发两个致命问题:
- 构造的范德蒙德矩阵存在严重列相关性,数值条件数极大,导致线性求解过程中SVD分解无法收敛,触发
SystemError。 - 矩阵数值范围异常,触发LAPACK底层缩放函数
DLASCL的参数校验错误,也就是ValueError。
而且这类高次多项式对收盘价这类时间序列数据完全无意义,只会拟合噪音,属于典型的过拟合。
解决方法
1. 大幅降低多项式阶数(优先推荐)
收盘价的趋势拟合用低次多项式足够,比如5-20次,完全没必要用到400次。示例代码:
import numpy as np import pandas as pd df = pd.read_csv('BTC-USDD.csv') # 用序列索引代替原始日期,避免大数值时间戳加剧数值病态 x = np.arange(len(df)) y = df['收盘价'].values # 改用10次多项式拟合 coeffs = np.polyfit(x, y, 10)
2. 标准化输入缓解数值病态(仅用于非极端高阶场景)
如果一定要用较高阶数(不推荐超过50次),先对x做标准化处理,缩小数值范围:
x_scaled = (x - x.mean()) / x.std() # 将x缩放到均值0、标准差1的范围 coeffs = np.polyfit(x_scaled, y, 50)
3. 换用数值更稳定的拟合方法
改用正交多项式(如切比雪夫多项式)拟合,避免范德蒙德矩阵的数值问题:
from numpy.polynomial import Chebyshev # 用切比雪夫多项式拟合,最高阶设为50 coeffs = Chebyshev.fit(x, y, 50)
额外注意事项
- 不要直接用原始时间戳作为x输入,这类数值范围极大,会进一步恶化矩阵的数值稳定性,用序列索引或归一化后的日期更合理。
- 收盘价属于时间序列数据,更适合用ARIMA、指数平滑等专门的时间序列模型,高次多项式的预测能力极差,几乎没有实际价值。
内容的提问来源于stack exchange,提问作者user6570555
相关产品推荐
相关产品推荐

