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