0

我正在运行类似于以下内容的 python 代码:

import numpy

def get_user_group(user, groups):
    if not user.group_id:
        user.group_id = assign(groups)
    return user.group_id

def assign(groups):
    for group in groups:
        ids.append(group.id)
        percentages.append(group.percentage) # e.g. .33

    assignment = numpy.random.choice(ids, p=percentages)
    return assignment

我们正在针对数以万计的用户在野外运行它。我注意到分配不尊重实际的组百分比。EG 如果我们的百分比是 [.9, .1],我们注意到每小时之间的分配是一致的,分别为 80% 和 20%。我们已经确认choice函数的输入是正确的,并且与实际行为不匹配。

有谁知道为什么会发生这种情况?是因为我们使用的是全局 numpy 吗?一些组将在 [.9, .1] 之间划分,而其他组将在 [.33,.34,.33] 等之间划分。不同组的组是否可能相互干扰?

我们在多个节点上的 python 烧瓶 Web 应用程序中运行此代码。

关于如何获得可靠的“随机”加权选择的任何建议?

4

1 回答 1

1

此评论耗尽了评论的限制,因此我将其发布在这里。

您的团队无法重现该问题但得到了正确的结果这一事实表明 NumPy 很可能可以满足您的需求。你可以在以后需要效率的时候从 NumPy 中受益,可见效率现在不是你关心的问题。

不过,在您的节点上进行更完整的代码和基础设施设置会很有帮助。你多久重启一次 Flask 服务器?你在哪里初始化 NumPy 随机生成器?考虑以下代码,它创建了一个/random可以自定义大小的页面,例如localhost:5000/random?size=20

from flask import Flask, request
import numpy
import pandas

... # your webapp

numpy.random.seed(0)

@app.route('/random', methods=['GET'])
def random():
    """Gives the desired number of random numbers
    with the state of the random number generator.
    """
    # DON'T PUT numpy.random.seed(0) HERE
    size = request.args.get('size')
    
    if size is not None:
        size = int(size)
    else:
        size = 1

    state = numpy.random.get_state()
    data = numpy.random.random(size=size)

    table = pandas.DataFrame(data=data)

    return table.to_html() + repr(state)

在此示例中,状态在 Flask 应用程序启动后初始化一次。每当/random请求页面时,都会生成良好的随机数。

如果将状态初始化放在函数中,肯定会导致意外分布,因为您将获得相同的随机数(和相同的选择)。

如果您使用多个节点并使用相同的种子进行初始化,您的不同节点将再次产生相同的选择。在这种情况下,使用唯一节点 ID 作为种子值。如果您经常重新启动服务器,请将重新启动 ID 或时间戳连接到唯一节点 ID。确保记录时间戳也是一个好主意。

于 2021-10-23T18:44:06.983 回答