文档章节

基于特定语料库的TF-IDF关键词提取实现

Gaussic
 Gaussic
发布于 2017/08/08 17:17
字数 944
阅读 186
收藏 0
点赞 0
评论 2

本文旨在对特定的语料库生成各词的逆文档频率。然后根据TF-IDF算法进行关键词提取。

转载请注明出处:Gaussic(自然语言处理)

GitHub代码:https://github.com/gaussic/tf-idf-keyword

分词

对于中文文本的关键词提取,需要先进行分词操作,本文采用全模式的结巴分词器进行分词。使用全模式的一个优势是可以对原始数据进行增益。如果不需要可以将cut_all修改为默认False。

去除其中的一些英文和数字,只保留中文:

import jieba
import re

def segment(sentence, cut_all=True):
    sentence = re.sub('[a-zA-Z0-9]', '', sentence.replace('\n', '')) # 过滤
    return jieba.cut(sentence, cut_all=cut_all) # 分词

语料库逆文档频率统计

高效文件读取

读取指定目录下的所有文本文件,使用结巴分词器进行分词。本文的IDF提取基于THUCNews(清华新闻语料库)的大约80万篇文本。

基于python生成器的实现,以下代码可以实现高效地读取文本并分词:

class MyDocuments(object):    # memory efficient data streaming
    def __init__(self, dirname):
        self.dirname = dirname
        if not os.path.isdir(dirname):
            print(dirname, '- not a directory!')
            sys.exit()

    def __iter__(self):
        for dirfile in os.walk(self.dirname):
            for fname in dirfile[2]:
                text = open(os.path.join(dirfile[0], fname), 
                            'r', encoding='utf-8').read()
                yield segment(text)  

词的逆文档频数统计

统计每一个词出现在多少篇文档中:

    documents = MyDocuments(inputdir)

    # 排除中文标点符号
    ignored = {'', ' ', '', '。', ':', ',', ')', '(', '!', '?', '”', '“'}
    id_freq = {}    # 频数
    i = 0   # 总文档数
    for doc in documents:
        doc = (x for x in doc if x not in ignored)
        for x in doc:
            id_freq[x] = id_freq.get(x, 0) + 1
        if i % 1000 == 0:   # 每隔1000篇输出状态
            print('Documents processed: ', i, ', time: ', 
                datetime.datetime.now())
        i += 1

计算逆文档频率并存储

    with open(outputfile, 'w', encoding='utf-8') as f:
        for key, value in id_freq.items():
            f.write(key + ' ' + str(math.log(i / value, 2)) + '\n')

逆文档频率(IDF)计算公式

输入图片说明

其中,D表示总文档数,Dw表示词w出现在多少篇文档中。

运行示例:

Building prefix dict from the default dictionary ...
Loading model from cache /var/folders/65/1sj9q72d15gg80vt9c70v9d80000gn/T/jieba.cache
Loading model cost 0.943 seconds.
Prefix dict has been built succesfully.
Documents processed:  0 , time:  2017-08-08 17:11:15.906739
Documents processed:  1000 , time:  2017-08-08 17:11:18.857246
Documents processed:  2000 , time:  2017-08-08 17:11:21.762615
Documents processed:  3000 , time:  2017-08-08 17:11:24.534753
Documents processed:  4000 , time:  2017-08-08 17:11:27.235600
Documents processed:  5000 , time:  2017-08-08 17:11:29.974688
Documents processed:  6000 , time:  2017-08-08 17:11:32.818768
Documents processed:  7000 , time:  2017-08-08 17:11:35.797916
Documents processed:  8000 , time:  2017-08-08 17:11:39.232018

可见,处理1000篇文档用时大约3秒,80万篇大约用时40分钟。

TF-IDF关键词提取

借鉴了结巴分词的处理思路,使用IDFLoader载入IDF文件:

class IDFLoader(object): 
    def __init__(self, idf_path):
        self.idf_path = idf_path
        self.idf_freq = {}     # idf
        self.mean_idf = 0.0    # 均值
        self.load_idf()

    def load_idf(self):       # 从文件中载入idf
        cnt = 0
        with open(self.idf_path, 'r', encoding='utf-8') as f:
            for line in f:
                try:
                    word, freq = line.strip().split(' ')
                    cnt += 1
                except Exception as e:
                    pass
                self.idf_freq[word] = float(freq)

        print('Vocabularies loaded: %d' % cnt)
        self.mean_idf = sum(self.idf_freq.values()) / cnt

使用TF-IDF抽取关键词:

TF-IDF计算公式:

输入图片说明

class TFIDF(object): 
    def __init__(self, idf_path):
        self.idf_loader = IDFLoader(idf_path)
        self.idf_freq = self.idf_loader.idf_freq
        self.mean_idf = self.idf_loader.mean_idf

    def extract_keywords(self, sentence, topK=20):    # 提取关键词
        # 分词
        seg_list = segment(sentence)
        
        freq = {}
        for w in seg_list:
            freq[w] = freq.get(w, 0.0) + 1.0  # 统计词频
        if '' in freq:
            del freq['']
        total = sum(freq.values())    # 总词数

        for k in freq:   # 计算 TF-IDF
            freq[k] *= self.idf_freq.get(k, self.mean_idf) / total

        tags = sorted(freq, key=freq.__getitem__, reverse=True)  # 排序

        if topK:   # 返回topK
            return tags[:topK]
        else:
            return tags

使用:

    # idffile为idf文件路径, document为待处理文本路径
    tdidf = TFIDF(idffile)
    sentence = open(document, 'r', encoding='utf-8').read()
    tags = tdidf.extract_keywords(sentence, topK)

示例输出:

交通
翼
路况
中国电信
电信
国电
服务
天
武汉
信息
市民
出行
便民
武汉热线
通路
交通广播
实时
看
分公司
手机

© 著作权归作者所有

共有 人打赏支持
Gaussic
粉丝 384
博文 28
码字总数 66788
作品 0
宝山
加载中

评论(2)

Gaussic
Gaussic

引用来自“JasonLuo90”的评论

IDF是指出现单词的文档数量吧,用id_freq[x] = id_freq.get(x, 0) + 1,那么同一篇文章中的相同单词导致这个数量不对
好像是的,抱歉:disappointed_relieved:,在doc前面加个set就好了
JasonLuo90
JasonLuo90
IDF是指出现单词的文档数量吧,用id_freq[x] = id_freq.get(x, 0) + 1,那么同一篇文章中的相同单词导致这个数量不对
基于python中jieba包的中文分词中详细使用(二)

基于python中jieba包的中文分词中详细使用(二) 01.前言 在基于python中jieba包的中文分词中详细使用(一)已经介绍了jieba分词的一些基本内容,现在接着去介绍。 02.关键词提取 02.01基于T...

meiqi0538 ⋅ 05/07 ⋅ 0

空间向量模型和tf-idf

向量空间模型 向量空间模型是一个把文本文件表示为标识符(比如索引)向量的代数模型,它应用于信息过滤、信息检索、索引以及相关排序。 1 定义 文档和查询都用向量来表示: 每一维都对应于一...

致Great ⋅ 2017/09/21 ⋅ 0

[Paper Reading] 基于文档主题结构的关键词抽取方法研究

写在前面: 本文知乎大V清华大学刘知远博士的博士论文。因为最近有个短线项目涉及到这方面,向大牛学习一下。 简述: 针对文档主题结构在关键词抽取中的重要作用,从四个方面提出考虑文档主题...

见鹿 ⋅ 2017/09/27 ⋅ 0

SparkML机器学习之特征工程(一)特征提取(TF-IDF、Word2Vec、CountVectorizer)

特征工程 我们都知道特征工程在机器学习中是很重要的,然而特征工程到底是什么?怎么样通俗的理解它呢?打个比方,即使你有再好的渔具,如果给你一片没有鱼的池塘,那也是白费力气的。而特征...

liuyanling41 ⋅ 04/08 ⋅ 0

TF-IDF与余弦相似性的应用(一):自动提取关键词

这个标题看上去好像很复杂,其实我要谈的是一个很简单的问题。 有一篇很长的文章,我要用计算机提取它的关键词(Automatic Keyphrase extraction),完全不加以人工干预,请问怎样才能正确做...

阮一峰 ⋅ 2013/03/15 ⋅ 0

TF-IDF及其算法

概念 TF-IDF(term frequency–inverse document frequency)是一种用于资讯检索与资讯探勘的常用加权技术。TF-IDF是一种统计方法,用以评估一字词对于一个文件集或一个语料库中的其中一份文...

牧羊人Berg ⋅ 2016/11/01 ⋅ 0

TF-IDF与余弦相似性的应用(一):自动提取关键词

转自:http://www.ruanyifeng.com/blog/2013/03/tf-idf.html 这个标题看上去好像很复杂,其实我要谈的是一个很简单的问题。 有一篇很长的文章,我要用计算机提取它的关键词(Automatic Keyph...

泳泳啊泳泳 ⋅ 01/07 ⋅ 0

Spark数据挖掘-TF-IDF文档矩阵

Spark数据挖掘-TF-IDF文档矩阵 前言 得到词文档矩阵往往都是文本挖掘算法的第一步,词文档矩阵中行表示语料库中出现过的词(实际代码都是对词进行整数编码),列表示所有的文档,矩阵中的每个...

clebeg ⋅ 2015/11/19 ⋅ 0

使用scikit-learn计算文本TF-IDF值(更新中)

一、TF-IDF介绍 (一)术语介绍 TF-IDF(Term Frequency-InversDocument Frequency)是一种常用于信息处理和数据挖掘的加权技术。该技术采用一种统计方法,根据字词的在文本中出现的次数和在...

海天一树X ⋅ 05/30 ⋅ 0

如何用Python提取中文关键词?

本文一步步为你演示,如何用Python从中文文本中提取关键词。如果你需要对长文“观其大略”,不妨尝试一下。 (由于微信公众号外部链接的限制,文中的部分链接可能无法正确打开。如有需要,请...

nkwshuyi ⋅ 2017/12/10 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

zblog2.3版本的asp系统是否可以超越卢松松博客的流量[图]

最近访问zblog官网,发现zlbog-asp2.3版本已经进入测试阶段了,虽然正式版还没有发布,想必也不久了。那么作为aps纵横江湖十多年的今天,blog2.2版本应该已经成熟了,为什么还要发布这个2.3...

原创小博客 ⋅ 今天 ⋅ 0

聊聊spring cloud的HystrixCircuitBreakerConfiguration

序 本文主要研究一下spring cloud的HystrixCircuitBreakerConfiguration HystrixCircuitBreakerConfiguration spring-cloud-netflix-core-2.0.0.RELEASE-sources.jar!/org/springframework/......

go4it ⋅ 今天 ⋅ 0

二分查找

二分查找,也称折半查找、二分搜索,是一种在有序数组中查找某一特定元素的搜索算法。搜素过程从数组的中间元素开始,如果中间元素正好是要查找的元素,则搜素过程结束;如果某一特定元素大于...

人觉非常君 ⋅ 今天 ⋅ 0

VS中使用X64汇编

需要注意的是,在X86项目中,可以使用__asm{}来嵌入汇编代码,但是在X64项目中,再也不能使用__asm{}来编写嵌入式汇编程序了,必须使用专门的.asm汇编文件来编写相应的汇编代码,然后在其它地...

simpower ⋅ 今天 ⋅ 0

ThreadPoolExecutor

ThreadPoolExecutor public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, ......

4rnold ⋅ 昨天 ⋅ 0

Java正无穷大、负无穷大以及NaN

问题来源:用Java代码写了一个计算公式,包含除法和对数和取反,在页面上出现了-infinity,不知道这是什么问题,网上找答案才明白意思是负的无穷大。 思考:为什么会出现这种情况呢?这是哪里...

young_chen ⋅ 昨天 ⋅ 0

前台对中文编码,后台解码

前台:encodeURI(sbzt) 后台:String param = URLDecoder.decode(sbzt,"UTF-8");

west_coast ⋅ 昨天 ⋅ 0

实验楼—MySQL基础课程-挑战3实验报告

按照文档要求创建数据库 sudo sercice mysql startwget http://labfile.oss.aliyuncs.com/courses/9/createdb2.sqlvim /home/shiyanlou/createdb2.sql#查看下数据库代码 代码创建了grade......

zhangjin7 ⋅ 昨天 ⋅ 0

一起读书《深入浅出nodejs》-node模块机制

node 模块机制 前言 说到node,就不免得提到JavaScript。JavaScript自诞生以来,经历了工具类库、组件库、前端框架、前端应用的变迁。通过无数开发人员的努力,JavaScript不断被类聚和抽象,...

小草先森 ⋅ 昨天 ⋅ 0

Java桌球小游戏

其实算不上一个游戏,就是两张图片,不停的重画,改变ball图片的位置。一个左右直线碰撞的,一个有角度碰撞的。 左右直线碰撞 package com.bjsxt.test;import javax.swing.*;import j...

森林之下 ⋅ 昨天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部