返回目錄
A
量化投資的藝術:策略設計、實作與風險控管 - 第 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)** 將突破實盤交互限制,為機器人交易提供更安全的學習途徑。結合上述技術,未來量化投資將更貼近市場真實動態,並能在變動的市場環境中保持競爭優勢。