摘要:本文對(duì)兩種文本相似度算法進(jìn)行比較。余弦值相似度算法最小編輯距離法氏編輯距離基于詞條空間編輯距離,又稱距離,是指兩個(gè)字串之間,由一個(gè)轉(zhuǎn)成另一個(gè)所需的最少編輯操作次數(shù)。但是同時(shí)也可以看出余弦相似度得到的結(jié)果相對(duì)比較高一些。
本文由作者祝娜授權(quán)網(wǎng)易云社區(qū)發(fā)布。
本文對(duì)兩種文本相似度算法進(jìn)行比較。余弦值相似度算法 VS 最小編輯距離法
1、L氏編輯距離(基于詞條空間)
編輯距離(Edit Distance),又稱Levenshtein距離,是指兩個(gè)字串之間,由一個(gè)轉(zhuǎn)成另一個(gè)所需的最少編輯操作次數(shù)。許可的編輯操作包括將一個(gè)字符替換成另一個(gè)字符,插入一個(gè)字符,刪除一個(gè)字符。
算法實(shí)現(xiàn)步驟:
1 設(shè)置n為字符串s的長(zhǎng)度。("我是個(gè)小仙女")
設(shè)置m為字符串t的長(zhǎng)度。("我不是個(gè)小仙女")
如果n等于0,返回m并退出。
如果m等于0,返回n并退出。
構(gòu)造兩個(gè)向量v0[m+1] 和v1[m+1],串聯(lián)0..m之間所有的元素。
2 初始化 v0 to 0..m。
3 檢查 s (i from 1 to n) 中的每個(gè)字符。
4 檢查 t (j from 1 to m) 中的每個(gè)字符
5 如果 s[i] 等于 t[j],則編輯代價(jià)cost為 0;
如果 s[i] 不等于 t[j],則編輯代價(jià)cost為1。
6 設(shè)置單元v1[j]為下面的最小值之一:
a、緊鄰該單元上方+1:v1[j-1] + 1
b、緊鄰該單元左側(cè)+1:v0[j] + 1
c、該單元對(duì)角線上方和左側(cè)+cost:v0[j-1] + cost
7 在完成迭代 (3, 4, 5, 6) 之后,v1[m]便是編輯距離的值。
我們得到最小編輯距離為1那么它們的相似度為 (1-ld/(double)Math.max(str1.length(), str2.length()));
1 - 1/8=7/8.
其算法實(shí)現(xiàn)(java):
public static float levenshtein(String str1,String str2) { //計(jì)算兩個(gè)字符串的長(zhǎng)度。 int len1 = str1.length(); int len2 = str2.length(); //建立上面說的數(shù)組,比字符長(zhǎng)度大一個(gè)空間 int[][] dif = new int[len1 + 1][len2 + 1]; //賦初值,步驟B。 for (int a = 0; a <= len1; a++) { dif[a][0] = a; } for (int a = 0; a <= len2; a++) { dif[0][a] = a; } //計(jì)算兩個(gè)字符是否一樣,計(jì)算左上的值 int temp; for (int i = 1; i <= len1; i++) { for (int j = 1; j <= len2; j++) { if (str1.charAt(i - 1) == str2.charAt(j - 1)) { temp = 0; } else { temp = 1; } //取三個(gè)值中最小的 dif[i][j] = min(dif[i - 1][j - 1] + temp, dif[i][j - 1] + 1, dif[i - 1][j] + 1); } } float similarity =1 - (float) dif[len1][len2] / Math.max(str1.length(), str2.length()); return similarity; }
2、余弦值(基于權(quán)值空間)
關(guān)于余弦相似度可以參照 百度詞條 余弦相似度
通過測(cè)量?jī)蓚€(gè)向量之間的角的余弦值來度量它們之間的相似性。0度角的余弦值是1,而其他任何角度的余弦值都不大于1;并且其最小值是-1。從而兩個(gè)向量之間的角度的余弦值確定兩個(gè)向量是否大致指向相同的方向。所以,它通常用于文件比較。
算法步驟
預(yù)處理→文本特征項(xiàng)選擇→加權(quán)→生成向量空間模型后計(jì)算余弦。
具體步驟見附件: 余弦相似度算法步驟解釋.docx
其算法實(shí)現(xiàn)(java):
public static double getSimilarity(String doc1, String doc2) { if (doc1 != null && doc1.trim().length() > 0 && doc2 != null && doc2.trim().length() > 0) {
MapAlgorithmMap = new HashMap(); // 將兩個(gè)字符串中的中文字符以及出現(xiàn)的總數(shù)封裝到,AlgorithmMap中 for (int i = 0; i < doc1.length(); i++) { char d1 = doc1.charAt(i); if (isHanZi(d1)) { int charIndex = getGB2312Id(d1); if (charIndex != -1) { int[] fq = AlgorithmMap.get(charIndex); if (fq != null && fq.length == 2) { fq[0]++; } else { fq = new int[2]; fq[0] = 1; fq[1] = 0; AlgorithmMap.put(charIndex, fq); } } } } 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); } } } } Iteratoriterator = 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 origin = denominator / Math.sqrt(sqdoc1 * sqdoc2); if (String.valueOf(origin).equals("NaN")) { return Double.valueOf("0"); } BigDecimal bg = new BigDecimal(origin); double f1 = bg.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue(); return f1; } else { throw new NullPointerException(" the Document is null or have not cahrs!!"); } } public static boolean isHanZi(char ch) { // 判斷是否漢字 return (ch >= 0x4E00 && ch <= 0x9FA5); } /** * 根據(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 = (buffer[0] & 0x0FF) - 161; // 編碼從A1開始,因此減去0xA1=161 int b1 = (buffer[1] & 0x0FF) - 161; // 第一個(gè)字符和最后一個(gè)字符沒有漢字,因此每個(gè)區(qū)只收16*6-2=94個(gè)漢字 return (short) (b0 * 94 + b1); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } return -1; }
現(xiàn)在對(duì)兩種計(jì)算相似度的算法進(jìn)行比較:
編輯距離相似度運(yùn)行結(jié)果:
"第六章 字符編碼" 與 "第一章 設(shè)計(jì)模式" 的相似度為:0.07159507274627686
"第六章 字符編碼" 與 "第二章 python學(xué)習(xí)" 的相似度為:0.06676656007766724
"第六章 字符編碼" 與 "第三章 python簡(jiǎn)介" 的相似度為:0.08275055885314941
"第六章 字符編碼" 與 "第四章 輸入輸出" 的相似度為:0.1878122091293335
"第六章 字符編碼" 與 "第五章 數(shù)據(jù)類型和變量" 的相似度為:0.20358151197433472
"第六章 字符編碼" 與 "第六章 字符編碼" 的相似度為:1.0
"第六章 字符編碼" 與 "第七章 list" 的相似度為:0.20995670557022095
runtime:989毫秒
L編輯距離的時(shí)間 算法采用矩陣的方式,計(jì)算兩個(gè)字符串之間的變化步驟,會(huì)遍歷兩個(gè)文本中的每一個(gè)字符兩兩比較,可以推斷出時(shí)間復(fù)雜度至少為 document1.length × document2.length
cos相似度運(yùn)行結(jié)果:
"第六章 字符編碼" 與 "第一章 設(shè)計(jì)模式" 的相似度為:0.5
"第六章 字符編碼" 與 "第二章 python學(xué)習(xí)" 的相似度為:0.59
"第六章 字符編碼" 與 "第三章 python簡(jiǎn)介" 的相似度為:0.68
"第六章 字符編碼" 與 "第四章 輸入輸出" 的相似度為:0.62
"第六章 字符編碼" 與 "第五章 數(shù)據(jù)類型和變量" 的相似度為:0.72
"第六章 字符編碼" 與 "第六章 字符編碼" 的相似度為:1.0
"第六章 字符編碼" 與 "第七章 list" 的相似度為:0.59
runtime:400毫秒
使用余弦定理計(jì)算文本效率相對(duì)比較高:其算法復(fù)雜度大致為:document1.length + document2.length。
但是同時(shí)也可以看出 余弦相似度得到的結(jié)果相對(duì)比較高一些。使用分詞或者過濾掉一些常用詞會(huì)對(duì)結(jié)果的準(zhǔn)確性更有利。
使用分詞的方法在本文中沒有展開。但是如果去掉文章里的“的、了、吧,呢、啊”等可以提高結(jié)果的準(zhǔn)確率。當(dāng)然同時(shí)也可以提高判斷的閥值。
運(yùn)行結(jié)果:
"第六章 字符編碼" 與 "第一章 設(shè)計(jì)模式" 的相似度為:0.37
"第六章 字符編碼" 與 "第二章 python學(xué)習(xí)" 的相似度為:0.48
"第六章 字符編碼" 與 "第三章 python簡(jiǎn)介" 的相似度為:0.57
"第六章 字符編碼" 與 "第四章 輸入輸出" 的相似度為:0.56
"第六章 字符編碼" 與 "第五章 數(shù)據(jù)類型和變量" 的相似度為:0.67
"第六章 字符編碼" 與 "第六章 字符編碼" 的相似度為:1.0
"第六章 字符編碼" 與 "第七章 list" 的相似度為:0.48
runtime:519毫秒
看以看出準(zhǔn)確度有了一定的提高。
番外:
L編輯距離動(dòng)態(tài)計(jì)算法,調(diào)用python腳本實(shí)現(xiàn),腳本文件
author = "victor"
-- coding:utf-8 --import sys
import Levenshtein
if name == "__main__":
if(len(sys.argv) < 3): print("Usage: python myratiodetect.py str1 str2") exit(-1) str1 = sys.argv[1] str2 = sys.argv[2] r = Levenshtein.ratio(str1, str2) print(r) exit(0)
本地運(yùn)行的前提為:已經(jīng)適應(yīng)pip安裝了:python_Levenshtein,所以其對(duì)服務(wù)器的依賴比較大,如果工程環(huán)境遷移了的話,會(huì)比較受影響。
程序的運(yùn)行結(jié)果:
"第六章 字符編碼" 與 "第一章 設(shè)計(jì)模式" 的相似度為:0.157063851181
"第六章 字符編碼" 與 "第二章 python學(xué)習(xí)" 的相似度為:0.165801038753
"第六章 字符編碼" 與 "第三章 python簡(jiǎn)介" 的相似度為:0.194563908481
"第六章 字符編碼" 與 "第四章 輸入輸出" 的相似度為:0.268671351528
"第六章 字符編碼" 與 "第五章 數(shù)據(jù)類型和變量" 的相似度為:0.300997688969
"第六章 字符編碼" 與 "第六章 字符編碼" 的相似度為:1.0
"第六章 字符編碼" 與 "第七章 list" 的相似度為:0.296406739228
runtime:2247毫秒
運(yùn)行速度.....比較慢..2333
參考:
https://www.2cto.com/kf/20140...
http://wdhdmx.iteye.com/blog/...
http://blog.sina.com.cn/s/blo...
http://blog.sina.com.cn/s/blo...
更多網(wǎng)易技術(shù)、產(chǎn)品、運(yùn)營(yíng)經(jīng)驗(yàn)分享請(qǐng)?jiān)L問網(wǎng)易云社區(qū)。
文章來源: 網(wǎng)易云社區(qū)
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/25320.html
摘要:在近鄰?fù)扑]中,最常用的相似度是余弦相似度。這就是由于余弦相似度被向量長(zhǎng)度歸一化后的結(jié)果。用余弦相似度計(jì)算出來,兩個(gè)用戶的相似度達(dá)到。余弦相似度適用于評(píng)分?jǐn)?shù)據(jù),杰卡德相似度適合用于隱式反饋數(shù)據(jù)。 今天,我們來聊聊協(xié)同過濾中的相似度計(jì)算方法有哪些。相似度的本質(zhì)推薦系統(tǒng)中,推薦算法分為兩個(gè)門派,一個(gè)是機(jī)器學(xué)習(xí)派,另一個(gè)就是相似度門派。機(jī)器學(xué)習(xí)派是后起之秀,而相似度派則是泰山北斗,以致?lián)纹饋硗?..
摘要:文和,創(chuàng)意實(shí)驗(yàn)室創(chuàng)意技術(shù)專家在機(jī)器學(xué)習(xí)和計(jì)算機(jī)視覺領(lǐng)域,姿勢(shì)預(yù)測(cè)或根據(jù)圖像數(shù)據(jù)探測(cè)人體及其姿勢(shì)的能力,堪稱最令人興奮而又最棘手的一個(gè)話題。使用,用戶可以直接在瀏覽器中運(yùn)行機(jī)器學(xué)習(xí)模型,無需服務(wù)器。 文 / ?Jane Friedhoff 和 Irene Alvarado,Google 創(chuàng)意實(shí)驗(yàn)室創(chuàng)意技術(shù)專家在機(jī)器學(xué)習(xí)和計(jì)算機(jī)視覺領(lǐng)域,姿勢(shì)預(yù)測(cè)或根據(jù)圖像數(shù)據(jù)探測(cè)人體及其姿勢(shì)的能力,堪稱最令人興...
摘要:代碼地址在這篇文章中,我將盡我所能揭秘三種降維技術(shù)和自編碼器。動(dòng)機(jī)當(dāng)處理真實(shí)問題和真實(shí)數(shù)據(jù)時(shí),我們往往遇到維度高達(dá)數(shù)百萬的高維數(shù)據(jù)。盡管在其原來的高維結(jié)構(gòu)中,數(shù)據(jù)能夠得到較好的表達(dá),但有時(shí)候我們可能需要給數(shù)據(jù)降維。 代碼地址:https://github.com/eliorc/Medium/blob/master/PCA-tSNE-AE.ipynb在這篇文章中,我將盡我所能揭秘三種降維技術(shù):...
摘要:在自然語言處理中,一個(gè)很重要的技術(shù)手段就是將文檔轉(zhuǎn)換為一個(gè)矢量,這個(gè)過程一般是使用這個(gè)庫進(jìn)行處理的。自然語言處理中,一般來說,代表詞。自然語言預(yù)處理中,一個(gè)很重要的步驟就是將你收集的句子進(jìn)行分詞,將一個(gè)句子分解成詞的列表。 前言 本文根據(jù)實(shí)際項(xiàng)目撰寫,由于項(xiàng)目保密要求,源代碼將進(jìn)行一定程度的刪減。本文撰寫的目的是進(jìn)行公司培訓(xùn),請(qǐng)勿以任何形式進(jìn)行轉(zhuǎn)載。由于是日語項(xiàng)目,用到的分詞軟件等,在...
摘要:實(shí)驗(yàn)結(jié)果實(shí)驗(yàn)數(shù)據(jù)集數(shù)據(jù)集都是新聞?lì)惥W(wǎng)頁,從五個(gè)中文新聞網(wǎng)站中收集一百個(gè)頁面這最多也就五類吧,而且也就五百個(gè),好像有點(diǎn)少了吧結(jié)果與驗(yàn)證性能指標(biāo)這這這比較文本長(zhǎng)度就了那不是只要包含新聞?wù)牟痪秃昧恕? 《Web Content Extraction Using Clustering with Web Structure》引用 Huang X, Gao Y, Huang L, et al. ...
閱讀 3407·2021-11-22 09:34
閱讀 674·2021-11-19 11:29
閱讀 1380·2019-08-30 15:43
閱讀 2257·2019-08-30 14:24
閱讀 1895·2019-08-29 17:31
閱讀 1251·2019-08-29 17:17
閱讀 2639·2019-08-29 15:38
閱讀 2776·2019-08-26 12:10