如何使用curve_fit为DataFrame数据做幂律拟合并绘制正确曲线
问题原因
你的代码拟合失败来自三个核心错误:
- 单位理解错误:表中
rcs列是dBsm(分贝平方米)的对数域数值,不是线性域RCS。雷达方程中线性域RCS和距离四次方成正比,但dB域下该关系为对数线性形式,直接用线性值套a*range^4公式完全不匹配。 - 拟合参数错误:幂律拟合对初始参数敏感度极高,
curve_fit默认初始参数为1,对你这种数值量级跨度大的场景会直接收敛到局部最优,得到完全错误的拟合结果。 - 绘图逻辑错误:一方面你拟合的是
rcs = f(range),即range为自变量、rcs为因变量,但绘图时把rcs放在x轴、range放在y轴,坐标轴对应关系完全颠倒;另一方面直接用原始离散的range点绘图,没有生成连续密集的插值序列,画出来的自然是折线段而非平滑曲线。
正确实现方案
你可以选择两种方式完成拟合,两种结果完全一致:
方案1:线性域幂律拟合
先把dB单位的rcs转换为线性值,设置合理初始参数完成拟合,再生成连续序列绘制平滑曲线:
import numpy as np import pandas as pd import matplotlib.pyplot as plt from scipy.optimize import curve_fit # 加载你的数据 df = pd.DataFrame({ 'rcs': [-40,-35,-30,-25,-20,-15,-10,-5,0,5], 'range': [12.9,14.9,22.9,35.44,43.48,62.4,92.4,132.99,182.6,252.99] }) # 定义四次幂律函数(线性域) def power_law(x, a): return a * np.power(x, 4) x = df['range'].values # 关键转换:dB转线性RCS y_linear = 10 ** (df['rcs'].values / 10) # 用第一个点估算初始参数a,避免拟合收敛到错误值 a_init = y_linear[0] / (x[0] ** 4) pop, _ = curve_fit(power_law, x, y_linear, p0=[a_init]) a_fit = pop[0] # 生成200个连续点用于绘制平滑曲线 x_smooth = np.linspace(x.min(), x.max(), 200) y_smooth = power_law(x_smooth, a_fit) # 绘图 plt.figure(figsize=(8,5)) plt.scatter(x, df['rcs'].values, label='原始散点', color='tab:blue') # 拟合结果转回dB单位和原始散点对齐 plt.plot(x_smooth, 10*np.log10(y_smooth), color='red', label=f'拟合曲线: σ(线性) = {a_fit:.2e} * R^4') plt.xlabel('range') plt.ylabel('rcs (dBsm)') plt.legend() plt.grid(alpha=0.3) plt.show()
方案2:dB域线性拟合(雷达数据处理常规方案)
dB域下四次方关系转换为线性形式:rcs_dB = 40*log10(range) + b,不需要非线性最小二乘,直接计算截距即可,拟合结果更稳定:
x = df['range'].values y_dB = df['rcs'].values x_log = np.log10(x) # 斜率固定为40,直接计算平均截距 b_fit = (y_dB - 40 * x_log).mean() # 生成平滑曲线点 x_smooth = np.linspace(x.min(), x.max(), 200) y_smooth_dB = 40 * np.log10(x_smooth) + b_fit # 绘图 plt.figure(figsize=(8,5)) plt.scatter(x, y_dB, label='原始散点', color='tab:blue') plt.plot(x_smooth, y_smooth_dB, color='red', label=f'拟合曲线: rcs(dB) = 40*log10(R) + {b_fit:.2f}') plt.xlabel('range') plt.ylabel('rcs (dBsm)') plt.legend() plt.grid(alpha=0.3) plt.show()
原代码问题对应说明
- 多项式拟合曲线不平滑:直接传入10个离散的原始range点绘图,连接后为折线,必须用
np.linspace生成密集连续的x序列才能得到平滑曲线。 - 幂律拟合线不穿过散点:未做dB到线性值的单位转换,且未设置合理初始参数,拟合完全不收敛到正确结果。
- 曲线起点不匹配:坐标轴对应关系颠倒,拟合和绘图的自变量、因变量没有对齐。
内容的提问来源于stack exchange,提问作者Mageo
相关产品推荐
相关产品推荐

