zoukankan      html  css  js  c++  java
  • TF-IDF提取行业关键词

    1. TF-IDF简介

    TF-IDF(Term Frequency/Inverse Document Frequency)是信息检索领域非常重要的搜索词重要性度量;用以衡量一个关键词(w)对于查询(Query,可看作文档)所能提供的信息。词频(Term Frequency, TF)表示关键词(w)在文档(D_i)中出现的频率:

    [TF_{w,D_i}= frac {count(w)} {left| D_i ight|} ]

    其中,(count(w))为关键词(w)的出现次数,(left| D_i ight|)为文档(D_i)中所有词的数量。逆文档频率(Inverse Document Frequency, IDF)反映关键词的普遍程度——当一个词越普遍(即有大量文档包含这个词)时,其IDF值越低;反之,则IDF值越高。IDF定义如下:

    [IDF_w=log frac {N}{sum_{i=1}^N I(w,D_i)} ]

    其中,(N)为所有的文档总数,(I(w,D_i))表示文档(D_i)是否包含关键词,若包含则为1,若不包含则为0。若词(w)在所有文档中均未出现,则IDF公式中的分母为0;因此需要对IDF做平滑(smooth):

    [IDF_w=log frac {N}{1+sum_{i=1}^N I(w,D_i)} ]

    关键词(w)在文档(D_i)的TF-IDF值:

    [TF-IDF_{w,D_i}=TF_{w,D_i}*IDF_w ]

    从上述定义可以看出:

    • 当一个词在文档频率越高并且新鲜度高(即普遍度低),其TF-IDF值越高。
    • TF-IDF兼顾词频与新鲜度,过滤一些常见词,保留能提供更多信息的重要词。

    TF-IDF模型的概率解释》从概率的角度给出TF-IDF的数学解释,《The Vector Space Model of text》为TF-IDF的实操教程,包括TF-IDF的一般计算、正则化,以及如何使用scikit-learn(sklearn)来计算TF-IDF矩阵。

    2. 关键词提取

    最近碰到一个需求,挖掘行业关键词;比如,IT行业的关键词有:Java、Python、机器学习等。TF-IDF正好可用来做关键词的抽取,词TF-IDF值越大,则说明该词为关键词。那么,问题来了:如何套用TF-IDF模型呢?

    模型套用

    为了做关键词挖掘,首先得有数据;我们从某招聘网站爬取了20个行业招聘信息数据。然后,对数据进行分词。我们发现,行业关键词具有领域特定性,即一个行业的关键词一般不会同属于另外几个行业。因此,我们每一个行业的分词结果作为一个大doc,则doc的总数量为20。用sklearn计算TF-IDF矩阵,取每个行业top词。

    在上述模型套用中,因为doc总数少,发现top词中会有一些常见词,诸如“认真负责”、“岗位”之类。为了过滤常见词,采取两个办法:

    • jieba分词对每一条招聘信息做关键词抽取(也是基于TF-IDF),如此能在生成大doc时剔除掉部分常见词。
    • 引入max_df,如果词的df超过某一阈值则被词表过滤。

    代码实现

    分词采用的jieba,如果觉得分词效果不太理想,可采用百度词条作为自定义分词词典;TF-IDF计算依赖于sklearn;求matrix 的row top则用到了numpy。具体代码如下:

    # -*- coding: utf-8 -*-
    # @Time    : 2016/9/6
    # @Author  : rain
    import codecs
    import os
    
    import jieba.analyse
    import numpy as np
    import pandas as pd
    from sklearn.feature_extraction.text import TfidfVectorizer
    
    base_path = "./resources/corpus/"
    seg_path = "./resources/segmented/"
    
    
    def segment():
        """word segment"""
        for txt in os.listdir(base_path):
            whole_base = os.path.join(base_path, txt)
            whole_seg = os.path.join(seg_path, txt)
            with codecs.open(whole_base, 'r', 'utf-8') as fr:
                fw = codecs.open(whole_seg, 'w', 'utf-8')
                for line in fr.readlines():
                    # seg_list = jieba.cut(line.strip())
                    seg_list = jieba.analyse.extract_tags(line.strip(), topK=20, withWeight=False, allowPOS=())
                    fw.write(" ".join(seg_list))
                fw.close()
    
    
    def read_doc_list():
        """read segmented docs"""
        trade_list = []
        doc_list = []
        for txt in os.listdir(seg_path):
            trade_list.append(txt.split(".")[0])
            with codecs.open(os.path.join(seg_path, txt), "r", "utf-8") as fr:
                doc_list.append(fr.read().replace('
    ', ''))
        return trade_list, doc_list
    
    
    def tfidf_top(trade_list, doc_list, max_df, topn):
        vectorizer = TfidfVectorizer(max_df=max_df)
        matrix = vectorizer.fit_transform(doc_list)
        feature_dict = {v: k for k, v in vectorizer.vocabulary_.items()}  # index -> feature_name
        top_n_matrix = np.argsort(-matrix.todense())[:, :topn]  # top tf-idf words for each row
        df = pd.DataFrame(np.vectorize(feature_dict.get)(top_n_matrix), index=trade_list)  # convert matrix to df
        return df
    
    
    segment()
    tl, dl = read_doc_list()
    tdf = tfidf_top(tl, dl, max_df=0.3, topn=500)
    tdf.to_csv("./resources/keywords.txt", header=False, encoding='utf-8')
    
    
  • 相关阅读:
    Windows 设置自启动计划任务(非登录启动)
    C# 计算代码执行时间
    使用RabbitMQ做数据接收和处理时,自动关闭
    Winform 连接Web Service 记录
    【转】DataTable 中数据筛选
    更改数据库管理员sa账户密码
    数据库显示可疑的修复方法
    SQL SERVER 2008 删除某个数据库的所有连接进程
    数据库自动备份还原成新库脚本
    关于BindingSource 组件的一些用法
  • 原文地址:https://www.cnblogs.com/en-heng/p/5848553.html
Copyright © 2011-2022 走看看