第 10 章 · 05 LSTM 时序预测 本节摘要:本节讲循环神经网络(RNN)与 LSTM 如何处理「带时间依赖」的金融序列。前馈网络把每个样本当独立点,RNN 则把过去若干步的信息「记忆」下来,适合做股价这种「今天的走势依赖过去几天」的任务。本节讲清四件事:普通 RNN 的梯度消失问题与 LSTM 的门控(遗忘/输入/输出)如何解决它;如何用滑窗把单变量时间序列变成监督学习格式;如何堆叠 LSTM 层并用 Embedding 接入非时序特征(如股票 id、月份);以及如何把 LSTM 用到多变量时序(消费信心 + 工业生产)与 SEC 文件收益预测上。读完本节,你能用 LSTM 做单变量与多变量的金融时序预测,并理解它的强项与弱项。
本节摘要:本节讲循环神经网络(RNN)与 LSTM 如何处理「带时间依赖」的金融序列。前馈网络把每个样本当独立点,RNN 则把过去若干步的信息「记忆」下来,适合做股价这种「今天的走势依赖过去几天」的任务。本节讲清四件事:普通 RNN 的梯度消失问题与 LSTM 的门控(遗忘/输入/输出)如何解决它;如何用滑窗把单变量时间序列变成监督学习格式;如何堆叠 LSTM 层并用 Embedding 接入非时序特征(如股票 id、月份);以及如何把 LSTM 用到多变量时序(消费信心 + 工业生产)与 SEC 文件收益预测上。读完本节,你能用 LSTM 做单变量与多变量的金融时序预测,并理解它的强项与弱项。
内容来源:原项目
19_recurrent_neural_nets/01_univariate_time_series_regression.ipynb、02_stacked_lstm_with_feature_embeddings.ipynb、04_multivariate_timeseries.ipynb、07_sec_filings_return_prediction.ipynb,汉化并套用体系化模板。
⚠️ 学习提示:LSTM 在金融上的样本外表现普遍不及在 NLP 或语音上——金融时序信噪比低、非平稳,LSTM 强大的记忆能力反而容易记住噪声。把 LSTM 当「另一种非线性的 VAR」对比理解,而不要期待它在股价预测上击败市场。
阅读完本节,你应当能够:
前馈网络每个样本独立,RNN 在样本之间共享一个「隐藏状态」——当前时刻的输出不仅依赖当前输入,还依赖上一时刻的隐藏状态:
这样网络就有了「记忆」。但普通 RNN 训练时会出现梯度消失/爆炸:梯度沿时间反向传播时,要连乘很多次权重矩阵,数值要么指数衰减要么爆炸,导致网络学不会「长程依赖」。
LSTM(Hochreiter & Schmidhuber, 1997)的解法是引入细胞状态 C_t 和三个门:
| 门 | 作用 | 直觉 |
|---|---|---|
| 遗忘门 f_t | 决定从细胞状态丢多少旧信息 | 「过去的事记得多少」 |
| 输入门 i_t | 决定写入多少新信息 | 「新输入要记多少」 |
| 输出门 o_t | 决定输出多少细胞状态 | 「现在该说出来多少」 |
细胞状态像一条「传送带」,门控决定什么该留什么该丢。这让梯度能顺畅地沿细胞状态传很远,LSTM 因此能学到几百步的依赖。
💡 核心心法:LSTM 的精髓是「可学习的记忆」——网络自己学会什么时候记、什么时候忘、什么时候说。这比普通 RNN 的「被动衰减记忆」强得多,也比前馈网络的「无记忆」强得多。但记住:能记住不等于该记,在噪声大的金融数据上,LSTM 记住的常常是噪声。
notebook 01_univariate_time_series_regression.ipynb 用 LSTM 预测 S&P500 指数:
sp500 = web.DataReader('SP500', 'fred', start='2010', end='2020').dropna() scaler = MinMaxScaler() sp500_scaled = pd.Series(scaler.fit_transform(sp500).squeeze(), index=sp500.index)
关键步骤是把时序转成监督学习格式——用滑窗生成「过去 N 天 → 下一天」的训练对:
window_size = N 是个重要超参:太小→看不到足够历史;太大→网络负担重、训练慢。LSTM 的输入形状是 (samples, timesteps, features),单变量就是 (N_samples, window_size, 1)。
⚠️ 标准化必须在滑窗之前:用全样本的 scaler 转换再切窗,会比每窗单独 scale 稳定。但要注意,严格按时间推断(out-of-time)应该只用训练段的统计量做 scale,否则泄漏——这点 notebook 简化了,实务要更严。
LSTM 模型本身很简洁:
from tensorflow.keras.layers import LSTM, Dense from tensorflow.keras.callbacks import ModelCheckpoint, EarlyStopping model = Sequential([ LSTM(20, input_shape=(window_size, 1)), Dense(1) ]) model.compile(optimizer='adam', loss='mse') checkpoint = ModelCheckpoint(str(results_path / 'lstm.h5'), save_best_only=True) early_stop = EarlyStopping(patience=5, restore_best_weights=True) model.fit(train_data, epochs=50, validation_data=val_data, callbacks=[checkpoint, early_stop])
notebook 02_stacked_lstm_with_feature_embeddings.ipynb 在 Quandl 周度股票数据上构建更复杂的模型:
return_sequences=True,把完整序列传给第二层;from tensorflow.keras.layers import Input, concatenate, Embedding, Reshape # 时序输入:52 周收益 returns_input = Input(shape=(window_size, 1), name='returns') x = LSTM(10, return_sequences=True)(returns_input) x = LSTM(10)(x) # 非时序输入:股票 id、月份 ticker_input = Input(shape=(1,), name='ticker') ticker_embed = Embedding(input_dim=n_tickers, output_dim=5)(ticker_input) ticker_embed = Reshape((5,))(ticker_embed) # 合并两路 combined = concatenate([x, ticker_embed]) output = Dense(1)(combined) model = Model([returns_input, ticker_input], output)
这种「时序分支 + 非时序分支」的多输入结构,在金融里很常见——股价收益是时序,但股票属性(行业、规模)是静态的。
notebook 04_multivariate_timeseries.ipynb 用 LSTM 做多变量时序——典型的「消费信心 + 工业生产」双序列:
df = web.DataReader(['UMCSENT', 'IPGMFN'], 'fred', '1980', '2019-12').dropna() df.columns = ['sentiment', 'ip'] # 平稳化:工业生产先 log 再做 12 阶差分,消费信心直接 12 阶差分 df_transformed = pd.DataFrame({'ip': np.log(df.ip).diff(12), 'sentiment': df.sentiment.diff(12)}).dropna()
平稳化是关键——LSTM 不是 ARIMA,但同样受益于平稳输入。工业生产有明显趋势与季节性,log + 12 阶差分大致去趋势去季节;消费信心无趋势,只需差分。
多变量 LSTM 的输入形状是 (samples, timesteps, n_features=2),本质上是 VAR 模型的非线性版本——VAR 用线性方程描述变量间滞后关系,LSTM 用循环层描述,但能捕捉非线性交互。
notebook 07_sec_filings_return_prediction.ipynb 把 LSTM 用到 NLP × 金融的交叉任务:用 SEC 财报文件(10-K)的文本预测发布后一周的收益。这是一个端到端流程:
from tensorflow.keras.layers import Bidirectional, GRU, Embedding, BatchNormalization, Dropout model = Sequential([ Embedding(input_dim=vocab_size, output_dim=embedding_dim, input_length=max_len), Bidirectional(GRU(32, return_sequences=True)), BatchNormalization(), Dropout(0.5), GRU(32), Dense(1) ])
Bidirectional 让 GRU 同时看正反两个方向——NLP 里常见,因为上下文都重要。这里 LSTM/GRU 的强项是处理「变长 token 序列」,而前馈网络做不到。但金融文本预测收益的信噪比同样极低,样本外 IC 有限。
(samples, timesteps, features)。return_sequences=True,Embedding 把分类变量(股票 id、月份)转低维向量,合并时序与非时序分支。下一节,我们看 强化学习交易 Agent DQN——用深度 Q 网络训练一个端到端的交易 Agent,把「观察市场 → 决策动作 → 获得奖励」的闭环跑起来。