句子相似度及R語(yǔ)言實(shí)現(xiàn)
本次不講原理,單純用R語(yǔ)言計(jì)算句子相似度。
方式一:機(jī)械相似性
兩個(gè)文本內(nèi)容上的相關(guān)程度,比如“你好嗎”和“你好”的相似性,純粹代表著內(nèi)容上字符是否完全共現(xiàn)。——基于Jaccard相似系數(shù)計(jì)算句子相似度
Jaccard 系數(shù)指:句子A的分詞詞語(yǔ)與句子B的分詞詞語(yǔ)交集的大小與句子A的分詞詞語(yǔ)與句子B的分詞詞語(yǔ)并集的大小的比值。有點(diǎn)拗口,其實(shí)就是兩個(gè)句子的分詞詞語(yǔ)的交集比并集。
【圖片來(lái)源:百度百科】
R語(yǔ)言:基于textreuse包: 由于 數(shù)據(jù)保密 性 ,所以部分內(nèi)容打碼了。

代碼解析:tokenize_words()是一個(gè)分詞的函數(shù)。

jaccard_similarity()計(jì)算兩組詞語(yǔ)的相似度。從相似度結(jié)果上看,x與y都是談?wù)摰侥赣H生病住院,z也講到住院,但并不是母親生病住院。且x與z、y與z的相似度不應(yīng)該是相等的,應(yīng)該是y與z的相似度要高于x與z的相似度,因?yàn)閤的重點(diǎn)有兩個(gè),一是母親生病住院,二是情緒低落,y的重點(diǎn)僅是母親住院,z也是與住院有關(guān),但不是母親住院。所以xz、yz兩者的相似值間會(huì)很近,但我認(rèn)為y與z的相似度應(yīng)該高一點(diǎn) (個(gè)人觀點(diǎn))。
library(textreuse)#比較文本相似度dir "C:/Users/yuan/Documents/test" #基于tm包建立語(yǔ)料庫(kù)corpus"Civil procedure"),tokenizer=tokenize_ngrams, n=comparisons#將該矩陣轉(zhuǎn)換成對(duì)的數(shù)據(jù)幀pairwise_candidates(comparisons)#比較句子相似度x "句子1"))y "句子2"))z "句子3"))jaccard_similarity(x , y) ##相似程度jaccard_similarity(x , z) jaccard_similarity(y , z)
補(bǔ)充:進(jìn)行文本相似度計(jì)算時(shí),保證文本里面要大于兩行,否則會(huì)報(bào)錯(cuò)的。 (我也不清楚為什么)若想比較句子或詞語(yǔ)差異性可采用jaccard_dissimilarity函數(shù)。若想比較文章間相似度,最好是將文件保存為同一類型, 不要一個(gè)txt文件 ,一個(gè) word文件或其他文件。
方式二:基于詞向量余弦值相似度
基于word2vec模型訓(xùn)練詞向量,再計(jì)算句子余弦值作為句子相似度。當(dāng)然,如果僅是為了學(xué)習(xí)的可以直接使用別人訓(xùn)練好的詞向量,若用于某領(lǐng)域的,可以找找該方向的詞向量,或者自己訓(xùn)練吧!word2vec有兩種模型。CBOW (Continuous Bag-Of-Words,即連續(xù)的詞袋模型)和Skip-Gram。通過(guò)word2vec訓(xùn)練詞向量,可以把對(duì)文本內(nèi)容的處理簡(jiǎn)化為K維向量空間中的向量運(yùn)算,再基于向量空間上的相似度可以用來(lái)表示文本語(yǔ)義上的相似度。同時(shí),對(duì)于word2vec訓(xùn)練出來(lái)的詞向量也可以用來(lái)做其他的分析,比如:聚類、近似詞等。由于不講原理,所以想了解word2vec實(shí)現(xiàn)原理的自行去百度了解。
前面也說(shuō)了數(shù)據(jù)保密性,所以就不展示數(shù)據(jù)結(jié)構(gòu)了。大概講一下我的數(shù)據(jù)!存在ecxel表中,每一行就是一個(gè)句子。
#釋放內(nèi)存rm(list = ls())gc()#加載所需的組件包library(readxl) #導(dǎo)入數(shù)據(jù)library(jiebaR) #分詞library(tmcn.word2vec) #word2vec模型library(wordVectors) #word2vec模型:與tmcn.word2vec一樣的,功能上比其多一點(diǎn)。library(dplyr) #管道操作#讀取數(shù)據(jù)yq_datas #將句子轉(zhuǎn)為因子形式。docs as.character(sapply(yq_datas$`YQMS(獄情描述)`, str_replace_all, #啟動(dòng)分詞器,進(jìn)行分詞wk vector #worker啟動(dòng)器參數(shù)說(shuō)明#type:默認(rèn)使用混合法的返回類型:mix(混合模型),mp(最大概率),hmm(隱式馬科夫模型),query(索引),tag(詞性標(biāo)注),simhash(距離:求相似),keywords(關(guān)鍵詞);#dict:指定主詞典的路徑(使用默認(rèn),在jiebaRD包中dict文件的jieba.dict.utf8文件);#hmm:指定隱馬爾科夫模式的路徑(使用默認(rèn)即可,也同目錄下的hmm_model.utf8文件);#user:可以路徑的方式自定義屬于用戶自己的字典(可以自己指定路徑,也可以修改同目錄下的user.dict.utf8文件);#idf:指定逆文檔頻次的路徑(同目錄下idf.utf8文件,一般是用于計(jì)算相似度和關(guān)鍵詞的);#stop_word:指定停止詞的路徑(也可以自己指定路徑,也可以修改同目錄下的stop_words.utf8文件(用了很多次感覺(jué)該文件時(shí)好時(shí)壞的,建議自己指定吧!));#topn:指定提取文檔關(guān)鍵詞的個(gè)數(shù);#encoding:指定輸入文件的編碼;#lines:指定最大的讀取行數(shù)(文件太大了可以根據(jù)這個(gè)分段進(jìn)行分詞);#bylines:是否按行分詞,就是按行返回結(jié)果;其他的參數(shù)可以參考worker函數(shù)。#保存分詞數(shù)據(jù):將列表轉(zhuǎn)向量導(dǎo)入文件,再進(jìn)行導(dǎo)入空值進(jìn)行換行,再繼續(xù)第二輪操作。con "C:/Users/yuan/Documents/R/win-library/3.6/tmcn.word2vec/examples/new_vector.txt",open=for(i in 1:length(vector)){ vect % unlist() write.table(vect,file = con,quote = FALSE,eol = " ",row.names = FALSE,col.names = FALSE) nul "" write.table(nul,file = con,quote = FALSE,eol = "\n",row.names = FALSE,col.names = FALSE)}close(con)#基于word2vec模型訓(xùn)練詞向量化model = train_word2vec(system.file("examples", "new_vector.txt", package = "tmcn.word2vec"),vectors = 500,min_count = 2)model[["醫(yī)院"]]#train_word2vec函數(shù)參數(shù)說(shuō)明:#train_file:已經(jīng)分好詞的txt文件路徑(詞語(yǔ)之間由空格隔開(kāi)),是一個(gè)訓(xùn)練數(shù)據(jù)文件。#output_file:word2vec模型訓(xùn)練好的詞向量存儲(chǔ)文件地址。#vectors:輸出的向量維數(shù),默認(rèn)是100個(gè),也可以設(shè)置大一點(diǎn),太大了內(nèi)存消耗大,處理速率低。#threads:訓(xùn)練模型用的線程數(shù),默認(rèn)是1,也可以通過(guò)parallel包的detectCores()函數(shù)查看當(dāng)前電腦可用核數(shù),然后選擇跑幾個(gè)線程。#classes:對(duì)詞語(yǔ)聚類的個(gè)數(shù),默認(rèn)是0,采用K均值進(jìn)行聚類。#window:表示當(dāng)前詞與預(yù)測(cè)詞在一個(gè)句子中的最大距離是多少。#cbow :word2vec訓(xùn)練模型選擇,1是CBOW加層次的網(wǎng)絡(luò)結(jié)構(gòu)(連續(xù)詞袋模型),0(默認(rèn))是Skip-gram模型,具體是如何實(shí)現(xiàn)的可以查看相關(guān)資料。#min_count:可以對(duì)字典做截?cái)?把詞頻少于min_count次數(shù)的詞語(yǔ)丟棄, 默認(rèn)值為5。#iter:迭代次數(shù),默認(rèn)為5。#force:是不是要覆蓋原有的模型。其他參數(shù)查看word2vec函數(shù)#計(jì)算句子相似度vector_similarity function(x,y){ wk_vec #啟動(dòng)分詞器 sentence_vector function(vec) #查找對(duì)應(yīng)詞的詞向量,不存在的詞設(shè)其值為0{ words #對(duì)傳入的形參分詞 sum_word_vec 0 for(i in 1:length(words)) #計(jì)算句子總詞向量 { word if(word %in% row.names(model)) word_vecelse word_vec 0 sum_word_vec } sum_word_vec #計(jì)算句子均值詞向量 return(sum_word_vec) } vecx vecy #cos cos return(cos)}vector_similarity(x,y)vector_similarity(x,z)vector_similarity(y,z)

其結(jié)果和我設(shè)想是一致的,y與z的相似度要大于x與z的相似度。步驟:1、導(dǎo)入數(shù)據(jù);2、使用jiebaR包分詞(采用默認(rèn)參數(shù)),需要注意設(shè)置參數(shù):bylines = T,否則它不會(huì)按行返回結(jié)果;3、將分詞保存后傳給word2vec模型訓(xùn)練詞向量;4、基于詞向量計(jì)算句子的總詞向量;5、計(jì)算兩組句子總詞向量的余弦值作為句子的相似度。
注:
1、關(guān)于分詞后的list結(jié)構(gòu)數(shù)據(jù)保存到txt文件的方法:1:打開(kāi)txt文件;2、將列表的第一個(gè)元素轉(zhuǎn)為向量形式;3、將向量形式的分詞寫(xiě)入文件中,再寫(xiě)入換行符;4、再將列表的第二個(gè)元素轉(zhuǎn)為向量寫(xiě)入文件,以此類推;5、關(guān)閉文件。如果你們有什么好的方法或者函數(shù)可以告訴一下我。
2、train_word2vec函數(shù)訓(xùn)練詞向量,輸入文件必須是放在tmcn.word2vec包中的examples文件夾,放在其他位置都無(wú)法讀取到,不清楚是電腦攔截了,還是其他的原因。若知道原因的,可以告訴我,非常感謝!
3、全部函數(shù)基本都是使用默認(rèn)參數(shù),后期優(yōu)化可以從參數(shù)入手了,詞語(yǔ)權(quán)重等等,最后本人不擅長(zhǎng)自然語(yǔ)言處理方向的分析,若在分析過(guò)程中有錯(cuò)誤的歡迎指正!
————————————————
版權(quán)聲明:本文為CSDN博主「weixin_39860919」的原創(chuàng)文章,遵循CC 4.0 BY-SA版權(quán)協(xié)議,轉(zhuǎn)載請(qǐng)附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/weixin_39860919/article/details/112413273

浙公網(wǎng)安備 33010602011771號(hào)