数据规模差异大时SciPy curve_fit无法稳定拟合AMM模型参数
AMM模型参数拟合的敏感性问题
我们使用scipy.optimize.curve_fit拟合自动做市商(AMM)模型的参数X_eff和Y_eff,模型公式为:
y_out = (Y_eff * x_in) / (X_eff + x_in)
当输入数据点(x_in, y_out)的规模差异显著,或大尺度数据点存在微小变动时,拟合得到的X_eff和Y_eff值会表现出极强的敏感性。
复现代码(无注释版)
import numpy as np from scipy.optimize import curve_fit def swap_model(x_in, X_eff, Y_eff): denominator = X_eff + x_in if np.isscalar(denominator): return (Y_eff * x_in) / (denominator if not np.isclose(denominator, 0) else 1e-9) else: denominator_copy = np.copy(denominator) denominator_copy[np.isclose(denominator_copy, 0)] = 1e-9 return (Y_eff * x_in) / denominator_copy bounds = ([1e-6, 1e-6], [np.inf, np.inf]) x_test_value = 6507.3125 print("--- Case 1: Poor Fit ---") x_data_bad = np.array([1, 2, 39000]) y_data_bad = np.array([8423.724335, 16846.531751, 319765062.090722]) y_actual_for_bad_case_test = 54311422.15982 try: popt_bad, _ = curve_fit(swap_model, x_data_bad, y_data_bad, bounds=bounds, maxfev=5000) X_eff_bad, Y_eff_bad = popt_bad print(f"Fitted (Bad): X_eff = {X_eff_bad:.4f}, Y_eff = {Y_eff_bad:.4f}") y_pred_bad = swap_model(x_test_value, X_eff_bad, Y_eff_bad) error_bad = abs(y_actual_for_bad_case_test - y_pred_bad) / y_actual_for_bad_case_test * 100 print(f"Predicted for {x_test_value:.4f}: {y_pred_bad:.4f}, Actual: {y_actual_for_bad_case_test:.4f}, Error: {error_bad:.2f}%") except RuntimeError as e: print(f"RuntimeError: {e}") except Exception as e: print(f"Other exception in bad fit: {e}") print("\n--- Case 2: Better Fit ---") x_data_good = np.array([1, 2, 32000]) y_data_good = np.array([8430.169107, 16859.464909, 264727159.854379]) y_actual_for_good_case_test = 54549399.392518 try: popt_good, _ = curve_fit(swap_model, x_data_good, y_data_good, bounds=bounds, maxfev=5000) X_eff_good, Y_eff_good = popt_good print(f"Fitted (Good): X_eff = {X_eff_good:,.4f}, Y_eff = {Y_eff_good:,.4f}") y_pred_good = swap_model(x_test_value, X_eff_good, Y_eff_good) error_good = abs(y_actual_for_good_case_test - y_pred_good) / y_actual_for_good_case_test * 100 print(f"Predicted for {x_test_value:.4f}: {y_pred_good:.4f}, Actual: {y_actual_for_good_case_test:.4f}, Error: {error_good:.2f}%") except RuntimeError as e: print(f"RuntimeError: {e}") except Exception as e: print(f"Other exception in good fit: {e}")
复现代码(带注释版)
# BUG DEMONSTRATION import numpy as np from scipy.optimize import curve_fit def swap_model(x_in, X_eff, Y_eff): denominator = X_eff + x_in # 避免除零,不过参数边界设置已经能起到一定作用 if np.isscalar(denominator): return (Y_eff * x_in) / (denominator if not np.isclose(denominator, 0) else 1e-9) else: # 处理数组输入 denominator_copy = np.copy(denominator) # 复制数组避免修改原输入 denominator_copy[np.isclose(denominator_copy, 0)] = 1e-9 return (Y_eff * x_in) / denominator_copy bounds = ([1e-6, 1e-6], [np.inf, np.inf]) # 参数必须为正数 # 用于预测测试的输入值 x_test_value = 6507.3125 print("--- Case 1: Poor Fit ---") x_data_bad = np.array([1, 2, 39000]) y_data_bad = np.array([8423.724335, 16846.531751, 319765062.090722]) # 该场景下x_test_value对应的实际输出值 y_actual_for_bad_case_test = 54311422.15982 try: popt_bad, _ = curve_fit(swap_model, x_data_bad, y_data_bad, bounds=bounds, maxfev=5000) X_eff_bad, Y_eff_bad = popt_bad print(f"Fitted (Bad): X_eff = {X_eff_bad:.4f}, Y_eff = {Y_eff_bad:.4f}") y_pred_bad = swap_model(x_test_value, X_eff_bad, Y_eff_bad) error_bad = abs(y_actual_for_bad_case_test - y_pred_bad) / y_actual_for_bad_case_test * 100 print(f"Predicted for {x_test_value:.4f}: {y_pred_bad:.4f}, Actual: {y_actual_for_bad_case_test:.4f}, Error: {error_bad:.2f}%") except RuntimeError as e: print(f"RuntimeError: {e}") except Exception as e: print(f"Other exception in bad fit: {e}") print("\n--- Case 2: Better Fit ---") x_data_good = np.array([1, 2, 32000]) y_data_good = np.array([8430.169107, 16859.464909, 264727159.854379]) # 该场景下x_test_value对应的实际输出值 y_actual_for_good_case_test = 54549399.392518 try: popt_good, _ = curve_fit(swap_model, x_data_good, y_data_good, bounds=bounds, maxfev=5000) X_eff_good, Y_eff_good = popt_good print(f"Fitted (Good): X_eff = {X_eff_good:,.4f}, Y_eff = {Y_eff_good:,.4f}") # 添加逗号提升可读性 y_pred_good = swap_model(x_test_value, X_eff_good, Y_eff_good) error_good = abs(y_actual_for_good_case_test - y_pred_good) / y_actual_for_good_case_test * 100 print(f"Predicted for {x_test_value:.4f}: {y_pred_good:.4f}, Actual: {y_actual_for_good_case_test:.4f}, Error: {error_good:.2f}%") except RuntimeError as e: print(f"RuntimeError: {e}") except Exception as e: print(f"Other exception in good fit: {e}")
拟合效果对比
- 有效拟合:

- 无效拟合:

内容的提问来源于stack exchange,提问作者notajoke
相关产品推荐
相关产品推荐

