Springboot+vue.js+协同过滤推荐+余弦相似度算法实现新闻推荐系统

news2024/11/14 12:21:45

Springboot+vue.js+协同过滤推荐+余弦相似度算法实现新闻推荐系统 - 简书

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

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

一、系统设计

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

image.png

二、效果实现

登录界面

image.png

系统主页

image.png

推荐列表

image.png

新闻搜索

image.png

新闻详情

image.png

浏览历史

image.png

其他效果省略

三、系统算法介绍

余弦相似度算法

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

image.png

分子为向量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);
    }

 

  • Neo4j 做推荐 (11)—— 协同过滤(余弦相似度)

    余弦距离: Jaacard相似度对于比较电影很有用,实际上是比较两组(类型、演员、导演等)。

  • AI算法集结【推荐系统、聚类、分类、协同过滤等】

  • 推荐引擎算法学习导论:协同过滤、聚类、分类

Java实现A*搜索算法界面模拟解决传教士与野人问题,JavaSwing,A*算法

基于Java+Springboot+遗传算法实现高校自动排课系统,课程管理系统

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

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

相关文章

SpringMvc详解

SpringMvc用来代替展示层Servlet&#xff0c;均属于Web层开发技术 Servlet是如何工作的 1、导入Servlet依赖坐标 2、创建一个Servlet接口实现类&#xff0c;重写其中的所有方法 3、在Servlet实现类上加上WebServlet注解&#xff0c;用来配置Servlet访问路径 4、启动Tomca…

Misc(6)

隐藏的钥匙 还是一样挨个试&#xff0c;详细信息里没有发现flag信息&#xff0c;就用010打开试试 文件头正常&#xff0c;暂时没有发现隐藏文件 喝&#xff0c;多搜搜还是有收获的&#xff0c;一开始以为是有隐藏文件就利用ctrlf在010中进行搜索 分别搜索了txt和rar文件都没有反…

VLAN基础知识2_VLAN二层通信原理

目录 1.VLAN二层通信简介 2.同一交换机VLAN二层通信 3.跨交换机VLAN二层通信 4.VLAN二层通信实验 4.1 VLAN基本配置命令 4.2 VLAN配置步骤 4.3 VLAN二层通信实验效果 1.VLAN二层通信简介 VLAN是一个逻辑上的分组&#xff0c;可以将一个物理网络端口分割成多个虚拟网络&…

C++初始化列表详解

写在前面&#xff1a; 初始化列表是一种用于初始化成员变量的语法结构&#xff0c;它可以在类的构造函数中使用&#xff0c;用于初始化类的成员变量。 而 列表初始化指的是 是一种初始化变量的简洁方式&#xff0c;可以用花括号{}来表示。列表初始化可以用于各种类型的变量&…

某农业大学c/c++第五次实验(类和对象)

1.Time时间类 【问题描述】 设计一个Time类&#xff0c;并设计多个重载的构造函数&#xff0c;可以设置时间、进行时间的加减运算、按12小时格式和24小时格式输出时间。 例如&#xff1a; 其中构造函数Time::Time(int s)根据总秒数计算hour、minute、second并构造对象&#x…

C语言,BMP格式解析,生成不同位深的图片。

0.前言 目录 0.前言 1.BMP格式详解 1.1图片的构成 1.2BMP格式 1.2.1文件头 1.2.2位图信息头 1.2.3调色板 1.2.4位图数据 2.生成 3.总结 最近工作任务繁重且对我来说小有难度&#xff0c;但是没有困难的事情做起来怎么有收获呢&#xff1f; 今天推荐一本书《寻找光…

Windows10环境下载安装Oracle19c教程

Windows10环境下载安装Oracle19c教程 前言1. 官网下载2. 运行setup.exe2.1 解压缩2.2 报错解决 3.正式安装3.1 配置选项3.2 系统类3.3 oracle主目录用户3.4 安装位置3.5 先决条件检查3.6 安装产品3.7 安装完成3.8 完全卸载oracle(非必备) 4. 安装验证4.1 CMD验证4.2 SQL Plus4.…

本周大新闻|Quest游戏订阅服务曝光;平价版苹果XR头显25年推出

本周XR大新闻&#xff0c;AR方面&#xff0c;彭博苹果预计25年推出更亲民头显&#xff1b;Vision Pro外屏含微透镜&#xff1b;WWDC23苹果高管脱口秀爆料更多细节&#xff1b;外媒爆料称Vision Pro预期销量改为15万台&#xff1b;VitreaLab展示RGB激光背光技术。还是提前说一下…

leetcode刷题之字符串相关问题

344.反转字符串 方法一&#xff1a;找中间结点&#xff0c;头尾翻转 var reverseString function(s) {let len s.lengthlet mid Math.floor((s.length - 1) / 2) //向下取整 如果长度是奇数&#xff0c;那么mid是最中间的结点 如果长度是偶数&#xff0c;那么mid是中间两个…

【Java技术专题】「攻破技术盲区」带你攻破你很可能存在的Java技术盲点之动态性技术原理指南(反射技术专题)

带你攻破你很可能存在的Java技术盲点之动态性技术原理指南 带你攻破你很可能存在的Java技术盲点之动态性技术原理指南编程语言的类型静态类型语言动态类型语言 技术核心方向反射API反射案例介绍反射功能操作获取构造器长度可变的参数 - 构造方法使用反射 API 获取参数长度可变的…

【软件测试】

系列文章目录 文章目录 系列文章目录前言第四章 单元测试4.1 软件测试过程概述4.2 什么是单元测试4.2.1 单元测试的定义4.2.2 单元测试的重要性4.2.3 单元测试原则 4.3 单元测试的目标和任务4.3.1 单元测试的目标&#xff1a;单元模块被正确编码4.3.2 单元测试的主要任务 4.4 单…

FreeRTOS:事件标志组

目录 一、事件标志组简介1.1事件位(事件标志)1.2事件组1.3事件标志组和事件位的数据类型 二、创建事件标志组2.1函数 xEventGroupCreate()2.2函数xEventGroupCreateStatic() 三、设置事件位3.1函数 xEventGroupClearBits()3.2函数xEventGroupClearBitsFromISR()3.3函数 xEventG…

Python模块MarkupPy 自定义html报告

简介 MarkupPy是Python模块用于生成HTML和XML格式的字符串。它的主要作用是提供了一种比原生HTML/XML更加易读和易写的编写方式&#xff0c;通过Python代码来生成HTML或XML代码。 使用MarkupPy&#xff0c;可以在Python中使用不同的对象类型和方法&#xff0c;来动态地生成HTML…

做自动化测试老是失败?你真的会做吗?资深测试的总结整理...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 自动化正在不断普…

揭开生成式人工智能的力量:60+医疗保健应用场景

预计生成式AI在医疗保健领域的增长速度将超过任何其他行业。在医疗技术领域&#xff0c;AI可带来更高效流程、个性化客户互动、更大的创新和更高价值。为了帮助领导者理解这些机会&#xff0c;BCG最近研究了医疗技术中生成式AI的60多个应用场景&#xff1a;从产研和软件开发到业…

Android自动化测试,5个必备的测试框架

Appium Appium是一个开源的移动测试工具&#xff0c;支持iOS和Android&#xff0c;它可以用来测试任何类型的移动应用&#xff08;原生、网络和混合&#xff09;。作为一个跨平台的工具&#xff0c;你可以在不同的平台上运行相同的测试。为了实现跨平台的功能&#xff0c;Appi…

关于数据库索引的入门简述

一、简介 数据库索引是现代数据库中高效数据检索的一个重要工具。它在优化查询性能和加快数据检索操作方面发挥着重要作用。这里我们深入了解下数据库索引其内部工作原理、优点和局限性。 二、数据库 1、SQL 数据库 为了理解索引&#xff0c;先说一句数据库&#xff0c;数据库…

Jenkins小技巧汇总

设置变量 设置全局环境变量 全局变量除了系统内置的全局环境变量之外&#xff0c;用户也可以设置全局变量。设置路径&#xff1a;【Dashboard】–>【Manage Jenkins】–>【System Configuration 下的 System】–>【Global properties】从描述中我们可以看到&#xf…

Jetson nano 之 ROS入门 - - 深度学习环境配置

文章目录 前言一、Anaconda安装二、Pytorch 与 TensorFlow 环境配置三、TensorRT 推理引擎配置总结 前言 Jetson Nano是一款由NVIDIA推出的小型计算机&#xff0c;其性能优异、功耗低、体积小巧&#xff0c;非常适合用于嵌入式系统和边缘设备的深度学习应用。Jetson Nano搭载了…

【Git原理与使用】-- 基本操作

目录 添加文件 查看objects中的文件 小结 修改文件 版本回退 回退的回退 小结 撤销修改 情况一&#xff1a;对于工作区的代码&#xff0c;还没有 add 情况二&#xff1a;已经 add &#xff0c;但没有 commit 情况三&#xff1a;已经 add &#xff0c;并且也 commit …