数据挖掘笔记-基于用户协同过滤推荐的简单实现

本文介绍了一种基于用户相似度的推荐系统算法,并通过Java代码实现了一个具体的例子。该算法首先计算用户间的相似度,然后选取最相似的用户作为邻居进行推荐。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

基本思想:首先计算出其他所有用户和当前用户的相似度,然后根据计算出的相似度的高低排序,找出N个与当前用户最近最相似的邻居用户,接着在这N个邻居用户喜欢的条目中,根据邻居用户与当前用户的远近相似程度计算出每一个条目的推荐度,最后根据每一个条目的推荐度高低给当前用户推荐物品。

Java实现代码如下:

public class BasedUserRecommend {
	
	//最近最相邻用户数量
	public static final int NEAREST_USER = 100;
	//推荐结果数量
	public static final int RECOMMEND_NUM = 100;
	//用户电影映射
	private Map<Long, Map<Long, Integer>> userMovies = DataLoader.getUserMovieMap();
	

	//余弦距离计算
	public double cosine(Map<Long, Integer> p1, Map<Long, Integer> p2) {
		double x = 0, y = 0, z = 0;
		for (Map.Entry<Long, Integer> entry : p1.entrySet()) {
			Long k1 = entry.getKey();
			int v1 = entry.getValue();
			if (p2.containsKey(k1)) {
				x += v1 * p2.get(k1);
			}
			y += Math.pow(v1, 2);
		}
		for (Map.Entry<Long, Integer> entry : p2.entrySet()) {
			z += Math.pow(entry.getValue(), 2);
		}
		if (y == 0 || z ==0) return 0;
		return x / (Math.pow(y, 0.5) * Math.pow(z, 0.5));
	}
	
	//计算距离当前用户最近的N的用户
	public List<Map.Entry<Long, Double>> calNearestUser(Long userId) {
		Map<Long, Integer> curMovieRatings = userMovies.get(userId);
		Map<Long, Double> userDistance = new HashMap<Long, Double>();
		for (Map.Entry<Long, Map<Long, Integer>> entry : userMovies.entrySet()) {
			Map<Long, Integer> movieRating = entry.getValue();
			double distance = cosine(curMovieRatings, movieRating);
			userDistance.put(entry.getKey(), distance);
		}
		List<Map.Entry<Long, Double>> list = new ArrayList<Map.Entry<Long, Double>>(userDistance.entrySet());
		Collections.sort(list, new Comparator<Map.Entry<Long, Double>>() {
			@Override
			public int compare(Entry<Long, Double> o1, Entry<Long, Double> o2) {
				return o2.getValue().compareTo(o1.getValue());
			}
		});
		return list.subList(0, NEAREST_USER);
	}

	//根据用户最近最相邻的用户获取最后推荐结果
	public void recommend(Long userId) {
		Set<Long> userMovieIds = userMovies.get(userId).keySet();
		Map<Long, Double> map = new HashMap<Long, Double>();
		List<Map.Entry<Long, Double>> nearestUsers = calNearestUser(userId); 
		for (Map.Entry<Long, Double> nearestUser : nearestUsers) {
			Long nearestUserId = nearestUser.getKey();
			double similarity = nearestUser.getValue();
			Map<Long, Integer> movieRatings = userMovies.get(nearestUserId);
			for (Map.Entry<Long, Integer> movieRating : movieRatings.entrySet()) {
				Long movieId = movieRating.getKey();
				if (userMovieIds.contains(movieId)) continue; 
				Double value = map.get(movieId);
				if (null == value) {
					map.put(movieId, similarity);
				} else {
					map.put(movieId, value + similarity);
				}
			}
		}
		List<Map.Entry<Long, Double>> list = new ArrayList<Map.Entry<Long, Double>>(map.entrySet());
		Collections.sort(list, new Comparator<Map.Entry<Long, Double>>() {
			@Override
			public int compare(Entry<Long, Double> o1, Entry<Long, Double> o2) {
				return o2.getValue().compareTo(o1.getValue());
			}
		});
		System.out.println("---recommend result---");
		for (int i = 0, len = list.size(); i < len; i++) {
			Map.Entry<Long, Double> entry = list.get(i);
			System.out.println(entry.getKey() + " : " + entry.getValue());
			if (i == RECOMMEND_NUM) break;
		}
	}
	
	public static void main(String[] args) {
		new BasedUserRecommend().recommend(1L);
	}
	
}

代码托管:https://github.com/fighting-one-piece/repository-datamining.git

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值