Lời mở đầu
Chào các bạn, hôm nay tuy không rảnh lắm, nhưng mình vẫn thử dịch và viết một bài về Time Series data [dữ liệu theo thời gian]. Bài viết này dựa trên ý hiểu của mình khi đọc bài gốc, có gì sai sót mong các bạn bỏ qua.
Định nghĩa
Time series data là gì ? Để trả lời câu hỏi này, tôi sẽ đặt ra 3 tình huống:
- Bạn làm quản lý ở một nhà hàng pizza, bạn thấy mỗi thứ 7 giá đơn hàng tăng lên một chút, bạn muốn biết việc bán ra của mình có theo một quy luật đặc biệt nào không.
- Công ty của bạn bán một sản phẩm và bạn được giao nhiệm vụ dự đoán lượng mua, dự báo số nguyên liệu cần cho sản phẩm này.
- Bạn là người duy trì hệ thống dữ liệu tập trung. Bạn muốn phát hiện ra những vấn đề xảy ra trong tiến trình của hệ thống như việc sử dụng CPU bất bình thường dẫn đến máy chủ sập. Vì vậy bạn phải theo dõi giá trị sử dụng CPU theo thời gian.
Như các bạn thấy trong các ví dụ trên, tôi đã và đang làm việc với dữ liệu theo thời gian, từ đơn hàng cho đến dự đoán của sản phẩm, ... Thể hiện rõ nhất ở đây là biểu đồ chứng khoán.
Trong xã hội hiện đại, khi lượng thông tin càng ngày càng tăng, việc phân tích dữ liệu time series trở nên cực kỳ quan trọng, nhưng cho dù có nhiều thuật toán hay mô hình trí tuệ nhân tạo sinh ra, việc dự đoán tương lai vẫn thất bại do sự thiếu ổn định trong chuỗi thời gian.
Một vài thuật ngữ trong Time Series
Trend: xu hướng của dữ liệu [tăng hoặc giảm]. Điều này có thể phát hiện thông qua độ dốc của dữ liệu trên biểu đồ.
Seasonality: dữ liệu bị ảnh hưởng theo thước đo thời gian như: giờ, tuần, tháng, năm, ... Trong trường hợp, này dữ liệu có chu kỳ lặp đi lặp lại theo thước đo thời gian kể trên với một tần suất cố định.
Cyclicity: một chu kỳ xảy ra khi dữ liệu tăng và giảm không theo một tần suất cố định. Dễ thấy nhất ở đây là trong lĩnh vực kinh tế.
Residuals: dữ liệu time series có thể chia thành 2 loại: giá trị dự báo tại thời điểm t và phần thặng dư tại thời điểm t
Value of series at time t = Predicted value at time t + Residual at time t
Một số ví dụ:
- Chuỗi theo xu hướng tăng:
- Chuỗi theo chu kỳ với tần suất cố định:
- Chuỗi theo chu kỳ với tần suất không cố định:
- Chuỗi chả theo thể loại gì:
Một chuỗi cũng có thể là tổ hợp của nhiều loại kể trên.
Tính ổn định của chuỗi
Đơn giản hiểu là một chuỗi lặp đi lặp lại theo một chu kỳ, giá trị không tăng theo thời gian. Dự đoán chuỗi có tính ổn định rất dễ do có các đặc tính như: mean, variance, autocorrelation, ...
Biến đổi về chuỗi ổn định
Đại đa số trường hợp chúng ta bắt gặp các chuỗi bất ổn định, vì vậy cần phải loại bỏ những yếu tố gây bất ổn định.
- De-trending [thủ tiêu xu hướng]: như tên gọi, loại bỏ các khu vực mang yếu tố xu hướng trong chuỗi. Việc loại bỏ có nhiều cách, phụ thuộc vào bản chất của dữ liệu: index hay non-index.
- Differencing: seasonal hoặc cyclical có thể được loại bỏ bằng cách lấy giá trị quan sát tại thời điểm t trừ giá trị quan sát tại thời điểm t-1.
- Logging: nôm na là khi xu hướng không dựa trên chỉ số giá cả [trong trường hợp không phải chuỗi tiền tệ] , logging sẽ biến chuỗi thành một chuỗi tuyến tính [log[exp[x]].
Pratice code
Kiểm tra tính ổn định của chuỗi
Visualize
Cách đơn giản nhất là quan sát chuỗi bằng mắt thường. Nếu bạn là dân code ngôn ngữ python-er như mình có thể dùng thư viện matplotlib để vẽ dữ liệu thành biểu đồ.
Ở đây tôi dùng dữ liệu xuất nhập khẩu Úc-Nhật.
csv_path = "/home/pham.minh.hoang/Pictures/monthly-australian-imports-from-.csv"
data_imports = pd.read_csv[csv_path][:-1:]
data = data_imports.drop[['Month'], 1]
data.values.reshape[-1,1]
plt.plot[data]
plt.title['Australian imports']
plt.show[]
data_detrend = [data - data.rolling[window=12].mean[]] / data.rolling[window=12].std[]
data_season = data_detrend - data_detrend.shift[12]
fig, ax = plt.subplots[3,figsize=[12, 9]]
ax[0].plot[data.index, data, label='raw data']
ax[0].plot[data.rolling[window=12].mean[], label="rolling mean"];
ax[0].plot[data.rolling[window=12].std[], label="rolling std [x10]"];
ax[0].legend[]
ax[1].plot[data.index, data_detrend, label="de-trended data"]
ax[1].plot[data_detrend.rolling[window=12].mean[], label="rolling mean"];
ax[1].plot[data_detrend.rolling[window=12].std[], label="rolling std [x10]"];
ax[1].legend[]
ax[2].plot[data.index, data_season, label="12 lag differenced de-trended data"]
ax[2].plot[data_season.rolling[window=12].mean[], label="rolling mean"];
ax[2].plot[data_season.rolling[window=12].std[], label="rolling std [x10]"];
ax[2].legend[]
plt.tight_layout[]
fig.autofmt_xdate[]
Adfuller
Cách 2, dùng adfuller test để kiểm tra tính ổn định của chuỗi. Bạn cần tải về thư viện statsmodels
pip install statsmodels
from statsmodels.tsa.stattools import adfuller
print[" > Is the data stationary ?"]
dftest = adfuller[data, autolag='AIC']
print["Test statistic = {:.3f}".format[dftest[0]]]
print["P-value = {:.3f}".format[dftest[1]]]
print["Critical values :"]
for k, v in dftest[4].items[]:
print["\t{}: {} - The data is {} stationary with {}% confidence".format[k, v, "not" if v Is the de-trended data stationary ?
Test statistic = -5.070
P-value = 0.000
Critical values :
1%: -3.4514162625887037 - The data is stationary with 99% confidence
5%: -2.8708187088091406 - The data is stationary with 95% confidence
10%: -2.5717136883095675 - The data is stationary with 90% confidence
> Is the 12-lag differenced de-trended data stationary ?
Test statistic = -5.530
P-value = 0.000
Critical values :
1%: -3.4521175397304784 - The data is stationary with 99% confidence
5%: -2.8711265007266666 - The data is stationary with 95% confidence
10%: -2.571877823851692 - The data is stationary with 90% confidence
KPSS
Cách 3, dùng KPSS test với giả thuyết rằng chuỗi có xu hướng ổn định. Nói cách khác, p-value < X% độ tin cậy => loại bỏ giả thuyết này, chuỗi không có xu hướng ổn định và ngược lại.
from statsmodels.tsa.stattools import kpss
print[" > Is the data stationary ?"]
statistic, p_value, n_lags, critical_values = kpss[data]
print["Test statistic = {:.3f}".format[statistic]]
print["P-value = {:.3f}".format[p_value]]
print["num lags: {}".format[n_lags]]
print["Critical values :"]
for k, v in critical_values.items[]:
print[f' {k} : {v}']
print[f'Result: The series is {"not " if p_value