基於TF-IDF演算法抽取文章關鍵詞

0. 寫在前面

本文目的,利用TF-IDF演算法抽取一篇文章中的關鍵詞,關於TF-IDF,這裡放一篇阮一峰老師科普好文 。

TF-IDF與餘弦相似性的應用(一):自動提取關鍵詞 - 阮一峰的網路日誌

TF-IDF是一種統計方法,用以評估一字詞對於一個文件集或一個語料庫中的其中一份文件的重要程度。(百度百科)

TF(Term Frequency)詞頻,某個詞在文章中出現的次數或頻率,如果某篇文章中的某個詞出現多次,那這個詞可能是比較重要的詞,當然,停用詞不包括在這裡。

IDF(inverse document frequency)逆文檔頻率,這是一個詞語「權重」的度量,在詞頻的基礎上,如果一個詞在多篇文檔中詞頻較低,也就表示這是一個比較少見的詞,但在某一篇文章中卻出現了很多次,則這個詞IDF值越大,在這篇文章中的「權重」越大。所以當一個詞越常見,IDF越低。

當計算出TFIDF的值後,兩個一乘就得到TF-IDF,這個詞的TF-IDF越高就表示,就表示在這篇文章中的重要性越大,越有可能就是文章的關鍵詞。

而Python的scikit-learn包下有計算TF-IDF的API,我們就用這個來簡單的實現抽取文章關鍵詞。

這裡用到的文本數據材料則是《冰與火之歌》的1-5季(冰歌粉哈哈哈)

1. 數據採集

文本數據來源《冰與火之歌》小說在線閱讀網站的內容爬取,這個的網站很多,這裡就不貼出是哪一個了

爬取的難度不大,爬取下來之後寫入本地文件

2. 文檔分詞

爬取了所有文檔之後,後續為了計算TF和IDF值,首先要提取文檔中的所有詞語,利用python的jieba庫可以來進行中文分詞。

下面遍歷所有文件里所有文檔來分詞

import jieba nnwordslist = []ntitlelist = []n# 遍歷文件夾nfor file in os.listdir(.):n if . not in file:n # 遍歷文檔n for f in os.listdir(file):n # 標題n # windows下編碼問題添加:.decode(gbk, ignore).encode(utf-8))n titlelist.append(file+--+f.split(.)[0])n # 讀取文檔n with open(file + // + f, r) as f:n content = f.read().strip().replace(n, ).replace( , ).replace(t, ).replace(r, )n # 分詞n seg_list = jieba.cut(content, cut_all=True)n result = .join(seg_list)n wordslist.append(result)n

文檔分詞之後還需要去停用詞來提高抽取準確性,這裡先準備一個停用詞字典。

stop_word = [unicode(line.rstrip()) for line in open(chinese_stopword.txt)]nn...nseg_list = jieba.cut(content, cut_all=True)nseg_list_after = []n# 去停用詞nfor seg in seg_list:n if seg.word not in stop_word:n seg_list_after.append(seg)nresult = .join(seg_list_after)nwordslist.append(result)n

同時,我們還可以新增自選的詞典,提高程序糾錯能力,例如

jieba.add_word(u丹妮莉絲)n

3. scikit-learn的TF-IDF實現

(裝好anaconda之後,scikit-learn已經完成)

scikit-learn中TF-IDF權重計算方法主要用到CountVectorizer()類TfidfTransformer()類。

CountVectorizer類會將文本中的詞語轉換為詞頻矩陣。矩陣中word[ i ][ j ],它表示j詞在i類文本下的詞頻。

fit_transform(raw_documents[, y])Learn the vocabulary dictionary and return term-document matrix.get_feature_names()Array mapping from feature integer indices to feature name

fit_transform(),學習詞語詞典並返迴文檔矩陣,矩陣中元素為詞語出現的次數。

get_feature_names(),獲取特徵整數索引到特徵名稱映射的數組,即文檔中所有關鍵字的數組。

vectorizer = CountVectorizer()nword_frequence = vectorizer.fit_transform(wordslist)nwords = vectorizer.get_feature_names()n

TfidfTransformer類用於統計每個詞語的TF-IDF值。

transformer = TfidfTransformer()ntfidf = transformer.fit_transform(word_frequence)nweight = tfidf.toarray()n

最後按權重大小順序輸出前n位的詞語即可

def titlelist():n for file in os.listdir(.):n if . not in file:n for f in os.listdir(file):n yield (file+--+f.split(.)[0]) # windows下編碼問題添加:.decode(gbk, ignore).encode(utf-8))nndef wordslist():n jieba.add_word(u丹妮莉絲) n stop_word = [unicode(line.rstrip()) for line in open(chinese_stopword.txt)]n print len(stop_word)n for file in os.listdir(.):n if . not in file:n for f in os.listdir(file):n with open(file + // + f) as t:n content = t.read().strip().replace(n, ).replace( , ).replace(t, ).replace(r, )n seg_list = pseg.cut(content)n seg_list_after = []n # 去停用詞n for seg in seg_list:n if seg.word not in stop_word:n seg_list_after.append(seg.word)n result = .join(seg_list_after)n # wordslist.append(result)n yield resultn nnif __name__ == "__main__":nn wordslist = list(wordslist())n titlelist = list(titlelist())n n vectorizer = CountVectorizer()n transformer = TfidfTransformer()n tfidf = transformer.fit_transform(vectorizer.fit_transform(wordslist))n n words = vectorizer.get_feature_names() #所有文本的關鍵字n weight = tfidf.toarray()n n print ssssn n = 5 # 前五位n for (title, w) in zip(titlelist, weight):n print u{}:.format(title)n # 排序n loc = np.argsort(-w)n for i in range(n):n print u-{}: {} {}.format(str(i + 1), words[loc[i]], w[loc[i]])n print nn

運行結果

得到每篇文檔的關鍵詞。

4. 最後

參考資料:

[1]. TF-IDF與餘弦相似性的應用(一):自動提取關鍵詞 - 阮一峰的網路日誌

[2]. Python Package Index

[3]. sklearn.feature_extraction.text.CountVectorizer - scikit-learn 0.18.1 documentation

代碼GitHub:wzyonggege/tf-idf


推薦閱讀:

層疊注意力模型 - 實現機器閱讀的正確姿勢 | 論文訪談間 #04
<Neural Relation Extraction with Selective Attention over Instances>筆記
HIN2Vec:異質信息網路中的表示學習 | PaperDaily #18
如何處理不均衡數據?

TAG:Python | 文本挖掘 | 自然语言处理 |