You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于GPyTorch多元正态分布计算效应量类似物及分区问题

基于BoTorch SAASBO的MVN条件分布与特征重要性计算实现

核心理论基础(针对多元正态条件分布)

对于p维多元正态分布 $p(\boldsymbol{\beta}) = \mathcal{N}(\boldsymbol{\mu}, \boldsymbol{\Sigma})$,将变量划分为单个特征$\beta_j$和其余特征$\boldsymbol{\beta}_{-j}$后:

  • 条件期望:$E(\boldsymbol{\beta}{-j} | \beta_j) = \boldsymbol{\mu}{-j} + \boldsymbol{\Sigma}{j,-j}^T \Sigma{jj}^{-1} (\beta_j - \mu_j)$
  • 条件方差:$V(\boldsymbol{\beta}{-j} | \beta_j) = \boldsymbol{\Sigma}{-j,-j} - \boldsymbol{\Sigma}{j,-j}^T \Sigma{jj}^{-1} \boldsymbol{\Sigma}_{j,-j}$
  • 论文补充材料中的$\alpha_j$(对应$\beta_j$的KLD)可通过下三角矩阵的行列式高效计算,无需直接求逆协方差矩阵。

代码实现(基于PyTorch/GPyTorch)

假设你已通过SAASBO模型获取了后验MVN的属性:

model.eval()
posterior = model.posterior(X_test)
mvn = posterior.mvn
mu = mvn.mean.squeeze()  # 假设为[p]维度的均值向量
Sigma = mvn.covariance_matrix.squeeze()  # [p,p]协方差矩阵
Lambda = mvn.precision_matrix.squeeze()  # [p,p]精度矩阵
L = mvn.scale_tril.squeeze()  # [p,p]下三角缩放矩阵(Sigma = L @ L.T)

1. 矩阵分区工具函数

用于提取协方差/精度矩阵中与$\beta_j$相关的子矩阵:

import torch

def partition_matrix(mat, j):
    """
    划分p维方阵为与beta_j相关的子矩阵
    参数:
        mat: [p,p] 协方差/精度矩阵
        j: 目标特征索引(0-based)
    返回:
        mat_jj: [1,1] 单个元素的子矩阵
        mat_j_minusj: [1, p-1] beta_j与其余特征的交叉项
        mat_minusj_j: [p-1, 1] 转置交叉项
        mat_minusj_minusj: [p-1, p-1] 其余特征的子矩阵
    """
    p = mat.shape[0]
    mat_jj = mat[j, j].unsqueeze(0).unsqueeze(0)
    # 提取beta_j对应的行/列,排除自身
    idx_minusj = torch.cat([torch.arange(j), torch.arange(j+1, p)], dim=0)
    mat_j_minusj = mat[j, idx_minusj].unsqueeze(0)
    mat_minusj_j = mat_j_minusj.T
    mat_minusj_minusj = mat[idx_minusj][:, idx_minusj]
    return mat_jj, mat_j_minusj, mat_minusj_j, mat_minusj_minusj

2. 条件分布计算(协方差矩阵版)

def conditional_mvn_cov(Sigma, mu, j, beta_j):
    """
    基于协方差矩阵计算条件分布N(beta_{-j} | beta_j)的期望和方差
    参数:
        Sigma: [p,p] 协方差矩阵
        mu: [p] 均值向量
        j: 目标特征索引
        beta_j: 标量,beta_j的取值
    返回:
        cond_mu: [p-1] 条件期望
        cond_cov: [p-1, p-1] 条件方差
    """
    sigma_jj, sigma_j_minusj, sigma_minusj_j, sigma_minusj_minusj = partition_matrix(Sigma, j)
    mu_minusj = mu[torch.cat([torch.arange(j), torch.arange(j+1, p)], dim=0)]
    
    # 计算条件期望
    sigma_jj_inv = 1.0 / sigma_jj
    cond_mu = mu_minusj + (sigma_minusj_j @ sigma_jj_inv @ (beta_j - mu[j]).unsqueeze(0).T).squeeze(-1)
    # 计算条件方差
    cond_cov = sigma_minusj_minusj - sigma_minusj_j @ sigma_jj_inv @ sigma_j_minusj
    return cond_mu, cond_cov

3. 条件分布计算(精度矩阵版,更高效)

利用精度矩阵的稀疏性(SAASBO模型特性),避免协方差求逆:

def conditional_mvn_precision(Lambda, mu, j, beta_j):
    """
    基于精度矩阵计算条件分布N(beta_{-j} | beta_j)的期望和方差
    参数:
        Lambda: [p,p] 精度矩阵(Sigma^{-1})
        mu: [p] 均值向量
        j: 目标特征索引
        beta_j: 标量,beta_j的取值
    返回:
        cond_mu: [p-1] 条件期望
        cond_cov: [p-1, p-1] 条件方差
    """
    lambda_jj, lambda_j_minusj, lambda_minusj_j, lambda_minusj_minusj = partition_matrix(Lambda, j)
    mu_minusj = mu[torch.cat([torch.arange(j), torch.arange(j+1, p)], dim=0)]
    
    # 条件方差为Lambda_{-j,-j}的逆,用Cholesky分解求逆更稳定
    L_chol = torch.linalg.cholesky(lambda_minusj_minusj)
    cond_cov = torch.cholesky_inverse(L_chol)
    # 计算条件期望
    cond_mu = mu_minusj - (cond_cov @ lambda_minusj_j @ (beta_j - mu[j]).unsqueeze(0).T).squeeze(-1)
    return cond_mu, cond_cov

4. 计算$\alpha_j$(对应$\beta_j$的KLD)

利用下三角矩阵L的行列式特性(行列式为对角线元素乘积),高效计算:

def compute_alpha_j(L, j):
    """
    计算论文补充材料中的alpha_j,即beta_j对应的KLD值
    参数:
        L: [p,p] 下三角缩放矩阵(Sigma = L @ L.T)
        j: 目标特征索引
    返回:
        alpha_j: 标量,KLD值
    """
    p = L.shape[0]
    # 计算det(Sigma) = (prod(L.diag()))^2
    det_Sigma = (torch.prod(L.diag())) ** 2
    # 计算det(Sigma_{-j,-j})
    idx_minusj = torch.cat([torch.arange(j), torch.arange(j+1, p)], dim=0)
    L_minusj = L[idx_minusj][:, idx_minusj]
    det_Sigma_minusj = (torch.prod(L_minusj.diag())) ** 2
    # Sigma_jj = L[j,j]^2
    sigma_jj = L[j, j] ** 2
    # 计算alpha_j
    alpha_j = 0.5 * torch.log(det_Sigma / (det_Sigma_minusj * sigma_jj))
    return alpha_j.item()

批量计算所有特征的KLD

# 计算p=10个特征的KLD值
kld_values = [compute_alpha_j(L, j) for j in range(10)]
print("各特征的KLD值(alpha_j):", kld_values)

内容的提问来源于stack exchange,提问作者iammteah

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 11:54:55