使用 Python 训练 arima 模型时如何解决 LinAlgError 和 ValueError

Posted

技术标签:

【中文标题】使用 Python 训练 arima 模型时如何解决 LinAlgError 和 ValueError【英文标题】:how to solve LinAlgError & ValueError when training arima model with Python 【发布时间】:2019-08-02 05:49:19 【问题描述】:

我正在尝试实现一个时间序列模型并得到一些奇怪的异常,这些异常对我没有任何意义。我想知道我是否犯了一个错误,或者这是完全可以预料的。细节来了……

在训练我的模型时,我尝试进行网格搜索以找到最佳 (p, d, q) 设置。这是完整的代码(我将在下面解释这里发生的事情):

下面的reproducible代码本质上是从https://machinelearningmastery.com/grid-search-arima-hyperparameters-with-python/复制的,有一些细微的变化...:

import warnings
from pandas import Series
from statsmodels.tsa.arima_model import ARIMA
from sklearn.metrics import mean_squared_error

# evaluate an ARIMA model for a given order (p,d,q)
def evaluate_arima_model(X, arima_order):
    # prepare training dataset
    train_size = int(len(X) * 0.66)
    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('float64')
    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:
                    print("Evaluating the settings: ", p, d, q)
                    mse = evaluate_arima_model(dataset, order)
                    if mse < best_score:
                        best_score, best_cfg = mse, order
                    print('ARIMA%s MSE=%.3f' % (order,mse))
                except Exception as exception:
                    print("Exception occured...", type(exception).__name__, "\n", exception)

    print('Best ARIMA%s MSE=%.3f' % (best_cfg, best_score))

# dataset
values = np.array([-1.45, -9.04, -3.64, -10.37, -1.36, -6.83, -6.01, -3.84, -9.92, -5.21,
                   -8.97, -6.19, -4.12, -11.03, -2.27, -4.07, -5.08, -4.57, -7.87, -2.80,
                   -4.29, -4.19, -3.76, -22.54, -5.87, -6.39, -4.19, -2.63, -8.70, -3.52, 
                   -5.76, -1.41, -6.94, -12.95, -8.64, -7.21, -4.05, -3.01])

# evaluate parameters
p_values = [7, 8, 9, 10]
d_values = range(0, 3)
q_values = range(0, 3)
warnings.filterwarnings("ignore")
evaluate_models(values, p_values, d_values, q_values)

这是输出(不是所有内容,但它提供了足够的信息):

Evaluating the settings:  7 0 0
Exception occured... LinAlgError 
 SVD did not converge
Evaluating the settings:  7 0 1
Exception occured... LinAlgError 
 SVD did not converge
Evaluating the settings:  7 0 2
Exception occured... ValueError 
 The computed initial AR coefficients are not stationary
You should induce stationarity, choose a different model order, or you can
pass your own start_params.
Evaluating the settings:  7 1 0
Exception occured... LinAlgError 
 SVD did not converge
Evaluating the settings:  7 1 1
Exception occured... ValueError 
 The computed initial AR coefficients are not stationary
You should induce stationarity, choose a different model order, or you can
pass your own start_params.
Evaluating the settings:  7 1 2
Exception occured... ValueError 
 The computed initial AR coefficients are not stationary
You should induce stationarity, choose a different model order, or you can
pass your own start_params.
Evaluating the settings:  7 2 0
Exception occured... LinAlgError 
 SVD did not converge
Evaluating the settings:  7 2 1
Exception occured... ValueError 
 The computed initial AR coefficients are not stationary
You should induce stationarity, choose a different model order, or you can
pass your own start_params.
Evaluating the settings:  7 2 2
Exception occured... ValueError 
 The computed initial AR coefficients are not stationary
You should induce stationarity, choose a different model order, or you can
pass your own start_params.

代码只是简单地尝试所有不同的给定设置,训练模型,计算每个给定设置的 MSE(均方误差),然后选择最好的一个(基于最小 MSE)。

但是在训练过程中,代码不断抛出LinAlgErrorValueError 异常,这对我没有任何意义。

据我所知,当抛出这些异常时,代码并没有真正训练某些设置,然后只是跳转到将要尝试的下一个设置。

为什么我会看到这些异常? 他们可以被忽略吗? 我需要做什么来解决它?

【问题讨论】:

【参考方案1】:

首先,回答您的具体问题:我认为“SVD 未收敛”是 Statsmodels 的 ARIMA 模型中的一个错误。如今,SARIMAX 模型得到了更好的支持(并且 ARIMA 模型所做的一切都做得更好),所以我建议改用它。为此,请将模型创建替换为:

model = sm.tsa.SARIMAX(history, trend='c', order=arima_order, enforce_stationarity=False, enforce_invertibility=False)

话虽如此,我认为鉴于您的时间序列和您正在尝试的规范,您仍然不太可能获得好的结果。

特别是,您的时间序列非常短,而且您只考虑极长的自回归滞后长度 (p > 6)。用这么少的数据点估计这么多参数是很困难的,特别是当你也有积分(d = 1 或 d = 2)并且你还添加了移动平均分量时。我建议您重新评估您正在考虑的模型。

【讨论】:

感谢您的回答。在我接受答案之前现在正在研究它。 ARIMA 模型的预测函数甚至返回置信区间,为了简单起见,我在上面没有提到。使用 SARIMAX 进行预测时如何计算置信区间?此外,通过更改可能的 p、d、q 值,我仍然可以进行网格搜索,对吧? (这些统计模型真的不是我的专长..) 是的,您可以从结果对象中获取置信区间,使用fcast_res = res.get_forecast() 后跟ci = fcast_res.conf_int(),而实际预测为fcast = fcast_res.predicted_mean。是的,您仍然可以进行网格搜索。 SARIMAX 只是一个 ARIMA 模型,如果需要,还可以选择添加 (S) 季节性项和 e(X) 生成回归量。 谢谢!最后一个问题.. 我的数据集有大量数字。 (例如:-6.1e+10)我偶尔会在训练期间看到“ValueError Input contains NaN、infinity or a value too large for dtype('float64')”'。我可以使用 sklearn.preprocessing.StandardScaler 标准化数据集。使用“fit”和“transform”函数,可以进行归一化。但随后计算的置信区间将基于标准化数据集(数字太小)。要对数据集(甚至是预测)进行反规范化,我可以调用 inverse_transform 函数,但如何解决 conf 的相同问题。采访? 不幸的是,没有直接的方法来转换置信区间。您可以选择许多方向,但没有一个是内置的(例如,一种称为 delta 方法或模拟的近似技术)。例如,请参阅 stats.stackexchange.com/questions/1713 以了解其中一些问题的讨论。

以上是关于使用 Python 训练 arima 模型时如何解决 LinAlgError 和 ValueError的主要内容,如果未能解决你的问题,请参考以下文章

如何跳过 ARIMA 模型(python)中的第一个滞后 N 天?

Python statsmodels ARIMA 预测

使用 statsmodels.tsa 返回训练集预测值

arima模型python 怎么看平稳性

Python/Pandas - 如何调整 auto_arima 模型参数以获得未来预测

ARIMA模型用于某些滞后