使用Scipy minimize进行幂律拟合参数优化的报错求助
解决scipy minimize优化幂律拟合参数的报错问题
报错原因分析
- TypeError:调用
minimize时错误执行了chi_square_ols()(加了括号),且目标函数参数格式不符合minimize要求——它要求目标函数的第一个参数是待优化的参数数组,而非分开的A和p。 - NameError:参数传递逻辑错误,未通过
args正确传递数据变量,导致函数内部无法识别x、y_av等变量。
核心修改步骤
- 重构目标函数:将
A和p合并为一个参数数组params作为函数第一个参数,固定数据x、y_av、unc通过args传入。 - 修正
minimize调用:直接传递函数名(不要加括号),用args传入非优化的固定变量。 - 对齐卡方计算逻辑:加入误差加权,和
curve_fit的计算规则保持一致,确保优化结果匹配。
修正后的完整代码
import matplotlib.pyplot as plt import math import scipy.optimize as scp from scipy.optimize import curve_fit import numpy as np x = [] y1 = [] y2 = [] y3 = [] y4 = [] y5 = [] y6 = [] y7 = [] y8 = [] y9 = [] y10 = [] y_av = [] unc = [] logx = [] logy = [] with open('data1.txt', 'r') as data_file: for line in data_file: lines = [i for i in line.split()] x.append(float(lines[0])) y1.append(float(lines[1])) y2.append(float(lines[2])) y3.append(float(lines[3])) y4.append(float(lines[4])) y5.append(float(lines[5])) y6.append(float(lines[6])) y7.append(float(lines[7])) y8.append(float(lines[8])) y9.append(float(lines[9])) y10.append(float(lines[10])) length = len(x) dof = length-2 for i in range(length): y_av.append((y1[i]+y2[i]+y3[i]+y4[i]+y5[i]+y6[i]+y7[i]+y8[i]+y9[i]+y10[i])/10) plt.title("Test") plt.xlabel('xdata') plt.ylabel('ydata') plt.plot(x, y_av, marker='o', c='g') plt.show() for i in range(length): squared_diff = sum((y - y_av[i])**2 for y in [y1[i], y2[i], y3[i], y4[i], y5[i], y6[i], y7[i], y8[i], y9[i], y10[i]]) unc.append(math.sqrt(squared_diff/10)) def power_fit(x, A, p): return A * x**p plt.errorbar(x, y_av, yerr=unc, fmt='ko', label='data') (params, cov) = scp.curve_fit(power_fit, x, y_av, sigma=unc) param_err = np.sqrt(np.diagonal(cov)) A1 = params[0] p1 = params[1] plt.plot(x, power_fit(x, *params), 'r--') chi_sq = np.sum(((y_av - A1*x**p1)/unc)**2) chi_sq_red = chi_sq/dof # 重构卡方函数:第一个参数是待优化的参数数组,后续为固定数据 def chi_square_ols(params, x, y_av, unc): A, p = params # 从数组中拆分出A和p model = A * np.power(x, p) # 加入误差加权,和curve_fit逻辑对齐 return np.sum(np.power((y_av - model)/unc, 2)) x0 = [1.00, 1.00] # 修正minimize调用:传函数名,args以元组传入固定变量 min_chi = scp.minimize(chi_square_ols, x0=x0, args=(x, y_av, unc)) print("优化结果:") print(min_chi) # 提取优化后的参数 opt_A, opt_p = min_chi.x print(f"优化得到的A: {opt_A}, p: {opt_p}")
关键修改说明
- 目标函数重构:将
A和p整合为参数数组,避免全局变量依赖,通过args传递固定数据。 - minimize调用修正:直接传递函数对象而非执行函数,
args用元组形式传入非优化变量。 - 加权卡方:加入
unc权重,确保优化逻辑和curve_fit一致,结果更具参考性。
内容的提问来源于stack exchange,提问作者eird19
相关产品推荐
相关产品推荐

