【王喆-推荐系统】评估篇-(task1)离线评估方法

举报
野猪佩奇996 发表于 2022/01/23 01:50:41 2022/01/23
【摘要】 学习总结 (1)五种主流的推荐模型离线评估方法:Holdout 检验、交叉检验、自助法、时间切割和离线 Replay。Holdout 检验最简单常用,它通过随机划分的方式把样本集划分成训练集和测试集。而...

学习总结

(1)五种主流的推荐模型离线评估方法:Holdout 检验、交叉检验、自助法、时间切割和离线 Replay。Holdout 检验最简单常用,它通过随机划分的方式把样本集划分成训练集和测试集。而交叉检验的评估效果更加稳定准确,它通过划分样本集为 k 份,再进行 k 次评估取平均的方式得到最终的评估指标。

(3)自助法 B o o t s t r a p Bootstrap Bootstrap 是为了解决样本量过少而提出的,它可以通过有放回采样的方式扩充训练集,但有改变数据本身分布的风险。而时间切割法在某个时间点上把样本分成前后两份,分别用于模型训练和评估,避免引入未来信息。最后是离线 Replay,它通过仿真线上模型更新过程来进行评估,是最接近线上环境的离线评估方法,但实现起来比较复杂。

在这里插入图片描述

推荐系统模型,如DIEN模型的效果是如何评估的,如何根据效果评估结果来更新模型,本次task学习的是最常用的评估方法——离线评估。

离线评估:将模型部署于线上环境之前,在离线环境下进行的评估。
优点:由于不用部署到生产环境,“离线评估”没有线上部署的工程风险,也不会浪费宝贵的线上流量资源,而且具有测试时间短,可多组并行,以及能够利用丰富的线下计算资源等。

一、离线评估的主要方法

离线评估:在离线环境下,将数据集分为训练集和测试集,测试集用于评估。

常用的离线评估方法主要有五种,分别是:Holdout 检验、交叉检验、自助法、时间切割、离线 Replay。

1.1 Holdout 检验、交叉检验和自助法

(1)Holdout检验

Holdout检验是最基础、最常用的。
将原始的样本集合随机划分为训练集和测试集。
(1)ex:对于一个推荐模型,我们可以把样本按照 70%-30% 的比例随机分成两部分。其中,70% 的样本用于模型的训练,30% 的样本用于模型的评估。

(2)Holdout的缺点:评估的结果有一定随机性,所以如果只进行少量的 Holdout 检验,得到的评估指标会存在一定的波动。那为了消除这种随机性,我们就要使用“交叉检验”的方法。

(2)交叉验证

先将全部样本划分成 k 个大小相等的样本子集,然后依次遍历这 k 个子集,每次把当前遍历到的子集作为验证集,其余所有的子集作为训练集,这样依次进行 k 次模型的训练和评估。

最后,我们再将所有 k 次评估指标的平均值作为最终的评估指标。在我们的实践中,k 经常取 10,也就是依次进行 10 次检验然后取指标均值。

小结:Holdout和交叉验证都是基于划分训练集和测试集的方法进行评估。但如果样本规模较小,这样划分会使训练集进一步减小。为了维持训练样本的规模,可以使用【自助法】。

(3)自助法Bootstrap

自助法(Bootstrap)是基于自助采样的检验方法。

它的主要过程是:对于总数为 n 的样本集合,我们先进行 n 次有放回地随机抽样,得到大小为 n 的训练集。在 n 次采样过程中,有的样本会被重复采样,有的样本没有被抽出过,我们再将这些没有被抽出的样本作为验证集进行模型验证。

自助法的缺点:
改变了原有数据的分布,有可能让模型产生一定程度的偏差。至于,到底是自助采样增加训练样本规模的收益大,还是数据分布被改变带来的损失大,这就需要我们在实践中进行验证了。

1.2 时间切割

未来信息:如果我们在 t 时刻进行模型预测, t+1 时刻的信息就是未来信息。
在构建特征工程时,要避免引入未来信息。
缺点:整个评估过程是静态的,模型不会随着评估的进行而更新。

在模型评估时,要避免训练集中包含“未来”样本。
比如,我们所有的样本数据分布在 t0到 tn这样的时间轴上,如果训练样本是通过随机采样得到的,那么训练数据也会分布在 t0到 tn上,同样,测试数据也会分布在 t0到 tn上。

为了防止信息穿越引起的模型“作弊”现象,可以使用时间分割方案,去划分训练集和测试集。
ex:一共处理了30天的样本,前25天的样本划分为训练集,后5天的样本作为测试集。
一般控制训练集和测试集的比例在3:1到10:1之间。比例太小则训练样本不够,比例太大则结果不够稳定。

1.3 离线 Replay

时间分割方法的缺点:整个评估过程是静态的,模型不会随着评估的进行而更新。如刚才的栗子,用前25天数据作训练集,如果在生产环境中,模型是日更新的,那么最后5天的评测过程就不准确,因为在离线测试中,我们并没有在后5天的评测过程中做到日更模型

离线 Replay:在离线状态下对线上更新过程进行仿真,让整个评估过程“动”起来。
在这里插入图片描述

图1 静态时间分割评估与动态Replay评估 (出自《深度学习推荐系统》)

从上图对比中看出,“Replay 评估方法”先根据产生时间对测试样本,由早到晚地进行排序,再让模型根据样本时间的先后进行预测。在模型更新的时间点上,模型需要增量学习更新时间点前的测试样本,更新模型后,再继续评估更新点之后的样本。

Replay 评估的过程更接近于真实的线上环境,因为它在线下还原了模型在线上的更新、预估过程。这也让 Replay 方法的评估结果更加权威可信。

缺点:因为它需要在评估过程中不断更新模型,这让评估过程的工程实现难度加大,因为包含了模型训练的时间,所以整个评估过程的总时长也会加长,影响评估和调参的效率。
小结:需要我们根据业务场景,对准确率性和评估效率进行权衡。

二、基于 Spark 的离线评估方法实践

无论是基于 Python 的 TensorFlow 还是基于 Scala 的 Spark,都有很多支持离线评估的库,本次task用 Spark 进行实践,主要是因为在业界数据集很大的情况下,Spark 在分布式环境下划分训练集和测试集的效率是最高的。

下面学习如何使用 Spark 实现 Holdout 检验、交叉检验和时间切割评估法。(另外两种方法,由于自助法不太常用,离线 Replay 又涉及过多的附加模块)。

2.1 Holdout 检验

利用 randomSplit 函数把全量样本 samples 按比例分割成 trainingSamplestestSamples。在 Spark 的后端,这个 randomSplit 函数会在各个节点分布式执行,所以整个执行效率是非常高的。
源代码参考: com.wzhe.sparrowrecsys.offline.spark.featureeng.FeatureEngForRecModel 中的 splitAndSaveTrainingTestSamples 函数。

val Array(trainingSamples, testSamples) = samples.randomSplit(Array(0.9, 0.1))

  
 
  • 1

2.2 交叉检验

3个关键参数:
一是 setEstimator,这是我们要评估的对象,它需要把我们构建的模型 pipeline 设置进去;
二是 setEvaluator,它用来设置评估所用的方法和指标;
三是 setNumFolds,它设置的是交叉检验中 k 的值,也就是把样本分成多少份用于交叉检验。

本质上 Spark 的 CrossValidator 其实是通过交叉检验来选择模型的最优参数,但也可以通过模型中 cvModel.avgMetrics 参数查看模型的评估指标。

val cv = new CrossValidator()
  .setEstimator(modelPipeline)
  .setEvaluator(new BinaryClassificationEvaluator)
  .setEstimatorParamMaps(paramGrid)
  .setNumFolds(10)  // Use 3+ in practice
val cvModel = cv.fit(training)

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

2.3 时间切割评估法

最高效方法,用where语句根据样本的时间跨度,将训练集和测试集分开,不用专门判断切割点。

如果你不知道样本的时间跨度,就要按照时间求取样本的分位数。
具体来说就是,通过 Spark 的 approxQuantile 函数,我们可以找到划分样本集为 8:2 的训练集和测试集的时间戳的值。那么接下来我们根据这个值通过 where 语句划分就可以了。我把这个过程的关键代码贴到了下面,供你参考。

代码参考: com.wzhe.sparrowrecsys.offline.spark.featureeng.FeatureEngForRecModel 中的 splitAndSaveTrainingTestSamplesByTimeStamp 函数。

//找到时间切割点
val quantile = smallSamples.stat.approxQuantile("timestampLong", Array(0.8), 0.05)
val splitTimestamp = quantile.apply(0)
//切割样本为训练集和测试集
val training = smallSamples.where(col("timestampLong") <= splitTimestamp).drop("timestampLong")
val test = smallSamples.where(col("timestampLong") > splitTimestamp).drop("timestampLong")

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

三、作业

离线 Replay 这个方法,跟之前讲过的增强学习有什么相似之处吗?它们两个还有什么更深层次的关系吗?

【答】离线Replay和RL都是动态更新模型的,都需要不断的测试和再训练模型。增强学习(如DRN)是通过不断接受反馈,在线更新模型的,所以评估方法不能引入未来信息,而简单的时间切割评估方法又不能模拟模型的更新频率,所以离线Replay是增强学习的唯一离线评估方法。

四、课后答疑

(1)在交叉检验的例子中,因为是使用的spark,那模型也必须是用spark实现的模型吧?那如果是tf实现的模型,该怎么做交叉检验呢?
【答】示例代码中是spark的交叉验证代码,并不支持tf模型。如果确实需要的话,需要根据交叉验证的思想自己实现。

(2)如果模型用early_stop来调整训练轮数,需要单独拿1天数据当验证集吗,然后测试集是验证集后一天的数据。就是想问上线之后每天跑是否也需要有“验证集”的概念?
【答】没有绝对,但early stop最好是有验证集,通过验证集来确定训练收敛的轮数,上线之后一般可以确定训练轮数来避免一些不可控的问题。

Reference

(1)https://github.com/wzhe06/Reco-papers
(2)《深度学习推荐系统实战》,王喆

文章来源: andyguo.blog.csdn.net,作者:山顶夕景,版权归原作者所有,如需转载,请联系作者。

原文链接:andyguo.blog.csdn.net/article/details/121241866

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。