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

解决Scipy报错:Result from function call is not a proper array of floats

常微分方程拟合报错:Result from function call is not a proper array of floats. 原因及修复

问题描述

尝试用Scipy求解并拟合常微分方程 dc/dt = -k*c^α(k和α为待拟合参数,c为t时刻的解)时,运行代码出现错误:error: Result from function call is not a proper array of floats.。曾尝试对自定义函数输出使用np.ravel(),但又遇到error: 'int' object has no attribute ravel错误,还原初始代码后希望得到问题原因和修复方案。

初始代码

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

# Define the ODE function
def ode_func(c, t, k, alpha):
    return -k*c**alpha

# Define the initial condition and time points
c0 = 1.73
t = np.linspace(1, 50, 1000)

# Solve the ODE using scipy's odeint function
c_true = odeint(ode_func, c0, t, args=(2, 2))

# Add some noise to the true solution
np.random.seed(0)
c_noisy = c_true + 0.1 * np.random.randn(*c_true.shape)

# Use scipy.optimize.curve_fit to fit the noisy data
popt, pcov = curve_fit(ode_func, t, c_noisy)

plt.plot(t, odeint(ode_func, c0, t, args=(popt[0], popt[1])), 'r-', label='Fitted solution')

#plotting the noisy solution
plt.plot(t, c_noisy, 'o', label='Noisy solution')
plt.legend()
plt.show()

错误详情

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
ValueError: object too deep for desired array
---------------------------------------------------------------------------
error                                     Traceback (most recent call last)
Cell In[32], line 2
      1 # Use scipy.optimize.curve_fit to fit the noisy data
----> 2 popt, pcov = curve_fit(ode_func, t, c_noisy)     

File c:\Python39\lib\site-packages\scipy\optimize\_minpack_py.py:859, in curve_fit(f, xdata, ydata, p0, sigma, absolute_sigma, check_finite, bounds, method, jac, full_output, **kwargs)
    856 if ydata.size != 1 and n > ydata.size:
    857     raise TypeError(f"The number of func parameters={n} must not"
    858                     f" exceed the number of data points={ydata.size}")
--> 859 res = leastsq(func, p0, Dfun=jac, full_output=1, **kwargs)
    860 popt, pcov, infodict, errmsg, ier = res
    861 ysize = len(infodict['fvec'])

File c:\Python39\lib\site-packages\scipy\optimize\_minpack_py.py:426, in leastsq(func, x0, args, Dfun, full_output, col_deriv, ftol, xtol, gtol, maxfev, epsfcn, factor, diag)
    424     if maxfev == 0:
    425         maxfev = 200*(n + 1)
--> 426     retval = _minpack._lmdif(func, x0, args, full_output, ftol, xtol,
    427                              gtol, maxfev, epsfcn, factor, diag)
    428 else:
    429     if col_deriv:

error: Result from function call is not a proper array of floats.

错误原因

  1. 函数参数顺序不匹配:curve_fit要求拟合函数的第一个参数是自变量(这里是t),后续是待拟合参数;但你的ode_func是给odeint设计的,参数顺序是(c, t, k, alpha),完全不符合curve_fit的调用逻辑。
  2. 维度不匹配:odeint返回的是二维数组(形状(1000,1)),而curve_fit期望因变量是一维数组,c_noisy的二维形状会导致维度错误。
  3. 函数功能错误:你直接把ODE的导数函数ode_func传给curve_fit,但curve_fit需要的是输入t和参数,返回对应c值的函数,而不是返回导数的函数。

修复方案

  1. 封装一个适配curve_fit的函数:输入t和待拟合参数k、alpha,内部调用odeint求解ODE,返回一维的解数组。
  2. 将c_noisy展平为一维数组,匹配拟合函数的输出形状。
  3. 给curve_fit提供初始参数猜测p0,帮助优化器更快收敛。

修复后的完整代码

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

# 定义ODE导数函数(给odeint用)
def ode_func(c, t, k, alpha):
    return -k * c**alpha

# 定义适配curve_fit的拟合函数:输入t和参数,返回ODE的解
def fit_func(t, k, alpha):
    c0 = 1.73  # 初始条件固定
    # 求解ODE并展平为一维数组
    return odeint(ode_func, c0, t, args=(k, alpha)).ravel()

# 初始条件和时间点
c0 = 1.73
t = np.linspace(1, 50, 1000)

# 生成真实解和带噪声的数据
np.random.seed(0)
c_true = odeint(ode_func, c0, t, args=(2, 2)).ravel()
c_noisy = c_true + 0.1 * np.random.randn(len(t))

# 拟合:提供初始参数猜测p0,避免优化器收敛失败
popt, pcov = curve_fit(fit_func, t, c_noisy, p0=[1, 1])

# 绘图展示
plt.plot(t, fit_func(t, *popt), 'r-', linewidth=2, label=f'拟合解 (k={popt[0]:.2f}, α={popt[1]:.2f})')
plt.plot(t, c_noisy, 'o', markersize=2, label='带噪声数据')
plt.xlabel('t')
plt.ylabel('c')
plt.legend()
plt.show()

说明

  • fit_func是专门给curve_fit用的,参数顺序符合要求,并且返回一维数组。
  • 用ravel()将odeint的二维输出转为一维,匹配c_noisy的形状。
  • 添加p0=[1,1]作为初始猜测,帮助curve_fit更快找到正确的参数值。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 20:35:26