用Java实现协同过滤算法(Android版)

一、先抄一下

什么事协同过滤算法?
协同过滤算法是一种基于用户行为数据的推荐算法,广泛应用于电商、社交网络、内容推荐等领域。

算法的原理
协同过滤算法主要分为两类:基于用户的协同过滤(User-based CF)和基于物品的协同过滤(Item-based CF)。以下是这两种算法的基本原理:

  1. 基于用户的协同过滤:找到与目标用户兴趣相似的其他用户,推荐那些相似用户评价高但目标用户尚未评价的物品。
  2. 基于物品的协同过滤:分析物品之间的相似性,推荐与用户已喜欢物品相似的其他物品。

在这里插入图片描述

二、抄完了,到我发挥了

我的原理:我喜欢了商品123,用户A喜欢商品1234,那系统就应该把商品4推荐给我。
如果这时候来了个用户B,用户B喜欢1256商品。那系统就应该把56也推荐给我。
最终推荐给我的应该是456,并且4一定是排在56前面。因为我喜欢的商品,有3个和用户A是一样的,有两个和用户B是一样的。我和A更相似,所以4应该排在前面。

具体代码实现

  1. 首先新建两个非常简单的类,User和Product
    在这里插入图片描述
  2. 然后新建一个订单类,每个订单都包含一个User和一个Product,相当于mysql数据库中存的一条订单,订单包含userId和ProductId,此处就用User和Product代替。
    在这里插入图片描述
  3. 第三步开始new女孩子,把她们拿出来给我干活。还有new商品,new订单
    在这里插入图片描述
    在这里插入图片描述
    这里的订单就相当于我从sql中取出来的所有订单,一个list集合,接下来的任务就是去判断相似度

为了方便学习,我用了中文命名。

上图观察可知: 我买了3个奥特曼,晓晓买了5个奥特曼,张丽买了3个奥特曼,并且我买的3个晓晓都买了,晓晓和我相似度真高,我喜欢晓晓。所以系统应该把我没买,晓晓买了的欧布奥特曼和赛罗奥特曼推荐给我

再看张丽,她比我多买了1个欧布奥特曼,所以和张丽的对比结果,应该给我推荐欧布奥特曼。

欧布奥特曼被推荐了2次,所以最终的推荐结果是,欧布奥特曼在前,赛罗奥特曼在后

上面使我们用眼睛看到的,下面就是具体实现

package com.example.studyonline.controllers;

import java.util.*;
import java.util.stream.Collectors;

public class Test {

    public static void main(String[] args){
        User 我 = new User("我");
        User user1 = new User("刘亦菲");
        User user2 = new User("朱玲");
        User user3 = new User("周佳佳");
        User user4 = new User("李蓉");
        User user5 = new User("廖雯静");
        User user6 = new User("汪齐齐");
        User 张丽 = new User("张丽");
        User 晓晓 = new User("晓晓");

        Product 迪迦奥特曼 = new Product("迪迦奥特曼");
        Product 泰罗奥特曼 = new Product("泰罗奥特曼");
        Product 赛文奥特曼 = new Product("赛文奥特曼");
        Product 欧布奥特曼 = new Product("欧布奥特曼");
        Product 赛罗奥特曼 = new Product("赛罗奥特曼");

        Order order = new Order(我,迪迦奥特曼);
        Order order1 = new Order(我,泰罗奥特曼);
        Order order2 = new Order(我,赛文奥特曼);

        Order order3 = new Order(晓晓,迪迦奥特曼);
        Order order4 = new Order(晓晓,赛文奥特曼);
        Order order5 = new Order(晓晓,赛文奥特曼);
        Order order6 = new Order(晓晓,欧布奥特曼);
        Order order7 = new Order(晓晓,赛罗奥特曼);

        Order order8 = new Order(张丽,迪迦奥特曼);
        Order order9 = new Order(张丽,泰罗奥特曼);
        Order order10 = new Order(张丽,欧布奥特曼);

        List<Order> orderList = new ArrayList<>();
        orderList.add(order);
        orderList.add(order1);
        orderList.add(order2);
        orderList.add(order3);
        orderList.add(order4);
        orderList.add(order5);
        orderList.add(order6);
        orderList.add(order7);
        orderList.add(order8);
        orderList.add(order9);
        orderList.add(order10);

        SimpleRecommender2 simpleRecommender2 = new SimpleRecommender2();
        for (int i = 0; i < orderList.size(); i++) {
            simpleRecommender2.addPurchase(orderList.get(i).getUser(),orderList.get(i).getProduct());
        }
        // 为我推荐商品
        List<Product> recommendations = simpleRecommender2.recommendItems(我, 3);
        System.out.println("给我的推荐结果:" + recommendations);

    }

    public static class SimpleRecommender2 {
        // 存储用户-商品购买数据
        private Map<User, Set<Product>> userItems = new HashMap<>();

        // 添加购买记录
        public void addPurchase(User user, Product product) {
            Set<Product> strings = userItems.get(user);
            if(strings == null){
                Set<Product> set = new HashSet<>();
                set.add(product);
                userItems.put(user,set);
            }else{
                strings.add(product);
                userItems.put(user,strings);
            }
            // userItems.computeIfAbsent(user, k -> new HashSet<>()).add(item);
        }

        // 计算Jaccard相似度
        private double jaccardSimilarity(Set<Product> set1, Set<Product> set2) {
            Set<Product> intersection = new HashSet<>(set1);
            intersection.retainAll(set2);

            Set<Product> union = new HashSet<>(set1);
            union.addAll(set2);

            return union.size() == 0 ? 0 : (double) intersection.size() / union.size();
        }

        // 获取推荐商品(基于最相似用户的购买记录)
        public List<Product> recommendItems(User targetUser, int topN) {
            Set<Product> targetItems = userItems.getOrDefault(targetUser, Collections.emptySet());

            // 存储候选商品及其推荐权重
            Map<Product, Double> candidateScores = new HashMap<>();

            // 遍历所有用户
            for (Map.Entry<User, Set<Product>> entry : userItems.entrySet()) {
                User user = entry.getKey();
                if (user.equals(targetUser)) continue;

                Set<Product> items = entry.getValue();
                double similarity = jaccardSimilarity(targetItems, items);

                // 只考虑有相似度的用户
                if (similarity > 0) {
                    // 添加该用户有而目标用户没有的商品
                    items.stream()
                            .filter(item -> !targetItems.contains(item))
                            .forEach(item -> candidateScores.merge(item, similarity, Double::sum));
                }
            }

            // 按权重降序排序
            return candidateScores.entrySet().stream()
                    .sorted(Map.Entry.<Product, Double>comparingByValue().reversed())
                    .limit(topN)
                    .map(Map.Entry::getKey)
                    .collect(Collectors.toList());
        }
    }

    public static class Order{
        public User user;
        public Product product;

        public Order(User user, Product product) {
            this.user = user;
            this.product = product;
        }

        public User getUser() {
            return user;
        }

        public void setUser(User user) {
            this.user = user;
        }

        public Product getProduct() {
            return product;
        }

        public void setProduct(Product product) {
            this.product = product;
        }

        @Override
        public String toString() {
            return user.name +"买了"+product.name;
        }
    }


    public static class User{
        public String name;

        public User(String name) {
            this.name = name;
        }

        @Override
        public String toString() {
            return "User{" +
                    "name='" + name + '\'' +
                    '}';
        }
    }

    public static class Product{
        public String name;

        public Product(String name) {
            this.name = name;
        }

        @Override
        public String toString() {
            return "Product{" +
                    "name='" + name + '\'' +
                    '}';
        }
    }
}

程序运行后,最终输出结果:
在这里插入图片描述
写着写着代码,突然好想我女朋友,也不知道她吃饭了没,喝水了没,多大了,出生了没。烦人,不写了。我自己学会了就行了。0.0

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值