使用lmfit与scipy.curve_fit拟合对数曲线失败求助
投票数与认可指数的对数曲线拟合问题排查
问题背景
使用《终极电影统计数据集》分析时,发现投票数(x轴)与认可指数(y轴)存在对数关系,但用scipy.curve_fit和lmfit拟合时,要么得到错误的拟合曲线,要么抛出真值错误。代入在线工具得到的拟合方程y = 0.986203*np.log(12.6695*x + 64567.3) - 8.30291作为初始参数仍无效。
原代码中的核心问题
- 未定义变量:代码中使用
newdf但未初始化,应替换为读取后的df - 模型函数定义错误:
scipy.curve_fit使用的logfunction仅包含a*np.log(b*x),与实际需要的带常数偏移的对数模型不符lmfit的函数未将拟合参数作为输入参数,而是直接引用全局变量,导致拟合时无法识别参数
- 语法错误:第二次
lmfit尝试中,函数返回语句写为return y = ...,属于非法赋值语法 - 数据未预处理:未检查/过滤投票数为0的行,会导致
np.log(0)引发数值错误 - 初始参数设置不合理:部分拟合尝试未提供接近真实值的初始参数,导致优化算法收敛失败
修正后的代码示例
1. 数据预处理与基础准备
import pandas as pd import numpy as np import matplotlib.pyplot as plt from scipy.optimize import curve_fit from lmfit import Model # 读取数据并预处理 df = pd.read_csv('movie_statistic_dataset.csv') # 替换未定义的newdf为df,过滤投票数为0的行避免log报错 data = df[['movie_numerOfVotes','approval_Index']].query('movie_numerOfVotes > 0').reset_index(drop=True) data.columns = ['Votes','Approval'] X = data['Votes'].values Y = data['Approval'].values
2. 使用scipy.curve_fit拟合
# 定义与在线工具一致的对数模型 def log_model(x, a, b, c, d): return a * np.log(b * x + c) - d # 传入在线工具得到的初始参数,提升拟合收敛效率 initial_params = [0.986, 12.67, 64567, 8.303] popt, pcov = curve_fit(log_model, X, Y, p0=initial_params) # 生成拟合预测值 y_pred = log_model(X, *popt) # 可视化对比 plt.scatter(X, Y, label='原始数据', alpha=0.5) plt.plot(X, y_pred, color='red', label='拟合曲线') plt.xlabel('投票数') plt.ylabel('认可指数') plt.legend() plt.show() print(f"拟合参数:a={popt[0]:.4f}, b={popt[1]:.4f}, c={popt[2]:.0f}, d={popt[3]:.4f}")
3. 使用lmfit拟合
# 正确定义模型函数(参数作为输入) def lm_log_model(x, a, b, c, d): return a * np.log(b * x + c) - d # 创建模型并设置初始参数 mod = Model(lm_log_model) params = mod.make_params(a=0.986, b=12.67, c=64567, d=8.303) # 执行拟合 result = mod.fit(Y, params=params, x=X) # 输出拟合报告 print(result.fit_report()) # 可视化 plt.scatter(X, Y, label='原始数据', alpha=0.5) plt.plot(X, result.best_fit, color='green', label='LM拟合曲线') plt.xlabel('投票数') plt.ylabel('认可指数') plt.legend() plt.show()
关键注意事项
- 初始参数的重要性:对数模型属于非线性拟合,初始参数接近真实值能大幅提升算法收敛成功率
- 数据校验:必须确保输入x(投票数)无0值或负数,避免对数运算抛出数值错误
- 函数定义规范:lmfit要求模型函数将所有待拟合参数作为输入参数,不能使用全局变量
内容的提问来源于stack exchange,提问作者Chirag Mohnani
相关产品推荐
相关产品推荐

