Java实现余弦定理计算文本相似度
生活随笔
收集整理的這篇文章主要介紹了
Java实现余弦定理计算文本相似度
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
相似度度量(Similarity),即計(jì)算個(gè)體間的相似程度,相似度度量的值越小,說明個(gè)體間相似度越小,相似度的值越大說明個(gè)體差異越大。
對(duì)于多個(gè)不同的文本或者短文本對(duì)話消息要來計(jì)算他們之間的相似度如何,一個(gè)好的做法就是將這些文本中詞語,映射到向量空間,形成文本中文字和向量數(shù)據(jù)的映射關(guān)系,通過計(jì)算幾個(gè)或者多個(gè)不同的向量的差異的大小,來計(jì)算文本的相似度。下面介紹一個(gè)詳細(xì)成熟的向量空間余弦相似度方法計(jì)算相似度
向量空間余弦相似度(Cosine Similarity)
執(zhí)行結(jié)果: 用時(shí):16 0.8461538461538461
對(duì)于多個(gè)不同的文本或者短文本對(duì)話消息要來計(jì)算他們之間的相似度如何,一個(gè)好的做法就是將這些文本中詞語,映射到向量空間,形成文本中文字和向量數(shù)據(jù)的映射關(guān)系,通過計(jì)算幾個(gè)或者多個(gè)不同的向量的差異的大小,來計(jì)算文本的相似度。下面介紹一個(gè)詳細(xì)成熟的向量空間余弦相似度方法計(jì)算相似度
向量空間余弦相似度(Cosine Similarity)
余弦相似度用向量空間中兩個(gè)向量夾角的余弦值作為衡量兩個(gè)個(gè)體間差異的大小。余弦值越接近1,就表明夾角越接近0度,也就是兩個(gè)向量越相似,這就叫"余弦相似性"。
思路上就是:將文本中的詞匯映射到向量空間,來計(jì)算兩個(gè)向量的夾角余弦值,作為兩個(gè)文本相似度的判斷。
代碼參考如下:
package com.test;import java.io.UnsupportedEncodingException; import java.util.HashMap; import java.util.Iterator; import java.util.Map;public class Cosine {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[]>();//將兩個(gè)字符串中的中文字符以及出現(xiàn)的總數(shù)封裝到,AlgorithmMap中for (int i = 0; i < doc1.length(); i++) {char d1 = doc1.charAt(i);if(isHanZi(d1)){//標(biāo)點(diǎn)和數(shù)字不處理int charIndex = getGB2312Id(d1);//保存字符對(duì)應(yīng)的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];}return denominator / Math.sqrt(sqdoc1*sqdoc2);//余弦計(jì)算} else {throw new NullPointerException(" the Document is null or have not cahrs!!");}}public static boolean isHanZi(char ch) {// 判斷是否漢字return (ch >= 0x4E00 && ch <= 0x9FA5);/*if (ch >= 0x4E00 && ch <= 0x9FA5) {//漢字return true;}else{String str = "" + ch;boolean isNum = str.matches("[0-9]+"); return isNum;}*//*if(Character.isLetterOrDigit(ch)){String str = "" + ch;if (str.matches("[0-9a-zA-Z\\u4e00-\\u9fa5]+")){//非亂碼return true;}else return false;}else return false;*/}/*** 根據(jù)輸入的Unicode字符,獲取它的GB2312編碼或者ascii編碼,* * @param ch 輸入的GB2312中文字符或者ASCII字符(128個(gè))* @return ch在GB2312中的位置,-1表示該字符不認(rèn)識(shí)*/public static short getGB2312Id(char ch) {try {byte[] buffer = Character.toString(ch).getBytes("GB2312");if (buffer.length != 2) {// 正常情況下buffer應(yīng)該是兩個(gè)字節(jié),否則說明ch不屬于GB2312編碼,故返回'?',此時(shí)說明不認(rèn)識(shí)該字符return -1;}int b0 = (int) (buffer[0] & 0x0FF) - 161; // 編碼從A1開始,因此減去0xA1=161int b1 = (int) (buffer[1] & 0x0FF) - 161; return (short) (b0 * 94 + b1);// 第一個(gè)字符和最后一個(gè)字符沒有漢字,因此每個(gè)區(qū)只收16*6-2=94個(gè)漢字} catch (UnsupportedEncodingException e) {e.printStackTrace();}return -1;}public static void main(String[] args) {String str1="余弦定理算法:doc1 與 doc2 相似度為:0.9954971, 耗時(shí):22mm";String str2="余弦定理算法:doc1 和doc2 相似度為:0.99425095, 用時(shí):33mm";long start=System.currentTimeMillis(); double Similarity=Cosine.getSimilarity(str1, str2);System.out.println("用時(shí):"+(System.currentTimeMillis()-start)); System.out.println(Similarity);} }執(zhí)行結(jié)果: 用時(shí):16 0.8461538461538461
總結(jié)
以上是生活随笔為你收集整理的Java实现余弦定理计算文本相似度的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 模拟浏览器自动化测试工具Selenium
- 下一篇: Java开发SVM之Eclipse集成L