Python中auto.arima()的等效函数

88 投票
10 回答
97087 浏览
提问于 2025-04-18 00:43

我正在尝试用ARIMA模型来预测每周的销售情况。可是我找不到一个可以调整(p,d,q)顺序的函数,statsmodels这个库里没有。目前,R语言有一个函数叫forecast::auto.arima(),可以自动调整(p,d,q)这些参数。

我该如何选择适合我模型的顺序呢?在Python中有没有类似的库可以用来做这个?

10 个回答

3

我写了这些工具函数,可以直接计算pdq值。get_PDQ_parallel这个函数需要三个输入数据,这些数据是以时间戳(日期时间)为索引的序列。n_jobs参数用来指定并行处理器的数量。输出结果将是一个数据框,里面包含了aic和bic值,索引是(P,D,Q)的顺序。p和q的范围是[0,12],而d的范围是[0,1]。

import statsmodels 
from statsmodels import api as sm
from sklearn.metrics import r2_score,mean_squared_error
from sklearn.utils import check_array
from functools import partial
from multiprocessing import Pool
def get_aic_bic(order,series):
    aic=np.nan
    bic=np.nan
    #print(series.shape,order)
    try:
        arima_mod=statsmodels.tsa.arima_model.ARIMA(series,order=order,freq='H').fit(transparams=True,method='css')
        aic=arima_mod.aic
        bic=arima_mod.bic
        print(order,aic,bic)
    except:
        pass
    return aic,bic

def get_PDQ_parallel(data,n_jobs=7):
    p_val=13
    q_val=13
    d_vals=2
    pdq_vals=[ (p,d,q) for p in range(p_val) for d in range(d_vals) for q in range(q_val)]
    get_aic_bic_partial=partial(get_aic_bic,series=data)
    p = Pool(n_jobs)
    res=p.map(get_aic_bic_partial, pdq_vals)  
    p.close()
    return pd.DataFrame(res,index=pdq_vals,columns=['aic','bic']) 
4
def evaluate_arima_model(X, arima_order):
    # prepare training dataset
    train_size = int(len(X) * 0.90)
    train, test = X[0:train_size], X[train_size:]
    history = [x for x in train]
    # make predictions
    predictions = list()
    for t in range(len(test)):
        model = ARIMA(history, order=arima_order)
        model_fit = model.fit(disp=0)
        yhat = model_fit.forecast()[0]
        predictions.append(yhat)
        history.append(test[t])
    # calculate out of sample error
    error = mean_squared_error(test, predictions)
    return error

# evaluate combinations of p, d and q values for an ARIMA model
def evaluate_models(dataset, p_values, d_values, q_values):
    dataset = dataset.astype('float32')
    best_score, best_cfg = float("inf"), None
    for p in p_values:
        for d in d_values:
            for q in q_values:
                order = (p,d,q)
                try:
                    mse = evaluate_arima_model(dataset, order)
                    if mse < best_score:
                        best_score, best_cfg = mse, order
                    print('ARIMA%s MSE=%.3f' % (order,mse))
                except:
                    continue
    print('Best ARIMA%s MSE=%.3f' % (best_cfg, best_score))

# load dataset
def parser(x):
    return datetime.strptime('190'+x, '%Y-%m')



import datetime
p_values = [4,5,6,7,8]
d_values = [0,1,2]
q_values = [2,3,4,5,6]
warnings.filterwarnings("ignore")
evaluate_models(train, p_values, d_values, q_values)

这段话的意思是,这个方法会给你 p、d、q 这三个值,然后你可以用这些值来建立你的 ARIMA 模型。

5

最简单的方法是通过 Nixtla 的 auto_arima 模型,使用 statsforecast 这个包来实现。这个包的功能和 R 语言里的 forecast::auto.arima 函数是一样的,但它经过了 numba 的优化,所以运行得更快,性能更好,比 R 和 pmdarima 的实现要强。

你只需要用 pip 安装这个库,命令是 pip install statsforecast。然后,

from statsforecast.core import StatsForecast
from statsforecast.models import auto_arima

fcst = StatsForecast(
     df, #your data 
     models=[auto_arima], 
     freq='W', # frequency of your data
     n_jobs=7, # you can also define the number of cores used for parallelizing

)
forecasts = fcst.forecast(12) #your horizon

这里有一个 示例笔记本,里面有很多例子。

34

现在有一个专门的Python包可以用来自动进行ARIMA模型的分析。你可以在这里找到它:https://github.com/tgsmith61591/pmdarima

文档说明在这里: http://alkaline-ml.com/pmdarima

使用示例可以查看这里:https://github.com/tgsmith61591/pmdarima/blob/master/examples/quick_start_example.ipynb

83

你可以尝试几种方法:

  1. ARIMAResults 包含 aicbic。根据它们的定义(可以查看 这里这里),这些标准会对模型中的参数数量进行惩罚。因此,你可以用这些数字来比较不同的模型。此外,scipy 还提供了 optimize.brute,它可以在指定的参数空间中进行网格搜索。所以你可以按照这样的流程进行:

     def objfunc(order, exog, endog):
         from statsmodels.tsa.arima.model import ARIMA
         fit = ARIMA(endog, order, exog).fit()
         return fit.aic()
    
     from scipy.optimize import brute
     grid = (slice(1, 3, 1), slice(1, 3, 1), slice(1, 3, 1))
     brute(objfunc, grid, args=(exog, endog), finish=None)
    

确保在调用 brute 时使用 finish=None

  1. 你可以从 ARIMAResults 中获取 pvalues。这样就可以很容易地实现一种逐步算法,根据增加的参数获得最低的 p 值来逐步增加模型的复杂度。

  2. 使用 ARIMAResults.predict 来交叉验证不同的模型。最好的方法是将时间序列的尾部(比如最近的 5% 数据)留作测试样本,然后用这些数据来计算拟合模型的 测试误差

撰写回答