从零开始学AB测试:躲坑篇
AB测试的原理很简单,只用到了最简单的统计假设检验,但表面的简单通常都隐藏着陷阱,这一点没有经过实践的摸爬滚打是不容易看到的,今天我就把前人已经踩过的坑,一共15个,给大家分享一下。在分享之前,大家脑中一定要有个概念,AB测试虽然简单且强大,但是其成立是有前提的:
- A组和B组的用户一定是要“随机”分配。随机这个事很有学问,绝对的随机甚至根本不可能,实际中只能做到尽量接近真随机。换句话说,随机性并不总是成立,你要仔细小心它失效的场景。
- 在以你测试的时间点为中心的一定时间范围内,用户的行为是不变的。
只要牢记并时刻检查这两点假设,那么很多下面的陷阱你自然就能避免了。
1. 不做AB测试
很显然,我们不能不做AB测试。不要企图用一些其他方法替代AB测试,比如:通过比较产品上线之前N天和之后N天的情况,对比分析去得出结论。这不也是AB对比吗?看起来没毛病,这种方法也不是完全没有用,但是很不稳定,所以不要用。
2. 乱作AB测试
既然AB大法这么好用,那么我们全靠它不就行了吗?以后有任何功能任何改动都先搞个AB测试吧!AB测试并不是做的越多越好,我们可以通过下面简单的公式来看一下:
我们追求的是总的效果,除了注重数量更要注重质量。
3. 采样污染
举个例子,如果你在节假日对你的产品做AB测试,那么测试阶段的用户群(样本)和平时的用户群自然会有很大的差异(回顾开头讲的第二条前提条件),这样很难得出你想要的测试结果。AB测试无法在全体样本上进行实验,所以必须采样,采样要保证随机性且能代表总体样本的分布,做实验的时候就要特别注意避免一些可能导致采样污染的特殊因素。
4. 时间范围不够
除了要避免在一些特殊时间进行测试,测试的时间还要足够长,理由如下:
- 时间长有助于收集更多的数据,保证统计显著性
- 如果新的特征改变比较明显,老用户可能会不适应,那么你需要给老用户一定的时间去适应你的改变,然后收集的数据才更有统计意义。(参考开头提到的第二条准则)
5. 只关注平均值
如果测试结果显示新版本比旧版本平均多吸引了30%的用户,那么是否就证明万事大吉,可以开开心心上线了呢? 还不行。这个时候还要对更细粒度的数据做一些分析,保证你看到的“好结果”是真的。 举个极端点例子,万一是系统Bug导致新版本多统计出了更多的用户呢? 我们相信,在AB实验结束并且展现了良好的结果时,你已经基本接近成功了,但是永远不要在分析更详细用户数据之前下结论。
6. 忽视技术实现
有些看不见的东西一样会影响用户,AB测试阶段除了产品特性的不同,技术细节也会改变,这些会不会影响到实验结果? 如果新版本加载更多的css资源,会不会导致页面加载变慢?这些看不见的细节也会影响用户体验,给实验结果带来干扰。
7. 不去思考为什么
AB测试不会一直成功,甚至失败的次数可能更多,但是如果实验结束之后不去思考为什么,那才是彻底的失败。实际上AB测试失败的时候,才是我们从中学习并真正了解用户的时候,千万不要放弃这样的机会,要多问些为什么。
“想要提高成功率,先提高失败率。”
8. 用错误的度量标准
举个例子,如果你优化的是网站首页的性能,那么就不要拿全站的统计结果去做度量标准。度量标准要选好,不要想当然。
9. 做一系列的测试
如果新版本有10个细节上的改动,那么是不是我们要做10个AB测试来分别测试他们的效果呢? 当然不行,千万不要这么做。产品的改动效果绝对不是线性相加的,不同的特征之间要一起组合才能生效,就好比把背景变黑之后一定要把字体变白才行。
10. 实验设置有噪声
还有很多我们无法预料的因素可能会影响到实验结果,那么怎么办呢? 我们不止要做AB测试,还要做AA测试,用AA测试来保证实验设置本身没有噪声干扰,这个也很重要。于是在实际中你要把1/3的用户分配给B组,1/3的用户分配给第一个A组,1/3的用户分配给第二个A组。
11. 忽略环境的改变
不管你的AB测试是成功了还是失败了,在一定时间之后你都要重新审视它,因为环境变了。昨天失败的AB测试,很可能是你的理念超前了,也许过了一年用户就可以接受了呢?一次失败不代表用永远失败,反之亦然。
12. 交叉访问污染
当线上同时存在两个版本的时候,你一定要考虑到单个用户的体验。如果一个用户在不同浏览器、不同设备上访问到了不同的版本,那么可能会带来用户体验的下降,同时对收集的数据造成干扰。 比如,如果AB版本之间的差异过于明显,那么老顾客可能就会很讨厌那个新版本,而在新版本上表现出消极的行为,同时在老版本上表现积极的行为,而我们无法从统计结果中对这种偏差就行纠正。所以保证单个用户体验的一致性就很重要。
13. 漏斗污染(Funnel pollution)
不确定这个翻译准确不准确,就直接按英文直译了。如果你是一个电商网站,那么你最终的目标是要用户下单付款,你的优化目标应该是针对整个下单的全流程,并且以最终下单的数量作为度量标准。假如你在首页做了某些活度,让点击产品页面的用户大幅度提升,有些统计数据看起来会很漂亮,但是对最终的结果可能没有任何帮助。这个也要注意。
14. 同时运行多个AB测试
线上同时存在多个版本的话,实在是有点复杂,一般情况下不会这么干,但仍要警惕。
15. 使用错误的经验
AB实验毕竟是一项科学实验,所以我们要用数据说话,不能想当然。不要乱用一些道听途说的经验,比如:“1000个用户样本就够了”,实际上收集多少用户的数据是要严格计算的。上一篇文章我们分享过类似的工具。再比如,不要以为在桌面端测试通过的方案,就可以放心在手机端同时上线了,实际上不同平台的差异非常大,必须单独进行AB测试。
总之,要记住开头提到的AB测试成立的两个前提,要时刻检验它们是否成立:
- A组和B组的用户一定是要“随机”分配。
- 在以你测试的时间点为中心的一定时间范围内,用户的行为是不变的。
如果你喜欢以上内容,欢迎到我的个人主页关注我:Homepage
从零开始学AB测试:躲坑篇的更多相关文章
- 从零开始学AB测试:基础篇
什么是AB测试? 通俗点理解,AB测试就是比较两个东西好坏的一套方法,这种A和B的比较在我们的生活和人生中非常常见,所以不难理解.具体到AB测试这个概念,它和我们比较哪个梨更大.比较哪个美女更漂亮.比 ...
- 58. Spring Boot国际化(i18n)【从零开始学Spring Boot】
国际化(internationalization)是设计和制造容易适应不同区域要求的产品的一种方式.它要求从产品中抽离所有地域语言,国家/地区和文化相关的元素.换言之,应用程序的功能和代码设计考虑在不 ...
- 52. spring boot日志升级篇—log4j多环境不同日志级别的控制【从零开始学Spring Boot】
在上一章节中我们介绍了,仅通过log4j-spring.properties对日志级别进行控制,对于需要多环境部署的环境不是很方便,可能我们在开发环境大部分模块需要采用DEBUG级别,在测试环境可能需 ...
- 从零开始学 Java - Spring 支持 CORS 请求踩的坑
谁没掉进过几个大坑 记得好久之前,总能时不时在某个地方看到一些标语,往往都是上面一个伟人的头像,然后不管是不是他说的话,下面总是有看起来很政治正确且没卵用的屁话,我活到目前为止,最令我笑的肚子痛得是下 ...
- 57. Spring 自定义properties升级篇【从零开始学Spring Boot】
之前在两篇文章中都有简单介绍或者提到过 自定义属性的用法: 25.Spring Boot使用自定义的properties[从零开始学Spring Boot] 51. spring boot属性文件之多 ...
- 54. spring boot日志升级篇—logback【从零开始学Spring Boot】
在<44. Spring Boot日志记录SLF4J>章节中有关相关的介绍,这里我们在深入的了解下logback框架. 为什么要使用logback ? --在开发中不建议使用System. ...
- 50. Spring Boot日志升级篇—log4j【从零开始学Spring Boot】
如果你使用的是spring boot 1.4.0版本的话,那么你可能需要配合以下文章进行学习 90.Spring Boot 1.4 使用log4j错误[从零开始学Spring Boot] Log4j是 ...
- (36)Spring Boot Cache理论篇【从零开始学Spring Boot】
Spring Boot Cache理论篇 在上一篇中我们介绍了Spring Boot集成Redis的实战例子,里面使用到了Spring Cache,那么什么是Spring Cache呢,本章将会做一个 ...
- 从零开始学Sketch——进阶篇-b
从零开始学Sketch——进阶篇 Sketch是一款矢量绘图应用,而矢量绘图无疑是目前进行网页.图标以及界面设计的最好方式. 在初识了Sketch的界面布局和基础工具之后,我们就可以开始进入高阶的Sk ...
随机推荐
- coding++: java把一个整数拆分为单个值
方式一: int num = 100; int[] ary = new int[(num+"").length()]; for(int i = ary.length-1;i> ...
- Java工程师常用Linux命令
本文所列的Linux常用命令包含:文件相关(目录操作,内容查看,查找与比较,压缩与解压),进程管理,网络操作,系统管理,性能监测与优化,Java常用工具多个方面概述. 文件目录基本操作 ls 命令用来 ...
- Python操作JSON数据代码示例
#!/usr/bin/env python import json import os def json_test(): return_dic = {} json_data = { 'appid':' ...
- 模块 configparser 配置文件生成修改
此模块用于生成和修改常见配置文档 1.来看一个好多软件的常见配置文件格式如下***.ini [DEFAULT] ServerAliveInterval = 45 Compression = yes C ...
- CSS3+CSS+HTML实现网页
效果图: 代码实现: 样式部分style.css: *{ margin:; padding:; } body{ background-color: #673929; font-size: 16px; ...
- Python执行js之PyexecJs
利用Python执行js 爬虫中会经常碰到JS加密,当我们找到他加密的JS代码之后我们需要获取它的返回值,python虽然可以模仿js写一个python版本的加密,但是这样有点费时间,也有点费头发~ ...
- CodeForces - 817B(分类讨论 + 排列组合)
题目链接 思路如下 这一题是:最菜的队伍只有三个人组成,我们只需对排序后的数组的 前三个元素进行分类讨论即可: a[3] != a[2] && a[3] != ar[1] a[3] = ...
- B. The Monster and the Squirrel
B. The Monster and the Squirrel Ari the monster always wakes up very early with the first ray of the ...
- JDBC下Date类型转换问题
一.前言 在学过MVC后,其中的DAO层是负责与数据库进行进行数据交互,而service层个servlet层需要数据时,不允许直接向数据库要,而是通过Dao层来获取相关数据.这个时候,就引出一个规定& ...
- mybatis源码分析:启动过程
mybatis在开发中作为一个ORM框架使用的比较多,所谓ORM指的是Object Relation Mapping,直译过来就是对象关系映射,这个映射指的是java中的对象和数据库中的记录的映射,也 ...