协同过滤算法代码实现

1.功能介绍

根据用户购买过的物品进行推荐

1.查找推荐用户购买过的物品
2.查找所有用户购买过的物品
3.找到同推荐用户购买过相同物品的用户和物品
4.计算用户之间的相似度【余弦相似性】
5.计算相似用户的物品推荐度
6.取相似度最高的前三个物品进行推荐(推荐物品数量可自定义)

2.代码实现

数据说明

1.测试数据userList总共有四条,分别为:

[
	{
    
    
		"userId":15
	},
	{
    
    
		"userId":30
	},
	{
    
    
		"userId":31
	},
	{
    
    
		"userId":32
	}
]

2.测试数据orderList总共有七条,分别为:

[
    {
    
    
        "orderId":"1",
        "flightId":"16",
        "userId":15
    },
    {
    
    
        "orderId":"2",
        "flightId":"3",
        "userId":15
    },
    {
    
    
        "orderId":"3",
        "flightId":"16",
        "userId":30
    },
    {
    
    
        "orderId":"4",
        "flightId":"1",
        "userId":30
    },
    {
    
    
        "orderId":"5",
        "flightId":"9",
        "userId":31
    },
    {
    
    
        "orderId":"6",
        "flightId":"13",
        "userId":31
    },
    {
    
    
        "orderId":"7",
        "flightId":"16",
        "userId":31
    }
]

实现类

	/**
     * 推荐算法--基于用户的协同过滤算法
     *
     * @param userId 要推荐的用户ID
     * @return 推荐的商品集合
     */
    public List<Integer> recommendFlightId(Integer userId) {
    
    
        System.out.println("推荐用户ID:" + userId);
        // 查询推荐用户信息
//        User uid = userService.getUserById(userId);
        // 查询所有用户信息
        List<User> userList = userService.listUser();

        Integer N = userList.size();
        System.out.println("用户数量:" + N);
        // 建立用户稀疏矩阵,用于用户相似度计算【相似度矩阵】
        Long[][] sparseMatrix = new Long[N][N];
        for (int i = 0; i < N; i++) {
    
    
            for (int j = 0; j < N; j++)
                sparseMatrix[i][j] = (long) 0;
        }
        // 存储每一个用户对应的不同物品总数  userId:total
        Map<Integer, Integer> userItemLength = new HashMap<>();
        // 建立物品到用户的倒排表 物品ID:购买过该物品的所有用户
        Map<Integer, Set<Integer>> itemUserCollection = new HashMap<>();
        // 辅助存储物品集合 所有被购买过的物品ID
        Set<Integer> items = new HashSet<>();
        // 辅助存储每一个用户的用户ID映射:user->userId
        Map<Integer, Integer> userIdMap = new HashMap<>();
        // 辅助存储每一个ID对应的用户映射:id->userId
        Map<Integer, Integer> idUser = new HashMap<>();

        // 依次处理N个用户
        for (int i = 0; i < N; i++) {
    
    
            Integer id = userList.get(i).getUserId();
            // 用户的所有订单
            List<Order> orderList = orderService.getByUserId(id);
            userItemLength.put(id, orderList.size());
            // 用户ID与稀疏矩阵建立对应关系
            userIdMap.put(id, i);
            idUser.put(i, id);

            // 建立物品--用户倒排表
            for (int j = 0; j < orderList.size(); j++) {
    
    
                // 订单中的物品(推荐的物品ID)
                Integer flightId = orderList.get(j).getFlightId();
                // 如果已经包含对应的物品--用户映射,直接添加对应的用户
                if (items.contains(flightId)) {
    
    
                    itemUserCollection.get(flightId).add(id);
                } else {
    
    
                    // 否则创建对应物品--用户集合映射
                    items.add(flightId);
                    // 创建物品--用户倒排关系
                    itemUserCollection.put(flightId, new HashSet<Integer>());
                    itemUserCollection.get(flightId).add(id);
                }
            }
        }
        // 输出倒排关系表
        System.out.println("输出倒排关系表:\n" + itemUserCollection);
        // 计算相似度矩阵【稀疏】
        Set<Map.Entry<Integer, Set<Integer>>> entrySet = itemUserCollection.entrySet();
        Iterator<Map.Entry<Integer, Set<Integer>>> iterator = entrySet.iterator();
        while (iterator.hasNext()) {
    
    
            Set<Integer> commonUsers = iterator.next().getValue();
            for (Integer user_u : commonUsers) {
    
    
                for (Integer user_v : commonUsers) {
    
    
                    if (user_u == user_v) {
    
    
                        continue;
                    }
                    //计算用户u与用户v都有正反馈的物品总数
                    sparseMatrix[userIdMap.get(user_u)][userIdMap.get(user_v)] += 1;
                }
            }
        }
        // 计算用户之间的相似度【余弦相似性】
        System.out.println("用户之间的相似度:");
        Integer recommendUserId = userIdMap.get(userId);
        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的物品推荐度
        Map<Integer, Double> itemRecommendDegree = new HashMap<>();//flightId->推荐度
        for (Integer item : items) {
    
    //遍历每一件物品
            //得到购买当前物品的所有用户集合
            Set<Integer> users = itemUserCollection.get(item);
            //如果被推荐用户没有购买当前物品,则进行推荐度计算
            if (!users.contains(userId)) {
    
    
                double RecommendDegree = 0.0;
                for (Integer user : users) {
    
    
                    //推荐度计算
                    RecommendDegree += sparseMatrix[userIdMap.get(userId)][userIdMap.get(user)] / Math.sqrt(userItemLength.get(userId) * userItemLength.get(user));
                }
                itemRecommendDegree.put(item, RecommendDegree);
            }
        }
        System.out.println("flightIdID,推荐度:\n" + itemRecommendDegree);
        //取最大的3个(可自定义)
        if (itemRecommendDegree.size() < 3) {
    
    
            List<Integer> list = itemRecommendDegree.entrySet().stream()
                    .sorted((entry1, entry2) -> entry2.getValue().compareTo(entry1.getValue()))
                    .map(entry -> entry.getKey()).collect(Collectors.toList());
            System.out.println("推荐的物品Id:" + list);
            return list;
        } else {
    
    
            List<Integer> list = itemRecommendDegree.entrySet().stream()
                    .sorted((entry1, entry2) -> entry2.getValue().compareTo(entry1.getValue()))
                    .map(entry -> entry.getKey()).collect(Collectors.toList())
                    .subList(0, 3);
            System.out.println("推荐的物品Id:" + list);
            return list;
        }

    }

推荐结果

这是传入userId:15的推荐结果,最后的1,9,13为推荐的物品ID

推荐用户ID:15
用户数量:4
输出倒排关系表:
{
    
    16=[30, 15, 31], 1=[30], 3=[15], 9=[31], 13=[31]}
用户之间的相似度:
15--30相似度:0.5
15--31相似度:0.4082482904638631
15--32相似度:NaN
flightIdID,推荐度:
{
    
    1=0.5, 9=0.4082482904638631, 13=0.4082482904638631}
推荐的物品Id[1, 9, 13]

猜你喜欢

转载自blog.csdn.net/weixin_43948460/article/details/130684142
今日推荐