跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
C++AI算法

C++ 实现 Wishart 分布样本矩阵生成

在 C++ 中从零实现 Wishart 分布随机矩阵生成的方法。基于 Bartlett 分解,通过 Cholesky 分解尺度矩阵 Sigma 和构造包含标准正态及卡方分布元素的矩阵 A,最终计算 W = B * B^T 得到样本。代码不依赖 BLAS/LAPACK,数值稳定且注释完整,适用于多元统计、贝叶斯建模等场景。

AiEngineer发布于 2026/3/30更新于 2026/5/2434 浏览

一、项目背景详细介绍

在多元统计分析、随机矩阵理论、贝叶斯统计、机器学习以及信号处理等领域中,Wishart 分布(Wishart Distribution) 是一个极其重要的矩阵值概率分布。

它可以被看作是:

多元正态分布样本协方差矩阵的分布

换句话说:

  • 正态分布 → 标量随机变量
  • 多元正态分布 → 随机向量
  • Wishart 分布 → 随机矩阵

1.1 Wishart 分布的应用场景

Wishart 分布广泛应用于:

  • 多元统计中的协方差矩阵建模
  • 贝叶斯统计中协方差的共轭先验
  • 高斯混合模型(GMM)的贝叶斯版本
  • 随机矩阵理论
  • 金融风险建模(协方差估计)

📌 在工程和科研中,能够正确、高效地从 Wishart 分布采样是很多高级算法的基础模块。


1.3 为什么要自己实现 Wishart 采样?

尽管很多统计库提供现成函数,但手写 Wishart 采样具有重要价值:

  1. 深刻理解随机矩阵生成机制
  2. 为贝叶斯模型(如逆 Wishart)打基础
  3. 便于嵌入不依赖第三方库的 C++ 工程
  4. 可定制数值精度与性能

二、项目需求详细介绍


2.1 功能性需求

本项目目标是:

👉 使用 C++ 从零实现 Wishart 分布随机矩阵生成

核心功能包括:


2.2 输入与输出
  • 输入
    • 自由度 n
    • 尺度矩阵 Sigma (p × p)
  • 输出
    • Wishart 随机矩阵 W (p × p)

2.3 非功能性需求
  1. 不依赖 BLAS / LAPACK
  2. 数值稳定、结构清晰
  3. 教学友好、注释完整
  4. 可直接作为研究代码使用

三、相关技术详细介绍


3.1 Wishart 采样的核心思想

Wishart 分布的采样可转化为两个关键步骤:

  1. 生成标准正态矩阵
  2. 通过线性变换引入协方差结构

3.3 所需随机变量
  • 标准正态分布
  • 卡方分布

卡方分布可以通过对标准正态分布变量的平方求和来生成。


四、实现思路详细介绍


4.1 总体流程设计

1. 对 Sigma 进行 Cholesky 分解 2. 构造 Bartlett 矩阵 A 3. 计算 B = L * A 4. 返回 W = B * B^T


4.2 数值稳定性设计
  1. 假设输入 Sigma 为对称正定
  2. Cholesky 分解只使用下三角
  3. 使用 double 精度
  4. 明确矩阵乘法顺序减少误差

4.3 数据结构选择
  • 矩阵:std::vector<std::vector<double>>
  • 随机数:std::mt19937

五、完整实现代码

/******************************************************
 * File: wishart.h
 ******************************************************/
#ifndef WISHART_H
#define WISHART_H
#include <vector>

/* 从 Wishart 分布生成样本矩阵 */
class WishartSampler {
public:
    WishartSampler(int dim, int df);
    std::vector<std::vector<double>> sample(const std::vector<std::vector<double>>& sigma);
private:
    int p; // 维度
    int n; // 自由度
    std::vector<std::vector<double>> choleskyDecomposition(
        const std::vector<std::vector<double>>& A);
    std::vector<std::vector<double>> multiply(
        const std::vector<std::vector<double>>& A,
        const std::vector<std::vector<double>>& B);
    std::vector<std::vector<double>> transpose(const std::vector<std::vector<double>>& A);
};
#endif

/******************************************************
 * File: wishart.cpp
 ******************************************************/
#include "wishart.h"
#include <cmath>
#include <random>
#include <stdexcept>

/* 构造函数 */
WishartSampler::WishartSampler(int dim, int df) : p(dim), n(df) {
    if (n < p) throw std::invalid_argument("df must be >= dimension");
}

/* Cholesky 分解(下三角) */
std::vector<std::vector<double>> WishartSampler::choleskyDecomposition(
    const std::vector<std::vector<double>>& A) {
    std::vector<std::vector<double>> L(p, std::vector<double>(p, 0.0));
    for (int i = 0; i < p; ++i) {
        for (int j = 0; j <= i; ++j) {
            double sum = 0.0;
            for (int k = 0; k < j; ++k)
                sum += L[i][k] * L[j][k];
            if (i == j)
                L[i][j] = std::sqrt(A[i][i] - sum);
            else
                L[i][j] = (A[i][j] - sum) / L[j][j];
        }
    }
    return L;
}

/* 矩阵乘法 */
std::vector<std::vector<double>> WishartSampler::multiply(
    const std::vector<std::vector<double>>& A,
    const std::vector<std::vector<double>>& B) {
    std::vector<std::vector<double>> C(p, std::vector<double>(p, 0.0));
    for (int i = 0; i < p; ++i)
        for (int j = 0; j < p; ++j)
            for (int k = 0; k < p; ++k)
                C[i][j] += A[i][k] * B[k][j];
    return C;
}

/* 转置 */
std::vector<std::vector<double>> WishartSampler::transpose(
    const std::vector<std::vector<double>>& A) {
    std::vector<std::vector<double>> T(p, std::vector<double>(p));
    for (int i = 0; i < p; ++i)
        for (int j = 0; j < p; ++j)
            T[j][i] = A[i][j];
    return T;
}

/* Wishart 采样 */
std::vector<std::vector<double>> WishartSampler::sample(
    const std::vector<std::vector<double>>& sigma) {
    std::mt19937 gen(std::random_device{}());
    std::normal_distribution<> normal(0.0, 1.0);

    /* Step 1: Cholesky 分解 */
    auto L = choleskyDecomposition(sigma);

    /* Step 2: 构造 Bartlett 矩阵 A */
    std::vector<std::vector<double>> A(p, std::vector<double>(p, 0.0));
    for (int i = 0; i < p; ++i) {
        double chi2 = 0.0;
        for (int k = 0; k < n - i; ++k) {
            double z = normal(gen);
            chi2 += z * z;
        }
        A[i][i] = std::sqrt(chi2);
        for (int j = 0; j < i; ++j)
            A[i][j] = normal(gen);
    }

    /* Step 3: B = L * A */
    auto B = multiply(L, A);

    /* Step 4: W = B * B^T */
    auto BT = transpose(B);
    return multiply(B, BT);
}

/******************************************************
 * File: main.cpp
 ******************************************************/
#include <iostream>
#include "wishart.h"

int main() {
    int p = 3;
    int df = 6;
    std::vector<std::vector<double>> sigma = {
        {1.0, 0.5, 0.2},
        {0.5, 1.0, 0.3},
        {0.2, 0.3, 1.0}
    };

    WishartSampler sampler(p, df);
    auto W = sampler.sample(sigma);

    std::cout << "Wishart sample matrix:\n";
    for (const auto& row : W) {
        for (double v : row)
            std::cout << v << " ";
        std::cout << "\n";
    }
    return 0;
}

六、代码详细解读(仅解读方法作用)


6.1 sample
  • 核心 Wishart 采样流程
  • 实现 Bartlett 分解
  • 返回对称正定矩阵

6.2 choleskyDecomposition
  • 将尺度矩阵分解为下三角矩阵
  • 引入协方差结构

6.3 Bartlett 矩阵构造
  • 对角线使用卡方分布
  • 下三角使用标准正态分布

七、项目详细总结

通过本项目,我们:

  1. 系统理解了 Wishart 分布的定义与意义
  2. 掌握了 Bartlett 分解的工程实现
  3. 学会了随机矩阵的数值生成方法
  4. 为贝叶斯协方差建模打下基础

该实现:

  • 完全独立
  • 数值稳定
  • 教学清晰
  • 可直接用于科研

八、项目常见问题及解答


Q1:为什么要求 df ≥ p?

A:这是 Wishart 分布存在的必要条件。


Q2:是否保证输出正定?

A:是的,Bartlett 分解理论上保证正定。


Q3:如何生成逆 Wishart 分布?

A:对 Wishart 矩阵取逆即可。


九、扩展方向与性能优化


  1. 实现逆 Wishart 分布
  2. 使用 Kahan 求和提高数值稳定性
  3. 使用 SIMD 加速矩阵乘法
  4. 扩展到稀疏 Wishart
  5. 集成到贝叶斯 GMM

目录

  1. 一、项目背景详细介绍
  2. 1.1 Wishart 分布的应用场景
  3. 1.3 为什么要自己实现 Wishart 采样?
  4. 二、项目需求详细介绍
  5. 2.1 功能性需求
  6. 2.2 输入与输出
  7. 2.3 非功能性需求
  8. 三、相关技术详细介绍
  9. 3.1 Wishart 采样的核心思想
  10. 3.3 所需随机变量
  11. 四、实现思路详细介绍
  12. 4.1 总体流程设计
  13. 4.2 数值稳定性设计
  14. 4.3 数据结构选择
  15. 五、完整实现代码
  16. 六、代码详细解读(仅解读方法作用)
  17. 6.1 sample
  18. 6.2 choleskyDecomposition
  19. 6.3 Bartlett 矩阵构造
  20. 七、项目详细总结
  21. 八、项目常见问题及解答
  22. Q1:为什么要求 df ≥ p?
  23. Q2:是否保证输出正定?
  24. Q3:如何生成逆 Wishart 分布?
  25. 九、扩展方向与性能优化
  • 💰 8折买阿里云服务器限时8折了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • 基于 YOLOv8-v12 与 SpringBoot 的小麦叶片病害检测系统
  • Python 中 argv 与 raw_input() 的区别详解
  • 基于 YOLOv8-v12 与 SpringBoot 的小麦叶片病害智能检测系统
  • LLaMA-Factory 大模型微调实战指南
  • 2026 年 3 月 13 日 AI 行业动态:TADA 开源与多模型更新
  • Google AI Studio 区域限制与年龄验证解决方法及 Three.js 简介
  • 二叉搜索树详解:原理、实现与 TreeMap 应用
  • AI 智能体 Coze 知识库:从入门到实战
  • 本地部署 Qwen 与 ComfyUI 制作 AI 漫剧教程
  • Flutter 三方库 arcade 的鸿蒙化适配指南
  • Rust 语言发展历史与核心特性解析
  • 全球主流 AI 大模型智能、速度与价格维度排名解析
  • 基于 Web 的宠物领养管理系统设计与实现
  • Windows 系统彻底卸载 OpenClaw、ClawHub 及飞书机器人配置指南
  • 昇腾 CANN 学习路径指南:Python、C++ 与算子开发选型
  • Stable Diffusion 各版本技术详解
  • 基于 Web 的宠物领养管理系统设计与实现
  • Stable Diffusion v1.5 图片生成:主图/Banner/邮件头图
  • Python 高效清理 Excel 空白行列:原理与实战
  • 智能家居插件管理工具技术指南:突破网络限制的本地化优化方案

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • RSA密钥对生成器

    生成新的随机RSA私钥和公钥pem证书。 在线工具,RSA密钥对生成器在线工具,online

  • Mermaid 预览与可视化编辑

    基于 Mermaid.js 实时预览流程图、时序图等图表,支持源码编辑与即时渲染。 在线工具,Mermaid 预览与可视化编辑在线工具,online

  • 随机西班牙地址生成器

    随机生成西班牙地址(支持马德里、加泰罗尼亚、安达卢西亚、瓦伦西亚筛选),支持数量快捷选择、显示全部与下载。 在线工具,随机西班牙地址生成器在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online