qinghuan
← 回到知识探索

AI 直觉 / 动手实验

三个模型都没换,只把平均放到另一处,为什么答案反了?

同一组0.8、0.8、0.01,平均概率选类别1,平均logit却选类别0;算清两种融合规则在做什么。

展开本文目录
  1. 下载完整练习包
  2. 先动手看看
  3. 先平均概率,相当于直接平均三个答案分布
  4. 先平均logit,实际平均的是对数胜算
  5. 把公式展开,会得到归一化的几何平均
  6. 运行完整小例子,再与独立公式核对
  7. 哪些情况下会相同,哪些细节需要先说清?
  8. 记住这三点
  9. 别把例子用过头
  10. 自己试一小步
  11. 查原始资料
开始前,会这些就够了
遇到不熟悉的词,先看这 2 个解释
对数胜算
先比较发生与不发生的概率比例,再对这个比例取自然对数。
概率融合
把多个模型给出的类别概率,按预先约定的规则合成一份概率。
打开完整术语小抄 ↗

三个分类器对类别1分别给出0.8、0.8、0.01。直接平均,得到0.536667,超过一半;先把概率变成二分类logit,再平均并转回概率,却得到0.352627,低于一半。

这里没有换模型、样本或权重,只是换了融合规则。实验没有真实标签,因此只能证明两种规则会给出不同选择,不能据此宣布其中一种更准确。

把例子带到自己的电脑上

下载完整练习包

需要 Python 3.10 或更新版本,无第三方依赖;实测 Windows / Python 3.14.0,Python 3.10 仅做语法兼容检查。使用标准库,不需要安装第三方包。下载 ZIP 后选择“全部提取”,进入能看到 README.md 的文件夹。

下载 ZIP · 5 个文件
包里有什么
  • demo.py:完整可运行源码
  • README.md:运行步骤与练习
  • observed.stdout.txt:本次实际输出
  • verification.json:源码和运行验证记录
  • SHA256SUMS.txt:文件摘要

在这个文件夹打开 PowerShell,逐行运行

python --version
python -B demo.py

解压后,在含 demo.py 的目录打开终端。命令分别回车执行。代码只对给定概率计算两种融合方式,没有导入PyTorch或scikit-learn,没有训练分类器。18组数值用独立的几何平均表达式核对;另检查相同输入、决策边界与无效输入。

找不到命令或文件时,先按 README 检查环境和所在目录。文中标出的阅读时间只估算文章篇幅,安装环境和动手练习可按自己的节奏进行。

同三份预测,先平均概率还是先平均 logit?

正在准备实验控件…

先看反向投票的预设:两个输入各给类别1八成概率,第三个只给百分之一。两种融合会选出不同类别。

直接平均概率
0.536667
直接平均的选择
类别 1
平均logit后转回概率
0.352627
平均logit的选择
类别 0

三个二分类logit分别为 1.386294、1.386294、-4.595120,均值为 -0.607510。两种规则对应算术平均与归一化几何平均,衡量方式不同;这里没有真实标签,不能据此判断哪一种更准。

二分类、三个等权输入、类别顺序一致;每个数是类别1的概率。二分类logit指 log(p/(1−p)),等于两类原始logit之差。这里只计算两种融合公式,没有训练模型或调用PyTorch/scikit-learn。限制概率严格在0与1之间;不比较哪种规则总是更好。

先平均概率,相当于直接平均三个答案分布

把每个分类器的完整输出写出来:类别1概率是p,类别0概率是1−p。本例依次是[0.2,0.8]、[0.2,0.8]、[0.99,0.01],两列的类别顺序一致。

每列直接求平均,类别1得到(0.8+0.8+0.01)/3=0.536667,类别0得到0.463333。若用最大概率选类,就选类别1。scikit-learn 的 soft voting 文档描述的就是基于加权概率和进行选择;这里采用三个相等权重。

它可以解释成先等概率选择一个分类器,再按那个分类器的分布看结果时,最终得到的混合分布。这是对给定概率的数学解释,不是在说三个分类器真的被随机调用。

先平均logit,实际平均的是对数胜算

二分类logit写成z=ln(p/(1−p))。p=0.8对应ln4≈1.386294,p=0.01对应ln(1/99)≈−4.595120。三个logit的平均值约为−0.607510。

再用p=1/(1+exp(−z))转回概率,得到0.352627。第三个输入对类别1的强烈反对,在对数胜算坐标下与前两个输入的支持共同参与平均。

这里的z是二分类的logit差值。若模型输出两类原始分数z₀、z₁,softmax给出的对数胜算等于z₁−z₀;不是把任意一个类别的原始分数直接当作这个二分类z。

把公式展开,会得到归一化的几何平均

对M个输入,令a=(∏pₘ)^(1/M),b=(∏(1−pₘ))^(1/M)。平均对数胜算再转回概率,结果正好是a/(a+b)。它比较的是两类各自的几何平均,并且最后还要归一化。

更一般地,若各模型使用相同类别顺序,pₘ,c=softmax(zₘ)的第c项,那么softmax(平均zₘ)的第c项,正比于∏pₘ,c^(1/M)。每个模型softmax的归一化常数,对所有类别相同,在最后一步会抵消。这个等式由softmax定义直接推得。

因此“平均概率”和“平均logit”是两种不同的定义,通常不相等。前者是算术平均,后者是归一化几何平均。不要只看到两边都写着mean,就把它们当成可以交换顺序的同一步操作。

运行完整小例子,再与独立公式核对

代码只对给定概率计算两种融合方式,没有导入PyTorch或scikit-learn,没有训练分类器。18组数值用独立的几何平均表达式核对;另检查相同输入、决策边界与无效输入。

本轮实际使用 Windows / Python 3.14.0 运行。保存为 demo.py,执行 python demo.py;只用标准库。检查使用显式 AssertionError,python -O 不会删除这些检查。

展开收起代码 · 小实验python · 53 行

长行可在代码区域内左右滚动,按 Tab 可把焦点移入代码区。

小实验 · python
"""Two equal-weight pooling rules, using Python's standard library only."""
from math import exp, isclose, isfinite, log, log1p, prod


def require(condition, message):
    if not condition:
        raise AssertionError(message)


def pool(probabilities):
    if not isinstance(probabilities, (list, tuple)) or not 1 <= len(probabilities) <= 10:
        raise ValueError("need 1 to 10 probabilities")
    if any(type(p) not in (int, float) or not isfinite(p) or not 0 < p < 1
           for p in probabilities):
        raise ValueError("probabilities must be finite and strictly between 0 and 1")
    logits = [log(p) - log1p(-p) for p in probabilities]
    mean_probability = sum(probabilities) / len(probabilities)
    mean_logit = sum(logits) / len(logits)
    # Stable inverse logit, also for very negative finite inputs.
    logit_probability = (1 / (1 + exp(-mean_logit)) if mean_logit >= 0
                         else exp(mean_logit) / (1 + exp(mean_logit)))
    return mean_probability, logit_probability


def main():
    for values in ([0.8, 0.8, 0.01], [0.8, 0.8, 0.8], [0.8, 0.8, 0.1]):
        arithmetic, logarithmic = pool(values)
        print(f"p={values}; mean_probability={arithmetic:.6f}; mean_logit_then_sigmoid={logarithmic:.6f}")
    a, b = pool([0.8, 0.8, 0.01])
    print(f"opposite_decisions: probability_pool={int(a > 0.5)}; logit_pool={int(b > 0.5)}")
    count = 0
    for p in (0.001, 0.01, 0.1, 0.5, 0.8, 0.999):
        for q in (0.01, 0.2, 0.9):
            values = [p, p, q]
            yes = prod(values) ** (1 / 3)
            no = prod(1 - value for value in values) ** (1 / 3)
            require(isclose(pool(values)[1], yes / (yes + no), abs_tol=1e-12),
                    "normalized geometric mean oracle")
            count += 1
        require(isclose(pool([p, p, p])[1], p, abs_tol=1e-12), "identical models")
    require(isclose(pool([0.8, 0.8, 1 / 17])[1], 0.5, abs_tol=1e-12), "decision boundary")
    for bad in ([], [0], [1], [True], [float('nan')]):
        try:
            pool(bad)
        except ValueError:
            pass
        else:
            raise AssertionError("invalid input accepted")
    print(f"PASS: {count} geometric-mean checks, identical inputs, threshold and invalid inputs")


if __name__ == '__main__':
    main()

怎样运行:在独立练习文件夹中,依次执行下载区的命令。2026-10-26 使用 Python 3.10 或更新版本,无第三方依赖;实测 Windows / Python 3.14.0,Python 3.10 仅做语法兼容检查 复跑这份源码并核对完整输出。代码只对给定概率计算两种融合方式,没有导入PyTorch或scikit-learn,没有训练分类器。18组数值用独立的几何平均表达式核对;另检查相同输入、决策边界与无效输入。

运行后对照结果
p=[0.8, 0.8, 0.01]; mean_probability=0.536667; mean_logit_then_sigmoid=0.352627
p=[0.8, 0.8, 0.8]; mean_probability=0.800000; mean_logit_then_sigmoid=0.800000
p=[0.8, 0.8, 0.1]; mean_probability=0.566667; mean_logit_then_sigmoid=0.547801
opposite_decisions: probability_pool=1; logit_pool=0
PASS: 18 geometric-mean checks, identical inputs, threshold and invalid inputs

哪些情况下会相同,哪些细节需要先说清?

如果三个输入都给0.8,两条路径都得到0.8。相同是可以发生的,但一个相同例子不能证明两条规则处处等价。保持前两个0.8时,logit融合恰好在第三个概率为1/17时打平两类,可以作为单独的边界检查。

本页限制0<p<1,避免把无穷logit或互相冲突的零概率支持混入这个有限数值实验。互动控件进一步限制在0.001到0.999。没有对原始logit做额外温度缩放,也没有改变模型权重。

实际集成要说明类别是否对齐、概率是否校准、融合权重和温度如何选,并在独立验证数据上比较。这里不要求模型彼此独立,也没有用独立性假设证明某一种融合总是最优。站内关于平均预测熵与模型分歧的旧文研究另一问题:平均后的分布相同,成员之间的分歧仍可不同。

记住这三点

  • 非线性变换前后各做一次平均,通常得到不同结果。
  • 平均logit对应归一化几何平均,而不是概率的算术平均。
  • 先固定类别顺序、权重、温度与评价数据,再比较融合规则。

别把例子用过头

  • 把二分类对数胜算与单个原始类别logit混为一谈。
  • 看到两个支持票就认定任何概率融合都一定支持同一类。
  • 把一个反例改写成“平均概率永远更好”或“平均logit永远更好”。

自己试一小步

固定前两个输入,能否手算第三个输入让logit融合恰好打平的位置?

  1. 把前两个概率设成0.7,写出它们的胜算。
  2. 令三个胜算的乘积等于1,解出第三个概率。
  3. 先预测概率平均的方向,再用完整程序核对两条路径。

做到这些,就算完成

  • 先写清类别1和类别0的对应关系。
  • 说明是否用了等权与相同温度。
  • 只比较规则输出,不凭空添加准确率结论。

查原始资料

想确认一个细节,先看这份资料对应的部分,不必从头读完所有文档。