jieba分词浅析---关键词提取

最近公司在做一个分词的项目,所以对分词有所研究,再经过整个项目的不断调整逐渐对分词有了更深入的了解,下面是我自己对分词的一些理解,希望能对大家有一定的帮助,也希望大家多多指点,如果有什么不对的地方请尽情留言,大家共同探讨进步。好了,话不多说上干货!!!

一.关键词提取的算法选择
jieba分词为我们提供了两种算法的选择:TF-IDF算法和TextRank算法
1.TF-IDF算法:
如果某个词或短语在一篇文章中出现的频率TF高,并且在其他文章中很少出现,则认为此词或者短语具有很好的类别区分能力,适合用来分类。
2.TextRank算法:
TextRank 算法是一种用于文本的基于图的排序算法。其基本思想来源于谷歌的 PageRank算法, 通过把文本分割成若干组成单元(单词、句子)并建立图模型, 利用投票机制对文本中的重要成分进行排序, 仅利用单篇文档本身的信息即可实现关键词提取、文摘。和 LDA、HMM 等模型不同, TextRank不需要事先对多篇文档进行学习训练, 因其简洁有效而得到广泛应用。
虽然TextRank算法看起来比较高级和方便,但其实其效率并没有什么太大的优势。
点击查看两种算法的比对试验
实验结果表明TextRank与TFIDF均严重依赖于分词结果——如果某词在分词时被切分成了两个词,那么在做关键词提取时无法将两个词黏合在一起(TextRank有部分黏合效果,但需要这两个词均为关键词)。因此是否添加标注关键词进自定义词典,将会造成准确率、召回率大相径庭。
TextRank的效果并不优于TFIDF,TextRank虽然考虑到了词之间的关系,但是仍然倾向于将频繁词作为关键词。此外,由于TextRank涉及到构建词图及迭代计算,所以提取速度较慢。
综上所述,我选择了TFIDF算法做为关键词提取的算法。

二.关键词提取

import jieba.analyse

jieba.analyse.extract_tags(sentence, topK=20, withWeight=False, allowPOS=())
sentence 为待提取的文本
topK 为返回几个 TF/IDF 权重最大的关键词,默认值为 20
withWeight 为是否一并返回关键词权重值,默认值为 False
allowPOS 仅包括指定词性的词,默认值为空,即不筛选
jieba.analyse.TFIDF(idf_path=None) 新建 TFIDF 实例,idf_path 为 IDF 频率文件

具体代码很简单我就不引入了。这里有个点需要注意就是topK,如果你要分词的内容很短在百字左右,建议你的关键词只取2-5个就可以了,太多了并不具有代表性,反而不好。另外词性的筛选根据个人需要可以选择添加。

三.提高关键词提取的准确性
许多人在提取关键词后会发现提取的关键词并不准确,造成这样的原因有很多,接下来我给大家一一解说。
1.分词的准确
要知道关键词的提取第一步预处理,首先进行分词和词性标注,将满足指定词性的词作为候选词,而如果分词出现问题,就会导致关键词的提取出现了偏差,就跟盖楼一样,地基不稳楼也就盖不好了。
提高分词的方法就是自定义分词,通过加载自定义分词,保证自己需要得到分词能够准确的被分出来。

 jieba.load_userdict(file_name)

除了自定义分词还有去停词
去停词有两种方式,一种是使用关键词组件中的停止词模块

 jieba.analyse.set_stop_words(file_name) 

通过这种方式可以在提取关键词的时候将不想要的词语去除。
还有一种方式就是通过代码的手段将不想要的词语去除,这种方式一个是可以起到数据清洗的作用,可以将一些特殊符号,英文,数字去掉。另一个就是在IDF训练时能起到一定的作用,这个在后面展开。
下面上代码

    #将需要去掉的词写在一个txt文件中,将这些词组成一个列表
    with open('stop.txt', "r", encoding='utf-8') as stop_f:
        for line in stop_f.readlines():
            line = line.strip()
            if not len(line):
                continue
            stop_words.append(line)
    #在分词后,遍历分词列表,将需要去掉的词
    if word in stop_words:
    	continue
    else:
    	a_list.append(word)

2.逆向文件频率(IDF)文本语料库
有人发现即使使用了去停词或者停止词,依然无法得到准确的关键词,这是为什么呢?
其原因在于TF-IDF算法本身。在jieba分词的TF-IDF提取关键词算法中,基于TF-IDF进行特征值提取,因为文本背景是某一具体行业,不适合使用通用的IDF语料库,应使用自定义的基于该行业背景的逆向文件频率(IDF)的文本语料库。
下面我们来看看该算法的具体原理:
在这里插入图片描述
词频 (term frequency, TF) 指的是某一个给定的词语在该文件中出现的次数。这个数字通常会被归一化(一般是词频除以文章总词数), 以防止它偏向长的文件。
在这里插入图片描述
逆向文件频率 (inverse document frequency, IDF) IDF的主要思想是:如果包含词条t的文档越少, IDF越大,则说明词条具有很好的类别区分能力。某一特定词语的IDF,可以由总文件数目除以包含该词语之文件的数目,再将得到的商取对数得到。
在这里插入图片描述
某一特定文件内的高词语频率,以及该词语在整个文件集合中的低文件频率,可以产生出高权重的TF-IDF。因此,TF-IDF倾向于过滤掉常见的词语,保留重要的词语。
从这里我们可以知道,提取的关键词不好的原因可能是因为语料库的问题。

基于上述情况,我们要对IDF进行训练,因为公司的项目我们有进行分词的存储,所以就方便了我对于自定义IDF的训练

下面这段代码不完全出自我本人,请原作者见谅(实在是找不到那篇文章了)

import PG
idf_dic = {}
#这里写了一个连PG库的方法,用来应对灾备的。直接略过了。
#第一步查库找到每个文本的ID,xxxxxx库是存分词的库
con = PG()
cur = con.cursor()
sql = "select DISTINCT context_id from xxxxxxxxx where DATASOURCE = '1'"
try:
    cur.execute(sql)
    data_t = cur.fetchall()# 查询是否已存在此词条
    doc_count = len(data_t)
except Exception as e:
    print("数据查询失败")
    print(e)
print("____数据查询结束____")
#根据ID查到该文本的所以分词
for uuid in data_t:
    sql_word = "select words from xxxxxxxxx where context_id='{}'".format(uuid[0])
    try:
        cur.execute(sql_word)
        data_word = cur.fetchall()
    except Exception as e:
        print("数据查询失败")
        print(e)
    #统计每个词出现的次数
    #这里说下我这里对每个文本的分词已经做了去重处理,所以不会出现一个文本一个词出现多次的情况,该词在该文本中只会+1
    for word in data_word:
        if len(word[0])>1:
            idf_dic[word[0]]= idf_dic.get(word[0], 0.0) + 1.0
print("____数据处理结束____")
#按照公式计算每个词的权重值
for k, v in idf_dic.items():
    w = k
    p = '%.10f' % (math.log(doc_count / (1.0 + v)))
    if w > u'\u4e00' and w <= u'\u9fa5':  # 判断key值全是中文
        idf_dic[w] = p
print("____数据计算结束____")
#将结果转化成文件格式
with open('wdic.txt.big','w',encoding='utf-8') as f:
    for k in idf_dic:
        if k != '\n':
            f.write(k + ' ' + str(idf_dic[k]) + '\n')
#在关键词提取之前引用
jieba.analyse.set_idf_path(file_name) 

这个dome的效率并不是很高,我提取了1万条文本的分词来训练,大概用时4个小时。希望大家能出出主意帮忙提高下效率,如有错误的地方也请大家多多指点。

谢谢能坚持看到这里的各位!!!

你可能感兴趣的:(分词研究,python,大数据)