Python中与auto.arima()相当的函数

88

我正在尝试使用ARIMA模型预测每周销售额。在statsmodels中,我找不到调整(p,d,q)顺序的函数。目前,R语言有一个名为forecast::auto.arima()的函数可以调整(p,d,q)参数。

我该如何选择合适的模型顺序?是否有Python库可供此目的使用?

10个回答

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)
    

确保使用finish=None调用brute

  1. 您可以从ARIMAResults中获取pvalues。因此,可以轻松实现一种类似于逐步向前算法的方法,其中模型的度数在添加参数的最低p值所在的维度上增加。

  2. 使用ARIMAResults.predict交叉验证备选模型。最好的方法是将时间序列的尾部(例如最近5%的数据)留出样本,并使用这些点来获得拟合模型的测试误差


19
现在主程序中已经有一个包装函数可以为你完成这个操作。http://statsmodels.sourceforge.net/devel/generated/statsmodels.tsa.stattools.arma_order_select_ic.html#statsmodels.tsa.stattools.arma_order_select_ic 目前它是我们最接近auto.arima的选择了。 - jseabold
3
@jseabold,您熟悉源代码,但名称表明它是arma而不是arima。 - behzad.nouri
1
是的,它仅用于订单选择。目前还没有自动检查集成功能。 - jseabold
5
没关系,对于那些也感到困惑的人来说,“exog/endog”是正在拟合的数据。Brute会自动将它的第二个参数用作函数的第一个参数,然后按照列表中列出的顺序使用其他参数。 - alksdjg
2
ARIMA(带有积分)的订单选择似乎现在可用 - schneiderfelipe
显示剩余3条评论

34

该库的文档可以在此处查阅:http://pyramid-arima.readthedocs.io/en/latest/index.html - lbcommer
1
只是提供信息,Python自动ARIMA已经移至pmdarima:https://github.com/tgsmith61591/pmdarima。这么做的原因可能是为了避免与另一个同名的更流行的库产生冲突。 - Jonno_FTW

4
最简单的方法是使用Nixtla的auto_arima模型,通过statsforecast包(https://github.com/Nixtla/statsforecast)来实现。它是forecast::auto.arima函数的镜像实现,使用numba进行优化。它具有更好的性能,并且比R和pmdarima实现更快。
只需使用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

这里有一个包含示例的笔记本

很遗憾,你所宣传的笔记本已经下架了。 - Winston Lee
谢谢,这是更新后的链接:https://nixtla.github.io/statsforecast/examples/getting_started_short.html - fede garza
谢谢,这是更新后的链接:https://nixtla.github.io/statsforecast/examples/getting_started_short.html - undefined

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模型。

3
旧的线程,但这可能不是选择d的最佳方法。传统上,这是通过使用单位根检验(如KPSS测试)来完成的。 - Adam
1
请注意,此代码仅从此处复制,并侵犯了该网站的版权。 - swineone

3

3

我编写了这些实用函数来直接计算PDQ值。 get_PDQ_parallel需要三个输入参数。其中,data是一个带时间戳(datetime)索引的系列数据;n_jobs提供并行处理器的数量;输出将是一个包含aic和bic值的数据框,其中order=(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']) 

2
可能的解决方案
df=pd.read_csv("http://vincentarelbundock.github.io/Rdatasets/csv/datasets/AirPassengers.csv")

# Define the p, d and q parameters to take any value between 0 and 2
p = d = q = range(0, 2)
print(p)


import itertools
import warnings

# Generate all different combinations of p, q and q triplets
pdq = list(itertools.product(p, d, q))
print(pdq)

# Generate all different combinations of seasonal p, q and q triplets
seasonal_pdq = [(x[0], x[1], x[2], 12) for x in list(itertools.product(p, d, q))]

print('Examples of parameter combinations for Seasonal ARIMA...')
print('SARIMAX: {} x {}'.format(pdq[1], seasonal_pdq[1]))
print('SARIMAX: {} x {}'.format(pdq[1], seasonal_pdq[2]))
print('SARIMAX: {} x {}'.format(pdq[2], seasonal_pdq[3]))
print('SARIMAX: {} x {}'.format(pdq[2], seasonal_pdq[4]))
Examples of parameter combinations for Seasonal ARIMA...
SARIMAX: (0, 0, 1) x (0, 0, 1, 12)
SARIMAX: (0, 0, 1) x (0, 1, 0, 12)
SARIMAX: (0, 1, 0) x (0, 1, 1, 12)
SARIMAX: (0, 1, 0) x (1, 0, 0, 12)

y=df

#warnings.filterwarnings("ignore") # specify to ignore warning messages

for param in pdq:
    for param_seasonal in seasonal_pdq:
        try:
            mod = sm.tsa.statespace.SARIMAX(y,
                                            order=param,
                                            seasonal_order=param_seasonal,
                                            enforce_stationarity=False,
                                            enforce_invertibility=False)

            results = mod.fit()

            print('ARIMA{}x{}12 - AIC:{}'.format(param, param_seasonal, results.aic))
        except:
            continue
ARIMA(0, 0, 0)x(0, 0, 1, 12)12 - AIC:3618.0303991426763
ARIMA(0, 0, 0)x(0, 1, 1, 12)12 - AIC:2824.7439963684233
ARIMA(0, 0, 0)x(1, 0, 0, 12)12 - AIC:2942.2733127230185
ARIMA(0, 0, 0)x(1, 0, 1, 12)12 - AIC:2922.178151133141
ARIMA(0, 0, 0)x(1, 1, 0, 12)12 - AIC:2767.105066400224
ARIMA(0, 0, 0)x(1, 1, 1, 12)12 - AIC:2691.233398643673
ARIMA(0, 0, 1)x(0, 0, 0, 12)12 - AIC:3890.816777796087
ARIMA(0, 0, 1)x(0, 0, 1, 12)12 - AIC:3541.1171286722
ARIMA(0, 0, 1)x(0, 1, 0, 12)12 - AIC:3028.8377323188824
ARIMA(0, 0, 1)x(0, 1, 1, 12)12 - AIC:2746.77973129136
ARIMA(0, 0, 1)x(1, 0, 0, 12)12 - AIC:3583.523640623017
ARIMA(0, 0, 1)x(1, 0, 1, 12)12 - AIC:3531.2937768990187
ARIMA(0, 0, 1)x(1, 1, 0, 12)12 - AIC:2781.198675746594
ARIMA(0, 0, 1)x(1, 1, 1, 12)12 - AIC:2720.7023088205974
ARIMA(0, 1, 0)x(0, 0, 1, 12)12 - AIC:3029.089945668332
ARIMA(0, 1, 0)x(0, 1, 1, 12)12 - AIC:2568.2832251221016
ARIMA(0, 1, 0)x(1, 0, 0, 12)12 - AIC:2841.315781459511
ARIMA(0, 1, 0)x(1, 0, 1, 12)12 - AIC:2815.4011044132576
ARIMA(0, 1, 0)x(1, 1, 0, 12)12 - AIC:2588.533386513587
ARIMA(0, 1, 0)x(1, 1, 1, 12)12 - AIC:2569.9453272483315
ARIMA(0, 1, 1)x(0, 0, 0, 12)12 - AIC:3327.5177587522303
ARIMA(0, 1, 1)x(0, 0, 1, 12)12 - AIC:2984.716706112334
ARIMA(0, 1, 1)x(0, 1, 0, 12)12 - AIC:2789.128542154043
ARIMA(0, 1, 1)x(0, 1, 1, 12)12 - AIC:2537.0293659293943
ARIMA(0, 1, 1)x(1, 0, 0, 12)12 - AIC:2984.4555708516436
ARIMA(0, 1, 1)x(1, 0, 1, 12)12 - AIC:2939.460958374472
ARIMA(0, 1, 1)x(1, 1, 0, 12)12 - AIC:2578.7862352774437
ARIMA(0, 1, 1)x(1, 1, 1, 12)12 - AIC:2537.771484229265
ARIMA(1, 0, 0)x(0, 0, 0, 12)12 - AIC:3391.5248913820797
ARIMA(1, 0, 0)x(0, 0, 1, 12)12 - AIC:3038.142074281268
C:\Users\Dell\Anaconda3\lib\site-packages\statsmodels\base\model.py:496: ConvergenceWarning: Maximum Likelihood optimization failed to converge. Check mle_retvals
  "Check mle_retvals", ConvergenceWarning)
ARIMA(1, 0, 0)x(0, 1, 0, 12)12 - AIC:2839.809192263449
ARIMA(1, 0, 0)x(0, 1, 1, 12)12 - AIC:2588.50367175184
ARIMA(1, 0, 0)x(1, 0, 0, 12)12 - AIC:2993.4630440139595
ARIMA(1, 0, 0)x(1, 0, 1, 12)12 - AIC:2995.049216326931
ARIMA(1, 0, 0)x(1, 1, 0, 12)12 - AIC:2588.2463284315304
ARIMA(1, 0, 0)x(1, 1, 1, 12)12 - AIC:2592.80110502723
ARIMA(1, 0, 1)x(0, 0, 0, 12)12 - AIC:3352.0350133621478
ARIMA(1, 0, 1)x(0, 0, 1, 12)12 - AIC:3006.5493366627807
ARIMA(1, 0, 1)x(0, 1, 0, 12)12 - AIC:2810.6423724894516
ARIMA(1, 0, 1)x(0, 1, 1, 12)12 - AIC:2559.584031948852
ARIMA(1, 0, 1)x(1, 0, 0, 12)12 - AIC:2981.2250436794675
ARIMA(1, 0, 1)x(1, 0, 1, 12)12 - AIC:2959.3142304724834
ARIMA(1, 0, 1)x(1, 1, 0, 12)12 - AIC:2579.8245645892207
ARIMA(1, 0, 1)x(1, 1, 1, 12)12 - AIC:2563.13922589258
ARIMA(1, 1, 0)x(0, 0, 0, 12)12 - AIC:3354.7462930846423
ARIMA(1, 1, 0)x(0, 0, 1, 12)12 - AIC:3006.702997636003
ARIMA(1, 1, 0)x(0, 1, 0, 12)12 - AIC:2809.3844175191666
ARIMA(1, 1, 0)x(0, 1, 1, 12)12 - AIC:2558.484602766447
ARIMA(1, 1, 0)x(1, 0, 0, 12)12 - AIC:2959.885810636943
ARIMA(1, 1, 0)x(1, 0, 1, 12)12 - AIC:2960.712709764296
ARIMA(1, 1, 0)x(1, 1, 0, 12)12 - AIC:2557.945907092698
ARIMA(1, 1, 0)x(1, 1, 1, 12)12 - AIC:2559.274166458508
ARIMA(1, 1, 1)x(0, 0, 0, 12)12 - AIC:3326.3285511700374
ARIMA(1, 1, 1)x(0, 0, 1, 12)12 - AIC:2985.868532151721
ARIMA(1, 1, 1)x(0, 1, 0, 12)12 - AIC:2790.7677149967103
ARIMA(1, 1, 1)x(0, 1, 1, 12)12 - AIC:2538.820635541546
ARIMA(1, 1, 1)x(1, 0, 0, 12)12 - AIC:2963.2789505804294
ARIMA(1, 1, 1)x(1, 0, 1, 12)12 - AIC:2941.2436984747465
ARIMA(1, 1, 1)x(1, 1, 0, 12)12 - AIC:2559.8258191422606
ARIMA(1, 1, 1)x(1, 1, 1, 12)12 - AIC:2539.712354465328

来自https://www.digitalocean.com/community/tutorials/a-guide-to-time-series-forecasting-with-arima-in-python-3,同时也可以看看https://github.com/decisionstats/pythonfordatascience/blob/master/time%2Bseries%20(1).ipynb

1
在conda中,使用conda install -c saravji pmdarima进行安装。
用户saravji已将其放置在anaconda云中。
然后使用:
from pmdarima.arima import auto_arima

(请注意,名称pyramid-arima已更改为pmdarima。)

0

RAPIDS cuML机器学习库具有auto-ARIMA函数

从链接的文档中:

实现了批量自动ARIMA模型,用于样本内和样本外时间序列预测。

此接口提供高度可定制的搜索功能,类似于R中的forecastfable包。它提供了一个抽象,围绕基础ARIMA模型进行预测和预测,就像使用单个模型一样。

一些示例代码:

from cuml.tsa.auto_arima import AutoARIMA


model = AutoARIMA(y)
model.search(s=12, d=(0, 1), D=(0, 1), p=(0, 2, 4), q=(0, 2, 4),
             P=range(2), Q=range(2), method="css", truncate=100)
model.fit(method="css-ml")
fc = model.forecast(20)

这里有一个笔记本电脑,其中有一个更详细的cuML ARIMA示例。

cuML库需要支持的NVIDIA GPU(以及适当的驱动程序和CUDA安装),因此应该速度很快。


0

实际上

def objfunc(order,*params ):    
    from statsmodels.tsa.arima_model import ARIMA   
    p,d,q = order   
    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=params, finish=None)

3
虽然这段代码片段可能解决了问题,但包括解释真的有助于提高您的帖子质量。请记住,您正在为未来的读者回答问题,而这些人可能不知道您的代码建议原因。请尽量不要在代码中添加过多的解释性注释,这会降低代码和解释的可读性! - Martin Tournoij

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接