Java實(shí)現(xiàn)文本查重的方法詳解
ansj 分詞法介紹
Ansj 是一個(gè)開源的 Java 中文分詞工具,基于中科院的 ictclas 中文分詞算法,采用隱馬爾科夫模型(HMM),比其他常用的開源分詞工具(如 MMseg4j)的分詞準(zhǔn)確率更高。作者為孫?。╝nsjsun),目前實(shí)現(xiàn)了中文分詞、中文姓名識(shí)別、用戶自定義詞典、關(guān)鍵字提取、自動(dòng)摘要、關(guān)鍵字標(biāo)記等功能,適用于對(duì)分詞效果要求高的各種項(xiàng)目。 雖然 Ansj 分詞的基本原理與 ictclas 的一樣,但是 Ansj 做了一些工程上的優(yōu)化,比如:用 DAT 高效地實(shí)現(xiàn)檢索詞典、鄰接表實(shí)現(xiàn)分詞 DAG、支持自定義詞典與自定義消歧義規(guī)則等。
Ansj 分詞器 git地址: github.com/NLPchina/ansj_seg
配置文件
在ansj中配置文件名為library.properties,這是一個(gè)不可更改的約定。
字段名 | 默認(rèn)值 | 說(shuō)明 |
---|---|---|
isNameRecognition | true | 是否開啟人名識(shí)別 |
isNumRecognition | true | 是否開啟數(shù)字識(shí)別 |
isQuantifierRecognition | true | 是否數(shù)字和量詞合并 |
isRealName | false | 是否取得真實(shí)的詞,默認(rèn)情況會(huì)取得標(biāo)注化后的 |
isSkipUserDefine | false | 是否用戶辭典不加載相同的詞 |
dic | library/default.dic | 自定義詞典路徑 |
dic_[key] | 你的詞典路徑 | 針對(duì)不同語(yǔ)料調(diào)用不同的自定義詞典 |
ambiguity | library/ambiguity.dic | 歧義詞典路徑 |
ambiguity_[key] | library/ambiguity.dic | 歧義詞典路徑 |
crf | null | crf 詞典路徑,不設(shè)置為默認(rèn) |
crf_[key] | 你的模型路徑 | 針對(duì)不同語(yǔ)料調(diào)用不同的分詞模型 |
synonyms | 默認(rèn)的同義詞典 | 針對(duì)不同語(yǔ)料調(diào)用不同的分詞模型 |
synonyms_[key] | 你的同義詞典路徑 | 針對(duì)不同語(yǔ)料調(diào)用不同的分詞模型 |
默認(rèn)的配置文件:
#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
目前支持的分詞策略:
名稱 | 用戶自定義詞典 | 數(shù)字識(shí)別 | 人名識(shí)別 | 機(jī)構(gòu)名識(shí)別 | 新詞發(fā)現(xiàn) |
---|---|---|---|---|---|
BaseAnalysis | X | X | X | X | X |
ToAnalysis | √ | √ | √ | X | X |
DicAnalysis | √ | √ | √ | X | X |
IndexAnalysis | √ | √ | √ | X | X |
NlpAnalysis | √ | √ | √ | √ | √ |
計(jì)算余弦相似度
余弦相似度是常見的相似度衡量手段,能夠用以比對(duì)兩個(gè)向量間的相似水準(zhǔn)。如下代碼呈現(xiàn)了計(jì)算兩篇論文之余弦相似度的方式:
余弦相似度是一種常用的計(jì)算兩個(gè)向量相似性的方法。它基于向量的點(diǎn)積和向量的模。
計(jì)算余弦相似度的原理如下:
- 向量表示:將需要比較的對(duì)象表示為向量。
- 點(diǎn)積運(yùn)算:計(jì)算兩個(gè)向量的點(diǎn)積,即對(duì)應(yīng)元素相乘后再求和。
- 向量模的計(jì)算:分別計(jì)算每個(gè)向量的模,通常使用歐幾里得范數(shù)。
- 計(jì)算余弦相似度:用兩個(gè)向量的點(diǎn)積除以它們的模的乘積。
具體公式為:
余弦相似度 = 向量 A 與向量 B 的點(diǎn)積 / (向量 A 的模 × 向量 B 的模)
余弦相似度的取值范圍在 -1 到 1 之間:
- 值為 1:表示兩個(gè)向量完全相同,即具有最大相似度。
- 值為 0:表示兩個(gè)向量相互垂直,即沒(méi)有相似性。
- 值為 -1:表示兩個(gè)向量完全相反,即具有最小相似度。
余弦相似度的優(yōu)點(diǎn)包括:
- 不受向量大小影響:它比較的是向量的方向,而不是它們的絕對(duì)大小。
- 對(duì)噪聲相對(duì)不敏感:在存在一些噪聲或誤差的情況下仍能給出相對(duì)合理的相似度度量。
在實(shí)際應(yīng)用中,余弦相似度常用于:
- 文本相似性度量:比較文本向量的相似度。
- 圖像相似性分析:衡量圖像特征向量的相似程度。
- 推薦系統(tǒng):找到用戶或物品之間的相似性。
/** * 計(jì)算余弦相似度 * @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)); } /** * 計(jì)算余弦相似度 * @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)))); }
具體實(shí)現(xiàn)看這里
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 /** * 計(jì)算余弦相似度 * @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)); } /** * 計(jì)算余弦相似度 * @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)))); } /** * 判斷文本是否重復(fù) * @param context1 文本1 * @param context2 文本2 * @param threshold 閾值 * @return 是否重復(fù) */ public boolean ifPlagiarism(String context1, String context2, double threshold){ return calculateCosSimilarity(context1, context2) > threshold; } /** * 判斷文本是否重復(fù) 默認(rèn)閾值 0.7 * @param context1 文本1 * @param context2 文本2 * @return 是否重復(fù) */ public boolean ifPlagiarism(String context1, String context2){ return ifPlagiarism(context1, context2, 0.7); } }
使用案例
public static void main(String[] args) { String str = "java實(shí)現(xiàn)論文查重,文本查重方案 采用 ansj 分詞法(barcke) -----" ; String str2 = "java實(shí)現(xiàn)論文查重,文本查重方案 采用 ansj 分詞法(barcke) -----" ; String str3 = "java實(shí)現(xiàn)cke) -----" ; System.out.println("分詞數(shù)據(jù)(ansj分詞法):" + TextPlagiarismCheckUtil.participleNlp(str)); System.out.println("重復(fù)率:" + TextPlagiarismCheckUtil.calculateCosSimilarity(str, str2) + "是否重復(fù)(默認(rèn)閾值0.7):" + TextPlagiarismCheckUtil.ifPlagiarism(str, str2)); System.out.println("重復(fù)率:" + TextPlagiarismCheckUtil.calculateCosSimilarity(str, str3) + "是否重復(fù)(默認(rèn)閾值0.7):" + TextPlagiarismCheckUtil.ifPlagiarism(str, str3)); }
執(zhí)行結(jié)果:
到此這篇關(guān)于Java實(shí)現(xiàn)文本查重的方法詳解的文章就介紹到這了,更多相關(guān)Java文本查重內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JAVA代碼設(shè)置selector不同狀態(tài)下的背景顏色
這篇文章主要介紹了JAVA代碼設(shè)置selector不同狀態(tài)下的背景顏色,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2018-05-05Mybatis + js 實(shí)現(xiàn)下拉列表二級(jí)聯(lián)動(dòng)效果
這篇文章給大家介紹基于Mybatis + js 實(shí)現(xiàn)下拉列表二級(jí)聯(lián)動(dòng)效果,實(shí)現(xiàn)代碼分為前端界面實(shí)現(xiàn)和后端處理方法,代碼簡(jiǎn)單易懂,對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2021-06-06Java 創(chuàng)建兩個(gè)線程模擬對(duì)話并交替輸出實(shí)現(xiàn)解析
這篇文章主要介紹了Java 創(chuàng)建兩個(gè)線程模擬對(duì)話并交替輸出實(shí)現(xiàn)解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-10-10SpringBoot利用攔截器實(shí)現(xiàn)避免重復(fù)請(qǐng)求
Spring MVC中的攔截器(Interceptor)類似于Servlet中的過(guò)濾器(Filter),它主要用于攔截用戶請(qǐng)求并作相應(yīng)的處理。本文就將利用攔截器實(shí)現(xiàn)避免重復(fù)請(qǐng)求,感興趣的小伙伴可以了解一下2022-11-11SpringBoot應(yīng)用啟動(dòng)流程源碼解析
這篇文章主要介紹了SpringBoot應(yīng)用啟動(dòng)流程源碼解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-04-04