01 统计学习导论

核心问题:如何从数据中发现规律?

统计学习 (Statistical Learning) 是一套从数据中提取模式、支持商业决策的工具框架。

  • 监督学习:已知”正确答案”,学习输入→输出的映射
  • 无监督学习:没有标签,发现数据内部的隐含结构

在金融、电商、医疗等领域,统计学习已成为决策的基础设施

统计学习的核心公式

假设响应变量 \(Y\)(如净利润)和特征向量 \(X = (X_1, \dots, X_p)\) 之间存在关系:

\[ \large{Y = f(X) + \epsilon} \]

  • \(f\):未知的系统性映射函数 — 我们要”学习”的对象
  • \(\epsilon\):随机误差项,均值为零,与 \(X\) 独立

统计学习的本质:用算法从经验数据中估计 \(f\)

统计学习在中国金融领域的应用

应用领域 方法 典型机构
智能信贷风控 XGBoost、深度学习 蚂蚁集团、京东金融
量化投资策略 Lasso、随机森林、LSTM 幻方量化、明汯投资
保险精算定价 Cox比例风险模型 中国人寿、平安保险
供应链优化 Prophet、ARIMA-GARCH 京东物流

核心挑战:从商业噪音中滤出确定性规律(\(f\)),防范随机噪音(\(\epsilon\))带来的误判。

案例一:长三角上市公司财务分析

研究目标:影响长三角地区上市公司净利润的因素

  • 营业收入 (Revenue) — 最有力的单一预测指标
  • 总资产 (Total Assets) — 正相关但波动更大
  • 行业分类 — 不同行业利润率差异显著

这是一个典型的回归问题 (Regression Problem)。

数据准备:加载与环境配置

import numpy as np  # 导入numpy库,用于数值计算
import pandas as pd  # 导入pandas库,用于数据框操作
import matplotlib.pyplot as plt  # 导入matplotlib库,用于绑图
import seaborn as sns  # 导入seaborn库,用于高级统计图表
import os  # 导入os模块,用于跨平台路径处理

plt.rcParams['font.sans-serif'] = ['Source Han Serif SC', 'SimHei', 'Arial Unicode MS']  # 设置中文字体
plt.rcParams['axes.unicode_minus'] = False  # 解决负号显示问题

# 根据操作系统自动选择数据根目录
DATA_ROOT = 'C:/qiufei/data' if os.name == 'nt' else '/home/ubuntu/r2_data_mount/qiufei/data'
FINANCIAL_STMT_PATH = os.path.join(DATA_ROOT, 'stock/financial_statement.h5')  # 财务报表路径
STOCK_BASIC_PATH = os.path.join(DATA_ROOT, 'stock/stock_basic_data.h5')  # 公司基本信息路径

数据合并与地区筛选

financial_statements_data = pd.read_hdf(FINANCIAL_STMT_PATH)  # 读取上市公司财务报表
stock_basic_info = pd.read_hdf(STOCK_BASIC_PATH)  # 读取公司基本信息

financial_data_2023 = financial_statements_data[
    financial_statements_data['quarter'] == '2023q4'
].copy()  # 筛选2023年年报数据

join_key = 'order_book_id'  # 合并键:股票代码
merged_company_data = pd.merge(
    financial_data_2023,
    stock_basic_info[[join_key, 'province', 'industry_name']],
    on=join_key, how='inner'
)  # 按股票代码内连接合并两张表

yrd_provinces_list = ['上海市', '江苏省', '浙江省', '安徽省']  # 长三角四省市
yrd_companies_data = merged_company_data[
    merged_company_data['province'].isin(yrd_provinces_list)
].copy()  # 筛选长三角地区公司

数据清洗与对数变换

is_valid_record = (
    (yrd_companies_data['revenue'] > 1e6) &  # 营业收入大于100万
    (yrd_companies_data['total_assets'] > 1e6) &  # 总资产大于100万
    (yrd_companies_data['net_profit'] > 0)  # 净利润为正
)  # 构建有效性过滤条件
yrd_cleaned_data = yrd_companies_data[is_valid_record].copy()  # 保留有效记录

yrd_cleaned_data['log_revenue'] = np.log10(yrd_cleaned_data['revenue'])  # 对营收取对数
yrd_cleaned_data['log_assets'] = np.log10(yrd_cleaned_data['total_assets'])  # 对资产取对数
yrd_cleaned_data['log_profit'] = np.log10(yrd_cleaned_data['net_profit'])  # 对利润取对数

top_industries_names = yrd_cleaned_data['industry_name'].value_counts().head(5).index  # 选取前5大行业
plotting_data = yrd_cleaned_data[yrd_cleaned_data['industry_name'].isin(top_industries_names)]  # 筛选绘图数据

为什么做对数变换? 工商银行营收数千亿 vs 小企业数千万,直接绑图中小企业全被挤到原点。\(\log_{10}\) 让不同量级公司在图上”均匀展开”。

财务数据可视化:净利润与营收、资产、行业

Code
academic_colors_palette = ['#E3120B', '#2C3E50', '#008080', '#F0A700', '#8E9EAA']  # 学术配色
fig, axes = plt.subplots(1, 3, figsize=(16, 5))  # 创建1行3列子图

axes[0].scatter(plotting_data['log_revenue'], plotting_data['log_profit'], alpha=0.4, s=25, c='#2C3E50')  # 左图散点
poly_coeff = np.polyfit(plotting_data['log_revenue'], plotting_data['log_profit'], 1)  # 线性拟合
axes[0].plot(plotting_data['log_revenue'], np.polyval(poly_coeff, plotting_data['log_revenue']), color='#E3120B', lw=2.5)  # 趋势线
axes[0].set_xlabel('Log10 营业收入', fontsize=11)  # x轴标签
axes[0].set_ylabel('Log10 净利润', fontsize=11)  # y轴标签
axes[0].set_title('净利润与营收呈强线性关系', fontweight='bold')  # 标题

axes[1].scatter(plotting_data['log_assets'], plotting_data['log_profit'], alpha=0.4, s=25, c='#008080')  # 中图散点
poly_coeff_assets = np.polyfit(plotting_data['log_assets'], plotting_data['log_profit'], 1)  # 线性拟合
axes[1].plot(plotting_data['log_assets'], np.polyval(poly_coeff_assets, plotting_data['log_assets']), color='#E3120B', lw=2.5)  # 趋势线
axes[1].set_xlabel('Log10 总资产', fontsize=11)  # x轴标签
axes[1].set_title('盈利随资产规模同步增长', fontweight='bold')  # 标题

sns.boxplot(x='industry_name', y='log_profit', data=plotting_data, ax=axes[2], palette=academic_colors_palette)  # 右图箱线图
axes[2].set_xlabel('细分行业', fontsize=11)  # x轴标签
axes[2].set_title('行业间利润分布差异显著', fontweight='bold')  # 标题
plt.xticks(rotation=30)  # 旋转标签
for ax in axes:  # 添加网格
    ax.grid(True, linestyle='--', alpha=0.5)
plt.tight_layout()  # 自动调整间距
plt.show()  # 显示图形
Figure 1: 长三角上市公司: 净利润与营收、资产、行业的关系 (2023年年报)

案例二:股票市场涨跌预测

研究对象:上汽集团 (600104.SH),长三角汽车行业龙头

问题类型分类问题 (Classification) — 预测明天”上涨”还是”下跌”

方法:利用过去几天的历史收益率(滞后项 Lags)作为特征

核心发现:历史收益率对未来涨跌的区分度极弱 → 市场效率

特征工程:构建滞后收益率

PRICE_DATA_PATH = os.path.join(DATA_ROOT, 'stock/stock_price_pre_adjusted.h5')  # 前复权价格路径
stock_price_history = pd.read_hdf(PRICE_DATA_PATH).reset_index()  # 读取全市场日度价格数据

saic_motor_data = stock_price_history[stock_price_history['order_book_id'] == '600104.XSHG'].copy()  # 筛选上汽集团
saic_motor_data['date'] = pd.to_datetime(saic_motor_data['date'])  # 转换日期格式
saic_motor_data = saic_motor_data.sort_values('date')  # 按日期排序
saic_motor_data['daily_return'] = saic_motor_data['close'].pct_change()  # 计算日收益率

num_lags = 5  # 构建5个滞后特征
for lag in range(1, num_lags + 1):  # 循环创建滞后列
    saic_motor_data[f'lag_return_{lag}'] = saic_motor_data['daily_return'].shift(lag)  # shift实现回溯

saic_motor_data['market_direction'] = (saic_motor_data['daily_return'] > 0).astype(int)  # 定义涨跌标签
saic_analysis_dataset = saic_motor_data[saic_motor_data['date'] >= '2015-01-01'].dropna()  # 筛选2015年后数据

关键手法:将时间序列预测转化为标准分类问题 — 量化投资的基础范式

历史收益率几乎无法区分涨跌方向

Code
fig, axes = plt.subplots(1, 3, figsize=(15, 5))  # 创建1行3列子图
lag_indices = [1, 2, 3]  # 选择前3个滞后项

for i, lag_idx in enumerate(lag_indices):  # 遍历绘制箱线图
    sns.boxplot(
        x='market_direction', y=f'lag_return_{lag_idx}',
        data=saic_analysis_dataset, ax=axes[i],
        palette=['#E3120B', '#008080'], showfliers=False
    )  # 按涨跌方向分组绘制
    axes[i].set_xticklabels(['下跌日', '上涨日'])  # 替换标签
    axes[i].set_title(f'滞后项 Lag {lag_idx} 收益分布', fontweight='bold')  # 标题
    axes[i].set_xlabel('今日方向')  # x轴
    axes[i].set_ylabel('过去收益率')  # y轴
    axes[i].grid(True, axis='y', alpha=0.3)  # 网格

plt.tight_layout()  # 调整间距
plt.show()  # 显示
Figure 2: 上汽集团 (600104.SH) 历史收益率滞后分析 (2015-2025)

四种分类模型的预测表现

from sklearn.linear_model import LogisticRegression  # 导入逻辑回归
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis, QuadraticDiscriminantAnalysis  # 导入LDA/QDA
from sklearn.neighbors import KNeighborsClassifier  # 导入KNN
from sklearn.metrics import accuracy_score  # 导入准确率函数

feature_columns = [f'lag_return_{i}' for i in range(1, 6)]  # 5个滞后特征
features_matrix = saic_analysis_dataset[feature_columns]  # 提取特征矩阵
target_vector = saic_analysis_dataset['market_direction']  # 提取目标标签

split_point = int(0.75 * len(features_matrix))  # 75%分位点
features_train, features_test = features_matrix.iloc[:split_point], features_matrix.iloc[split_point:]  # 划分特征
target_train, target_test = target_vector.iloc[:split_point], target_vector.iloc[split_point:]  # 划分标签

classifiers_dict = {
    '逻辑回归': LogisticRegression(),
    'LDA': LinearDiscriminantAnalysis(),
    'QDA': QuadraticDiscriminantAnalysis(),
    'K-近邻 (K=3)': KNeighborsClassifier(n_neighbors=3)
}  # 四种分类器

prediction_accuracies = {}  # 存储准确率
for name, clf in classifiers_dict.items():  # 遍历训练
    clf.fit(features_train, target_train)  # 拟合模型
    predictions = clf.predict(features_test)  # 预测
    prediction_accuracies[name] = accuracy_score(target_test, predictions)  # 计算准确率

所有模型的准确率都接近随机水平

Code
plt.figure(figsize=(10, 6))  # 创建画布
bar_colors = ['#2C3E50', '#008080', '#F0A700', '#8E9EAA']  # 分配颜色
plt.barh(list(prediction_accuracies.keys()), list(prediction_accuracies.values()), color=bar_colors, alpha=0.8)  # 水平条形图
plt.axvline(x=0.5, color='#E3120B', linestyle='--', label='随机水平 (50%)')  # 基准线
plt.xlim(0.48, 0.55)  # 放大观察范围
plt.xlabel('测试集预测准确率')  # x轴标签
plt.title('上汽集团次日涨跌预测准确率对比', fontweight='bold')  # 标题
plt.legend()  # 图例
plt.grid(axis='x', linestyle=':', alpha=0.6)  # 网格
plt.show()  # 显示
Figure 3: 上汽集团股价方向预测: 不同算法的性能对比

核心洞察:无论是线性还是非线性分类器,准确率都在50%附近 → 市场有效性假说的实证证据。

高维数据挑战:当特征比样本还多

量化多因子模型的典型困境:

  • 特征 \(p = 2000+\)(财务因子、价量因子、情绪因子…)
  • 样本 \(n = 300\)(如沪深300成分股的月度截面)

\(p > n\) 时,矩阵 \(\mathbf{X}^T\mathbf{X}\) 奇异不可逆 → OLS 彻底崩溃

模型会”完美记忆”训练数据的每一丝随机波动 → 过拟合 (Overfitting)

解决方案:正则化与特征降维

方法 机制 效果
Lasso 回归 将冗余因子权重压缩为零 稀疏模型,可解释性强
岭回归 (Ridge) 限制所有参数幅度 处理多重共线性,稳定性好

这些技术已被国内头部券商和量化私募广泛使用

本书第六章将系统介绍这些正则化方法。

统计学习 vs 机器学习 vs 人工智能

AI、机器学习与统计学习的层级关系 三个同心椭圆展示AI包含ML、ML包含统计学习的嵌套关系 人工智能 (AI) 模拟人类认知和决策的宏大目标 机器学习 (ML) 让计算机从数据中自主学习 统计学习 提供数学基石与推断框架 本书聚焦

统计学习 不仅关注”预测准不准”,更关注”为什么准”、“置信区间多宽”。

本书内容概览

基础方法

  • 第2章:统计学习理论基础
  • 第3章:线性回归
  • 第4章:分类方法
  • 第5章:重采样方法
  • 第6章:模型选择与正则化

高级方法

  • 第7章:非线性方法
  • 第8章:基于树的方法
  • 第9章:支持向量机
  • 第10章:深度学习
  • 第11章:生存分析
  • 第12章:无监督学习
  • 第13章:多重检验

数据与工具

全部案例数据来自中国本土真实市场,本地离线可用。

数据类型 文件 场景
公司基本信息 stock_basic_data.h5 筛选、分类
财务报表 financial_statement.h5 面板分析
日度行情 stock_price_*.h5 收益率、技术分析
估值因子 valuation_factors_*.h5 多因子模型
指数/期货/基金 index/, future/, fund/ 市场分析

Python工具包:NumPy, Pandas, Matplotlib, Scikit-learn, Statsmodels, PyTorch

数学符号约定

本书采用以下标准记号:

符号 含义 示例
小写字母 标量 \(x, y, z\)
粗体小写 向量 \(\mathbf{x}, \mathbf{y}\)
粗体大写 矩阵 \(\mathbf{X}, \mathbf{Y}\)
大写字母 随机变量 \(X, Y, Z\)
帽子记号 估计量 \(\hat{\beta}, \hat{y}\)

回归中:\(n\) = 样本量,\(p\) = 特征数,\(\mathbf{X}\) = \(n \times p\) 设计矩阵

本章小结

  1. 统计学习是从数据中估计 \(f\) 的方法论,分为监督学习和无监督学习
  2. 回归问题预测连续值(如净利润),分类问题预测离散类别(如涨跌)
  3. 真实金融数据验证了市场有效性 — 简单的历史特征难以预测涨跌
  4. 高维问题 (\(p \gg n\)) 需要正则化等现代方法
  5. 本书从统计学习视角解读算法,兼顾预测能力与可解释性