Python双变量多项式拟合:泵性能曲线多函数拟合问题求助
泵性能双变量多项式拟合问题解决方法
问题背景
需要基于泵性能实验数据拟合三组双变量函数:
pressure = func(flowrate, RPM) flowrate = func(pressure, RPM) RPM = func(flowrate, pressure)
理论遵循相似定律(流量∝RPM,压力∝RPM²),但实际数据存在偏差,计划用二次多项式(或三次)拟合:
Y = a*x1² + b*x1 + c*x2² + d*x2 + e*x1*x2 + f
使用scipy.curve_fit时得到错误结果,且需直接获取拟合系数,不倾向使用sklearn。
原代码错误分析
- 未处理NaN值:数据中存在
np.nan,会直接导致拟合失败 - 测试计算错误:
param[3]**rpm_test是幂运算,应为乘法param[3]*rpm_test - 未提供初始参数:
curve_fit默认初始值全为1,对于量级差异极大的变量(如RPM为几千、流量为几十),易导致拟合发散或结果不合理
修正后的代码
import numpy as np import pandas as pd from scipy.optimize import curve_fit # 原始实验数据 df = pd.DataFrame({ 'Flow(lpm)': [128.0846942, 105.7579874, 95.11146262, 69.57902038, 53.25344504, 35.47260492, np.nan, 131.96, 110.57, 91.32, 73.02, 53.9, 20.41, np.nan, 116.06, 99.46, 83.7, 68.84, 54.47, 20.98, np.nan, 103.0, 87.6, 73.6, 57.8, 44.0, 19.49, np.nan, 86.2, 73.1, 56.0, 42.6, 28.1, 16.33, np.nan, 56.2, 47.1, 38.6, 30.9, 24.0, 12.3], 'Speed Feedback (RPM)': [5204.0, 5208.0, 5206.0, 5206.0, 5176.0, 5175.0, np.nan, 4710.72, 4706.4, 4714.93, 4687.11, 4691.0, 4602.0, np.nan, 4103.21, 4115.26, 4147.8, 4148.14, 4141.09, 4124.72, np.nan, 3675.89, 3657.88, 3673.73, 3671.41, 3675.27, 3664.88, np.nan, 3118.66, 3186.23, 3106.92, 3107.19, 3114.69, 3090.08, np.nan, 2077.44, 2073.23, 2062.01, 2069.37, 2068.02, 2067.91], 'dP (PSI)': [16.5, 25.34, 28.78, 35.45, 37.86, 38.87, np.nan, 8.85, 17.01, 23.42, 27.48, 30.5, 32.4, np.nan, 6.69, 11.84, 17.24, 20.16, 22.64, 25.81, np.nan, 5.2, 9.6, 13.2, 16.3, 18.1, 20.38, np.nan, 3.7, 6.5, 10.0, 12.1, 13.5, 14.54, np.nan, 1.2, 2.7, 3.7, 4.7, 5.2, 6.3] }) # 1. 清理数据:移除含NaN的无效行 clean_df = df.dropna() flow_lpm = clean_df['Flow(lpm)'].to_numpy() rpm = clean_df['Speed Feedback (RPM)'].to_numpy() dP = clean_df['dP (PSI)'].to_numpy() X = (flow_lpm, rpm) y = dP # 2. 定义二次双变量多项式拟合函数 def poly_2d(X, a, b, c, d, e, f): x1, x2 = X return a * x1**2 + b * x1 + c * x2**2 + d * x2 + e * x1 * x2 + f # 3. 设置初始参数(基于相似定律和数据量级估算,提升拟合稳定性) # 压力随流量增大而减小、随RPM平方增大而增大,交叉项初始值设为小量 initial_guess = [-0.001, 0.1, 1e-6, -0.01, 1e-5, 0] # 4. 执行曲线拟合 params, params_cov = curve_fit(poly_2d, X, y, p0=initial_guess) print("拟合系数:", params) # 5. 测试拟合结果(修正原代码中的幂运算错误) flow_test = 54 rpm_test = 5195 dp_test = (params[0]*flow_test**2 + params[1]*flow_test + params[2]*rpm_test**2 + params[3]*rpm_test + params[4]*flow_test*rpm_test + params[5]) print(f"预测压力:{dp_test:.2f} PSI")
额外优化建议
- 数据归一化:将流量、RPM、压力缩放到[0,1]或[-1,1]区间,避免因变量量级差异过大导致拟合不稳定,拟合后可还原系数
- 扩展三次多项式:若二次拟合精度不足,可添加三次项(如
g*x1³、h*x2³、i*x1²*x2、j*x1*x2²),同步调整初始参数即可 - 筛选中间区间数据:若端点数据偏差大,可通过条件筛选保留中间区间,例如:
clean_df = clean_df[(clean_df['Flow(lpm)'] > 20) & (clean_df['Flow(lpm)'] < 130)] - 拟合效果验证:计算决定系数
R²评估拟合质量:y_pred = poly_2d(X, *params) r_squared = 1 - (np.sum((y - y_pred)**2) / np.sum((y - np.mean(y))**2)) print(f"R²值:{r_squared:.4f}")
内容的提问来源于stack exchange,提问作者Jesh Kundem
相关产品推荐
相关产品推荐

