美文网首页
基于TF-IDF的关键词提取

基于TF-IDF的关键词提取

作者: 时间里的小恶魔 | 来源:发表于2019-10-31 16:28 被阅读0次
    • TF-IDF(Term Frequency-Inverse Document Frequency, 词频-逆文件频率). 一个词语在一篇文章中出现次数越多, 同时在所有文档中出现次数越少, 越能够代表该文章.这也就是TF-IDF的含义.
    • 词频 (term frequency, TF) 指的是某一个给定的词语在该文件中出现的次数。这个数字通常会被归一化(一般是词频除以文章总词数), 以防止它偏向长的文件。(同一个词语在长文件里可能会比短文件有更高的词频,而不管该词语重要与否。)公式为:


      TF计算公式
    • 逆向文件频率 (inverse document frequency, IDF) IDF的主要思想是:如果包含词条t的文档越少, IDF越大,则说明词条具有很好的类别区分能力。某一特定词语的IDF,可以由总文件数目除以包含该词语之文件的数目,再将得到的商取对数得到。计算公式为:


      IDF计算公式
    • 则TF-IDF的计算公式为:


      TF-IDF的计算公式
    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 = "/Users/zhangyulong/Documents/study/recommonder/code/data/phone-title/id_title.txt"
        # 停用词文件
        stop_file = "/Users/zhangyulong/Documents/study/recommonder/code/data/phone-title/stop_words.txt"
    
        tfidf = TF_IDF(file, stop_file)
        # tfidf.getTag("小米 红米6Pro 异形全面屏, 后置1200万双摄, 4000mAh超大电池")
    
        # dMap 中key为商品id,value为去除停用词后的词
        dMap = tfidf.loadData()
        for id in dMap.keys():
            tfIdfDic = tfidf.getTFIDF(dMap[id],dMap)
            print(id,tfIdfDic)
    

    数据集格式为:

    5594    小米 红米6Pro 异形全面屏, 后置1200万双摄, 4000mAh超大电池
    5363    小米粿x20S刘海屏 全网通4G智能手机游戏6G运行128G 千元指纹人脸
    7901    Xiaomi/小米 小米6手机6骁龙835手机陶瓷尊享版米8全网通4G白蓝色
    7059    小米粿X9 -8全面屏6寸智能正品手机游戏6G运行128G 指纹人脸解锁
    7020    直降100元 官方正品一加6 OnePlus/一加 A6000 一加6手机一加6t 一加六 一加5 1+6限量全网通
    2936    全新 OnePlus/一加 一加手机5全网通一加5手机一加5星辰黑128G
    
    8813 [('一加', 0.6931471805599453), ('\xa0', 0.304514560702321), ('5t', 0.23055496588212102), ('全网', 0.23055496588212102), ('OnePlus', 0.18723326709712443), ('发', 0.16189169784036417), ('当天', 0.14391156831212787), ('现货', 0.10893558156616394), ('4G', 0.06788686054184703), ('手机', 0.05084114446885693)]
    5735 [('一加', 0.5941261547656673), ('\xa0', 0.3480166408026526), ('高通', 0.26349138957956686), ('835', 0.23452959614326943), ('OnePlus', 0.2139808766824279), ('骁龙', 0.2139808766824279), ('128G', 0.1740083204013263), ('全', 0.06544933799101108), ('网通', 0.05904846951317628), ('手机', 0.03873611007151004)]
    6835 [('八核', 0.26349138957956686), ('变焦', 0.26349138957956686), ('荣耀', 0.2130935538253881), ('指纹', 0.19804205158855578), ('解锁', 0.19804205158855578), ('双卡', 0.18501908324613048), ('双待', 0.18501908324613048), ('双摄', 0.18501908324613048), ('智能手机', 0.11956974525511939), ('honor', 0.11495985088815001), ('4G', 0.0775849834763966), ('全', 0.06544933799101108), ('网通', 0.05904846951317628)]
    4807 [('高配', 0.28375995800876436), ('荣耀', 0.2294853656581103), ('双卡', 0.19925132041890975), ('双待', 0.19925132041890975), ('64G', 0.18739357581681296), ('128G', 0.18739357581681296), ('智能手机', 0.12876741796705166), ('honor', 0.12380291634108465), ('4G', 0.08355305912842712), ('正品', 0.07292611001451811), ('全', 0.0704839024518581), ('网通', 0.0635906594757283)]
    5050 [('520', 0.26349138957956686), ('直降', 0.2139808766824279), ('荣耀', 0.2130935538253881), ('元', 0.13550857034899152), ('华为', 0.11495985088815001), ('honor', 0.11495985088815001), ('智能', 0.10654677691269406), ('官方', 0.09221315580825469), ('4G', 0.0775849834763966), ('正品', 0.06771710215633824), ('全', 0.06544933799101108), ('网通', 0.05904846951317628), ('手机', 0.01936805503575502)]
    6679 [('送豪礼', 0.28375995800876436), ('荣耀', 0.2294853656581103), ('运行', 0.21327605555690626), ('内存', 0.21327605555690626), ('指纹', 0.21327605555690626), ('解锁', 0.21327605555690626), ('6G', 0.19925132041890975), ('128G', 0.18739357581681296), ('智能手机', 0.12876741796705166), ('honor', 0.12380291634108465), ('全', 0.0704839024518581), ('网通', 0.0635906594757283)]
    

    相关文章

      网友评论

          本文标题:基于TF-IDF的关键词提取

          本文链接:https://www.haomeiwen.com/subject/rfjtbctx.html