《從零開始的資料科學筆記》Day#18: 資料具有時間特性怎麼訓練?

更新 發佈閱讀 26 分鐘
raw-image

在現實生活中,許多資料並非靜止的,它們會隨著時間不斷變化,形成了一種特殊的資料型態,這就是時間序列資料。時間序列數據廣泛存在於各種領域,如金融市場的股票價格波動、氣候監測的溫度變化、製造業的機器故障檢測,以及網站流量的每日訪問量等。這些資料的最大特點在於:當前的觀測值與過去的值密切相關,未來的趨勢也會受到歷史數據的驅動。

在進行時間序列分析時,簡單的靜態建模方法往往不足以捕捉數據的時間依賴性或動態特徵。例如,在股票預測中,今天的收盤價與昨天的收盤價必然具有一定相關性,僅僅依靠單次獨立的觀測結果無法準確預測未來的趨勢。因此,時間序列分析的重點在於:如何利用數據的時間特性進行建模,挖掘時間依賴模式與變化規律,並在此基礎上做出準確預測。

在這篇筆記中,我會聚焦於如何針對具有時間特性的資料訓練模型,並讓大家了解以下兩個核心問題:

  1. 如何建構特徵,讓模型能理解時間的動態特性?
  2. 如何設計模型與驗證方法,確保它既考慮因果關係,又具有預測穩定性?

⏳ 什麼是時間序列分析?

時間序列分析(Time Series Analysis)是一種針對隨時間變化的資料所採用的分析方法,主要在研究資料在時間軸上的模式和趨勢,並利用這些結構性特徵進行描述、解釋和預測。 時間序列數據的最大特點是時序性,其核心假設是:過去的行為會影響未來的趨勢

時間序列資料的定義

時間序列數據是一組依據時間順序排列的觀測值,通常包括規律的時間間隔,例如:

  • 一天中的溫度變化(小時為單位)
  • 每月公司的銷售數據(月份為單位)
  • 每秒的心跳頻率(秒為單位)

這些數據中的觀測值彼此之間並非獨立,而是存在一定的依賴性。這種依賴性可能反映在長期的趨勢、週期性變化,或者短期的隨機波動中。

時間序列資料的基本元素

時間序列數據可以被分解為以下幾個主要部分:

  1. 趨勢(Trend):
  • 描述數據在長期的整體變化方向,可能是逐漸增加、減少或維持穩定。
  • 示例:隨著時間推移,全球平均氣溫逐漸升高。
  1. 季節性(Seasonality):
  • 描述數據在固定時間間隔內的重複模式。
  • 示例:零售業每年聖誕期間銷售激增,或者氣溫隨季節變化有明顯周期性波動。
  1. 週期性(Cycle):
  • 與季節性不同,週期性並不一定是固定間隔的變化模式,通常與商業或經濟循環相關。
  • 示例:經濟的繁榮與衰退循環。
  1. 隨機性(Noise):
  • 數據中不可預測的隨機波動部分,通常沒有明顯的模式。
  • 示例:股票市場的短期波動,以及因外部偶然事件導致的異常變動。

時間序列分析的典型方法

針對時間序列資料的特性,分析方式主要分為統計方法機器學習/深度學習方法

統計方法

適用於資料具有較強的線性或穩定模式的情況:

  • 移動平均法(Moving Average, MA):用於平滑數據,消除短期波動,反映長期趨勢
  • 自回歸模型(AR):利用歷史數據的滯後值預測當前值
  • ARIMA(自回歸整合移動平均模型):是 AR 與 MA 的結合,可用於穩定與季節資料的建模與預測
  • SARIMA(季節性 ARIMA):進一步結合季節性,適合具有固定周期波動的資料

機器學習方法

適用於資料具有非線性、復雜關係,或需要處理大規模特徵的情況:

  • 樹狀演算法: XGBoost, Random Forests
  • 支持向量機(SVM)

深度學習方法

適用於長記憶、非線性和超大規模的時序建模,對於非常複雜的動態序列表現出色:

  • LSTM / GRU(長短期記憶):對長期依賴性建模效果優異
  • Conv1D(卷積時間序列):適用於局部結構模式檢測
  • Transformer:優化了長距依賴和注意力機制,能更靈活和穩健地建模時間序列。

時間序列分析的應用場景

金融市場預測:

  • 預測股票價格、外匯匯率和債券收益等

銷售與供應鏈:

  • 預測產品的需求量,制定生產和庫存計劃

氣象預測:

  • 預測氣溫、降雨量、颱風路徑等

異常檢測:

  • 發現工業設備運行中的不正常信號,提前預測機器故障

交通流量分析:

  • 預測道路車流量或網絡流量

健康數據監測:

  • 分析心率、血壓等生命體徵,進行健康風險評估

🧾 0. 環境建議與可重現性

安裝所需套件:

pip install numpy pandas matplotlib seaborn statsmodels scikit-learn prophet

設定亂數種子:

RANDOM_STATE = 42

📦 1. 資料集說明(Dataset Card)

  • 名稱:Daily Weather Data
  • 來源:Kaggle - Daily Climate Time Series(或 NOAA、任意地區氣象局公開資料)
  • 任務:時間序列迴歸(預測未來日均氣溫)
  • 欄位:
    • date:日期
    • meantemp:日均氣溫(°C)
    • 其他可能欄位:降雨量、濕度、風速,可作為多變量特徵

🔎 2. 載入與初探(Loading & Quick EDA)

從日均溫的圖可以看出,此份資料擁有特定的模式,搭配時間來看的話就知道是每年6、7月份開始溫度會持續往上,12、1月開始往下,形成這種起伏的圖形。 這就是一種擁有標準季節性特點的時間序列資料。

import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.dates import AutoDateLocator, DateFormatter
import seaborn as sns
import kagglehub
import os


# Download latest version
path = kagglehub.dataset_download("sumanthvrao/daily-climate-time-series-data")
print("Path to dataset files:", path)
os.listdir(path)

df = pd.read_csv(os.path.join(path, 'DailyDelhiClimateTrain.csv'))
df = df.sort_values("date")
df.set_index("date", inplace=True)

# 檢查資料
print(df.info())
print(df.describe())
print("Missing values:", df.isna().sum())

# 繪製每日平均溫度,僅顯示年月於 X 軸
plt.figure(figsize=(12, 4))
plt.plot(df["meantemp"])
plt.title("Daily Average Temperature")
plt.xlabel("Date")
plt.ylabel("Temperature (°C)")

# 格式化 X 軸日期顯示為年月
plt.gca().xaxis.set_major_formatter(plt.matplotlib.dates.DateFormatter('%Y-%m'))

ax = plt.gca()
ax.xaxis.set_major_locator(AutoDateLocator(maxticks=12)) # 每年最多顯示 12 個標籤
ax.xaxis.set_major_formatter(DateFormatter('%Y-%m'))
plt.gcf().autofmt_xdate()

plt.show()
Index: 1462 entries, 2013-01-01 to 2017-01-01
Data columns (total 4 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 meantemp 1462 non-null float64
1 humidity 1462 non-null float64
2 wind_speed 1462 non-null float64
3 meanpressure 1462 non-null float64

meantemp humidity wind_speed meanpressure
count 1462.000000 1462.000000 1462.000000 1462.000000
mean 25.495521 60.771702 6.802209 1011.104548
std 7.348103 16.769652 4.561602 180.231668
min 6.000000 13.428571 0.000000 -3.041667
25% 18.857143 50.375000 3.475000 1001.580357
50% 27.714286 62.625000 6.221667 1008.563492
75% 31.305804 72.218750 9.238235 1014.944901
max 38.714286 100.000000 42.220000 7679.333333

Missing values: meantemp 0
humidity 0
wind_speed 0
meanpressure 0
raw-image

🧼 3. 資料前處理(Preprocessing)

  • 如果有缺失值,則用線性差補法補值
  • 使用盒鬚圖來檢查異常值,從圖上來看,並沒有任何資料點落在上下界線以外的地方,因此判斷沒有異常值
# 缺值處理:線性插補
df["meantemp"] = df["meantemp"].interpolate(method="linear")

# 檢查是否有異常值(用盒鬚圖觀察)
sns.boxplot(x=df["meantemp"])
plt.title("Temperature Distribution")
plt.show()
raw-image

📊 4. 趨勢與季節性分析(Trend & Seasonality Analysis)

時間序列分析的任務相比其他任務,會需要在建模之前多一些檢查資料的步驟,用以確定此份資料集真的適用於時間序列分析的技術。

4.1 趨勢與季節性視覺化

以結果來看:

  • 具備季節性: 固定的波動
  • 具備趨勢性: 趨勢穩定向上
  • 具備隨機性: 殘差均勻分布在零線兩側

後面較進階的分析留待之後的筆記中再說明。

from statsmodels.tsa.seasonal import seasonal_decompose

decomp = seasonal_decompose(df["meantemp"], model="additive", period=365)
decomp.plot()
plt.suptitle("Trend, Seasonality, and Residuals", y=1.02)
plt.show()
raw-image

4.2 平穩性檢定(Stationarity Test)

from statsmodels.tsa.stattools import adfuller

adf_result = adfuller(df["meantemp"])
print("ADF Statistic:", adf_result[0])
print("p-value:", adf_result[1])
if adf_result[1] < 0.05:
print("=> 平穩,可直接建模")
else:
print("=> 不平穩,建議做差分或使用SARIMA")
ADF Statistic: -2.0210690559206714
p-value: 0.2774121372301609
=> 不平穩,建議做差分或使用SARIMA

4.3 自相關分析(ACF & PACF)

from statsmodels.graphics.tsaplots import plot_acf, plot_pacf

fig, ax = plt.subplots(1, 2, figsize=(12, 4))
plot_acf(df["meantemp"], lags=50, ax=ax[0])
plot_pacf(df["meantemp"], lags=50, ax=ax[1])
ax[0].set_title("Autocorrelation Function (ACF)")
ax[1].set_title("Partial Autocorrelation Function (PACF)")
plt.show()
raw-image

📉 5. 訓練/測試資料切分(Train-Test Split)

時間序列分析的資料集在切分的時候必須依照時間的先後切分,不能像其他任務一樣隨機切分,會將之前的一段時間當做訓練資料,後面的時間當做測試資料。

df_test = pd.read_csv(os.path.join(path, 'DailyDelhiClimateTest.csv'))
df_test = df_test.sort_values("date")
df_test.set_index("date", inplace=True)
train = df
test = df_test

plt.figure(figsize=(12,4))
plt.plot(train.index, train["meantemp"], label="Train")
plt.plot(test.index, test["meantemp"], label="Test")
plt.legend()
plt.title("Train-Test Split")
plt.show()
raw-image

🧠 6. 建立基準模型(Baseline)

使用naive方法 (預測今天 = 昨天的溫度)

y_pred_naive = test.shift(1)["meantemp"]
mae_naive = (test["meantemp"] - y_pred_naive).abs().mean()
print("Baseline MAE:", mae_naive)
Baseline MAE: 1.3176342284233629

🔧 7. 建立 ARIMA 模型

模型訓練過程會產些一些表格跟數字,可以暫時忽略,直接看最後的預測圖,可以發現模型預測的一點也不準。 因為只單純以時間跟日均溫來建模,沒有納入其他相關的外部特徵(如:降雨量、濕度等),也沒有進行模型的參數調整。

from statsmodels.tsa.arima.model import ARIMA
from sklearn.metrics import mean_absolute_error, root_mean_squared_error

model = ARIMA(train["meantemp"], order=(5,1,2))
model_fit = model.fit()
print(model_fit.summary())

y_pred_arima = model_fit.forecast(steps=len(test))
mae_arima = mean_absolute_error(test["meantemp"], y_pred_arima)
print("ARIMA MAE:", mae_arima)

plt.figure(figsize=(12,4))
plt.plot(train.index, train["meantemp"], label="Train")
plt.plot(test.index, test["meantemp"], label="Test")
plt.plot(test.index, y_pred_arima, label="ARIMA Forecast")
plt.legend()
plt.show()
                               SARIMAX Results                                
==============================================================================
Dep. Variable: meantemp No. Observations: 1462
Model: ARIMA(5, 1, 2) Log Likelihood -2764.775
Date: Fri, 12 Sep 2025 AIC 5545.551
Time: 15:13:35 BIC 5587.846
Sample: 01-01-2013 HQIC 5561.328
- 01-01-2017
Covariance Type: opg
==============================================================================
coef std err z P>|z| [0.025 0.975]
------------------------------------------------------------------------------
ar.L1 -0.1991 0.545 -0.365 0.715 -1.268 0.870
ar.L2 0.4022 0.331 1.214 0.225 -0.247 1.052
ar.L3 -0.0749 0.037 -2.031 0.042 -0.147 -0.003
ar.L4 -0.0208 0.056 -0.371 0.710 -0.130 0.089
ar.L5 0.0099 0.047 0.210 0.833 -0.082 0.102
ma.L1 -0.0217 0.544 -0.040 0.968 -1.088 1.045
ma.L2 -0.5639 0.445 -1.266 0.205 -1.437 0.309
sigma2 2.5772 0.074 34.839 0.000 2.432 2.722
===================================================================================
Ljung-Box (L1) (Q): 0.00 Jarque-Bera (JB): 264.82
Prob(Q): 1.00 Prob(JB): 0.00
Heteroskedasticity (H): 0.80 Skew: -0.47
Prob(H) (two-sided): 0.01 Kurtosis: 4.86
===================================================================================

ARIMA MAE: 8.775028671142111
raw-image

📏 8. 模型評估

rmse = mean_squared_error(test["meantemp"], y_pred_arima, squared=False)
mae = mean_absolute_error(test["meantemp"], y_pred_arima)
print("RMSE:", rmse, "MAE:", mae)
RMSE: 10.73003505614012 
MAE: 8.775028671142111

🔮 9. 模型推論與保存

import joblib

# 保存ARIMA模型
joblib.dump(model_fit, "arima_temperature_model.joblib")

# 載入模型並推論未來7天
loaded_model = joblib.load("arima_temperature_model.joblib")
future_forecast = loaded_model.forecast(steps=7)
print("Next 7 days forecast:")
print(future_forecast)
Next 7 days forecast:
2017-01-02 11.338623
2017-01-03 12.027578
2017-01-04 12.776290
2017-01-05 12.918541
2017-01-06 13.061968
2017-01-07 13.033440
2017-01-08 13.077401
Freq: D, Name: predicted_mean, dtype: float64

✅ 後續改善方向

  • 嘗試不同 ARIMA 參數組合 (p,d,q),使用 AIC / BIC 選擇最佳模型
  • 嘗試使用 SARIMA 模型,加入季節性參數 (P,D,Q,m)
  • 比較 Prophet 與 ARIMA 的 MAE、RMSE
  • 嘗試用 LSTM 或 GRU 模型做預測(進階練習)
  • 用外部特徵(降雨量、濕度)建立多變量模型,觀察是否能提升預測效果
留言
avatar-img
留言分享你的想法!
avatar-img
Ethan的AI學習筆記
4會員
29內容數
我是一個不務正業的資料科學家,從零開始學習的路途上跌跌撞撞,跌過許多坑,也撞過許多牆... 當有人迷失方向時,希望這些筆記可以成為你的指南針。
Ethan的AI學習筆記的其他內容
2025/10/04
在剛接觸機器學習時,會學習到模型是使用一組特徵X和標籤Y來訓練的,例如:使用房子的坪數、屋齡、地段等特徵可以預測這間房子的房價,這就是機器學習中迴歸分析的經典應用。但是在現實場景中,往往會出現數量龐大但是沒有明確標籤或類別的資料,這時應該怎麼利用這些資料,才能挖掘出潛藏在資料中的訊息?
Thumbnail
2025/10/04
在剛接觸機器學習時,會學習到模型是使用一組特徵X和標籤Y來訓練的,例如:使用房子的坪數、屋齡、地段等特徵可以預測這間房子的房價,這就是機器學習中迴歸分析的經典應用。但是在現實場景中,往往會出現數量龐大但是沒有明確標籤或類別的資料,這時應該怎麼利用這些資料,才能挖掘出潛藏在資料中的訊息?
Thumbnail
2025/09/23
疾病診斷在醫學領域中是一項非常重要的任務,正確的診斷能夠有效幫助患者及早接受治療,改善預後,並避免不必要的風險。然而,疾病診斷通常需要依賴大量且複雜的數據分析,例如病患的檢測數值、影像和臨床數據等。面對如此大量的資料,人工診斷可能會因主觀判斷或疲勞而存在不確定性,這便為機器學習和人工智慧提供了一個巨
Thumbnail
2025/09/23
疾病診斷在醫學領域中是一項非常重要的任務,正確的診斷能夠有效幫助患者及早接受治療,改善預後,並避免不必要的風險。然而,疾病診斷通常需要依賴大量且複雜的數據分析,例如病患的檢測數值、影像和臨床數據等。面對如此大量的資料,人工診斷可能會因主觀判斷或疲勞而存在不確定性,這便為機器學習和人工智慧提供了一個巨
Thumbnail
2025/09/20
在學習完機器學習的各種基礎知識後,我們終於可以開始進入實際應用的階段。機器學習的常見應用大致可分為四大類:迴歸(Regression)、分類(Classification)、分群(Clustering)、以及時間序列分析(Time Series Analysis)。身為資料科學家,理解並掌握這些方法
Thumbnail
2025/09/20
在學習完機器學習的各種基礎知識後,我們終於可以開始進入實際應用的階段。機器學習的常見應用大致可分為四大類:迴歸(Regression)、分類(Classification)、分群(Clustering)、以及時間序列分析(Time Series Analysis)。身為資料科學家,理解並掌握這些方法
Thumbnail
看更多
你可能也想看
Thumbnail
還在煩惱平凡日常該如何增添一點小驚喜嗎?全家便利商店這次聯手超萌的馬來貘,推出黑白配色的馬來貘雪糕,不僅外觀吸睛,層次豐富的雙層口味更是讓人一口接一口!本文將帶你探索馬來貘雪糕的多種創意吃法,從簡單的豆漿燕麥碗、藍莓果昔,到大人系的奇亞籽布丁下午茶,讓可愛的馬來貘陪你度過每一餐,增添生活中的小確幸!
Thumbnail
還在煩惱平凡日常該如何增添一點小驚喜嗎?全家便利商店這次聯手超萌的馬來貘,推出黑白配色的馬來貘雪糕,不僅外觀吸睛,層次豐富的雙層口味更是讓人一口接一口!本文將帶你探索馬來貘雪糕的多種創意吃法,從簡單的豆漿燕麥碗、藍莓果昔,到大人系的奇亞籽布丁下午茶,讓可愛的馬來貘陪你度過每一餐,增添生活中的小確幸!
Thumbnail
本月交易日誌紀錄,主要為情緒與交易紀錄,同時公開分享給有興趣的交易者,同時也很歡迎交流。
Thumbnail
本月交易日誌紀錄,主要為情緒與交易紀錄,同時公開分享給有興趣的交易者,同時也很歡迎交流。
Thumbnail
如果只擷取自己喜歡的歷史片段,忽略其他不同的發展,以為發現走勢的規律,其實只是假象,股市不一定會按照理性邏輯發展,在沒有秩序的地方硬要找出秩序來可能徒勞無功,歷史規律是有參考價值,但不一定可以適用到每一次的不同背景環境差異。
Thumbnail
如果只擷取自己喜歡的歷史片段,忽略其他不同的發展,以為發現走勢的規律,其實只是假象,股市不一定會按照理性邏輯發展,在沒有秩序的地方硬要找出秩序來可能徒勞無功,歷史規律是有參考價值,但不一定可以適用到每一次的不同背景環境差異。
Thumbnail
放眼長遠,關注積極因素,而非過度執著於短期價格波動。
Thumbnail
放眼長遠,關注積極因素,而非過度執著於短期價格波動。
Thumbnail
只是短短幾個交易日,趨勢和型態幾乎是一面倒的改變,75%以上都是...
Thumbnail
只是短短幾個交易日,趨勢和型態幾乎是一面倒的改變,75%以上都是...
Thumbnail
本研究使用了盤中逐筆成交資料(Tick-by-tick Data)來進行股票價格的預測,並討論了馬可夫鏈模型和擴散核模型在這方面的應用。研究結果表明,大多數股票的未來三秒價格可以在少於22個狀態中找到,顯示了交易價格的低不確定性。此外,研究還發現波動性更大和價格更高的股票更難以準確預測。
Thumbnail
本研究使用了盤中逐筆成交資料(Tick-by-tick Data)來進行股票價格的預測,並討論了馬可夫鏈模型和擴散核模型在這方面的應用。研究結果表明,大多數股票的未來三秒價格可以在少於22個狀態中找到,顯示了交易價格的低不確定性。此外,研究還發現波動性更大和價格更高的股票更難以準確預測。
Thumbnail
行情在絕望中誕生,在希望中毀滅。行情創高時一定是有人認為前景樂觀才推升股價,但同時也有人擔心行情在希望中毀滅而賣出股票,各自不同的解讀,其間的差異是在時間,回顧過去及想像未來的時間長度不一樣
Thumbnail
行情在絕望中誕生,在希望中毀滅。行情創高時一定是有人認為前景樂觀才推升股價,但同時也有人擔心行情在希望中毀滅而賣出股票,各自不同的解讀,其間的差異是在時間,回顧過去及想像未來的時間長度不一樣
Thumbnail
今天看到一段話蠻有感覺的,就是「預測和預期的差別是什麼?」
Thumbnail
今天看到一段話蠻有感覺的,就是「預測和預期的差別是什麼?」
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News