聊天視窗

量化投資的藝術:策略設計、實作與風險控管 - 第 9 章

第九章 機器學習進階:深度學習與強化學習

發布於 2026-03-06 09:59

# 第九章 機器學習進階:深度學習與強化學習 量化投資的數據量與複雜性不斷上升,傳統的機器學習方法已難以捕捉時序依賴與高維交互。深度學習(DL)與強化學習(RL)在金融時序數據與決策制定上展現了強大潛力。本章將從理論、實作到風險管理,全面拆解 **LSTM、Transformer、DQN** 等主流框架在量化投資中的應用。 --- ## 9.1 先驅概覽 | 方法 | 核心思想 | 典型用途 | 主要優勢 | 潛在缺陷 | |------|----------|----------|----------|----------| | LSTM | 長短期記憶門控 | 時序預測、波動率預測 | 能保留長距離依賴 | 過擬合風險高,訓練慢 | | Transformer | 自注意力機制 | 時序分解、預測、特徵交互 | 兼容並行,捕捉全局依賴 | 資源佔用大,訓練成本高 | | DQN (Deep Q-Network) | 強化學習 + 深度神經網絡 | 自動化交易、資產配置 | 可學習動態策略,適應環境變化 | 需要大量交互數據,收斂慢 | > **關鍵點**:深度模型需要**大量標記資料**與**高效的 GPU**支援,並且對**過擬合**與**可解釋性**特別敏感。 --- ## 9.2 LSTM 在金融時序預測中的實務 ### 9.2.1 理論基礎 LSTM 透過輸入門、遺忘門與輸出門,能在序列中維持長距離記憶,適合解決 **vanishing/exploding gradient** 問題。其數學表達式: \[ \begin{aligned} f_t &= \sigma(W_f \cdot [h_{t-1}, x_t] + b_f) \\ \i_t &= \sigma(W_i \cdot [h_{t-1}, x_t] + b_i) \\ \o_t &= \sigma(W_o \cdot [h_{t-1}, x_t] + b_o) \\ \tilde{c}_t &= \tanh(W_c \cdot [h_{t-1}, x_t] + b_c) \\ \c_t &= f_t \odot \c_{t-1} + i_t \odot \tilde{c}_t \\ \h_t &= o_t \odot \tanh(\c_t) \end{aligned} \] ### 9.2.2 實作範例:股價回報率預測 python import numpy as np import pandas as pd from sklearn.preprocessing import MinMaxScaler from tensorflow.keras.models import Sequential from tensorflow.keras.layers import LSTM, Dense, Dropout from tensorflow.keras.callbacks import EarlyStopping # 1. 資料載入與預處理 price_df = pd.read_csv('daily_price.csv', parse_dates=['Date'], index_col='Date') returns = price_df['Close'].pct_change().dropna().values.reshape(-1, 1) scaler = MinMaxScaler(feature_range=(0, 1)) scaled = scaler.fit_transform(returns) # 2. 建立時序資料集 look_back = 30 # 30 天窗口 X, y = [], [] for i in range(len(scaled) - look_back): X.append(scaled[i:i+look_back]) y.append(scaled[i+look_back]) X, y = np.array(X), np.array(y) X = X.reshape((X.shape[0], X.shape[1], 1)) # 3. 模型結構 model = Sequential([ LSTM(64, input_shape=(look_back, 1), return_sequences=True), Dropout(0.2), LSTM(32), Dropout(0.2), Dense(1) ]) model.compile(optimizer='adam', loss='mse') # 4. 訓練 early = EarlyStopping(patience=10, restore_best_weights=True) model.fit(X, y, epochs=200, batch_size=32, validation_split=0.2, callbacks=[early]) # 5. 評估 pred = model.predict(X) rmse = np.sqrt(np.mean((pred - y)**2)) print('RMSE:', rmse) #### 重要參數 | 參數 | 說明 | 建議取值 | |------|------|----------| | `look_back` | 時間窗口 | 20~60 | | `units` | LSTM 隱藏單元 | 32~128 | | `dropout` | 避免過擬合 | 0.1~0.3 | | `batch_size` | 訓練批次 | 16~64 | ### 9.2.3 過擬合與正則化 * **早停**:觀察驗證集損失,停留最佳權重。<br>* **Dropout**:隨機丟棄部分門控訊號。<br>* **資料增強**:對波動率高的時段進行「滑動窗口」擴充。<br>* **交叉驗證**:使用時序交叉驗證,確保未來資料不被泄露。 --- ## 9.3 Transformer 在金融預測中的應用 ### 9.3.1 為何選擇 Transformer? 傳統 LSTM 在長序列上計算複雜度高,且不能並行。Transformer 透過 **自注意力**(Self‑Attention)直接捕捉全局依賴,訓練可並行化,適合處理 **多資產、跨市場** 的高維時序數據。 ### 9.3.2 典型模型:Finformer(金融 Transformer) python import torch import torch.nn as nn import torch.nn.functional as F class Finformer(nn.Module): def __init__(self, seq_len, d_model=64, n_heads=4, num_layers=3, dropout=0.1): super().__init__() self.pos_emb = nn.Parameter(torch.zeros(1, seq_len, d_model)) encoder_layer = nn.TransformerEncoderLayer(d_model=d_model, nhead=n_heads, dim_feedforward=256, dropout=dropout) self.transformer = nn.TransformerEncoder(encoder_layer, num_layers=num_layers) self.fc = nn.Linear(d_model, 1) def forward(self, src): # src: (batch, seq_len, d_model) src = src + self.pos_emb out = self.transformer(src) # (batch, seq_len, d_model) out = out[:, -1, :] # use last token representation return self.fc(out) #### 參數說明 | 參數 | 作用 | 建議範圍 | |------|------|----------| | `seq_len` | 序列長度 | 30~120 | | `d_model` | 嵌入維度 | 32~128 | | `n_heads` | 多頭注意力數 | 2~8 | | `num_layers` | Transformer 層數 | 2~6 | | `dropout` | 正則化 | 0.1~0.3 | ### 9.3.3 跨資產特徵交互 Transformer 的多頭注意力能自然學習 **不同股票之間** 的相互影響。例如,將同時期的多支股票回報、波動率、成交量堆疊成 `(batch, seq_len, asset_num * feature_num)`,Transformer 會自動挖掘「領先指標」與「共動因子」。 ### 9.3.4 可解釋性工具 * **Attention Map**:可視化每個資產對預測結果的影響。<br>* **SHAP**:結合 Transformer 輸出,估計特徵重要度。<br>* **Grad‑CAM**:適用於 CNN 風格的 Transformer,提取關鍵時間窗。 --- ## 9.4 強化學習:從 DQN 到 PPO ### 9.4.1 RL 框架概覽 | 方法 | 典型場景 | 優點 | 缺點 | |------|----------|------|------| | DQN | 單股票交易 | 簡單實作,離散行動 | 需要大量樣本,穩定性差 | | Double DQN | 與 DQN 同 | 消除過估計 | 同樣受限於離散行動 | | DDPG / TD3 | 連續權重調整 | 連續空間 | 需要精細的環境設計 | | PPO | 連續或離散 | 穩定收斂,易於調參 | 計算量大 | > 本章以 **DQN** 為入門示例,後續可延伸至 **PPO**、**DDPG**。 ### 9.4.2 環境設計 python import gym import numpy as np class StockTradingEnv(gym.Env): def __init__(self, price_series, window=30, initial_cash=10000): super().__init__() self.price = price_series.values self.window = window self.initial_cash = initial_cash self.action_space = gym.spaces.Discrete(3) # 0: hold, 1: buy, 2: sell self.observation_space = gym.spaces.Box(low=-np.inf, high=np.inf, shape=(window, 1), dtype=np.float32) self.reset() def reset(self): self.idx = self.window self.cash = self.initial_cash self.holdings = 0 return self._get_observation() def _get_observation(self): return self.price[self.idx-self.window:self.idx].reshape(-1, 1) def step(self, action): price_now = self.price[self.idx] reward = 0 if action == 1: # buy self.holdings += 1 self.cash -= price_now elif action == 2: # sell if self.holdings > 0: self.holdings -= 1 self.cash += price_now self.idx += 1 done = self.idx >= len(self.price) # Portfolio value portfolio_value = self.cash + self.holdings * self.price[self.idx-1] reward = portfolio_value - self.initial_cash return self._get_observation(), reward, done, {} ### 9.4.3 DQN 實作(使用 Stable‑Baselines3) python from stable_baselines3 import DQN from stable_baselines3.common.vec_env import DummyVecEnv env = DummyVecEnv([lambda: StockTradingEnv(price_series)]) model = DQN('MlpPolicy', env, verbose=1, learning_rate=1e-3, buffer_size=10000, learning_starts=1000, batch_size=32) model.learn(total_timesteps=50000) # Evaluation obs = env.reset() for _ in range(100): action, _states = model.predict(obs) obs, reward, done, info = env.step(action) if done: break print('Final portfolio value:', env.envs[0].cash + env.envs[0].holdings * env.envs[0].price[env.envs[0].idx-1]) ### 9.4.4 風險評估與正則化 | 風險指標 | 說明 | |----------|------| | 風險‑回報比 | 總報酬 / 平均絕對回報 | | 最大回撤 | 期間內資金最大下跌幅度 | | 夏普比率 | 平均報酬 / 標準差 | #### 正則化技巧 * **Epsilon‑Greedy Decay**:從 1.0 逐漸降至 0.01,減少過度探索。<br>* **Reward Normalization**:將回報值映射至 `[-1,1]`,避免梯度爆炸。<br>* **Replay Buffer Prioritization**:重複高資訊價值樣本,提升學習效率。<br>* **Actor‑Critic Hybrid**:結合價值函數,減少方差。 --- ## 9.5 可解釋性與過度擬合的風險 1. **可解釋性** - *SHAP*、*LIME*:解釋每筆交易背後的重要特徵。<br> - *Attention 可視化*:在 Transformer 內觀察時間/資產重要度。<br> - *Partial Dependence Plot*:分析單個因子對預測的影響。<br> 2. **過度擬合** - **交叉驗證**:時序交叉驗證(Walk‑Forward)是評估過擬合的關鍵。 - **Dropout / L2 正則化**:在 LSTM、Transformer 中使用。 - **早停**:監控驗證集回測表現。 - **資料多樣化**:加入宏觀、替代資料(新聞情感、社群情緒)以提升泛化。 3. **模型更新** - **滾動窗口訓練**:每月或每季重新訓練,避免因市場結構變化而產生過度擬合。 - **版本控制**:使用 MLflow、DVC 追蹤模型參數、資料版本與回測結果。 --- ## 9.6 實務建議與最佳實踐 | 步驟 | 重點 | 工具/套件 | |------|------|-----------| | 資料清洗 | 欠缺值處理、異常檢測 | pandas, scipy, pyod | | 特徵工程 | 時序特徵、跨資產交互 | featuretools, tsfresh | | 模型選擇 | LSTM vs Transformer vs RL | TensorFlow, PyTorch, Stable‑Baselines3 | | 訓練管線 | GPU 加速、分布式 | Horovod, Dask, Ray | | 評估框架 | 回測、風險、解釋 | zipline, backtrader, Zipline‑Backtesting, quantstats | | 上線監控 | 交易信號、風險限額、延遲 | Prometheus, Grafana, Airflow | ### 1. 訓練與回測並行 在深度學習模型上,**訓練**與**回測**往往是分開進行。為了節省時間,建議使用 **同一套時序資料**,在訓練結束後立即將模型套用於回測,確保回測環境與訓練環境一致。 ### 2. 風險限制的結合 深度模型往往難以內部預測風險,建議在策略層面結合**VaR**或**CVaR**限額,或在 RL 中加入**風險‑懲罰**(risk‑penalty)項,讓模型學會在高風險情況下減少交易。 ### 3. 簡化模型,提升穩定性 在初期開發時,先從簡單的 **GRU** 或 **一層 LSTM** 開始,逐步加入層數、注意力機制,避免一次性投入複雜架構造成難以定位問題。 --- ## 9.7 小結 1. **深度學習**:LSTM 方便處理長時序,Transformer 以自注意力捕捉跨資產關聯;兩者均需嚴格避免過擬合。<br>2. **強化學習**:DQN/PPO 可直接學習交易策略,但對環境設計與回報設置極其敏感。<br>3. **可解釋性**:投資者與合規部門常要求解釋,使用 SHAP、Attention 可視化、LIME 等工具至關重要。<br>4. **風險控制**:在深度模型外層加上 VaR、止損、風險‑懲罰,可降低系統性風險。<br>5. **實務落地**:重視資料品質、持續迭代、模型版本管理與運營監控,才能真正將深度學習與強化學習轉化為可持續的量化投資利器。 > **展望**:隨著計算資源與資料集的豐富,Transformer 及其變體(如 **Finformer、Informer**)在多資產時序預測上已經成為主流;同時,**離線強化學習(offline RL)** 將突破實盤交互限制,為機器人交易提供更安全的學習途徑。結合上述技術,未來量化投資將更貼近市場真實動態,並能在變動的市場環境中保持競爭優勢。