You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SciPy插值得到意外曲线,与LibreOffice Calc三次趋势线结果不符

核心差异说明

你遇到的结果不一致是因为两类方法的底层逻辑完全不同:

  • LibreOffice Calc的「3次多项式趋势线」是全局三次多项式最小二乘拟合:会基于所有样本点拟合一个唯一的三次多项式 y = a·x³ + b·x² + c·x + d,拟合目标是最小化所有样本点的预测值和真实值的平方误差,不需要严格穿过每一个原始样本点。
  • scipy.interpolate.interp1d(kind='cubic') 是分段三次样条插值:会在每两个相邻样本点之间分别生成一个独立的三次多项式,要求所有分段在连接点处值、一阶导数、二阶导数全部连续,且必须严格经过每一个原始样本点,天然就会出现局部弯曲的形态。

实现和Calc一致效果的方法

直接使用numpy.polyfit做全局三次多项式拟合即可,和Calc的趋势线计算逻辑完全一致,示例代码如下:

import numpy as np
import matplotlib.pyplot as plt

# 原始样本数据
x = np.array([1, 4, 16, 64, 256])
y = np.array([80, 40, 20, 10, 5])

# 三次多项式拟合,deg=3表示三次,返回系数按高次到低次排列:[a, b, c, d]
cubic_coeffs = np.polyfit(x, y, deg=3)
# 生成可直接调用的多项式函数
cubic_predict = np.poly1d(cubic_coeffs)

# 生成平滑曲线用于绘图
x_smooth = np.linspace(x.min(), x.max(), 500)
y_smooth = cubic_predict(x_smooth)

# 可视化验证
plt.scatter(x, y, c="blue", label="原始样本")
plt.plot(x_smooth, y_smooth, c="red", label="全局三次多项式拟合(同Calc结果)")
plt.xlabel("x")
plt.ylabel("y")
plt.legend()
plt.show()

之前测试方法无效的原因

  • 样条插值本身和全局多项式拟合就是两类完全不同的方法,无论怎么调整参数都不可能得到和Calc趋势线一致的结果。
  • 如果你之前用scipy.optimize.curve_fit没有得到预期结果,大概率是没有明确指定三次多项式的函数形式,只要传入正确的三次函数形式就能得到和polyfit完全一致的结果:
from scipy.optimize import curve_fit

# 明确指定三次多项式的函数形式
def cubic_func(x, a, b, c, d):
    return a * x**3 + b * x**2 + c * x + d

# 拟合得到的参数popt和np.polyfit输出的系数完全相同
popt, _ = curve_fit(cubic_func, x, y)

补充说明

你的原始样本x取值是指数级增长的,且天然符合y = 80 / √x的幂律关系,三次多项式拟合只是对该分布的近似,如果你的使用场景允许换拟合模型,幂律拟合的效果会比三次多项式好很多。

内容的提问来源于stack exchange,提问作者lambdakappatheta

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 14:24:01