10 深度学习

深度学习

深度学习:机器学习的革命性分支

深度学习已在金融风控、量化投资、自然语言处理等领域取得突破性进展。

  • 量化投资:资产价格预测、因子挖掘、算法交易策略
  • 金融风控:信用评分、欺诈检测、反洗钱监控
  • 自然语言处理:财经新闻情感分析、公告信息提取
  • 时间序列预测:股价走势、波动率预测、宏观经济指标预测

核心优势:深度学习模型可自动从原始数据中学习特征,无需人工特征工程。

从单层神经网络说起:感知机

考虑一个具有 \(p\) 个输入和 \(K\) 个输出的问题,单层神经网络模型为:

\[ f(X) = \beta_0 + \sum_{k=1}^{K} \beta_k A_k \]

其中隐藏单元 \(A_k\) 通过激活函数计算:

\[ A_k = g\left(w_{k0} + \sum_{j=1}^{p} w_{kj} X_j\right) \]

  • \(g(\cdot)\)激活函数(如 Sigmoid、ReLU)
  • \(w_{kj}\):连接输入 \(X_j\) 到隐藏单元 \(A_k\)权重
  • \(\beta_k\):连接隐藏单元到输出的权重

激活函数:引入非线性的关键

激活函数 公式 输出范围 特点
Sigmoid \(g(z) = \frac{1}{1+e^{-z}}\) \((0, 1)\) 二分类输出层
tanh \(g(z) = \frac{e^z - e^{-z}}{e^z + e^{-z}}\) \((-1, 1)\) 零中心化
ReLU \(g(z) = \max(0, z)\) \([0, +\infty)\) 计算简单,缓解梯度消失
Softmax \(g(z)_k = \frac{e^{z_k}}{\sum_j e^{z_j}}\) \((0, 1)\), 和为1 多分类输出层

为什么需要非线性激活?\(g(z) = z\)(恒等函数),则无论多少层都等价于单层线性模型:

\[ f(X) = \tilde{\beta}_0 + \sum_{j=1}^{p} \tilde{\beta}_j X_j \]

深度神经网络:堆叠多个隐藏层

一个具有 \(L\) 个隐藏层的深度网络:

\[ f(X) = \beta_0 + \sum_{k=1}^{K} \beta_k A^{(L)}_k \]

其中每一层的激活递归计算:

\[ A^{(l)}_k = g\left(w^{(l)}_{k0} + \sum_{j=1}^{K_{l-1}} w^{(l)}_{kj} A^{(l-1)}_j\right), \quad l = 1, \ldots, L \]

  • 输入层:\(A^{(0)}_j = X_j\)
  • 越深的层学习越抽象的特征
  • “深度”正是”深度学习”名称的由来

卷积神经网络 (CNN)

CNN:专为图像设计的神经网络

卷积神经网络的核心思想:

  • 局部连接:每个神经元只连接输入的一小部分区域
  • 权重共享:同一个卷积核在整个图像上滑动扫描
  • 平移不变性:无论特征在图像哪个位置,都能被检测到

典型 CNN 由以下几种层组成:

  1. 卷积层 (Conv):使用卷积核提取局部特征(边缘、纹理等)
  2. 池化层 (Pool):降低特征维度,引入形变容忍度
  3. 全连接层 (FC):在最后进行分类或回归

金融应用:K线图模式识别、财务报表图表分析

卷积操作与池化操作

卷积操作:使用 \(H \times W\) 的滤波器 \(K\) 对输入 \(I\) 进行特征提取

\[ (I * K)_{i,j} = \sum_{m=0}^{H-1} \sum_{n=0}^{W-1} I_{i+m, j+n} \cdot K_{m,n} \]

最大池化:选择局部区域内的最大值,降低维度

\[ \text{MaxPool}(I)_{i,j} = \max_{(m,n) \in R_{i,j}} I_{m,n} \]

卷积层作用

  • 自动提取局部特征
  • 边缘 → 纹理 → 形状
  • 参数量远少于全连接

池化层作用

  • 降低特征图维度
  • 减少计算量
  • 增强平移不变性

实战:CNN 手写数字识别 (MNIST)

MNIST 数据集:60,000 个训练样本 + 10,000 个测试样本,每张 \(28 \times 28\) 灰度图像。

Code
import numpy as np  # 导入numpy用于数值计算
import matplotlib.pyplot as plt  # 导入matplotlib用于数据可视化
from tensorflow import keras  # 导入keras深度学习框架
from tensorflow.keras import layers, models  # 导入神经网络层和模型构建工具
plt.rcParams['font.sans-serif'] = ['Source Han Serif SC', 'SimHei', 'Arial Unicode MS']  # 设置中文字体
plt.rcParams['axes.unicode_minus'] = False  # 解决负号显示问题

mnist_dataset = keras.datasets.mnist  # 获取MNIST数据集对象
(train_images, train_labels), (test_images, test_labels) = mnist_dataset.load_data()  # 解包训练集和测试集

# 预处理:reshape为(样本数, 28, 28, 1)并归一化至[0,1]
train_images = train_images.reshape((60000, 28, 28, 1)).astype('float32') / 255  # 训练集预处理
test_images = test_images.reshape((10000, 28, 28, 1)).astype('float32') / 255  # 测试集预处理
Figure 1

构建并训练 CNN 模型

# 构建CNN:两组卷积+池化,最后全连接输出
cnn_model = models.Sequential([  # 创建顺序模型
    layers.Conv2D(32, (3, 3), activation='relu', input_shape=(28, 28, 1)),  # 第一卷积层:32个3×3滤波器
    layers.MaxPooling2D((2, 2)),  # 第一池化层:2×2最大池化
    layers.Conv2D(64, (3, 3), activation='relu'),  # 第二卷积层:64个3×3滤波器
    layers.MaxPooling2D((2, 2)),  # 第二池化层:2×2最大池化
    layers.Conv2D(64, (3, 3), activation='relu'),  # 第三卷积层:64个3×3滤波器
    layers.Flatten(),  # 展平层:将多维特征图转为一维向量
    layers.Dense(64, activation='relu'),  # 全连接层:64个神经元
    layers.Dense(10, activation='softmax')  # 输出层:10个类别的softmax概率
])  # 模型构建完成

cnn_model.compile(optimizer='adam',  # Adam自适应学习率优化器
                  loss='sparse_categorical_crossentropy',  # 稀疏分类交叉熵损失
                  metrics=['accuracy'])  # 监控准确率指标

# 训练模型(为节省时间仅训练3个epoch;生产环境建议10-20个epoch)
cnn_history = cnn_model.fit(train_images, train_labels, epochs=3,  # 训练3轮
                            batch_size=64, validation_split=0.2, verbose=0)  # 批大小64,20%验证集

CNN 模型评估:MNIST 测试准确率

Code
test_loss, test_accuracy = cnn_model.evaluate(test_images, test_labels, verbose=0)  # 在测试集评估模型
print(f'MNIST 测试集准确率: {test_accuracy:.4f}')  # 打印测试集准确率

plt.figure(figsize=(12, 4))  # 创建宽幅画布

plt.subplot(1, 2, 1)  # 左图:准确率曲线
plt.plot(cnn_history.history['accuracy'], label='训练集准确率', linewidth=2)  # 训练准确率
plt.plot(cnn_history.history['val_accuracy'], label='验证集准确率', linewidth=2)  # 验证准确率
plt.xlabel('Epoch', fontsize=12)  # x轴标签
plt.ylabel('准确率', fontsize=12)  # y轴标签
plt.title('模型准确率', fontsize=14)  # 子图标题
plt.legend(fontsize=10)  # 添加图例
plt.grid(True, alpha=0.3)  # 半透明网格

plt.subplot(1, 2, 2)  # 右图:损失曲线
plt.plot(cnn_history.history['loss'], label='训练集损失', linewidth=2)  # 训练损失
plt.plot(cnn_history.history['val_loss'], label='验证集损失', linewidth=2)  # 验证损失
plt.xlabel('Epoch', fontsize=12)  # x轴标签
plt.ylabel('损失', fontsize=12)  # y轴标签
plt.title('模型损失', fontsize=14)  # 子图标题
plt.legend(fontsize=10)  # 添加图例
plt.grid(True, alpha=0.3)  # 半透明网格

plt.tight_layout()  # 自动调整间距
plt.show()  # 显示图形
MNIST 测试集准确率: 0.9843
Figure 2: CNN 在 MNIST 上的训练过程:准确率和损失变化曲线

循环神经网络 (RNN)

RNN:给网络装上”记忆”

当数据变成时间序列(股价、文本、语音),需要网络具备记忆能力。

RNN 隐藏层递归公式

\[ A_{\ell k} = g\left(w_{k0} + \sum_{j=1}^{p} w_{kj} X_{\ell j} + \sum_{s=1}^{K} u_{ks} A_{\ell-1, s}\right) \]

  • \(X_{\ell j}\):时间步 \(\ell\) 的输入特征
  • \(A_{\ell-1, s}\)前一个时间步的隐藏状态(“记忆”)
  • \(u_{ks}\):隐藏层到隐藏层的递归权重

输出\(O_\ell = \beta_0 + \sum_{k=1}^{K} \beta_k A_{\ell k}\)

RNN 的结构:紧凑与展开形式

循环神经网络结构示意图 左侧展示RNN的紧凑循环表示,右侧展示按时间步展开的完整结构 紧凑表示 X_t RNN A_{t-1} O_t 展开形式 X_1 A_1 O_1 X_2 A_2 O_2 X_3 A_3 O_3 X_4 A_4 Y 输入 隐藏层 输出 记忆传递

LSTM:解决长期依赖问题

标准 RNN 存在梯度消失问题 → 难以学习长期依赖

LSTM 引入三个门控机制

作用 关键公式
遗忘门 \(f_t\) 控制丢弃多少旧的细胞状态 \(f_t = \sigma(W_f \cdot [h_{t-1}, x_t] + b_f)\)
输入门 \(i_t\) 控制写入多少新信息 \(i_t = \sigma(W_i \cdot [h_{t-1}, x_t] + b_i)\)
输出门 \(o_t\) 控制输出多少细胞状态 \(o_t = \sigma(W_o \cdot [h_{t-1}, x_t] + b_o)\)

核心思想:细胞状态 \(C_t\) 可在多个时间步上保持信息不变,门控机制实现选择性记忆与遗忘。

深度学习的训练

反向传播:深度学习训练的数学核心

反向传播本质是链式法则在计算图上的高效实现。

核心步骤

  1. 输出层误差\[ \delta^{(L)} = \nabla_{A^{(L)}} J \odot g'(Z^{(L)}) \]

  2. 误差逆向传播(对任意隐藏层 \(l\)): \[ \delta^{(l)} = \left((W^{(l+1)})^T \delta^{(l+1)}\right) \odot g'(Z^{(l)}) \]

  3. 计算权重梯度\[ \frac{\partial J}{\partial W^{(l)}} = \delta^{(l)} (A^{(l-1)})^T \]

关键问题:连续乘以权重矩阵 → 梯度消失或爆炸

解决训练难题:正则化与优化

正则化技术 — 防止过拟合

  • Dropout:随机丢弃神经元输出
  • L1/L2 正则化:权重惩罚项
  • 数据增强:随机变换训练数据
  • 早停:验证集性能不再提升时停止

优化算法 — 加速收敛

  • SGD:随机梯度下降
  • Momentum:动量法(加速收敛)
  • Adam:自适应矩估计(最常用)
  • RMSprop:均方根传播

梯度问题的解决方案

  • ReLU 激活函数(缓解梯度消失)
  • 批量归一化(Batch Normalization)
  • 残差连接(ResNet)
  • 梯度裁剪(RNN 常用)

文档分类与自然语言处理

词嵌入:让机器理解语义

词袋模型 (Bag of Words):高维稀疏,无语义信息

词嵌入 (Word Embeddings):低维稠密,语义相似的词距离更近

  • 每个词被映射为一个 \(d\) 维实数向量
  • “好看” 和 “精彩” 在嵌入空间中距离很近
  • 常见预训练词嵌入:Word2Vec、GloVe

在 Keras 中Embedding 层将词索引映射为密集向量

# 词嵌入层示例
layers.Embedding(
    input_dim=10000,   # 词汇表大小
    output_dim=32,     # 嵌入维度
    input_length=200   # 序列长度
)

情感分析:IMDb 电影评论分类

Code
import numpy as np  # 导入numpy用于数值计算
import matplotlib.pyplot as plt  # 导入matplotlib用于数据可视化
from tensorflow import keras  # 导入keras深度学习框架
from tensorflow.keras import layers, models  # 导入层和模型构建工具
plt.rcParams['font.sans-serif'] = ['Source Han Serif SC', 'SimHei', 'Arial Unicode MS']  # 设置中文字体
plt.rcParams['axes.unicode_minus'] = False  # 解决负号显示问题

VOCAB_SIZE = 10000  # 词汇表大小:保留频率最高的10000个词
MAX_SEQUENCE_LENGTH = 200  # 每条评论截取或填充至200个词
EMBEDDING_DIM = 32  # 词嵌入维度

# 创建模拟数据(演示用;实际应用中应使用真实IMDb数据)
num_train_samples = 2000  # 训练样本数
num_test_samples = 500  # 测试样本数
train_sequences = np.random.randint(1, VOCAB_SIZE, size=(num_train_samples, MAX_SEQUENCE_LENGTH))  # 模拟训练集词索引
train_labels = np.random.randint(0, 2, size=num_train_samples)  # 模拟训练标签(0=负面,1=正面)
test_sequences = np.random.randint(1, VOCAB_SIZE, size=(num_test_samples, MAX_SEQUENCE_LENGTH))  # 模拟测试集词索引
test_labels = np.random.randint(0, 2, size=num_test_samples)  # 模拟测试标签
Figure 3

情感分析模型训练与评估

# 构建情感分类模型
sentiment_model = models.Sequential([  # 创建顺序模型
    layers.Embedding(VOCAB_SIZE, EMBEDDING_DIM, input_length=MAX_SEQUENCE_LENGTH),  # 词嵌入层
    layers.Flatten(),  # 展平嵌入矩阵为一维向量
    layers.Dense(16, activation='relu'),  # 隐藏层:16个神经元
    layers.Dense(1, activation='sigmoid')  # 输出层:Sigmoid输出正面概率
])  # 模型构建完成

sentiment_model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])  # 编译模型

sentiment_history = sentiment_model.fit(  # 训练模型
    train_sequences, train_labels, epochs=5,  # 训练5轮
    batch_size=128, validation_split=0.2, verbose=0)  # 批大小128,20%验证集

sentiment_test_loss, sentiment_test_acc = sentiment_model.evaluate(test_sequences, test_labels, verbose=0)  # 评估
print(f'测试集准确率: {sentiment_test_acc:.4f}')  # 打印准确率
测试集准确率: 0.4840

结果解读:模拟数据上准确率接近 50%(随机水平),说明模型未学到有意义的特征——这正是预期结果。实际应用中使用真实语料 + 预训练词向量可显著提升性能。

金融时间序列预测

LSTM 预测海康威视股价

使用双层 LSTM 基于过去 60 个交易日预测下一天收盘价。

关键步骤

  1. 加载海康威视(002415.XSHE)后复权股价数据
  2. MinMaxScaler 归一化到 [0, 1]
  3. 滑动窗口法构造序列样本(窗口 = 60 天)
  4. 按时间顺序 80/20 分割(不可随机打乱!)
  5. 双层 LSTM + Dropout 防过拟合
import numpy as np  # 导入numpy用于数值计算
import pandas as pd  # 导入pandas用于数据处理
import os  # 导入os用于跨平台路径处理
from sklearn.preprocessing import MinMaxScaler  # 导入归一化工具
from tensorflow import keras  # 导入keras框架
from tensorflow.keras import layers, models  # 导入层和模型工具

DATA_DIR = 'C:/qiufei/data' if os.name == 'nt' else '/home/ubuntu/r2_data_mount/qiufei/data'  # 跨平台数据路径
stock_price_path = os.path.join(DATA_DIR, 'stock/stock_price_post_adjusted.h5')  # 后复权股价文件路径
stock_price_history = pd.read_hdf(stock_price_path).reset_index()  # 读取股价数据
haikang_data = stock_price_history[stock_price_history['order_book_id'] == '002415.XSHE'].copy()  # 筛选海康威视
haikang_data = haikang_data.sort_values('date')  # 按日期排序
closing_prices = haikang_data['close'].values.reshape(-1, 1)  # 提取收盘价为二维数组

数据预处理:归一化与滑动窗口

price_scaler = MinMaxScaler(feature_range=(0, 1))  # 创建归一化器(范围0-1)
scaled_prices = price_scaler.fit_transform(closing_prices)  # 对收盘价归一化

def create_sliding_window_sequences(data, window_length):  # 定义滑动窗口函数
    """将时间序列转换为(特征序列, 目标值)对"""
    features_list, targets_list = [], []  # 初始化特征和目标列表
    for i in range(len(data) - window_length):  # 滑动窗口遍历
        features_list.append(data[i:i + window_length])  # 窗口内数据作为特征
        targets_list.append(data[i + window_length])  # 窗口后一天作为目标
    return np.array(features_list), np.array(targets_list)  # 转为numpy数组

LOOKBACK_WINDOW = 60  # 使用过去60个交易日预测下一天
sequence_features, sequence_targets = create_sliding_window_sequences(scaled_prices, LOOKBACK_WINDOW)  # 构造序列

# 按时间顺序80/20分割(时间序列不可随机打乱)
split_point = int(len(sequence_features) * 0.8)  # 计算分割点
train_x, test_x = sequence_features[:split_point], sequence_features[split_point:]  # 特征分割
train_y, test_y = sequence_targets[:split_point], sequence_targets[split_point:]  # 目标分割

构建双层 LSTM 模型并训练

# 构建双层LSTM模型
lstm_model = models.Sequential([  # 创建顺序模型
    layers.LSTM(50, return_sequences=True, input_shape=(LOOKBACK_WINDOW, 1)),  # 第一层LSTM:50单元,返回序列
    layers.Dropout(0.2),  # 20%随机丢弃防止过拟合
    layers.LSTM(50, return_sequences=False),  # 第二层LSTM:50单元,只返回最后时间步
    layers.Dropout(0.2),  # 再次20%随机丢弃
    layers.Dense(25),  # 全连接层:25个神经元
    layers.Dense(1)  # 输出层:预测1个值
])  # 模型构建完成

lstm_model.compile(optimizer='adam', loss='mean_squared_error')  # Adam优化器+MSE损失

# 训练模型(为节省时间训练20个epoch;生产环境建议50-100个epoch)
lstm_history = lstm_model.fit(train_x, train_y, epochs=20,  # 训练20轮
                              batch_size=64, validation_split=0.1, verbose=0)  # 批大小64,10%验证集

LSTM 股价预测结果

Code
import matplotlib.pyplot as plt  # 导入绘图库
plt.rcParams['font.sans-serif'] = ['Source Han Serif SC', 'SimHei', 'Arial Unicode MS']  # 设置中文字体
plt.rcParams['axes.unicode_minus'] = False  # 解决负号显示问题

predicted_prices = lstm_model.predict(test_x)  # 在测试集上预测
actual_prices = price_scaler.inverse_transform(test_y)  # 真实价格反归一化
predicted_prices_original = price_scaler.inverse_transform(predicted_prices)  # 预测价格反归一化

# 展示最近365天的预测对比
display_days = min(365, len(actual_prices))  # 展示天数
plt.figure(figsize=(14, 5))  # 创建画布
plt.plot(actual_prices[-display_days:], label='真实股价', linewidth=2)  # 真实股价曲线
plt.plot(predicted_prices_original[-display_days:], label='预测股价', linewidth=2, linestyle='--')  # 预测曲线
plt.title('海康威视股价预测 (LSTM)', fontsize=14)  # 标题
plt.xlabel('时间 (天)', fontsize=12)  # x轴
plt.ylabel('收盘价 (元)', fontsize=12)  # y轴
plt.legend(fontsize=11)  # 图例
plt.grid(True, alpha=0.3)  # 网格
plt.tight_layout()  # 调整间距
plt.show()  # 显示
 1/24 ━━━━━━━━━━━━━━━━━━━━ 5s 249ms/step

 6/24 ━━━━━━━━━━━━━━━━━━━━ 0s 11ms/step 

11/24 ━━━━━━━━━━━━━━━━━━━━ 0s 11ms/step

16/24 ━━━━━━━━━━━━━━━━━━━━ 0s 11ms/step

21/24 ━━━━━━━━━━━━━━━━━━━━ 0s 11ms/step

24/24 ━━━━━━━━━━━━━━━━━━━━ 0s 24ms/step

24/24 ━━━━━━━━━━━━━━━━━━━━ 1s 25ms/step
Figure 4: LSTM 模型对海康威视股价预测结果。实线为真实价格,虚线为模型预测。

LSTM 预测的局限性

预测滞后效应:预测曲线往往”追随”真实价格,存在时间滞后

对突变的捕捉有限:股价剧烈波动时,模型反应不够灵敏

不代表投资建议:股价受宏观经济、政策、市场情绪等多重因素影响

改进方向

  • 融合多源信息(基本面、技术指标、新闻情绪)
  • 使用注意力机制(Transformer)替代 LSTM
  • 增加特征维度(成交量、换手率、资金流向)
  • 结合时域与频域分析

本章小结

深度学习知识图谱

主题 核心内容 关键应用
神经网络基础 激活函数、多层网络、反向传播 所有深度学习任务的基石
CNN 卷积、池化、权重共享 图像分类、K线图识别
RNN / LSTM 递归结构、门控机制 时间序列、文本处理
训练技巧 Dropout、BatchNorm、Adam 防过拟合、加速收敛
NLP 词嵌入、情感分析 财经新闻分析
金融应用 LSTM 股价预测 量化投资、风险管理

何时使用深度学习:大量数据 + 复杂模式 + 充足算力 + 传统方法瓶颈

深度学习的挑战:数据需求大、计算资源多、可解释性差、超参数调优复杂