基于用户的协同过滤推荐算法java实现(UserCF)

   UserCF的核心思想即为根据用户数据模拟向量相似度,我们根据这个相似度,来找出指定用户的相似用户,然后将相似用户买过的而指定用户没有买的东西推荐给指定用户,推荐度的计算也是结合了相似用户与指定用户的相似度累加。注意这里我们默认是用户的隐反馈行为,所以每一个物品的影响因子默认为1。

品的影响因子默认为1。

package cn.csu.CFUtils;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Scanner;
import java.util.Set;

/**
 * 基于用户的协同过滤推荐算法实现
A a b d
B a c
C b e
D c d e
 * @author Administrator
 *
 */
public class UserCF {

    public static void main(String[] args) {
        /**
         * 输入用户-->物品条目  一个用户对应多个物品
         * 用户ID	物品ID集合
         *   A		a b d
         *   B		a c
         *   C		b e
         *   D		c d e
         */
        Scanner scanner = new Scanner(System.in);
        System.out.println("Input the total users number:");
        //输入用户总量
        int N = scanner.nextInt();
        int[][] sparseMatrix = new int[N][N];//建立用户稀疏矩阵,用于用户相似度计算【相似度矩阵】
        Map<String, Integer> userItemLength = new HashMap<>();//存储每一个用户对应的不同物品总数  eg: A 3
        Map<String, Set<String>> itemUserCollection = new HashMap<>();//建立物品到用户的倒排表 eg: a A B
        Set<String> items = new HashSet<>();//辅助存储物品集合
        Map<String, Integer> userID = new HashMap<>();//辅助存储每一个用户的用户ID映射
        Map<Integer, String> idUser = new HashMap<>();//辅助存储每一个ID对应的用户映射
        System.out.println("Input user--items maping infermation:<eg:A a b d>");
        scanner.nextLine();
        for(int i = 0; i < N ; i++){//依次处理N个用户 输入数据  以空格间隔
            String[] user_item = scanner.nextLine().split(" ");
            int length = user_item.length;
            userItemLength.put(user_item[0], length-1);//eg: A 3
            userID.put(user_item[0], i);//用户ID与稀疏矩阵建立对应关系
            idUser.put(i, user_item[0]);
            //建立物品--用户倒排表
            for(int j = 1; j < length; j ++){
                if(items.contains(user_item[j])){//如果已经包含对应的物品--用户映射,直接添加对应的用户
                    itemUserCollection.get(user_item[j]).add(user_item[0]);
                }else{//否则创建对应物品--用户集合映射
                    items.add(user_item[j]);
                    itemUserCollection.put(user_item[j], new HashSet<String>());//创建物品--用户倒排关系
                    itemUserCollection.get(user_item[j]).add(user_item[0]);
                }
            }
        }
        System.out.println(itemUserCollection.toString());
        //计算相似度矩阵【稀疏】
        Set<Entry<String, Set<String>>> entrySet = itemUserCollection.entrySet();
        Iterator<Entry<String, Set<String>>> iterator = entrySet.iterator();
        while(iterator.hasNext()){
            Set<String> commonUsers = iterator.next().getValue();
            for (String user_u : commonUsers) {
                for (String user_v : commonUsers) {
                    if(user_u.equals(user_v)){
                        continue;
                    }
                    sparseMatrix[userID.get(user_u)][userID.get(user_v)] += 1;//计算用户u与用户v都有正反馈的物品总数
                }
            }
        }
        System.out.println(userItemLength.toString());
        System.out.println("Input the user for recommendation:<eg:A>");
        String recommendUser = scanner.nextLine();
        System.out.println(userID.get(recommendUser));
        //计算用户之间的相似度【余弦相似性】
        int recommendUserId = userID.get(recommendUser);
        for (int j = 0;j < sparseMatrix.length; j++) {
                if(j != recommendUserId){
                    System.out.println(idUser.get(recommendUserId)+"--"+idUser.get(j)+"相似度:"+sparseMatrix[recommendUserId][j]/Math.sqrt(userItemLength.get(idUser.get(recommendUserId))*userItemLength.get(idUser.get(j))));
                }
        }
        
        //计算指定用户recommendUser的物品推荐度
        for(String item: items){//遍历每一件物品
            Set<String> users = itemUserCollection.get(item);//得到购买当前物品的所有用户集合
            if(!users.contains(recommendUser)){//如果被推荐用户没有购买当前物品,则进行推荐度计算
                double itemRecommendDegree = 0.0;
                for(String user: users){
                    itemRecommendDegree += sparseMatrix[userID.get(recommendUser)][userID.get(user)]/Math.sqrt(userItemLength.get(recommendUser)*userItemLength.get(user));//推荐度计算
                }
                System.out.println("The item "+item+" for "+recommendUser +"'s recommended degree:"+itemRecommendDegree);
            }
        }
        scanner.close();
    }

}


 

  • 1
    点赞
  • 44
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,基于用户协同过滤算法是一种常用的推荐算法。下面是一个简单的JAVA实现: 首先,我们需要定义一个User类,用来存储用户信息和用户对物品的评分: ```java public class User { private String name; private Map<String, Double> ratings; // 物品评分 public User(String name) { this.name = name; this.ratings = new HashMap<>(); } public String getName() { return name; } public Map<String, Double> getRatings() { return ratings; } public void addRating(String itemId, double rating) { ratings.put(itemId, rating); } public double getRating(String itemId) { return ratings.getOrDefault(itemId, 0.0); } } ``` 然后,我们需要定义一个UserCF类,用来实现基于用户协同过滤算法: ```java public class UserCF { private List<User> users; public UserCF(List<User> users) { this.users = users; } /** * 计算用户相似度 */ private double sim(User user1, User user2) { Set<String> commonItems = new HashSet<>(user1.getRatings().keySet()); commonItems.retainAll(user2.getRatings().keySet()); // 获取两个用户共同评分的物品 if (commonItems.size() == 0) { return 0; } double sum1 = 0, sum2 = 0, sum3 = 0; for (String itemId : commonItems) { double rating1 = user1.getRating(itemId); double rating2 = user2.getRating(itemId); sum1 += rating1 * rating1; sum2 += rating2 * rating2; sum3 += rating1 * rating2; } return sum3 / (Math.sqrt(sum1) * Math.sqrt(sum2)); } /** * 获取与指定用户相似度最高的k个用户 */ private List<User> topKSimilarUsers(User user, int k) { List<User> similarUsers = new ArrayList<>(users); similarUsers.remove(user); // 移除当前用户 similarUsers.sort(Comparator.comparingDouble(u -> -sim(user, u))); // 按相似度从高到低排序 return similarUsers.subList(0, Math.min(k, similarUsers.size())); // 返回前k个用户 } /** * 基于用户协同过滤推荐算法 */ public List<String> recommend(User user, int k) { List<User> similarUsers = topKSimilarUsers(user, k); Set<String> items = new HashSet<>(); for (User u : similarUsers) { items.addAll(u.getRatings().keySet()); } items.removeAll(user.getRatings().keySet()); // 移除当前用户已评分的物品 Map<String, Double> scores = new HashMap<>(); for (String itemId : items) { double sum = 0; double simSum = 0; for (User u : similarUsers) { double rating = u.getRating(itemId); if (rating > 0) { double s = sim(user, u); sum += s * rating; simSum += s; } } if (simSum > 0) { scores.put(itemId, sum / simSum); } } List<String> recommendedItems = new ArrayList<>(scores.keySet()); recommendedItems.sort(Comparator.comparingDouble(scores::get).reversed()); // 按得分从高到低排序 return recommendedItems; } } ``` 最后,我们可以使用如下代码来测试该算法: ```java public class Test { public static void main(String[] args) { List<User> users = new ArrayList<>(); User user1 = new User("user1"); user1.addRating("item1", 3.0); user1.addRating("item2", 4.0); user1.addRating("item3", 2.0); User user2 = new User("user2"); user2.addRating("item1", 4.0); user2.addRating("item3", 3.0); user2.addRating("item4", 2.0); User user3 = new User("user3"); user3.addRating("item2", 3.0); user3.addRating("item3", 4.0); user3.addRating("item4", 2.0); users.add(user1); users.add(user2); users.add(user3); UserCF userCF = new UserCF(users); User user = new User("user"); user.addRating("item1", 5.0); user.addRating("item3", 1.0); List<String> recommendedItems = userCF.recommend(user, 2); System.out.println(recommendedItems); } } ``` 输出结果为:[item2, item4],表示推荐给用户的物品为item2和item4。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值