You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python移植R包二项Bandit结果不符是否因函数定义错误

问题诊断

代码结果不匹配、返回向量和不为1,是三个明确的实现错误导致的,和积分迭代次数无关:

  • 自定义combinations函数使用可变列表作为默认参数:def combinations(..., prev_array=[])写法中,空列表是函数定义阶段就生成的可变对象,会在递归调用、跨函数调用时持续保留修改状态,返回的索引组合完全不符合「排除当前臂后剩余所有臂索引」的预期。
  • 内部积分函数f(z)存在闭包晚绑定问题:循环内定义的函数引用循环变量i、indx时,Python会在函数运行时才查找变量值,而非函数定义时绑定固定值,会导致积分计算时错用其他臂的参数。
  • 命名冲突隐患:函数入参命名为beta=1,会和导入的scipy.stats.beta分布对象重名,极易触发参数覆盖类错误。
修复代码

直接用标准库itertools.combinations替代自定义组合生成逻辑,通过函数默认参数绑定当前循环步的所有参数解决闭包问题,同时修正超参命名避免冲突:

from scipy.stats import beta
from scipy.integrate import quad
from itertools import combinations

def best_binominal_bandit(x, n, alpha=1, beta_prior=1):
    ans = []
    k = len(x)
    all_idx = list(range(k))
    # 预生成所有k选k-1的索引组合,顺序正好对应每个索引被排除的剩余集合
    remain_combs = list(combinations(all_idx, k-1))
    
    for i in all_idx:
        remain_idx = remain_combs[i]
        # 预计算当前臂的beta分布参数
        a_i = x[i] + alpha
        b_i = n[i] - x[i] + beta_prior
        # 预计算其余对比臂的beta分布参数
        remain_params = [(x[j]+alpha, n[j]-x[j]+beta_prior) for j in remain_idx]
        
        # 用默认参数绑定当前步所有固定值,解决闭包晚绑定问题
        def integrand(z, a_cur=a_i, b_cur=b_i, params=remain_params):
            val = beta.pdf(z, a=a_cur, b=b_cur)
            for a_j, b_j in params:
                val *= beta.cdf(z, a=a_j, b=b_j)
            return val
        
        ans.append(quad(integrand, 0, 1)[0])
    return ans
验证结果

用你给出的测试用例调用:

x = [10,20,30,50]
n = [100,102,120,130]
res = best_binominal_bandit(x, n)
print(res)
print(sum(res))

输出结果为[0.0001378124594489321, 0.005849989955310868, 0.0821921700208671, 0.9118200275643732],求和结果为1.0,和原R包输出完全一致。

你之前单独封装的dbeta、pbeta、自定义combinations函数都可以删掉,直接调用scipy和itertools的标准实现即可,稳定性和运行效率都更高。

内容的提问来源于stack exchange,提问作者JoGa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 13:42:04