java和python实现一个加权SlopeOne推荐算法
一.加权SlopeOne算法公式:
(1).求得所有item之间的评分偏差
上式中分子部分为项目j与项目i的偏差和,分母部分为所有同时对项目j与项目i评分的用户数
(2).加权预测评分
项目j与项目i
上式中表示用户u对项目j的评分预测,分子为项目j对项目i的偏差加上用户对项目i的评分,cji表示同时对项目j与项目i评分的用户数
二.python实现
#!/usr/bin/python
# -*- coding: utf-8 -*- user_data = {"小明": {"张学友": 4, "周杰伦": 3, "刘德华": 4},
"小海": {"张学友": 5, "周杰伦": 2},
"李梅": {"周杰伦": 3.5, "刘德华": 4},
"李磊": {"张学友": 5, "刘德华": 3}} class recommender: def __init__(self,data):
self.frequency={}
self.deviation={}
self.data=data #计算所有item之间评分偏差
def computeDeviation(self):
for ratings in self.data.values():
for item,rating in ratings.items():
self.frequency.setdefault(item,{})
self.deviation.setdefault(item,{})
for item2,rating2 in ratings.items():
if item!=item2:
self.frequency[item].setdefault(item2,0)
self.deviation[item].setdefault(item2,0.0)
self.frequency[item][item2]+=1#两个项目的用户数
self.deviation[item][item2]+=(rating-rating2)#累加两个评分差值
for item,ratings in self.deviation.items():
for item2 in ratings:
ratings[item2]/=self.frequency[item][item2] #评分预测
def predictRating(self,userRatings,k):
recommendations={}
frequencies={}
for item,rating in userRatings.items():
for diffItem,diffRating in self.deviation.items():
if diffItem not in userRatings and item in self.deviation[diffItem]:
fre=self.frequency[diffItem][item]
recommendations.setdefault(diffItem,0.0)
frequencies.setdefault(diffItem,0)
#分子部分
recommendations[diffItem]+=(diffRating[item]+rating)*fre
#分母部分
frequencies[diffItem]+=fre
recommendations=[(k,v/frequencies[k]) for (k,v) in recommendations.items()]
#排序返回前k个
recommendations.sort(key=lambda a_tuple:a_tuple[1],reverse=True)
return recommendations[:k] if __name__=='__main__':
r=recommender(user_data)
r.computeDeviation()
u=user_data['李磊']
print(r.predictRating(u,5))
三.java实现
import java.util.HashMap;
import java.util.Map;
import java.util.List;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Collections; /**
* Created by on 2016/12/8.ShiYan
* 一.计算所有物品对的偏差
* 二.利用偏差进行预测
*/
public class SlopeOne {
Map<String,Map<String,Integer>> frequency=null;
Map<String,Map<String,Double>> deviation=null;
Map<String,Map<String,Integer>> user_rating=null; public SlopeOne( Map<String,Map<String,Integer>> user_rating){
frequency=new HashMap<String,Map<String,Integer>>();
deviation=new HashMap<String,Map<String,Double>>();
this.user_rating=user_rating;
} /**
* 所有有item间的评分偏差
*/
public void computeDeviation(){
for(Map.Entry<String,Map<String,Integer>> ratingsEntry:user_rating.entrySet()){
for(Map.Entry<String,Integer> ratingEntry:ratingsEntry.getValue().entrySet()){
String item=ratingEntry.getKey();
int rating=ratingEntry.getValue();
Map<String,Integer> itemFrequency=null;
if(!frequency.containsKey(item)){
itemFrequency=new HashMap<String, Integer>();
frequency.put(item,itemFrequency);
}else{
itemFrequency=frequency.get(item);
} Map<String,Double> itemDeviation=null;
if(!deviation.containsKey(item)){
itemDeviation=new HashMap<String, Double>();
deviation.put(item,itemDeviation);
}else{
itemDeviation=deviation.get(item);
} for(Map.Entry<String,Integer> ratingEntry2:ratingsEntry.getValue().entrySet()){
String item2=ratingEntry2.getKey();
int rating2=ratingEntry2.getValue();
if(!item.equals(item2)){
//两个项目的用户数
itemFrequency.put(item2,itemFrequency.containsKey(item2)?itemFrequency.get(item2)+1:0);
//两个项目的评分偏差,累加
itemDeviation.put(item2,itemDeviation.containsKey(item2)?itemDeviation.get(item2)+(rating-rating2):0.0);
}
}
}
} for(Map.Entry<String,Map<String,Double>> itemsDeviation:deviation.entrySet()){
String item=itemsDeviation.getKey();
Map<String,Double> itemDev=itemsDeviation.getValue();
Map<String,Integer> itemFre=frequency.get(item);
for(String itemName:itemDev.keySet()){
itemDev.put(itemName,itemDev.get(itemName)/itemFre.get(itemName));
}
}
} /**
* 评分预测
* @param userRating 目标用户的评分
* @param k 返回前k个
* @return
*/
public List<Map.Entry<String,Double>> predictRating(Map<String,Integer> userRating,int k){
Map<String,Double> recommendations=new HashMap<String,Double>();
Map<String,Integer> frequencies=new HashMap<String, Integer>();
for(Map.Entry<String,Integer> userEntry:userRating.entrySet()){
String userItem=userEntry.getKey();
double rating=userEntry.getValue();
for(Map.Entry<String,Map<String,Double>> deviationEntry:deviation.entrySet()){
String item=deviationEntry.getKey();
Map<String,Double> itemDeviation=deviationEntry.getValue();
Map<String,Integer> itemFrequency=frequency.get(item);
if(!userRating.containsKey(item) && itemDeviation.containsKey(userItem)){
int fre=itemFrequency.get(userItem);
if(!recommendations.containsKey(item))
recommendations.put(item,0.0);
if(!frequencies.containsKey(item))
frequencies.put(item,0);
//分子部分
recommendations.put(item,recommendations.get(item)+(itemDeviation.get(userItem)+rating)*fre);
//分母部分
frequencies.put(item,frequencies.get(item)+fre);
}
}
}
for(Map.Entry<String,Double> recoEntry:recommendations.entrySet()){
String key=recoEntry.getKey();
double value=recoEntry.getValue()/frequencies.get(key);
recommendations.put(key,value);
}
//排序,这里还可以使用优先队列返回top_k
List<Map.Entry<String,Double>> list_map=new ArrayList<Map.Entry<String,Double>>(recommendations.entrySet());
Collections.sort(list_map,new Comparator<Map.Entry<String,Double>>(){
@Override
public int compare(Map.Entry<String, Double> o1, Map.Entry<String, Double> o2) {
if(o2.getValue()>o1.getValue())
return 1;
else if(o2.getValue()<o1.getValue())
return -1;
else
return 0;
}
}
);
List<Map.Entry<String,Double>> top_k=new ArrayList<Map.Entry<String, Double>>();
if(list_map.size()<k) k=list_map.size();
for(int i=0;i<k;i++){
top_k.add(list_map.get(i));
}
return top_k;
} public static void main(String[] args){
Map<String,Map<String,Integer>> userRatings=new HashMap<String, Map<String, Integer>>();
Map<String,Integer> xiMingRating=new HashMap<String, Integer>();
xiMingRating.put("张学友",4);
xiMingRating.put("周杰伦",3);
xiMingRating.put("刘德华",4);
Map<String,Integer> xiHaiRating=new HashMap<String, Integer>();
xiHaiRating.put("张学友",5);
xiHaiRating.put("周杰伦",2);
Map<String,Integer> liMeiRating=new HashMap<String, Integer>();
liMeiRating.put("周杰伦",3);
liMeiRating.put( "刘德华",4);
Map<String,Integer> liLeiRating=new HashMap<String, Integer>();
liLeiRating.put("张学友",5);
liLeiRating.put("刘德华",3);
userRatings.put("xiMing",xiMingRating);
userRatings.put("xiHai",xiHaiRating);
userRatings.put("liMei", liMeiRating);
userRatings.put("liLei",liLeiRating); SlopeOne slopOne=new SlopeOne(userRatings);
slopOne.computeDeviation();
List<Map.Entry<String,Double>> top_k=slopOne.predictRating(userRatings.get("liLei"),5);
for(Map.Entry<String,Double> item:top_k){
System.out.println(item.getKey()+" "+item.getValue());
}
}
}
java和python实现一个加权SlopeOne推荐算法的更多相关文章
- SlopeOne推荐算法
Slope One 算法 是一种基于评分的预测算法, 本质上也是一种基于项目的算法.与一般的基于项目的算法不同, 该算法不计算项目之间的相似度, 而是用一种简单的线性回归模型进行预测(可 ...
- 从分类,排序,top-k多个方面对推荐算法稳定性的评价
介绍 论文名: "classification, ranking, and top-k stability of recommendation algorithms". 本文讲述比 ...
- 一起学Hadoop——使用IDEA编写第一个MapReduce程序(Java和Python)
上一篇我们学习了MapReduce的原理,今天我们使用代码来加深对MapReduce原理的理解. wordcount是Hadoop入门的经典例子,我们也不能免俗,也使用这个例子作为学习Hadoop的第 ...
- 黑马基础阶段测试题:创建一个存储字符串的集合list,向list中添加以下字符串:”C++”、”Java”、” Python”、”大数据与云计算”。遍历集合,将长度小于5的字符串从集合中删除,删除成功后,打印集合中的所有元素
package com.swift; import java.util.ArrayList; import java.util.List; import java.util.ListIterator; ...
- Python开发一个csv比较功能相关知识点汇总及demo
Python 2.7 csv.reader(csvfile, dialect='excel', **fmtparams)的一个坑:csvfile被csv.reader生成的iterator,在遍历每二 ...
- 算法:时间复杂度+二分查找法(Java/Go/Python)实现
导读 曾几何时学好数据结构与算法是我们从事计算机相关工作的基本前提,然而现在很多程序员从事的工作都是在用高级程序设计语言(如Java)开发业务代码,久而久之,对于数据结构和算法就变得有些陌生了,由于长 ...
- Java or Python?测试开发工程师如何选择合适的编程语言?
很多测试开发工程师尤其是刚入行的同学对编程语言和技术栈选择问题特别关注,毕竟掌握一门编程语言要花不少时间成本,也直接关系到未来的面试和就业(不同企业/项目对技术栈要求也不一样),根据自身情况做一个相对 ...
- Java VS Python 应该先学哪个?
http://blog.segmentfault.com/hlcfan/1190000000361407 http://www.tuicool.com/articles/fqAzqi Java 和 P ...
- 6月份最新语言排行:Java,Python我更看好谁?
文章首发于终端研发部,转载,请标明原文链接 今天的主题是:探讨一下6月份语言排行还有我的最新展望! 最近,编程语言排行榜前几天发布更新了,在最新的TIOBE编程语言排行榜中,Java依旧位居第一,但前 ...
随机推荐
- 四则运算计算器的微信小程序_1 界面
主界面wxml文件: page{ height:100%; } .content{ min-height:100%; display:flex; flex-direction:column; alig ...
- 【图论好题】ABC #142 Task F Pure
题目大意 给定一个 $N$ 个点 $M$ 条边的有向图 $G$,无重边.自环.找出图 $G$ 的一个导出子图(induced subgraph) $G'$,且 $G'$ 中的每个点的入度和出度都是 1 ...
- POJ - 1815 Friendship (最小点割集)
(点击此处查看原题) 题目分析 题意:有n个人,编号记为1~n,n个人之间可能有人可以互相联系,如果A能和B联系,那么至少满足这两种情况之一:(1)A知道B的电话(2)A可以和C联系,并且C可以和B联 ...
- 剑指offer-左旋转字符串-知识迁移能力-python
题目描述汇编语言中有一种移位指令叫做循环左移(ROL),现在有个简单的任务,就是用字符串模拟这个指令的运算结果.对于一个给定的字符序列S,请你把其循环左移K位后的序列输出.例如,字符序列S=”abcX ...
- Flask-migrate基本使用方法
数据库迁移操作顺序: 1.python 文件 db init 2.根据需求修改模型 3.python flaskapp文件 db migrate -m"新版本名(注释)" 4.py ...
- js判断变量是否为undefined
可能很多朋友认为undefined是在js中未定义变量时才会提示的错误,其实不然undefined 是js中的一特殊的变量,我们也可以提前定义哦,下面我来介绍js undefined 用法. Java ...
- javaScript中 数组的新方法(reduce)
定义和用法 reduce() 方法接收一个函数作为累加器,数组中的每个值(从左到右)开始缩减,最终计算为一个值. reduce() 可以作为一个高阶函数,用于函数的 compose. 注意: redu ...
- MySQL--高性能MySQL笔记二
人们通常使用varchar(15):来存储IP地址,然而它们其实是32位无符号整数,不是字符串,所以应该使用无符号整数存储IP地址,MySQL 提供 INET_ATON() 和 INET_NTOA() ...
- 使用sublimeserver启动本地服务器进行调试
最近在做前后端分离的项目,访问后台接口的时候会产生跨域问题,修改了相关配置解决了跨域问题,但是配置中只对开发环境进行了设置,没有设置生产环境,为了验证生产环境确实无法访问后台接口遂npm run bu ...
- echarts图表自适应盒子的大小(盒子的大小是动态改变的),大到需要全屏展示
项目中用到了echarts,并且页面是自适应的,且页面中有一个[放大.缩小]功能,因此图表还需要根据盒子的大小来变化. 即:两个需求,如下: ① 图表根据窗口的大小自适应 ② 图表根据所在盒子的大小自 ...