使用SciPy curve_fit实现对数回归却拟合出直线的问题
问题原因与解决办法
核心问题
你用mdates.date2num(x)将日期转换为数值后,这类数值通常是极大的整数(比如代表从1970年起始的天数,动辄上万),对超大数值取对数后,相邻日期的log值差异极小,最终拟合曲线趋近于直线。另外,curve_fit默认初始参数[1,1]不适用于对数模型,容易导致拟合结果偏离预期。
解决步骤
1. 对日期x做缩放处理
将日期转换为相对天数(以数据中第一个日期为基准,计算后续日期与它的差值),缩小x的取值范围,让log(x)的变化更明显:
# 替换原x处理逻辑 x_days = (x - x.min()).dt.days + 1 # 加1避免出现log(0)的报错
2. 给curve_fit指定初始参数
手动设置初始参数p0,引导拟合算法找到更优解,而非依赖默认值:
log_popt, log_pcov = curve_fit(log_func, x_days, y, p0=[y.mean(), 1])
3. 修改后的完整代码
def plotVideoPerformance(df): plt.figure(figsize=(10,5)) # Data Points x = df['period'] # 确保period是datetime类型,非则先转换 if not pd.api.types.is_datetime64_any_dtype(x): df['period'] = pd.to_datetime(df['period']) x = df['period'] y = df['estimated_revenue_total'] title = df['title'].unique() # 转换为相对天数,优化log计算的数值范围 x_days = (x - x.min()).dt.days + 1 # Regression Functions def log_func(x,a,b): return a + b * np.log(x) # 设置初始参数,提升拟合精度 log_popt, log_pcov = curve_fit(log_func, x_days, y, p0=[y.mean(), 1]) log_params = f"a=%.2f,b=%.2f" % tuple(log_popt) log_reg = log_func(x_days, *log_popt) plt.scatter(x, y) plt.plot(x, log_reg, 'b', label=log_params) plt.legend() plt.title(title[0]) plt.show()
额外检查点
- 若数据本身的趋势接近线性,对数回归结果自然会趋近直线,此时需重新评估模型是否匹配数据特征
内容的提问来源于stack exchange,提问作者JieudenCuben
相关产品推荐
相关产品推荐

