A/B 测试的算法
我需要为我的用户开发一个A/B测试的方法。简单来说,我需要把我的用户分成几个组,比如40%和60%。
我大约有100万个用户,我想知道最好的方法是什么。随机数字不行,因为每次用户会得到不同的结果。我的第二个选择是修改我的数据库,让每个用户都有一个预先设定的号码(随机生成的)。这样做的缺点是,如果我得到的是50这个号码,那么这个用户就会一直是50,除非我创建一个新用户。我对此没有意见,但我不确定修改数据库是否是个好主意。
有没有其他解决方案可以避免这个问题呢?
4 个回答
这是一个简单的JavaScript一行代码:
const AB = (str) => parseInt(sha1(str).slice(0, 1), 16) % 2 === 0 ? 'A': 'B';
然后对于1000万个随机生成的邮箱,结果是:
{ A: 5003530, B: 4996470 }
我建议你可以加一个辅助表,这个表里只放用户ID和A/B的分类。这样你就不需要改动原来的表格,而且如果将来需要调整每个分类的比例也很简单。这种做法对原有数据的影响很小。
你在使用MySQL,所以说这个做法好不好,其实很难判断。修改数据库可能会很麻烦,而且如果数据库越来越大,可能会影响性能。此外,你还需要调整系统,以便在每个新用户加入时都把这个数字放到数据库里。你把这个问题标记为Python相关,所以这里有一种不需要改动数据库的方法。既然你在谈论用户,可能每个用户都有一个唯一的标识符,比如电子邮件。为了说明,我会用uuid来代替电子邮件。
import hashlib
def calculateab(email):
maxhash = 16**40
emailhash = int(hashlib.sha1(email).hexdigest(), 16)
div = (maxhash/100)-1
return int(float(emailhash/div))
#A small demo
if __name__ == '__main__':
import uuid, time, json
emails = []
verify = {}
for i in range(1000000):
emails.append(str(uuid.uuid4()))
starttime = time.time()
for i in emails:
ab = calculateab(i)
if ab not in verify:
verify[ab] = 1
else:
verify[ab] += 1
#json for your eye's pleasure
print json.dumps(verify, indent = 4)
#if you look at the numbers, you'll see that they are well distributed so
#unless you are going to do that every second for all users, it should work fine
print "total calculation time {0} seconds".format((time.time() - starttime))
这和Python关系不大,更像是数学上的解决方案。你可以使用md5、sha1或者类似的东西,只要它们是固定长度的,并且是十六进制数字。第六行的-1
是可选的,它将范围设置为0到99,而不是1到100。你也可以把它改成使用浮点数,这样会更灵活一些。
对主键运行一个简单的算法。例如,如果你有一个用户ID是整数,可以把它们分成偶数和奇数。
如果你需要分成超过两个组,可以使用取模函数。