android引入开源库
本系列的第1部分探讨了推荐系统使用的一些核心方法和特定算法。 本部分从描述推荐引擎的上下文开始。 然后,它向您展示了一些用于构建推荐系统的开源解决方案。 您将看到如何在Ruby中开发一个简单的集群应用程序并将其应用于第1部分中的样本数据。 然后,您将实验两个实现相似算法但使用明显不同方法的开源引擎。 最后,您将获得开放源域中可用的其他推荐器,机器学习和数据挖掘解决方案的概述。
推荐引擎对与服务的一组用户的行为有关的可用数据进行操作。 在大多数情况下,该服务是一个网站,向单个用户展示单个项目,并跟踪用户相对于这些项目的行为(例如,对其进行查看,购买和评级)。 这种数据构成使用基于用户或基于项目的协作筛选的推荐引擎的基本要求。
图1说明了推荐系统的简单生态系统。 生态系统包括:
- 少数用户
- 服务
- 区分服务中单个用户行为的能力(购买,视图等)
- 一种推荐引擎,用于计算和存储推荐的工件
图1.推荐系统的简单生态系统
接下来,我将介绍一个使用Ruby的简单集群实现。 实施组根据用户的个人行为将其视为用户。
集群化基于用户的协作过滤
回想一下, 第1部分探讨了由四个用户组成的简单群体中基于用户的协作过滤。 要在总体中提出建议,您必须首先根据这些用户的行为对其进行分类。 第一个示例通过简单的聚类算法k -means探索用户的分类。
从第1部分中您知道, k -means首先将项目随机分为k个簇。 然后,根据每个聚类的成员计算质心 。 然后,根据聚类的质心检查每个项目的距离。 如果发现某个项目更靠近另一个群集,则将其移至该群集。 每次检查所有项目时都会重新计算质心。 如果在迭代过程中没有任何项目移动,则算法结束。
图2显示了四个阅读博客的用户的样本数据集。
图2.用户博客阅读行为的样本数据
清单1显示了Cluster
类的Ruby实现,该类表示k -means算法的集群。
清单1.用Ruby编写的Cluster
类
class Cluster
# Initialize the class instance
def initialize
@people = Array.new
@vcentroid = Hash.new( "0" )
end
# Add a feature vector to the cluster
def add( person )
@people.push( person )
end
# Remove a feature vector from the cluster
def remove( person )
@people.delete( person )
end
# Return the cluster centroid
def get_people
return @people
end
# Calculate the centroid vector from the cluster members
def calculate_centroid
# Clear the centroid vector
@vcentroid.clear
tcentroid = Hash.new( "0" )
# Iterate through each feature vector
@people.each do |person|
# Sum the feature vectors in this cluster
person.each do |key,value|
tcentroid[key] = tcentroid.delete(key).to_i + value.to_i
end
end
# Compute the average for the centroid
tcentroid.each do |key,value|
@vcentroid[key] = value.to_f / @people.length
end
end
# Calculate the geometric distance
def calculate_gd( person )
gd = 0.0
person.each do |key,value|
gd += (@vcentroid[key].to_f-value.to_f) * (@vcentroid[key].to_f-value.to_f)
end
gd = Math.sqrt(gd)
return gd
end
end
Cluster
类包含作为数组的集群成员和作为哈希的集群质心(以博客名称为键,值作为查看的文章)。 initialize
方法同时创建数组和哈希。
三种方法管理集群的成员:
-
add
方法将一个person
添加到集群中。 -
remove
方法删除一个person
。 -
get_people
方法提取数组以进行迭代。
有两种方法管理集群。 calculate_centroid
方法根据聚类的当前成员calculate_centroid
更新聚类的平均值。 calculate_gd
方法返回簇质心和通过的person
对象之间的欧几里得距离。
清单2显示了对图2中的示例数据进行操作的k- means的Ruby实现。
清单2.实现基本的k -means算法
def kmeans
# Sample user hashes
marc = { 'linux' => '13', 'oss' => '10', 'cloud' => '6',
'java' => '0', 'agile' => '0' }
megan = { 'linux' => '3', 'oss' => '0', 'cloud' => '1',
'java' => '6', 'agile' => '7' }
elise = { 'linux' => '11', 'oss' => '0', 'cloud' => '9',
'java' => '0', 'agile' => '1' }
jill = { 'linux' => '0', 'oss' => '3', 'cloud' => '0',
'java' => '9', 'agile' => '8' }
# Define our two clusters and initialize them with two users
cluster1 = Cluster.new
cluster1.add(marc)
cluster1.add(megan)
cluster2 = Cluster.new
cluster2.add(elise)
cluster2.add(jill)
changed = true
# Repeat until no further membership changes occur
while changed do
changed = false
# Recalculate each cluster's centroid (mean)
cluster1.calculate_centroid
cluster2.calculate_centroid
# Get the membership of each cluster
people1 = cluster1.get_people
people2 = cluster2.get_people
# Check members of cluster 1 against the cluster centroids
puts "Checking cluster 1"
people1.each do |person|
if cluster2.calculate_gd(person) < cluster1.calculate_gd(person) then
puts "Feature vector moved from cluster 1 to cluster 2"
cluster1.remove(person)
cluster2.add(person)
changed = true
end
end
# Check members of cluster 2 against the cluster centroids
puts "Checking cluster 2"
people2.each do |person|
if cluster1.calculate_gd(person) < cluster2.calculate_gd(person) then
puts "Feature vector moved from cluster 2 to cluster 1"
cluster2.remove(person)
cluster1.add(person)
changed = true
end
end
end
puts
puts "Cluster 1 contains"
people = cluster1.get_people
people.each do |person|
person.each do |key,value| print "#{key}=#{value} " end
puts
end
puts
puts "Cluster 2 contains"
people = cluster2.get_people
people.each do |person|
person.each do |key,value| print "#{key}=#{value} " end
puts
end
puts
end
清单2首先将示例数据添加到集群中。 接下来,它计算每个聚类的质心(作为其成员的平均值),然后检查每个成员与两个聚类的距离。 如果成员距离其当前群集中的质心较远,则将其从其原始群集中移除,然后添加到另一个群集中。 检查所有成员后,您将重新计算质心并再次检查成员。 当没有进一步的更改发生时,该算法完成。
要将样本用户聚类为k = 2个聚类,请调用kmeans
方法,如清单3中的控制台会话所示。
清单3.运行简单的k -means实现
$ ruby kmeans.rb
Checking cluster 1
Feature vector moved from cluster 1 to cluster 2
Checking cluster 2
Feature vector moved from cluster 2 to cluster 1
Checking cluster 1
Checking cluster 2
Cluster 1 contains
cloud=6 java=0 linux=13 oss=10 agile=0
cloud=9 java=0 linux=11 oss=0 agile=1
Cluster 2 contains
cloud=0 java=9 linux=0 oss=3 agile=8
cloud=1 java=6 linux=3 oss=0 agile=7
$
该算法成功地将Marc和Elise聚类为聚类1,并将Megan和Jill聚类为聚类2。聚类完成后,推荐引擎可以使用聚类成员之间的差异来形成推荐。
自己动手做事并不是构建推荐功能的唯一选择。 接下来,我将深入探讨两个开源推荐引擎,并简要描述一些其他可用的开源解决方案。
建议和Top-N建议
SUGGEST是Top-N推荐引擎,实现为库。 SUGGEST(由明尼苏达大学的George Karypis开发)使用几种协作过滤算法,并实现了基于用户和基于项目的协作过滤。 可以在初始化特定数据集时指定算法。
数据通过一组用户项事务提供给SUGGEST。 在本文的示例中,数据代表每个用户已阅读的博客。 在更准确的模型中,您将显示各个历史交易,例如阅读的特定文章。 在这种情况下,我将使其保持简单,并继续使用现有数据集(四个用户,五个博客)。
SUGGEST公开了一个简单的API。 您只需要三个函数即可使用C编程语言构建推荐引擎:
-
SUGGEST_Init
加载历史交易记录,定义特定的推荐算法,并初始化推荐实例。 -
SUGGEST_TopN
基于传递的样本数据计算推荐。 -
SUGGEST_Clean
释放SUGGEST_Init
创建的推荐引擎实例。
第四个函数SUGGEST_EstimateAlpha
定义了基于概率的算法的最佳alpha值(如果使用了该算法)。
清单4给出了一个使用SUGGEST的简单推荐实现。
清单4.使用SUGGEST推荐引擎的示例应用程序(用C编写)
#include <stdio.h>
#include "suggest.h"
int nusers = 4;
#define MARC 0
#define MEGAN 1
#define ELISE 2
#define JILL 3
int nitems = 20; // Marc Megan Elise Jill
#define LINUX1 0 // 1 0 1 0
#define LINUX2 1 // 1 0 0 1
#define LINUX3 2 // 1 0 1 0
#define LINUX4 3 // 1 1 1 0
#define OSS1 4 // 1 1 0 1
#define OSS2 5 // 0 0 1 1
#define OSS3 6 // 1 0 1 0
#define CLOUD1 7 // 0 1 1 0
#define CLOUD2 8 // 1 1 1 1
#define CLOUD3 9 // 0 0 0 1
#define CLOUD4 10 // 1 0 1 1
#define CLOUD5 11 // 0 0 0 0
#define JAVA1 12 // 0 1 0 1
#define JAVA2 13 // 0 1 0 0
#define JAVA3 14 // 1 1 0 1
#define JAVA4 15 // 0 1 1 1
#define JAVA5 16 // 0 0 0 1
#define AGILE1 17 // 0 1 0 1
#define AGILE2 18 // 0 1 0 0
#define AGILE3 19 // 0 0 1 1
#define NTRANS 40
// Historical transactions of users and items.
int userid[NTRANS] =
{ MARC , MARC , MARC , MARC , MARC , MARC , MARC , MARC , MARC,
MEGAN, MEGAN, MEGAN, MEGAN, MEGAN, MEGAN, MEGAN, MEGAN, MEGAN, MEGAN,
ELISE, ELISE, ELISE, ELISE, ELISE, ELISE, ELISE, ELISE, ELISE,
JILL, JILL, JILL, JILL, JILL, JILL, JILL, JILL, JILL, JILL, JILL, JILL,
};
int itemid[NTRANS] =
{ /* Marc Blog Reads */
LINUX1, LINUX2, LINUX3, LINUX4, OSS1, OSS3, CLOUD2, CLOUD4, JAVA3,
/* Megan Blog Reads */
LINUX4, OSS1, CLOUD1, CLOUD2, JAVA1, JAVA2, JAVA3, JAVA4, AGILE1, AGILE2,
/* Elise Blog Reads */
LINUX1, LINUX3, LINUX4, OSS2, OSS3, CLOUD1, CLOUD2, JAVA4, AGILE3,
/* Jill Blog Reads */
LINUX2, OSS1, OSS2, CLOUD2, CLOUD3, CLOUD4, JAVA1, JAVA3, JAVA4, JAVA5, AGILE1, AGILE2
};
int main()
{
int *rcmd_handle;
int behavior[7]={LINUX1, LINUX2, LINUX4, OSS1, OSS2, CLOUD1, CLOUD3 };
int recommendation[2];
int result, i;
rcmd_handle = SUGGEST_Init( nusers, nitems, NTRANS, userid, itemid,
3, 2, 0.0 );
result = SUGGEST_TopN( rcmd_handle, 7, behavior, 2, recommendation );
if (result) {
printf("Recommendations (%d) are %d and %d\n", result,
recommendation[0], recommendation[1]);
} else printf("No recommendation made.\n");
SUGGEST_Clean( rcmd_handle );
return 0;
}
清单4首先定义了历史数据,并在两个数组( users
和items
)中进行了定义。 只要user [ index ]
定义了用户项目交易( users[0]
购买了items[0]
等),这两个数组就相关了。 为了简化和可读性,以用户项顺序定义数组。
在清单4的简短main
函数中使用了SUGGEST解决方案。 在那里,首先使用示例用户和项目数据(一起代表一组项目中多个用户的交易)初始化您的推荐人。 将user
和items
数组以及它们的限制和可能的值(用户和项标识符)传递到SUGGEST_Init
。 另外,指定基于项目的Top-N推荐算法(基于用户的Top-N和基于余弦的相似度函数)和推荐区域的大小。 接下来,在“购物篮”中填充各项以计算推荐请求,然后调用SUGGEST_TopN
来请求推荐。 最后,释放与推荐器关联的资源并退出。 请注意,在此示例中,该网站提供了20个文章,涉及五个主题,涉及四个用户的历史数据。
清单5中的控制台会话显示了示例SUGGEST推荐程序的执行。
清单5.使用示例数据运行SUGGEST推荐引擎
$ ./topn
Recommendations (2) are 2 and 8
$
在这种情况下,引擎建议特定的阅读器可能喜欢LINUX3和CLOUD2。 考虑到用户的先前行为以及该用户的观看频率,这些建议是合理的。 请注意,调用SUGGEST_TopN
的结果是推荐数组中推荐的数量。
SUGGEST是Top-N协同过滤算法的一种简单而有效的实现。
RESTful Web服务和easyrec
easyrec开源推荐引擎采用新颖的方法来构建推荐服务。 (easyrec由奥地利研究工作室通过奥地利联邦科学与研究部的资助开发和维护。)
easyrec公开了一种代表性状态转移(REST)接口,以将其与开发人员选择的语言完全分开。 这种方法增强了开发人员将服务与最终用户应用程序集成的能力,并提高了服务的可伸缩性。
easyrec API公开了一组丰富的RESTful接口,这些接口涵盖了推荐系统所需的所有可能操作,包括项目购买,查看和评级。 这些操作记录在easyrec数据库中。 通过一组特定的界面提供建议,例如“与给定项目的相关项目”,“其他用户也查看了这些项目”,“给定用户的特定建议”和“还购买了其他用户”。 这些基本推荐操作涵盖了许多预测方案中最常见的情况。 easyrec API支持XML和JSON进行响应。
现在,我将向您展示一个使用easyrec请求给定用户推荐的示例。 easyrec解决方案是作为一个软件包提供的,您可以将其集成到自己的设置中,但还可以使用演示服务器进行测试。 接下来,您将使用此服务器通过easyrec的测试数据来请求建议。
您可以使用清单6中的简单Ruby脚本来请求对指定用户的推荐。 用户和项目列表是在easyrec数据库中预定义的。 清单6定义了用于与远程Web服务进行交互的Ruby函数。 此函数将构建一个URL,该URL表示对easyrec的请求。 (在这种情况下, recommendationsforuser
是所请求的命令。)
清单6.与easyrec交互以获得建议的Ruby函数
#!/usr/bin/ruby
require 'rubygems'
require 'json'
require 'net/http'
def recommend_for_user( userid )
puts "Request for recommendations for user #{userid}"
apikey = "3d66b20f7cbf176bf182946a15a5378e"
request = "http://intralife.researchstudio.at:8080" +
"/api/1.0/json/recommendationsforuser?" +
"apikey=#{apikey}&" +
"tenantid=EASYREC_DEMO&" +
"userid=#{userid}&" +
"requesteditemtype=ITEM"
resp = Net::HTTP.get_response(URI.parse(request))
parsed = JSON.parse(resp.body)
parsed2 = parsed['recommendeditems']
parsed2['item'].each do |item|
puts item['description']
end
end
如清单6所示,除了REST名称空间和命令之外,您还定义了:
-
apikey
(使用来自easyrec网站的示例密钥) -
tenantid
- 推荐感兴趣的用户ID
您还可以指定对ITEM
类型感兴趣,以允许所有推荐的产品。 定义了统一资源标识符(URI)后,您将使用Ruby的Net:HTTP
客户端API发送请求并返回并存储响应。 解析此响应,然后在每个返回的项目上进行迭代。
清单7举例说明了在特定用户的交互式Ruby Shell(IRB)中对Recommendation_for_user recommend_for_user()
函数的使用。 在这种情况下,推荐包括基于该用户偏好的音乐选择。
清单7.使用easyrec提出建议
irb(main):027:0> recommend_for_user( "24EH1723322222A3" )
Request for recommendations for user 24EH1723322222A3
Beastie Boys - Intergalactic
Gorillaz - Clint Eastwood
irb(main):028:0>
清单7展示了easyrec提供的界面的简单性,可以用任何支持HTTP客户端和JSON或XML解析器的语言来实现。
其他开源产品
其他几个推荐程序解决方案或解决方案的元素也可以作为开源使用。 本节将探讨其中的一些产品。 (请参阅相关信息 ,这些和其他选项。)
镜头套件
LensKit(来自明尼苏达大学)是构建推荐系统的框架,通常用于研究协作过滤。 LensKit的目标是提供一种高质量的实现,该可读性和可读性可集成到Web应用程序中。
螃蟹
Crab推荐器引擎框架是为Python构建的,并使用了Python生态系统的一些科学计算方面,例如NumPy和SciPy。 Crab实现了基于用户和项目的协作过滤。 该项目计划在将来实现Slope One和奇异值分解算法,并最终使用REST API。
MyMediaLite
MyMediaLite是包含多个推荐系统算法的轻量级库,可用于开发推荐引擎。 MyMediaLite基于用户项评级反馈实现评级预测和项目预测。 该库是在Microsoft .NET平台上运行的C#中实现的(在Linux®中具有Mono支持)。
威化饼
Waffles是Mike Gashler在杨百翰大学用C ++开发的机器学习工具包。 Waffles构造了一组基于CLI的工具。 这些工具实现了包括推荐在内的用于机器学习的细粒度任务,从而支持以比API集成所需的更高级别编写脚本的机器学习任务的功能。 通过为可用任务包括大量参数,Waffles使操作可以根据当前任务进行微调。
杜安
Duine是来自挪威Telematica研究所的用于预测引擎开发的软件库。 除信息过滤外,Duine还使用Java™语言来实现协作过滤技术。 该框架的最后一次提交是在2009年,因此该项目现在可能处于非活动状态。
推荐实验室
Recommenderlab是R环境的协作过滤扩展。 Recommenderlab提供了用于研究和开发推荐系统的通用基础结构。 Recommenderlab环境有利于算法开发,评估以及多种算法之间的比较。
其他产品
开源域还有其他几种产品,可作为算法构建和评估的开发环境。 除许多其他方法和模型外,Shogun机器学习工具箱还专注于大规模内核方法(例如支持向量机[SVM])。 Milk是Python的机器学习工具包,其重点是监督分类方法(SVM,k-NN等)。 最后,Weka提供了用Java编程语言编写的数据挖掘软件。
结论
随着网络规模的扩大,个性化的推动继续在推荐引擎领域内产生新算法和丰富多样的解决方案。 在开源领域中,可以使用多种编程语言进行各种项目,从用于开发协作过滤算法的环境到用于算法评估的框架一直到功能全面的解决方案。
翻译自: https://www.ibm.com/developerworks/opensource/library/os-recommender2/index.html
android引入开源库