文本相似度分析(基於jieba和gensim)



##基礎概念 本文在進行文本相似度分析過程分為以下幾個部分進行,
  • 文本分詞
  • 語料庫制作
  • 算法訓練
  • 結果預測

分析過程主要用兩個包來實現jieba,gensim
jieba:主要實現分詞過程
gensim:進行語料庫制作和算法訓練


##結巴(jieba)分詞

在自然語言處理領域中,分詞和提取關鍵詞都是對文本處理時通常要進行的步驟。用Python語言對英文文本進行預處理時可選擇NLTK庫,中文文本預處理可選擇jieba庫。結巴分詞是基於統計的分詞方法,它對給出大量已經分詞的文本,利用統計機器學習模型學習詞語切分的規律(稱為訓練),從而實現對未知文本的切分。例如最大概率分詞方法和最大熵分詞方法等。隨着大規模語料庫的建立,統計機器學習方法的研究和發展,基於統計的中文分詞方法漸漸成為了主流方法。


###jieba分詞的三種模式: * 精確模式:將句子最精確的分開,適合文本分析 * 全模式:句子中所有可以成詞的詞語都掃描出來,速度快,不能解決歧義 * 搜索引擎模式:在精確的基礎上,對長詞再次切分,提高召回

結巴分詞的其他特點諸如:支持繁體分詞,支持自定義詞典,基於Trie樹結構實現高效的詞圖掃描,采用了動態規划查找最大概率路徑等特點。


###jieba庫中分詞函數

1、jieba.cut()方法
參數string:需要接受分詞的字符串。
參數cut_all:控制是否采用全模式分詞發,參數為True時表示采用全模式。
參數HMM:控制是否使用HMM模型,參數為True時表示使用HMM模型。

2、jieba.cut_for_search()
參數string:需要接受分詞的字符串。
參數HMM:控制是否使用HMM模型,參數為True時表示使用HMM模型。

jieba.cut 以及 jieba.cut_for_search 返回的結構都是一個可迭代的 generator,可以使用 for 循環來獲得分詞后得到的每一個詞語。jieba.lcut和jieba.lcut_for_search參數和上面兩個方法一致但返回的是一個list。


###python上的分詞輸出對比
import jieba

string='上海市浦東新區世紀大道100號樓501'

#精准模式
text_cut=jieba.cut(string)
print(" ".join(text_cut))

#全模式
text_cut=jieba.cut(string,cut_all=True)
print(" ".join(text_cut))

#搜索模式
text_cut=jieba.cut_for_search(string)
print(" ".join(text_cut))

三種模式的輸出結果:
精准模式:上海市浦東新區 世紀 大道 100 號樓 501
全模式:上海 上海市 上海市浦東新區 海市 浦東 浦東新區 新區 世紀 紀大 大道 100 號 樓 501
搜索引擎模式:上海 海市 浦東 新區 上海市 上海市浦東新區 世紀 大道 100 號樓 501


###jieba分詞自定義字典

在使用jieba時,用戶除了直接對文本進行分詞外,還可以自行添加新詞,已達到優化分詞效果的目的。

1、加載自定義字典jieba.load_userdict()
參數filename:為文件類對象或自定義詞典的路徑
詞典格式分為3個部分:詞語、詞頻(可省略)、詞性(可省略),用空格隔開,順序不可顛倒。
file_name 若為路徑或二進制方式打開的文件,則文件必須為 UTF-8 編碼。

2、從字典中添加或刪除詞匯add_word、del_word
add_word(word,freq=None,tag=None),add_word有3個參數,添加詞名稱,詞頻,詞性
del_word(word),del_word只有一個參數詞語名稱

3、詞頻調整suggest_freq
suggest_freq(segment,tune=True)
調節單個詞語的詞頻,可以使其能(或不能)被分出來,詞頻越高在分詞時,能夠被分出來的概率越大。


###python示例
import jieba

#載入自定義詞典
jieba.load_userdict('word_dict.txt')

#查看用戶自定義詞典中的內容
print(jieba.user_word_tag_tab)

#往自定義詞典中添加新詞
jieba.add_word('人民廣場',freq=5,tag='n')

#添加新詞后的結果
print(jieba.user_word_tag_tab)

string='上海市浦東新區世紀大道100號樓501'
text_cut=jieba.cut(string)
print(" ".join(text_cut))

#調整詞頻,重新分詞
jieba.suggest_freq(('上海市','浦東新區'),tune=True)
text_cut=jieba.cut(string)
print(" ".join(text_cut))

輸出結果:
載入詞典內容:{'世紀大道': 'n', '浦東新區 2 ': 'n', '世紀公園 3 ': 'n'}
添加新詞后:{'世紀大道': 'n', '浦東新區 2 ': 'n', '世紀公園 3 ': 'n', '人民廣場': 'n'}
結巴原始字典庫,分詞結果:上海市浦東新區 世紀 大道 100 號樓 501
使用自定義詞典后,分詞結果:上海市浦東新區 世紀大道 100 號樓 501
調整詞頻后,分詞結果:上海市 浦東新區 世紀大道 100 號樓 501


結巴分詞官方文檔: https://pypi.org/project/jieba/

結巴分詞github地址:
https://github.com/fxsjy/jieba


##Gensim

Gensim是一款開源的第三方Python工具包,用於從原始的非結構化的文本中,無監督地學習到文本隱層的主題向量表達。
它支持包括TF-IDF,LSA,LDA,和word2vec在內的多種主題模型算法。


###相關概念
  • 語料(Corpus):一組原始文本的集合,用於無監督地訓練文本主題的隱層結構。在Gensim中,Corpus通常是一個可迭代的對象(比如列表)。每一次迭代返回一個可用於表達文本對象的稀疏向量。

  • 向量(Vector):由一組文本特征構成的列表。是一段文本在Gensim中的內部表達。在向量空間模型中,每個文檔被表示成了一組特征,比如,一個單一的特征可能被視為一個問答對。

  • 稀疏向量(SparseVector):通常,大部分問題的答案都是0,為了節約空間,我們會從文檔表示中省略他們,向量中的每一個元素是一個(key, value)的元組,比如(1,3),(2,4),(5,0),其中(5,0)是一個稀疏向量,在表示是會被忽略。

  • 模型(Model):是一個抽象的術語。定義了兩個向量空間的變換(即從文本的一種向量表達變換為另一種向量表達)。

把幾個概念組織起來表述:gensim可以通過讀取一段語料,輸出一個向量,表示文檔中的一個詞。為了節約空間,通常稀疏的詞向量會被忽略,剩下的詞向量則可以用來訓練各種模型,即從原有的文本表達轉向另一種文本表達。


###語料庫制作 語料庫制作主要包含兩個過程: 獲取詞袋:本文主要來自於結巴分詞結果 向量轉換:對獲取的詞袋進行向量轉換
1、獲取詞袋函數 gensim.corpora.Dictionary() gensim.corpora.dictionary.Dictionary可以為每個出現在語料庫中的單詞分配了一個獨一無二的整數編號id。這個操作收集了單詞計數及其他相關的統計信息。
###python示例
import jieba
import gensim

print(jieba.user_word_tag_tab)
string=['上海市浦東新區世紀大道100號樓501','上海市世紀大道100號樓501']

texts_list=[]
for sentence in string:
    sentence_list=[ word for word in jieba.cut(sentence)]
    texts_list.append(sentence_list)

dictionary=gensim.corpora.Dictionary(texts_list)
print(dictionary)
print(dictionary.token2id)

輸出結果:
Dictionary(7 unique tokens: ['100', '501', '上海市浦東新區', '世紀', '號樓']...)
{'100': 0, '501': 1, '上海市浦東新區': 2, '世紀': 3, '號樓': 4, '大道': 5, '上海市': 6}

第一行結果告訴我們語料庫中有7個不同的單詞,這表明每個文檔將會用7個數字表示(即7維向量)。
第二行結果是查看單詞與編號之間的映射關系。


2、向量轉換 dictionary.doc2bow() 函數doc2bow() 簡單地對每個不同單詞的出現次數進行了計數,並將單詞轉換為其編號,然后以稀疏向量的形式返回結果。
###python示例
corpus = [dictionary.doc2bow(doc) for doc in texts_list]
print(corpus)

輸出結果:
[[(0, 1), (1, 1), (2, 1), (3, 1), (4, 1), (5, 1)], [(0, 1), (1, 1), (3, 1), (4, 1), (5, 1), (6, 1)]]

以上結果中,表示兩個字符串中,每個詞的id以及它對應的出現頻次,比如第一個元組(0,1)代表的是編號為0的詞在第一個字符串中出現一次。


###算法訓練

下面我們使用tf-idf算法對上面的語料庫進行建模,識別不同文本的相似度。


###python示例
#測試字符串
test_string='浦東新區世紀大道100號樓501'
test_doc_list=[word for word in jieba.cut(test_string)]
test_doc_vec=dictionary.doc2bow(test_doc_list)

# 使用TF-IDF模型對語料庫建模
tfidf = gensim.models.TfidfModel(corpus)

#分析測試文檔與已存在的每個訓練文本的相似度
index = gensim.similarities.SparseMatrixSimilarity(tfidf[corpus], num_features=len(dictionary.keys()))
sim = index[tfidf[test_doc_vec]]

print(sim)

輸出結果:
[ 0.63650501 0.63650501 0. ]
表示測試文本與訓練的3個文本相似度分布0.63 0.63 0
以上就是使用jieba和gensim文本相似度的簡單實現.


gensim官方文檔: https://pypi.org/project/gensim/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM