如何优化Python中Cross模型对我的数据的曲线拟合效果?
优化Cross模型曲线拟合效果的问题
我尝试用Cross模型拟合流变数据,但拟合效果很差。当前数据为剪切速率(x轴)和黏度(y轴),拟合曲线与实验数据偏差明显,实验数据(蓝色散点)和拟合曲线(红色线条)的对比显示模型无法贴合数据趋势。
当前代码
# Data used in model - from dataframe x1M_5 = df_PEO_EXPT_080223["1M_5_wt%_Shear Rate"] y1M_5 = df_PEO_EXPT_080223["1M_5_wt%_Viscosity"] x1M_5 y1M_5 #CurveFit Cross Model from scipy.optimize import curve_fit def Cross(x, Y0, Yinfinity, A, P): y = Yinfinity + ((Y0 - Yinfinity)/(1 - (A*x)**P)) return(y) guess = [2.14191448e+04, 5.22945442e+03, 2.24737143e-01, 4.63747120e+02] popt, pcov = curve_fit(Cross, x1M_5, y1M_5, p0= guess, maxfev = 100000) popt pcov y_model = Cross(x1M_5, *popt) ax = fig.add_subplot(111) plt.scatter(x1M_5, y1M_5) plt.plot(x1M_5, y_model, color='r') plt.xscale('log') plt.yscale('log') plt.show() print(popt)
问题分析与解决方案
- 修正模型公式:标准Cross模型的分母应为
1 + (A*x)**P,你当前代码中用了减号,这会导致当A*x >=1时分母出现负数或零,引发数值异常,这是拟合失效的核心原因。 - 重置初始猜测值:初始参数必须符合流变学物理意义:
Y0(零剪切黏度)取数据中黏度的最大值Yinfinity(无穷剪切黏度)取数据中黏度的最小值A可按黏度开始下降的剪切速率的倒数估算P(流动指数)通常在0~1之间,你之前的463完全超出合理范围,会误导拟合算法
- 添加参数约束:用
bounds限制参数范围,避免出现无物理意义的数值,示例:bounds=([0, 0, 0, 0], [1e5, 1e4, 1, 1]) - 数据校验:确保数据中无零值、负值等异常点,必要时先做筛选。
修改后的代码
# 从数据框提取实验数据 x1M_5 = df_PEO_EXPT_080223["1M_5_wt%_Shear Rate"] y1M_5 = df_PEO_EXPT_080223["1M_5_wt%_Viscosity"] # 导入所需库 from scipy.optimize import curve_fit import matplotlib.pyplot as plt # 修正后的标准Cross模型 def Cross(x, Y0, Yinfinity, A, P): return Yinfinity + (Y0 - Yinfinity) / (1 + (A * x) ** P) # 基于物理意义生成初始猜测值 eta0_guess = y1M_5.max() etainf_guess = y1M_5.min() # 找到黏度开始下降的剪切速率,取倒数作为A的初始值 shear_rate_drop = x1M_5[y1M_5 < 0.9 * eta0_guess].min() A_guess = 1 / shear_rate_drop if shear_rate_drop > 0 else 0.1 P_guess = 0.5 # 流动指数初始值取0~1范围内的典型值 guess = [eta0_guess, etainf_guess, A_guess, P_guess] # 添加参数约束,确保符合物理范围 popt, pcov = curve_fit(Cross, x1M_5, y1M_5, p0=guess, maxfev=100000, bounds=([0, 0, 0, 0], [1e5, 1e4, 1, 1])) # 生成拟合曲线数据 y_model = Cross(x1M_5, *popt) # 绘图对比 fig, ax = plt.subplots() ax.scatter(x1M_5, y1M_5, label='实验数据') ax.plot(x1M_5, y_model, color='r', label='拟合曲线') ax.set_xscale('log') ax.set_yscale('log') ax.set_xlabel('剪切速率') ax.set_ylabel('黏度') ax.legend() plt.show() print("拟合得到的参数:", popt)
内容的提问来源于stack exchange,提问作者Chirag Patel
相关产品推荐
相关产品推荐

