干货篇 | 神策:帮你发现分析数据异常:指标智能预警实践
导读: 传统的指标预警方式通常基于规则实现,存在不够灵活和容易误报等问题。报警发生后,往往还需要大量的人工分析,才能定位到触发报警的真正原因。神策推出的智能预警功能,旨在帮助用户精准触发指标预警,并自动分析出触发报警的真正原因。本文分享机器学习方法在智能预警和诊断中的实践应用。
嘉宾介绍: 胡士文,神策数据机器学习算法专家,负责人工智能机器学习在神策产品和业务中的探索和落地,主要包括推荐系统、智能匹配、指标预测和诊断、用户流失预测。神策产品矩阵中的智能功能已经应用于各行业多个标杆客户,均为客户带来了显著的效果和收入提升。加入神策之前,曾负责或参与360搜索知识图谱、360搜索右侧推荐、360浏览器推荐、知乎首页推荐等项目, 具有丰富的机器学习算法经验,善于利用数据和算法推动业务增长,解决实际问题。
本科毕业于华中科技大学软件学院,研究生毕业于中科院计算所系统结构国家重点实验室。
目录
- 业务背景
- 产品形态
- 算法实践
- 挑战和todos
01 业务背景
首先介绍下指标智能预警的业务背景,我们分两个方面讲一下:第一,在日常工作中,业务负责人、项目负责人,甚至公司老板都会去关注和管理很多重要的业务指标,比如一个产品、一个模块的DAU、一个推荐系统的CTR这样的业务指标。那关注这些指标的一个需求就是在数据发生异常时能够及时的报警。这样我们能够及时去发现问题,并且跟进问题。但是在实际情况下,怎么去设置报警的规则,其实是具有一定难度的。一方面报警规则的设置是依赖一些业务经验的。就比如DAU的指标,在什么样的情况下判断它是异常的,需要报警。
另外一方面就是报警规则,如果我们用规则去设置报警,那么设置是不太灵活的。不灵活就会导致容易误报或者漏报。右图的截图是我们神策分析在上一个版本所提供的设置预警的功能,可以看到其实功能是非常有限的。我们提供它跟上一小时相比低于某个阈值就报警,或者跟昨天同期相比低于某一个阈值就报警,或者低于一个特定值就报警,但其实这样的报警设置规则是满足不了业务的需求的。
举个简单的例子,如果我们是在一个外卖的场景下,比如美团外卖,或滴滴打车这样的场景,我们要去监控每个小时的订单量,如果设置成跟上一小时相比低于10%就报警。那这样的话外卖场景下晚上8点比晚上7点低10%其实是一个很正常的现象。那如果我们把报警规则设置成比昨日同期低10%就报警也是会有问题的,比在一些异常天气的情况下,那美团外卖的订单量就会有明显的增长。那么到了第二天,天气正常了,订单量也随之下降了。所以用这样的规则会容易触发一些误报。所以在这块我们希望能用机器学习算法去自动的判断这个真实的指标是不是已经发生异常了。
第二方面是当我们真正遇到一个异常指标时,接下来就要去分析这个异常的原因究竟是什么。在很多公司可能会有一些专门的分析师根据他们的业务经验做一些探索分析。我们还以DAU为例,如果发现DAU下降了,那分析师可能会去看下操作系统和版本,是不是因为某一个新发的APP版本有bug ,或者某个体验问题造成下降。或者他可能去看在不同投放渠道是不是有一些拉新的问题,导致了整个的DAU下降。整个思路的实践其实有几个问题。第一个问题,如果整体缺乏一些基础数据的采集,那分析其实是进行不下去的。第二个问题是在分析过程中,是需要各种的数据的join操作和人工做很多维度下钻的,整个的过程是比较耗时耗力的。根据我们客户情况来看,通常分析师去分析一个数据异常的问题会需要好几天的时间。像去分析一个DAU异常,或是push 转化率异常这样的问题,常常需要三到五天,因为需要一些业务的经验,还需要很多数据的join 和人工维度的工作。
所以我们是期望有一个自动化的智能化的方式,当这个指标真正发生异常的时候,能够自动的找到这个指标真正异常的原因,这个是我们面临的业务背景,以及在这个业务背景下两个急需解决的问题。
在这个业务背景的情况下,我们期待做这么一款预警和分析的产品,它有这几个特点:第一个特点就是数据的收集是全面的。因为我们要去做一些数据的异常的原因分析的话,就需要去做很多的维度下钻和数据的关联工作,所以前提就是要做一些全面的基础数据的采集。
第二点是希望能够去做智能的指标预警,也就是不需要业务人员或分析师去配各种复杂的报警规则,而是当这个指标发生的时候,工具就能告诉我们这个指标是正常还是异常的。如果是异常的,就报警。
第三点是当真正有数据异常发生的时候,我们希望能够自动的去分析出数据异常的原因是什么。
第四点是我们希望这个功能是具有一定的业务通用性的。因为像神策的产品是面向各行各业的客户的,那每个客户的业务场景可能会不一样,有的客户是做外卖的,有的是做金融的,有的是做游戏的。那在各行各业的业务场景里面,他们的数据异常的原因和数据异常分析的方法和思路可能都是不一样的。在很多 toC 公司上,它可能不是问题,但在神策这边就会是一个比较大的挑战。因为我们是希望这套方法和产品,能够在各行各业各个业务场景下都能具有业务通用性,去发挥作用和价值的。
02 产品形态
接下来分享下我们面对这样的业务挑战,正在做的一款智能预警的产品。这是一个智能化的报警和异常分析的工具。这个产品它其实有很多的功能,使用起来也有一定的复杂度,这里我主要介绍两个比较重要的功能:
第一就是智能预警功能。这个功能只需要做一些简单的配置。当这个指标真正发生了之后,自动的智能的去判断这个指标是正常还是异常。
第二个重要的产品的解决方案是,当这个数据真正发生异常之后,我们能够自动的帮用户挖掘出造成这个数据异常的维度和原因是什么?比如它可能是在某一个投放渠道发生了异常,导致整个DAU的异常。也可能是因为来了一批作弊的用户,或是一批薅羊毛的用户,导致整个转化率或CTR下降了,这个产品也是能够自动的去把这些异常的原因给分析出来。这块就是我们构建的产品形态。
03 算法实践
介绍完了我们的业务场景和解决方案,接下来和大家分享下在这个解决方案里面,机器学习到底解决了哪些问题,以及面对那些挑战我们是怎么解决的。这块也主要是围绕前面我们抛出来的两个问题,第一是怎么去智能的做指标的报警。第二是怎么去做自动化的异常维度和原因分析和下钻。
首先来看下智能指标预警。回到我们的业务问题,其实面临的问题是,当一个指标发生的时候,怎么去判断这个指标它是正常还是异常的。我们把它转化成了一个预测指标的正常值的机器学习问题。当我们用一些机器学习的方法去预测这个指标的正常值是什么。预测值跟实际发生值如果出现了比较大的偏差时,就可以判断出这个指标异常了。
那我们是怎么去做这个指标预测的?其实我们就是把这个异常报警的问题转化成了指标预测的问题。因为我们神策是一个2B的产品的公司,所以在指标预测这块,是非常强调算法的通用性的,希望这个指标预测的算法是能够在各行各业,各种业务情况下,都能够有效的。目前做指标预测大概有两种思路:
第一种思路是用回归的思路去做一个有监督的学习。那我们面临的问题是可能要去构建一些特征。目前来看,很多的特征它是和各行各业有相关的。比如外卖行业,它可能是跟天气有关,如果我们要去用这种有监督的学习方法的话,可能就需要构建天气类的特征。还有一些金融类的客户,可能他的一些指标是跟国家的政策,甚至是一些金融的政策强相关的。我们目前采用的解决方案出于算法通用性的考虑,没有去构建那么多的行业特征,而是使用了一种时序预测算法。时序预测是我们输入的训练集仅仅是这个指标过往一段时间内的真实的值,没有额外的任何特征的信息。使用这个指标过去一段时间的值,来去预测它下一个时间点的真实值应该是什么。
我们现在使用的预测的方法是Facebook 开源的一个时序预测的工具prophet。Facebook 也是用prophet去预测他们的很多业务指标。比如像Facebook 的DAU以及站内用户互动次数等等。
接下来看一下prophet是怎么做时序预测的。prophet把预测拆解成了三个方面,分别用三个不同的模型去预测这个指标的趋势,周期性和一些特殊事件对这个指标造成的影响,接下来就这三个方面分别介绍一下是怎么去建模和预测。
首先讲下趋势的预测,在prophet里面它提供了两种趋势预测的模型。第一种是线性的模型。t的意思是时间。g(t)是这个线性模型预测出来的这个指标的趋势。K是这个指标的变化趋势,可以简单的认为它是斜率,但是实际的指标的变化趋势是会随着时间变化的。比如DAU在增长时可能刚开始DAU增长很迅猛,后面DAU增长就会变得相对缓慢,甚至慢慢进入一个瓶颈期。在这里引入了一个 δ这个参数,用来引入趋势变点,虽然在这个趋势中k 是固定的,但是随着时间的推移,这个趋势是可以变化的。a(t)表示的是随着时间的变化,我应该考虑哪一些变点。而δ就是对各个趋势变点的建模。m是一个偏移量,偏移量就是我们要去做线性拟合的时候,y 等于x+b,就是那个b。最后的那部的a(t)转置乘以γ,这部分的加入是为了让整个g(t)的拟合是一个连续的函数。
所以这个公式可以从两方面去理解它。第一就是这个k ,是去拟合整个趋势变化的一个斜率。第二是它引入了趋势变化的概念,让整个模型能够去更好的拟合趋势的变化,这个线性模型大概就是这样一个思路。
prophet还提供了另外一种趋势预测的方法,叫非线性饱和模型。它会有个指标假设的上限,也就是公式里面的C ,表示的是整个指标的上限。分母的k ,是去拟合整个指,慢慢去逼近这个上限的一个速度。这个非线性饱和模型其实也会有一些变点的考虑,我们这里为了简化就没有把它体现出来,这是prophet提供的两种趋势预测的算法。
在我们实践的过程中,非线性饱和模型它是要提供一个超参的,提供一个C,但我们其实是不希望对每个客户都去给他设定一个C,所以我们选定的是第一个线性模型。线性模型,一方面它能自动的去拟合这个变化趋势,另外一方面它也能自动拟合这个趋势变化的情况。我们刚提到变点,也是可以去自动学习和拟合出来的,这是趋势预测的部分。
第二部分是整个周期的预测。我们的很多业务指标,它会呈现一些比如说按周,周一的一些业务指标和周天的业务指标是不一样的。像DAU在周一和周六它都是不一样的。还有一些按小时的指标监控,每天的高峰期可能会在晚上六七点,低峰期肯定是在凌晨的一两点。在不同的小时,它的指标的值也是不一样的。那在有的业务场景下,可能按月也会有一定的周期性。在这个预测方法里面,对于周期性的预测是用傅利叶级数去拟合不同的周期的。
右图是傅利叶级数的示意图,大概能说明傅利叶级数是怎么去拟合这个周期性的指标的。s(t)是需要拟合几个周期性就设置几个s(t)。比如要拟合三个周期性,分别是按月周期、按周周期、按日周期,那就要设置三个s(t) 。s(t)里面有一个超参N是需要我们去设置的。N越大的话,这个模型的拟合能力越强,那同时也意味着这个模型越有可能过拟合。an和 bn就是整个周期预测里面需要去拟合和训练的参数。如果我们去拟合三个周期,那需要设置三个s(t)。那需要拟合的参数就是3×2n,要拟合6n个参数。整个周期预测我们就是用傅利叶级数去拟合的。
预测的最后一部分就是对特殊事件的拟合。特殊事件比如说像节假日,或者像本周一(4月5日)虽然周一是工作日,但其实它是清明的节假日。所以如果我们不考虑节假日的话,那么对本周一的这种情况就会出现偏差,这是一类特殊事件。
还有一类特殊事件像双十一、618,也会对数据指标产生非常剧烈的影响。我们对特殊事件的处理主要是基于一个正态分布的假设。就是对每一类特殊事件,去用一个分量单独的预测。方式就是用一个正态分布去拟合这个特殊的事件,通常情况下,我们会对节假日考虑一个特殊事件。像双十一、618这类电商运营的活动,我们去建两个分量,来分别拟合这种特殊事件对于真正的指标所造成的影响。但这块也存在难点。如果我们用一段时间的训练数据,通常能够覆盖到几个节假日,但是我们用现在这个时间点过去半年的数据去做训练集的话,那其实是cover 不到双十一这个时间点的。所以像双十一、618这种特殊事件,除非我们的输入的训练数据的周期量比较长,否则是存在数据比较稀疏,甚至数据缺失的问题的。
前面提到了三部分,如果把它累加到一起,其实就是整个时序预测的大概方法。但是在实际的过程中,我们拿到的去做预测的训练数据,通常不是那么的理想,会有很多的异常值。可能在单个公司业务场景下这个不是一个问题,因为在做一些机器学习任务的时候,我们通常都会有一些手动的数据清洗。但是在我们神策这个 toB 的业务场景下,第一我们没有手动的数据清洗的过程。第二我们也没有一个很通用的业务知识能够知道在哪个业务场景下,哪些数据是正常的,哪些数据是异常的。
所以我们采用了一个非常通用的解决方案,对数据去做分片的正态分布的建模。举个例子,如果是按天的时序预测,从周一到周天我们会去对每个周一的数据去建一个正态分布,然后把在正负三倍标准差之外的数据,当做是一个异常数据,大概去做一个粗略的异常值的检测。
这个是我们在客户真实环境下,去预测这个客户的LTV。我们如果用过去二十天的数据去预测未来十天的数据,可以看到预测未来三四天的数据还是比较准确的,但后面预测的周期越长,积累的偏差也就越大。但从实际情况来看,如果输入的数据情况比较理想,预测的结果还是比较理想的。输入数据情况比较理想指的是:第一这个数据量比较多,第二数据没有太大的异常。如果数据里面缺了一段数据,或者APP出了两天的bug,导致有一些异常的数据,恰好我们又没有识别出来的话,那么预测效果可能就没有那么理想了。但整体来看这个预算法在我们实际的场景下表现还是不错的。
刚刚讲了我们怎么去预测一个指标的值,那我们是如何去判定这个指标是不是异常的?假设我们有一个预测器可以预测出这个指标的期望值,同时我们也拿到了这个指标的真实的值,那我们怎么去判定这个真实的值是否发生了异常呢?在这种情况下,我们在做技术方案设计时有两种思路:
第一种思路是做一个单独的异常的判定器。就是输入预测值和真实值,还有其他一些特征,然后去预测当前是不是发生了异常。那这就变成了一个分类的问题。就像刚刚提到的,因为我们是一个通用的2B的场景,我们期望能够减少一些手动的特征工程。所以目前我们没有采用这种解决方案。
我们采用的解决方案是去预测这个指标的正常区间。当真实值不在预测的这个区间里面,我们就认为这个指标是发生了异常,就可以报警。那如果这个真实的值在这个区间里面,就认为这个指标是正常的,就不报警了。
当我们检测到一个数据异常之后,这只是问题的开始,接下来我们是想要知道这个异常的原因是什么。在讲解决方案之前,先给大家分析几个case ,来看一下我们现在面临的问题是什么。
假设现在发现的是新用户的数量发生了异常的下降,面临这个问题分析师可能会去做进一步的分析。他可能会先到不同的平台去看,比如在IOS和安卓上看,第一天和第二天两个平台都出现了一个比较明显的数据下降,那得到的结论就是IOS和安卓并没有表现出数据异常下降的区别,所以IOS和安卓不是导致数据异常性的原因。接下来的分析思路是去看一下在各个渠道投放拉新的效果。如果通过数据分析发现,在百度渠道,这两天的数据是比较平稳的。但在头条这个渠道,第一天是十五万,第二天是七万,那我们可以推断是因为在头条这个渠道上投放出问题,导致的新用户数量出现了异常下降,这就是一个人工分析的过程。
但这个过程中存在两个问题:第一个问题就是这个分析的过程是依赖业务经验,并且是比较耗时耗力的。另外一个问题就是IOS和安卓这两个维度出现了数据的下降,头条这个渠道也出现了异常下降。但是我们通过人工的分析,能够知道IOS 的下降和安卓的下降是一个结果,而不是原因。真正造成新用户异常下降的原因其实头条的投放异常,导致了新用户的数据异常。那如果我们想自动的去做这个事情,怎么能够识别出来头条这个维度的数据异常下降是原因,而IOS和安卓这个维度的异常下降是结果呢?这块其实是我们面临的实际问题。
接下来看另外一个例子,在广告投放点击率这种场景下,假设我们发现广告投放的点击率有一个异常的下降,那分析师可能会去看各个渠道的点击率是不是发生了异常。但有一种情况就是当各个渠道去看的时候,发现各个渠道的点击率都是正常的,那这个时候我们该怎么去进一步分析问题呢?
如果这个时候是一个有经验的分析师的话,他可能会去进一步的分析。除了去分析每一个渠道的点击率以外,还应该去看各个渠道的投放量。在百度这个渠道,投放量从十万变成了五万,在头条这个渠道从八万变成了十五万。虽然说各个渠道的点击率是稳定的,但是百度这个渠道它的点击率比较高,但是它的投放量变低了,而头条这个渠道它的点击率比较低,但是它的投放量变多了,这就意味着虽然各个渠道的点击率是稳定的,但是各个渠道的投放量的占比发生了变化,这样也会造成整个指标的异常的变化。那在这种情况下,我们的分析思路又跟刚刚的新用户数量异常下降场景的分析思路不一样,那在各种各样的数据异常情况的分析思路中,我们能不能找到一个比较普适的自动分析数据异常原因的思路呢?
分析师通常会通过自己业务经验去做异常面的分析,那结论有很多种,比如来了一批作弊的用户导致转化率下降了, APP发新版了恰好有个bug所以导致一些指标异常了,或者某个渠道投放出问题了导致数据异常了。
我们在设计自动异常原因的分析的这个功能时候,是假设异常的原因隐藏在数据的维度和属性当中,也就是说当一些异常的原因不在数据的各个属性和维度中时候,我接下来描述的方法就是失效的。
面临刚刚提到的这个场景,神策目前设计了两种诊断的功能:第一个是维度下钻,第二个是异常用户的分析。这也是造成数据异常的两个常见的原因。
在前面有提到当新用户数量一直下降这种情况下,我们怎么识别出在头条渠道数据下降才是真正数据下降原因,而IOS 和安卓的下降并不是原因而是结果。我们目前常用的方法就是去计算各个维度占比的变化。这个case下,虽然IOS和安卓它在前后两天数据是有下降,但是他们的占比并没有下降。而当我们按照渠道这个维度下钻的时候,发现百度和头条这两个渠道,它的占比发生了明显的变化,所以就能够定位出是头条这个维度的数据异常造成了整个指标的异常。
所以我们的解决方案就是去自动的遍历各个维度,并且去分析各个维度的占比变化,从而定位到造成这个异常变的化真正原因。前面还提到了,在这种点击率指标发生异常的情况下,我们只是分维度看还不够,还要看每一个维度的投放量。那抽象来看,就是在面对a 除以b 这种分子除以分母类型的指标情况下,通常是ctr、cvr这类指标。我们除了要去考虑各个维度,还要去考虑分子和分母占比的变化,这样才能够真正的定位到这个数据异常的原因,这是我们维度下钻的思路。
在异常用户这块,我们会做一个假设,假设用户的行为次数是服从正态分布的。对每个指标的情况,我们去做每个用户次数的正态分布建模。这样我们就能建模出发生这些用户次数的概率,从而找到造成这次指标异常的用户。
对于a除以b这一类型的指标,像ctr或者cvr这类的指标,我们也要去考虑到分子和分母的分布。举个例子,比如ctr 有一个异常的下降,如果是因为某一两个作弊的用户他在狂刷,狂刷曝光但是又不点,造成ctr下降的话,那就要去看这些用户点击量和曝光量分别是什么,需要去看它的曝光量发生了异常,才能定位到这个异常的真正原因。这个就是我们在数据发生异常之后去做自动诊断所采用的方法。
04 挑战和todos
最后给大家分享一下我们在这块遇到的一些问题和或后续的一些改进计划。我们面临的第一个问题就是报警的误报率和漏报率的一个权衡。虽然采取了一种智能的预警的方式,但是仍然存在误报率和漏报率的权衡。那么后续我们也是希望在产品上能够让用户可以配置的功能,用户是想少一些误报,还是少一些漏报,相应的去体现到算法的灵敏程度上,去解决这方面的问题。
另一方面问题就是算法的通用性和准确性的问题。在测算法里面,我们通常会面临训练数据是有很多异常数据的。如果我们想要这个算法非常的通用,就需要有通用的数据异常识别的方法。如果我们想要一些追求准确性的话,其实加入一些业务知识是能够比较好的去识别异常数据的,但是又会牺牲一定的通用性。所以在这块我们后续也考虑在产品上加入一些用户权限可标识异常数据。
还有一方面挑战是来自诊断算法。前面也提到了,我们假设所有的数据异常都存在各个维度和属性当中。那如果这个客户没有去做很好的数据采集,那我们面临的情况就是巧妇难为无米之炊,无从下手,所以我们这个方法的前提就是要做比较全面的数据采集。
最后一点就是我们在整个过程中,不管是在做的智能预警这个功能和产品,或是Lookalike,还是我们在整个2B场景下构建所有的智能和机器学习产品功能其实都面临同一个问题,就是参数的选择的问题。在c 端的场景下,或者在具体业务场景下,这可能不是一个问题。因为算法工程师在过程中就会自动的去做参数选择的工作。但是在2B场景下,我们期望能够有一个通用的方法去做自动的参数选择,这样就能避免去做很多参数写死或是手动调参的工作。在这块,神策也是开始探索自动调参、自动机器学习的实践。
总结一下,今天主要跟大家分享了在数据指标的预警这块,我们面临的问题。首先跟大家介绍了我们的业务背景,以及设计的产品功能和解决方案,重点分享了在这块的技术方案。第一方面是怎么去做指标的实时预测,我们把一个报警指标的问题转化成为一个指标预测的问题。第二方面就是我们是怎么去做异常指标的自动分析和诊断的,最后跟大家分享了下我们现在面临的挑战。