Chuỗi thời gian 3 — Mô hình cổ điển: ETS & ARIMA

13 thg 7, 2026 6 lượt xem
#ai
#time-series
#holt-winters
#exponential-smoothing
#arima

Chuỗi thời gian 3 — Mô hình cổ điển: ETS & ARIMA

Trong thời đại của deep learning, nhiều người bỏ qua các mô hình dự báo cổ điển vì nghĩ chúng "lỗi thời". Đây là một sai lầm tốn kém. Trên dữ liệu chuỗi thời gian đơn biến (một chuỗi số theo thời gian) với vài trăm đến vài nghìn điểm — đúng loại dữ liệu bạn gặp hằng ngày ở ngân hàng: khối lượng giao dịch theo ngày, số dư cuối kỳ, số hồ sơ vay nộp mỗi tuần — các mô hình như ETS (exponential smoothing) và ARIMA thường ngang bằng hoặc thắng cả những mạng neural phức tạp, mà lại nhanh gấp trăm lần, dễ diễn giải và không cần GPU. Các cuộc thi dự báo lớn (M3, M4) đều khẳng định điều này.

Bài này đi qua ba tầng: (1) các baseline naive bắt buộc phải so sánh; (2) họ làm mượt hàm mũ; (3) họ ARIMA/SARIMA. Bối cảnh xuyên suốt: dự báo khối lượng giao dịch theo ngày của một chi nhánh. Trước khi đọc, nên nắm phần phân rã và ACF/PACF ở Chuỗi thời gian 2 — EDA & phân rã; tổng quan bài toán ở Chuỗi thời gian 1 — Tổng quan.

1. Baseline: naive & seasonal-naive

Trước khi huấn luyện bất kỳ mô hình nào, bạn phải có baseline. Nếu một mô hình ARIMA cầu kỳ không đánh bại được phép dự báo "sao chép ngày hôm qua", thì công sức của nó là vô nghĩa. Đây là quy tắc bất di bất dịch, giống như baseline trong ML cổ điển (xem ML 5 — Đánh giá).

  • Naive: dự báo giá trị kế tiếp bằng đúng giá trị quan sát cuối cùng: ŷ(t+1) = y(t). Đơn giản nhưng cực mạnh với chuỗi giống bước ngẫu nhiên (random walk).
  • Seasonal-naive: dự báo bằng giá trị của cùng kỳ mùa vụ trước: ŷ(t) = y(t - m), với m là chu kỳ mùa vụ. Với giao dịch theo ngày, m = 7: dự báo thứ Hai tuần này bằng thứ Hai tuần trước. Đây là baseline khó thắng cho dữ liệu có mùa vụ tuần rõ rệt.
  • Trung bình trượt (moving average): dự báo bằng trung bình k giá trị gần nhất. Làm mượt nhiễu nhưng luôn trễ pha và không bắt được xu hướng.
  • Drift: naive có cộng thêm độ dốc trung bình của toàn chuỗi — kéo dài đường thẳng nối điểm đầu và điểm cuối.

Điểm mấu chốt: seasonal-naive thường là baseline mạnh nhất cho dữ liệu ngân hàng vì tính mùa vụ tuần/tháng rất ổn định. Mọi con số MAPE, RMSE (xem Chuỗi thời gian 6 — Đánh giá) của mô hình phức tạp đều phải đặt cạnh baseline này.

2. Làm mượt hàm mũ (Exponential Smoothing / ETS)

Ý tưởng cốt lõi: các quan sát gần hiện tại quan trọng hơn các quan sát xa. Thay vì trung bình đều mọi điểm (như moving average), ta gán trọng số giảm theo hàm mũ về quá khứ. Họ này còn gọi là ETS (Error, Trend, Seasonality).

2.1. SES — Simple Exponential Smoothing

Dùng cho chuỗi không có xu hướng, không mùa vụ (đi ngang quanh một mức). Công thức đệ quy của mức (level):

ℓ(t) = α · y(t) + (1 − α) · ℓ(t−1)
ŷ(t+1) = ℓ(t)

α (alpha, trong khoảng 0–1) là hệ số làm mượt. α gần 1 → phản ứng nhanh với dữ liệu mới nhưng nhiễu; α gần 0 → mượt và ì. Trực giác: mỗi ước lượng mức mới là trung bình có trọng số giữa "quan sát vừa thấy" và "niềm tin cũ". Dự báo nhiều bước tương lai đều bằng một hằng số (đường ngang).

2.2. Holt — thêm thành phần xu hướng (trend)

SES không dự báo được xu hướng: nếu giao dịch đang tăng đều, SES sẽ luôn dự báo thấp hơn thực tế. Holt's linear trend thêm một phương trình cho độ dốc (trend) b(t):

ℓ(t) = α · y(t) + (1 − α) · (ℓ(t−1) + b(t−1))
b(t) = β · (ℓ(t) − ℓ(t−1)) + (1 − β) · b(t−1)
ŷ(t+h) = ℓ(t) + h · b(t)

β (beta) điều khiển tốc độ cập nhật độ dốc. Dự báo h bước tới là đường thẳng dốc. Biến thể damped trend (xu hướng tắt dần) nhân độ dốc với hệ số φ < 1 để tránh ngoại suy tuyến tính vô hạn — thực tế thường chính xác hơn vì xu hướng hiếm khi kéo dài mãi.

2.3. Holt-Winters — thêm mùa vụ (seasonality)

Đây là phiên bản đầy đủ nhất cho dữ liệu ngân hàng: trend + seasonality. Thêm phương trình mùa vụ s(t) với m là độ dài chu kỳ và γ (gamma) là hệ số làm mượt mùa vụ. Có hai kiểu kết hợp mùa vụ:

  • Cộng tính (additive): biên độ dao động mùa vụ không đổi theo mức. ŷ(t+h) = ℓ(t) + h·b(t) + s(t+h−m).
  • Nhân tính (multiplicative): biên độ mùa vụ tỷ lệ thuận với mức của chuỗi (chuỗi càng lớn, dao động càng lớn). Rất phổ biến ở dữ liệu tài chính đang tăng trưởng — ví dụ dao động cuối tuần của giao dịch lớn dần khi tổng lượng giao dịch tăng.

Quy tắc chọn: nếu vẽ chuỗi thấy "cái phễu loe ra" (biên độ mùa vụ tăng theo mức) → dùng nhân tính; nếu biên độ đều → cộng tính. Ba tham số α, β, γ thường được ước lượng tự động bằng tối ưu hoá (tối thiểu hoá SSE), bạn hiếm khi phải chỉnh tay.

# Minh hoa — KHONG danh dau chay duoc (day la Python)
from statsmodels.tsa.holtwinters import ExponentialSmoothing

# y: Series khoi luong giao dich theo ngay, mua vu tuan m=7
model = ExponentialSmoothing(
    y,
    trend="add",              # xu huong cong tinh
    damped_trend=True,        # xu huong tat dan
    seasonal="mul",           # mua vu nhan tinh
    seasonal_periods=7,
).fit()

forecast = model.forecast(14)  # du bao 14 ngay toi
print(model.params)            # alpha, beta, gamma da uoc luong

3. Họ ARIMA

ARIMA tiếp cận từ góc khác: mô hình hoá tự tương quan (autocorrelation) — quan hệ giữa một giá trị và các giá trị trước đó của chính nó. Ba thành phần trong tên viết tắt:

  • AR(p) — AutoRegressive: giá trị hiện tại là tổ hợp tuyến tính của p giá trị trước đó. Ví dụ AR(1): y(t) = c + φ₁·y(t−1) + ε(t). Hiểu như "hôm nay phụ thuộc hôm qua".
  • I(d) — Integrated: số lần lấy sai phân (differencing) để biến chuỗi thành dừng (stationary). Sai phân bậc 1: y'(t) = y(t) − y(t−1), loại bỏ xu hướng. d thường là 0, 1 hoặc 2.
  • MA(q) — Moving Average: giá trị hiện tại phụ thuộc q sai số dự báo (nhiễu) trước đó, không phải giá trị. Ví dụ MA(1): y(t) = c + ε(t) + θ₁·ε(t−1).

Gộp lại: ARIMA(p, d, q). Điều kiện tiên quyết là chuỗi phải dừng sau khi sai phân d lần — dùng kiểm định ADF/KPSS để xác nhận (xem Chuỗi thời gian 2).

3.1. SARIMA — thêm thành phần mùa vụ

ARIMA thuần không bắt được mùa vụ tuần/tháng. SARIMA (Seasonal ARIMA) bổ sung bốn tham số mùa vụ: SARIMA(p,d,q)(P,D,Q,m).

  • (P, D, Q) là các bậc AR/I/MA nhưng áp dụng ở khoảng cách mùa vụ (lag m, 2m, ...).
  • m là độ dài chu kỳ: m = 7 cho mùa vụ tuần (dữ liệu ngày), m = 12 cho mùa vụ năm (dữ liệu tháng).
  • D là sai phân mùa vụ: y(t) − y(t−m), loại bỏ mẫu hình lặp lại theo mùa.

Ví dụ SARIMA(1,1,1)(1,1,1,7): sai phân thường 1 lần để bỏ xu hướng, sai phân mùa vụ 1 lần để bỏ mùa vụ tuần, cộng thành phần AR/MA cả ở lag ngắn lẫn lag 7.

3.2. Chọn bậc từ ACF/PACF

Cách chọn pq cổ điển dựa trên hai đồ thị (xem cách vẽ ở Chuỗi thời gian 2):

Đồ thịHành viGợi ý bậc
PACF (Partial ACF) cắt đứt sau lag p, ACF giảm dầnĐặc trưng ARChọn AR(p), q = 0
ACF cắt đứt sau lag q, PACF giảm dầnĐặc trưng MAChọn MA(q), p = 0
Cả ACF và PACF cùng giảm dầnARMA hỗn hợpThử p, q nhỏ và so sánh

"Cắt đứt" nghĩa là các thanh tương quan rơi vào vùng không ý nghĩa (dải xanh) một cách đột ngột. Đây là nghệ thuật hơn khoa học — thường bạn thử vài phương án quanh gợi ý và chọn bằng tiêu chí thông tin AIC/BIC (càng thấp càng tốt).

3.3. auto_arima — tự động tìm bậc

Trong thực tế, ít ai đọc ACF/PACF bằng mắt cho hàng trăm chuỗi. Thư viện pmdarima cung cấp auto_arima — tự động thử nhiều tổ hợp (p,d,q)(P,D,Q,m), chạy kiểm định dừng để chọn d/D, và giữ mô hình có AIC thấp nhất.

# Minh hoa — KHONG danh dau chay duoc (day la Python)
import pmdarima as pm

model = pm.auto_arima(
    y,
    seasonal=True, m=7,        # mua vu tuan
    d=None, D=None,            # de auto_arima tu chon bac sai phan
    start_p=0, start_q=0,
    max_p=3, max_q=3,
    stepwise=True,             # tim kiem theo buoc, nhanh hon vet can
    information_criterion="aic",
    trace=True,                # in cac mo hinh da thu
)
print(model.summary())
forecast, conf_int = model.predict(n_periods=14, return_conf_int=True)

Lưu ý: auto_arima tiện nhưng không phải nút thần kỳ. Nó có thể chọn mô hình overfit hoặc bỏ sót cấu trúc mùa vụ nếu m sai. Luôn kiểm tra phần dư và so với baseline.

4. Giả định & chẩn đoán phần dư

Một mô hình ARIMA/ETS được xem là tốt khi phần dư (residual = thực tế − dự báo) là white noise (nhiễu trắng): không còn cấu trúc nào để khai thác. Nếu phần dư vẫn còn tự tương quan, nghĩa là mô hình đã bỏ sót tín hiệu.

Bốn điều cần kiểm tra ở phần dư:

  1. Không tự tương quan: vẽ ACF của phần dư — mọi thanh phải nằm trong dải không ý nghĩa. Kiểm định chính thức là Ljung-Box test (p-value lớn → không bác bỏ giả thuyết "phần dư độc lập" → tốt).
  2. Trung bình bằng 0: nếu khác 0, dự báo bị lệch (bias) một cách hệ thống.
  3. Phương sai không đổi (homoscedastic): nếu phần dư "loe ra" theo thời gian, có thể cần biến đổi log hoặc mô hình phương sai (GARCH).
  4. Phân phối gần chuẩn: cần thiết để khoảng tin cậy dự báo (prediction interval) đáng tin.
# Minh hoa — KHONG danh dau chay duoc (day la Python)
from statsmodels.stats.diagnostic import acorr_ljungbox

resid = model.resid()                          # phan du cua mo hinh
lb = acorr_ljungbox(resid, lags=[7, 14], return_df=True)
print(lb)   # p-value > 0.05 o cac lag -> phan du gan white noise

5. Khi nào dùng ETS vs ARIMA?

Hai họ này chồng lấn (một số ETS tương đương một dạng ARIMA đặc biệt) nhưng khác nhau về triết lý và điểm mạnh:

Tiêu chíETS (Holt-Winters)ARIMA / SARIMA
Mô hình hoáLevel + Trend + Seasonality trực tiếpTự tương quan sau khi sai phân
Yêu cầu dừngKhông cần (xử lý xu hướng nội tại)Cần chuỗi dừng (phải sai phân)
Diễn giảiRất trực quan (3 thành phần)Trừu tượng hơn (hệ số AR/MA)
Mùa vụ nhân tínhHỗ trợ tự nhiênCần biến đổi log trước
Biến ngoại sinhKhông (thuần đơn biến)Có — dùng SARIMAX (thêm regressor)
Tự động hoáETS tự chọn dạng khá tốtauto_arima trưởng thành

Nguyên tắc thực dụng:

  • Chuỗi có mùa vụ rõ, biên độ tăng theo mức → thử Holt-Winters nhân tính trước, thường thắng nhanh.
  • Cần đưa biến ngoại sinh (ví dụ: ngày lễ, chiến dịch marketing, ngày cuối tháng lương về) → dùng SARIMAX, vì đây là điểm ETS không làm được.
  • Không chắc → chạy cả hai, so AIC và lỗi trên tập kiểm định, luôn đặt cạnh seasonal-naive.

Khi các mô hình cổ điển không đủ (nhiều mùa vụ chồng nhau, chuỗi rất dài, nhiều biến ngoại sinh phức tạp), hãy chuyển sang tiếp cận feature + ML ở Chuỗi thời gian 4 hoặc mô hình nâng cao ở Chuỗi thời gian 5.

Use case thực tế

Bối cảnh: Phòng Vận hành NCB cần dự báo số lượng giao dịch mỗi ngày tại một chi nhánh trong 14 ngày tới để bố trí nhân sự quầy và tiếp quỹ ATM. Dữ liệu: 18 tháng lịch sử giao dịch theo ngày (~540 điểm).

Bước 1 — Lấy dữ liệu. Tổng hợp giao dịch theo ngày từ bảng giao dịch để có chuỗi đầu vào:

-- ▶ Chạy được
SELECT date_trunc('day', created_at)::date AS ngay,
       COUNT(*)                            AS so_giao_dich
FROM transactions
GROUP BY 1
ORDER BY 1;

Bước 2 — EDA nhanh. Vẽ chuỗi thấy: xu hướng tăng nhẹ (khách hàng tăng), mùa vụ tuần rõ (thứ Bảy/Chủ nhật giảm ~40%), và biên độ dao động cuối tuần lớn dần theo thời gian → gợi ý mùa vụ nhân tính.

Bước 3 — Baseline. Seasonal-naive (m = 7): dự báo mỗi ngày bằng cùng thứ tuần trước. Đo trên tập kiểm định 14 ngày cuối: MAPE = 11.2%. Đây là mốc phải vượt.

Bước 4 — Thử hai mô hình.

Mô hìnhCấu hìnhMAPE (14 ngày)Ghi chú
Seasonal-naivem=711.2%baseline
Holt-Winterstrend add + damped, seasonal mul, m=77.8%nhanh, dễ giải thích
SARIMA(1,1,1)(1,1,1,7) qua auto_arima7.5%AIC thấp nhất

Bước 5 — Chẩn đoán. Chạy Ljung-Box trên phần dư SARIMA: p-value tại lag 7 và 14 đều > 0.3 → phần dư là white noise, mô hình đã bắt hết cấu trúc. Holt-Winters có phần dư còn tự tương quan nhẹ tại lag 7 nhưng chấp nhận được.

Kết luận: SARIMA và Holt-Winters cho kết quả gần như ngang nhau và cùng đánh bại baseline ~30% tương đối. Phòng Vận hành chọn Holt-Winters cho production vì dễ giải thích với lãnh đạo và tái huấn luyện tức thời mỗi tuần. Khi cần thêm biến "ngày lương về" (làm giao dịch tăng đột biến), họ dự phòng chuyển sang SARIMAX. Chi tiết vận hành và giám sát drift ở Chuỗi thời gian 8.

Ghi nhớ

  • Luôn có baseline trước: naive và seasonal-naive (m=7 cho dữ liệu ngày) là mốc bắt buộc; mô hình phức tạp phải vượt qua chúng mới có giá trị.
  • ETS = làm mượt hàm mũ: trọng số giảm theo hàm mũ về quá khứ. SES (chỉ level), Holt (+ trend), Holt-Winters (+ seasonality). Tham số α, β, γ điều khiển tốc độ cập nhật từng thành phần.
  • Mùa vụ nhân tính khi biên độ dao động tăng theo mức của chuỗi — rất phổ biến ở dữ liệu tài chính đang tăng trưởng.
  • ARIMA(p,d,q): AR (p giá trị trước), I (d lần sai phân để chuỗi dừng), MA (q sai số trước). SARIMA(p,d,q)(P,D,Q,m) thêm thành phần mùa vụ.
  • Chọn bậc: đọc ACF/PACF (PACF cắt đứt → AR; ACF cắt đứt → MA) hoặc để auto_arima chọn theo AIC — nhưng luôn kiểm tra lại.
  • Chẩn đoán phần dư: mô hình tốt khi phần dư là white noise (Ljung-Box p-value cao, ACF phần dư trong dải không ý nghĩa).
  • ETS vs ARIMA: ETS trực quan, không cần dừng; ARIMA linh hoạt hơn và qua SARIMAX đưa được biến ngoại sinh (ngày lễ, kỳ lương) — thứ ETS không làm được.

Bài viết liên quan

Phân biệt AI/ML/DL, các kiểu học máy, quy trình ML end-to-end và thuật ngữ nền tảng.

13 thg 7, 2026 14

Chất lượng dữ liệu, xử lý thiếu/ngoại lai, mã hoá, chuẩn hoá, tạo đặc trưng và tránh data leakage.

13 thg 7, 2026 13

Mô hình ngôn ngữ lớn hoạt động ra sao, token, context window, tham số sinh, và kỹ thuật viết prompt.

13 thg 7, 2026 13

Retrieval-Augmented Generation, vector database, tool calling, agent và MCP để xây ứng dụng LLM thực tế.

13 thg 7, 2026 11