ARMA statsmodel застряла на одном предсказании при итерации на разных временных сериях

Я сделал модель ARMA, чтобы предсказать серию продаж некоторых вещей в разных магазинах. Для каждой временной серии, если есть данные, она тестирует и сохраняет модель с лучшей Akaike Information Critera. Тем не менее, она всегда дает одни и те же результаты, поэтому, наверное, у меня где-то есть проблема, но я не смог ее найти. Действительно, вот моя модель:

import statsmodels.tsa.api as smt

array = []

for i, row in test.iterrows():
  print("row['shop_id']: ", row['shop_id'], " row['item_id']: ", row['item_id'])
  ts = pd.DataFrame(sales_monthly.loc[pd.IndexSlice[:, [row['shop_id']],[row['item_id']]], :]['item_price'].values*sales_monthly.loc[pd.IndexSlice[:, [row['shop_id']],[row['item_id']]], :]['item_cnt_day'].values).T.iloc[0]
  print(ts.values)
  if ts.values != []:
    best_aic = np.inf
    best_order = None
    best_model = None

    rng = range(5)
    for i in rng:
      for j in rng:
        try:
          tmp_model = smt.ARMA(ts.values, order = (i, j)).fit(method='mle', trand='nc')
          tmp_aic = tmp_model.aic
          if tmp_aic < best_aic:
            best_aic = tmp_aic
            best_order = (i, j)
            best_model = tmp_mdl
        except Exception as e:
          continue
    y_hat = best_model.forecast()[0][0]
    if y_hat<0:
      y_hat = 0
  else:
    y_hat = 0
  print("predicted:", y_hat)
  d = {'id':row['ID'], 'item_cnt_month': y_hat}
  array.append(d)
  print("-------------------")

df = pd.DataFrame(array)
df

Он распечатывает:

row['shop_id']:  5  row['item_id']:  5037
[2599.  2599.  3998.  3998.  1299.  1499.  1499.  2997.5  749.5]
predicted: 15001.056988528915
-------------------
row['shop_id']:  5  row['item_id']:  5320
[]
predicted: 0
-------------------
row['shop_id']:  5  row['item_id']:  5233
[2697. 1198.  599. 2997. 1199.]
predicted: 15001.056988528915
-------------------
row['shop_id']:  5  row['item_id']:  5232
[599.]
predicted: 0
-------------------
row['shop_id']:  5  row['item_id']:  5268
[]
predicted: 0
-------------------
row['shop_id']:  5  row['item_id']:  5039
[5198.  6597.  2599.  5197.   749.5 1499. ]
predicted: 15001.056988528915
-------------------
row['shop_id']:  5  row['item_id']:  5041
[11497.  7998.]
predicted: 15001.056988528915
-------------------
row['shop_id']:  5  row['item_id']:  5046
[ 299. 1495.  349.  349.]
predicted: 15001.056988528915
-------------------
...

Я не понимаю, потому что когда я пытаюсь предсказать их одного за другим, это работает хорошо. Например, с помощью следующего ts.values:

array([ 7770.        , 15640.        , 15540.        , 12950.        ,
       30775.        , 15950.        , 12760.        , 22330.        ,
       15949.64285714,     0.        ,  6380.        ,  3190.        ,
        9670.        ,  3490.        ,  3090.        ,  3490.        ,
        3490.        , 10470.        ])

i:

import statsmodels.tsa.api as smt

# pick best order by Aikake Information Criterion smallest aic wins
best_aic = np.inf
best_order = None
best_mdl = None

rng = range(5)
for i in rng:
  for j in rng:
    try:
      tmp_mdl = smt.ARMA(ts.values, order = (i, j)).fit(method='mle', trand='nc')
      tmp_aic = tmp_mdl.aic
      if tmp_aic < best_aic:
        best_aic = tmp_aic
        best_order = (i, j)
        best_mdl = tmp_mdl
    except:
      continue
    
print(best_aic, best_order)
print('aic: {} | order: {}'.format(best_aic, best_order))
print(best_mdl.forecast()[0][0])

Он возвращается:

204.39695560597815 (0, 0)
aic: 204.39695560597815 | order: (0, 0)
1712.4545454545446

Ответы (1 шт):

Автор решения: CrazyElf

Во-первых у вас описка:

  tmp_model = smt.ARMA(ts.values, order = (i, j)).fit(method='mle', 
  ...
    best_model = tmp_mdl

tmp_mdl в этом блоке кода вообще не вычисляется. Если это действительно ваш код, который вы Jupyter Notebook запускаете или другой ipython среде, то что у вас в tmp_mdl лежит, то и будет лежать и оно никак не меняется.

Во-вторых, даже если этой описки в коде нет и вы присваиваете значение правильно, как и в вашем коде ниже, то я не уверен, что такое присваивание сохраняет состояние модели, ведь вы копируете ссылку, а не саму модель. Возможно, последующие итерации меняют состояние модели и best_model потом ссылается на ту же модель, но с новым состоянием после выполнения строки

  tmp_model = smt.ARMA(ts.values, order = (i, j)).fit(method='mle', trand='nc')

Я бы попробовал сохранять не лучшую модель, а вычислять и сохранять предсказание лучшей модели.

if tmp_aic < best_aic:
    ...
    y_hat = best_model.forecast()[0][0]

Оно уж точно по ссылке не должно поменяться - это же число. Число скопируется.

→ Ссылка