UserCF的设计流程(Python,Java)

基本介绍:

在推荐系统领域,协同过滤(Collaborative Filtering)是一种常见且有效的推荐算法。其中,基于用户的协同过滤(UserCF)是一种流行的方法,它通过分析用户之间的行为和偏好来进行推荐。

UserCF设计基本流程:

  1. 数据准备
    UserCF算法的实施需要一定的数据支持。首先,我们需要获得用户对项目(或物品)的评分数据,可以是用户对电影的评分、用户对商品的购买行为等。其次,我们需要构建用户-项目的评分矩阵,矩阵的行表示用户,列表示项目,矩阵中的每个元素表示用户对项目的评分。

  2. 相似度计算
    在UserCF算法中,我们需要计算用户之间的相似度。常用的相似度计算方法包括余弦相似度、皮尔逊相关系数等。

  3. 用户相似度矩阵构建
    根据相似度计算的结果,我们可以构建用户相似度矩阵。该矩阵的行和列分别表示用户,矩阵中的每个元素表示对应用户之间的相似度。我们可以使用一个二维数组或字典来表示该矩阵,其中数组或字典的键可以是用户的唯一标识符。

  4. 候选项目生成
    在UserCF算法中,我们需要为目标用户生成一组候选项目。这些候选项目是由与目标用户相似的其他用户喜欢的项目组成的。具体而言,对于目标用户,我们可以通过相似度矩阵找到与其相似度最高的K个用户,然后将这些用户喜欢的项目加入候选项目列表。

  5. 推荐列表生成
    基于候选项目列表,我们可以生成最终的推荐列表。一种常用的方法是根据候选项目的流行度进行排序,选择热门度较高的项目作为推荐结果。另一种方法是根据候选项目与目标用户的相似度加权进行排序,选择与目标用户更为相似的项目作为推荐结果。

简单实现:

根据用户对于景点的评分,给用户推荐景点(python)

# 用字典的形式表示测试数据data,其中键是用户id,值是另一个字典,该字典的键是景点id,值是对该景点评分
data = {
    "user1": {"spot1": 5, "spot2": 3, "spot3": 2},
    "user2": {"spot1": 5, "spot2": 1, "spot3": 2, "spot4": 4, "spot5": 5},
    "user3": {"spot1": 1, "spot4": 4, "spot6": 5},
    "user4": {"spot1": 1, "spot2": 2, "spot3": 5},
    "user5": {"spot1": 5, "spot2": 3, "spot7": 4}
}


# 基于皮尔相关系数计算两个用户之间相似度
def cal_similarity(user1, user2):
    # 1.获取两个用户都评论的景点,避免不必要计算
    common_spots = set(data[user1]).intersection(data[user2])
    n = len(common_spots)
    if n == 0:
        return 0

    # 2.计算用户对景点评分和
    ''' sum1 = 0
        for spot in common_spots:
            sum1 += data[user1][spot] '''
    sum1 = sum(data[user1][spot] for spot in common_spots)
    sum2 = sum(data[user2][spot] for spot in common_spots)

    # 3.计算评分平方和
    sumsq1 = sum(pow(data[user1][spot], 2) for spot in common_spots)
    sumsq2 = sum(pow(data[user2][spot], 2) for spot in common_spots)

    # 4.乘积和
    pSum = sum(data[user1][spot] * data[user2][spot] for spot in common_spots)

    # 4.计算系数
    num = pSum - (sum1 * sum2) / n
    den = ((sumsq1 - pow(sum1, 2) / n) * (sumsq2 - pow(sum2, 2) / n)) ** 0.5
    if den == 0:
        return 0
    r = round(num / den, 2)
    return r


# 计算与目标用户的n个相似度最高的用户
def nearst_user(username, n=1):
    similarities = []
    for user in data:
        if user != username:
            sim = cal_similarity(user, username)
            similarities.append((user, sim))
    # 使用第二个字段(相似度) 从大到小排序
    similarities.sort(key=lambda x: x[1], reverse=True)
    # 返回前n个人
    return similarities[:n]


# 根据这些相似用户给目标用户进行推荐
def recommend(username, n=1):
    recommendations = {}
    users = nearst_user(username, n)
    print(users)
    for user, _ in users:
        for spot in data[user]:
            if spot not in data[username] or data[username][spot] == 0:
                if spot not in recommendations:
                    recommendations[spot] = 0
                # recommendations => 景点:评分
                recommendations[spot] = data[user][spot]
    # 根据推荐分数排序
    re_spots = sorted(recommendations.items(), key=lambda x: x[1], reverse=True)
    return re_spots[:n]


# user1 = 'user1'
# user2 = 'user2'
# similarity = cal_similarity(user1, user2)
# print(f'用户{user1}和用户{user2}的相似度为: {similarity}')

print(recommend('user1', 4))

Java版本:

public class UserCF {

    private static Map<String, Map<String, Integer>> data = new HashMap<>();

    public static void main(String[] args) {
        // 初始化数据
        initData();

        // 计算相似用户
        List<Map.Entry<String, Double>> similarUsers = nearestUser("user1", 2);
        System.out.println(similarUsers);

        // 生成推荐列表
        List<Map.Entry<String, Integer>> recommendations = recommend("user1", 3);
        System.out.println(recommendations);
    }

    private static void initData() {
        Map<String, Integer> user1 = new HashMap<>();
        user1.put("spot1", 5);
        user1.put("spot2", 3);
        user1.put("spot3", 2);

        Map<String, Integer> user2 = new HashMap<>();
        user2.put("spot1", 5);
        user2.put("spot2", 1);
        user2.put("spot3", 2);
        user2.put("spot4", 4);
        user2.put("spot5", 5);

        Map<String, Integer> user3 = new HashMap<>();
        user3.put("spot1", 1);
        user3.put("spot4", 4);
        user3.put("spot6", 5);

        Map<String, Integer> user4 = new HashMap<>();
        user4.put("spot1", 1);
        user4.put("spot2", 2);
        user4.put("spot3", 5);

        Map<String, Integer> user5 = new HashMap<>();
        user5.put("spot1", 5);
        user5.put("spot2", 3);
        user5.put("spot7", 4);

        data.put("user1", user1);
        data.put("user2", user2);
        data.put("user3", user3);
        data.put("user4", user4);
        data.put("user5", user5);
    }

    public static double calSimilarity(String user1, String user2) {
        Set<String> commonSpots = new HashSet<>(data.get(user1).keySet());
        commonSpots.retainAll(data.get(user2).keySet());

        int n = commonSpots.size();
        if (n == 0) {
            return 0;
        }

        int sum1 = commonSpots.stream().mapToInt(spot -> data.get(user1).get(spot)).sum();
        int sum2 = commonSpots.stream().mapToInt(spot -> data.get(user2).get(spot)).sum();

        double sumsq1 = commonSpots.stream().mapToDouble(spot -> Math.pow(data.get(user1).get(spot), 2)).sum();
        double sumsq2 = commonSpots.stream().mapToDouble(spot -> Math.pow(data.get(user2).get(spot), 2)).sum();

        int pSum = commonSpots.stream().mapToInt(spot -> data.get(user1).get(spot) * data.get(user2).get(spot)).sum();

        double num = pSum - (sum1 * sum2) / (double) n;
        double den = Math.sqrt((sumsq1 - Math.pow(sum1, 2) / (double) n) * (sumsq2 - Math.pow(sum2, 2) / (double) n));
        if (den == 0) {
            return 0;
        }

        return Math.round(num / den * 100) / 100.0;
    }

    public static List<Map.Entry<String, Double>> nearestUser(String username, int n) {
        List<Map.Entry<String, Double>> similarities = new ArrayList<>();
        for (String user : data.keySet()) {
            if (!user.equals(username)) {
                double sim = calSimilarity(user, username);
                similarities.add(new AbstractMap.SimpleEntry<>(user, sim));
            }
        }

        similarities.sort((a, b) -> Double.compare(b.getValue(), a.getValue()));
        return similarities.subList(0, Math.min(n, similarities.size()));
    }

    public static List<Map.Entry<String, Integer>> recommend(String username, int n) {
        Map<String, Integer> recommendations = new HashMap<>();
        List<Map.Entry<String, Double>> similarUsers = nearestUser(username, n);

        for (Map.Entry<String, Double> similarUser : similarUsers) {
            String user = similarUser.getKey();
            for (Map.Entry<String, Integer> entry : data.get(user).entrySet()) {
                String spot = entry.getKey();
                int rating = entry.getValue();
                if (!data.get(username).containsKey(spot) || data.get(username).get(spot) == 0) {
                    recommendations.put(spot, recommendations.getOrDefault(spot, 0) + rating);
                }
            }
        }

        List<Map.Entry<String, Integer>> sortedRecommendations = new ArrayList<>(recommendations.entrySet());
        sortedRecommendations.sort((a, b) -> Integer.compare(b.getValue(), a.getValue()));
        return sortedRecommendations.subList(0, Math.min(n, sortedRecommendations.size()));
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/597350.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

C语言例题34、反向输出字符串(递归方式)

题目要求&#xff1a;输入5个字符后&#xff0c;使用递归方式逆序输出 #include <stdio.h>void reverse(int num) {char cur_char;if (num 1) {cur_char getchar();printf("逆序输出为&#xff1a;");putchar(cur_char);} else {cur_char getchar();revers…

宏电全栈式IoT赋能供排水智能监测,护航城市生命线

城市供水、排水系统是维系城市正常运行、满足群众生产生活需要的重要基础设施&#xff0c;是城市的“生命线”。随着城市化进程加快&#xff0c;城市规模不断扩大&#xff0c;地下管线增长迅速&#xff0c;城市“生命线安全”的监管日益面临挑战。 宏电作为物联网行业的领航者…

软件测试与管理:黑盒测试-等价类划分法和 边界值分析法

知识思维导图&#xff1a; 例题1&#xff1a;日期检查功能的等价类划分 设有一个档案管理系统&#xff0c;要求用户输入以年月表示的日期。假设日期限定在1990年1月~2049年12月&#xff0c;并规定日期由6位数字字符组成&#xff0c;前4位表示年&#xff0c;后2位表示月。现用等…

后台启动HIVE的JDBC连接

后台启动HIVE的JDBC连接 生活就像一杯咖啡&#xff0c;有时苦涩&#xff0c;有时香甜&#xff0c;但都是值得品味的经历。无论遇到什么挑战&#xff0c;记住在每一天的开始&#xff0c;你都有机会给自己倒上一杯清新的力量&#xff0c;为心灵添一抹温暖。勇敢地面对生活的苦与甜…

10000 字详细讲解 Spring 中常用注解及其使用

如下图京东购物页面&#xff0c;当我们选择点击访问某一类商品时&#xff0c;就会向后端发起 HTTP 请求&#xff0c;当后端收到请求时&#xff0c;就会找到对应的代码逻辑对请求进行处理&#xff0c;那么&#xff0c;后端是如何来查找处理请求相对应的代码呢&#xff1f;答案就…

C++使用单链表实现一元多项式的加,乘操作

相邀再次喝酒 待 葡萄成熟透 但是命运入面 每个邂逅 一起走到了 某个路口 是敌与是友 各自也没有自由 位置变了 各有队友 首先&#xff0c;按照惯例&#xff0c;十分欢迎大家边听歌边观看本博客&#xff01;&#xff01; 最佳损友 - 陈奕迅 - 单曲 - 网易云音乐 (163.com) 一…

leetcode295. 数据流的中位数

class MedianFinder {//A为小根堆&#xff0c;B为大根堆List<Integer> A,B;public MedianFinder() {A new ArrayList<Integer>();B new ArrayList<Integer>();}public void addNum(int num) {int m A.size(),n B.size();if(m n){insert(B,num);int top …

开源模型 Prometheus 2 能够评估其他语言模型,其效果几乎与 GPT-4 相当

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

springboot使用研究

map-underscore-to-camel-case: true 开启驼峰命名 GetMapping("/userInfo")public Result<Users> userInfo(RequestHeader(name "Authorization") String token,HttpServletResponse response) {Map<String, Object> map JwtUtil.parseT…

Java | Spring框架|Bean的装配之注解配置

Spring | Bean的装配之 注解配置&#xff1a;简化配置的新标准 Spring框架的注解配置是近年来流行的配置方式&#xff0c;它通过在Java代码中使用注解来简化Bean的配置。这种方式减少了XML配置文件的使用&#xff0c;使得Bean的定义更加直观和简洁。 一、 使用注解定义Bean …

Problem 5: Whack-A-Mole打地鼠

实战题&#xff1a;打地鼠 内容如附件所示&#xff1a; 测试数据为:1,2,4,8,9,10,11,14 答案为&#xff1a;10,2,4 原始分布&#xff1a; 击打10号 击打2号 击打4号 要求&#xff0c;所示实例解以图示的方式给出&#xff0c;并且5组测试数据都需要测试&#xff0c;…

软件工程案例学习-图书管理系统-面向对象方法

文档编号&#xff1a;LMS_1 版 本 号&#xff1a;V1.0 ** ** ** ** ** ** 文档名称&#xff1a;需求分析规格说明书 项目名称&#xff1a;图书管理系统 项目负责人&#xff1a;计敏 胡杰 ** ** …

开式双比例泵控制放大器

比例泵PQ控制放大器的主要作用是通过接收来自控制器的信号&#xff0c;并将其转换为适当的电流信号&#xff0c;以驱动变量泵。这种控制方式可以实现对泵输出流量和压力的精确控制&#xff0c;从而实现节能和提高效率的目的。比例泵PQ控制放大器通常用于节能型泵控制系统中&…

【Linux系列】tail查询使用

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

【6D位姿估计】ZebraPose 层次化分组策略 由粗到细的表面编码

前言 本文介绍6D位姿估计的方法ZebraPose&#xff0c;也可以称为六自由度物体姿态估计&#xff0c;输入单张图片&#xff0c;输出物体的三维位置和三维方向。 它来自CVPR2022的论文&#xff0c;通过层次化分组策略&#xff0c;高效地编码物体表面的信息。 ZebraPose提出了一…

运维自动化之 ansible

目录 一 常见的自动化运维工具 &#xff08;一&#xff09;有哪些常见的 自动化运维工具 &#xff08;二&#xff09;为什么后面都变成用 ansible 二 ansible 基本介绍 1&#xff0c; ansible 是什么 2&#xff0c;ansible能干什么 3&#xff0c;ansible 工作原…

Linux网络—PXE高效批量网络装机

目录 一、部署PXE远程安装服务 1、搭建PXE远程安装服务器 1&#xff09;安装并启用 TFTP 服务 2&#xff09;安装并启用 DHCP 服务 3&#xff09;准备 Linux 内核、初始化镜像文件 4&#xff09;准备 PXE 引导程序 5&#xff09;安装FTP服务&#xff0c;准备CentOS 7 安…

OpenCV 入门(一) —— OpenCV 基础

OpenCV 入门系列&#xff1a; OpenCV 入门&#xff08;一&#xff09;—— OpenCV 基础 OpenCV 入门&#xff08;二&#xff09;—— 车牌定位 OpenCV 入门&#xff08;三&#xff09;—— 车牌筛选 OpenCV 入门&#xff08;四&#xff09;—— 车牌号识别 OpenCV 入门&#xf…

Springboot框架web开发实用功能-02

在些模块中汇总了一些web开发常用的配置和功能。 涉及的模块 springboot-common-config&#xff0c; 端口号&#xff1a;17000 Springboot框架web开发常用功能 Restful接口定义 查询参数 Data public class QueryParam {private String key;private String value; }Control…

MATLAB实现杜拉德公式和凯夫公式的计算固液混合料浆临界流速

MATLAB实现杜拉德公式和凯夫公式的计算固液混合料浆临界流速: 杜拉德公式是用来计算非均质固液混合料浆在输送管中的临界速度的公式&#xff0c;具体形式为&#xff1a; uL FL (2gD / (ρ0 - ρ1))^(1/2) 其中&#xff1a; uL&#xff1a;表示料浆的临界速度&#xff0c;…
最新文章