java实现论文查重,文本查重方案 采用 ansj 分词法

需求要求实现一个文本查重,重复率超过70% 就不让用户新增文本。固研究实现基于java的文本查重工具,分享出来方便大家使用~

ansj 分词法介绍

Ansj 是一个开源的 Java 中文分词工具,基于中科院的 ictclas 中文分词算法,采用隐马尔科夫模型(HMM),比其他常用的开源分词工具(如 MMseg4j)的分词准确率更高。作者为孙健(ansjsun),目前实现了中文分词、中文姓名识别、用户自定义词典、关键字提取、自动摘要、关键字标记等功能,适用于对分词效果要求高的各种项目。
虽然 Ansj 分词的基本原理与 ictclas 的一样,但是 Ansj 做了一些工程上的优化,比如:用 DAT 高效地实现检索词典、邻接表实现分词 DAG、支持自定义词典与自定义消歧义规则等。

Ansj 分词器 git地址: https://github.com/NLPchina/ansj_seg

配置文件

在ansj中配置文件名为library.properties,这是一个不可更改的约定。

字段名默认值说明
isNameRecognitiontrue是否开启人名识别
isNumRecognitiontrue是否开启数字识别
isQuantifierRecognitiontrue是否数字和量词合并
isRealNamefalse是否取得真实的词,默认情况会取得标注化后的
isSkipUserDefinefalse是否用户辞典不加载相同的词
diclibrary/default.dic自定义词典路径
dic_[key]你的词典路径针对不同语料调用不同的自定义词典
ambiguitylibrary/ambiguity.dic歧义词典路径
ambiguity_[key]library/ambiguity.dic歧义词典路径
crfnullcrf 词典路径,不设置为默认
crf_[key]你的模型路径针对不同语料调用不同的分词模型
synonyms默认的同义词典针对不同语料调用不同的分词模型
synonyms_[key]你的同义词典路径针对不同语料调用不同的分词模型

默认的配置文件:

#path of userLibrary this is default library
dic=library/default.dic

#redress dic file path
ambiguityLibrary=library/ambiguity.dic

#set real name
isRealName=true

#isNameRecognition default true
isNameRecognition=true

#isNumRecognition default true
isNumRecognition=true

#digital quantifier merge default true
isQuantifierRecognition=true

目前支持的分词策略:

名称用户自定义词典数字识别人名识别机构名识别新词发现
BaseAnalysisXXXXX
ToAnalysisXX
DicAnalysisXX
IndexAnalysisXX
NlpAnalysis

计算余弦相似度

余弦相似度是常见的相似度衡量手段,能够用以比对两个向量间的相似水准。如下代码呈现了计算两篇论文之余弦相似度的方式:

余弦相似度是一种常用的计算两个向量相似性的方法。它基于向量的点积和向量的模。

计算余弦相似度的原理如下:

  1. 向量表示:将需要比较的对象表示为向量。
  2. 点积运算:计算两个向量的点积,即对应元素相乘后再求和。
  3. 向量模的计算:分别计算每个向量的模,通常使用欧几里得范数。
  4. 计算余弦相似度:用两个向量的点积除以它们的模的乘积。

具体公式为:

余弦相似度 = 向量 A 与向量 B 的点积 / (向量 A 的模 × 向量 B 的模)

余弦相似度的取值范围在 -1 到 1 之间:

  • 值为 1:表示两个向量完全相同,即具有最大相似度。
  • 值为 0:表示两个向量相互垂直,即没有相似性。
  • 值为 -1:表示两个向量完全相反,即具有最小相似度。

余弦相似度的优点包括:

  1. 不受向量大小影响:它比较的是向量的方向,而不是它们的绝对大小。
  2. 对噪声相对不敏感:在存在一些噪声或误差的情况下仍能给出相对合理的相似度度量。

在实际应用中,余弦相似度常用于:

  1. 文本相似性度量:比较文本向量的相似度。
  2. 图像相似性分析:衡量图像特征向量的相似程度。
  3. 推荐系统:找到用户或物品之间的相似性。
/**
     * 计算余弦相似度
     * @param vec1 map1
     * @param vec2 map2
     * @return 相似度
     */
    public double calculateCosSimilarity(Map<String, Integer> vec1, Map<String, Integer> vec2) {
        double dotProduct = 0.0;
        double norm1 = 0.0;
        double norm2 = 0.0;
        for (Map.Entry<String, Integer> entry : vec1.entrySet()) {
            String word = entry.getKey();
            int count = entry.getValue();
            dotProduct += count * vec2.getOrDefault(word, 0);
            norm1 += Math.pow(count, 2);
        }
        for (Map.Entry<String, Integer> entry : vec2.entrySet()){
            int count = entry.getValue();
            norm2 += Math.pow(count, 2);
        }
        return dotProduct / (Math.sqrt(norm1) * Math.sqrt(norm2));
    }

    /**
     * 计算余弦相似度
     * @param context1 文本1
     * @param context2 文本2
     * @return 相似度
     */
    public double calculateCosSimilarity(String context1, String context2){
        return calculateCosSimilarity(participleNlp(context1).stream().collect(Collectors.groupingBy(o -> o, Collectors.summingInt(o -> 1))),
                participleNlp(context2).stream().collect(Collectors.groupingBy(o -> o, Collectors.summingInt(o -> 1))));
    }

具体实现看这里

mavaen 依赖

采用 ansj 5.1.6的版本

        <dependency>
            <groupId>org.ansj</groupId>
            <artifactId>ansj_seg</artifactId>
            <version>5.1.6</version>
        </dependency>

util 代码如下

package cn.ideamake.business.tools.util;

import lombok.experimental.UtilityClass;
import org.ansj.domain.Term;
import org.ansj.splitWord.analysis.NlpAnalysis;

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

/**
 * @author Barcke
 * @version 1.0
 * @projectName business-tools
 * @className TextPlagiarismCheckUtil
 * @date 2024/4/16 09:40
 * @slogan: 源于生活 高于生活
 * @description: 文本查重工具 分词采用 ansj 分词方法
 **/
@UtilityClass
public class TextPlagiarismCheckUtil {

    // 分词方法 可替换!!!  start 
    
    /**
     * Nlp分词方式
     * @param context 文本信息
     * @return 分词后的list
     */
    public List<String> participleNlp(String context){
        return participleNlpToTerm(context).stream().map(Term::getName).collect(Collectors.toList());
    }

    /**
     * Nlp分词方式
     * @param context 文本信息
     * @return 分词后的Term
     */
    public List<Term> participleNlpToTerm(String context){
        return NlpAnalysis.parse(context).getTerms();
    }

    // 分词方法 可替换!!!  end

    /**
     * 计算余弦相似度
     * @param vec1 map1
     * @param vec2 map2
     * @return 相似度
     */
    public double calculateCosSimilarity(Map<String, Integer> vec1, Map<String, Integer> vec2) {
        double dotProduct = 0.0;
        double norm1 = 0.0;
        double norm2 = 0.0;
        for (Map.Entry<String, Integer> entry : vec1.entrySet()) {
            String word = entry.getKey();
            int count = entry.getValue();
            dotProduct += count * vec2.getOrDefault(word, 0);
            norm1 += Math.pow(count, 2);
        }
        for (Map.Entry<String, Integer> entry : vec2.entrySet()){
            int count = entry.getValue();
            norm2 += Math.pow(count, 2);
        }
        return dotProduct / (Math.sqrt(norm1) * Math.sqrt(norm2));
    }

    /**
     * 计算余弦相似度
     * @param context1 文本1
     * @param context2 文本2
     * @return 相似度
     */
    public double calculateCosSimilarity(String context1, String context2){
        return calculateCosSimilarity(participleNlp(context1).stream().collect(Collectors.groupingBy(o -> o, Collectors.summingInt(o -> 1))),
                participleNlp(context2).stream().collect(Collectors.groupingBy(o -> o, Collectors.summingInt(o -> 1))));
    }

    /**
     * 判断文本是否重复
     * @param context1 文本1
     * @param context2 文本2
     * @param threshold 阈值
     * @return 是否重复
     */
    public boolean ifPlagiarism(String context1, String context2, double threshold){
        return calculateCosSimilarity(context1, context2) > threshold;
    }

    /**
     * 判断文本是否重复 默认阈值 0.7
     * @param context1 文本1
     * @param context2 文本2
     * @return 是否重复
     */
    public boolean ifPlagiarism(String context1, String context2){
        return ifPlagiarism(context1, context2, 0.7);
    }

}

使用案例

    public static void main(String[] args) {
        String str = "java实现论文查重,文本查重方案 采用 ansj 分词法(barcke) -----" ;

        String str2 = "java实现论文查重,文本查重方案 采用 ansj 分词法(barcke) -----" ;

	    String str3 = "java实现cke) -----" ;

        System.out.println("分词数据(ansj分词法):" + TextPlagiarismCheckUtil.participleNlp(str));

        System.out.println("重复率:" + TextPlagiarismCheckUtil.calculateCosSimilarity(str, str2) + "是否重复(默认阈值0.7):" + TextPlagiarismCheckUtil.ifPlagiarism(str, str2));

        System.out.println("重复率:" + TextPlagiarismCheckUtil.calculateCosSimilarity(str, str3) + "是否重复(默认阈值0.7):" + TextPlagiarismCheckUtil.ifPlagiarism(str, str3));
    }

执行结果:
image

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

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

相关文章

THS6.0.1.0开启健康检查(by lqw)

可以在节点管理器或者分组管理的编辑配置里添加以下信息&#xff1a; 之后点监控,点击实时指标&#xff0c;点击HTTP集群统计&#xff1a; 下图是配置并生效的效果&#xff1a; 也可以使用頁面配置&#xff1a; 推荐使用tcp形式&#xff0c;有的应用后端可能不支持http…

代理知识科普:为什么有的代理IP速度比较慢呢?

代理IP在跨境业务中被广泛的应用&#xff0c;今天我们将一同深入探讨一个问题&#xff1a;“为什么有的IP代理速度比较慢&#xff1f;”随着数字化时代的不断发展&#xff0c;代理服务成为了许多网络操作的关键环节。然而&#xff0c;有时我们可能会遇到IP代理速度慢的问题&…

MT3026 砍玉米

样例1&#xff1a; 输入&#xff1a; 6 1 3 4 2 5 1 7 8 19 10 30 2 输出&#xff1a; 6 其中1<n<10^5,1<xi,hi<10^9 思路&#xff1a;贪心&#xff1a;从左到右或者从右到左依次判断每一棵玉米是否可以倒下 &#xff08;以从左到右为例&#xff1a;先往左倒&…

[论文笔记]Root Mean Square Layer Normalization

引言 今天带来论文Root Mean Square Layer Normalization的笔记&#xff0c;论文题目是均方根层归一化。 本篇工作提出了RMSNorm&#xff0c;认为可以省略重新居中步骤。 简介 层归一化对Transformer等模型非常重要&#xff0c;它可以帮助稳定训练并提升模型收敛性&#xf…

生成对抗网络GAN的扩展应用理解

注&#xff1a;本文仅个人学习理解&#xff0c;如需详细内容请看原论文&#xff01; 一、cycleGAN 1.整体架构&#xff1a; 将图片A通过生成器生成图片B&#xff0c;然后通过判别器判别图片B的真假&#xff1b;并且图片B通过另一个生成器生成A‘&#xff0c;让A和A’近似。 2…

Python这十大特征,堪称“圆满”!

当你犹豫是否要开始 Python 学习之前&#xff0c;可以先详尽了解一下这门编程语言。 软件开发者 Guido Van Rossum 于 1991 年创建了 Python&#xff0c;旨在使程序员的工作更加简单。Python 是目前全球比较流行且产业急需的程序设计语言&#xff0c;也是一门跨平台、开源、免…

2024-8.python作用域+函数其他

变量的作用域 讲到了函数就必须介绍变量的作用域相关。 作用域指的是变量的有效范围。变量并不是在哪个位置都可以访问的&#xff0c;访问权限取决于这个变量是在哪里赋值的&#xff0c;也就是在哪个作用域内赋的值。变量在哪个作用域内赋值&#xff0c;则表示该变量的作用域就…

POST 为什么会发送两次请求?

本文目录 同源策略 什么是同源策略 CORS 简单请求 预检请求 附带身份凭证的请求与通配符 完整的请求流程图 总结 前言 最近博主在字节面试中遇到这样一个面试题&#xff0c;这个问题也是前端面试的高频问题&#xff0c;因为在前端开发的日常开发中我们总是会与post请求…

【数据结构】-- 栈和队列

&#x1f308; 个人主页&#xff1a;白子寰 &#x1f525; 分类专栏&#xff1a;python从入门到精通&#xff0c;魔法指针&#xff0c;进阶C&#xff0c;C语言&#xff0c;C语言题集&#xff0c;C语言实现游戏&#x1f448; 希望得到您的订阅和支持~ &#x1f4a1; 坚持创作博文…

Mybatis-plus中的分页操作

Mybatis-plus中的分页操作 1.导入Mybatis-plus依赖2.创建mybatis配置类3.参数 1.导入Mybatis-plus依赖 因为是一个springboot项目&#xff0c;其中的pom.xml文件内容如下&#xff1a; <?xml version"1.0" encoding"UTF-8"?> <project xmlns&q…

ping命令的使用

一、实验环境 同实验案例分析ARP解析过程环境。 二、需求描述 熟悉 ping 命令的用法并熱悉 ping 命令的各种参数 三、推荐步骤 分别 ping 一个存在的和不存在的IP地址&#xff0c;观察返回的信息分别测试 ping 命令的相关参数。 四、实验步骤 1.ping 一个存在的和不存在…

数据加密、文档加密为什么都选择安企神软件

数据加密、文档加密为什么都选择安企神软件 免费试用安企神 在数据加密和文件加密领域&#xff0c;有众多优秀的软件&#xff0c;他们功能各异、价格不同、效果也大相径庭&#xff0c;经过对比使用、用户口碑和技术网站评判&#xff0c;安企神在各方面都稳坐第一把交易。其原…

ECA-Net:深度卷积神经网络中的高效通道注意力机制【原理讲解及代码!!!】

ECA-Net&#xff1a;深度卷积神经网络中的高效通道注意力机制 在深度学习领域&#xff0c;特别是在深度卷积神经网络&#xff08;DCNN&#xff09;中&#xff0c;注意力机制已经成为提升模型性能的关键技术之一。其中&#xff0c;ECA模块&#xff08;Efficient Channel Attent…

Nginx常用配置,开箱即用

经常遇到Nginx安装和配置的问题。这里笔者将常用配置统统写在下面&#xff0c;方便咱们日常使用。这里本着开箱即用的原则&#xff0c;所以大多数时候不会解释为什么要这样去配置&#xff0c;也不涉及Nginx的安装步骤。下面的所有配置&#xff0c;都可以直接复制后粘贴使用&…

虚幻引擎源码版安装下载,点击GenerateProjectFiles.bat报错 error NU1101NuGet包问题解决参考方案

开发环境配置与源码安装使用 安装VS2022 按照官方文档安装需要的vs配置 虚幻引擎源代码下载 Epic里面下载的引擎与源代码引擎区别&#xff1a;Epic里面下载的引擎是已经编译过的它的源代码访问权限不完整&#xff0c;源代码版本提供比较完整引擎代码&#xff0c;并且可以修…

顺序表(增删减改)+通讯录项目(数据结构)+顺序表专用题型

什么是顺序表 顺序表和数组的区别 顺序表本质就是数组 结构体初阶进阶 系统化的学习-CSDN博客 简单解释一下&#xff0c;就像大家去吃饭&#xff0c;然后左边是苍蝇馆子&#xff0c;右边是修饰过的苍蝇馆子&#xff0c;但是那个好看的苍蝇馆子一看&#xff0c;这不行啊&a…

SAP NWDI(二)服务开启(SLD,CM,CMS)

一、启用System Landscape Directory 二、启用 NWDI using CMS

反射

目录 01、Java反射机制概述1.1、使用反射&#xff0c;实现同上的操作、调用私有属性 02、理解Class类并获取Class实例2.1、Class类的理解2.2、获取Class实例的4种方式2.3、Class实例对应的结构的说明 03、ClassLoader的理解3.1、ClassLoader的理解3.2、使用ClassLoader加载配置…

C语言【数组】

一、数组基本语法 1. 什么是数组 数组是c语言的一种数据结构&#xff0c;用于存储一组具有相同数据类型的数据&#xff1b; 数组中每个元素可以通过下标进行访问&#xff0c;索引从0开始&#xff0c;最大值为数组长度-1。 2. 数组的使用 类型 数组名[元素个数]; int arr[5]…

xftp、xshell连不上虚拟机解决方法

一、检查连接虚拟机ip看是否正确 查看虚拟机系统 IP ifconfig 二、检查虚拟机防火墙是否关闭 查看防火墙状态(ubuntu) sudo ufw status 关闭防火墙 sudo ufw disable 查看防火墙状态(centos) systemctl status firewalld.service 关闭防火墙 systemctl stop firewalld.se…