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

使用scipy.curve_fit一维方法实现二维曲面拟合报错求助

解决scipy.optimize.curve_fit二维曲面拟合时的索引错误

错误原因

你遇到的IndexError本质是:curve_fit在拟合迭代过程中,会对传入的自变量(此处为index_line)进行数值调整,可能生成非整数的浮点数作为索引参数。尽管初始的index_line是整数数组,但拟合过程中临时传入的索引值不符合numpy数组的索引类型要求,因此触发报错。

解决方案

无需通过索引间接获取x、y数据,直接将一维化的x_line和y_line作为二维自变量传入curve_fit,同时修改拟合函数的参数结构,让它直接接收x、y数据而非索引。这种方式逻辑更清晰,也从根源上避免了索引类型问题。

修改后的完整代码

import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit

### 定义曲面公式与拟合函数
# 原始二维曲面公式
sag_eq = lambda x, y, x0, y0, z0, r, k: ((1/r)*((x-x0)**2+(y-y0)**2)**2) / (1+np.sqrt(1-(1+k)*(1/r)**2*((x-x0)**2+(y-y0)**2))) + z0

# 适配curve_fit的拟合函数:第一个参数接收x、y组成的元组
def sag_fit_func(x_y, x0, y0, z0, r, k):
    x, y = x_y
    return ((1/r)*((x-x0)**2+(y-y0)**2)**2) / (1+np.sqrt(1-(1+k)*(1/r)**2*((x-x0)**2+(y-y0)**2))) + z0

### 生成带噪声的二维数据
x_dom = np.linspace(0,0.32, 2**8)
y_dom = np.linspace(0,0.24, 2**7)
param = [x_dom[-1]/2, y_dom[-1]/2, 0, -0.2, -1]
zz = []
for y in y_dom:
    base = sag_eq(x_dom, y, param[0], param[1], param[2], param[3], param[4])
    noise = np.random.rand(len(base))
    zz.append(base+noise*1e-3)

zz=np.array(zz)
xx, yy = np.meshgrid(x_dom, y_dom)

### 转换为一维数组用于拟合
x_line = xx.reshape(len(x_dom)*len(y_dom))
y_line = yy.reshape(len(x_dom)*len(y_dom))
z_line = zz.reshape(len(x_dom)*len(y_dom))

### 测试曲面生成(可选)
surface_1 = sag_eq(xx, yy, param[0], param[1], param[2], param[3], param[4])

fig, [ax_data, ax_surf1] = plt.subplots(1,2)
ax_data.contourf(xx, yy, zz); ax_data.set_title("原始数据曲面")
ax_surf1.contourf(xx, yy, surface_1); ax_surf1.set_title("公式生成曲面")
plt.show()

fig, [ax_x, ax_y] = plt.subplots(1, 2)
ax_x.scatter(x_line, z_line); ax_x.set_title("一维X-Z数据")
ax_y.scatter(y_line, z_line); ax_y.set_title("一维Y-Z数据")
plt.show()

### 执行拟合
popt, pcov = curve_fit(sag_fit_func, (x_line, y_line), z_line, p0=param)
print("拟合得到的参数:", popt)

# 验证拟合结果
fit_surface = sag_eq(xx, yy, *popt)
fig, ax_fit = plt.subplots()
ax_fit.contourf(xx, yy, fit_surface); ax_fit.set_title("拟合曲面")
plt.show()

额外说明

  • 用普通def定义拟合函数而非lambda,是因为复杂表达式的可读性更好,也便于后续调试和修改。
  • curve_fit支持传入多维自变量,只要函数的第一个参数能正确解构输入的多维数据即可,这种方式是处理多自变量拟合的标准做法。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 19:14:53