You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python/Pandas技术问题:寻找AIC曲线的局部最优值(非全局最小)

寻找96附近的最优AIC阶数的Python实现方案

嘿,这个需求特别合理——有时候全局最优的阶数可能太过高阶(比如这里的192),反而带来过拟合风险,而相近AIC值的低阶模型(比如96附近)会更简洁实用。下面给你几种落地的实现思路:

方法1:直接限定区间找局部最小值

最简单直接的方式就是把搜索范围锁定在96的邻近区间(比如±20阶,你可以根据需求调整),然后在这个区间内找出AIC最小的阶数。

import pandas as pd

# 你已有的数据
dic_aic = {0: 16.83024400288158, 1: 10.580792750644934, ..., 192: 10.272853618268071}
aic_df = pd.DataFrame(dic_aic.items(), columns=['Order', 'AIC'])
aic_df = aic_df.set_index('Order')

# 定义96附近的搜索区间,比如80到112
target_range = range(80, 113)
# 筛选出区间内的数据
subset_aic = aic_df.loc[target_range]
# 找出区间内AIC最小的阶数
local_best_order = subset_aic['AIC'].idxmin()
local_min_aic = subset_aic['AIC'].min()

print(f"96附近的最优阶数:{local_best_order},对应的AIC值:{local_min_aic}")

方法2:平滑曲线后找局部极小值

如果原始AIC曲线有微小波动,你可以先对曲线做平滑处理,再寻找96附近的局部极小值点,这样结果更稳定。比如用滚动平均来平滑:

# 对AIC值做滚动平滑(窗口大小可以调整,比如5阶)
aic_df['Smoothed_AIC'] = aic_df['AIC'].rolling(window=5, center=True).mean()

# 寻找局部极小值:当前值小于左右相邻值
aic_df['Is_Local_Min'] = (aic_df['Smoothed_AIC'] < aic_df['Smoothed_AIC'].shift(1)) & \
                         (aic_df['Smoothed_AIC'] < aic_df['Smoothed_AIC'].shift(-1))

# 筛选出96附近的局部极小值点(比如±15阶)
local_mins = aic_df.loc[(aic_df.index >= 81) & (aic_df.index <= 111) & aic_df['Is_Local_Min']]

# 从这些局部极小值里挑出AIC最小的那个
if not local_mins.empty:
    best_local = local_mins['Smoothed_AIC'].idxmin()
    print(f"平滑后96附近的最优阶数:{best_local},平滑AIC值:{local_mins.loc[best_local, 'Smoothed_AIC']}")
else:
    print("96附近没有找到局部极小值,建议调整窗口大小或区间范围")

方法3:基于曲线变化率(积分/导数)选择最优阶数

如果想用积分的思路,本质是看AIC曲线在96附近的下降趋势:当阶数增加时,AIC下降的幅度越来越小,说明再增加阶数收益很低,这时候的阶数就是我们要找的“拐点”。

你可以计算AIC的一阶差分(也就是相邻阶数的AIC变化量),然后找变化量趋近于0的点(在96附近):

# 计算AIC的一阶差分(后一阶减当前阶,负数表示下降)
aic_df['AIC_Diff'] = aic_df['AIC'].diff()

# 找96附近,差分绝对值小于某个阈值(比如0.005)的点,且之后的差分变化不大
threshold = 0.005
candidates = aic_df.loc[(aic_df.index >= 85) & (aic_df.index <= 105)]
# 筛选出差分绝对值小于阈值的点
potential_orders = candidates[abs(candidates['AIC_Diff']) < threshold].index.tolist()

if potential_orders:
    # 从候选点里选最接近96的,或者AIC最小的
    best_order = min(potential_orders, key=lambda x: (abs(x-96), candidates.loc[x, 'AIC']))
    print(f"基于变化率的96附近最优阶数:{best_order},AIC值:{candidates.loc[best_order, 'AIC']}")
else:
    print("96附近没有找到符合阈值的阶数,建议调整阈值或区间")

另外,你也可以对差分曲线做积分,看累积的下降总量,当累积量不再明显增加时,对应的阶数就是合适的选择——不过对于这个场景,直接用差分已经足够直观了。


内容的提问来源于stack exchange,提问作者christianbauer1

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 13:02:46