心法利器[33] | 快速的关键词抽取baseline

心法利器

本栏目主要和大家一起讨论近期自己学习的心得和体会,与大家一起成长。具体介绍:仓颉专项:飞机大炮我都会,利器心法我还有

往期回顾

关键词抽取是一个很特殊的任务,这个任务的难点却非常鲜明:

  • 通常没什么训练数据,有监督方法可能哑火。

  • 场景依赖很大,通用性很难做到。

  • 只是辅助工作,所以重型武器很难进入,而且最好要快速有一个可靠的方案。

今天我来给大家快速地整一个baseline,这个baseline的效果不见得非常优秀,但胜在无监督、开发成本低、灵活性高、速度快,能跑起来就是好的嘛。

方案思路

整个思路的核心其实非常简单,当NLP还处于统计时代,最关键的一个指标就是这个tf-idf,tf句子中的词频,idf对应出现在给定海量数据下的文章或者句子的个数,tf越高越重要,出现在文章的文章量越多,这个词越不重要,那么,很简单的,tf-idf就是一个非常简单评价词汇重要性的指标,甚至,在短文本场景,甚至tf都不需要考虑了,idf成了唯一的,简单的标准。

换言之,一个句子中,idf最高的几个词,就可以被认为是关键词。

上代码

idf这个指标是需要大量数据去训的。当然,我们也可以去拿一些用开放域数据训的来直接用,最为直接而可靠的,也是我自己比较喜欢的是jieba内的idf.txt,大家可以直接去jieba的源码里找,没记错应该是人民日报数据来训的,我自己的经验上来看,足够支撑常用的一些场景了。当然如果不够,可以自己找语料训一个,这里就不写这个脚本了,做一个数据统计然后求个log对各位大佬来说并不困难。

来看看预测代码怎么弄吧。

首先我们先确定一下这块代码需要的东西以及需要分的模块:

  • 初始化,我们需要的加载是idf词典,同时我们也需要一个默认值,对未登录词给一个默认值。

  • 预测模块。

这么看内容其实不会很多,我直接把代码放上来。

import jieba
import numpy as np
import heapq

class keywordExtractor():
    def __init__(self):
        idf_dict = {}
        data_list = []
        with open("./data/idf.txt") as f:
            for line in f:
                ll = line.strip().split(" ")
                if len(ll) != 2:
                    continue
                if ll[0] not in idf_dict:
                    idf_dict[ll[0]] = float(ll[1])
                data_list.append(float(ll[1]))
        self.__idf_dict = idf_dict
        self.median = np.median(data_list)
    
    def get_idf(self,word):
        return self.__idf_dict.get(word, self.median)
    
    def predict(self, query, top_n = 1):
        if len(query) <= 2:
            return [query]
    
        # 切词
        word_list = list(jieba.cut(query))
        if len(word_list) < top_n:
            return word_list
        
        # 默认赋值
        idf_list = []
        for word in word_list:
            idf_list.append(self.get_idf(word))
           
        # 可以进行一些藏经相关的业务调整
        
        # 归一化
        weight_list = [i / max(idf_list) for i in idf_list]
        zip_list = zip(range(len(weight_list)), weight_list)
        n_large_idx = [i[0] for i in heapq.nlargest(top_n, zip_list, key=lambda x:x[1])]

        return [word_list[i] for i in n_large_idx], weight_list
    
if __name__ == "__main__":
    keyword_extractor = keywordExtractor()
    print(keyword_extractor.predict("看最近的日程"))
    print(keyword_extractor.predict("看最近的日程", 2))

加载:

  • 加载这块直接走加载脚本就好了,这个应该不是很难,基本的读取操作了。

  • 这里的默认值我使用的是中位数,属于经验值吧。

  • 另外这里有一个细节,这个idf的词典我用的还是比较简单的

预测模块:

  • 切词,然后根据词典查idf作为权重。

  • 有一个模块我空了出来,这里可以根据自己的业务做一些权重的调整,例如基于位置的调权。

  • 权重归一化,求一个相对的大小,为了避免长度导致的相对大小波动,所以归一化我这里除以的不是和,而是最大值。

  • 另外这里求TOPN的方法也可以记录一下。

小结

这是一个无比简单但是还相对可靠的方案,大家要是想做可以用这个方式来试一下,甚至以可以用这个来做预标注来训练也行。

关键词抽取的方案网上说的真的少,我之前写过一篇词权重的文章,有兴趣大家可以看看其他的拓展方法,NLP.TM[20] | 词权重问题

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值