1. 程式人生 > >基於TF-IDF演算法的短標題關鍵詞提取

基於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)