您的位置:首页 > 其它

Mahout in action 中文版-2.推荐器的介绍-2.3~2.6

2014-01-02 10:05 561 查看


2.3 评估推荐器

推荐器是一个工具,它用来解决“如何为一个用户给出最好的推荐”这样的问题。在得出结果之前,最好先弄清楚问题。究竟怎样才是一个好的推荐结果?我们如何才能得出这样的结果?这一章剩下的部分将停下来探索推荐器的评估,因为这是用来了解特定推荐器的有力工具。

最理想的推荐器会像巫师一样某明奇妙的猜到你所喜欢的东西。它可能会知道你有多喜欢一个东西,甚至你都没有见过它或者从未表达过你是否喜欢它。一个推荐器能够精确的得出你对于每个项目的偏好指数,然后按照偏好指数排名罗列出来,这就是一个好的推荐。

确实,为一些或者全部的项目打分评级是推荐引擎常见做法。所以,评估推荐器的一种方案就是评估它所产生的偏好指数——也就是评估偏好指数与真实喜好程度的匹配程度。


2.3.1 训练数据与打分

那些所谓的“真实喜好程度”其实并不存在。没有人会知道它具体的值(包括你)。其实我们可以通过把真实数据中的一小部分当作测试数据(Testing Data)来进行模拟,剩下的则是训练数据(Training Data)。除了用来训练的偏好指数,其余的偏好指数都用来预测这些被去掉的偏好指数。

如此,为推荐器打分就变得十分简单了。例如,我们可以计算所有预测值和真实值差值的平均值。如果把这个当作分数来看,那么肯定是越低越好。因为越低意味着差异越小,当然0是最完美的——预测和真实无任何差异。

有时,这些差值的均方根也被利用起来,当然这个值也是越低越好。详情见下表:



表2.1 均差和钧方差试图

上表中显示了预测值和真实值的差异,以及这些差异如何转化为分数。均方差对出差错的项惩罚更加严厉,因为Item 2的存在。例如,Item 2的预测差了两个等级,那么均方差会去2的平方编程了4,而差了1则还是1。这样一下就差了2倍。由于简单的均差表达更为直接,在下一个例子中,我们还将使用它:


2.3.2 运行RecommenderEvaluator

清单2.3 推荐器评估程序的配置和运行

A 使用例子中的可重复数据

B 建立一个和上述一样的推荐器

C 70%的数据作为训练集;30%的数据作为测试集

大多数的处理过程发生在evaluate()这个函数当中。RecommenderEvaluator负责将数据分为训练集和测试集,用训练集构建一个DataModel和Recommender用来进行测试活动,得到结果之后在于真实数据进行比较。

需要指出的是,这个方法中不会有Recommender。这是因为,这个方法需要根据训练集产生的DataModel构造一个Recommender,所以调用者需要提供一个能够利用DataModel产生Recommender的对象——RecommenderBuilder。他的构造方法和我们之前提到的方法一样。


2.3.3 评估结果

这个程序打印出评估结果:用一个分数(数字)代表Recommender的性能如何。你会看到这个程序的结果为1.0。即使你多次的随机选取,结果依然如此,因为你所调用的 RandomUtils.useTestSeed()函数每次产生的随机数序列是一样的。它仅仅被用在这样例子或者单元测试中,因为我们需要保证结果的可再现性。但是千万不要把它用在你实际的代码中。

这个值的意义如何取决于它被用到什么地方——AverageAbsoluteDifferenceRecommenderEvaluator。本次结果1.0代表测试结果平均和真实结果相差1.0。

在1到5这样的范围中,平均相差1不算很多,但是我们的数据太少了。如果每次都进行随机的切分(三七分),那么每次得到的结果可能都不相同。

这种评估技术可以用于任何的Recommender和DataModel。如果您想使用均方差进行评估,那么就将AverageAbsoluteDifferenceRecommenderEvaluator替换为RMSRecommenderEvaluator。

DataModelBuilder可以控制DataModel从训练集中的建立。它可以作为evaluate()的参数替换掉上述的null。不过通常默认的就可以了,但是如果你自己使用了特定的DataModel,那就不可以替换成DataModelBuilder了。DataModelBuilder相当于是把训练集数据注入到评估过程的一个接口。

最后一个参数1.0控制了你要使用多少数据,这里它代表100%。如果你降低这个参数,可以更快的构建一个的精度的评估过程。比如你调成0.1,那么就用了10%的数据。这对于快速测试推荐器的微小的变化是十分实用的。


2.4 评估查准率(precision)和召回率(recall)

  我们可以从更广义的角度去看待推荐问题:它并不是严格的要去估计偏好指数来提供推荐结果,也不总是要向用户提供准确的偏好指数的值。很多时候,我们只需从好到坏列出推荐排序,事实上,有些时候我们只需列出很少一部分排名考前的就可以了。

这样来看,我们也可以利用经典的信息检索中的度量方法去评估分类器:查准率和召回率。这些术语被典型的用在搜索引擎之中。而且,搜索引擎正是为一个查询返回一些排名较好的结果。

一个搜索引擎虽然要尽量多的返回相关结果,但是一定不能在靠前的结果中返回一些不相干的结果。查准率描述的是在靠前的结果中相关结果所占的比例,我们说“10条结果的精度”就是说前十条之中正确结果所占的比例。而召回率描述的是在靠前结果中包含了多少应该出现的结果。看下面的示意图可以帮你大致的了解一下:



图2.3 上下文搜索中的查准率和召回率

这些术语很容易在推荐器上套用:查准率就是在靠前的推荐结果中准确的推荐结果所占的比例,召回率就是在靠前结果中准确的推荐结果在整个应该被推荐结果中所占的比例。在下一小节中我们将会更出更直观的解释。

清单2.4 查准率与召回率评估程序的配置和运行

A 前两条结果的查准率和召回率

如果不调用RandomUtils.useTestSeed(),那么结果将会随着每次对训练集和测试集的选择不同而发生微妙的变化,但是我们的测试程序数据很少,所以没有必要在用真正的随机函数。运行结果如下:

0.75

1.0

在前2条的结果中,查准率为0.75;平均看来有四分之三的结果是正确的。召回率为1.0;所有应该被推荐的结果都在结果之中。

但是,究竟什么才算应该被推荐的结果?其实这个框架下也没有一个合适的定义,直觉告诉我们,在测试集中偏好指数最高的那些项目肯定是最应该被推荐的,而其余的则不是。

清单2.5 测试集中用户5的偏好指数

  让我们来看看引擎为用户5的推荐结果,在想想对于101、102、103应该是如何推荐的。结果中显示三个项目的偏好指数分别是4.0、3.0、2.0。没错,三个项目的排序是没问题的,但是103应该被推荐吗?它可是最低的了,用户5貌似不是很喜欢103,而102也一般般。不过101但是很受5的喜爱,102、103是可以被推荐的,但是不是一个好的推荐。

  这个问题需要RecommenderEvaluator来解决。如果不给定一个确定的临界值,我们将无法知道那些是好的推荐那些是不好的推荐,而这个框架为每个用户提供了一个临界值。这个临界值的定义为用户平均的偏好指数加上一个标准差:

  如果你忘记了统计学的知识,不必担心。这一项不仅仅是比高一点点就行了,它需要加上一个很有意义的标准差。在实践经验中,一般推荐结果前16%的就算是较好的结果了,另外一个参数作用和之前讨论的差不多,您可以在相关文档中看到详细的信息。


2.4.2 查准率和召回率的一些问题

  查准率和召回率发挥作用的前提是如何定义什么才是“好”的推荐结果。在上面我们给出了一个临界值,或者说程序提供了这样的定义。

  另外还存在一个模糊的问题,推荐结果包含了一些用户已经表现出喜欢的项目。其实一个好的推荐应该把这些用户已经知道的项目去除掉在推荐出来。

  试想我们为一个喜欢法国信徒电影的用户做推荐,但是这种电影本身就很少。比如,我们为这个人推荐了一个电影,但是该电影几乎从来都没有人知道,那么这也不是一个好的推荐,虽然客观的讲这确实很了不起。一些好的推荐应该从所有其他用户已知的电影中选取。

  时候,偏好不能取值,或者说偏好是一些布尔的值,那么情况就会变得复杂一些了。在这里,偏好程度没有一个可比性(因为没有大小之分),所以在集合中我们选取一些应该被推荐的就可以了。

  查准率和召回率在测试环节也有某种用途。用户喜欢一个被推荐项目理论上可以认为是一个好的推荐,但是绝不能等同于是最喜欢的。然而,对于这种布尔型的偏好程度,你只能采取查准-召回的评估方法,均差和均方差都不能奏效。所以对数据的限制的理解还是十几重要的。


2.5 评估GroupLens的数据集

  有了前面的基础,我们不仅能够讨论推荐引擎的处理速度,也可以评估他的推荐质量。大数据的实验还在后面的章节之中,但是现在我们可以使用一些小的数据集来实战一下。


2.5.1 提取推荐数据

  GroupLens ( http://grouplens.org/ ) 是一个可以提供一些不同大小数据集的搜索项目,每个数据集来自于真实的用户对电影的评价。它是世界上可以获取真实数据的项目之一。本书后续还将继续使用它提供的数据。从GroupLens网站上下载“100K data set”,连接为 http://www.grouplens.org/node/73。解压你下载的数据,然后找到一个名为ua.base的文件,这个文件是一个标签化的文件,包括:用户ID,项目ID,等级(偏好指数)和一些附加信息。

  这个文件有用吗?里面只有标签,没有逗号隔开,而且每一行还包含了一些额外的信息。没错,这个文件需要配合FileDataModel对象才有意义。回到清单2.3,这里我们构建了一个RecommenderEvaluator,尝试把文件的路径改为ua.base的路径。在运行一下,这回大概需要几分钟的时间,因为它里面包含了100,000条数据。

  最后运行结果应该为0.9,不算很差,虽然在五个等级的情况下不是很理想。或许这个Recommender对象不是很适合这样的数据。


2.5.2 用其他的推荐器进行实验

  我们来用一个叫做“slope-one”的推荐器跑一下这个数据,它在即将来临的章节中讲到。只需替换一下RecommenderBuilder对象。把他替换成org.apache.mahout.cf.taste.impl.recommender.slopeone.SlopeOneRecommeder。就象这样:

清单 SlopeOneRecommender的评估程序

  重新跑一遍,你发现它同样很快,而且得到了一个0.748的结果。它已经比以前更准确了!

  这并不代表slope –one总是那么的快和准确。每一种算法都有自己的特点和属性去处理很困难的数据。Slope –one在运行时是比较快的,但是它需要一定的预处理时间。例如,基于用户的推荐器对于第一个例子中的数据处理的会很好。我们将在后续章节讨论每种算法的优点。它强调拿真实数据测试的重要性以及Mahout在处理这类问题是多么的轻而易举。


2.6 总结

  这一章我们介绍了推荐引擎的主要思想。我们还创建了一些输入数据用推荐器跑了一下,然后分析了他的运行结果。

  然后我们在推荐之前花了一些时间去分析推荐引擎的输出,因为我们将会在后续章节频繁的做这样的工作。这章也讲了如何利用差值去评估计算结果的精度,以及信息检索领域的查准率和召回率在评估中的应用。最后我们对GroupLens的推荐实例进行了评估,展示了如何以经验为主的去提高一个推进引擎的性能。

  在深入的学习推荐引擎之前,有一个重要概念是需要知道的,我们将在下一章介绍:数据表达(representation of data)。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: