simple a+b输入数据_数据科学的基础:A/B测试

作者:Tony Yiu

编译:ronghuaiyang

导读

使用一个简单的例子来解释A/B测试的复杂细节(也就是假设检验)。

自从我开始写博客,我发现写一个概念,并试图把它教给读者会迫使我更深入地去学习这个概念。

因此,在接下来的几周,我将逐一介绍每个数据科学家应该具备的核心能力,以便我们都能在面试中取得好成绩(祝好运)!现在进入今天的话题!

伪装的假设检验

d17d5e61a7f1fdc834a3e5f83a68ff22.png

如果你有统计学背景,在某个时候你可能会想,“A/B测试和假设检验是一回事吗?”没错,就是一回事!因此,让我们通过一个简单的例子来探究假设检验是如何工作的,从而得出A/B测试。

假设我们的客户,装了一个非常成功的个人理财应用程序,带着以下问题来找我们:

“Tony,我们重新设计的应用程序目的在帮助人们存下更多省下来的钱。但它真的有用吗?请帮助我们解决这个问题,这样我们才能决定是否部署它。”

所以我们的工作是弄清楚人们是否会因为新的应用程序而存更多的钱。首先,我们需要弄清楚我们是否拥有所需的数据。我们问,“您收集了哪些可能有用的数据?”

原来我们的客户已经做了一个实验,收集了一些数据:

  • 6个月前,我们的客户随机选择1000名新注册用户,将其中500名分配给对照组,500名分配给实验组。
  • 对照组继续使用当前的应用程序。
  • 同时,实验组使用重新设计的app。
  • 所有用户开始时的储蓄率为0%。
  • 1000名用户只占该应用总用户的一小部分。

6个月后,我们的客户记录了实验中所有1000名用户的储蓄率。储蓄率是指每个用户每月储蓄的工资的百分比。她发现了以下内容:

对照组的平均储蓄率由0%提高到12%,标准差为5%

实验组的平均储蓄率由0%提高到13%,标准差为5%

我们的实验结果在直方图上看起来是这样的:

82b6618717b79bb33b56c493e45d1a75.png

对照组和实验组的储蓄率直方图

与对照组相比,实验组的成员在六个月后的储蓄率确实有所提高。那么,仅仅绘制这个柱状图,把它展示给我们的客户,然后结束就足够了吗?

不,因为我们仍然不能确定我们所观察到的储蓄增长是真实的。幸运的是,我们本可以用这样一种方式为我们的实验抽样用户,即那些希望节省更多钱的人最终都进入了实验组。为此,我们需要提出以下问题:

我们从随机事件中观察到的结果得到的可能性有多大

回答这个问题是假设检验(以及A/B检验)的关键。

零假设

想象一下,在现实中,新的应用程序设计并没有帮助用户节省更多。然而,即使新设计是一个无用的,仍然有可能在我们进行实验时观察到储蓄率的增加。

8bdb67a42dc5f779c5b1a6f1e7e68248.png

怎么会这样呢?这是因为我们在抽样。例如,如果我从成千上万的人群中随机选出100个人,计算他们的平均身高,我可能得到5英尺8英寸。如果我再做几次,下次可能得到5英尺10英寸,之后可能得到5英尺7英寸。

因为我们是用样本而不是整体来计算统计量的,所以我们计算的每个样本均值都是不同的。

知道抽样会导致变化,我们可以把上面的问题重新组织成:

如果新的应用程序设计真的对人们的储蓄没有影响,那么观察到储蓄像随机增加一样大的概率是多少

正式地说,我们的零假设是:对照组储蓄率的增加等于实验组储蓄率的增加

我们现在的工作是检验零假设。我们可以用概率思维实验来做。

一次又一次的进行模拟实验

想象一下,我们可以轻松地、即时地一次又一次地进行我们的实验。此外,我们仍然处于一个并行的世界,在那里,新的应用程序设计是一个无用的,对用户的省钱没有任何影响。我们会观察到什么?

对于好奇的人来说,我们是这样模拟的:

  • 取与对照组统计特征相同(均值= 12%,标准差= 5%)的两个正态分布随机变量各抽取500个人(我们的对照组中有500名用户,实验组中有另外500名用户)。这些将是我们的对照组和实验组(同样的意思,因为我们在这个世界上,我们的新设计没有任何影响)。在这里使用泊松分布随机变量在技术上更正确,但为了简单起见,我们使用正态分布随机变量。
  • 记录各组间的平均储蓄差异(即我们用实验组的平均储蓄减去对照组的平均储蓄)。
  • 这样做一万次。
  • 绘制各组间平均节约量差异的柱状图。

当我们这样做时,我们得到下面的直方图。柱状图显示了由于随机性(由抽样驱动),组间的平均储蓄率差异有多大。

红色的竖线显示了我们在客户进行实验时实际观察到的平均储蓄率差异(1%)。直方图红线右边的百分比是我们想要的——随机抽取时省下来的钱增加1%的概率(我们这里做了一个单次实验,因为它是更容易理解和想象)。

4dab95f01666bf13af1f1cff3fa664e2.png

显示10,000次模拟中组间平均值差异的直方图(假设新设计对储蓄率没有影响)

在这种情况下,这个值非常低——在我们运行的10,000个实验中只有9个(假设新设计对节省没有影响)。

这意味着由于随机性,观测到的值和我们所观测到的值一样高,只有0.09%的变化。

0.09%的机会就是p值。

我们的目标,一如既往,是建立一个直观的理解。这些工具如何工作,为什么工作。因此,一般来说,我们将避免术语,而喜欢简单的解释。然而,p值是一个关键的概念,你会在数据科学世界中遇到很多,所以我们必须面对它。p值(我们在上面的模拟中计算的0.09%的值)表示:

如果零假设成立,我们观察到的概率。

因此,p值是我们用来检验零假设是否成立的数字。根据它的定义,看起来我们想要一个尽可能低的p值。p值越低,我们在实验中幸运的可能性就越小。在实践中,我们将设置一个p值截止值(称为alpha),低于这个值,我们将拒绝原假设,并得出观察到的效果/影响最有可能是真实的(统计上显著的)。

现在我们来研究一个统计特性,它可以让我们快速计算p值。

中心极限定理

现在我们来谈谈统计的基础概念之一:中心极限定理。该定理指出,如果你把独立的随机变量加起来,其和的归一化趋于正态分布。即使随机变量本身不是正态分布,中心极限定理也成立。

翻译一下:如果我们计算一系列的样本均值(假设我们的观测值是相互独立的,就像抛硬币是相互独立的一样),所有这些样本均值的分布就是正态分布

8d4cca951808303f354d7008b309833c.png

看一下我们之前计算的平均值差异的直方图。看起来像正态分布,对吧?我们可以使用Q-Q plot来做可视化,如果我们的分布是正态的,它会紧紧地粘在红色的45度线上。确实如此,酷毙了!

所以当我们一遍又一遍地做储蓄实验时,这就是中心极限定理的一个例子!

那么为什么这很重要呢?

还记得我们之前是如何通过10000次实验来检验零假设的吗。听起来是不是很累?实际上,重复进行实验既累人又昂贵。但由于中心极限定理,我们不需要这么做!

我们知道重复实验的分布是什么样子的—正态分布,我们可以用这个知识来统计推断10000个实验的分布,而不需要实际去做这么多实验!

我们复习一下我们目前所知道的:

  • 我们观察到对照组和实验组的平均储蓄率有1%的差异。我们想知道这是一个真实的差别还是仅仅是统计上的噪音。
  • 我们知道我们需要对实验结果持保留态度,因为我们只对客户的总用户基数中的一小部分进行了测试。如果我们在一个新的样本上再做一次,结果就会改变。
  • 由于我们担心在现实中新的app设计不会对储蓄产生影响,我们的零假设是,对照组和实验组的均值差为零。
  • 我们从中心极限定理得知,如果我们重复采样并进行新的实验,这些实验的结果(观察到的对照组和实验组之间的平均差值)将呈正态分布。
  • 从统计学上我们知道,当我们取两个独立随机变量之差时,结果的方差等于各个方差之和:
a2ec14ee9292e5b580eeced32a20ba05.png

完成工作

好了!现在我们有了运行假设检验所需的一切。所以让我们继续完成我们从客户那里收到的工作:

926a9a3c39723be4532ce70346454859.png

和上面一样的直方图(再贴一次):

  • 首先,在我们通过查看数据产生偏见之前,我们需要选择一个截断值,称为alpha(如果我们计算的p值小于alpha,我们拒绝零假设,并得出新设计增加了储蓄率的结论)。alpha值对应于出现假阳性的概率—当零假设为真时,拒绝零假设。0.05在统计学中是相当标准的,所以我们将采用它。
  • 接下来,我们需要计算测试统计量。检验统计量是上面直方图的数值等效物,它告诉我们与零假设值(在我们的例子中是零)有多少个标准差的距离,观察值是1%。我们可以这样计算:
  • Standard Error是实验组的平均储蓄率与对照组的平均储蓄率之差的标准差。在上图中,标准差用蓝色直方图的宽度表示。回想一下,两个随机变量之差的方差等于个体方差之和(标准差是方差的平方根)。我们可以很容易使用我们已经拥有的信息计算标准差:
a6b22edb3801f20e69cf422ccae42080.png
  • 记住,对照组和实验组的储蓄率都有5%的标准差。样本方差是0.0025,N是每组的观察次数N等于500。把这些数字代入公式,我们得到的标准误差是0.316%。
  • 在检验统计公式中,观测值为1%,假设值为0%(因为我们的零假设是没有影响)。将这些值和我们刚刚计算的标准误差代入测试统计公式,我们得到测试统计量为0.01/0.00316 = 3.16。
  • 我们的观测值为1%,与假设值0%相差3.16个标准差。挺多的。我们可以使用下面的Python代码来计算p值(用于双尾测试)。p值是0.0016。注意,我们将p值用在双尾测试中,因为我们不能假设新设计相比当前的设计一样或者更好—也可能更糟。
  • p值0.0016低于我们0.05的alpha值,所以我们拒绝零假设,并告诉我们的客户,是的,新的应用程序设计确实帮助她的用户节省了更多的钱。

最后,请注意,我们分析计算的0.0016的p值与我们之前模拟的0.0009不同。这是因为我们运行的模拟是单侧的(单侧测试更容易理解和可视化)。我们可以通过将模拟的p值乘以2(为了解释第二个尾部)来调和这些值,得到0.0018—非常接近0.0016。

结论

在现实世界中,A/B测试不会像我们虚构的例子那样一目了然。很可能我们的客户(或老板)没有现成的数据供我们使用,我们必须自己收集和清理数据。以下是一些准备A/B考试时需要注意的额外实用问题:

  • 你需要多少数据?收集数据既费时又昂贵。一个运行糟糕的实验甚至可能会疏远用户。但是如果你没有收集足够的观察值,你的测试就不是很可靠。因此,你需要仔细权衡更多观察的好处和收集它们的增量成本。
  • 错误拒绝真实零假设(第1类错误)的代价与错误拒绝虚假零假设(第2类错误)的代价是什么?回到我们的例子,第1类错误相当于在新应用程序设计实际上对节省没有影响的情况下对其进行绿灯亮起。第二类错误与坚持当前的设计是一样的,而新的设计实际上鼓励人们节省更多的钱。我们通过选择一个合理的截断值alpha来权衡类型1和类型2错误的风险。较高的alpha值会增加第1类错误的风险,较低的alpha值会增加第2类错误的风险。

英文原文:https://towardsdatascience.com/data-science-fundamentals-a-b-testing-cb371ceecc27

6a3da64496077bc4e4d918e930045d4b.png

请长按或扫描二维码关注本公众号

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ubuntu16.04ros编译时报错home/bobac3/ros_workspace/src/multipoint_navigation/src/multipoint_nav.cpp:20:17: warning: non-static data member initializers only available with -std=c++11 or -std=gnu++11 int cycle = 1; //巡航次数 ^ /home/bobac3/ros_workspace/src/multipoint_navigation/src/multipoint_nav.cpp: In member function ‘void Multipoint_Nav::move()’: /home/bobac3/ros_workspace/src/multipoint_navigation/src/multipoint_nav.cpp:90:26: error: ‘goal’ does not name a type for(auto goal:pose) //遍历导航点列表 ^ In file included from /opt/ros/kinetic/include/ros/ros.h:40:0, from /opt/ros/kinetic/include/actionlib/client/simple_action_client.h:45, from /home/bobac3/ros_workspace/src/multipoint_navigation/src/multipoint_nav.cpp:1: /opt/ros/kinetic/include/ros/console.h:373:3: error: expected ‘;’ before ‘do’ do \ ^ /opt/ros/kinetic/include/ros/console.h:561:35: note: in expansion of macro ‘ROS_LOG_COND’ #define ROS_LOG(level, name, ...) ROS_LOG_COND(true, level, name, __VA_ARGS__) ^ /opt/ros/kinetic/include/rosconsole/macros_generated.h:110:23: note: in expansion of macro ‘ROS_LOG’ #define ROS_INFO(...) ROS_LOG(::ros::console::levels::Info, ROSCONSOLE_DEFAULT_ ^ /home/bobac3/ros_workspace/src/multipoint_navigation/src/multipoint_nav.cpp:152:17: note: in expansion of macro ‘ROS_INFO’ ROS_INFO("------------------loop ( %d ) termination!----------- ^ /opt/ros/kinetic/include/ros/console.h:373:3: error: expected primary-expression before ‘do’ do \ ^ /opt/ros/kinetic/include/ros/console.h:561:35: note: in expansion of macro ‘ROS_LOG_COND’ #define ROS_LOG(level, name, ...) ROS_LOG_COND(true, level, name, __VA_ARGS__) ^ /opt/ros/kinetic/include/rosconsole/macros_generated.h:110:23: note: in expansion of macro ‘ROS_LOG’ #define ROS_INFO(...) ROS_LOG(::ros::console::levels::Info, ROSCONSOLE_DEFAULT_
最新发布
06-10
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值