如何使用Python实现数据的多项分布最大似然估计
多项分布的极大似然估计是解析解,不需要做迭代优化,核心逻辑非常简单:每个类别的概率估计值 = 该类别的观测频数 / 全部样本的总频数,所有类别估计出的概率之和严格为1,完全符合概率定义。
针对给出的「类别-频数」汇总格式数据,直接按这个逻辑计算即可,下面给出两种Python实现方式。
示例数据
category number 100 1658 101 1801 102 1856 103 1804 104 1779 105 1765 106 1912 107 1976 108 2233 109 2512 110 3133
实现1:纯原生Python,无需安装第三方依赖
适合数据量不大、不想额外装库的场景:
# 录入类别-频数字典 freq_map = { 100: 1658, 101: 1801, 102: 1856, 103: 1804, 104: 1779, 105: 1765, 106: 1912, 107: 1976, 108: 2233, 109: 2512, 110: 3133 } # 计算总样本量 total_count = sum(freq_map.values()) # 计算每个类别的MLE概率 p_estimate = {cat: cnt / total_count for cat, cnt in freq_map.items()} # 输出结果 for cat, p in p_estimate.items(): print(f"类别{cat} 概率估计值: {round(p, 4)}") # 校验:概率和应为1 print(f"\n概率和校验值: {sum(p_estimate.values())}")
实现2:Pandas 实现,适合结构化文件读取场景
如果你的数据是存在csv、txt等结构化文件里,用pandas处理效率更高:
import pandas as pd from io import StringIO # 下面的字符串是模拟本地文件内容,实际使用时替换成pd.read_csv("你的文件路径", sep=r"\s+")即可 raw_data = """category number 100 1658 101 1801 102 1856 103 1804 104 1779 105 1765 106 1912 107 1976 108 2233 109 2512 110 3133 """ df = pd.read_csv(StringIO(raw_data), sep=r"\s+") # 计算总样本量,生成概率列 total = df["number"].sum() df["p_mle"] = df["number"] / total print(df)
补充说明
- 上述计算得到的估计值是多项分布极大似然估计的解析结果,是无偏估计,不需要额外调用统计库做拟合。
- 如果你手里的原始数据是每条样本对应一行、未做频数汇总的格式,只需要先对类别列做
value_counts()得到频数表,后续计算逻辑完全一致。 - 如果你需要加入先验信息做平滑(比如拉普拉斯平滑),那属于贝叶斯估计范畴,不是纯极大似然估计的结果。
内容的提问来源于stack exchange,提问作者bioTao
相关产品推荐
相关产品推荐

