使用 scipy.optimize.curve_fit() 将表面拟合到 3D 散点数据时出现类型错误

TypeError when fitting surface to 3D scatter data using scipy.optimize.curve_fit()

我有一个 Pandas DataFrame,其列包含 x、y 和 z 值。

import pandas as pd
df = pd.DataFrame({'Age': x,
                   'Mileage': y,
                   'Price': z})

使用 scipy.optimize.curvefit() 我能够拟合单变量指数函数 y = exp(-bx):

import numpy as np
from scipy.optimize import curve_fit

# fit y to x
def exp_function(x, a, b):
    return a * np.exp(-b * x)

popt, pcov = curve_fit(exp_function, df['Age'],    # x-values
                        df['Price'],               # y-values
                        absolute_sigma=False, maxfev=1000)

# popt
# array([2.81641498e+04, 1.29183078e-01])                      # a, b-values

但是当我尝试将相同的分析扩展到 3D 时,我遇到了 TypeError

# fit z to (x, y)
def exp_function_2(x, y, a, b, c):
    return (a/2) * (np.exp(-b * x) + np.exp(-c * y))

popt, pcov = curve_fit(exp_function_2, 
                       df['Age'],           # x-values
                       df['Mileage'],       # y-values
                       df['Price'],         # z-values
                       absolute_sigma=False, maxfev=1000)


# TypeError: exp_function_2() takes 5 positional arguments but 1518 were given

它似乎认为我正在将 1518 个参数(我的 Pandas 数据帧的长度)传递给 exp_function_2()

为什么我的代码适用于 2D (x, y) 适配,但在 3D (x, y, z) 适配上却卡住了?

您正在使用不正确的参数调用该方法。

原型为curve_fit(f, xdata, ydata, p0=None, ...)docs indicate,其中p0是您函数参数的起始猜测。所以在你有一个 TypeError 的情况下,你将框架的所有 1518 个元素作为默认参数传递给你的函数,当然它只接受 5 个参数。事实上,您的代码在 2D 情况下工作是一个快乐的巧合,根本没有使用 p0 关键字参数。

您需要在 xdata 中将两个预测变量作为单个参数传递,然后将它们解包到指数函数中。像这样的东西(虽然我不确定我的数据帧索引是否正确,但我很少使用 pandas):

def exp_function_2(x, a, b, c):
    return (a/2) * (np.exp(-b * x['Age']) + np.exp(-c * x['Mileage']))