1 初始文本挖掘
1.1 何為文本挖掘
文本挖掘是指從大量文本數據中抽取事先未知的、可理解的、最終可用的知識的過程,同時運用這些知識更好地組織信息以便將來參考。
1.2 文本挖掘基本流程
文本挖掘的過程相似于又區別于數據挖掘。
參考:用 Python 做文本挖掘的流程
1.3 文本挖掘的應用
- 基于內容的推薦,例如基于小說內容相似度的小說的推薦
- 信息自動分類
- 信息自動抽取
- 自動問答、機器翻譯
- …….
2 Python的jieba模塊使用基礎
“結巴”中文分詞:做最好的Python 中文分詞組件
2.1 安裝(windows)
2.1.1 安裝步驟
- 打開cmd
- 輸入:pip install jieba,完成模塊安裝
- 在python環境:import jieba
2.1.2 文件結構與解析(部分)
我們可以注意到有一個dict.txt文件,這就是jieba模塊的基礎字典,也是其分詞的基礎,打開字典后有如下圖三列,分別表示詞語、詞頻與詞性:
其中對于詞性的對照具體參考:結巴分詞標注兼容_ICTCLAS2008漢語詞性標注集
2.2 分詞
2.2.1 分詞模式
在jieba分詞中支持三種分詞模式(默認為精準模式):
- 精確模式:試圖將句子最精確地切開,適合文本分析;
- 全模式:把句子中所有的可以成詞的詞語都掃描出來, 速度非常快,但是不能解決歧義;
- 搜索引擎模式:在精確模式的基礎上,對長詞再次切分,提高召回率,適合用于搜索引擎分詞。
實例
import jieba
testSentence = "利用python進行數據分析"
print("1.精準模式分詞結果:"+"/".join(jieba.cut(testSentence,cut_all=False)))
print("2.全模式分詞結果:"+"/".join(jieba.cut(testSentence,cut_all=True)))
print("3.搜索引擎模式分詞結果:"+"/".join(jieba.cut_for_search(testSentence)))
print("4.默認(精準模式)分詞結果:"+"/".join(jieba.cut(testSentence)))
結果
1.精準模式分詞結果:利用/python/進行/數據分析
2.全模式分詞結果:利用/python/進行/行數/數據/數據分析/分析
3.搜索引擎模式分詞結果:利用/python/進行/數據/分析/數據分析
4.默認(精準模式)分詞結果:利用/python/進行/數據分析
2.2.2 查看詞性
實例
import jieba.posseg
testSentence = "利用python進行數據分析"
words = jieba.posseg.cut(testSentence)
for item in words:
print(item.word+"----"+item.flag)
結果
利用----n
python----eng
進行----v
數據分析----l
2.3 添加自定義詞典
2.3.1 詞典加載
在分詞過程中我們會遇到一些jieba自帶的詞典中沒有的詞,比如隨意構造“簡書書院”
import jieba
#詞典加載
testSentence2="簡書書院是一個很好的交流平臺"
print("+---------+---------+---------+---------+---------+---------+---------+----")
print("1.加載詞典前分詞結果:")
print([item for item in jieba.posseg.cut(testSentence2)])
print("+---------+---------+---------+---------+---------+---------+---------+----")
jieba.load_userdict("C:/Anaconda3/Lib/site-packages/jieba/dict2.txt")
print("2.加載詞典后分詞結果:")
print([item for item in jieba.posseg.cut(testSentence2)])
結果如下:
+---------+---------+---------+---------+---------+---------+---------+----
1.加載詞典前分詞結果:
[pair('簡書', 'n'), pair('書院', 'n'), pair('是', 'v'), pair('一個', 'm'), pair('很好', 'a'), pair('的', 'uj'), pair('交流平臺', 'n')]
+---------+---------+---------+---------+---------+---------+---------+----
2.加載詞典后分詞結果:
[pair('簡書書院', 'x'), pair('是', 'v'), pair('一個', 'm'), pair('很好', 'a'), pair('的', 'uj'), pair('交流平臺', 'n')]
我們可以注意到簡書書院在加載自建字典夠能夠被精準地分出來。
在添加字典注意將txt文檔保存為utf-8編碼,如下圖示:
2.3.2 調整詞典
- 只能調高詞頻,不能調低詞頻
add_word(word, freq=None, tag=None)
suggest_freq(segment, tune=True) - 只能降低詞頻,不能調高詞頻
?del_word(word)
suggest_freq(("segmentPart1","segmentPart2"),True)
(1)調高詞頻
實例
import jieba
print("1.原始分詞結果:"+"/".join(jieba.cut("數據分析與數據挖掘的應用", HMM=False)))
jieba.add_word("的應用")
print("2.使用add_word(word, freq=None, tag=None)結果:"+"/".join(jieba.cut("數據分析與數據挖掘的應用", HMM=False)))
jieba.suggest_freq("的應用",tune=True)
print("3.使用suggest_freq(segment, tune=True)結果:"+"/".join(jieba.cut("數據分析與數據挖掘的應用", HMM=False)))
結果
1.原始分詞結果:數據分析/與/數據挖掘/的/應用
2.使用add_word(word, freq=None, tag=None)結果:數據分析/與/數據挖掘/的應用
3.使用suggest_freq(segment, tune=True)結果:數據分析/與/數據挖掘/的應用
(2)降低詞頻
實例
import jieba
jieba.suggest_freq(("中","將"),True)
print("使用suggest_freq(('segmentPart1','segmentPart2'),True)分詞結果:"+"/".join(jieba.cut("在簡書中將盡力呈現優質內容", HMM=False)))
結果
使用suggest_freq(('segmentPart1','segmentPart2'),True)分詞結果:在/簡/書/中/將/盡力/呈現/優質/內容
2.4分詞分析
進一步我們需要對文本信息進行相關分析,如返回詞語所在位置、返回關鍵詞等等。
2.4.1 返回詞語所在位置
實例
import jieba.analyse
print("1.采取精準模式結果:")
print([item for item in jieba.tokenize("數據分析與數據挖掘的應用")])
print("-------------------")
print("2.采取搜索模式結果:")
print([item for item in jieba.tokenize("數據分析與數據挖掘的應用",mode="search")])
結果
1.采取精準模式結果:
[('數據分析', 0, 4), ('與', 4, 5), ('數據挖掘', 5, 9), ('的', 9, 10), ('應用', 10, 12)]
-------------------
2.采取搜索模式結果:
[('數據', 0, 2), ('分析', 2, 4), ('數據分析', 0, 4), ('與', 4, 5), ('數據', 5, 7), ('挖掘', 7, 9), ('數據挖掘', 5, 9), ('的', 9, 10), ('應用', 10, 12)]
返回的數據格式為:[('詞語',開始位置,結束位置),...,()]
2.4.2 提取文本中的關鍵詞
實例
import jieba.analyse
print(jieba.analyse.extract_tags("我喜歡廣州小蠻腰",3))
print(jieba.analyse.extract_tags("我喜歡廣州廣州小蠻腰",3))
print(jieba.analyse.extract_tags("我喜歡廣州廣州廣州小蠻腰",3))
結果
['小蠻', '廣州', '喜歡']
['小蠻', '廣州', '喜歡']
['廣州', '小蠻', '喜歡']
其結果是結合文中出現的詞頻與字典中的詞頻進行排序。
3 文本相似度
在許多app中都有推薦功能,比如網易云音樂有每日歌曲推薦、某些閱讀軟件有書籍閱讀等等,一般的推薦模式有基于用戶和基于內容,其中基于內容的推薦可能就有計算到文本相似度,當然肯定還結合了其他維度,如音樂的風格等。同理在搜索引擎中也會根據與搜索關鍵詞的相似度對網頁進行排序。接下來將實現基于TF-IDF加權技術的文本相似度計算。
3.1 理論概念
語料庫:真實存在的語言材料
稀疏向量與稀疏矩陣
稀疏向量就是包含較多0值的向量,正常的向量可以拆分成值向量和順序向量,如稀疏向量(2,0,3,4,0,5,0,6)可用值向量(2,3,4,5,6)和順序向量(1,0,1,1,0,1,0,1)表示。
同理稀疏矩陣也類似,只不過稀疏矩陣可將元素轉換為三元組表,如矩陣[2 0 0 0;0 5 0 6]的三元組表為[2 1 1;5 2 2;6 2 4],其中第一個三元組表示矩陣中的元素2是在矩陣的第1行第1列的位置。TF-IDF:是一種用于資訊檢索與資訊探勘的常用加權技術。
(1)TF(term frequency)
詞頻,指的是某一個給定的詞語在該文檔中出現的頻率。計算公式為某詞在一個文檔中出現的次數除以所有字詞在該文檔中出現的次數。
其中以所有字詞在文檔中出現的系數作為分母目的在于將詞數進行歸一化是為了防止偏向長的文檔(不管該詞語重要與否,同一個詞語在長文檔里可能會比短文件有更高的詞數)。
(2)IDF(inverse document frequency)
逆向文件頻率,是一個詞語普遍重要性的度量。計算公式為總文檔數目除以包含該詞語之文件的數目,再將得到的商取對數。
(3)計算實例
詞語“母牛”在某一篇總詞語數為100個的文件出現了3次,該文件所在的語料庫的文件總數為10,000,000份,并且“母牛”在其中的1,000份文件出現過,那么“母牛”一詞在該文件中的詞頻就是3/100=0.03,其逆向文件頻率為 log(10,000,000 / 1,000)=4。最后的TF-IDF的分數為0.03 * 4=0.12。
參考:TF-IDF及其算法
3.2 計算步驟
- 文檔讀取
- 文檔分詞
- 文檔格式歸一化
- 統計詞頻,詞語過濾【可選】
- 通過語料庫建立詞典,并通過token2id獲取特征數提取詞典特征數
- 基于詞典建立新的語料庫
- 將新語料庫通過TF-IDF進行處理
- 讀取要對比的文檔,并將格式歸一化
- 將對比文檔轉化為稀疏向量
- 計算稀疏矩陣相似度,從而建立索引
- 打印輸出最終相似度
3.2 實戰
3.2.1 需求
假設我們有一個搜索引擎資源庫,里面包含sentence1,sentence2,sentence3三個句子,現在我們將要進行查詢并按相似度進行排序返回結果。
3.2.2 Python實現
'''
利用gensim做TF-IDF主題模型
'''
from gensim import corpora, models, similarities
import jieba
from collections import defaultdict
# 1.導入句子
sentence1 = "我喜歡吃番薯"
sentence2 = "番薯是個好東西"
sentence3 = "利用python進行文本挖掘"
# 2.分詞
data1 = " ".join(jieba.cut(sentence1))
data2 = " ".join(jieba.cut(sentence2))
data3 = " ".join(jieba.cut(sentence3))
# 3.轉換格式:"詞語1 詞語2 詞語3 … 詞語n"
texts = [list(data1), list(data2), list(data3)]
# 4.基于文本建立詞典
dictionary = corpora.Dictionary(texts)
featureNum=len(dictionary.token2id.keys())#提取詞典特征數
dictionary.save("./dictionary.txt")#保存語料庫
# 5.基于詞典建立新的語料庫
corpus = [dictionary.doc2bow(text) for text in texts]
# 6.TF-IDF處理
tfidf = models.TfidfModel(corpus)
'''
# 輸出每個句子每個詞語的tfidf值
corpus_tfidf = tfidf[corpus]
for doc in corpus_tfidf:
print(doc)
'''
# 7.加載對比句子并整理其格式
query = "吃東西"
data4 = jieba.cut(query)
data41 = ""
for item in data4:
data41 += item+" "
new_doc = data41
# 8.將對比句子轉換為稀疏向量
new_vec = dictionary.doc2bow(new_doc.split())
# 9.計算相似性
index = similarities.SparseMatrixSimilarity(tfidf[corpus],num_features=featureNum)
sim = index[tfidf[new_vec]]
for i in range(len(sim)):
print("查詢與第"+str(i+1)+"句話的相似度為:"+str(sim[i]))
注意:
官方文檔中提示建立的語料庫是存在內存中的一個列表格式,因此對于很大的語料庫,最好還是存在硬盤上,然后依次訪問文件。這樣可以不用考慮語料庫的大小,也避免了占用太多內存。
3.2.3 結果與分析
最終輸出結果如下:
查詢與第1句話的相似度為:0.399284
查詢與第2句話的相似度為:0.347683
查詢與第3句話的相似度為:0.0
我們可以看出查詢的句子“吃東西”與第一句話“我喜歡吃番薯”相似度最高,其次是第二句話“番薯是個好東西”,最后是第三句話,很明顯第一句話和第二句中的番薯是一種食物,故跟查詢的關鍵詞“吃東西”有相關,但是第三句話完全跟吃東西沒關,故返回的相似度為0,至于與第一句話的相似度為什么比第二句話高,這就需要考慮句子中具體的詞或詞語的TF-IDF值和余弦相似度了。
綜上,最終我們查詢返回的順序應如下:
(1)我喜歡吃番薯
(2)番薯是個好東西
(3)利用python進行文本挖掘
4 后記
實際上Python中的gensim模塊還提供了SVD、LDA等主題模型,有興趣的讀者可以繼續研究,另外對于文本挖掘有興趣的小伙伴可以參考[我愛自然語言處理]。(http://www.52nlp.cn/)
本文所有代碼只用于技術交流,拒絕任何商用活動
個人Github
后續的學習細節將會記錄在個人博客DebugNLP
中,歡迎各路同學互相交流