Springboot 实现基于用户和物品的协同过滤算法

news2024/11/15 14:02:01

 

目录

 

简介

协同过滤算法(简称CF)

算法详解

算法使用

基于用户

基于物品

总结


前言-与正文无关

生活远不止眼前的苦劳与奔波,它还充满了无数值得我们去体验和珍惜的美好事物。在这个快节奏的世界中,我们往往容易陷入工作的漩涡,忘记了停下脚步,感受周围的世界。让我们一起提醒自己,要适时放慢脚步,欣赏生活中的每一道风景,享受与家人朋友的温馨时光,发现那些平凡日子里隐藏的幸福时刻。因为,这些点点滴滴汇聚起来的,才是构成我们丰富多彩生活的本质。希望每个人都能在繁忙的生活中找到自己的快乐之源,不仅仅为了生存而工作,更为了更好的生活而生活。

送你张美图!希望你开心!

简介

协同过滤算法(简称CF)


在早期,协同过滤几乎等同于推荐系统。主要的功能是预测和推荐。协同过滤推荐算法分为两类,分别是:

(英文userCF)

基于用户的协同过滤算法(相似的用户可能喜欢相同物品);这个一般适合推荐新闻和皮皮虾之类的,数据跟人有很大关系,而且信息是每日都是更新的。如果你推荐购物这种,因为一个新建的用户可能购买的商品不足全量商品万分之1,商品数据量大,人对商品购买少,很难找到相似的人;随着用户和物品数量的增加,计算复杂度增加,所以需要这种更适合第二种算法。
(英文itemCF)

基于物品的协同过滤算法(这种方法通过分析物品之间的相似性,根据用户喜欢的物品,,推荐最大相似度其他物品。比如用户喜欢物品A,然后通过算法的出物品C和A的相似度极高,那么用户有可能喜欢物品C)。当然也有缺点:需要足够的用户-物品交互数据来找出物品之间的相似性。

算法详解

如果想知道算法细节可以看我的皮尔森相关系数介绍,这边只是代码级别

推荐系统算法 协同过滤算法详解(二)皮尔森相关系数-CSDN博客

算法使用

下面例子都是基于电影推荐系统做的,向用户推荐喜欢的电影。核心有几个字段,1用户id,2电影id,3是评分。如果你不是电影推荐而是其他,其实代码都一样,逻辑也都大差不差。

核心协同过滤算法类,不管你是基于用户,还是基于商品电影都需要,使用的是皮尔森相关系数

package com.tarzan.recommend.core;

import com.tarzan.recommend.dto.RelateDTO;
import org.assertj.core.util.Lists;

import java.util.*;
import java.util.stream.IntStream;

/**
 * 核心算法
 *
 */
public class CoreMath {



    /**
     * 计算相关系数并排序
     * @param key
     * @param map
     * @return Map<Integer,Double>
     */
    public static Map<Integer,Double> computeNeighbor(Integer key, Map<Integer,List<RelateDTO>>  map,int type) {
        Map<Integer,Double> distMap = new TreeMap<>();
        List<RelateDTO> userItems=map.get(key);
        map.forEach((k,v)->{
            //排除此用户
            if(!k.equals(key)){
                //关系系数
                double coefficient = relateDist(v,userItems,type);
                //关系距离
             //   double distance=Math.abs(coefficient);
                distMap.put(k,coefficient);
            }
        });
        return distMap;
    }


    /**
     * 计算两个序列间的相关系数
     *
     * @param xList
     * @param yList
     * @param type 类型0基于用户推荐 1基于物品推荐
     * @return double
     */
    private static double relateDist(List<RelateDTO> xList, List<RelateDTO> yList,int type) {
        List<Double> xs= Lists.newArrayList();
        List<Double> ys= Lists.newArrayList();
        xList.forEach(x->{
            yList.forEach(y->{
                if(type==0){
                    if(x.getItemId().equals(y.getItemId())){
                        xs.add(x.getIndex());
                        ys.add(y.getIndex());
                    }
                }else{
                    if(x.getUseId().equals(y.getUseId())){
                        xs.add(x.getIndex());
                        ys.add(y.getIndex());
                    }
                }
            });
        });
        return getRelate(xs,ys);
    }

    /**
     * 方法描述: 皮尔森(pearson)相关系数计算
     *
     * @param xs x集合
     * @param ys y集合
     */
    public static double getRelate(List<Double> xs, List<Double> ys){
        int n=xs.size();
        //至少有两个元素
        if (n<2) {
            return 0D;
        }
        double Ex= xs.stream().mapToDouble(x->x).sum();
        double Ey=ys.stream().mapToDouble(y->y).sum();
        double Ex2=xs.stream().mapToDouble(x->Math.pow(x,2)).sum();
        double Ey2=ys.stream().mapToDouble(y->Math.pow(y,2)).sum();
        double Exy= IntStream.range(0,n).mapToDouble(i->xs.get(i)*ys.get(i)).sum();
        double numerator=Exy-Ex*Ey/n;
        double denominator=Math.sqrt((Ex2-Math.pow(Ex,2)/n)*(Ey2-Math.pow(Ey,2)/n));
        if (denominator==0) {
            return 0D;
        }
        return numerator/denominator;
    }

}

实体类

package com.tarzan.recommend.dto;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * 关系数据
 *
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class RelateDTO {
    /** 用户id */
    private Integer useId;
    /** 电影id */
    private Integer itemId;
    /** 评分 */
    private Double index;


}

基于用户

入参是你要给推荐具体电影的当前用户id,

package com.tarzan.recommend.service;

import com.tarzan.recommend.core.ItemCF;
import com.tarzan.recommend.core.UserCF;
import com.tarzan.recommend.dto.ItemDTO;
import com.tarzan.recommend.dto.RelateDTO;

import java.util.List;
import java.util.stream.Collectors;

/**
 * 推荐服务
 *
 */
public class Recommend{

    /**
     * 方法描述: 猜你喜欢
     *
     * @param userId 用户id
     */
    public static List<Integer>  userCfRecommend(int userId){
        List<RelateDTO> data= Sql获取不同用户对不同电影评分关系;
        // 获取到推荐的电影id
        List<Integer> recommendations = UserCF.recommend(userId, data);
        return recommendations ;
    }


}
package com.tarzan.recommend.core;

import com.tarzan.recommend.dto.RelateDTO;

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

/**
 * 核心算法
 *
 * @since JDK1.8
 */
public class ItemCF {

    /**
     * 方法描述: 推荐电影id列表
     *
     * @param itemId 当前电影id
     * @param list 用户电影评分数据
     * @return {@link List<Integer>}
     */
    public static List<Integer> recommend(Integer itemId, List<RelateDTO> list) {
        //按物品分组
        Map<Integer, List<RelateDTO>>  itemMap=list.stream().collect(Collectors.groupingBy(RelateDTO::getItemId));
        //获取其他物品与当前物品的关系值
        Map<Integer,Double>  itemDisMap = CoreMath.computeNeighbor(itemId, itemMap,1);
        //获取关系最近物品
        double maxValue=Collections.max(itemDisMap.values());
        return itemDisMap.entrySet().stream().filter(e->e.getValue()==maxValue).map(Map.Entry::getKey).collect(Collectors.toList());
    }


}

 

基于物品

入参是当前用户曾经评过高分的电影id,以此通过算法推荐和此电影相似度高的电影

package com.tarzan.recommend.service;

import com.tarzan.recommend.core.ItemCF;
import com.tarzan.recommend.core.UserCF;
import com.tarzan.recommend.dto.ItemDTO;
import com.tarzan.recommend.dto.RelateDTO;

import java.util.List;
import java.util.stream.Collectors;

/**
 * 推荐服务
 *
 */
public class Recommend{

    /**
     * 方法描述: 猜你喜欢
     *
     * @param itemId 电影id
     */
    public static List<Integer>  userCfRecommend(int userId){
        List<RelateDTO> data= Sql获取不同用户对不同电影评分关系;
        // 获取到推荐的电影id
        List<Integer> recommendations = ItemCF.recommend(itemId, data);
        return recommendations ;
    }


}

总结

建议使用基于物品的协同过滤算法,基于物品协同过滤可以预先计算好物品间的相似度,在线查询要比基于用户快的多,且基于物品实际效果质量一般比基于用户高,但这个也不是绝对的,像是抖音这中视频都是最新更新的还是基于用户靠谱。

系数计算要保证,分数值至少每行两个首要条件,其次对比值要多,少的话就没有那么理想结果

------------------------------------------与正文内容无关------------------------------------
如果觉的文章写对各位读者老爷们有帮助的话,麻烦点赞加关注呗!作者在这拜谢了!

混口饭吃了!如果你需要Java 、Python毕设、商务合作、技术交流、就业指导、技术支持度过试用期。请在关注私信我,本人看到一定马上回复!

这是我全部文章所在目录,看看是否有你需要的,如果遇到觉得不对地方请留言,看到后我会查阅进行改正。

A乐神-CSDN博客

关注在文章左上角,作者信息处。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

简单线性Dp

文章目录 线性Dp的定义AcWing 898. 数字三角形思路CODE正序倒序 AcWing 895. 最长上升子序列Dp 分析CODE AcWing 897. 最长公共子序列Dp 分析CODE 线性Dp的定义 处理起来是线性的&#xff08;&#xff1f;&#xff1f;&#xff1f;&#xff09;&#xff0c;这部分交给ai老先生…

Gurobi输出日志文件的解读【Gurobi】

本章来解读一下Gurobi的刷屏式输出&#xff0c;根本不需要cout&#xff0c;直接通过model.optimize();进行输出。 例如&#xff1a; 现在我们来逐行解读一下&#xff1a; 第一部分&#xff1a;版本型号 可以直接跳过 CPU model: 12th Gen Intel(R) Core(TM) i5-12500H, instr…

【EI会议征稿通知】第五届计算机信息和大数据应用国际学术会议(CIBDA 2024)

第五届计算机信息和大数据应用国际学术会议&#xff08;CIBDA 2024&#xff09; 2024 5th International Conference on Computer Information and Big Data Applications 第五届计算机信息和大数据应用国际学术会议&#xff08;CIBDA 2024&#xff09;将于2024年3月22-24日在…

Google Chrome 中出现 ERR_SSL_KEY_USAGE_INCOMPATIBLE 错误

证书的方式发生了变化&#xff0c;出现了这个新错误&#xff0c;导致我无法浏览该网站。 可以右键属性获取位置 关闭导航器chrome并转到文件夹&#xff0c;找到Local State文件并删除 执行指令结束进程&#xff0c;重新打开浏览器即可 taskkill /im "chrome.exe"…

基于C#制作一个俄罗斯方块小游戏

目录 引言游戏背景介绍游戏规则游戏设计与实现开发环境与工具游戏界面设计游戏逻辑实现游戏优化和测试性能优化测试工具和流程说明引言 俄罗斯方块是一款经典的益智游戏,深受玩家喜爱。本文将介绍如何使用C#编程语言制作一个简单的俄罗斯方块小游戏,并探讨其设计与实现过程。…

TOFU: A Two-Step Floorplan Refinement Framework for Whitespace Reduction

TOFU: A Two-Step Floorplan Refinement Framework for Whitespace Reduction 目录 摘要一、简介二、准备工作2.1 布局规划2.2 基于约束图的合法化 3 提出的算法A 概况B 平面图合法化1&#xff09;约束图构造&#xff1a; C 两步空白删除框架1.基于位置的模块2. 基于区域重新分…

利用二分法及不动点迭代求解非线性方程(MatLab)

一、问题描述 利用二分法及不动点迭代求解非线性方程。 二、实验目的 掌握二分法及不动点迭代的算法原理&#xff1b;能分析两种方法的收敛性&#xff1b;能熟练编写代码实现利用二分法及不动点迭代来求解非线性方程。 三、实验内容及要求 二分法 (1) 编写代码计算下列数字…

华为配置小型网络WLAN 的基本业务示例

配置小型网络WLAN基本业务示例 组网图形 图1 配置小型网络WLAN基本业务组网图 小型WLAN网络简介配置注意事项组网需求数据规划配置思路操作步骤配置文件 小型WLAN网络简介 本文介绍的WLAN网络是指利用频率为2.4GHz或5GHz的射频信号作为传输介质的无线局域网&#xff0c;相对于有…

Vue-43、Vue中组件自定义事件

1、给学生绑定atguigu事件 2、在组件内触发事件 第二种写法 传多个参数。 解绑 解绑一个事件 解绑多个自定义事件 this.$off([xxx1,xxx2]);解绑所有事件 this.$off();总结

一文速学-selenium高阶操作连接已存在浏览器

前言 不得不说selenium不仅在自动化测试作为不可或缺的工具&#xff0c;在数据获取方面也是十分好用&#xff0c;能够十分快速的见到效果&#xff0c;这都取决于selenium框架的足够的灵活性&#xff0c;甚至在一些基于web端的自动化办公都十分有效。 通过selenium连接已经存在…

【活动回顾】CMeet 成都:转鸿蒙 对应用开发来说是否是职业发展新机会 - 圆满结束!

文章目录 前言一、活动介绍二、精彩分享内容及活动议程2.1、《COC 成都社区情况和活动介绍》2.2、“匿”问我答&#xff0c;现场互动2.3、《话题一&#xff1a;升职加薪》2.4、《话题二&#xff1a;说说鸿蒙》2.5、2023 CSDN 1024 程序员节成都站贡献人物表彰2.6、《话题三&…

谁说后端不能画出美丽的动图?让我来给大家拜个年!

今天我们要介绍的是Python的内置库——小海龟&#xff08;turtle&#xff09;&#xff0c;它是一个非常实用的绘画工具&#xff0c;不仅可以帮助我们绘制图形&#xff0c;还能让我们查看整个绘画过程。即使对绘画一窍不通的人也能够使用它来创作出生动、形象的gif动图。现在正是…

AIGC项目——Meta:根据对话音频生成带动作和手势的3d逼真数字人

From Audio to Photoreal Embodiment: Synthesizing Humans in Conversations From Audio to Photoreal Embodiment:Synthesizing Humans in Conversations 从二元对话的音频中&#xff0c;我们生成相应的逼真的面部、身体和手势。 概括性:角色是由作者的声音驱动的(而不是模…

【获奖必看2.0】美赛小技巧之一秒输入一个公式

大家好呀&#xff0c;美赛开赛还有四天的时间&#xff0c;今天给大家带来的是美赛论文写作时非常实用的一个小技巧——快速输入任何复杂公式。 相信很多小伙伴在论文写作的时候都有一个小烦恼&#xff0c;那就是在面对比较复杂的公式的时候&#xff0c;应该怎么进行快速输入呢…

12.2 关键点提取——SIFT

一、理论 文章看了以下博文&#xff1a;Sift中尺度空间、高斯金字塔、差分金字塔&#xff08;DOG金字塔&#xff09;、图像金字塔-CSDN博客 该文章对SIFT写的很详细&#xff0c;所以在这里我直接抄过来作为笔记。如果以后作者变为付费文章可以提醒我删除。 1.图像金字塔 图像…

酒店|酒店管理小程序|基于微信小程序的酒店管理系统设计与实现(源码+数据库+文档)

酒店管理小程序目录 目录 基于微信小程序的酒店管理系统设计与实现 一、前言 二、系统功能设计 三、系统实现 1、管理员模块的实现 (1) 用户信息管理 (2) 酒店管理员管理 (3) 房间信息管理 2、小程序序会员模块的实现 &#xff08;1&#xff09;系统首页 &#xff0…

Spring Boot + security + jwt 测试安全策略

一、测试概述 主要目的是测试security的用法。因测试搭建mysql和redis比较麻烦&#xff0c;所以我这里将自定义的jwt和用户信息缓存到程序的内存中。 本人测试的项目比较混乱&#xff0c;Spring Boot父类只标出有用的依赖。其子类用的版本为jdk11。后续会继续深入oauth2&#x…

微服务-微服务Alibaba-Nacos注册中心实现

1. 系统架构的演变 俗话说&#xff0c; 没有最好的架构&#xff0c;只有最合适的架构。 微服务架构也是随着信息产业的发展而出现的最有普 遍适用性的一套架构模式。通常来说&#xff0c;我们认为架构发展历史经历了这样一个过程&#xff1a;单体架构——> 垂直架构 ——&g…

Java后端须知的前端知识

Java后端须知的前端知识 HTML &#xff08;超文本标记语言&#xff09; W3C标准 结构&#xff1a;HTML表现&#xff1a;CSS行为&#xff1a;JavaScript 快速入门 <html><head><title></title></head><body><font color"red&q…

【linux】复制cp和硬连接、软连接的区别? innode 关系?

1.命令&#xff1a; cp -r [源文件或目录] [目的目录] #复制 ln -s [被链接的文件] [链接的目录/名称] #软连接 ln [被链接的文件] [链接的目录/名称] #硬连接 注&#xff1a;cp -r 会把所有source当作普通文件&#xff08;regular文件&#xff09;&#x…