利用curve_fit拟合幂律曲线时镜像异常的原因及修正方法
双对数图幂律拟合出现Y轴镜像的原因及修正方法
兄弟,你的问题根本不是curve_fit用错了,而是绘制拟合曲线时的参数传反了!
问题根源
看你代码里的这一行:
plt.plot(index_list, power_law(freq_list, *popt))
你把freq_list(也就是原始数据的Y值)当成了幂律函数的输入自变量x,但实际上幂律模型a*x^(-b)的自变量应该是index_list(原始数据的X轴索引)。把Y值当成X代入计算,相当于强行交换了X和Y的角色,结果自然就出现了镜像/扭曲的曲线。
修正方法
只需要把拟合曲线的绘制代码改成用index_list作为power_law的输入即可,同时可以优化细节让图表更清晰:
import numpy as np import matplotlib.pyplot as plt from scipy.optimize import curve_fit f = open("input.txt", "r") index_list = [] freq_list = [] index = 0 for line in f: split_line = line.split() freq_list.append(int(split_line[1])) index_list.append(index) index += 1 # 转成numpy数组,让curve_fit运算更稳定 index_array = np.array(index_list) freq_array = np.array(freq_list) # 绘制原始数据双对数图 plt.loglog(index_array, freq_array, label="原始数据") def power_law(x, a, b): return a * np.power(x, -b) # 执行拟合 popt, pcov = curve_fit(power_law, index_array, freq_array) # 用正确的自变量index_array计算拟合曲线 plt.loglog(index_array, power_law(index_array, *popt), 'r--', label=f"拟合曲线: a={popt[0]:.2f}, b={popt[1]:.2f}") plt.legend() plt.xlabel("Index") plt.ylabel("Frequency") plt.show()
额外优化建议
- 把列表转成numpy数组给
curve_fit,运算效率更高,也能避免潜在的列表运算问题 - 给曲线加图例、坐标轴标签,让图表可读性更强
- 如果拟合收敛效果不好,可以给
curve_fit加初始参数p0,比如p0=[np.max(freq_array), 1],帮助算法更快锁定最优解
内容的提问来源于stack exchange,提问作者StijnVanDijk




