简单的协同过滤推荐-spark

最近才开始接触spark的相关内容,根据老师的需要做一个关于spark streaming的协同过滤推荐。中间也遇到很多问题,也很困扰,希望有大牛能给予指导~

一.Userbased Recommdation--spark streaming

基于用户的协同过滤推荐

 

本次试验是使用spark streaming操作基于用户信息的去做的推荐。

试验数据1.training.txt  110M左右,包含所有用户的信息,数据内容:

Userid,itemid,ratings

(为了方面处理可以将每个相同的用户id合并,成userid@itemid:rating,itemid:rating。。当然这是另一种处理方式,可以节约内存的开销)

2.test.txt测试集包含了要处理的所有用户,数据格式:

Userid,itemid,rating

。。

这里主要使用的主要是userid,itemidRating的使用是在后面计算RMSE标准误差,RMSE越小则表明预测的结果越精准,本次试验的RMSE0.6~0.7之间。。。具体我忘了。

3.TrainingTest.txt根据测试集的用户id从训练集中提取出来之后的数据,可以方便我们很快的获取到要计算的用户的评价信息。

 

步骤:

1.将test.txt文件作为streaming不断读取的流。(假设这个文件在不断的更新神马的。。)在调用spark给的读取本地文件流的时候老是读取为空,所以使用了一个信息的读取方式:

 

使用的类需要去继承:

org.apache.spark.streaming.receiver.Receiver<String>这个类

 这个图怎么贴不上去。。

 private void receive(BufferedReader reader) throws IOException {
String userInput="";
try {
for(int i=0;i<sendquantity;i++){
String str =reader.readLine();
// while(str== null)
// {
// System.err.println("over the test");
// System.exit(1);
// }
userInput = str;
store(userInput);}


} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}  
}

代码大致是这样,在git上好像有个类似的项目。

将读取的每行存储到store中。

2.然后打开receive.onstart(),利用JavaReceiverInputDStream<String> lines = jssc.receiverStream(r);去接受这个存储在store中的信息。本次试验用的是java写的,所以调用的是java api当然scala也是相似的。

3.逻辑阶段map:在每个子节点读取training集合,在map阶段读取。。首先我们去找这个在training中这个用户是否对指定的itemid进行了评价?如果评价了就找这个用户和测试用户评价的交集,如果有,那么计算出两个用户的相似度,这里使用Pearson相似度来算。将相似度和给Item评分与当前用户的平均分的差存到一个新的list中。

4.处理list,在处理的过程中对pearsondiffave进行处理。得出最后的得分。

注意这里不使用reduce了,可以省去shuffle的时间,不过不知道这个想法对不对。

他妹的,我用saveastextfile这个借口好像也不行,估计是脸丑。。所以用Java api进行处理存储文件

最后 jssc.start(); jssc.awaitTermination()一个是打开streaming进行处理,一个是等待处理结果结束。

 

大致就是这个思维。


二.ItemBasedRecommdation

基于物品的协同过滤推荐---spark streaming

 

其大致都和userbased的相似,所以就主要写关系算法的内部实现过程:

1.找到要评分的用户看他评价了哪些商品,将商品记录下来,然后在遍历training的过程中找到一一对应的Itemid,记录打分,

2.算两个item的相似度,就是要评价的item和这个用户打分的item的相似度。这个相似度作为一个权值,去乘以已知的打分。最终加权平均求得最后的打分。

 

 

在这我也没有使用reducebykey的方法,省去shuffle不知道能不能节约时间

那么问题来了。。。:

问题1

我存储training集合的数据结构是

Hashmap<itemid,String>

String是代表useid:ratinguseridrating。。。。形成一个String

 

我试过使用hashmap<itemid,hashmap<userid,rating>>这样的存储结构,但是哈希表的数据结构开辟的过大,开始使用512m的内存一直出现GC LIMIT, JAVA heap什么错误。不过这样的数据结构能节约很大一部分时间。

 

还有一个问题一直困扰着我,就是在spark streaming中不断的发送数据,处理之后的那些RDD是不是一直被CACHE在内存中?我的GC Limit报错出现在用

hashmap<itemid,hashmap<userid,rating>>这种结构去load 大的训练集出现的。不知道是怎么回事?

我使用的是2G,8G都出现了内存出错,应该不是内存太小的问题吧?


问题2 我在用spark去计算每个节点下用户的平均数的时候,使用hashmap<itemid,hashmap<userid,rating>>这种存储结构可以很顺利的load进比较大的数据集。但是在map阶段处理的时间实在无法忍受,用10M的文件(文本文件一共9行每行差不多50W个用户,用split去划分的)去遍历一个training的时候居然要用近一天半的时间才能处理好。。好无语。。我一直以为代码跑死了。。。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值