Jieba中文分词 (二) ——词性标注与关键词提取

2021-06-24 11:24:56 浏览数 (1)

jieba分词

上一篇jieba中文分词(一)分词与自定义字典已介绍了jieba中文分词安装,分词原理,分词方法,自定义字典,添加字典等多种常用分词方法。本篇将继续介绍jieba分词关键词提取、词性标注、及常见问题。

关键词提取

关键词提取,将文本中最能表达文本含义的词语抽取出来,有点类似于论文的关键词或者摘要。关键词抽取可以采取:

  • 有监督学习: 文本作为输入,关键词作为标注,进行训练得到模型。此方法难点在于需要大量人工标注。
  • 无监督学习: 先抽取出候选词,对每个候选词打分,取出前K个分值高的作为最后的关键词。jieba分词实现了基于TF-IDF和基于TextRank的关键词抽取算法。
基于 TF-IDF 算法的关键词抽取

基于TF-IDF的关键词抽取算法,目标是获取文本中词频高,也就是TF大的,且语料库其他文本中词频低的,也就是IDF大的。这样的词可以作为文本的标志,用来区分其他文本。

代码语言:javascript复制
import jieba.analyse
jieba.analyse.extract_tags(sentence, 
              topK=20, 
              withWeight=False, 
              allowPOS=())

sentence: 为待提取的文本 topK: 为返回几个 TF/IDF 权重最大的关键词,默认值为 20 withWeight: 为是否一并返回关键词权重值,默认值为 False allowPOS: 仅包括指定词性的词,默认值为空,即不筛选

代码示例:

代码语言:javascript复制
import jieba
import jieba.analyse

topK = 5
file_name = 'test.txt'
"""
test.txt
西三旗硅谷先锋小区半地下室出租,便宜可合租硅谷
工信处女干事每月经过下属科室都要亲口交代24口交换机等技术性器件的安装工作
"""
with open(file_name, 'rb') as f:
    content = f.read()
    
tags = jieba.analyse.extract_tags(content, topK=topK)
print(", ".join(tags))
print('*'*40)

# 关键词提取所使用逆向文件频率(IDF)文本语料库可以切换成自定义语料库的路径
jieba.analyse.set_idf_path("../extra_dict/idf.txt.big");
tags = jieba.analyse.extract_tags(content, topK=topK)
print(", ".join(tags))
print('*'*40)

# 关键词提取所使用停止词文本语料库可以切换成自定义语料库的路径
jieba.analyse.set_stop_words("../extra_dict/stop_words.txt")
jieba.analyse.set_idf_path("../extra_dict/idf.txt.big");
tags = jieba.analyse.extract_tags(content, topK=topK)
print(", ".join(tags))
print('*'*40)

# 关键词一并返回关键词权重值示例
withWeight = True
tags = jieba.analyse.extract_tags(content, topK=topK, withWeight=withWeight)
for tag in tags:
    print("tag: %stt weight: %f" % (tag[0],tag[1]))

硅谷, 西三旗, 工信处, 女干事, 24 硅谷, 西三旗, 先锋, 小区, 合租 硅谷, 西三旗, 先锋, 小区, 合租 tag: 硅谷 weight: 1.039545 tag: 西三旗 weight: 0.519773 tag: 先锋 weight: 0.519773 tag: 小区 weight: 0.519773 tag: 合租 weight: 0.519773

基于 TextRank 算法的关键词抽取
代码语言:javascript复制
jieba.analyse.textrank(sentence, 
        topK=20, 
        withWeight=False, 
        allowPOS=('ns', 'n', 'vn', 'v')) 

sentence: 为待提取的文本 topK: 为返回几个权重最大的关键词,默认值为 20 withWeight: 为是否一并返回关键词权重值,默认值为 False allowPOS: 仅包括指定词性的词,默认过滤词性

算法论文:TextRank: Bringing Order into Texts[1]

一般步骤:
  • 先将文本进行分词和词性标注,将特定词性的词(比如名词)作为节点添加到图中。
  • 出现在一个窗口中的词语之间形成一条边,窗口大小可设置为2~10之间,默认为5,它表示一个窗口中有多少个词语。
  • 对节点根据入度节点个数以及入度节点权重进行打分,入度节点越多,且入度节点权重大,则打分高。
  • 然后根据打分进行降序排列,输出指定个数的关键词。
代码示例:
代码语言:javascript复制
tags = jieba.analyse.textrank(content, 
             topK=5, 
             withWeight=True) 
for tag in tags:
    print("tag: %stt weight: %f" % (tag[0],tag[1]))

tag: 硅谷 weight: 1.000000 tag: 女干事 weight: 0.847395 tag: 技术性 weight: 0.800966 tag: 器件 weight: 0.794530 tag: 交换机 weight: 0.766318

词性标注

通过查询字典的方式获取识别词的词性,通过HMM隐马尔科夫模型来获取未登录词的词性,从而完成整个语句的词性标注。但可以看到查询字典的方式不能解决一词多词性的问题,也就是词性歧义问题。故精度上还是有所欠缺的。

标注句子分词后每个词的词性,词性标示兼容ICTCLAS 汉语词性标注集。

除了jieba默认分词模式,提供paddle模式下的词性标注功能。

代码示例:
代码语言:javascript复制
import jieba
import jieba.posseg as pseg
jieba.add_word('数据STUDIO')

words = pseg.cut("我关注了微信公众号数据STUDIO") 
print('jieba默认模式')
for word, flag in words:
    print('%s %s' % (word, flag))
print(' '*10)
jieba.enable_paddle() #启动paddle模式。
words = pseg.cut("我关注了微信公众号数据STUDIO",use_paddle=True) #paddle模式
print('paddle模式')
for word, flag in words:
    print('%s %s' % (word, flag))
print(' '*10)

jieba默认模式 我 r 关注 v 了 ul 微信 vn 公众 n 号 m 数据STUDIO x Paddle enabled successfully...... paddle模式 我 r 关注 v 了 u 微信公众号数据STUDIO nz

默认模式词性和专名类别标签集合如下表。 (↔️滑动)

标签

含义

标签

含义

标签

含义

标签

含义

n

名词

f

方位词

al

形容词性惯用语

m

数词

nr

人名

v

动词

b

区别词

mq

数量词

nr1

汉语姓氏

vd

副动词

bl

区别词性惯用语

q

量词

nr2

汉语名字

vn

名动词

z

状态词

qv

动量词

nrj

日语人名

vshi

动词“是”

r

代词

qt

时量词

nrf

音译人名

vyou

动词“有”

rr

人称代词

d

副词

ns

地名

vf

趋向动词

rz

指示代词

p

介词

nsf

音译地名

vx

形式动词

rzt

时间指示代词

pba

介词“把”

nt

机构团体名

vi

不及物动词(内动词)

rzs

处所指示代词

pbei

介词“被”

nz

其它专名

vl

动词性惯用语

rzv

谓词性指示代词

c

连词

nl

名词性惯用语

vg

动词性语素

ry

疑问代词

cc

并列连词

ng

名词性语素

a

形容词

ryt

时间疑问代词

cc

并列连词

t

时间词

ad

副形词

rys

处所疑问代词

tg

时间词性语素

an

名形词

ryv

谓词性疑问代词

s

处所词

ag

形容词性语素

rg

代词性语素

paddle模式词性和专名类别标签集合如下表,其中词性标签 24 个(小写字母),专名类别标签 4 个(大写字母)。 (↔️滑动)

标签

含义

标签

含义

标签

含义

标签

含义

n

普通名词

f

方位名词

s

处所名词

t

时间

nr

人名

ns

地名

nt

机构名

nw

作品名

nz

其他专名

v

普通动词

vd

动副词

vn

名动词

a

形容词

ad

副形词

an

名形词

d

副词

m

数量词

q

量词

r

代词

p

介词

c

连词

u

助词

xc

其他虚词

w

标点符号

PER

人名

LOC

地名

ORG

机构名

TIME

时间

并行分词

原理:将目标文本按行分隔后,把各行文本分配到多个 Python 进程并行分词,然后归并结果,从而获得分词速度的可观提升。

基于 python 自带的 multiprocessing 模块,目前暂不支持 Windows。

  • jieba.enable_parallel(4) 开启并行分词模式,参数为并行进程数
  • jieba.disable_parallel() 关闭并行分词模式

Tokenize:返回词语在原文的起止位置

注意,输入参数只接受 unicode

默认模式
代码语言:javascript复制
import jieba
import jieba.posseg as pseg
from prettytable import PrettyTable  
jieba.add_word('数据STUDIO')
jieba.add_word('微信公众号')
result = jieba.tokenize(u'我关注了微信公众号数据STUDIO')

x = PrettyTable(["word", "start", "end"])  
x.align["word"] = "l"# 左对齐
x.padding_width = 2 # 列边和内容之间有两个空格(默认为一个空格)
for tk in result:
    x.add_row([tk[0], tk[1], tk[2]])
print(x)

word

start

end

0

1

关注

1

3

3

4

微信公众号

4

9

数据STUDIO

9

17

搜索模式
代码语言:javascript复制
result = jieba.tokenize(u'我关注了微信公众号数据STUDIO', mode='search')
x = PrettyTable(["word", "start", "end"])  
x.align["word"] = "l"# 左对齐
x.padding_width = 2 # 列边和内容之间有两个空格(默认为一个空格)
for tk in result:
    x.add_row([tk[0], tk[1], tk[2]])
print(x)

word

start

end

0

1

关注

1

3

3

4

公众

6

8

微信公众号

4

9

数据

9

11

数据STUDIO

9

17

延迟加载机制

jieba 采用延迟加载,import jiebajieba.Tokenizer() 不会立即触发词典的加载,一旦有必要才开始加载词典构建前缀字典。如果你想手工初始 jieba,也可以手动初始化。

代码语言:javascript复制
import jieba
jieba.initialize()  # 手动初始化(可选)

有了延迟加载机制后,你可以改变主词典的路径:

  • 下载你所需要的词典,然后覆盖 jieba/dict.txt 即可;
  • 或者用:
代码语言:javascript复制
jieba.set_dictionary('data/dict.txt.big')

常见问题

  1. “台中”总是被切成“台 中”?(以及类似情况)

P(台中) < P(台)×P(中),“台中”词频不够导致其成词概率较低

解决方法:强制调高词频

jieba.add_word('台中') 或者 jieba.suggest_freq('台中', True)

  1. “今天天气 不错”应该被切成“今天 天气 不错”?(以及类似情况)

解决方法:强制调低词频

jieba.suggest_freq(('今天', '天气'), True)

或者直接删除该词 jieba.del_word('今天天气')

  1. 切出了词典中没有的词语,效果不理想?

解决方法:关闭新词发现

jieba.cut('丰田太省了', HMM=False)jieba.cut('我们中出了一个叛徒', HMM=False)

更多问题[2]

参考资料

[1]

TextRank算法论文: http://web.eecs.umich.edu/~mihalcea/papers/mihalcea.emnlp04.pdf

[2]

更多问题: https://github.com/fxsjy/jieba/issues?sort=updated&state=closed

0 人点赞