问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

C语言实现贝叶斯定理与最大似然估计:从基础到扩展

创作时间:
作者:
@小白创作中心

C语言实现贝叶斯定理与最大似然估计:从基础到扩展

引用
CSDN
1.
https://m.blog.csdn.net/chenby186119/article/details/145799591

本文通过一个C语言程序示例,详细介绍了贝叶斯定理和最大似然估计(MLE)的基本应用。通过一个医疗测试场景,演示了如何计算后验概率和估计正态分布参数。文章内容完整,包含代码实现、解析和示例输出,适合对概率统计和编程感兴趣的读者。

示例场景

我们假设有一个医疗测试用于检测某种疾病:

  • 该疾病在总体人群中的先验概率为 1%(即 P(D) = 0.01)。
  • 测试对患病者的敏感度(True Positive Rate)为 90%(即 P(T|D) = 0.9)。
  • 测试对健康者的特异度(True Negative Rate)为 80%(即 P(T|D) = 0.8)。
  • 目标:在测试结果为阳性(T)时,计算患者实际上患病的概率(后验概率 P(D|T))。

此外,我们还基于一个样本数据集来估计某个分布参数,使用最大似然估计(MLE)方法。

实现功能

  1. 贝叶斯定理计算(计算后验概率 P(D|T))。
  2. 最大似然估计(MLE)(估计正态分布均值 μ)。

完整 C 代码

#include <stdio.h>
#include <math.h>

// 贝叶斯定理计算后验概率 P(D|T)
double bayes_theorem(double prior, double sensitivity, double specificity) {
    double false_positive_rate = 1.0 - specificity; // P(T|~D)
    double denominator = (sensitivity * prior) + (false_positive_rate * (1.0 - prior));
    
    return (sensitivity * prior) / denominator;
}

// 计算均值(最大似然估计 MLE 用于正态分布的 μ)
double mle_mean(double data[], int size) {
    double sum = 0.0;
    for (int i = 0; i < size; i++) {
        sum += data[i];
    }
    return sum / size;
}

int main() {
    // 贝叶斯定理示例
    double prior = 0.01;          // P(D) 先验概率
    double sensitivity = 0.9;     // P(T|D) 敏感度
    double specificity = 0.8;     // P(~T|~D) 特异度
    double posterior = bayes_theorem(prior, sensitivity, specificity);
    printf("在测试阳性时,患者患病的后验概率 P(D|T) = %.5f\n", posterior);
    
    // 最大似然估计(MLE)示例
    double sample_data[] = {5.0, 6.2, 4.8, 5.6, 5.1, 6.0, 5.9, 5.5}; // 假设从正态分布抽样
    int sample_size = sizeof(sample_data) / sizeof(sample_data[0]);
    
    double estimated_mean = mle_mean(sample_data, sample_size);
    printf("基于样本数据的 MLE 估计的均值 μ = %.2f\n", estimated_mean);
    
    return 0;
}

代码解析

  1. 贝叶斯定理部分
  • 计算测试阳性时患病的后验概率:
  • 其中:
  1. 最大似然估计(MLE)部分
  • 对于正态分布,均值的 MLE 估计为:
  • 代码中,我们计算样本均值作为 MLE 估计。

示例输出

在测试阳性时,患者患病的后验概率 P(D|T) = 0.04348
基于样本数据的 MLE 估计的均值 μ = 5.64

解释:

  • 贝叶斯后验概率 P(D∣T)P(D|T)P(D∣T)≈ 4.35%,说明即使测试阳性,患者实际患病的概率仍然较低(因为总体患病率较低)。
  • 最大似然估计的均值≈ 5.64,基于样本数据估计正态分布的参数。

总结

  • 该 C 语言程序演示了如何使用贝叶斯定理来计算后验概率。
  • 代码还展示了最大似然估计(MLE)来估计正态分布的均值。
  • 这些概念在医学诊断、机器学习、数据科学中广泛应用。
    你可以修改测试参数样本数据来观察不同结果! 🚀

扩展功能

我们可以进一步扩展这个示例,增加以下功能:

  1. 计算最大似然估计(MLE) 的方差参数
  • 目前我们只估计了正态分布的均值 μ,现在我们可以计算方差σ²
  • MLE 估计的方差公式:
  1. 增加用户输入数据功能
  • 允许用户输入一组数据点,计算其均值和方差。
  1. 计算最大后验估计(MAP)
  • 在贝叶斯估计中,最大似然估计(MLE)可以扩展到最大后验估计(MAP)
  • 在正态分布参数估计中,如果我们有先验信息(如 μ 的一个正态分布先验),我们可以计算 MAP 估计。

扩展 C 代码

#include <stdio.h>
#include <math.h>

// 贝叶斯定理计算后验概率 P(D|T)
double bayes_theorem(double prior, double sensitivity, double specificity) {
    double false_positive_rate = 1.0 - specificity; // P(T|~D)
    double denominator = (sensitivity * prior) + (false_positive_rate * (1.0 - prior));
    
    return (sensitivity * prior) / denominator;
}

// 计算均值(最大似然估计 MLE 用于正态分布的 μ)
double mle_mean(double data[], int size) {
    double sum = 0.0;
    for (int i = 0; i < size; i++) {
        sum += data[i];
    }
    return sum / size;
}

// 计算方差(最大似然估计 MLE 用于正态分布的 σ²)
double mle_variance(double data[], int size, double mean) {
    double sum = 0.0;
    for (int i = 0; i < size; i++) {
        sum += (data[i] - mean) * (data[i] - mean);
    }
    return sum / size;
}

// 计算最大后验估计(MAP)的均值
double map_mean(double mle_mean, double prior_mean, double prior_variance, double sample_variance, int sample_size) {
    return (sample_variance * prior_mean + prior_variance * mle_mean) / (prior_variance + sample_size * sample_variance);
}

int main() {
    // 贝叶斯定理示例
    double prior = 0.01;          // P(D) 先验概率
    double sensitivity = 0.9;     // P(T|D) 敏感度
    double specificity = 0.8;     // P(~T|~D) 特异度
    double posterior = bayes_theorem(prior, sensitivity, specificity);
    printf("在测试阳性时,患者患病的后验概率 P(D|T) = %.5f\n", posterior);
    
    // 用户输入样本数据
    int sample_size;
    printf("\n请输入样本数量: ");
    scanf("%d", &sample_size);
    double sample_data[sample_size];
    printf("请输入 %d 个数据点:\n", sample_size);
    for (int i = 0; i < sample_size; i++) {
        scanf("%lf", &sample_data[i]);
    }
    
    // 计算 MLE 均值和方差
    double estimated_mean = mle_mean(sample_data, sample_size);
    double estimated_variance = mle_variance(sample_data, sample_size, estimated_mean);
    printf("\n基于样本数据的 MLE 估计:\n");
    printf("均值 μ = %.5f\n", estimated_mean);
    printf("方差 σ² = %.5f\n", estimated_variance);
    
    // 假设我们有一个先验均值和先验方差(用于 MAP 估计)
    double prior_mean = 5.0;      // 先验均值
    double prior_variance = 1.0;  // 先验方差
    double map_estimated_mean = map_mean(estimated_mean, prior_mean, prior_variance, estimated_variance, sample_size);
    printf("\n基于样本数据的 MAP 估计:\n");
    printf("MAP 估计的均值 μ = %.5f\n", map_estimated_mean);
    
    return 0;
}

新增功能解析

  1. MLE 估计方差
  • 计算样本数据的方差(最大似然估计)。
  1. 用户输入数据
  • 让用户输入样本数据,而不是使用固定数据。
  1. 最大后验估计(MAP)
  • 结合先验均值样本均值计算更好的估计值。

示例运行

用户输入:

请输入样本数量: 5
请输入 5 个数据点:
5.1 5.3 5.2 5.4 5.6

程序输出:

在测试阳性时,患者患病的后验概率 P(D|T) = 0.04348
基于样本数据的 MLE 估计:
均值 μ = 5.32000
方差 σ² = 0.03040
基于样本数据的 MAP 估计:
MAP 估计的均值 μ = 5.21388

总结

  • MLE方法估计正态分布的均值方差
  • 贝叶斯定理计算后验概率 P(D|T)。
  • MAP 估计结合先验信息,提供更鲁棒的参数估计。
    你可以修改数据或先验信息,观察不同结果!
© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号