基於TF-IDF演算法的短標題關鍵詞提取
開啟微信掃一掃,關注微信公眾號【資料與演算法聯盟】
轉載請註明出處:http://blog.csdn.net/gamer_gyt
博主微博:http://weibo.com/234654758
Github:https://github.com/thinkgamer
TF-IDF演算法介紹
TF-IDF(Term Frequency–InverseDocument Frequency)是一種用於資訊檢索與文字挖掘的常用加權技術。TF-IDF的主要思想是:如果某個詞或短語在一篇文章中出現的頻率TF高,並且在其他文章中很少出現,則認為此詞或者短語具有很好的類別區分能力,適合用來分類。
TF-IDF實際是TF*IDF,其中TF(Term Frequency)表示詞條t在文件Di中的出現的頻率,TF的計算公式如下所示:
TF-IDF實際是TF*IDF,其中TF(Term Frequency)表示詞條t在文件Di中的出現的頻率,TF的計算公式如下所示:
其中N為所有的文件總數,I(t,Di)表示文件Di是否包含詞條t,若包含為1,不包含為0。但此處存在一個問題,即當詞條t在所有文件中都沒有出現的話公式6.2的分母為0,此時就需要對IDF做平滑處理,改善後的IDF計算公式如下所示:
那麼最終詞條t在文件Di中的TF-IDF值為:TF-IDFt,Di = TFt,Di * IDFt 。
從上述的計算詞條t在文件Di中的TF-IDF值計算可以看出:當一個詞條在文件中出現的頻率越高,且新鮮度低(即普遍度低),則其對應的TF-IDF值越高。
比如現在有一個預料庫,包含了100篇(N)論文,其中涉及包含推薦系統(t)這個詞條的有20篇,在第一篇論文(D1)中總共有200個技術詞彙,其中推薦系統出現了15次,則詞條推薦系統的在第一篇論文(D1)中的TF-IDF值為:
短標題關鍵詞提取
廢話不多說,直接上程式碼,實現如下:
# -*-coding:utf-8-*-
"""
Data: 2018-08
Author: Thinkgamer
"""
import jieba
import math
import jieba.analyse
class TF_IDF:
def __init__(self,file,stop_file):
self.file = file
self.stop_file = stop_file
self.stop_words = self.getStopWords()
# 獲取停用詞列表
def getStopWords(self):
swlist=list()
for line in open(self.stop_file,"r",encoding="utf-8").readlines():
swlist.append(line.strip())
print("載入停用詞完成...")
return swlist
# 載入商品和其對應的短標題,使用jieba進行分詞並去除停用詞
def loadData(self):
dMap = dict()
for line in open(self.file,"r",encoding="utf-8").readlines():
id,title = line.strip().split("\t")
dMap.setdefault(id, [])
for word in list(jieba.cut(str(title).replace(" ",""), cut_all=False)):
if word not in self.stop_words:
dMap[id].append(word)
print("載入商品和對應的短標題,並使用jieba分詞和去除停用詞完成...")
return dMap
# 獲取一個短標題中的詞頻
def getFreqWord(self,words):
freqWord = dict()
for word in words:
freqWord.setdefault(word,0)
freqWord[word] += 1
return freqWord
# 統計單詞在所有短標題中出現的次數
def getCountWordInFile(self,word,dMap):
count = 0
for key in dMap.keys():
if word in dMap[key]:
count += 1
return count
# 計算TFIDF值
def getTFIDF(self,words,dMap):
# 記錄單詞關鍵詞和對應的tfidf值
outDic = dict()
freqWord = self.getFreqWord(words)
for word in words:
# 計算TF值,即單個word在整句中出現的次數
tf = freqWord[word]*1.0 / len(words)
# 計算IDF值,即log(所有的標題數/(包含單個word的標題數+1))
idf = math.log(len(dMap)/(self.getCountWordInFile(word,dMap)+1))
tfidf = tf * idf
outDic[word] = tfidf
# 給字典排序
orderDic = sorted(outDic.items(), key=lambda x:x[1], reverse=True)
return orderDic
def getTag(self,words):
# withWeight 用來設定是否列印權重
print(jieba.analyse.extract_tags(words, topK=20, withWeight=True))
if __name__ == "__main__":
# 資料集
file = "data/id_title.txt"
# 停用詞檔案
stop_file = "data/stop_words.txt"
tfidf=TF_IDF(file,stop_file)
tfidf.getTag(open("data/one","r",encoding="utf-8").read(),)
# dMap 中key為商品id,value為去除停用詞後的詞
# dMap = tfidf.loadData()
# for id in dMap.keys():
# tfIdfDic = tfidf.getTFIDF(dMap[id],dMap)
# print(id,tfIdfDic)