qinghuan
← 回到知识探索

AI 直觉 / 可下载小项目

按权重抽两个不同选项,入选概率还是原来的比例吗?

精确列出三个选项的六种顺序,拆开首次概率、条件概率、无序集合概率与最终入选概率。

展开本文目录
  1. 下载完整练习包
  2. 每一步的分母都在变
  3. 不关心顺序,就把所有对应顺序相加
  4. 入选概率要加上第一名和第二名的所有路径
  5. Gumbel-Top-k 的对应关系有明确条件
  6. 运行完整实验并检查报告
  7. 记住这些要点
  8. 别把例子用过头
  9. 自己试一小步
  10. 查原始资料
开始前,会这些就够了
遇到不熟悉的词,先看这 2 个解释
包含概率
一次选出一组候选后,某个候选至少出现一次的概率。
Plackett–Luce 顺序概率
每次按剩余权重选择一项,移除它后继续,整条顺序的概率是条件概率连乘。
打开完整术语小抄 ↗

三个候选的权重是 1、2、3,第一次选择概率是 1/6、2/6、3/6。现在要求选两个不同候选:第一次选中后移除,再按剩余权重抽第二次。候选 A 最终入选的概率不再是 1/6,也不是简单乘二得到的 1/3。

我们把全部六种顺序列出,用精确分数求和。这个小表能帮助你检查候选采样、排名模型及 Gumbel-Top-k 的概率含义。

把例子带到自己的电脑上

下载完整练习包

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

下载 ZIP · 5 个文件
包里有什么
  • plackett_luce.py:完整可运行示例
  • README.md:运行说明与独立练习
  • observed.stdout.txt:本次实际输出
  • verification.json:源码和产物验证记录
  • SHA256SUMS.txt:内容摘要

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

python --version
python -B plackett_luce.py

解压到独立练习文件夹,在含 plackett_luce.py 的目录打开终端运行。已运行 Fraction 六种有序结果精确枚举、无序集合合并、包含概率及权重整体缩放检查;未运行 TensorFlow、随机 Gumbel 采样或真实模型解码。

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

每一步的分母都在变

把三个选项叫 A、B、C,权重 w=[1,2,3],总和 W=6。Plackett–Luce 的顺序概率是每一步的“当前权重除以剩余权重和”连乘。权重只是正数,不必预先加起来为 1。

先 A 后 B:P(A,B)=(1/6)×(2/5)=1/15。先 B 后 A:P(B,A)=(2/6)×(1/4)=1/12。第二步的分母不同,所以交换顺序会改变概率。

一般地,对互不重复的顺序 i₁,…,iₖ,概率为 ∏ⱼ wᵢⱼ/(W−Σₗ<ⱼwᵢₗ)。iⱼ 是第 j 次选中的下标,分母删去此前所有选中项。本文要求全部权重严格为正,避免零权重支持集合的额外边界。

不关心顺序,就把所有对应顺序相加

只关心最后集合为 {A,B} 时,概率是 P(A,B)+P(B,A)=1/15+1/12=3/20=0.15。不能把 wAwB 除以所有两两权重乘积之和:那会得到 2/(2+3+6)=2/11≈0.181818,是另一种集合分布。

程序遍历六种有序结果,首先验证总概率为 1,再按无序集合合并。排序候选并不会把不同概率的顺序变成等概率;合并时应加概率而不是简单数次数。

入选概率要加上第一名和第二名的所有路径

A 入选有两类互斥路径:A 先被抽中,或 B/C 先被抽中再抽 A。相加得到 πA=1/6+(2/6)(1/4)+(3/6)(1/3)=5/12≈0.416667。

同样计算 πB=11/15≈0.733333,πC=17/20=0.85。三者之和为 2,因为每次恰好选两个不同项;这组值不是三选一的概率向量,没必要把它们强行归一化为和等于 1。

当一次选完全部三个选项时,每项最终入选概率都是 1,原权重只影响顺序。这也是最直接的反例:不放回选择 k 个时,最终包含概率通常不再与第一次权重成比例。

Gumbel-Top-k 的对应关系有明确条件

对每个 log wᵢ 加一个独立标准 Gumbel 噪声,再按结果取前 k 项,理论上得到上述有序不放回分布。这里取的是带噪声的对数权重;直接按原权重取最大 k 项则是确定性排序。

本文没有运行随机 Gumbel 采样,只有精确概率枚举。引用定理用于说明对应关系,代码验证的是小规模概率账本;它没有证明实际随机数实现或大模型采样器正确。

若用样本估计总量,要先确认公式需要首次选择概率、每一步条件概率,还是最终包含概率。把三者混用会破坏估计;不放回样本之间也不能直接按独立样本处理。

运行完整实验并检查报告

保存为 plackett_luce.py,运行 python -B plackett_luce.py。预期输出来自本次实际运行;完整结果写入 report.json。

已运行 Fraction 六种有序结果精确枚举、无序集合合并、包含概率及权重整体缩放检查;未运行 TensorFlow、随机 Gumbel 采样或真实模型解码。

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

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

小实验 · python
"""Exact Plackett-Luce probabilities for ordered draws without replacement."""
from fractions import Fraction as F
import itertools
import json
from pathlib import Path


def ordered_probability(weights,order):
    if not weights or not all(w>0 for w in weights):
        raise ValueError('strictly positive weights required')
    if len(order)>len(weights) or len(set(order))!=len(order):
        raise ValueError('distinct draws required')
    if any(type(i) is not int or not 0<=i<len(weights) for i in order):
        raise ValueError('unknown item')
    remaining=sum(weights); probability=F(1)
    for i in order:
        probability *= weights[i]/remaining
        remaining -= weights[i]
    return probability


def distribution(weights,k):
    if type(k) is not int or not 0<=k<=len(weights):
        raise ValueError('invalid sample size')
    return [(order,ordered_probability(weights,order))
            for order in itertools.permutations(range(len(weights)),k)]


def main():
    w=[F(1),F(2),F(3)]
    rows=distribution(w,2)
    assert sum(p for order,p in rows)==1
    first=[sum(p for order,p in rows if order[0]==i) for i in range(3)]
    inclusion=[sum(p for order,p in rows if i in order) for i in range(3)]
    assert first==[F(1,6),F(1,3),F(1,2)]
    assert inclusion==[F(5,12),F(11,15),F(17,20)] and sum(inclusion)==2
    subsets={}
    for order,p in rows:
        key=tuple(sorted(order)); subsets[key]=subsets.get(key,F(0))+p
    ab=ordered_probability(w,(0,1)); ba=ordered_probability(w,(1,0))
    assert ab==F(1,15) and ba==F(1,12) and subsets[(0,1)]==F(3,20)
    product_weighted=F(1*2,1*2+1*3+2*3)
    assert product_weighted!=subsets[(0,1)]
    assert distribution([10*x for x in w],2)==rows
    all_rows=distribution(w,3)
    assert [sum(p for order,p in all_rows if i in order) for i in range(3)]==[1,1,1]
    uniform=distribution([F(1)]*3,2)
    assert all(p==F(1,6) for order,p in uniform)
    rejected=0
    for weights,order in [([F(0),F(1)],(0,)),(w,(0,0)),(w,(3,))]:
        try: ordered_probability(weights,order)
        except ValueError: rejected+=1
    try: distribution(w,4)
    except ValueError: rejected+=1
    assert rejected==4
    report=dict(weights=list(map(str,w)),ordered=[dict(order=o,probability=str(p)) for o,p in rows],
        first_choice=list(map(str,first)),inclusion=list(map(str,inclusion)),
        subset_probabilities={str(k):str(v) for k,v in subsets.items()},
        product_weighted_ab=str(product_weighted),all_selected=[1,1,1],checks_passed=True)
    Path('report.json').write_text(json.dumps(report,indent=2)+'\n',encoding='utf-8')
    print(f'P(A then B)={float(ab):.6f}; P(B then A)={float(ba):.6f}')
    print(f'P(set A,B)={float(subsets[(0,1)]):.6f}; normalized product={float(product_weighted):.6f}')
    print('first-choice probabilities =',[round(float(p),6) for p in first])
    print('included in two draws =',[round(float(p),6) for p in inclusion])
    print('sum of inclusion probabilities =',float(sum(inclusion)))
    print('checks=PASS; report.json written')


if __name__=='__main__': main()

怎样运行:在独立练习文件夹中执行 python -B plackett_luce.py。2026-10-18 已在 Windows、Python 3.14.0 运行此份源码并通过自带检查。已运行 Fraction 六种有序结果精确枚举、无序集合合并、包含概率及权重整体缩放检查;未运行 TensorFlow、随机 Gumbel 采样或真实模型解码。

运行后对照结果
P(A then B)=0.066667; P(B then A)=0.083333
P(set A,B)=0.150000; normalized product=0.181818
first-choice probabilities = [0.166667, 0.333333, 0.5]
included in two draws = [0.416667, 0.733333, 0.85]
sum of inclusion probabilities = 2.0
checks=PASS; report.json written

记住这些要点

  • 不放回抽样每一步都要移除选中项并重新归一化。
  • 顺序概率与无序集合概率不同。
  • 选 k 个时,所有包含概率之和为 k。
  • Gumbel-Top-k 对应的是带噪声对数权重的有序分布。

别把例子用过头

  • 把首次概率直接当成最终入选概率。
  • 把集合概率写成权重乘积归一化。
  • 把不放回得到的样本当成相互独立。

自己试一小步

把权重改成 [1,1,8],两个小权重候选一起入选的概率是多少?

  1. 先列六种顺序的条件乘积。
  2. 合并成三个无序集合并计算每项包含概率。
  3. 比较 k=1、2、3 时包含概率的总和与单项变化。

做到这些,就算完成

  • 每个 k 的有序结果总概率为 1。
  • 包含概率总和等于 k。
  • 不把概率相近当成概率相等。

查原始资料

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

  • PlackettLuce distribution (新标签页)↗TensorFlow Probability · 英文

    顺序概率乘积与选中后移除再归一化

    2026-10-18 已打开并阅读Mathematical Details 的 pmf 和 sequential sampling;本文只转述相关定义,实验数字由随文程序产生。

  • Introduction to PlackettLuce (新标签页)↗Turner 等 / PlackettLuce 作者 · 英文

    Luce 选择概率与排名模型的条件乘积

    2026-10-18 已打开并阅读第 1 节式 P(j|S) 与排名概率;本文只转述相关定义,实验数字由随文程序产生。

  • Stochastic Beams and Where to Find Them (新标签页)↗Kool 等原作者 · 英文

    Gumbel-Top-k 与不放回抽样;包含概率不按原权重成比例

    2026-10-18 已打开并阅读第 2.4 节、脚注 1 与定理 1;本文只转述相关定义,实验数字由随文程序产生。