
1 初始文本挖掘
1.1 何為文本挖掘
文本挖掘是指從大量文本數(shù)據(jù)中抽取事先未知的、可理解的、最終可用的知識(shí)的過(guò)程,同時(shí)運(yùn)用這些知識(shí)更好地組織信息以便將來(lái)參考。
1.2 文本挖掘基本流程
文本挖掘的過(guò)程相似于又區(qū)別于數(shù)據(jù)挖掘。

參考:用 Python 做文本挖掘的流程
1.3 文本挖掘的應(yīng)用
- 基于內(nèi)容的推薦,例如基于小說(shuō)內(nèi)容相似度的小說(shuō)的推薦
- 信息自動(dòng)分類(lèi)
- 信息自動(dòng)抽取
- 自動(dòng)問(wèn)答、機(jī)器翻譯
- …….
2 Python的jieba模塊使用基礎(chǔ)
“結(jié)巴”中文分詞:做最好的Python 中文分詞組件
2.1 安裝(windows)
2.1.1 安裝步驟
- 打開(kāi)cmd
- 輸入:pip install jieba,完成模塊安裝
- 在python環(huán)境:import jieba
2.1.2 文件結(jié)構(gòu)與解析(部分)

我們可以注意到有一個(gè)dict.txt文件,這就是jieba模塊的基礎(chǔ)字典,也是其分詞的基礎(chǔ),打開(kāi)字典后有如下圖三列,分別表示詞語(yǔ)、詞頻與詞性:

其中對(duì)于詞性的對(duì)照具體參考:結(jié)巴分詞標(biāo)注兼容_ICTCLAS2008漢語(yǔ)詞性標(biāo)注集
2.2 分詞
2.2.1 分詞模式
在jieba分詞中支持三種分詞模式(默認(rèn)為精準(zhǔn)模式):
- 精確模式:試圖將句子最精確地切開(kāi),適合文本分析;
- 全模式:把句子中所有的可以成詞的詞語(yǔ)都掃描出來(lái), 速度非???,但是不能解決歧義;
- 搜索引擎模式:在精確模式的基礎(chǔ)上,對(duì)長(zhǎng)詞再次切分,提高召回率,適合用于搜索引擎分詞。
實(shí)例
import jieba
testSentence = "利用python進(jìn)行數(shù)據(jù)分析"
print("1.精準(zhǔn)模式分詞結(jié)果:"+"/".join(jieba.cut(testSentence,cut_all=False)))
print("2.全模式分詞結(jié)果:"+"/".join(jieba.cut(testSentence,cut_all=True)))
print("3.搜索引擎模式分詞結(jié)果:"+"/".join(jieba.cut_for_search(testSentence)))
print("4.默認(rèn)(精準(zhǔn)模式)分詞結(jié)果:"+"/".join(jieba.cut(testSentence)))
結(jié)果
1.精準(zhǔn)模式分詞結(jié)果:利用/python/進(jìn)行/數(shù)據(jù)分析
2.全模式分詞結(jié)果:利用/python/進(jìn)行/行數(shù)/數(shù)據(jù)/數(shù)據(jù)分析/分析
3.搜索引擎模式分詞結(jié)果:利用/python/進(jìn)行/數(shù)據(jù)/分析/數(shù)據(jù)分析
4.默認(rèn)(精準(zhǔn)模式)分詞結(jié)果:利用/python/進(jìn)行/數(shù)據(jù)分析
2.2.2 查看詞性
實(shí)例
import jieba.posseg
testSentence = "利用python進(jìn)行數(shù)據(jù)分析"
words = jieba.posseg.cut(testSentence)
for item in words:
print(item.word+"----"+item.flag)
結(jié)果
利用----n
python----eng
進(jìn)行----v
數(shù)據(jù)分析----l
2.3 添加自定義詞典
2.3.1 詞典加載
在分詞過(guò)程中我們會(huì)遇到一些jieba自帶的詞典中沒(méi)有的詞,比如隨意構(gòu)造“簡(jiǎn)書(shū)書(shū)院”
import jieba
#詞典加載
testSentence2="簡(jiǎn)書(shū)書(shū)院是一個(gè)很好的交流平臺(tái)"
print("+---------+---------+---------+---------+---------+---------+---------+----")
print("1.加載詞典前分詞結(jié)果:")
print([item for item in jieba.posseg.cut(testSentence2)])
print("+---------+---------+---------+---------+---------+---------+---------+----")
jieba.load_userdict("C:/Anaconda3/Lib/site-packages/jieba/dict2.txt")
print("2.加載詞典后分詞結(jié)果:")
print([item for item in jieba.posseg.cut(testSentence2)])
結(jié)果如下:
+---------+---------+---------+---------+---------+---------+---------+----
1.加載詞典前分詞結(jié)果:
[pair('簡(jiǎn)書(shū)', 'n'), pair('書(shū)院', 'n'), pair('是', 'v'), pair('一個(gè)', 'm'), pair('很好', 'a'), pair('的', 'uj'), pair('交流平臺(tái)', 'n')]
+---------+---------+---------+---------+---------+---------+---------+----
2.加載詞典后分詞結(jié)果:
[pair('簡(jiǎn)書(shū)書(shū)院', 'x'), pair('是', 'v'), pair('一個(gè)', 'm'), pair('很好', 'a'), pair('的', 'uj'), pair('交流平臺(tái)', 'n')]
我們可以注意到簡(jiǎn)書(shū)書(shū)院在加載自建字典夠能夠被精準(zhǔn)地分出來(lái)。
在添加字典注意將txt文檔保存為utf-8編碼,如下圖示:

2.3.2 調(diào)整詞典
- 只能調(diào)高詞頻,不能調(diào)低詞頻
add_word(word, freq=None, tag=None)
suggest_freq(segment, tune=True) - 只能降低詞頻,不能調(diào)高詞頻
?del_word(word)
suggest_freq(("segmentPart1","segmentPart2"),True)
(1)調(diào)高詞頻
實(shí)例
import jieba
print("1.原始分詞結(jié)果:"+"/".join(jieba.cut("數(shù)據(jù)分析與數(shù)據(jù)挖掘的應(yīng)用", HMM=False)))
jieba.add_word("的應(yīng)用")
print("2.使用add_word(word, freq=None, tag=None)結(jié)果:"+"/".join(jieba.cut("數(shù)據(jù)分析與數(shù)據(jù)挖掘的應(yīng)用", HMM=False)))
jieba.suggest_freq("的應(yīng)用",tune=True)
print("3.使用suggest_freq(segment, tune=True)結(jié)果:"+"/".join(jieba.cut("數(shù)據(jù)分析與數(shù)據(jù)挖掘的應(yīng)用", HMM=False)))
結(jié)果
1.原始分詞結(jié)果:數(shù)據(jù)分析/與/數(shù)據(jù)挖掘/的/應(yīng)用
2.使用add_word(word, freq=None, tag=None)結(jié)果:數(shù)據(jù)分析/與/數(shù)據(jù)挖掘/的應(yīng)用
3.使用suggest_freq(segment, tune=True)結(jié)果:數(shù)據(jù)分析/與/數(shù)據(jù)挖掘/的應(yīng)用
(2)降低詞頻
實(shí)例
import jieba
jieba.suggest_freq(("中","將"),True)
print("使用suggest_freq(('segmentPart1','segmentPart2'),True)分詞結(jié)果:"+"/".join(jieba.cut("在簡(jiǎn)書(shū)中將盡力呈現(xiàn)優(yōu)質(zhì)內(nèi)容", HMM=False)))
結(jié)果
使用suggest_freq(('segmentPart1','segmentPart2'),True)分詞結(jié)果:在/簡(jiǎn)/書(shū)/中/將/盡力/呈現(xiàn)/優(yōu)質(zhì)/內(nèi)容
2.4分詞分析
進(jìn)一步我們需要對(duì)文本信息進(jìn)行相關(guān)分析,如返回詞語(yǔ)所在位置、返回關(guān)鍵詞等等。
2.4.1 返回詞語(yǔ)所在位置
實(shí)例
import jieba.analyse
print("1.采取精準(zhǔn)模式結(jié)果:")
print([item for item in jieba.tokenize("數(shù)據(jù)分析與數(shù)據(jù)挖掘的應(yīng)用")])
print("-------------------")
print("2.采取搜索模式結(jié)果:")
print([item for item in jieba.tokenize("數(shù)據(jù)分析與數(shù)據(jù)挖掘的應(yīng)用",mode="search")])
結(jié)果
1.采取精準(zhǔn)模式結(jié)果:
[('數(shù)據(jù)分析', 0, 4), ('與', 4, 5), ('數(shù)據(jù)挖掘', 5, 9), ('的', 9, 10), ('應(yīng)用', 10, 12)]
-------------------
2.采取搜索模式結(jié)果:
[('數(shù)據(jù)', 0, 2), ('分析', 2, 4), ('數(shù)據(jù)分析', 0, 4), ('與', 4, 5), ('數(shù)據(jù)', 5, 7), ('挖掘', 7, 9), ('數(shù)據(jù)挖掘', 5, 9), ('的', 9, 10), ('應(yīng)用', 10, 12)]
返回的數(shù)據(jù)格式為:[('詞語(yǔ)',開(kāi)始位置,結(jié)束位置),...,()]
2.4.2 提取文本中的關(guān)鍵詞
實(shí)例
import jieba.analyse
print(jieba.analyse.extract_tags("我喜歡廣州小蠻腰",3))
print(jieba.analyse.extract_tags("我喜歡廣州廣州小蠻腰",3))
print(jieba.analyse.extract_tags("我喜歡廣州廣州廣州小蠻腰",3))
結(jié)果
['小蠻', '廣州', '喜歡']
['小蠻', '廣州', '喜歡']
['廣州', '小蠻', '喜歡']
其結(jié)果是結(jié)合文中出現(xiàn)的詞頻與字典中的詞頻進(jìn)行排序。
3 文本相似度
在許多app中都有推薦功能,比如網(wǎng)易云音樂(lè)有每日歌曲推薦、某些閱讀軟件有書(shū)籍閱讀等等,一般的推薦模式有基于用戶和基于內(nèi)容,其中基于內(nèi)容的推薦可能就有計(jì)算到文本相似度,當(dāng)然肯定還結(jié)合了其他維度,如音樂(lè)的風(fēng)格等。同理在搜索引擎中也會(huì)根據(jù)與搜索關(guān)鍵詞的相似度對(duì)網(wǎng)頁(yè)進(jìn)行排序。接下來(lái)將實(shí)現(xiàn)基于TF-IDF加權(quán)技術(shù)的文本相似度計(jì)算。
3.1 理論概念
語(yǔ)料庫(kù):真實(shí)存在的語(yǔ)言材料
稀疏向量與稀疏矩陣
稀疏向量就是包含較多0值的向量,正常的向量可以拆分成值向量和順序向量,如稀疏向量(2,0,3,4,0,5,0,6)可用值向量(2,3,4,5,6)和順序向量(1,0,1,1,0,1,0,1)表示。
同理稀疏矩陣也類(lèi)似,只不過(guò)稀疏矩陣可將元素轉(zhuǎn)換為三元組表,如矩陣[2 0 0 0;0 5 0 6]的三元組表為[2 1 1;5 2 2;6 2 4],其中第一個(gè)三元組表示矩陣中的元素2是在矩陣的第1行第1列的位置。TF-IDF:是一種用于資訊檢索與資訊探勘的常用加權(quán)技術(shù)。
(1)TF(term frequency)
詞頻,指的是某一個(gè)給定的詞語(yǔ)在該文檔中出現(xiàn)的頻率。計(jì)算公式為某詞在一個(gè)文檔中出現(xiàn)的次數(shù)除以所有字詞在該文檔中出現(xiàn)的次數(shù)。
其中以所有字詞在文檔中出現(xiàn)的系數(shù)作為分母目的在于將詞數(shù)進(jìn)行歸一化是為了防止偏向長(zhǎng)的文檔(不管該詞語(yǔ)重要與否,同一個(gè)詞語(yǔ)在長(zhǎng)文檔里可能會(huì)比短文件有更高的詞數(shù))。
(2)IDF(inverse document frequency)
逆向文件頻率,是一個(gè)詞語(yǔ)普遍重要性的度量。計(jì)算公式為總文檔數(shù)目除以包含該詞語(yǔ)之文件的數(shù)目,再將得到的商取對(duì)數(shù)。
(3)計(jì)算實(shí)例
詞語(yǔ)“母?!痹谀骋黄傇~語(yǔ)數(shù)為100個(gè)的文件出現(xiàn)了3次,該文件所在的語(yǔ)料庫(kù)的文件總數(shù)為10,000,000份,并且“母牛”在其中的1,000份文件出現(xiàn)過(guò),那么“母?!币辉~在該文件中的詞頻就是3/100=0.03,其逆向文件頻率為 log(10,000,000 / 1,000)=4。最后的TF-IDF的分?jǐn)?shù)為0.03 * 4=0.12。
參考:TF-IDF及其算法
3.2 計(jì)算步驟
- 文檔讀取
- 文檔分詞
- 文檔格式歸一化
- 統(tǒng)計(jì)詞頻,詞語(yǔ)過(guò)濾【可選】
- 通過(guò)語(yǔ)料庫(kù)建立詞典,并通過(guò)token2id獲取特征數(shù)提取詞典特征數(shù)
- 基于詞典建立新的語(yǔ)料庫(kù)
- 將新語(yǔ)料庫(kù)通過(guò)TF-IDF進(jìn)行處理
- 讀取要對(duì)比的文檔,并將格式歸一化
- 將對(duì)比文檔轉(zhuǎn)化為稀疏向量
- 計(jì)算稀疏矩陣相似度,從而建立索引
- 打印輸出最終相似度
3.2 實(shí)戰(zhàn)
3.2.1 需求
假設(shè)我們有一個(gè)搜索引擎資源庫(kù),里面包含sentence1,sentence2,sentence3三個(gè)句子,現(xiàn)在我們將要進(jìn)行查詢并按相似度進(jìn)行排序返回結(jié)果。
3.2.2 Python實(shí)現(xiàn)
'''
利用gensim做TF-IDF主題模型
'''
from gensim import corpora, models, similarities
import jieba
from collections import defaultdict
# 1.導(dǎo)入句子
sentence1 = "我喜歡吃番薯"
sentence2 = "番薯是個(gè)好東西"
sentence3 = "利用python進(jìn)行文本挖掘"
# 2.分詞
data1 = " ".join(jieba.cut(sentence1))
data2 = " ".join(jieba.cut(sentence2))
data3 = " ".join(jieba.cut(sentence3))
# 3.轉(zhuǎn)換格式:"詞語(yǔ)1 詞語(yǔ)2 詞語(yǔ)3 … 詞語(yǔ)n"
texts = [list(data1), list(data2), list(data3)]
# 4.基于文本建立詞典
dictionary = corpora.Dictionary(texts)
featureNum=len(dictionary.token2id.keys())#提取詞典特征數(shù)
dictionary.save("./dictionary.txt")#保存語(yǔ)料庫(kù)
# 5.基于詞典建立新的語(yǔ)料庫(kù)
corpus = [dictionary.doc2bow(text) for text in texts]
# 6.TF-IDF處理
tfidf = models.TfidfModel(corpus)
'''
# 輸出每個(gè)句子每個(gè)詞語(yǔ)的tfidf值
corpus_tfidf = tfidf[corpus]
for doc in corpus_tfidf:
print(doc)
'''
# 7.加載對(duì)比句子并整理其格式
query = "吃東西"
data4 = jieba.cut(query)
data41 = ""
for item in data4:
data41 += item+" "
new_doc = data41
# 8.將對(duì)比句子轉(zhuǎn)換為稀疏向量
new_vec = dictionary.doc2bow(new_doc.split())
# 9.計(jì)算相似性
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]))
注意:
官方文檔中提示建立的語(yǔ)料庫(kù)是存在內(nèi)存中的一個(gè)列表格式,因此對(duì)于很大的語(yǔ)料庫(kù),最好還是存在硬盤(pán)上,然后依次訪問(wèn)文件。這樣可以不用考慮語(yǔ)料庫(kù)的大小,也避免了占用太多內(nèi)存。
3.2.3 結(jié)果與分析
最終輸出結(jié)果如下:
查詢與第1句話的相似度為:0.399284
查詢與第2句話的相似度為:0.347683
查詢與第3句話的相似度為:0.0
我們可以看出查詢的句子“吃東西”與第一句話“我喜歡吃番薯”相似度最高,其次是第二句話“番薯是個(gè)好東西”,最后是第三句話,很明顯第一句話和第二句中的番薯是一種食物,故跟查詢的關(guān)鍵詞“吃東西”有相關(guān),但是第三句話完全跟吃東西沒(méi)關(guān),故返回的相似度為0,至于與第一句話的相似度為什么比第二句話高,這就需要考慮句子中具體的詞或詞語(yǔ)的TF-IDF值和余弦相似度了。
綜上,最終我們查詢返回的順序應(yīng)如下:
(1)我喜歡吃番薯
(2)番薯是個(gè)好東西
(3)利用python進(jìn)行文本挖掘
4 后記
實(shí)際上Python中的gensim模塊還提供了SVD、LDA等主題模型,有興趣的讀者可以繼續(xù)研究,另外對(duì)于文本挖掘有興趣的小伙伴可以參考[我愛(ài)自然語(yǔ)言處理]。(http://www.52nlp.cn/)
本文所有代碼只用于技術(shù)交流,拒絕任何商用活動(dòng)
個(gè)人Github
后續(xù)的學(xué)習(xí)細(xì)節(jié)將會(huì)記錄在個(gè)人博客DebugNLP
中,歡迎各路同學(xué)互相交流