基于概率图模型的中国股市关联性分析

邱飞

2025-12-17

简介

本讲座目标:帮助你掌握一种强大的数据分析工具——高斯图模型(Gaussian Graphical Model),使你能够从股票价格数据中”看见”公司之间的真实联系,而非被表面的”同涨同跌”所迷惑。

开篇问题:一个真实的困惑

假设你是一名量化分析师,需要为客户构建一个分散化的股票投资组合。你观察到:

  • 招商银行平安银行的收益率相关系数很高
  • 招商银行中国平安的相关系数也不低
  • 平安银行中国平安的相关系数同样较高

问题:这三只股票之间真的都有直接联系吗?还是其中某些相关性只是”假象”?

什么关系?

表面现象:边际相关网络 招商银行 平安银行 中国平安 高相关 中等 中等相关 隐藏结构:条件独立网络? 招商银行 平安银行 中国平安 直接联系 直接联系 条件独立?
Figure 1: 边际相关 vs 条件独立:哪种更接近真相?

核心问题:使用本讲座介绍的高斯图模型,我们能够检验:招商银行与中国平安之间是否只是因为都与平安银行相关,而彼此之间没有直接联系

📌 预告:在本讲座的最后(第 8.5 节),我们将使用真实的 A 股数据来验证这个假设,看看条件独立性分析能否揭示这些金融股之间的”真实关系”。

理论背景与起源

概率图模型(Probabilistic Graphical Models, PGM)结合了概率论与图论,为处理复杂系统中的不确定性和多变量依赖关系提供了强有力的框架。

💡 直觉理解:把每只股票想象成一个”节点”,如果两只股票之间有”边”相连,说明它们有直接的统计联系;如果没有边,说明它们只是通过其他股票”间接”相关。图模型就是帮助我们画出这张”真正的关系图”的数学工具。

历史渊源

PGM 的思想可以追溯到多个学科领域:

  1. 统计物理学(19世纪末-20世纪初)
    • Boltzmann 分布与 Gibbs 分布:Ludwig Boltzmann 和 Josiah Willard Gibbs 在研究热力学系统时,首次建立了状态空间上的概率分布与”能量函数”之间的指数关系。后来的马尔可夫随机场(MRF)采用了完全相同的数学形式。
    • Ising 模型(1925):Ernst Ising 在其博士论文中提出的 Ising 模型,可视为最早的无向图模型(Undirected Graphical Model),用于描述铁磁性材料中原子自旋之间的相互作用。
  2. 遗传学与因果推理(1920s-1930s)
    • 路径分析(Path Analysis):Sewall Wright 于 1921 年提出路径分析方法,用有向图表示遗传性状之间的因果关系。这可以视为有向图模型(Directed Graphical Model)或贝叶斯网络的前身。
  3. 计算机科学与人工智能(1980s-至今)
    • 贝叶斯网络(Bayesian Networks):Judea Pearl 在其开创性著作《Probabilistic Reasoning in Intelligent Systems》(1988)中系统阐述了贝叶斯网络的理论基础,为不确定性推理和因果推断提供了完整的框架。Pearl 后来因其在因果推理领域的贡献获得 2011 年图灵奖。
    • 隐马尔可夫模型(HMM)与条件随机场(CRF):分别在语音识别和自然语言处理领域取得巨大成功,展示了图模型在序列数据建模中的威力。

高斯图模型的理论地位

  • 本讲座重点介绍高斯图模型(Gaussian Graphical Model, GGM),属于连续变量的无向图模型。其数学基础由 Arthur Dempster (1972) 在其经典论文”Covariance Selection”中奠定,

  • 核心思想是:通过研究精度矩阵(Precision Matrix,即协方差矩阵的逆)的稀疏结构来推断变量之间的条件独立性关系。

  • 在现代高维统计学中,GGM 因其简洁的理论性质和与 Lasso 正则化的自然结合而成为研究热点。

为什么需要高斯图模型?

边际相关 vs. 条件相关

理解 GGM 的关键在于区分两种相关性概念:

概念 衡量什么 矩阵对应 例子
边际相关(Marginal Correlation) 两变量之间的总体相关性 协方差矩阵 \(\Sigma\) 或相关矩阵 股票 A 和股票 B 同涨同跌
条件相关(Conditional Correlation) 控制其他所有变量后的相关性 精度矩阵 \(\Theta = \Sigma^{-1}\) 排除市场因素后,A 和 B 是否仍相关

直观案例:市场因子的”混杂效应”

考虑一个简单的例子:假设有三只股票 \(A\)\(B\)\(M\)(市场指数)。

股票 A ←——→ 市场 M ←——→ 股票 B
  • 如果 \(A\)\(B\) 都紧密跟随市场 \(M\) 波动,则它们的边际相关系数 \(\rho_{AB}\) 会很高。
  • 然而,如果我们”控制住” \(M\)(即在给定 \(M\) 的条件下),\(A\)\(B\) 之间可能完全独立!
  • 这意味着 \(A\)\(B\) 之间不存在”直接联系”,它们的高相关仅仅是因为共同受市场驱动。

这正是 GGM 能够揭示的:精度矩阵中 \(\Theta_{AB} = 0\),表示 \(A\)\(B\) 在条件独立意义下没有边相连。

🍦 经典类比:冰淇淋销量与溺水事故

这是统计学中最著名的虚假相关(Spurious Correlation)案例之一:

现象:研究发现,冰淇淋销量与游泳溺水事故数量呈强正相关(相关系数约 0.8)。

错误结论:吃冰淇淋会导致溺水?或者溺水会刺激冰淇淋消费?

真相:存在一个隐藏的混杂变量——夏季气温

冰淇淋销量 ← 炎热天气 → 游泳人数增加 → 溺水事故
  • 天气热 → 人们买更多冰淇淋
  • 天气热 → 人们更多去游泳 → 溺水风险上升

一旦我们控制住天气因素(条件于气温),冰淇淋销量与溺水事故之间的相关性就消失了!

数学语言\(\text{冰淇淋} \perp \text{溺水} \mid \text{天气}\)

这正是高斯图模型所做的:在网络中,只有真正有直接联系的变量之间才会有边

👥 社交网络类比:朋友的朋友

另一种理解条件独立的方式是通过社交网络

想象你和小明都是小红的朋友,但你和小明之间从未直接交流过。

  • 边际层面:你和小明可能有很多共同点(都喜欢小红分享的内容、都参加小红组织的活动)
  • 条件层面:如果”控制住”小红(即假设小红不存在),你和小明之间没有任何联系
Code
graph LR
    A["你"] --- B["小红"]
    B --- C["小明"]
    A -.-x|"条件独立"| C
    
    style A fill:#e3f2fd
    style B fill:#fff3e0
    style C fill:#e8f5e9
graph LR
    A["你"] --- B["小红"]
    B --- C["小明"]
    A -.-x|"条件独立"| C
    
    style A fill:#e3f2fd
    style B fill:#fff3e0
    style C fill:#e8f5e9
Figure 2: 社交网络中的条件独立:你与小明只是通过小红间接相连

股票网络中

  • 边际相关高:两只股票都跟大盘走势相似
  • 条件独立:排除大盘影响后,它们没有直接联系
  • 有边相连:即使排除大盘,它们仍然同步波动(如同一家公司的 A 股和 H 股)

高斯图模型就是帮我们找出:谁是真朋友,谁只是朋友的朋友?

金融应用的意义

传统相关分析 GGM 分析
发现”谁和谁一起涨跌” 发现”谁直接影响谁”
受市场因子混杂 剔除第三方因素干扰
网络稠密、难以解读 网络稀疏、结构清晰
侧重描述 更接近因果机制

理论框架:高斯图模型

目标:理解为什么精度矩阵(协方差矩阵的逆)能揭示变量之间的”直接联系”。这是整个高斯图模型的数学核心。

数学预备知识(Matrix Algebra Primer)

在深入理论之前,我们先回顾几个关键的线性代数概念:

协方差矩阵与矩阵的逆

协方差矩阵 \(\Sigma\)

对于 \(p\) 个随机变量 \(X_1, \dots, X_p\),协方差矩阵 \(\Sigma\) 是一个 \(p \times p\) 矩阵: \[ \Sigma = \begin{pmatrix} \text{Var}(X_1) & \text{Cov}(X_1,X_2) & \cdots & \text{Cov}(X_1,X_p) \\ \text{Cov}(X_2,X_1) & \text{Var}(X_2) & \cdots & \text{Cov}(X_2,X_p) \\ \vdots & \vdots & \ddots & \vdots \\ \text{Cov}(X_p,X_1) & \text{Cov}(X_p,X_2) & \cdots & \text{Var}(X_p) \end{pmatrix} \]

矩阵的逆:若 \(\Sigma\) 可逆,则存在唯一矩阵 \(\Theta = \Sigma^{-1}\) 使得 \(\Sigma \Theta = I\)

Schur 补与正定矩阵

Schur 补(Schur Complement)

将矩阵分块为: \[ M = \begin{pmatrix} A & B \\ C & D \end{pmatrix} \]\(D\) 可逆,则 \(A\) 关于 \(D\) 的 Schur 补为 \(A - BD^{-1}C\)

正定矩阵

若对所有非零向量 \(v\),都有 \(v^T \Sigma v > 0\),则 \(\Sigma\) 是正定的。协方差矩阵总是半正定的。

条件分布推导:问题设定

这是理解高斯图模型的核心数学工具

设定:设 \(X = (X_1, X_2)^T \sim \mathcal{N}(\mu, \Sigma)\),将均值和协方差分块:

\[ \mu = \begin{pmatrix} \mu_1 \\ \mu_2 \end{pmatrix}, \quad \Sigma = \begin{pmatrix} \Sigma_{11} & \Sigma_{12} \\ \Sigma_{21} & \Sigma_{22} \end{pmatrix} \]

目标:求 \(X_1 | X_2 = x_2\) 的条件分布。

条件分布推导:第一、二步

第一步:联合密度函数 \[ f(x) = \frac{1}{(2\pi)^{p/2} |\Sigma|^{1/2}} \exp\left( -\frac{1}{2} (x - \mu)^T \Sigma^{-1} (x - \mu) \right) \]

第二步:分块逆矩阵

\(\Theta = \Sigma^{-1}\),分块为 \(\begin{pmatrix} \Theta_{11} & \Theta_{12} \\ \Theta_{21} & \Theta_{22} \end{pmatrix}\),则:

\[ \Theta_{11} = (\Sigma_{11} - \Sigma_{12}\Sigma_{22}^{-1}\Sigma_{21})^{-1}, \quad \Theta_{12} = -\Theta_{11} \Sigma_{12} \Sigma_{22}^{-1} \]

条件分布推导:第三、四步

第三步:展开二次型 \[ (x-\mu)^T \Theta (x-\mu) = (x_1 - \mu_1)^T \Theta_{11} (x_1 - \mu_1) + 2(x_1 - \mu_1)^T \Theta_{12} (x_2 - \mu_2) + \cdots \]

第四步:配方(Completing the Square)

\(x_1\) 配方,令 \(\tilde{\mu}_1 = \mu_1 - \Theta_{11}^{-1}\Theta_{12}(x_2 - \mu_2)\)\[ (x-\mu)^T \Theta (x-\mu) = (x_1 - \tilde{\mu}_1)^T \Theta_{11} (x_1 - \tilde{\mu}_1) + \text{(与 } x_1 \text{ 无关的项)} \]

条件分布:结论

\[ \boxed{X_1 | X_2 = x_2 \sim \mathcal{N}\left( \mu_1 + \Sigma_{12}\Sigma_{22}^{-1}(x_2 - \mu_2), \; \Sigma_{11} - \Sigma_{12}\Sigma_{22}^{-1}\Sigma_{21} \right)} \]

关键观察\[ \boxed{\text{条件协方差} = \Sigma_{11} - \Sigma_{12}\Sigma_{22}^{-1}\Sigma_{21} = \Theta_{11}^{-1}} \]

💡 直观理解

  • 精度矩阵的子块 \(\Theta_{11}\) 编码了 \(X_1\) 在给定 \(X_2\) 后的”剩余不确定性”
  • 如果 \(\Theta_{12}\) 的某个元素为零,说明对应变量之间没有”直接联系”——它们的协方差完全可以通过其他变量解释

精度矩阵与条件独立性 (Precision Matrix & Conditional Independence)

基本定义

假设我们有一组随机变量 \(X = (X_1, \dots, X_p)^T\),服从多元正态分布 \(\mathcal{N}(\mu, \Sigma)\),其中 \(\Sigma\)\(p \times p\) 的协方差矩阵。

我们定义精度矩阵(Precision Matrix) \(\Theta\) 为协方差矩阵的逆: \[ \Theta = \Sigma^{-1} \]

精度矩阵也称为浓度矩阵(Concentration Matrix)信息矩阵(Information Matrix)

💡 为什么要研究逆矩阵? 这看起来像是”多此一举”——我们明明有协方差矩阵,为什么还要费力求逆?

答案是:协方差矩阵 \(\Sigma\) 衡量的是边际关系(不考虑其他变量),而精度矩阵 \(\Theta\) 衡量的是条件关系(控制住其他变量后)。这两种关系可能完全不同!

核心定理

高斯图模型的理论基础是以下定理:

定理(Precision Matrix 与条件独立性):设 \(X \sim \mathcal{N}(\mu, \Sigma)\)\(\Theta = \Sigma^{-1}\)。则: \[X_i \perp X_j \mid X_{\setminus \{i,j\}} \iff \Theta_{ij} = 0\]

即变量 \(X_i\)\(X_j\) 在给定所有其他变量的条件下相互独立,当且仅当精度矩阵的 \((i,j)\) 元素为零。

证明思路(第一步)

第一步:条件分布的显式形式

设将 \(X\) 分块为 \((X_i, X_j, X_{-(i,j)})^T\)。给定 \(X_{-(i,j)}\) 时:

\[ \begin{pmatrix} X_i \\ X_j \end{pmatrix} \Bigg| X_{-(i,j)} \sim \mathcal{N}\left( \mu^*, \Sigma^* \right) \]

其中条件协方差矩阵 \(\Sigma^*\) 可以通过 Schur 补计算。

证明思路(第二步)

第二步:精度矩阵与条件协方差的关系

\(\Theta_{12}\) 为精度矩阵对应 \((i,j)\)\(2 \times 2\) 子矩阵: \[ \Theta_{12} = \begin{pmatrix} \Theta_{ii} & \Theta_{ij} \\ \Theta_{ji} & \Theta_{jj} \end{pmatrix} \]

则条件协方差为: \[ \text{Cov}(X_i, X_j \mid X_{-(i,j)}) = \frac{-\Theta_{ij}}{\Theta_{ii}\Theta_{jj} - \Theta_{ij}^2} \]

证明结论

结论

  • \(\Theta_{ij} = 0\),则条件协方差为 \(0\)
  • 对于正态分布,协方差为零 \(\Leftrightarrow\) 独立
  • 因此 \(\Theta_{ij} = 0 \Leftrightarrow X_i \perp X_j \mid X_{-(i,j)}\) \(\square\)

线性回归视角

另一种理解精度矩阵的直观方式是通过线性回归

\[ X_i = \sum_{k \neq i} \beta_{ik} X_k + \varepsilon_i \]

可以证明: \[ \beta_{ij} = -\frac{\Theta_{ij}}{\Theta_{ii}}, \quad \text{Var}(\varepsilon_i) = \frac{1}{\Theta_{ii}} \]

回归系数公式的证明

证明 \(\beta_{ij} = -\Theta_{ij}/\Theta_{ii}\)

在多元正态分布中,条件期望就是最优线性预测: \[ \mathbb{E}[X_i \mid X_{-i}] = \mu_i + \Sigma_{i,-i} \Sigma_{-i,-i}^{-1} (X_{-i} - \mu_{-i}) \]

利用分块矩阵逆的性质:\(\Theta_{i,-i} = -\Theta_{ii} \cdot \Sigma_{i,-i} \Sigma_{-i,-i}^{-1}\)

因此:\(\beta_{ij} = -\Theta_{ij}/\Theta_{ii}\) \(\square\)

直观解释

精度矩阵元素 回归解释 图模型含义
\(\Theta_{ii}\) 残差精度(\(1/\text{Var}(\varepsilon_i)\) 节点 \(i\) 的”固有不确定性”
\(\Theta_{ij}\) 与回归系数成比例 \((i,j)\)的”强度”
\(\Theta_{ij} = 0\) \(X_j\) 不在 \(X_i\) 的回归模型中 节点 \(i\)\(j\) 之间无边

💡 关键洞察:精度矩阵实际上编码了一系列”节点对节点”的回归关系!

这解释了为什么 Graphical Lasso 的核心子问题是 Lasso 回归——我们实际上在做的是:对每个节点 \(i\),用正则化回归找出哪些其他节点能”直接预测”它。

偏相关系数 (Partial Correlation)

定义与公式

精度矩阵的元素 \(\Theta_{ij}\) 虽然携带了条件依赖的信息,但其数值大小不直观(受变量尺度影响)。为此,我们将其标准化为偏相关系数(Partial Correlation Coefficient)

\[ \rho_{ij \mid \text{rest}} = - \frac{\Theta_{ij}}{\sqrt{\Theta_{ii} \Theta_{jj}}} \]

解释

  • 偏相关系数 \(\rho_{ij \mid \text{rest}} \in [-1, 1]\)
  • \(\rho_{ij \mid \text{rest}} = 0\) → 条件独立(无边)
  • \(\rho_{ij \mid \text{rest}} > 0\) → 正条件相关(红色边)
  • \(\rho_{ij \mid \text{rest}} < 0\) → 负条件相关(绿色边)

公式推导(简化版)

条件协方差:\(\text{Cov}(X_i, X_j \mid X_{-(i,j)}) = -\Theta_{ij}/\det(\Theta_{12})\)

条件方差:\(\text{Var}(X_i \mid X_{-(i,j)}) = \Theta_{jj}/\det(\Theta_{12})\)

偏相关系数 = 条件协方差 / √(条件方差乘积),化简后得:

\[\rho_{ij \mid \text{rest}} = -\frac{\Theta_{ij}}{\sqrt{\Theta_{ii} \Theta_{jj}}} \quad \square\]

三变量计算示例

协方差矩阵与精度矩阵: \[ \Sigma = \begin{pmatrix} 1 & 0.8 & 0.6 \\ 0.8 & 1 & 0.7 \\ 0.6 & 0.7 & 1 \end{pmatrix}, \quad \Theta = \Sigma^{-1} \approx \begin{pmatrix} 2.80 & -2.09 & -0.22 \\ -2.09 & 3.52 & -1.21 \\ -0.22 & -1.21 & 1.98 \end{pmatrix} \]

偏相关系数计算结果

偏相关 计算式 结果
\(\rho_{12 \mid 3}\) \(-\frac{-2.09}{\sqrt{2.80 \times 3.52}}\) ≈ 0.67
\(\rho_{13 \mid 2}\) \(-\frac{-0.22}{\sqrt{2.80 \times 1.98}}\) ≈ 0.09
\(\rho_{23 \mid 1}\) \(-\frac{-1.21}{\sqrt{3.52 \times 1.98}}\) ≈ 0.46

用 Python 验证这个计算

Code
import numpy as np

# 定义协方差矩阵
Sigma = np.array([
    [1.0, 0.8, 0.6],
    [0.8, 1.0, 0.7],
    [0.6, 0.7, 1.0]
])

# 计算精度矩阵
Theta = np.linalg.inv(Sigma)
print("精度矩阵 Θ:")
print(np.round(Theta, 2))

# 计算偏相关系数:这里展示公式 -Θ_ij / sqrt(Θ_ii * Θ_jj)
def compute_partial_corr(Theta):
    """从精度矩阵计算偏相关系数矩阵"""
    p = Theta.shape[0]
    d = np.sqrt(np.diag(Theta))
    partial_corr = -Theta / np.outer(d, d)
    np.fill_diagonal(partial_corr, 1)
    return partial_corr

partial_corr = compute_partial_corr(Theta)
print("\n偏相关系数矩阵:")
print(np.round(partial_corr, 3))

# 对比:边际相关系数
print("\n边际相关系数(协方差矩阵本身,因为是标准化的):")
print(Sigma)
精度矩阵 Θ:
[[ 2.8  -2.09 -0.22]
 [-2.09  3.52 -1.21]
 [-0.22 -1.21  1.98]]

偏相关系数矩阵:
[[1.    0.665 0.093]
 [0.665 1.    0.458]
 [0.093 0.458 1.   ]]

边际相关系数(协方差矩阵本身,因为是标准化的):
[[1.  0.8 0.6]
 [0.8 1.  0.7]
 [0.6 0.7 1. ]]

Important

🔑 关键发现

变量对 边际相关系数 偏相关系数 解释
\((X_1, X_2)\) 0.80 0.67 仍有较强直接联系
\((X_1, X_3)\) 0.60 0.09 大部分是通过 \(X_2\) 的间接联系!
\((X_2, X_3)\) 0.70 0.46 仍有较强直接联系

结论\(X_1\)\(X_3\) 的高边际相关(0.60)大部分是虚假的——它们主要是因为都与 \(X_2\) 相关。控制住 \(X_2\) 后,偏相关仅为 0.09。

这正是高斯图模型的价值:看透表象,找到真正的”直接联系”。

稀疏估计与 Graphical Lasso

高维估计的挑战

在实际金融数据中,我们面临高维问题

  • 维度 \(p\)(股票数量):可能是几十甚至数百只
  • 样本量 \(n\)(历史交易日):通常 200-500 天

样本协方差矩阵的局限

情形 样本协方差矩阵 \(S\) 直接求逆 \(S^{-1}\)
\(n > p\) 满秩,可逆 可行,但不稳定
\(n \approx p\) 接近奇异 高度不稳定
\(n < p\) 秩亏,不可逆 不可行

即使 \(n > p\),直接用 \(S^{-1}\) 作为 \(\Theta\) 的估计也会过拟合

稀疏性假设

我们假设真实的金融网络是稀疏的(Sparse)

  • 绝大多数股票之间没有直接联系
  • 只有少数”核心”股票与其他股票有直接边
  • 这符合金融市场的实际特征(同行业、供应链上下游)

什么是 Lasso?

Tip

💡 Lasso(Least Absolute Shrinkage and Selection Operator)是一种正则化技术,通过对参数的绝对值施加惩罚,能够自动将不重要的参数”压缩”为精确的零

直观理解:想象在二维空间中最小化目标函数:

  • \(\ell_2\) 约束(Ridge,圆形):最优解被”拉向”原点,但几乎不会精确为零
  • \(\ell_1\) 约束(Lasso,菱形):因为菱形有”尖角”,最优解更容易落在坐标轴上——即某些参数精确为零!

Lasso 几何直观

Code
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.patches import Circle, Polygon
from matplotlib.lines import Line2D

fig, axes = plt.subplots(1, 2, figsize=(12, 5))

# === 左图:L2 约束(Ridge)===
ax1 = axes[0]
ax1.set_xlim(-2.5, 2.5)
ax1.set_ylim(-2.5, 2.5)
ax1.set_aspect('equal')
ax1.axhline(y=0, color='gray', linewidth=0.5, linestyle='--')
ax1.axvline(x=0, color='gray', linewidth=0.5, linestyle='--')

# 绘制椭圆等高线(目标函数)
theta1 = np.linspace(0, 2*np.pi, 100)
for r in [0.5, 1.0, 1.5, 2.0]:
    x_ellipse = 1.5 + r * 0.8 * np.cos(theta1)
    y_ellipse = 1.2 + r * 0.5 * np.sin(theta1 - 0.3)
    ax1.plot(x_ellipse, y_ellipse, 'b-', alpha=0.3, linewidth=1)

# L2 约束圆
circle = Circle((0, 0), 1.2, fill=False, edgecolor='red', linewidth=2.5)
ax1.add_patch(circle)
ax1.fill_between(1.2*np.cos(theta1), 1.2*np.sin(theta1), alpha=0.15, color='red')

# 最优解点(在圆上但不在坐标轴)
opt_x_l2, opt_y_l2 = 0.85, 0.85
ax1.plot(opt_x_l2, opt_y_l2, 'ko', markersize=12, markerfacecolor='gold', markeredgewidth=2)
ax1.annotate('Optimal\n(non-sparse)', (opt_x_l2, opt_y_l2), 
             xytext=(opt_x_l2+0.5, opt_y_l2+0.6), fontsize=11,
             arrowprops=dict(arrowstyle='->', color='black'))

# 无约束最优解
ax1.plot(1.5, 1.2, 'b*', markersize=15)
ax1.annotate('Unconstrained\nOptimum', (1.5, 1.2), xytext=(1.8, 1.8), fontsize=10,
             arrowprops=dict(arrowstyle='->', color='blue'))

ax1.set_xlabel(r'$\theta_1$', fontsize=12)
ax1.set_ylabel(r'$\theta_2$', fontsize=12)
ax1.set_title(r'L2 Constraint (Ridge): $\|\theta\|_2^2 \leq t$', fontsize=13, fontweight='bold')

# === 右图:L1 约束(Lasso)===
ax2 = axes[1]
ax2.set_xlim(-2.5, 2.5)
ax2.set_ylim(-2.5, 2.5)
ax2.set_aspect('equal')
ax2.axhline(y=0, color='gray', linewidth=0.5, linestyle='--')
ax2.axvline(x=0, color='gray', linewidth=0.5, linestyle='--')

# 绘制椭圆等高线(目标函数)
for r in [0.5, 1.0, 1.5, 2.0]:
    x_ellipse = 1.5 + r * 0.8 * np.cos(theta1)
    y_ellipse = 1.2 + r * 0.5 * np.sin(theta1 - 0.3)
    ax2.plot(x_ellipse, y_ellipse, 'b-', alpha=0.3, linewidth=1)

# L1 约束菱形
t = 1.2
diamond = Polygon([(t, 0), (0, t), (-t, 0), (0, -t)], 
                   fill=True, facecolor='lightgreen', edgecolor='green', 
                   linewidth=2.5, alpha=0.4)
ax2.add_patch(diamond)

# 最优解点(在菱形角上 = 稀疏!)
opt_x_l1, opt_y_l1 = 1.2, 0.0  # 在坐标轴上
ax2.plot(opt_x_l1, opt_y_l1, 'ko', markersize=12, markerfacecolor='gold', markeredgewidth=2)
ax2.annotate(r'Optimal ($\theta_2 = 0$)' + '\nSPARSE!', (opt_x_l1, opt_y_l1), 
             xytext=(opt_x_l1+0.3, opt_y_l1-0.8), fontsize=11, color='darkgreen',
             fontweight='bold', arrowprops=dict(arrowstyle='->', color='darkgreen'))

# 无约束最优解
ax2.plot(1.5, 1.2, 'b*', markersize=15)
ax2.annotate('Unconstrained\nOptimum', (1.5, 1.2), xytext=(1.8, 1.8), fontsize=10,
             arrowprops=dict(arrowstyle='->', color='blue'))

# 高亮菱形顶点
for corner in [(t, 0), (0, t), (-t, 0), (0, -t)]:
    ax2.plot(corner[0], corner[1], 'g^', markersize=8)

ax2.set_xlabel(r'$\theta_1$', fontsize=12)
ax2.set_ylabel(r'$\theta_2$', fontsize=12)
ax2.set_title(r'L1 Constraint (Lasso): $\|\theta\|_1 \leq t$', fontsize=13, fontweight='bold')

# 添加图例
legend_elements = [
    Line2D([0], [0], color='blue', alpha=0.3, linewidth=2, label='Objective contours'),
    Line2D([0], [0], marker='*', color='w', markerfacecolor='blue', markersize=12, label='Unconstrained optimum'),
    Line2D([0], [0], marker='o', color='w', markerfacecolor='gold', markersize=10, 
           markeredgecolor='black', markeredgewidth=1.5, label='Constrained optimum'),
]
fig.legend(handles=legend_elements, loc='lower center', ncol=3, fontsize=10, frameon=True)

plt.tight_layout()
plt.subplots_adjust(bottom=0.18)
plt.show()
Figure 3: L1 (Lasso) vs L2 (Ridge) 约束区域的几何对比

为什么菱形产生稀疏解?

从几何上看:

  • 椭圆等高线代表目标函数的等高面(越接近中心,目标函数值越小)
  • 约束区域限制了参数必须落在的范围内
  • 最优解是等高线与约束边界的切点

关键观察:

  • L2(圆形):等高线几乎可以与圆的任何位置相切 → 解一般不在坐标轴上
  • L1(菱形):菱形的”尖角”在坐标轴上 → 等高线更容易与尖角相切 → 稀疏解!

软阈值函数:Lasso 稀疏性的数学本质

对于一维 Lasso 问题 \(\min_\theta \frac{1}{2}(y - \theta)^2 + \lambda|\theta|\),最优解有解析形式

\[ \hat{\theta} = \text{sign}(y) \cdot \max(|y| - \lambda, 0) = S_\lambda(y) \]

这称为软阈值函数(Soft Thresholding)

Code
import numpy as np
import matplotlib.pyplot as plt

y = np.linspace(-3, 3, 500)
lambdas = [0.5, 1.0, 1.5]
colors = ['#2ecc71', '#3498db', '#9b59b6']

fig, ax = plt.subplots(figsize=(8, 5))

# 无惩罚的恒等线
ax.plot(y, y, 'k--', alpha=0.4, linewidth=1.5, label=r'No penalty ($\lambda=0$)')

for lam, color in zip(lambdas, colors):
    soft_thresh = np.sign(y) * np.maximum(np.abs(y) - lam, 0)
    ax.plot(y, soft_thresh, color=color, linewidth=2.5, label=rf'$\lambda = {lam}$')
    # 标注零区域
    ax.axvspan(-lam, lam, alpha=0.05, color=color)

ax.axhline(y=0, color='gray', linewidth=0.5)
ax.axvline(x=0, color='gray', linewidth=0.5)

ax.set_xlabel(r'Input $y$', fontsize=12)
ax.set_ylabel(r'Output $\hat{\theta} = S_\lambda(y)$', fontsize=12)
ax.set_title('Soft Thresholding Function', fontsize=13, fontweight='bold')
ax.legend(loc='lower right', fontsize=10)
ax.set_xlim(-3, 3)
ax.set_ylim(-3, 3)
ax.grid(True, alpha=0.3)

# 添加注释
ax.annotate('Zero region\n(sparse!)', xy=(0, 0), xytext=(1.5, -1.5),
            fontsize=10, color='darkgreen',
            arrowprops=dict(arrowstyle='->', color='darkgreen'))

plt.tight_layout()
plt.show()
Figure 4: 软阈值函数:当 |y| ≤ λ 时,解被 ‘压缩’ 为精确的零

直观解释:当输入信号 \(|y|\) 小于阈值 \(\lambda\) 时,Lasso 直接将其”压缩”为零——这就是为什么 Lasso 能自动进行变量选择

在 Graphical Lasso 中,这意味着:如果两只股票之间的条件相关性较弱(信号小于阈值),算法会直接认为它们没有直接联系

这就是为什么 Graphical Lasso 能够自动发现哪些股票之间真的有直接联系,哪些只是”假相关”。

极大似然函数推导

设观测数据为 \(X^{(1)}, \dots, X^{(n)} \stackrel{i.i.d.}{\sim} \mathcal{N}(0, \Sigma)\)

对数似然函数(忽略常数)为: \[\ell(\Theta) = \frac{n}{2} \log \det \Theta - \frac{n}{2} \text{tr}(\Theta S)\]

其中 \(S = \frac{1}{n}\sum_{i=1}^n X^{(i)}(X^{(i)})^T\) 是样本协方差矩阵。

Graphical Lasso 目标函数

添加 \(\ell_1\) 惩罚后,优化问题为: \[\hat{\Theta} = \arg \max_{\Theta \succ 0} \left\{ \log \det \Theta - \text{tr}(S \Theta) - \lambda \|\Theta\|_{1,\text{off}} \right\}\]

其中 \(\|\Theta\|_{1,\text{off}} = \sum_{i \neq j} |\Theta_{ij}|\) 是非对角元素的 \(\ell_1\) 范数。

\(\lambda\) 参数的影响

\(\lambda\) 估计的 \(\hat{\Theta}\) 图结构
\(\lambda \to 0\) 接近 \(S^{-1}\) 稠密
\(\lambda\) 适中 稀疏但保留关键边 较稀疏
\(\lambda \to \infty\) 对角矩阵 无边(孤立节点)

坐标下降算法思想

Friedman 等人(2008)提出的 Graphical Lasso 算法采用块坐标下降策略:

  1. \(\Theta\)\(S\) 按行/列分块
  2. 固定除第 \(j\) 行/列外的所有元素,优化第 \(j\) 行/列
  3. 子问题恰好是一个 Lasso 回归
  4. 循环遍历所有行/列,直到收敛

算法伪代码

输入: \(S\), \(\lambda\), 收敛阈值 \(\varepsilon\)

初始化: \(W = S + \lambda I\)

循环 对每一列 \(j = 1, \dots, p\):

  1. 分块: \(W_{11} = W_{-j,-j}, s_{12} = S_{-j,j}\)
  2. 解 Lasso: \(\beta = \arg\min_\beta \frac{1}{2} \beta^T W_{11} \beta - s_{12}^T \beta + \lambda \|\beta\|_1\)
  3. 更新: \(w_{12} = W_{11} \beta\)

直到 \(W\) 收敛

输出: \(\Theta = W^{-1}\)

方法比较

方法 核心思想 优点 缺点
Graphical Lasso 直接优化带惩罚似然 高效 需调参
邻域选择 (MB) 对每个节点做 Lasso 可并行 不保证正定
CLIME 线性规划 理论优雅 计算慢
QUIC 二阶近似加速 更快收敛 实现复杂

模型选择 (Model Selection)

\(\lambda\) 的选择对结果影响巨大。常用方法:交叉验证、BIC / EBIC 准则。

交叉验证

将数据分为训练集和验证集,选择使验证集对数似然最大的 \(\lambda\)\[ \lambda^* = \arg\max_\lambda \left\{ \log \det \hat{\Theta}_\lambda^{\text{train}} - \text{tr}(S^{\text{valid}} \hat{\Theta}_\lambda^{\text{train}}) \right\} \]

优点:直接优化预测性能

缺点:计算量大;可能选择过于稠密的模型

BIC 准则

BIC(贝叶斯信息准则)\[ \text{BIC}(\lambda) = -2 \ell(\hat{\Theta}_\lambda) + \log(n) \cdot |\mathcal{E}_\lambda| \]

其中 \(|\mathcal{E}_\lambda|\) 是估计图中的边数。

Extended BIC (EBIC)

Foygel & Drton (2010) 提出的 EBIC: \[ \text{EBIC}_\gamma(\lambda) = -2 \ell(\hat{\Theta}_\lambda) + \log(n) \cdot |\mathcal{E}_\lambda| + 4 \gamma \log(p) \cdot |\mathcal{E}_\lambda| \]

  • \(\gamma \in [0, 1]\) 控制对复杂模型的额外惩罚
  • \(\gamma = 0\) 退化为 BIC;\(\gamma = 0.5\) 是常用选择

稳定性选择

Meinshausen & Bühlmann (2010) 提出:

  1. 对数据进行多次子采样
  2. 对每次子采样运行 Graphical Lasso
  3. 统计每条边被选中的频率
  4. 只保留选中频率超过阈值(如 \(\pi_{\text{thr}} = 0.6\))的边

优点:结果稳健,不依赖单一的 \(\lambda\) 选择

模型选择:实践建议

场景 推荐方法 理由
探索性分析 交叉验证 平衡拟合与泛化
学术研究 EBIC (\(\gamma = 0.5\)) 理论保证,偏向稀疏
稳健推断 稳定性选择 减少假阳性边

环境准备与数据获取

首先,我们需要导入必要的库并设置 Tushare API。

Code
import tushare as ts
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import networkx as nx
from sklearn.covariance import GraphicalLassoCV
from sklearn.preprocessing import StandardScaler

# 设置 Tushare API Token
ts.set_token(tushare_token)
pro = ts.pro_api()

获取股票数据

为了演示,我们将选取上证50 (SSE 50) 成分股中权重最大的 30 只股票来进行分析,以观察它们之间的关联结构。

这里我们获取过去三年的日线数据,以确保样本量足够。

Code
# 获取上证50成分股列表
df_index = pro.index_weight(index_code='000016.SH', start_date='20230101', end_date='20230131')
# 选取权重最大的 30 只股票
tickers = df_index.head(30)['con_code'].tolist()
ticker_names = df_index.head(30)['con_code'].tolist() # 暂时用代码,后续可以换成名称

print(f"Selected {len(tickers)} stocks for analysis.")

# 获取日线数据(3年)
data_dict = {}
start_date = '20210101'  # 扩展为3年
end_date = '20231231'

for ticker in tickers:
    try:
        df = pro.daily(ts_code=ticker, start_date=start_date, end_date=end_date)
        df = df.set_index('trade_date').sort_index()
        data_dict[ticker] = df['close']
    except Exception as e:
        print(f"Error fetching {ticker}: {e}")

# 合并为一个 DataFrame
prices = pd.DataFrame(data_dict)
prices.index = pd.to_datetime(prices.index)

# 查看数据概况
print(prices.shape)
prices.head()
Selected 30 stocks for analysis.
(727, 30)
600519.SH 601318.SH 600036.SH 601012.SH 601166.SH 600900.SH 600030.SH 600887.SH 601888.SH 603259.SH ... 600690.SH 600436.SH 601088.SH 601288.SH 601601.SH 600406.SH 603799.SH 688599.SH 603986.SH 601225.SH
trade_date
2021-01-04 1997.00 85.18 43.17 100.10 19.65 18.90 29.18 47.36 292.25 137.11 ... 30.01 279.98 17.99 3.13 38.35 26.69 87.1 24.17 198.62 9.59
2021-01-05 2059.45 84.27 42.18 104.87 18.86 18.89 29.14 50.93 293.02 141.99 ... 31.78 296.38 17.65 3.13 37.90 27.12 88.3 23.18 208.90 9.51
2021-01-06 2100.00 85.74 44.15 107.00 19.73 19.21 29.62 50.56 288.00 143.74 ... 31.65 294.45 17.95 3.13 38.17 26.29 89.0 22.73 203.72 9.59
2021-01-07 2140.00 86.26 45.90 113.55 20.10 19.23 29.75 51.69 311.00 145.95 ... 32.68 299.91 18.26 3.14 39.27 27.20 95.6 23.60 200.55 10.05
2021-01-08 2090.00 86.10 46.60 110.40 20.32 19.34 30.06 49.27 291.00 146.21 ... 33.00 296.59 18.63 3.14 39.00 27.82 94.9 23.50 202.56 10.24

5 rows × 30 columns

数据预处理

我们需要计算股票的对数收益率,并进行标准化处理。

Code
# 计算对数收益率
returns = np.log(prices / prices.shift(1)).dropna()

# 标准化数据 (Graphical Lasso 对尺度敏感)
scaler = StandardScaler()
X = scaler.fit_transform(returns)

print(f"Data shape after preprocessing: {X.shape}")
Data shape after preprocessing: (706, 30)

模型训练:Graphical Lasso

我们使用交叉验证(Cross-Validation)来自动选择正则化参数 \(\alpha\),以获得最佳的稀疏结构。

Code
# 训练 Graphical Lasso 模型
# alpha 越大,图越稀疏
model = GraphicalLassoCV(cv=5)
model.fit(X)

covariance = model.covariance_
precision = model.precision_
alpha = model.alpha_

print(f"Optimal alpha: {alpha}")
Optimal alpha: 0.16928927015796227

结果可视化

我们将精度矩阵转换为网络图。非零的偏相关系数(Partial Correlation)表示节点之间的边。

上证50成分股条件依赖网络

Code
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches

# 获取股票名称(通过tushare查询或使用预设映射)
# 尝试获取股票名称
try:
    stock_name_map = {}
    for code in returns.columns:
        stock_info = pro.stock_basic(ts_code=code, fields='ts_code,name')
        if len(stock_info) > 0:
            stock_name_map[code] = stock_info.iloc[0]['name']
        else:
            stock_name_map[code] = code
except:
    # 如果API调用失败,使用代码作为名称
    stock_name_map = {code: code for code in returns.columns}

# 从精度矩阵计算偏相关系数矩阵
# 正确公式: ρ_ij|rest = -Θ_ij / √(Θ_ii × Θ_jj)
d = np.sqrt(np.diag(precision))
partial_corr = -precision / np.outer(d, d)  # 注意负号!
np.fill_diagonal(partial_corr, 1)  # 对角线为1(自相关)

# 创建图结构
G = nx.Graph()

# 使用股票名称作为节点标签
stock_codes = returns.columns.tolist()
stock_names_display = [stock_name_map.get(code, code) for code in stock_codes]
G.add_nodes_from(stock_names_display)

# 添加边(设定阈值,只显示较强的关联)
threshold = 0.15 
edges = []
weights = []
edge_colors_list = []

n_features = len(stock_codes)
for i in range(n_features):
    for j in range(i + 1, n_features):
        coef = partial_corr[i, j]
        if abs(coef) > threshold:
            name_i = stock_names_display[i]
            name_j = stock_names_display[j]
            G.add_edge(name_i, name_j, weight=coef)
            edges.append((name_i, name_j))
            weights.append(coef)
            # 根据偏相关系数正负确定颜色
            if coef > 0:
                edge_colors_list.append('#e74c3c')  # 红色:正相关
            else:
                edge_colors_list.append('#27ae60')  # 绿色:负相关

# 绘图 - 使用更紧凑的尺寸
fig, ax = plt.subplots(figsize=(10, 7))

# 布局算法 - 减小k值使节点更紧凑
pos = nx.spring_layout(G, k=0.15, seed=42, iterations=100)

# 绘制节点
nx.draw_networkx_nodes(G, pos, node_size=400, node_color='#3498db', alpha=0.85, ax=ax)

# 绘制边(使用正确的颜色列表)
if edges:  # 只有当有边时才绘制
    edge_widths = [abs(w) * 5 for w in weights]
    nx.draw_networkx_edges(G, pos, edgelist=edges, width=edge_widths, 
                           edge_color=edge_colors_list, alpha=0.7, ax=ax)

# 绘制标签(使用较小字体以适应中文名称)
nx.draw_networkx_labels(G, pos, font_size=5, font_family='sans-serif', ax=ax)

# 添加图例
pos_patch = mpatches.Patch(color='#e74c3c', label='正偏相关(协同波动)')
neg_patch = mpatches.Patch(color='#27ae60', label='负偏相关(反向波动)')
ax.legend(handles=[pos_patch, neg_patch], loc='upper left', fontsize=10, frameon=True)

# 统计边的数量
n_pos_edges = sum(1 for w in weights if w > 0)
n_neg_edges = sum(1 for w in weights if w <= 0)

ax.set_title(f'上证50成分股条件依赖网络\n(阈值={threshold}, 正边数={n_pos_edges}, 负边数={n_neg_edges})', 
             fontsize=14, fontweight='bold')
ax.axis('off')
plt.tight_layout()
plt.show()

# 打印边统计信息
print(f"\n=== 网络统计 ===")
print(f"节点数: {G.number_of_nodes()}")
print(f"边数: {G.number_of_edges()}")
print(f"  - 正偏相关边: {n_pos_edges}")
print(f"  - 负偏相关边: {n_neg_edges}")
Figure 5: 上证50成分股条件依赖网络(Graphical Lasso)

=== 网络统计 ===
节点数: 30
边数: 18
  - 正偏相关边: 18
  - 负偏相关边: 0

跨行业样本对比:正负偏相关边的直观展示

上述上证50成分股主要是大盘蓝筹股,它们之间几乎都是正偏相关(红色边)。为了让同学们直观地看到红色边和绿色边的对比,我们下面使用一组跨行业的股票进行分析。

跨行业样本对比(图表)

Code
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
import networkx as nx
from sklearn.covariance import GraphicalLassoCV
from sklearn.preprocessing import StandardScaler


# 选取跨行业代表性股票(去除金融和地产,加入农业和消费)
# 样本区间扩展为3年,增加观察样本量
cross_industry_stocks = {
    # 科技成长
    '海康威视': '002415.SZ',
    '立讯精密': '002475.SZ',
    '中兴通讯': '000063.SZ',
    # 医药(防御性)
    '恒瑞医药': '600276.SH',
    '片仔癀': '600436.SH',
    '云南白药': '000538.SZ',
    # 白酒消费(防御+成长)
    '贵州茅台': '600519.SH',
    '五粮液': '000858.SZ',
    '泸州老窖': '000568.SZ',
    # 日常消费
    '伊利股份': '600887.SH',
    '海天味业': '603288.SH',
    '双汇发展': '000895.SZ',
    # 农业
    '牧原股份': '002714.SZ',
    '温氏股份': '300498.SZ',
    '新希望': '000876.SZ',
    # 新能源(高成长)
    '宁德时代': '300750.SZ',
    '隆基绿能': '601012.SH',
    # 传统制造
    '三一重工': '600031.SH',
    '美的集团': '000333.SZ',
}

# 获取数据(3年期间)
data_cross = {}
for name, code in cross_industry_stocks.items():
    try:
        df = pro.daily(ts_code=code, start_date='20210101', end_date='20231231')  # 3年数据
        df = df.set_index('trade_date').sort_index()
        data_cross[name] = df['close']
    except Exception as e:
        print(f"获取 {name} 失败: {e}")

# 合并数据
prices_cross = pd.DataFrame(data_cross)
prices_cross.index = pd.to_datetime(prices_cross.index)

# 处理缺失值
prices_cross = prices_cross.dropna(axis=1, how='any')  # 删除有缺失的股票
prices_cross = prices_cross.dropna()  # 删除有缺失的日期

print(f"成功获取 {len(prices_cross.columns)} 只股票,{len(prices_cross)} 个交易日的数据")

# 计算对数收益率
returns_cross = np.log(prices_cross / prices_cross.shift(1)).dropna()

# 标准化
scaler_cross = StandardScaler()
X_cross = scaler_cross.fit_transform(returns_cross)

# 训练 Graphical Lasso
model_cross = GraphicalLassoCV(cv=5)
model_cross.fit(X_cross)
precision_cross = model_cross.precision_

print(f"Graphical Lasso 最优 alpha: {model_cross.alpha_:.4f}")

# 计算偏相关系数(注意负号!)
d_cross = np.sqrt(np.diag(precision_cross))
partial_corr_cross = -precision_cross / np.outer(d_cross, d_cross)
np.fill_diagonal(partial_corr_cross, 1)

# 创建网络
G_cross = nx.Graph()
stock_names_cross = returns_cross.columns.tolist()
G_cross.add_nodes_from(stock_names_cross)

# 添加边(使用较低阈值以显示更多边)
threshold_cross = 0.15  # 与上证50样本使用相同阈值,便于对比
edges_cross = []
weights_cross = []
colors_cross = []

n_cross = len(stock_names_cross)
for i in range(n_cross):
    for j in range(i + 1, n_cross):
        coef = partial_corr_cross[i, j]
        if abs(coef) > threshold_cross:
            G_cross.add_edge(stock_names_cross[i], stock_names_cross[j], weight=coef)
            edges_cross.append((stock_names_cross[i], stock_names_cross[j]))
            weights_cross.append(coef)
            if coef > 0:
                colors_cross.append('#e74c3c')  # 红色:正偏相关
            else:
                colors_cross.append('#27ae60')  # 绿色:负偏相关

# 统计
n_pos_cross = sum(1 for w in weights_cross if w > 0)
n_neg_cross = sum(1 for w in weights_cross if w <= 0)

# 按行业分配颜色(与stock list对应)
industry_colors = {
    # 科技:青色
    '海康威视': '#1abc9c', '立讯精密': '#1abc9c', '中兴通讯': '#1abc9c',
    # 医药:红色
    '恒瑞医药': '#e74c3c', '片仔癀': '#e74c3c', '云南白药': '#e74c3c',
    # 白酒:金色
    '贵州茅台': '#f1c40f', '五粮液': '#f1c40f', '泸州老窖': '#f1c40f',
    # 日常消费:橙色
    '伊利股份': '#e67e22', '海天味业': '#e67e22', '双汇发展': '#e67e22',
    # 农业:棕色
    '牧原股份': '#8B4513', '温氏股份': '#8B4513', '新希望': '#8B4513',
    # 新能源:绿色
    '宁德时代': '#2ecc71', '隆基绿能': '#2ecc71',
    # 传统制造:蓝色
    '三一重工': '#3498db', '美的集团': '#3498db',
}
node_colors = [industry_colors.get(n, '#3498db') for n in G_cross.nodes()]

# 绘图 - 使用更紧凑的尺寸
fig, ax = plt.subplots(figsize=(10, 7))

# 布局 - 减小k值使节点更紧凑
pos_cross = nx.spring_layout(G_cross, k=0.25, seed=42, iterations=100)

# 绘制节点
nx.draw_networkx_nodes(G_cross, pos_cross, node_size=500, node_color=node_colors, alpha=0.9, ax=ax)

# 绘制边
if edges_cross:
    edge_widths = [abs(w) * 6 for w in weights_cross]
    nx.draw_networkx_edges(G_cross, pos_cross, edgelist=edges_cross, width=edge_widths, 
                           edge_color=colors_cross, alpha=0.7, ax=ax)

# 绘制标签
nx.draw_networkx_labels(G_cross, pos_cross, font_size=7, font_family='sans-serif', ax=ax)

# 图例
pos_patch = mpatches.Patch(color='#e74c3c', label=f'正偏相关(协同波动): {n_pos_cross} 条')
neg_patch = mpatches.Patch(color='#27ae60', label=f'负偏相关(反向波动): {n_neg_cross} 条')
ax.legend(handles=[pos_patch, neg_patch], loc='upper left', fontsize=11, frameon=True)

ax.set_title(f'跨行业股票条件依赖网络\n(阈值={threshold_cross}, 正边={n_pos_cross}, 负边={n_neg_cross})', 
             fontsize=14, fontweight='bold')
ax.axis('off')
plt.tight_layout()
plt.show()

# 打印统计
print(f"\n=== 跨行业网络统计 ===")
print(f"节点数: {G_cross.number_of_nodes()}")
print(f"边数: {G_cross.number_of_edges()}")
print(f"  - 正偏相关边(红色): {n_pos_cross}")
print(f"  - 负偏相关边(绿色): {n_neg_cross}")

# 展示部分偏相关系数
partial_corr_df_cross = pd.DataFrame(partial_corr_cross, 
                                      index=stock_names_cross, 
                                      columns=stock_names_cross)
print("\n=== 偏相关系数矩阵(部分展示)===")
print(partial_corr_df_cross.round(2))
成功获取 18 只股票,727 个交易日的数据
Graphical Lasso 最优 alpha: 0.0799
Figure 6: 跨行业股票条件依赖网络:同时展示正偏相关(红)与负偏相关(绿)

=== 跨行业网络统计 ===
节点数: 18
边数: 13
  - 正偏相关边(红色): 13
  - 负偏相关边(绿色): 0

=== 偏相关系数矩阵(部分展示)===
      海康威视  立讯精密  恒瑞医药   片仔癀  云南白药  贵州茅台   五粮液  泸州老窖  伊利股份  海天味业  双汇发展  牧原股份  \
海康威视  1.00  0.18  0.04  0.07  0.16  0.00  0.07  0.00  0.05  0.00  0.00  0.00   
立讯精密  0.18  1.00  0.06  0.07  0.00  0.03  0.00  0.01  0.01  0.00  0.00  0.00   
恒瑞医药  0.04  0.06  1.00  0.07  0.10  0.00  0.06  0.00  0.04  0.05  0.05  0.00   
片仔癀   0.07  0.07  0.07  1.00  0.15  0.12  0.09  0.11  0.04  0.06  0.00  0.00   
云南白药  0.16  0.00  0.10  0.15  1.00  0.00  0.02  0.01  0.05  0.00  0.00  0.00   
贵州茅台  0.00  0.03  0.00  0.12  0.00  1.00  0.33  0.29  0.06  0.04  0.05  0.03   
五粮液   0.07  0.00  0.06  0.09  0.02  0.33  1.00  0.45  0.12  0.07  0.01  0.00   
泸州老窖  0.00  0.01  0.00  0.11  0.01  0.29  0.45  1.00  0.02  0.08  0.00  0.00   
伊利股份  0.05  0.01  0.04  0.04  0.05  0.06  0.12  0.02  1.00  0.08  0.14  0.04   
海天味业  0.00  0.00  0.05  0.06  0.00  0.04  0.07  0.08  0.08  1.00  0.17  0.00   
双汇发展  0.00  0.00  0.05  0.00  0.00  0.05  0.01  0.00  0.14  0.17  1.00  0.06   
牧原股份  0.00  0.00  0.00  0.00  0.00  0.03  0.00  0.00  0.04  0.00  0.06  1.00   
温氏股份 -0.00  0.00  0.00 -0.00  0.00 -0.00 -0.00 -0.00  0.00  0.00  0.13  0.24   
新希望   0.00  0.00  0.04  0.00  0.00  0.00  0.00  0.00  0.04  0.00  0.13  0.32   
宁德时代  0.09  0.07  0.00  0.09  0.02  0.01  0.02  0.00  0.01  0.00 -0.00  0.01   
隆基绿能  0.08  0.02  0.00  0.06  0.00  0.00  0.05  0.00  0.00  0.00 -0.00  0.00   
三一重工  0.09  0.08  0.03  0.01  0.06  0.00  0.06  0.00  0.07  0.00  0.04  0.03   
美的集团  0.05  0.05  0.11  0.00  0.00  0.09  0.01  0.02  0.20  0.04  0.02  0.03   

      温氏股份   新希望  宁德时代  隆基绿能  三一重工  美的集团  
海康威视 -0.00  0.00  0.09  0.08  0.09  0.05  
立讯精密  0.00  0.00  0.07  0.02  0.08  0.05  
恒瑞医药  0.00  0.04  0.00  0.00  0.03  0.11  
片仔癀  -0.00  0.00  0.09  0.06  0.01  0.00  
云南白药  0.00  0.00  0.02  0.00  0.06  0.00  
贵州茅台 -0.00  0.00  0.01  0.00  0.00  0.09  
五粮液  -0.00  0.00  0.02  0.05  0.06  0.01  
泸州老窖 -0.00  0.00  0.00  0.00  0.00  0.02  
伊利股份  0.00  0.04  0.01  0.00  0.07  0.20  
海天味业  0.00  0.00  0.00  0.00  0.00  0.04  
双汇发展  0.13  0.13 -0.00 -0.00  0.04  0.02  
牧原股份  0.24  0.32  0.01  0.00  0.03  0.03  
温氏股份  1.00  0.41 -0.00 -0.00  0.00  0.00  
新希望   0.41  1.00  0.00 -0.00  0.04  0.00  
宁德时代 -0.00  0.00  1.00  0.17  0.05  0.00  
隆基绿能 -0.00 -0.00  0.17  1.00  0.04  0.00  
三一重工  0.00  0.04  0.05  0.04  1.00  0.25  
美的集团  0.00  0.00  0.00  0.00  0.25  1.00  

📊 边的颜色解读与市场特征

观察结果:即使选取了跨行业的股票,网络中几乎全部是红色边(正偏相关)

为什么 A 股市场绿色边少见?

这反映了中国股票市场的重要特征:整体联动性强

  1. 市场因子主导:A 股受政策、资金流动、情绪等整体因素影响较大
  2. 行业轮动而非对冲:不同行业往往是”轮流上涨”,而非”此涨彼跌”
  3. 缺乏真正的对冲资产:A 股股票之间很难形成稳定的负相关

何时会出现绿色边?

  • 股票 vs 债券股票 vs 黄金 ETF
  • 融券/反向指数 ETF
  • 国际市场中,成长股 vs 价值股 有时呈负相关

边颜色的要点

边颜色 含义 投资启示
红色(正) 同涨同跌 不能用于分散风险
绿色(负) 反向波动 潜在的对冲机会

A 股全是红边说明:中国股市难以通过”选股”完全规避系统性风险

结果解读与金融应用

边的经济学含义

通过 Graphical Lasso 模型,网络图具有明确的金融含义。

边的颜色解读

边类型 含义 经济学解释
红色边 正偏相关 同行业、供应链或政策驱动
绿色边 负偏相关 可能存在对冲关系
无边 条件独立 仅通过中心节点间接相关

稀疏性的意义

大多数股票之间没有连边,验证了我们的假设:

  • 大多数股票相关性是间接产生
  • 通过少数几个中心节点(Hubs)或共同市场因素传导

方法论比较

与传统方法的对比

分析方法 衡量内容 优缺点
皮尔逊相关 边际相关 简单但受混杂影响
偏相关(无正则化) 条件相关 高维不稳定
Graphical Lasso 稀疏条件相关 高维稳健、可解释
滑动窗口 Glasso 时变稀疏条件相关 捕捉动态变化

与其他网络构建方法的对比

方法 核心思想 优缺点
相关性网络 阈值化相关矩阵 简单但阈值选择任意
最小生成树 (MST) 保留最强连接 结构唯一但丢失信息
GGM (本方法) 条件依赖建模 理论基础强
格兰杰因果网络 时序因果关系 有方向性

方法论优劣分析

优势 (Advantages):

  1. 去伪存真:相比于传统的皮尔逊相关系数(Pearson Correlation),偏相关系数能剔除“混杂变量”的影响,揭示更本质的直接联系。
  2. 处理高维数据:在股票数量接近或超过观测天数时(Small \(N\), Large \(P\)),Graphical Lasso 依然稳健,而传统的协方差逆矩阵估计会失效。
  3. 网络拓扑分析:生成的图结构使得我们可以利用复杂网络理论(Complex Networks)的工具(如中心度、聚类系数)来分析系统性风险。

方法论优劣分析

局限性 (Limitations):

  1. 正态性假设:GGM 假设收益率服从多元正态分布。然而,真实金融数据往往具有“尖峰厚尾”特性(Fat Tails),可能导致模型偏差。
    • 改进方向:使用 Nonparanormal 变换或 Copula Graphical Models。
  2. 静态假设:这里我们假设在观测窗口(如一年)内网络结构是不变的。实际上,金融市场结构随时间剧烈演变(Structural Breaks)。
    • 改进方向:使用 Time-varying Graphical Lasso 或滑动窗口分析。

典型应用场景

  1. 投资组合分散化 (Portfolio Diversification)
    • 避免同时持有在图中直接相连的股票,因为它们具有无法分散的特质风险。
    • 寻找图中的“孤立点”或属于不同社团(Community)的股票构建组合。
  2. 系统性风险监控 (Systemic Risk)
    • 监控网络密度的变化。如果网络突然变得稠密,或者出现超级中心节点(Super Hubs),往往预示着市场脆弱性增加。
  3. 配对交易 (Pairs Trading)
    • 基于偏相关系数寻找配对,可能比基于简单的协整或相关性更稳健,因为它排除了第三方的干扰。

案例验证:数据准备与边际相关

在本讲座开篇,我们提出了一个问题:招商银行与中国平安之间的高相关性是”真实的直接联系”还是”通过平安银行的间接联系”?

现在,让我们用实际数据来验证这个假设:

Code
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.covariance import GraphicalLassoCV
from sklearn.preprocessing import StandardScaler



# 获取三只股票的数据
# 招商银行: 600036.SH, 平安银行: 000001.SZ, 中国平安: 601318.SH
three_stocks = {
    '招商银行': '600036.SH',
    '平安银行': '000001.SZ',
    '中国平安': '601318.SH'
}

# 获取数据
data_3stocks = {}
for name, code in three_stocks.items():
    try:
        df = pro.daily(ts_code=code, start_date='20210101', end_date='20231231')  # 3年数据
        df = df.set_index('trade_date').sort_index()
        data_3stocks[name] = df['close']
    except Exception as e:
        print(f"Error fetching {name}: {e}")

# 合并数据
prices_3 = pd.DataFrame(data_3stocks)
prices_3.index = pd.to_datetime(prices_3.index)

# 计算对数收益率
returns_3 = np.log(prices_3 / prices_3.shift(1)).dropna()

# 标准化
scaler_3 = StandardScaler()
X_3 = scaler_3.fit_transform(returns_3)

# ====== 1. 计算边际相关系数(皮尔逊相关) ======
corr_matrix = returns_3.corr()

print("=" * 60)
print("【边际相关系数矩阵(皮尔逊相关)】")
print("=" * 60)
print(corr_matrix.round(3))
============================================================
【边际相关系数矩阵(皮尔逊相关)】
============================================================
       招商银行   平安银行   中国平安
招商银行  1.000  0.783  0.675
平安银行  0.783  1.000  0.660
中国平安  0.675  0.660  1.000

案例验证:条件相关(精度矩阵)

Code
# ====== 2. 计算条件相关(偏相关系数) ======
# 使用精度矩阵计算
cov_matrix = returns_3.cov().values
precision_3 = np.linalg.inv(cov_matrix)

# 计算偏相关系数
d_3 = np.sqrt(np.diag(precision_3))
partial_corr_3 = -precision_3 / np.outer(d_3, d_3)
np.fill_diagonal(partial_corr_3, 1)

partial_corr_df = pd.DataFrame(partial_corr_3, 
                                index=returns_3.columns, 
                                columns=returns_3.columns)

print("=" * 60)
print("【偏相关系数矩阵(条件相关)】")
print("=" * 60)
print(partial_corr_df.round(3))
============================================================
【偏相关系数矩阵(条件相关)】
============================================================
       招商银行   平安银行   中国平安
招商银行  1.000  0.609  0.337
平安银行  0.609  1.000  0.287
中国平安  0.337  0.287  1.000

案例验证:条件相关(Graphical Lasso)

Code
# ====== 3. 使用 Graphical Lasso 验证 ======
model_3 = GraphicalLassoCV(cv=5)
model_3.fit(X_3)
precision_glasso = model_3.precision_

d_glasso = np.sqrt(np.diag(precision_glasso))
partial_corr_glasso = -precision_glasso / np.outer(d_glasso, d_glasso)
np.fill_diagonal(partial_corr_glasso, 1)

partial_corr_glasso_df = pd.DataFrame(partial_corr_glasso, 
                                       index=returns_3.columns, 
                                       columns=returns_3.columns)

print("=" * 60)
print("【Graphical Lasso 偏相关系数矩阵】")
print(f"(最优正则化参数 α = {model_3.alpha_:.4f})")
print("=" * 60)
print(partial_corr_glasso_df.round(3))
============================================================
【Graphical Lasso 偏相关系数矩阵】
(最优正则化参数 α = 0.0488)
============================================================
       招商银行   平安银行   中国平安
招商银行  1.000  0.570  0.329
平安银行  0.570  1.000  0.287
中国平安  0.329  0.287  1.000

案例验证:结果可视化

Code
# ====== 4. 可视化对比 ======
# 使用 constrained_layout 自动调整布局,防止重叠
fig, axes = plt.subplots(1, 3, figsize=(15, 5), constrained_layout=True)

# 热力图函数
def plot_heatmap(ax, matrix, title, cmap='RdBu_r'):
    im = ax.imshow(matrix, cmap=cmap, vmin=-1, vmax=1)
    ax.set_xticks(range(len(matrix.columns)))
    ax.set_yticks(range(len(matrix.index)))
    ax.set_xticklabels(matrix.columns, rotation=45, ha='right', fontsize=10)
    ax.set_yticklabels(matrix.index, fontsize=10)
    ax.set_title(title, fontsize=12, fontweight='bold')
    
    # 添加数值标签
    for i in range(len(matrix.index)):
        for j in range(len(matrix.columns)):
            val = matrix.iloc[i, j]
            color = 'white' if abs(val) > 0.5 else 'black'
            ax.text(j, i, f'{val:.2f}', ha='center', va='center', 
                   fontsize=11, color=color, fontweight='bold')
    return im

plot_heatmap(axes[0], corr_matrix, '边际相关系数\n(皮尔逊相关)')
plot_heatmap(axes[1], partial_corr_df, '偏相关系数\n(精度矩阵)')
im = plot_heatmap(axes[2], partial_corr_glasso_df, '偏相关系数\n(Graphical Lasso)')

# 添加 colorbar
fig.colorbar(im, ax=axes, shrink=0.8, label='相关系数', location='right')

# plt.tight_layout() # constrained_layout 已启用,不需要 tight_layout
plt.show()

# ====== 5. 结论分析 ======
print("=" * 60)
print("【结论分析】")
print("=" * 60)

# 提取关键数值
marginal_zs_zp = corr_matrix.loc['招商银行', '中国平安']
partial_zs_zp = partial_corr_df.loc['招商银行', '中国平安']
glasso_zs_zp = partial_corr_glasso_df.loc['招商银行', '中国平安']

print(f"招商银行 与 中国平安:")
print(f"  - 边际相关系数:   {marginal_zs_zp:.3f}")
print(f"  - 偏相关系数:     {partial_zs_zp:.3f}")
print(f"  - Glasso偏相关:   {glasso_zs_zp:.3f}")
print()

if abs(partial_zs_zp) < 0.3 and abs(marginal_zs_zp) > 0.5:
    print("✓ 验证成功!招商银行与中国平安的高边际相关主要是间接关联,")
    print("  控制平安银行后,两者的条件相关性大幅下降。")
    verification_result = "consistent"
elif abs(partial_zs_zp) >= 0.3:
    print("⚠ 结果与预期不完全一致:招商银行与中国平安之间存在一定的直接联系,")
    print("  但偏相关系数仍低于边际相关系数,说明部分相关来自间接联系。")
    verification_result = "partial"
else:
    print("ℹ 边际相关本身不高,条件独立性分析意义有限。")
    verification_result = "low_marginal"
Figure 7: 三只股票的相关性与条件独立性分析
============================================================
【结论分析】
============================================================
招商银行 与 中国平安:
  - 边际相关系数:   0.675
  - 偏相关系数:     0.337
  - Glasso偏相关:   0.329

⚠ 结果与预期不完全一致:招商银行与中国平安之间存在一定的直接联系,
  但偏相关系数仍低于边际相关系数,说明部分相关来自间接联系。

🔍 案例分析结论:数据会说话

根据上述实际数据分析,我们观察到具体的数值变化:

  1. 边际相关高 (0.675):招商银行与中国平安的原始相关系数高达 0.675,表明它们在市场上表现出很强的同涨同跌特性。
  2. 偏相关降低 (0.337/0.329):当我们控制了其他变量(特别是平安银行)后,它们的直接相关性下降到了 0.33左右,降幅约为 50%

结论解读

  • 部分中介效应:相关系数的显著下降(从 0.68 降至 0.33),说明它们表面上的高相关性中,有一半左右是因为它们都与第三方(如平安银行或市场大盘)相关而产生的”间接联系”。
  • 仍有直接联系:偏相关系数 (0.33) 依然显著不为零,说明招商银行与中国平安之间确实存在直接的业务或情绪传导机制,而不仅仅是完全由外部因素驱动的虚假相关。
  • 符合预期但更复杂:结果表明现实比”非黑即白”(全真或全假)更复杂——它们既是”真朋友”(有直接联系),也是”朋友的朋友”(有间接联系)。

这正是高斯图模型的价值:它不只是告诉你”相关”,还能量化这其中有多少是”直接”的,有多少是”间接”的

总结与展望

核心要点回顾

本讲座介绍了概率图模型(PGM)在金融市场分析中的应用,重点聚焦于高斯图模型(GGM)

概念 核心内容
精度矩阵 \(\Theta\) 协方差矩阵的逆,编码条件依赖结构
条件独立性 \(\Theta_{ij} = 0 \Leftrightarrow X_i \perp X_j \mid X_{\text{rest}}\)
偏相关系数 \(\rho_{ij \mid \text{rest}} = -\Theta_{ij}/\sqrt{\Theta_{ii}\Theta_{jj}}\)
Graphical Lasso \(\ell_1\) 正则化精度矩阵估计,实现稀疏网络
模型选择 交叉验证、EBIC、稳定性选择

Tip

✅ 自我检测:你学会了吗?

完成本讲座后,你应该能够回答以下问题:

1. 概念理解

  • 边际相关和条件相关有什么区别?
    查看答案 边际相关衡量两变量之间的总体关联(不考虑其他变量),对应协方差矩阵;条件相关衡量控制其他变量后的直接关联,对应精度矩阵。例如:招商银行与中国平安的边际相关高,但条件相关可能很低(见 Section 8)。
  • 为什么精度矩阵的非对角元素为零意味着条件独立?
    查看答案 对于多元正态分布,条件协方差 \(\text{Cov}(X_i, X_j \mid X_{\text{rest}}) = -\Theta_{ij}/(\ldots)\)。当 \(\Theta_{ij}=0\) 时,条件协方差为零;对于正态分布,协方差为零等价于独立(见 Section 2)。
  • Lasso 正则化为什么能产生稀疏解?
    查看答案 L1 约束区域是菱形,其”尖角”位于坐标轴上。目标函数等高线与菱形的切点倾向于落在尖角处,使某些参数精确为零。可参考软阈值函数:当信号弱于 \(\lambda\) 时,直接压缩为零。

2. 方法应用

  • 如何用 Python 计算偏相关系数矩阵?
    查看答案 公式:partial_corr = -precision / np.outer(np.sqrt(np.diag(precision)), np.sqrt(np.diag(precision))),其中 precision = np.linalg.inv(cov_matrix) 或使用 GraphicalLassoCV 估计。
  • 正则化参数 \(\lambda\) 如何影响网络结构?
    查看答案 \(\lambda\) 越大 → 惩罚越强 → 精度矩阵越稀疏 → 网络边越少;\(\lambda\) 越小 → 网络越稠密。
  • 交叉验证和 EBIC 各有什么优缺点?
    查看答案 交叉验证:直接优化预测性能,但计算量大且可能选择过于稠密的模型。EBIC:有理论保证,偏向稀疏模型,计算更快,但需选择超参数 \(\gamma\)

3. 金融解读

  • 网络中的红色边和绿色边分别代表什么?
    查看答案 红色边(正偏相关):两股票即使排除其他因素仍同涨同跌,通常是同行业或供应链关系。绿色边(负偏相关):反向波动,可能是对冲机会(A股市场较少见)。
  • 如何利用 GGM 网络进行投资组合分散化?
    查看答案 避免同时持有直接相连的股票(无法分散风险);选择图中不同社团或孤立节点的股票构建组合。
  • GGM 方法的主要局限性是什么?
    查看答案
    1. 假设正态分布,但金融数据常有厚尾;(2) 假设网络结构静态,但市场结构随时间变化;(3) 只能捕捉线性条件依赖。

未来研究方向

  1. 动态图模型:捕捉网络结构的时变特性(Time-varying GGM)。
  2. 非参数/半参数方法:放松正态性假设(Nonparanormal, Copula GGM)。
  3. 因果发现:从 GGM 推断因果关系(PC 算法、LiNGAM)。
  4. 深度学习结合:图神经网络(GNN)与 GGM 的结合。
  5. 跨市场分析:构建多国股市的跨境金融网络。

学习路径建议

Note

🎯 下一步学习建议

如果你想进一步深入学习

阶段 建议内容
巩固基础 复习本讲座代码,自己下载数据运行一遍
理论深化 阅读 Hastie 等人的免费电子书 Chapter 7
实践拓展 选取不同行业的股票,比较网络结构差异
高级进阶 学习时变图模型或 Copula 方法

相关课程推荐

  • Stanford CS 228: Probabilistic Graphical Models(斯坦福公开课)
  • 《统计学习方法》- 李航(国内经典教材,有图模型章节)

参考文献

📚 基础文献

以下是理解本讲座内容的核心参考资料,按重要性排序:

  1. Friedman, J., Hastie, T., & Tibshirani, R. (2008). Sparse inverse covariance estimation with the graphical lasso. Biostatistics, 9(3), 432-441. DOI: 10.1093/biostatistics/kxm045
    • 本讲座的核心方法,论文简短(10页),算法讲解清晰
    • 建议阅读:Section 1-3(跳过证明细节)
  2. Hastie, T., Tibshirani, R., & Wightman, M. (2015). Statistical Learning with Sparsity: The Lasso and Generalizations. CRC Press. 免费PDF
    • 免费电子书,Chapter 7 专门讲 Graphical Lasso,写作通俗易懂
    • 建议阅读:Chapter 7(约30页)
  3. scikit-learn GraphicalLassoCV 文档: 官方文档
    • 实践指南,包含代码示例,适合动手实践

📖 进阶阅读(可选)

以下文献适合有兴趣深入研究的同学:

经典理论

  • Dempster, A. P. (1972). Covariance selection. Biometrics, 28(1), 157-175. DOI: 10.2307/2528966
    • GGM 的开创性工作,奠定了通过精度矩阵研究条件独立性的理论基础。
  • Lauritzen, S. L. (1996). Graphical Models. Oxford University Press. 链接
    • 图模型领域的经典教科书,适合系统学习理论。

金融网络应用

  • Tumminello, M., Lillo, F., & Mantegna, R. N. (2010). Correlation, hierarchies, and networks in financial markets. Journal of Economic Behavior & Organization, 75(1), 40-58. DOI: 10.1016/j.jebo.2010.01.004
    • 金融市场网络分析的综述,涵盖多种方法比较。
  • Billio, M., Getmansky, M., Lo, A. W., & Pelizzon, L. (2012). Econometric measures of connectedness and systemic risk. Journal of Financial Economics, 104(3), 535-559. DOI: 10.1016/j.jfineco.2011.12.010
    • 系统性风险与金融网络的经典论文。

最新综合参考

  • Maathuis, M. H., et al. (Eds.). (2018). Handbook of Graphical Models. CRC Press. DOI: 10.1201/9780429463976
    • 图模型领域的最新综合性参考书。

教材与专著

  • Koller, D., & Friedman, N. (2009). Probabilistic Graphical Models. MIT Press.
  • Hastie, T., Tibshirani, R., & Wightman, M. (2015). Statistical Learning with Sparsity. CRC Press. Free PDF
  • Maathuis, M. H., et al. (2018). Handbook of Graphical Models. CRC Press.

在线资源

  • Stanford CS 228 - Probabilistic Graphical Models: Course Website
  • scikit-learn GraphicalLassoCV 文档: Link

其他相关文献

  • Mantegna, R. N. (1999). Hierarchical structure in financial markets. The European Physical Journal B, 11(1), 193-197. DOI: 10.1007/s100510050929
  • Tumminello, M., Aste, T., Di Matteo, T., & Mantegna, R. N. (2005). A tool for filtering information in complex systems. PNAS, 102(30), 10421-10426. DOI: 10.1073/pnas.0500298102