分享

Spark 高级分析:第三章第6,7节

feilong 2017-12-15 09:36:50 发表于 连载型 [显示全部楼层] 回帖奖励 阅读模式 关闭右栏 0 5679
本帖最后由 feilong 于 2017-12-15 21:37 编辑

问题导读

1.如何评估推荐质量?
2.评估模型时是否会将数据集作为一个整体作为输入?
3.什么是AUC?如何计算?






上一篇:Spark 高级分析:第三章第4,5节
http://www.aboutyun.com/forum.php?mod=viewthread&tid=23482&extra=


6. 评估推荐质量
有理由假定用户倾向于播放有吸引力的艺术家的歌曲,而不是播放那些没有吸引力的艺术家的歌曲。因此,用户的播放给出了什么是“好”的推荐和“坏”的推荐。这是一个不确定的假设,但是是没有其他数据可以做的最好的假设。例如,假设用户2093760喜欢的比上面列出的五个艺术家还要多,而且是在其他170万个没有播放的艺术家中,有一些是感兴趣的,并不是所有的都是“坏”的推荐。
为了使这一点有意义,一些艺术家的播放数据可以被搁置并隐藏在ALS模型构建过程中。然后,这个数据可以被解释为对每个用户的“好”推荐集合,但是推荐者还没有被给出。推荐者被要求对模型中的所有项目进行排名,并对被调查的艺术家的排名进行检查。理想情况下,推荐者将它们全部放在列表的顶部或附近。

这个度量直接关系到信息检索的概念,即接收者操作特征(ROC)曲线。上面的度量等于ROC曲线下的面积,也就是曲线下面积AUC。AUC可以被看作是随机选择的“好”艺术家高于随机选择的“坏”艺术家的概率。

其他系统级相关的评价指标是在RankingMetrics中实现的。这些指标包括精度、召回率和平均准确率(MAP)。MAP也会经常用到,而且更侧重于顶层推荐的质量。然而,AUC在这里将作为整个模型输出质量的一个常用且广泛的度量方法。

事实上,在机器学习的过程中,经常要保存一些数据来选择模型并评估其准确性。通常,数据被分为三个子集:训练集、交叉验证(CV)和测试集。为简单起见,在最初的示例中,只使用两组:训练集和CV。这就足够选择一个模型了。在下一章中,这个想法将被扩展到包含测试集。

7. 计算AUC
本手册附带的源代码中提供了AUC的实现。它很复杂所以没有在这里复制,但是在源代码中的注释中有详细的解释。它接收CV集作为每个用户的“积极”或“优秀”的艺术家,以及一个预测功能。这个函数将每个用户艺术家的组合转换成一个包含用户、艺术家和一个数字的预测,其中值越大意味着建议级别越高。

为了使用它,输入数据必须被分割成一个训练集和CV集。ALS模型只在训练集上进行训练,而CV集用于评估模型。在这里,90%的数据用于训练,剩下的10%用于交叉验证:
[mw_shl_code=scala,true]def areaUnderCurve(
positiveData: RDD[Rating],
bAllItemIDs: Broadcast[Array[Int]],
predictFunction: (RDD[(Int,Int)] => RDD[Rating])) = {
...
}
val allData = buildRatings(rawUserArtistData, bArtistAlias)
]val Array(trainData, cvData) = allData.randomSplit(Array(0.9, 0.1))
trainData.cache()
cvData.cache()
val allItemIDs = allData.map(_.product).distinct().collect()
val bAllItemIDs = sc.broadcast(allItemIDs)
val model = ALS.trainImplicit(trainData, 10, 5, 0.01, 1.0)
val auc = areaUnderCurve(cvData, bAllItemIDs, model.predict)[/mw_shl_code]
注意,areaUnderCurve()接受函数作为其第三个参数。这里predict()方法从MatrixFactorizationModel被传入,但很快就会换出另一种方法。

结果是0.96。这是好的吗?它肯定比随机推荐的0.5要高。它接近1.0,这是最大可能的分数。一般来说,AUC超过0.9将被认为是高的。

这种评价可以反复用不同的90%作为训练集,所得的AUC值的平均值可能是对算法在数据集上性能的更好估计。事实上,一个常见的做法是将数据划分为k大小相似的子集,利用k - 1子集在一起训练,并评估剩余子集。这可以重复k次,每次使用不同的子集。这被称为k -折叠交叉验证。为了简单起见,这里的示例将不会实现这一点。

用更简单的方法来衡量这一点是很有帮助的。例如,考虑向每个用户推荐全球最受欢迎的艺术家。这不是个性化的,但很简单,而且可能很有效。定义这个简单的预测函数并评估其AUC分数:
[mw_shl_code=scala,true]def predictMostListened(
sc: SparkContext,
train: RDD[Rating])(allData: RDD[(Int,Int)]) = {
val bListenCount = sc.broadcast(
train.map(r => (r.product, r.rating)).
reduceByKey(_ + _).collectAsMap()
)
allData.map { case (user, product) =>
Rating(
user,
product,
bListenCount.value.getOrElse(product, 0.0)
)
}
}
val auc = areaUnderCurve(
cvData, bAllItemIDs, predictMostListened(sc, trainData))[/mw_shl_code]
这是Scala语法的另一个有趣的示范,在这里,函数似乎被定义为包含两个参数列表。调用函数并提供前两个参数创建一个局部应用函数,它本身需要一个参数(allData)来返回预测。结果predictMostListened(sc,trainData)是一个函数。

结果是0.93。这表明非个性化的建议已经相当有效。很高兴看到,到目前为止构建的模型打败了这种简单的方法。但能做得更好吗?


没找到任何评论,期待你打破沉寂

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

推荐上一条 /2 下一条