Ana içeriğe atla
Veri Bilimi

SARIMAX: Dış Değişkenli Mevsimsel Zaman Serileri

SARIMAX'in mevsimsel zaman serisi modellemesini dış yordayıcılarla nasıl birleştirdiğini öğrenin. Parametrelerini anlayın, ARIMA ve SARIMA'dan farkını görün ve Python'da bir tahmin modeli kurun.
Dario Radečić's photo
Dario Radečić
Güncel · 15 dk. oku

Yapay Zeka ile Keşfedin

ChatGPTClaudePerplexity

Ücretsiz Hesabınızı Oluşturun

Alıştırma and program your progress.

Google Ile Devam Edin
Devam ederek Kullanım Şartlarımızı, Gizlilik Politikamızı ve verilerinizin ABD’de saklandığını kabul etmiş olursunuz.

Diyelim ki hedef aylık elektrik talebi. ARIMA ve SARIMA gibi modeller yalnızca serinin geçmiş değerlerine ve kendi geçmiş tahmin hatalarına bakar. Oysa talep sıcaklık gibi dış faktörlere de bağlıdır: sıcak bir yaz ve soğuk bir kış talebi artırır. Model bu faktörleri göremezse, her alışılmadık ayı gürültü olarak yorumlar ve hava değiştiğinde bir sonraki sefer aynı hatayı yapar.

SARIMAX, mevsimsel bir ARIMA modeline dışsal (exogenous) değişkenler ekleyerek bu sorunu çözer. Serinin geçmişinden eğilim ve mevsimselliği yine öğrenir, ancak geçmiş değerlerin açıklayamadığı noktaları açıklayan dış bilgileri de kullanır.

Python ile zaman serisi verilerini düzenleme, yorumlama ve görselleştirme konusunda başlangıca ihtiyacınız varsa, bir haftada temelleri oturtmak için Python ile Zaman Serileri öğrenim yolumuza kaydolun .

SARIMAX Nedir?

SARIMAX bir mevsimsel ARIMA modeli olup dışsal yordayıcıları da kullanabilir. Özellikle, ad Mevsimsel Otoregresif Bütünleşik Hareketli Ortalama ve Dışsal değişkenler (Seasonal AutoRegressive Integrated Moving Average with eXogenous regressors) ifadesinin kısaltmasıdır.

SARIMAX, bir hedef seriyi dört bilgi kaynağından tahmin ederek çalışır:

  • Geçmiş değerler: En son aylardaki talep
  • Geçmiş tahmin hataları: Modelin son aylarda ne kadar yanıldığı
  • Mevsimsel kalıplar: Önceki yılların aynı ayındaki talep
  • Dışsal değişkenler: Modele eklediğiniz dış veriler; örneğin ortalama aylık sıcaklık

Diyelim ki amaç gelecek temmuz ayı için elektrik talebini tahmin etmek. SARIMAX son birkaç aydaki talebe, önceki temmuzlardaki talebe ve temmuz için beklenen sıcaklığa bakar. İlk ikisi serinin içinden, sıcaklık ise dışarıdan gelir.

Modeli SARIMAX(p, d, q)(P, D, Q, S) olarak yazarsınız. İlk parametre grubu kısa vadeli davranışı, ikinci grup ise mevsimsel bileşeni kapsar; burada S bir döngüdeki zaman adımı sayısıdır. Yıllık desenli aylık veride S 12'dir.

Dışsal değişkenler bu gösterime dahil değildir. Bunları modele ayrı, kendi girdileri olarak verirsiniz.

SARIMAX Nasıl Çalışır

SARIMAX'in iki grup terimi vardır ve dışsal değişkenler bunların üzerine eklenir.

Mevsimsel olmayan terimler (p, d, q) kısa vadeli davranışı modeller:

  • Otoregresif derecesi p: Modelin kaç geçmiş değeri kullandığı. p = 2 ile, bu ayın talebi önceki iki ayın talebine bağlıdır

  • Fark alma derecesi d: Eğilimi kaldırmak için serinin kaç kez farkının alındığı. d = 1 ile model ham talep yerine aylık değişimlerle çalışır

  • Hareketli ortalama derecesi q: Modelin kaç geçmiş tahmin hatasını kullandığı. Model geçen ay talebi olduğundan az tahmin ettiyse, o hata bu ayın tahminine girer

Mevsimsel terimler (P, D, Q, S) aynı şeyi mevsimsel gecikmelerde yapar:

  • Mevsimsel otoregresif derecesi P: Modelin kaç geçmiş mevsime baktığı. P = 1 ve aylık veride, bu temmuzun talebi geçen temmuzun talebine bağlıdır

  • Mevsimsel fark alma derecesi D: Serinin mevsimsel gecikmede kaç kez farkının alındığı. D = 1 ile model bu temmuzu geçen temmuzla karşılaştırır; bu da tekrarlayan yıllık deseni kaldırır

  • Mevsimsel hareketli ortalama derecesi Q: Modelin mevsimsel gecikmelerde kaç geçmiş tahmin hatasını kullandığı; örneğin geçen temmuzdaki hata

  • Mevsimsel periyot S: Bir döngünün kaç zaman adımı olduğu. Yıllık desenli aylık veride 12, haftalık desenli günlük veride 7'dir

Dışsal değişkenler, serinin içinde olmayan bilgiyi ekler.

Elektrik talebi örneğinde bu, sıcaklıktır. Sıcak bir yaz ya da soğuk bir kış talebi artırır ve geçmiş talep değerleri modele gelecek ay havanın nasıl olacağını söyleyemez. Ay-içi desen zaten mevsimsel terimlerden gelir, bu yüzden örnek yalnızca sıcaklığı dışsal değişken olarak kullanır.

statsmodels'da SARIMAX, hataları mevsimsel bir ARIMA sürecini izleyen, dışsal değişkenler üzerinde bir doğrusal regresyondur. Tek bir dışsal değişkenle şu şekilde görünür:

Tek bir dışsal değişkenli SARIMAX

Tek bir dışsal değişkenli SARIMAX

Burada y_t ay t'deki elektrik talebidir, x_t o aydaki sıcaklıktır, beta sıcaklık katsayısıdır ve u_t talebin sıcaklıkla açıklanmayan kısmıdır. Mevsimsel olmayan ve mevsimsel terimler u_t'yi modeller.

Düz söylemek gerekirse, talebin bir kısmını sıcaklık açıklar, geri kalanını SARIMA terimleri modeller.

İşte daha görsel bir genel bakış:

SARIMAX bileşenleri

SARIMAX bileşenleri

ARIMA vs. SARIMA vs. ARIMAX vs. SARIMAX

Bu dört model aynı ailenin üyesidir. Farklar ince olsa da bir okumada anlayabilirsiniz.

ARIMA bir seriyi kendi geçmiş değerleri ve geçmiş tahmin hatalarından modeller. SARIMA bunun üzerine mevsimsel terimler ekler, böylece her S adımda tekrarlanan desenleri modelleyebilir. ARIMAX ARIMA'ya dışsal değişkenler ekler, ancak varsayılan olarak mevsimsel terimler yoktur. SARIMAX ikisine de sahiptir.

Bu nedenle SARIMAX diğer modelleri özel durumlar olarak temsil edebilir. Dışsal değişken geçmezseniz SARIMA modeli elde edersiniz. Tüm mevsimsel dereceleri sıfıra ayarlarsanız mevsimsel olmayan bir ARIMAX elde edersiniz. İkisi de yoksa ARIMA modelidir.

Ne yazık ki, terminoloji paketler arasında tutarlı değildir.

Klasik ARIMAX, dışsal değişkenleri ARIMA denklemine serinin geçmiş değerlerinin yanına doğrudan koyar. statsmodels'ın SARIMAX'i ise önceki bölümde gösterildiği gibi, yerine SARIMA hatalarıyla bir regresyon uydurur. İki form farklı katsayılar tahmin eder; bu nedenle aynı sıcaklık değişkeni, kullanılan pakete bağlı olarak farklı bir katsayı alabilir.

Sınıf ve fonksiyon adları da örtüşmez. statsmodels'daki ARIMA sınıfı da mevsimsel terimleri ve dışsal değişkenleri kabul eder. R'de, forecast paketi dışsal yordayıcıları Arima() ve auto.arima()'nın xreg argümanı üzerinden ele alır. Bu yüzden araçlar arasında sonuçları karşılaştırmadan önce her paketin modeli nasıl tanımladığını kontrol etmeyi unutmayın.

Kısa bir özet:

  Mevsimsellik? Dış değişkenler?
ARIMA Hayır Hayır
SARIMA Evet Hayır
ARIMAX Varsayılan değil Evet
SARIMAX Evet Evet

ARIMA model ailesi karşılaştırması

SARIMAX Ne Zaman Kullanılır

Hedefte tekrarlayan bir mevsimsel desen varsa ve dış değişkenler tahmini iyileştirebilecekse SARIMAX mantıklıdır.

Örneğin:

  • Elektrik talebi: Yıllık döngünün üzerine sıcaklık ve resmi tatil gibi takvim etkileri
  • Perakende satışlar: Promosyonlar, fiyatlar ve tatil dönemleri
  • Otel rezervasyonları: Yıllık seyahat sezonunun üzerine yerel etkinlikler ve oda fiyatları
  • Toplu taşıma kullanım sayısı: Günlük veride haftalık bir desenin üzerine hava durumu ve okul tatilleri

Ancak SARIMAX her zaman doğru seçim değildir. Şu iki durumda daha basit bir model aynı işi görebilir:

  • Anlamlı mevsimsellik yoksa: Seri bir deseni tekrar etmiyorsa, mevsimsel terimler yalnızca tahmin edilecek parametre ekler. ARIMA veya ARIMAX yeterlidir
  • Yordayıcılar doğruluğu artırmıyorsa: Dışsal değişkenler ayrılmış bir test dönemindeki hatayı düşürmüyorsa, onları kaldırın ve SARIMA kullanın. Eğitim verisindeki daha iyi uyum sayılmaz

Burada hatırlanacak şey, SARIMAX'in tahmin dönemindeki her dışsal değişken için değerlere ihtiyaç duyduğudur.

Bazı değerler önceden bilinir; örneğin resmi tatiller veya planlı promosyonlar. Sıcaklık gibi diğerleri ise SARIMAX kullanmadan önce ayrı bir şekilde tahmin edilmelidir. Bir yordayıcı için gelecekteki değerleri elde edemiyorsanız, onu tahminde kullanamazsınız.

Python ile SARIMAX Modeli Nasıl Kurulur

Bu bölümde, ham veriden 12 aylık bir tahmine kadar statsmodels ile bir SARIMAX modeli kuracağım.

Örnek, dış değişken olarak sıcaklıkla birlikte sentetik aylık elektrik talebini kullanır. Küçük ve yeniden üretilebilir olup makalenin geri kalanıyla aynı hikâyeyi izler.

Veriyi hazırlayın

Veri kümesi Ocak 2015'ten Aralık 2024'e kadar on yıllık aylık veriyi kapsar.

Talepte yukarı yönlü bir eğilim, zamanla yavaşça değişen yıllık bir takvim deseni, bir hava etkisi ve gürültü vardır. İki sıcaklık ölçümü özellikle eksiktir; böylece boşluklarla nasıl çalışılacağını görebilirsiniz:

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import warnings

warnings.filterwarnings("ignore")

rng = np.random.default_rng(10)

# Monthly timestamps from January 2015 to December 2024
dates = pd.date_range(start="2015-01-01", periods=120, freq="MS")
month = dates.month.to_numpy()

# Average monthly temperature in degrees Celsius
temperature = 12 + 11 * np.sin(2 * np.pi * (month - 4) / 12) + rng.normal(0, 2, 120)

# Calendar pattern that repeats every year and changes slowly over time
calendar_effect = 15 * np.cos(2 * np.pi * (month - 1) / 12)
for t in range(12, 120):
    calendar_effect[t] = calendar_effect[t - 12] + rng.normal(0, 2.5)

# Short-term noise where each month carries over part of the previous one
noise = np.zeros(120)
for t in range(1, 120):
    noise[t] = 0.5 * noise[t - 1] + rng.normal(0, 6)

# Demand in GWh: upward trend, calendar pattern, weather effect, and noise
trend = np.linspace(500, 560, 120)
heating_demand = 6 * np.clip(18 - temperature, 0, None)
cooling_demand = 9 * np.clip(temperature - 18, 0, None)
demand = trend + calendar_effect + heating_demand + cooling_demand + noise

df = pd.DataFrame(
    {"demand_gwh": demand.round(1), "temperature": temperature.round(1)},
    index=dates,
)

# Two missing temperature readings
df.loc[["2018-07-01", "2021-02-01"], "temperature"] = np.nan

print(df.head())

Veri kümesinin ilk beş satırı

Veri kümesinin ilk beş satırı

Ya da görsel bir genel bakışı tercih ediyorsanız:

Sıcaklık veri kümesi

Sıcaklık veri kümesi

Kendi verinizle çalışıyorsanız, pd.read_csv() ile yükleyin ve tarih sütununu indeks olarak ayarlayın. İş akışının geri kalanı aynı kalır.

SARIMAX tutarlı frekansa sahip bir zaman indeksine ihtiyaç duyar. .asfreq() yöntemi frekansı aylığa ayarlar ve eksik olan her ay için boş bir satır ekler. Ardından boşlukları sayabilir ve doldurabilirsiniz:

df = df.asfreq("MS")
print(df.isna().sum())

df["temperature"] = df["temperature"].interpolate()

Sıcaklıktaki boşlukların enterpolasyonu

Sıcaklıktaki boşlukların enterpolasyonu

Lineer enterpolasyon burada işe yarar çünkü sıcaklık aylar arasında düzgün değişir. Hedef için aynı şeyi yapmayın; eğer büyük parçalar eksikse, modele uydurma değerleri öğretmiş olursunuz.

Sırada dışsal değişkenler var. Sıcaklık düştüğünde ve yükseldiğinde talep artar, ancak ham sıcaklık üzerinde doğrusal bir regresyon U-şeklini modelleyemez. Bu yüzden sıcaklığı iki özelliğe böleceğim:

  • Isıtma dereceleri: Ortalama sıcaklığın 18 santigrat derecenin altında olduğu derece sayısı; değilse sıfır
  • Soğutma dereceleri: Ortalama sıcaklığın 18 santigrat derecenin üstünde olduğu derece sayısı; değilse sıfır
df["heating_degrees"] = (18 - df["temperature"]).clip(lower=0)
df["cooling_degrees"] = (df["temperature"] - 18).clip(lower=0)

Şimdi veriyi hedef y ve dışsal değişkenler X olarak ayırın. Ayrım kronolojik olmalıdır: model geçmişte eğitilir ve gelecekte test edilir. Rastgele bir ayrım, geleceğe ait bilgiyi eğitime sızdırır:

y = df["demand_gwh"]
X = df[["heating_degrees", "cooling_degrees"]]

y_train, y_test = y[:"2022-12"], y["2023-01":]
X_train, X_test = X[:"2022-12"], X["2023-01":]

print(f"Train: {len(y_train)} months, Test: {len(y_test)} months")

Eğitim/test ayrımı

Eğitim/test ayrımı

Burada hatırlanacak şey, X_test'in fiilen gözlemlenmiş sıcaklıkları içermesidir. Gerçek bir tahminde bunları önceden bilmezsiniz — en iyi ihtimalle bir hava tahmininiz olur. Bu, ileride göreceğiniz test puanının iyimser olduğu anlamına gelir. Yordayıcıların gözlemlenen değerlerini yalnızca aynı değerler tahmin anında da mevcut olacaksa (örneğin resmi tatiller veya planlanan fiyatlar) değerlendirmede kullanın.

Mevsimsellik ve durağanlığı inceleyin

Bir grafikle başlayın. Aradığınız şey eğilimler, mevsimsel döngüler ve ani değişimlerdir:

from statsmodels.tsa.seasonal import seasonal_decompose

fig, ax = plt.subplots(figsize=(10, 4))
y_train.plot(ax=ax, title="Monthly electricity demand (GWh)")
plt.show()

Eğitim dönemindeki aylık elektrik talebi

Eğitim dönemindeki aylık elektrik talebi

Talep zamanla artar ve her kış zirve yapar; her yaz daha küçük bir zirve görülür. Desen her 12 ayda bir tekrar eder.

Mevsimsel ayrıştırma, seriyi eğilim, mevsimsel ve artık bileşenlere ayırır; böylece mevsimsel periyot S'i doğrulayabilirsiniz:

decomposition = seasonal_decompose(y_train, model="additive", period=12)
decomposition.plot()
plt.show()

Elektrik talebinin mevsimsel ayrıştırması

Elektrik talebinin mevsimsel ayrıştırması

Mevsimsel bileşen her yıl tekrar eder; dolayısıyla S = 12.

ARIMA ailesi modeller durağan bir seri ister — ortalaması ve varyansı zamanla değişmeyen bir seri. Talep eğilim ve mevsimsel döngü içerdiği için durağan değildir. 

Fark alma bunun etrafından dolanmanın bir yoludur:

  • Düzenli fark alma (d): Bu ayın değerinden geçen ayın değeri çıkarılır. Eğilimi kaldırır

  • Mevsimsel fark alma (D): Geçen yılın aynı ayındaki değer çıkarılır. Tekrarlayan mevsimsel deseni kaldırır ve doğrusal eğilimi de kaldırır

Genişletilmiş Dickey-Fuller (ADF) testi durağanlığı kontrol eder. Sıfır hipotezi serinin durağan olmadığıdır; bu yüzden küçük bir p-değeri (0,05'in altında) durağanlık lehine kanıttır:

from statsmodels.tsa.stattools import adfuller

series_versions = {
    "Original": y_train,
    "Seasonally differenced (D=1)": y_train.diff(12).dropna(),
    "Both differences (d=1, D=1)": y_train.diff().diff(12).dropna(),
}

for name, series in series_versions.items():
    adf_stat, p_value = adfuller(series)[:2]
    print(f"{name}: ADF statistic = {adf_stat:.2f}, p-value = {p_value:.4f}")

ADF testi sonucu

ADF testi sonucu

Orijinal seri durağan değildir. Yalnızca mevsimsel fark alma bunu düzeltir; dolayısıyla üzerine düzenli fark alma eklemek bir şey katmaz. İşe yarayan en küçük fark alma miktarını kullanın — fazladan farklar seriye gürültü ekler ve modeli uydurmayı zorlaştırır.

Dolayısıyla seçim d = 0 ve D = 1.

Ancak ADF testini yalnızca destekleyici kanıt olarak görün. p, q, P ya da Q hakkında hiçbir şey söylemez ve kısa serilerde ayarlarına bağlı olarak farklı cevaplar verebilir.

Aday parametreleri seçin

ACF ve PACF grafikleri kalan dereceler için aday değerler seçmenize yardımcı olur:

  • ACF (otokorelasyon fonksiyonu): Serinin kendi gecikmeli değerleriyle korelasyonunu gösterir. ACF'deki sivrilikler hareketli ortalama terimlerine işaret eder; kısa gecikmelerde q, mevsimsel gecikmelerde Q

  • PACF (kısmi otokorelasyon fonksiyonu): Aynı korelasyonu gösterir, ancak aradaki gecikmelerin etkisini kaldırır. PACF'deki sivrilikler otoregresif terimlere işaret eder; kısa gecikmelerde p, mevsimsel gecikmelerde P

Modelin çalıştığı seri bu olduğu için ikisini de mevsimsel farkı alınmış seri için çizmelisiniz:

from statsmodels.graphics.tsaplots import plot_acf, plot_pacf

y_seasonal_diff = y_train.diff(12).dropna()

fig, axes = plt.subplots(1, 2, figsize=(12, 4))
plot_acf(y_seasonal_diff, lags=24, ax=axes[0])
plot_pacf(y_seasonal_diff, lags=24, ax=axes[1])
plt.show()

Mevsimsel farkı alınmış elektrik talebinin ACF ve PACF grafikleri

Mevsimsel farkı alınmış elektrik talebinin ACF ve PACF grafikleri

ACF'de 12. gecikmede belirgin bir negatif sivrilik ve 24'te bir şey yok. Bu, tipik bir mevsimsel hareketli ortalama terimi işaretidir; dolayısıyla Q = 1 iyi bir adaydır. Her iki grafik de kısa gecikmelerde birkaç sivrilik gösterir; bu yüzden p ve q denenmeye değerdir.

Bir sonraki adım, küçük bir aday model kümesini uydurmak ve AIC veya BIC ile karşılaştırmaktır. Her ikisi de modelin eğitim verisine ne kadar iyi uyduğunu puanlar ve fazladan parametreleri cezalandırır. Daha düşük daha iyidir ve BIC, AIC'ye göre karmaşıklığı daha fazla cezalandırır:

import itertools
from statsmodels.tsa.statespace.sarimax import SARIMAX

candidates = []
for p, q, P, Q in itertools.product([0, 1], [0, 1], [0, 1], [0, 1]):
    candidate = SARIMAX(
        y_train,
        exog=X_train,
        order=(p, 0, q),
        seasonal_order=(P, 1, Q, 12),
        trend="c",
    ).fit(disp=False)
    candidates.append({
        "order": (p, 0, q),
        "seasonal_order": (P, 1, Q, 12),
        "AIC": round(candidate.aic, 1),
        "BIC": round(candidate.bic, 1),
    })

print(pd.DataFrame(candidates).sort_values("AIC").head(5).to_string(index=False))

AIC ve BIC sonuçları

AIC ve BIC sonuçları

SARIMAX(1, 0, 0)(0, 1, 1, 12) hem AIC hem BIC'de kazanır. Listede en basit modellerden biridir.

trend="c" argümanı sabit ekler. Mevsimsel fark alma ile sabit, yıldan yıla talepteki artışı modeller.

pmdarima kütüphanesindeki auto_arima() gibi bu aramayı sizin için yapan araçlar bulursunuz. İlk geçiş için kullanışlıdırlar, ancak AIC ve BIC yalnızca eğitim verisi üzerindeki uyumu ölçer. Bir modele güvenmeden önce, görmediği veri üzerinde test edin.

Modeli uydurun

Hedefi ilk argüman olarak ve dışsal değişkenleri exog üzerinden verin. order argümanı (p, d, q) alır, seasonal_order ise (P, D, Q, S) alır:

model = SARIMAX(
    y_train,
    exog=X_train,
    order=(1, 0, 0),
    seasonal_order=(0, 1, 1, 12),
    trend="c",
)
results = model.fit(disp=False)
print(results.summary())

SARIMAX model özeti

SARIMAX model özeti

Katsayı tablosunu böyle okuyun:

  • heating_degrees: Modeldeki diğer her şey sabitken her ek ısıtma derecesi yaklaşık 6,6 GWh ek talep ile birlikte görülür

  • cooling_degrees: Her ek soğutma derecesi yaklaşık 7,4 GWh ek taleple birlikte görülür

  • ar.L1: Geçen ayın açıklanamayan farkının yaklaşık %46'sı bu aya taşır

  • ma.S.L12: Geçen yılın aynı ayındaki hataya göre tahmini düzelten mevsimsel hareketli ortalama terimi

  • sigma2: Kalan gürültünün varyansı

Tüm katsayıların p-değerleri sıfıra yakındır; bu da her terimin modele bir şey kattığını gösterir.

Ancak bu katsayılar, nedenleri değil, uyarlanmış model içindeki ilişkileri açıklar. Burada veriyi talebin nedeni olarak sıcaklıkla ürettiğim için okuma güvenlidir. Gerçek veride bir yordayıcı, modelin görmediği bir şeyle birlikte hareket ettiği için önemli görünebilir.

Modeli teşhis edin ve değerlendirin

İyi bir model, rastgele gürültüye benzeyen artıklar bırakır. Artıklarda hâlâ bir desen varsa model bir şeyi kaçırmış demektir.

.plot_diagnostics() yöntemi tek çağrıda dört grafik verir:

from statsmodels.stats.diagnostic import acorr_ljungbox

results.plot_diagnostics(figsize=(12, 8))
plt.show()

Artık teşhis grafiği

Artık teşhis grafiği

Şunlara bakın:

  • Standartlaştırılmış artıklar: Eğilim yok, tekrar eden desen yok ve yayılmanın çok genişlediği uzun aralıklar yok
  • Histogram ve Q-Q grafiği: Noktalar normal dağılıma yakın
  • Korrelogram: Güven bandının dışında sivrilik yok; özellikle 12. gecikmede — oradaki bir sivrilik modelin mevsimselliği tam olarak ele almadığı anlamına gelir

Ljung-Box testi size aynı denetimi bir sayı olarak verir. Sıfır hipotezi, verilen gecikmeye kadar artıkların otokorelasyonu olmadığıdır; bu yüzden büyük p-değerleri istersiniz:

# Skip the first 13 residuals, which come from the differencing start-up period
print(acorr_ljungbox(results.resid[13:], lags=[12, 24]))

Ljung-Box testi sonuçları

Ljung-Box testi sonuçları

Her iki p-değeri de 0,05'in oldukça üzerindedir; bu nedenle artıklar gürültü gibidir.

Şimdi en önemli kısma — modelin görmediği veri üzerindeki doğruluğa. .get_forecast() yöntemi 24 test ayını tahmin eder ve o aylar için dışsal değerlere ihtiyaç duyar.

Tek bir tahmin sayısı kendi başına çok şey ifade etmez; bu yüzden SARIMAX'i iki karşılaştırma noktasıyla kıyaslayacağım:

  • Mevsimsel safi (naive) tahmin: Eğitim verisinin son 12 ayındaki değerleri tekrarlar
  • SARIMA: Aynı model, ancak dışsal değişkenler olmadan
from sklearn.metrics import mean_absolute_error, root_mean_squared_error

sarimax_pred = results.get_forecast(steps=len(y_test), exog=X_test).predicted_mean

# Baseline 1: repeat the last 12 observed months
naive_pred = pd.Series(np.tile(y_train[-12:].to_numpy(), 2), index=y_test.index)

# Baseline 2: the same model without exogenous variables
sarima_results = SARIMAX(
    y_train, order=(1, 0, 0), seasonal_order=(0, 1, 1, 12), trend="c"
).fit(disp=False)
sarima_pred = sarima_results.get_forecast(steps=len(y_test)).predicted_mean

for name, pred in [("SARIMAX", sarimax_pred), ("SARIMA", sarima_pred), ("Seasonal naive", naive_pred)]:
    mae = mean_absolute_error(y_test, pred)
    rmse = root_mean_squared_error(y_test, pred)
    print(f"{name:<15} MAE = {mae:.2f} GWh, RMSE = {rmse:.2f} GWh")

fig, ax = plt.subplots(figsize=(10, 4))
y_train["2020":].plot(ax=ax, label="Train")
y_test.plot(ax=ax, label="Test")
sarimax_pred.plot(ax=ax, label="SARIMAX", linestyle="--")
naive_pred.plot(ax=ax, label="Seasonal naive", linestyle=":")
ax.legend()
plt.show()

Test setinde SARIMAX ve mevsimsel safi tahminler ile gerçek talep

Test setinde SARIMAX ve mevsimsel safi tahminler ile gerçek talep

MAE (ortalama mutlak hata), GWh cinsinden hatanın ortalama büyüklüğüdür. RMSE (kök ortalama kare hata) büyük hataları daha fazla cezalandırır.

SARIMAX her iki ölçütte de SARIMA'nın hatasının yaklaşık yarısına sahiptir. Yalnızca mevsimsel terimler olağan dışı soğuk bir ocak ya da sıcak bir temmuzu tahmin edemez; sıcaklık özellikleri edebilir.

Unutmayın, bu sonuç gözlemlenmiş test dönemi sıcaklıklarını kullanır. Yerlerine hava tahminleri konduğunda fark daha küçük olurdu.

Gelecekteki değerleri tahmin edin

Modelden memnun kaldığınızda, tahminin en güncel aydan başlaması için modeli tüm veriler üzerinde yeniden uydurun.

Ardından .get_forecast() ile tahmin yapın. Her gelecek ayda her dışsal değişken için bir değere ihtiyacınız var. Biri eksikse, statsmodels hata verir.

Bu değerlerin nereden geleceği değişkene bağlıdır. Örneğin:

  • Bilinen takvim özellikleri: Resmi tatiller ve çalışma günleri yıllar öncesinden bilinir
  • Planlı iş kararları: Takımınız şimdiden planladıysa fiyatlar ve promosyonlar bilinir
  • Hava durumu: Sıcaklık, bir hava servisi veya başka bir modelden ayrı bir tahmin gerektirir
  • Tarihsel ortalamalar: Daha iyisi yoksa, geçmiş veriden her takvim ayının ortalama değerini kullanın

Burada hava tahmini yerine vekil olarak son seçeneği kullanacağım:

final_results = SARIMAX(
    y, exog=X, order=(1, 0, 0), seasonal_order=(0, 1, 1, 12), trend="c"
).fit(disp=False)

future_dates = pd.date_range(start="2025-01-01", periods=12, freq="MS")

# Stand-in for a weather forecast: the average temperature of each calendar month
monthly_normals = df.groupby(df.index.month)["temperature"].mean()
future_temperature = monthly_normals.loc[future_dates.month].to_numpy()

X_future = pd.DataFrame({
    "heating_degrees": np.clip(18 - future_temperature, 0, None),
    "cooling_degrees": np.clip(future_temperature - 18, 0, None),
}, index=future_dates)

forecast = final_results.get_forecast(steps=12, exog=X_future)
forecast_df = pd.concat([forecast.predicted_mean.rename("forecast"), forecast.conf_int(alpha=0.05)], axis=1)
print(forecast_df.round(1))

fig, ax = plt.subplots(figsize=(10, 4))
y["2021":].plot(ax=ax, label="Observed")
forecast.predicted_mean.plot(ax=ax, label="Forecast")
ci = forecast.conf_int(alpha=0.05)
ax.fill_between(ci.index, ci.iloc[:, 0], ci.iloc[:, 1], alpha=0.3, label="95% interval")
ax.legend()
plt.show()

%95 tahmin aralığıyla 12 aylık elektrik talebi tahmini

%95 tahmin aralığıyla 12 aylık elektrik talebi tahmini

Tahmin tanıdık bir şekli izler: en yüksek talep kışın, yazın daha küçük bir çıkıntı ve en düşük talep ilkbahar ve sonbaharda.

Ancak %95 aralık, verdiğiniz sıcaklık değerleri sabitken uyarlanmış modelin belirsizliğini kapsar. Bu aralık sıcaklıklardaki belirsizliği içermez. Ocak beklenenden çok daha soğuk geçerse, model doğru olsa bile gerçek talep aralığın dışında kalabilir.

Tahminin ne kadar hassas olduğunu görmek isterseniz, daha soğuk ve daha sıcak sıcaklık senaryolarıyla tekrar çalıştırın ve sonuçları karşılaştırın.

SARIMAX'in Sınırlamaları

SARIMAX birçok mevsimsel tahmin problemi için iyi bir modeldir, ancak bazı sınırları vardır. Bilmeniz gerekenler:

  • Gelecek yordayıcılar zorunludur: Model, her gelecek ayda her dışsal değişken için değer olmadan tahmin yapamaz. Bir yordayıcı önceden bilinmiyorsa ve onu tahmin edemiyorsanız, geçmiş veride uyumu ne kadar iyileştirirse iyileştirsin, modele ait değildir

  • Yordayıcı belirsizliği gizlidir: Gelecekteki yordayıcılar da tahmin ise, onların hataları talep tahminine yansır. Standart tahmin aralığı bunları içermez; bu nedenle görünenden daha dar olur

  • Bir mevsimsel periyodu ele alır: Standart form tek bir S'i destekler. Saatlik elektrik talebinde günlük ve haftalık döngü vardır; SARIMAX ikisini aynı anda modelleyemez. Ayrıca saatlik veride haftalık döngü için S = 168 gibi uzun mevsimsel periyotlarla yavaşlar

  • İlişkiler değişebilir: Model, eğitim verisindeki kalıpların gelecekte de aynı kalacağını varsayar. Daha fazla ev ısı pompasına geçerse, soğuk havanın talep üzerindeki etkisi değişir ve eski katsayı bunu artık açıklamaz. Modeli düzenli olarak taze verilerle yeniden uydurmalı ve doğruluğunu zaman içinde takip etmelisiniz

  • Parametre seçimi özen ister: Düşük AIC'li bir model yine de kötü tahmin yapabilir. AIC ve BIC yalnızca eğitim verisine bakar; bu yüzden nihai adayları ayrılmış bir dönem üzerinde, tercihen birkaç zaman penceresiyle zaman serisi çapraz doğrulamasıyla test edin

  • Nedensel bir model değildir: Anlamlı bir katsayı, bir yordayıcının tahmine yardımcı olduğunu söyler; hedefte değişime neden olduğunu değil. Bir fiyatı değiştirdiğinizde talebin ne olacağını bilmek istiyorsanız nedensel çıkarım yöntemlerine ihtiyacınız vardır

Sonuç

Verileriniz mevsimsel bir deseni tekrar ediyor ve dış faktörlere bağlıysa, SARIMAX denemeye değerdir. Serinin geçmişini ve onu etkileyen dış faktörleri birleştirir. Verilerinizde ikisi de varsa, model genellikle yalnızca birini gören bir modelden daha iyidir.

Burada hatırlanacak şey, modelin yalnızca verdiğiniz girdiler kadar iyi olduğudur. Mevsimsel periyodu veriye göre seçin, yordayıcıları dikkatle hizalayın, AIC'ye güvenmek yerine gelecekteki veri üzerinde test edin ve bir şey inşa etmeden önce her yordayıcı için gelecekteki değerlere sahip olacağınızdan emin olun. Bunu yapamıyorsanız, SARIMAX veri kümeniz için doğru seçim değildir.

Öğrenmeye devam etmek isterseniz, bir öğleden sonra içinde temelleri anlamak için Python ile Zaman Serisi Analizi kursumuza kaydolun.


Dario Radečić's photo
Author
Dario Radečić
LinkedIn
Hırvatistan merkezli Kıdemli Veri Bilimci. 700’ün üzerinde yayımlanmış makaleyle 10 M+ görüntüleme elde eden, önde gelen bir teknoloji yazarı. TPOT ile Makine Öğrenimi Otomasyonu kitabının yazarı.

SSS

SARIMAX ne için kullanılır?

SARIMAX, tekrarlayan mevsimsel desene sahip ve dış faktörlere bağımlı zaman serilerini tahmin eder. Sıcaklıkla elektrik talebi veya yerel etkinliklerle otel rezervasyonları yaygın örneklerdir. Seriniz bu iki özelliğin yalnızca birine sahipse, genelde SARIMA veya ARIMAX gibi daha basit bir model işi görür.

SARIMA ile SARIMAX arasındaki fark nedir?

SARIMA bir seriyi kendi geçmiş değerleri, geçmiş tahmin hataları ve mevsimsel desenlerden modeller. SARIMAX bunun üzerine dışsal değişkenler ekler; böylece sıcaklık veya fiyatlar gibi dış bilgileri de kullanabilir. SARIMAX'i dışsal değişken olmadan uydurursanız SARIMA modeli elde edersiniz.

SARIMAX bir makine öğrenimi modeli midir?

SARIMAX, yaygın anlamda bir makine öğrenimi modeli değil, istatistiksel bir modeldir. Sabit bir yapısı, az sayıda parametresi ve okunup yorumlanabilen katsayıları vardır. Bu, makine öğrenimi modellerinin öğrenmek için yeterli veriye sahip olmadığı küçük veri kümeleri için onu iyi bir seçenek yapar.

Neden SARIMAX ile tahmin yaparken get_forecast() hata veriyor?

Modeli exog argümanıyla uydurduysanız, statsmodels her gelecek zaman adımı için dışsal değerlere ihtiyaç duyar. Bunlar olmadan get_forecast() bir ValueError fırlatır. Eğitimde kullandığınız yordayıcılarla aynı sütunlara sahip ve her tahmin adımı için bir satır içeren bir DataFrame geçin.

SARIMAX birden fazla mevsimsel periyodu işleyebilir mi?

Standart formunda hayır; çünkü seasonal_order tek bir S periyodu kabul eder. Birden fazla döngüye sahip veriler için (örneğin günlük ve haftalık deseni olan saatlik talep), S'yi daha kısa döngüye ayarlayıp daha uzun olan için Fourier terimlerini exog üzerinden geçebilirsiniz. TBATS ve Prophet gibi modeller birden fazla mevsimsel periyodu kutudan çıktığı gibi destekler.

Konular
Veri Bilimi
İlgili

blog

2026’da En Popüler 40 Yazılım Mühendisi Mülakat Sorusu

Algoritmalar, sistem tasarımı ve davranışsal senaryoları kapsayan bu temel sorularla teknik mülakat sürecine hakim olun. Uzman cevapları, kod örnekleri ve kanıtlanmış hazırlık stratejileri edinin.
Dario Radečić's photo

Dario Radečić

15 dk.

blog

Hızlı Sevkiyat İçin Pratik Vibe Kodlama Teknoloji Yığını

Ön uç, arka uç, veritabanları, kimlik doğrulama, depolama, e-posta, test, dağıtım ve izleme için en iyi araçları keşfedin.
Abid Ali Awan's photo

Abid Ali Awan

14 dk.

Eğitim

Python'da Listeyi String'e Nasıl Dönüştürürsünüz

Bu hızlı eğitimde, Python'da bir listeyi string'e nasıl dönüştüreceğinizi öğrenin.
Adel Nehme's photo

Adel Nehme

Eğitim

.gitignore Nasıl Kullanılır: Örneklerle Pratik Bir Giriş

Git deponuzu temiz tutmak için .gitignore’u nasıl kullanacağınızı öğrenin. Bu eğitim; temelleri, yaygın kullanım durumlarını ve başlamanıza yardımcı olacak pratik örnekleri kapsar!
Kurtis Pykes 's photo

Kurtis Pykes

8 dk.

Devamını Gör