(点击放大图像)
众所周知,数据科学的目标是从大数据中创造价值。然而,数据科学也应该满足第二个目标即避免信息过载。一个典型的可以满足这两个目标的系统就是推荐引擎。不仅是像Amazon这样的网上商店,同样的还有流媒体服务如Netflix公司也遭到了信息过载的困扰。客户可能很容易迷失在其庞大的(百万)产品或电影中。推荐引擎通过呈现给用户可能的选择帮助用户从繁多的产品中缩小选择范围。当然这些推荐引擎可以随机的展现给用户一些可能的选择,但这并没有真正降低信息过载。因此,这些推荐引擎通过应用统计科学来给用户展现更匹配他们期望的结果。例如,一个观看了《Frozen》的Netflix用户会从Pixar看到类似的儿童电影推荐结果。
(点击放大图像)
在接下来的一系列三篇博客中我们将详细的说明如何为"The Marketing Technologist (TMT)"的读者构建一个推荐引擎。TMT目前拥有超过50个类别的文章,覆盖了众多类别的主题,从数据科学到ReactJS编程。浏览完网站上所有的文章是非常耗时的,尤其是在文章的数量一直增长的情况下。同时读者很可能仅仅对他们所熟悉的领域的文章感兴趣。如果一个推荐引擎能够筛选出用户感兴趣的文章,那么它就可以被认为是能从数据中创造价值并避免信息过载的那一类系统。
两种类型的推荐系统
粗略地讲,我们可以将推荐引擎划分为两种类型:协同过滤和基于内容的推荐。就像维基百 科说的:协同过滤是一个使用涉及多个代理,观点和数据源之间的协作技术模式来过滤信息或模式的过程。在TMT案例中,这意味着在多个读者中找到一些规律。如果一群读者对特定系列中的文章感兴趣,当一个读者开始读这个系列中的一篇文章,那么他有很大的概率会对这个系列中的其他文章感兴趣。因此,可以基于其他用户的阅读行为来给类似的用户进行推荐。
基于内容的推荐引擎是不同的,因为它们是以产品的属性进行推荐。在我们的案例中产品就是TMT的文章,属性则是文章中的关键字。如果一个用户在读的文章中包含'Google Analytics'和'Tag Manager'的关键字,那么这个用户很有可能也喜欢包含这些关键字的其他文章。因此,基于内容的推荐引擎会推荐包含这些关键字的文章。值得注意的是最近从"Geek"到"The Marketing Technologist"的升级中,一个非常简单的基于内容过滤推荐方法被集成到TMT中。就是在每篇文章的下面有5篇其他相关的文章展示给用户供他们继续阅读。推荐的文章就是包含用户在读文章中任意一个标签的最新发表的5篇文章。在这个简单的例子中,标签可以当作产品的一个属性。
(点击放大图像)
协同过滤和基于内容的推荐背后的原理(图标来自于www.flaticon.com的Freepik)
这两类系统各有利弊。基于内容的推荐系统将推荐的文章限定在基于一组特征类似的文章中。例如,在给包含'Google Analytics'这样具体特征的文章进行推荐的时候会在其他文章中查找类似的关键字。然而,一个包含类似的分析工具'Snowplow'这样具体特征的文章,却不太可能被推荐出来。实际上用户可能对这两类文章都感兴趣,因为他们都属于分析这个主题。因此,基于内容的推荐系统并不善于发现隐藏的模式。协同过滤推荐系统在寻找隐藏模式这点上是优于基于内容的推荐系统。协同过滤着眼于用户的阅读行为,不专门关注用户阅读文章的内容。所以如果一个用户阅读了关于数据科学和转化率优化(CRO),尽管那些CRO的文章的内容和数据科学是截然不同的,协同过滤推荐系统也会向数据科学的读者们推荐关于CRO的文章。协同过滤的最大的缺点是,它需要大量的历史用户阅读行为数据,以便找到这些模式。基于内容的推荐可以在不给或者少量的历史数据的条件下完成,因此更容易实现。
协同过滤推荐系统的准备前提
在接下来的两篇博客中,我们将会实现一个基于内容推荐系统和基于协同过滤算法的推荐系统,并分析推荐结果。然而,为了能够实现目标,我们首先需要准备一些前提物料。对于协同过滤推荐系统这意味着我们需要实现得到用户阅读文章行为的方法。我们的同事Erik Driessen已经实现了通过使用谷歌分析(Google Analytics)并且分配客户端ID来记录用户阅读行为的方法。Simo Ahava在他的博客《在谷歌分析中存储客户端ID》解释了如何有效的实现它。
此外,由于Erik已经在文章的内容上增加了'Enhanced Ecommerce'插件,这样我们就可以追踪到用户是否完整的阅读了这篇文章。最后,在谷歌分析中可以创建自定义报表,展示客户端ID和他们已经阅读过的文章。
需要注意的是,目前跨设备的解决方案尚未实现。因此,如果用户使用不同的设备继续阅读文章或着中间清除了cookie,后续的行为将不能和他前期的阅读行为联系起来。
(点击放大图像)
谷歌分析中一个自定义的用户层面的阅读行为报表示例
基于内容的推荐系统的准备前提
在基于内容的推荐中,显然我们会需要所有TMT文章内容。有多种实现的方法。其中的一个将是直接从数据库中提取这些文章的文本。然而,因为我们是Geek,通过编写一个Python脚本,可以自动检索文章和相应的指标如作者和类别,这将是一件更酷的事情。因此,我们创建了从TMT网站复制文章的Python脚本,具体分为两个步骤。步骤1和步骤2的代码在这里(注:英文原文并未给出链接)。
步骤1: 创建一个TMT全量文章的列表.
可以使用Python的urllib2
库加载网页源代码。用urllib2.urlopen("http://www.themarketingtechnologist.co")
这个命令可以加载我们自己TMT博客的前端页面的源代码。这个首页总是展现最新发表的10篇文章。使用BeautifulSoup库,我们可以很容易通过在DOM中搜索并提取所有带class ="post"
的article
元素,并将它们存储在一个Pandas dataframe中。此外,在每个这样的元素内部,我们还可以通过搜索相应的DOM元素来提取作者和标签等元素。
因为只有十篇最新的博客文章在首页显示,为了获取更多博客文章,我们还需要检查在页面底部是否有Older posts >
按钮。同样的,可以通过搜索相应的DOM元素,如class="older-posts"
来完成。在更早博客文章区块中可以通过使用get
函数从href
属性值中提取到下一个页面的链接。在每个页面上我们重复上述过程。最后,我们将得到一个包含所有文章的名称、标签、作者和指向文章内容链接的数据帧。
步骤2:检索每篇文章内容
在步骤1中,我们保存了一个到每一篇文章的链接,所以我们可以下载每篇文章的全部内容。但是存在一个特殊的问题,即每篇博客文章的内容是通过JavaScript加载的。因此,如果我们使用的urllib2
加载文章的静态资源,我们将无法得到文章的内容。为了执行JavaScript代码来加载文章内容,我们实际需要通过Web浏览器进行渲染出文章的内容。幸运的是,这可以通过使用流行的Selenium
库来达到目的。使用Python的几行代码并结合Selenium
库可以打开Firefox浏览器,定位到相应的URL并渲染页面。然后就可以在DOM中搜索我们想要的信息,例如博客文章的内容。
需要注意的是,因为使用Selenium
执行所有的JavaScript代码,这也意味着谷歌分析的代码也会被执行。因此,明智的做法是采取措施防止产生脏数据。例如,在GA过滤器列表加入您的IP地址或者通过谷歌安装Google Analytics Opt-out Addon
插件。还要注意的是,实际上并不需要在Firefox浏览器中把每个渲染出来页面呈现在我们面前。你也可以使用一个轻量级的驱动程序,如PhantomJS
这使得可以在后台渲染页面而减少视觉上额外的开销。
这就是截至到现在建立推荐系统需要的准备前提。在接下来的几个月中,我们需要收集协同过滤模型中用到的用户层面的阅读行为。因此,在下面的博客文章中,我们先开始创建一个基于内容的推荐系统,并分析其结果。
这是在推荐引擎系列中的第一篇文章。
继续阅读该系列的第二篇文章:博客推荐系统:基于内容相似性的推荐(第二部分)。
查看英文原文:A recommendation system for blogs: Setting up the prerequisites (part 1)