基于协同过滤推荐+余弦相似度算法实现新闻推荐系统

2023-11-17

针对海量的新闻资讯数据,如何快速的根据用户的检索需要,完成符合用户阅读需求的新闻资讯推荐?本篇文章主要采用余弦相似度及基于用户协同过滤算法实现新闻推荐,通过余弦相似度算法完成针对不同新闻数据之间的相似性计算,实现分类标签。通过协同过滤算法发现具备相似阅读习惯的用户,展开个性化推荐。
本次新闻推荐系统:

主要包含技术:springboot,mybatis,mysql,javascript,vue.js,html,css
主要包含算法:余弦相似度,基于用户协同过滤推荐

一、系统设计

系统采用前后端分离的开发模式完成,系统前端主要采用Vue.js,javascript,html,CSS等技术实现。系统后端框架采用springboot+mybatis+mysql数据库搭建,针对海量的新闻资讯数据采用分表操作,完成数据存储分析。系统前后端数据交互,采用Ajax异步调用传输JSON实现。系统架构主要分为基础数据存储,新闻资讯爬虫,新闻分析计算,新闻网站前端四个层面,其中爬虫主要定时采集互联网各大新闻网站的公开资讯数据,完成数据清洗,过滤等操作。系统主要架构设计如下图:
在这里插入图片描述

二、效果实现

登录界面

在这里插入图片描述

系统主页

在这里插入图片描述

推荐列表

在这里插入图片描述

新闻搜索

在这里插入图片描述

新闻详情

在这里插入图片描述

浏览历史

在这里插入图片描述
其他效果省略

三、系统算法介绍

余弦相似度算法

余弦相似度,又称为余弦相似性,是通过计算两个向量的夹角余弦值来评估他们的相似度。余弦相似度将向量根据坐标值,绘制到向量空间中,如最常见的二维空间。
余弦相似度衡量的是2个向量间的夹角大小,通过夹角的余弦值表示结果,因此2个向量的余弦相似度为:
在这里插入图片描述

分子为向量A与向量B的点乘,分母为二者各自的L2相乘,即将所有维度值的平方相加后开方。
余弦相似度的取值为[-1,1],值越大表示越相似。

余弦相似度java代码实现

 public static double getSimilarity(String doc1, String doc2) {
       if (doc1 != null && doc1.trim().length() > 0 && doc2 != null && doc2.trim().length() > 0){
            Map<Integer, int[]> AlgorithmMap = new HashMap<Integer, int[]>();
            //将两个字符串中的中文字符以及出现的总数封装到,AlgorithmMap中
            for (int i = 0; i < doc1.length(); i++) {
                char d1 = doc1.charAt(i);
                if (isHanZi(d1)) {//标点和数字不处理
                    int charIndex = getGB2312Id(d1);//保存字符对应的GB2312编码
                    if (charIndex != -1) {
                        int[] fq = AlgorithmMap.get(charIndex);
                        if (fq != null && fq.length == 2) {
                            fq[0]++;//已有该字符,加1
                        } else {
                            fq = new int[2];
                            fq[0] = 1;
                            fq[1] = 0;
                            AlgorithmMap.put(charIndex, fq);//新增字符入map
                        }
                    }
                }
            }
            for (int i = 0; i < doc2.length(); i++) {
                char d2 = doc2.charAt(i);
                if (isHanZi(d2)) {
                    int charIndex = getGB2312Id(d2);
                    if (charIndex != -1) {
                        int[] fq = AlgorithmMap.get(charIndex);
                        if (fq != null && fq.length == 2) {
                            fq[1]++;
                        } else {
                            fq = new int[2];
                            fq[0] = 0;
                            fq[1] = 1;
                            AlgorithmMap.put(charIndex, fq);
                        }
                    }
                }
            }
            Iterator<Integer> iterator = AlgorithmMap.keySet().iterator();
            double sqdoc1 = 0;
            double sqdoc2 = 0;
            double denominator = 0;
            while (iterator.hasNext()) {
                int[] c = AlgorithmMap.get(iterator.next());
                denominator += c[0] * c[1];
                sqdoc1 += c[0] * c[0];
                sqdoc2 += c[1] * c[1];
            }
            double v = denominator / Math.sqrt(sqdoc1 * sqdoc2);//余弦计算
            v = Double.isNaN(v) ? 0d : v;
            return v;
        } else {
            throw new NullPointerException(" the Document is null or have not cahrs!!");
        }
    }

协同过滤推荐算法

协同过滤算法是一个大类,主要有基于用户、基于物品、两者结合等分支,这里我主要介绍的是基于用户的协同过滤算法。主要的思想也很简单,中国有一句俗语“物以类聚,人以群分”,我们可以有很大的把握认为一个和你很相似的用户喜欢的物品也大概率也是你喜欢的物品,这就是基于用户的协同过滤推荐算法的思想。实现基于用户协同过滤推荐,主要包含以下几个步骤:

1.计算用户相似度
2.获取需要推荐给用户的物品(本系统内主要是新闻数据)

基于用户协同推荐算法实现

/***
     * 协同过滤算法
     * 1. 找到与目标用户兴趣相似的用户集合
     * 2. 找到这个集合中用户喜欢的、并且目标用户没有听说过的新闻推荐给目标用户
     * @param userInfos
     * @param recommendUser
     * @return
     */
    public static List<GPair<String, Double>> XtglNewsTj(List<GPair<String, List<String>>> userInfos, String recommendUser) {
        int N = userInfos.size();
        //建立用户稀疏矩阵,用于用户相似度计算【相似度矩阵】
        int[][] sparseMatrix = new int[N][N];
        //存储每个用户对应的不同总数eg: A 3
        Map<String, Integer> userItemLength = new HashMap<>();
        //建立新闻到用户的倒排表 eg: a A B
        Map<String, Set<String>> itemUserCollection = new HashMap<>();
        Set<String> items = new HashSet<>();//辅助存储新闻集合
        Map<String, Integer> userID = new HashMap<>();//辅助存储每一个用户的用户ID映射
        Map<Integer, String> idUser = new HashMap<>();//辅助存储每一个ID对应的用户映射
        for(int i = 0; i < N ; i++){//依次处理N个用户 输入数据  以空格间隔
            userItemLength.put(userInfos.get(i).getKey(), userInfos.get(i).getValue().size());//eg: A 3
            userID.put(userInfos.get(i).getKey(), i);//用户ID与稀疏矩阵建立对应关系
            idUser.put(i, userInfos.get(i).getKey());
            //建立新闻--用户倒排表
            for(int j = 0; j < userInfos.get(i).getValue().size(); j ++){
                if(items.contains(userInfos.get(i).getValue().get(j))){//如果已经包含对应的新闻--用户映射,直接添加对应的用户
                    itemUserCollection.get(userInfos.get(i).getValue().get(j)).add(userInfos.get(i).getKey());
                }else{//否则创建对应新闻--用户集合映射
                    items.add(userInfos.get(i).getValue().get(j));
                    itemUserCollection.put(userInfos.get(i).getValue().get(j), new HashSet<String>());//创建新闻--用户倒排关系
                    itemUserCollection.get(userInfos.get(i).getValue().get(j)).add(userInfos.get(i).getKey());
                }
            }
        }
        System.out.println(itemUserCollection.toString());
        //计算相似度矩阵【稀疏】
        Set<Map.Entry<String, Set<String>>> entrySet = itemUserCollection.entrySet();
        Iterator<Map.Entry<String, Set<String>>> iterator = entrySet.iterator();
        while(iterator.hasNext()){
            Set<String> commonUsers = iterator.next().getValue();
            for (String user_u : commonUsers) {
                for (String user_v : commonUsers) {
                    if(user_u.equals(user_v)){
                        continue;
                    }
                    sparseMatrix[userID.get(user_u)][userID.get(user_v)] +=1;
                }
            }
        }
        /计算用户之间的相似度【余弦相似性】
        int recommendUserId = userID.get(recommendUser);
        List<GPair<String, Double>> res = new ArrayList<>();
        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的新闻推荐度
        List<GPair<String, Double>> recommondInfos = new ArrayList<>();
        for(String item: items){//遍历每一件新闻
            Set<String> users = itemUserCollection.get(item);//得到 当前新闻的所有用户集合
            if(!users.contains(recommendUser)){//如果被推荐用户当前新闻,则进行推荐度计算
                double itemRecommendDegree = 0.0;
                for(String user: users){
                    itemRecommendDegree += sparseMatrix[userID.get(recommendUser)][userID.get(user)]/Math.sqrt(userItemLength.get(recommendUser)*userItemLength.get(user));//推荐度计算
                }
                recommondInfos.add(new GPair<>(item, itemRecommendDegree));
            }
        }
        recommondInfos.sort(new Comparator<GPair<String, Double>>() {
            @Override
            public int compare(GPair<String, Double> o1, GPair<String, Double> o2) {
                return o2.getValue().compareTo(o1.getValue());
            }
        });
        return combine(recommendUser, userInfos,recommondInfos);
    }
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

基于协同过滤推荐+余弦相似度算法实现新闻推荐系统 的相关文章

随机推荐

  • Scratch中的坐标系

    Scratch中的坐标系即普通的平面坐标系 其中水平方向为x轴 竖直方向为y轴 x轴与y轴交点为 0 0 点 x轴正方向为水平向右 y轴正方向为竖直向上 舞台默认大小为宽480 高360 其中x轴范围是 240 240 y轴范围是 180
  • 该产品与此版 VMware Workstation 不兼容,因此无法使用

    目录 VMware虚拟机开机报错 解决错误 VMware虚拟机开机报错 配置文件 D Users tyn Documents Virtual Machines Ubuntu16 的克隆 Ubuntu16 的克隆 vmx 是由 VMware
  • intellij idea开发环境下使用jetty跑项目修改js、jsp文件提示Cannot Save Files 问题

    问题描述如题 试了好久终于找到解决办法 记录下来与大家分享 1 首先进入你的maven仓库找到jetty的位置 我的位置在 C Users ccpit m2 repository org mortbay 供大家参考 2 进入jetty目录
  • DrawerLayout+ToolBar

    ToolBar自定义图标 关联DrawerLayout http blog csdn net static zh article details 52621240 Android侧滑菜单DrawerLayout的使用 http blog c
  • (休息几天)读曼昆之微观经济学——供给需求和政府政策

    1价格上限的短期效应和长期效应 价格上限的一个常见例子是租金管制 在很多城市 当地政府部门规定了房东对租房者索要的最高价格上限 该政策的目的是帮助穷人能租得起房子 经济学家通常痛批租金管制政策 认为它是一种非常缺乏效率的帮助穷人提高他们生活
  • QT信号与槽机制解析

    信号 Signal 与槽 Slot 是Qt编程的基础 有了信号与槽的编程机制 在Qt中处理界面各个组件的交互操作时变得更加直观和简单 GUI程序设计的主要内容就是对界面上各组件的信号的响应 只需要知道什么情况下发射哪些信号 合理地去响应和处
  • 持续增加时间价值30条

    今天分享阅读 时间价值 第一章时的笔记 持续增加时间价值30条 1 当你认为时间在帮助自己的时候 就觉得他是自己的朋友 当你有了要做的事情 当你在确定的方向上往前走 那么时间是在累积我们的成果 就是在帮我们的忙 2 在大的时间面前不要做太小
  • [深入研究4G/5G/6G专题-45]: 5G Link Adaption链路自适应-1-总体架构

    目录 第1章 链路自适应技术概述 1 1 概述 1 2 链路自适应技术的类型 1 3 基本概念
  • 电信行业BOSS系统

    BOSS系统 是Business Operation Support System的简称 即业务运营支撑系统 通常所说的BOSS系统分为四个部分 计费及结算系统 营业与账务系统 客户服务系统和决策支持系统 BOSS系统从业务层面来看就是一个
  • 什么是 JSONP?

    前言 首先我们得先了解JSONP是怎么产生的 最开始跨域请求数据没有现在方便 Ajax直接请求普通文件存在跨域无权限访问的问题 然后聪明的程序员想出了一套非官方的解决办法 程序员发现凡是带有 src 这个属性的标签都拥有跨域的能力 比如 l
  • 自媒体创作审核不通过怎么办?教你一个小技巧,提高效率

    自媒体人是不是会遇到平台审核内容不通过的时候 遇到这个问题你是怎么解决的呢 是不是修改内容提交还是不通过 今天 教你一个小技巧 快速解决内容审核不通过的问题 提高发稿效率 很多自媒体新手不知道稿件还能不能进行质量检测 所以 有时候写的自媒体
  • [深入研究4G/5G/6G专题-24]: 5G NR开机流程4.2 - 随机接入应答消息MSG2的调度过程与上行同步、时间提前量TA通过PDSCH信道下发

    作者主页 文火冰糖的硅基工坊 文火冰糖 王文兵 的博客 文火冰糖的硅基工坊 CSDN博客 本文网址 目录 前言 前置条件 第1章 随机接入知识准备
  • UNIAPP中文字上下左右居中

    效果 index vue
  • Flutter drawer侧滑栏实现

    侧滑栏对于大部分App来说都是经常用到的 接下来我们来一步步的实现flutter的侧滑栏效果 这里需要使用flutter提供的 Drawer和DrawerHeader控件 DrawerHeader通常用作侧滑栏的头部控件 比如用户头像等 D
  • Vulnhub之Me-and-My-Girlfriend

    Vulnhub是一个很好的靶机平台 想看官网点这里 今天学习Me and My Girlfriend 点击这里下载哦 这个比较简单 入门学习 VMware和VirtualBox都可以导入 成功后如图 这里修改连接为NAT模式 然后就开始玩耍
  • Mybatis使用datetimepicker日期和时间插件查询时间范围

    使用说明 collectStartDate和setStartDate类型为Date 对应的创建时间在mysql中为varchar类型 一 下载和引入datetimepicker样式和js 二 页面代码 li li
  • ORA-12514: TNS:listener does not currently know of service requested in connect descriptor 已解决

    今天用Navicat Premium 连接 Oracle时报错了 报错信息 ORA 12514 TNS listener does not currently know of service requested in connect des
  • linux压缩文件夹命令 tar_每天一个Linux系统命令|tar

    名称 tar命令是Linux系统下最常用的打包命令 它不但可以对文件或者文件夹打包 还可以打包的时候同时压缩文件 用法描述 tar 选项 目标文件 源文件 压缩 tar 选项 压缩文件 解压 选项描述 如下是该命令的一些选项 按照使用频率进
  • 从零开始开发自己的类keras深度学习框架7:简易版word2vec

    认真学习 佛系更博 前面几章基本介绍了全连接神经网络和卷积神经网络的原理已经开发过程 本章开始将写一些自然语言处理相关的知识 当然 自然处理领域的知识点比图像处理的要复杂 抽象 可能要花更多时间来研究 首先 我们来了解一下word2vec
  • 基于协同过滤推荐+余弦相似度算法实现新闻推荐系统

    针对海量的新闻资讯数据 如何快速的根据用户的检索需要 完成符合用户阅读需求的新闻资讯推荐 本篇文章主要采用余弦相似度及基于用户协同过滤算法实现新闻推荐 通过余弦相似度算法完成针对不同新闻数据之间的相似性计算 实现分类标签 通过协同过滤算法发