Python curve_fit有多个自变量

rfe*_*and 40 python curve-fitting scipy

Python curve_fit使用单个自变量计算函数的最佳拟合参数,但有没有办法,使用curve_fit或其他东西,以适应具有多个独立变量的函数?例如:

def func(x, y, a, b, c):
    return log(a) + b*log(x) + c*log(y)
Run Code Online (Sandbox Code Playgroud)

其中x和y是自变量,我们想要适合a,b和c.

xnx*_*xnx 48

你可以curve_fit为自变量传递一个多维数组,但是你func必须接受同样的事情.例如,调用此数组X,并将其拆包x,y为清楚起见:

import numpy as np
from scipy.optimize import curve_fit

def func(X, a, b, c):
    x,y = X
    return np.log(a) + b*np.log(x) + c*np.log(y)

# some artificially noisy data to fit
x = np.linspace(0.1,1.1,101)
y = np.linspace(1.,2., 101)
a, b, c = 10., 4., 6.
z = func((x,y), a, b, c) * 1 + np.random.random(101) / 100

# initial guesses for a,b,c:
p0 = 8., 2., 7.
print curve_fit(func, (x,y), z, p0)
Run Code Online (Sandbox Code Playgroud)

给予合适:

(array([ 9.99933937,  3.99710083,  6.00875164]), array([[  1.75295644e-03,   9.34724308e-05,  -2.90150983e-04],
   [  9.34724308e-05,   5.09079478e-06,  -1.53939905e-05],
   [ -2.90150983e-04,  -1.53939905e-05,   4.84935731e-05]]))
Run Code Online (Sandbox Code Playgroud)

  • 我只是想分享我针对与@ScottG 相同问题的解决方案。假设 x 方向有 20 个样本,y 方向有 30 个样本,以及每个交叉点的数据(总共 20x30 = 600 个样本)。我使用 `x,y = np.mesgrid(x,y)` 然后使用 `np.stack((x,y), axis=2).reshape(-1, 2)` 得到 `(600,2 )` 数组将是 `xdata`,包含所有 600 个 x 和 y 组合。然后,我将 600 个样本中的数据展平为一维“(600,)”数组,该数组将是“ydata”,而不是二维“(20, 30)”数组。然后你可以用 `x, y = np.hsplit(X, 2)` 将数据解压到 func 中。(“X”是“xdata”) (3认同)
  • 如果 x 和 y 的大小不同,有没有办法修改解决方案以使用曲线拟合。例如,x = linspace(0.1,1.1,101) 和 y = np.array([1.0,2.0])? (2认同)

Mar*_*hke 5

优化具有多个输入维度和可变数量参数的函数

此示例演示如何通过增加系数数量来拟合具有二维输入 (R^2 -> R) 的多项式。该设计非常灵活,因此curve_fit中的可调用 f可以为任意数量的非关键字参数定义一次。

在此输入图像描述

最小可重复示例

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

def poly2d(xy, *coefficients):
    x = xy[:, 0]
    y = xy[:, 1]
    proj = x + y
    res = 0
    for order, coef in enumerate(coefficients):
        res += coef * proj ** order
    return res

nx = 31
ny = 21

range_x = [-1.5, 1.5]
range_y = [-1, 1]
target_coefficients = (3, 0, -19, 7)

xs = np.linspace(*range_x, nx)
ys = np.linspace(*range_y, ny)
im_x, im_y = np.meshgrid(xs, ys)
xdata = np.c_[im_x.flatten(), im_y.flatten()]
im_target = poly2d(xdata, *target_coefficients).reshape(ny, nx)

fig, axs = plt.subplots(2, 3, figsize=(29.7, 21))
axs = axs.flatten()

ax = axs[0]
ax.set_title('Unknown polynomial P(x+y)\n[secret coefficients: ' + str(target_coefficients) + ']')
sm = ax.imshow(
    im_target,
    cmap = plt.get_cmap('coolwarm'),
    origin='lower'
    )
fig.colorbar(sm, ax=ax)

for order in range(5):
    ydata=im_target.flatten()
    popt, pcov = curve_fit(poly2d, xdata=xdata, ydata=ydata, p0=[0]*(order+1) )

    im_fit = poly2d(xdata, *popt).reshape(ny, nx)

    ax = axs[1+order]
    title = 'Fit O({:d}):'.format(order)
    for o, p in enumerate(popt):
        if o%2 == 0:
            title += '\n'
        if o == 0:
            title += ' {:=-{w}.1f} (x+y)^{:d}'.format(p, o, w=int(np.log10(max(abs(p), 1))) + 5)
        else:
            title += ' {:=+{w}.1f} (x+y)^{:d}'.format(p, o, w=int(np.log10(max(abs(p), 1))) + 5)
    title += '\nrms: {:.1f}'.format( np.mean((im_fit-im_target)**2)**.5 )
    ax.set_title(title)
    sm = ax.imshow(
        im_fit,
        cmap = plt.get_cmap('coolwarm'),
        origin='lower'
        )
    fig.colorbar(sm, ax=ax)

for ax in axs.flatten():
    ax.set_xlabel('x')
    ax.set_ylabel('y')

plt.show()
Run Code Online (Sandbox Code Playgroud)

PS 这个答案的概念与我在这里的其他答案相同,但代码示例更清晰。到时候我会删除另一个答案。