小工具知识网

当前位置: 首页 > 行业知识 > 推荐系统算法 协同过滤算法详解(三)Springboot 实现基于用户和物品的协同过滤算法

行业知识

推荐系统算法 协同过滤算法详解(三)Springboot 实现基于用户和物品的协同过滤算法

2026-10-30 23:43:48 来源:互联网转载

目录

 

简介

协同过滤算法(简称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     */    public static Map computeNeighbor(Integer key, Map  map,int type) {        Map distMap = new TreeMap();        List 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 xList, List yList,int type) {        List xs= Lists.newArrayList();        List 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 xs, List ys){        int n=xs.size();        //至少有两个元素        if (nx).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@NoArgsConstructorpublic 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  userCfRecommend(int userId){        List data= Sql获取不同用户对不同电影评分关系;        // 获取到推荐的电影id        List 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}     */    public static List recommend(Integer itemId, List list) {        //按物品分组        Map  itemMap=list.stream().collect(Collectors.groupingBy(RelateDTO::getItemId));        //获取其他物品与当前物品的关系值        Map  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  userCfRecommend(int userId){        List data= Sql获取不同用户对不同电影评分关系;        // 获取到推荐的电影id        List recommendations = ItemCF.recommend(itemId, data);        return recommendations ;    }}

总结

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

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

------------------------------------------与正文内容无关------------------------------------

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

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

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

A乐神-CSDN博客

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

上一篇:贝爷服务器怎么开?

下一篇:怎么默认启动ntp服务器?