如何使用scipy.optimize.minimize求解粘度公式的6个最优缺失参数
粘度公式参数拟合问题解答
问题概述
当前任务为拟合三指数叠加形式的粘度公式最优参数,优化目标为最小化拟合结果与3组实测数据的平方误差:
- 粘度公式形式:$\eta(T) = a_0 e^{-a_1 T} + a_2 e^{-a_3 T} + a_4 e^{-a_5 T}$,其中T为温度
- 实测数据点:
- T=40时,实测粘度39.3
- T=50时,实测粘度26.9
- T=100时,实测粘度5.4
- 可使用的优化工具:
scipy.optimize.minimize(局部优化)、scipy.optimize.differential_evolution(全局优化)
现有代码问题
你的公式转写逻辑本身没有语法错误,但存在3个直接导致优化失败的问题:
- 初始值设置完全不符合物理量级:你传入的a1、a3、a5初始值为5,代入计算得$e{-5*40}=e{-200}\approx0$,初始状态下三个指数项输出几乎为0,和实测值差数百个数量级,优化器极易陷入无效局部最优
- 未添加参数约束:粘度随温度升高单调递减为正,所有6个参数必须为非负值,无约束情况下优化可能输出无物理意义的负参数
- 未掌握
differential_evolution的必填参数:该全局优化函数不需要初始猜测值,但必须为每个参数传入合理的取值边界(bounds),缺省该参数会直接运行报错
修正后可运行代码
import scipy.optimize as optimize import numpy as np # 粘度计算函数,直接接收参数数组a,减少冗余传参 def visc(x, a): a0, a1, a2, a3, a4, a5 = a return a0*np.exp(-a1*x) + a2*np.exp(-a3*x) + a4*np.exp(-a5*x) # 平方误差目标函数 def error(a): return (visc(40, a) - 39.3)**2 + (visc(50, a) - 26.9)**2 + (visc(100, a) - 5.4)**2 # -------------------- 方式1:使用minimize局部优化 -------------------- # 合理初始值:保证初始计算结果和实测值同量级 # 振幅项a0/a2/a4取几十的量级,衰减系数a1/a3/a5取0.0x量级,保证40度时指数项不会衰减到接近0 x0 = [50, 0.01, 20, 0.02, 10, 0.05] # 加非负约束,避免出现无物理意义的参数 bounds_minimize = [(0, None)]*6 res_min = optimize.minimize(error, x0=x0, bounds=bounds_minimize) print("minimize拟合结果参数:", res_min.x) print("minimize拟合误差:", res_min.fun) # -------------------- 方式2:使用differential_evolution全局优化 -------------------- # 不需要初始值,只需要给每个参数设合理边界:振幅0~100,衰减系数0~0.1 bounds_de = [(0, 100), (0, 0.1), (0, 100), (0, 0.1), (0, 100), (0, 0.1)] res_de = optimize.differential_evolution(error, bounds=bounds_de) print("differential_evolution拟合结果参数:", res_de.x) print("differential_evolution拟合误差:", res_de.fun) # 验证拟合效果 print("40度拟合值:", visc(40, res_de.x)) print("50度拟合值:", visc(50, res_de.x)) print("100度拟合值:", visc(100, res_de.x))
使用说明
- 关于
minimize的初始值选择:不需要精准匹配最优值,只要代入初始值计算的粘度结果和实测值在同一个数量级即可,你可以手动调整参数试算,只要初始输出不接近0或者远大于实测值,优化就能正常收敛 - 关于
differential_evolution的边界设置:按照物理意义给范围即可,振幅项上限只要大于最大实测粘度(39.3)留足余量,衰减系数上限保证在最低温度(40)下指数项不会衰减到0即可,不需要刻意精准 - 两种优化方式输出的参数可能略有差异,但最终拟合的三个点误差都会接近0,符合要求;如果需要更稳定的结果优先用
differential_evolution,不需要凑初始值,不容易陷入局部最优
内容的提问来源于stack exchange,提问作者Nicho_Link
相关产品推荐
相关产品推荐

