jieba分词-小白使用贴

作者: 大米007 | 来源:发表于2018-11-15 14:45 被阅读0次

(主要内容均来源于github上的说明)

特点

  • 支持三种分词模式:
    • 精确模式,试图将句子最精确地切开,适合文本分析;
    • 全模式,把句子中所有的可以成词的词语都扫描出来, 速度非常快,但是不能解决歧义;
    • 搜索引擎模式,在精确模式的基础上,对长词再次切分,提高召回率,适合用于搜索引擎分词。
  • 支持繁体分词。
  • 支持自定义词典。
  • MIT授权协议。

安装说明

  • 全自动安装:easy_install jieba 或者 pip install jieba / pip3 install jieba。
  • 半自动安装:先下载 http://pypi.python.org/pypi/jieba/ ,解压后运行 python setup.py install。
  • 手动安装:将 jieba 目录放置于当前目录或者 site-packages 目录。
  • 通过 import jieba 来引用。

算法

  • 基于前缀词典实现高效的词图扫描,生成句子中汉字所有可能成词情况所构成的有向无环图 (DAG)。
  • 采用了动态规划查找最大概率路径, 找出基于词频的最大切分组合。
  • 对于未登录词,采用了基于汉字成词能力的HMM模型,使用了Viterbi算法。

主要功能-分词

  • jieba.cut 方法接受三个输入参数: 需要分词的字符串;cut_all 参数用来控制是否采用全模式;HMM参数用来控制是否使用HMM模型。
  • jieba.cut_for_search 方法接受两个参数:需要分词的字符串;是否使用HMM模型。该方法适合用于搜索引擎构建倒排索引的分词,粒度比较细。
    • jieba.cut 以及 jieba.cut_for_search 返回的结构都是一个可迭代的 generator,可以使用for 循环来获得分词后得到的每一个词语(unicode),或者用jieba.lcut以及jieba.cut_for_search直接返回list。
  • jieba.Tokenizer(dictionary=DEFAULT_DICT) 新建自定义分词器,可用于同时使用不同词典。
  • jieba.dt 为默认分词器,所有全局分词相关函数都是该分词器的映射。

注:待分词的字符串可以是 unicode 或 UTF-8 字符串、GBK 字符串。注意:不建议直接输入 GBK 字符串,可能无法预料地错误解码成 UTF-8

分词示例代码:

seg_list = jieba.cut("我来到北京清华大学", cut_all=True)
print("Full Mode: " + "/ ".join(seg_list))  # 全模式
输出:
Full Mode: 我/ 来到/ 北京/ 清华/ 清华大学/ 华大/ 大学

seg_list = jieba.cut("我来到北京清华大学", cut_all=False)
print("Default Mode: " + "/ ".join(seg_list))  # 精确模式,不写cut_all,即默认也是精确模式
输出:
Default Mode: 我/ 来到/ 北京/ 清华大学

seg_list = jieba.cut_for_search("小明硕士毕业于中国科学院计算所,后在日本京都大学深造")  # 搜索引擎模式
print(", ".join(seg_list))
输出:小明, 硕士, 毕业, 于, 中国, 科学, 学院, 科学院, 中国科学院, 计算, 计算所, ,, 后, 在, 日本, 京都, 大学, 日本京都大学, 深造

载入词典:

  • 开发者可以指定自己自定义的词典,以便包含 jieba 词库里没有的词。虽然 jieba 有新词识别能力,但是自行添加新词可以保证更高的正确率。
  • 用法:jieba.load_userdict(file_name) 。说明:file_name 为文件类对象或自定义词典的路径。
  • 词典格式和 dict.txt 一样,一个词占一行;每一行分三部分:词语、词频(可省略)、词性(可省略),用空格隔开,顺序不可颠倒。file_name 若为路径或二进制方式打开的文件,则文件必须为 UTF-8 编码。
  • 词频省略时使用自动计算的能保证分出该词的词频。
    例如:
创新办 3 i
云计算 5
凱特琳 nz
台中
  • 更改分词器(默认为 jieba.dt)的 tmp_dir 和 cache_file 属性,可分别指定缓存文件所在的文件夹及其文件名,用于受限的文件系统。
  • 使用 add_word(word, freq=None, tag=None) 和 del_word(word) 可在程序中动态修改词典。
  • 使用 suggest_freq(segment, tune=True) 可调节单个词语的词频,使其能(或不能)被分出来。

注意:自动计算的词频在使用 HMM 新词发现功能时可能无效。

自定义词典示例代码:

首先,创建一个名为dict_hrjlk_test.dt词典文件,内容如下:

云计算 5
李小福 2 nr
创新办 3 i
easy_install 3 eng
好用 300
韩玉赏鉴 3 nz
八一双鹿 3 nz
台中
凱特琳 nz
Edu Trust认证 2000

示例代码如下:

import jieba
jieba.load_userdict("/Users/roy/Run/jieba-dict/dict_hrjlk_test.dt")
jieba.add_word('石墨烯')
  • 此时去检查字典文件,发现'石墨烯'并没有被写入到字典文件中,可见只能是保存到内存中了,或者在jieba中称为缓存*
testStr='「台中」正確應該不會被切開。mac上可分出「石墨烯」;此時又可以分出來凱特琳了。'
words = jieba.cut(testStr)
print('/'.join(words))
输出:
「/台中/」/正確/應該/不會/被/切開/。/mac/上/可/分出/「/石墨烯/」/。
  • 这时'石墨烯'可以被分出来
jieba.del_word('石墨烯')
words = jieba.cut(testStr)
print('/'.join(words))
「/台中/」/正確/應該/不會/被/切開/。/mac/上/可/分出/「/石墨/烯/」/。
  • 从字典中动态删除'石墨烯'后,不会被识别为一个词了,被分开。

主要功能-关键词提取

基于 TF-IDF 算法的关键词抽取

这里提取的是关键词,即能很好的标识出文章的词,不是高频词

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 频率文件

例1(extract_tags):

testStr = '职位内容:\
1.作为大前端一员参与到六哥核心业务组件的重构与开发,包括Web端、移动端和数据可视化等;\
2.基于各类成熟技术,如PWA,WebAssembly,VUE,RN等,提升产品体验;\
3.持续思考提升工程质量的方式,如版本管理、代码重构·Code Review和自动化测试等;\
4.通过实现SSO、渐进增强、代码复用等方式实现工作自动化;\
5.分享和推动更科学的项目管理方式,帮助项目更好地成功。'
tags = jieba.analyse.extract_tags(testStr)
print(",".join(tags))
输出:
重构,自动化,方式,代码,六哥,Web,PWA,WebAssembly,VUE,RN,Code,Review,SSO,成熟技术,可视化,提升,复用,工程质量,项目管理,组件

这里是基本的提取方式,下面介绍逆向文件频率(IDF)


IDF的主要思想是:如果包含词条t的文档越少,也就是n越小,IDF越大,则说明词条t具有很好的类别区分能力。

语料文件示例:

劳动防护 13.900677652
勞動防護 13.900677652
生化学 13.900677652
生化學 13.900677652
奥萨贝尔 13.900677652
奧薩貝爾 13.900677652
考察队员 13.900677652
考察隊員 13.900677652
岗上 11.5027823792
崗上 11.5027823792

代码示例:

testStr ='职位内容:\
1.作为大前端一员参与到六哥核心业务组件的重构与开发,包括Web端、移动端和数据可视化等;\
2.基于各类成熟技术,如PWA,WebAssembly,VUE,RN等,提升产品体验;\
3.持续思考提升工程质量的方式,如版本管理、代码重构·Code Review和自动化测试等;\
4.通过实现SSO、渐进增强、代码复用等方式实现工作自动化;\
5.分享和推动更科学的项目管理方式,帮助项目更好地成功。'

jieba.analyse.set_idf_path("/Users/roy/Run/jieba-dict/idf.dt");
tags = jieba.analyse.extract_tags(testStr,topK=10)
print(",".join(tags))

停用词

语料文件示例

one
has
or
that
的
了
和

代码示例:

testStr ='职位内容:\
1.作为大前端一员参与到六哥核心业务组件的重构与开发,包括Web端、移动端和数据可视化等;\
2.基于各类成熟技术,如PWA,WebAssembly,VUE,RN等,提升产品体验;\
3.持续思考提升工程质量的方式,如版本管理、代码重构·Code Review和自动化测试等;\
4.通过实现SSO、渐进增强、代码复用等方式实现工作自动化;\
5.分享和推动更科学的项目管理方式,帮助项目更好地成功。'

jieba.analyse.set_stop_words("/Users/roy/Run/jieba-dict/stop_words.dt")
tags = jieba.analyse.extract_tags(testStr,topK=10)
print(",".join(tags))

关键词一并返回关键词权重值

testStr = '职位内容:\
1.作为大前端一员参与到六哥核心业务组件的重构与开发,包括Web端、移动端和数据可视化等;\
2.基于各类成熟技术,如PWA,WebAssembly,VUE,RN等,提升产品体验;\
3.持续思考提升工程质量的方式,如版本管理、代码重构·Code Review和自动化测试等;\
4.通过实现SSO、渐进增强、代码复用等方式实现工作自动化;\
5.分享和推动更科学的项目管理方式,帮助项目更好地成功。'

tags = jieba.analyse.extract_tags(testStr, topK=10, withWeight=True)
for tag in tags:
    print("tag: %s\t\t weight: %f" % (tag[0],tag[1]))
输出:
tag: 重构      weight: 0.335018
tag: 自动化         weight: 0.254009
tag: 方式      weight: 0.240075
tag: 代码      weight: 0.239148
tag: 六哥      weight: 0.220126
tag: Web         weight: 0.199246
tag: PWA         weight: 0.199246
tag: WebAssembly         weight: 0.199246
tag: VUE         weight: 0.199246
tag: RN      weight: 0.199246

基于TextRank算法的关键词抽取

  • jieba.analyse.textrank(sentence, topK=20, withWeight=False, allowPOS=('ns', 'n', 'vn', 'v')) 直接使用,接口相同,注意默认过滤词性。
  • jieba.analyse.TextRank() 新建自定义 TextRank 实例

基本思想:

  • 将待抽取关键词的文本进行分词
  • 以固定窗口大小(默认为5,通过span属性调整),词之间的共现关系,构建图
  • 计算图中节点的PageRank,注意是无向带权图

主要功能-词性标注

  • jieba.posseg.POSTokenizer(tokenizer=None) 新建自定义分词器,tokenizer 参数可指定内部使用的 jieba.Tokenizer 分词器。jieba.posseg.dt 为默认词性标注分词器。
  • 标注句子分词后每个词的词性,采用和 ictclas 兼容的标记法。
  • 按词性过滤结果,是个有效的技巧

代码如下

import jieba
import jieba.posseg as pseg
words = pseg.cut('我爱北京天安门')
for word, flag in words:
    print('%s %s' % (word, flag))
输出:
我 r
爱 v
北京 ns
天安门 ns

尝试改变词性

jieba.add_word('天安门', tag='nnn')
for word, flag in words:
    print('%s %s' % (word, flag))
输出:
我 r
爱 v
北京 ns
天安门 nnn

主要功能-并行分词

  • 原理:将目标文本按行分隔后,把各行文本分配到多个 Python 进程并行分词,然后归并结果,从而获得分词速度的可观提升
  • 基于 python 自带的 multiprocessing 模块,目前暂不支持 Windows
jieba.enable_parallel(4) # 开启并行分词模式,参数为并行进程数
jieba.disable_parallel() # 关闭并行分词模式
  • 实验结果:在 4 核 3.4GHz Linux 机器上,对金庸全集进行精确分词,获得了 1MB/s 的速度,是单进程版的 3.3 倍。

注意:并行分词仅支持默认分词器 jieba.dt 和 jieba.posseg.dt。

主要功能-返回词语在原文的起止位置

默认模式

result = jieba.tokenize('永和服装饰品有限公司')
for tk in result:
    print('word %s\t\t start: %d \t\t end:%d' % (tk[0],tk[1],tk[2]))
输出:
word 永和      start: 0        end:2
word 服装      start: 2        end:4
word 饰品      start: 4        end:6
word 有限公司        start: 6        end:10

搜索模式

result = jieba.tokenize('永和服装饰品有限公司', mode='search')
for tk in result:
    print('word %s\t\t start: %d \t\t end:%d' % (tk[0],tk[1],tk[2]))
输出:
word 永和                start: 0                end:2
word 服装                start: 2                end:4
word 饰品                start: 4                end:6
word 有限                start: 6                end:8
word 公司                start: 8                end:10
word 有限公司            start: 6                end:10

主要功能-ChineseAnalyzer for Whoosh 搜索引擎

(不了解whoosh的,可以看另一篇关于whoosh的文章)

from __future__ import unicode_literals
import sys,os
sys.path.append("../")
from whoosh.index import create_in,open_dir
from whoosh.fields import *
from whoosh.qparser import QueryParser

from jieba.analyse.analyzer import ChineseAnalyzer

analyzer = ChineseAnalyzer()

schema = Schema(title=TEXT(stored=True), path=ID(stored=True), content=TEXT(stored=True, analyzer=analyzer))
if not os.path.exists("tmp"):
    os.mkdir("tmp")

ix = create_in("tmp", schema) # for create new index
#ix = open_dir("tmp") # for read only
writer = ix.writer()

writer.add_document(
    title="document1",
    path="/a",
    content="This is the first document we’ve added!"
)

writer.add_document(
    title="document2",
    path="/b",
    content="The second one 你 中文测试中文 is even more interesting! 吃水果"
)

writer.add_document(
    title="document3",
    path="/c",
    content="买水果然后来世博园。"
)

writer.add_document(
    title="document4",
    path="/c",
    content="工信处女干事每月经过下属科室都要亲口交代24口交换机等技术性器件的安装工作"
)

writer.add_document(
    title="document4",
    path="/c",
    content="咱俩交换一下吧。"
)

writer.commit()
searcher = ix.searcher()
parser = QueryParser("content", schema=ix.schema)

for keyword in ("水果世博园","你","first","中文","交换机","交换"):
    print("result of ",keyword)
    q = parser.parse(keyword)
    results = searcher.search(q)
    for hit in results:
        print(hit.highlights("content"))
    print("="*10)

for t in analyzer("我的好朋友是李明;我爱北京天安门;IBM和Microsoft; I have a dream. this is intetesting and interested me a lot"):
    print(t.text)

主要功能-命令行接口

实例

python -m jieba news.txt > cut_result.txt

命令行选项(翻译):

使用: python -m jieba [options] filename
固定参数:
  filename              输入文件
可选参数:
  -h, --help            显示此帮助信息并退出
  -d [DELIM], --delimiter [DELIM]
                        使用 DELIM 分隔词语,而不是用默认的' / '。
                        若不指定 DELIM,则使用一个空格分隔。
  -p [DELIM], --pos [DELIM]
                        启用词性标注;如果指定 DELIM,词语和词性之间
                        用它分隔,否则用 _ 分隔
  -D DICT, --dict DICT  使用 DICT 代替默认词典
  -u USER_DICT, --user-dict USER_DICT
                        使用 USER_DICT 作为附加词典,与默认词典或自定义词典配合使用
  -a, --cut-all         全模式分词(不支持词性标注)
  -n, --no-hmm          不使用隐含马尔可夫模型
  -q, --quiet           不输出载入信息到 STDERR
  -V, --version         显示版本信息并退出

如果没有指定文件名,则使用标准输入。

延时加载机制

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

import jieba
jieba.initialize()  # 手动初始化(可选)

在 0.28 之前的版本是不能指定主词典的路径的,有了延迟加载机制后,你可以改变主词典的路径:

jieba.set_dictionary('data/dict.txt.big')

其它词典

1.占用内存较小的词典文件 https://github.com/fxsjy/jieba/raw/master/extra_dict/dict.txt.small

2.支持繁体分词更好的词典文件 https://github.com/fxsjy/jieba/raw/master/extra_dict/dict.txt.big

3.下载你所需要的词典,然后覆盖 jieba/dict.txt 即可;或者用 jieba.set_dictionary('data/dict.txt.big')

算法释义

HMM(Hidden Markov Model): 隐式马尔科夫模型

HMM的典型介绍就是这个模型是一个五元组:

  • StatusSet: 状态值集合
  • ObservedSet: 观察值集合
  • TransProbMatrix: 转移概率矩阵
  • EmitProbMatrix: 发射概率矩阵
  • InitStatus: 初始状态分布

HMM模型可以用来解决三种问题:

  • 参数(StatusSet,TransProbMatrix,EmitRobMatrix,InitStatus)已知的情况下,求解观察值序列。(Forward-backward算法)
  • 参数(ObservedSet,TransProbMatrix,EmitRobMatrix,InitStatus)已知的情况下,求解状态值序列。(viterbi算法)
  • 参数(ObservedSet)已知的情况下,求解(TransProbMatrix,EmitRobMatrix,InitStatus)。(Baum-Welch算法)

其中,第三种问题最玄乎也最不常用,第二种问题最常用,【中文分词】,【语音识别】, 【新词发现】, 【词性标注】 都有它的一席之地。所以本文主要介绍第二种问题,即【viterbi算法求解状态值序列】的方法。

StatusSet & ObservedSet

状态值集合为(B, M, E, S): {B:begin, M:middle, E:end, S:single}。分别代表每个状态代表的是该字在词语中的位置,B代表该字是词语中的起始字,M代表是词语中的中间字,E代表是词语中的结束字,S则代表是单字成词。

观察值集合为就是所有汉字(东南西北你我他...),甚至包括标点符号所组成的集合。

状态值也就是我们要求的值,在HMM模型中文分词中,我们的输入是一个句子(也就是观察值序列),输出是这个句子中每个字的状态值。 比如:

小明硕士毕业于中国科学院计算所

输出的状态序列为

BEBEBMEBEBMEBES

根据这个状态序列我们可以进行切词:

BE/BE/BME/BE/BME/BE/S

所以切词结果如下:

小明/硕士/毕业于/中国/科学院/计算/所

同时我们可以注意到:

B后面只可能接(M or E),不可能接(B or E)。而M后面也只可能接(M or E),不可能接(B, S)。

这五元的关系是通过一个叫Viterbi的算法串接起来, ObservedSet序列值是Viterbi的输入, 而StatusSet序列值是Viterbi的输出, 输入和输出之间Viterbi算法还需要借助三个模型参数, 分别是InitStatus, TransProbMatrix, EmitProbMatrix, 接下来一一讲解:

InitStatus

初始概率分布

#B
-0.26268660809250016
#E
-3.14e+100
#M
-3.14e+100
#S
-1.4652633398537678

示例数值是对概率值取对数之后的结果(可以让概率相乘的计算变成对数相加),其中-3.14e+100作为负无穷,也就是对应的概率值是0。下同。

也就是句子的第一个字属于{B,E,M,S}这四种状态的概率,如上可以看出,E和M的概率都是0,这和实际相符合,开头的第一个字只可能是词语的首字(B),或者是单字成词(S)。

TransProbMatrix

转移概率是马尔科夫链很重要的一个知识点,大学里面学过概率论的人都知道,马尔科夫链最大的特点就是当前T=i时刻的状态Status(i),只和T=i时刻之前的n个状态有关。也就是:

{Status(i-1), Status(i-2), Status(i-3), ... Status(i - n)}
更进一步的说,HMM模型有三个基本假设(具体哪三个请看文末备注)作为模型的前提,其中有个【有限历史性假设】,也就是马尔科夫链的n=1。即Status(i)只和Status(i-1)相关,这个假设能大大简化问题。

回过头看TransProbMatrix,其实就是一个4x4(4就是状态值集合的大小)的二维矩阵,示例如下:

矩阵的横坐标和纵坐标顺序是BEMS x BEMS。(数值是概率求对数后的值,别忘了。)

-3.14e+100 -0.510825623765990 -0.916290731874155 -3.14e+100
-0.5897149736854513 -3.14e+100 -3.14e+100 -0.8085250474669937
-3.14e+100 -0.33344856811948514 -1.2603623820268226 -3.14e+100
-0.7211965654669841 -3.14e+100 -3.14e+100 -0.6658631448798212

比如TransProbMatrix[0][0]代表的含义就是从状态B转移到状态B的概率,由TransProbMatrix[0][0] = -3.14e+100可知,这个转移概率是0,这符合常理。由状态各自的含义可知,状态B的下一个状态只可能是ME,不可能是BS,所以不可能的转移对应的概率都是0,也就是对数值负无穷,在此记为-3.14e+100。

由上TransProbMatrix矩阵可知,对于各个状态可能转移的下一状态,且转移概率对应如下:

#B
#E:-0.510825623765990,M:-0.916290731874155
#E
#B:-0.5897149736854513,S:-0.8085250474669937
#M
#E:-0.33344856811948514,M:-1.2603623820268226
#S
#B:-0.7211965654669841,S:-0.6658631448798212

EmitProbMatrix

这里的发射概率(EmitProb)其实也是一个条件概率而已,根据HMM模型三个基本假设(哪三个请看文末备注)里的【观察值独立性假设】,观察值只取决于当前状态值,也就是:

P(Observed[i], Status[j]) = P(Status[j]) * P(Observed[i]|Status[j])

其中P(Observed[i]|Status[j])这个值就是从EmitProbMatrix中获取。

EmitProbMatrix示例如下:

#B
耀:-10.460283,涉:-8.766406,谈:-8.039065,伊:-7.682602,洞:-8.668696,...
#E
耀:-9.266706,涉:-9.096474,谈:-8.435707,伊:-10.223786,洞:-8.366213,...
#M
耀:-8.47651,涉:-10.560093,谈:-8.345223,伊:-8.021847,洞:-9.547990,....
#S
蘄:-10.005820,涉:-10.523076,唎:-15.269250,禑:-17.215160,洞:-8.369527...

到此,已经介绍完HMM模型的五元参数,假设现在手头上已经有这些参数的具体概率值,并且已经加载进来,那么我们只剩下Viterbi这个算法函数,这个模型就算可以开始使用了。所以接下来讲讲Viterbi算法。

HMM中文分词之Viterbi算法

输入样例:

小明硕士毕业于中国科学院计算所

Viterbi算法计算过程如下:

定义变量

二维数组 weight[4][15],4是状态数(0:B,1:E,2:M,3:S),15是输入句子的字数。比如 weight[0][2] 代表 状态B的条件下,出现'硕'这个字的可能性。

二维数组 path[4][15],4是状态数(0:B,1:E,2:M,3:S),15是输入句子的字数。比如 path[0][2] 代表 weight[0][2]取到最大时,前一个字的状态,比如 path[0][2] = 1, 则代表 weight[0][2]取到最大时,前一个字(也就是明)的状态是E。记录前一个字的状态是为了使用viterbi算法计算完整个 weight[4][15] 之后,能对输入句子从右向左地回溯回来,找出对应的状态序列。

使用InitStatus对weight二维数组进行初始化

已知InitStatus如下:

#B
-0.26268660809250016
#E
-3.14e+100
#M
-3.14e+100
#S
-1.4652633398537678

且由EmitProbMatrix可以得出

Status(B) -> Observed(小)  :  -5.79545
Status(E) -> Observed(小)  :  -7.36797
Status(M) -> Observed(小)  :  -5.09518
Status(S) -> Observed(小)  :  -6.2475

所以可以初始化 weight[i][0] 的值如下:

weight[0][0] = -0.26268660809250016 + -5.79545 = -6.05814
weight[1][0] = -3.14e+100 + -7.36797 = -3.14e+100
weight[2][0] = -3.14e+100 + -5.09518 = -3.14e+100
weight[3][0] = -1.4652633398537678 + -6.2475 = -7.71276

注意上式计算的时候是相加而不是相乘,因为之前取过对数的原因。

遍历句子计算整个weight二维数组

//遍历句子,下标i从1开始是因为刚才初始化的时候已经对0初始化结束了
for(size_t i = 1; i < 15; i++)
{
    // 遍历可能的状态
    for(size_t j = 0; j < 4; j++) 
    {
        weight[j][i] = MIN_DOUBLE;
        path[j][i] = -1;
        //遍历前一个字可能的状态
        for(size_t k = 0; k < 4; k++)
        {
            double tmp = weight[k][i-1] + _transProb[k][j] + _emitProb[j][sentence[i]];
            if(tmp > weight[j][i]) // 找出最大的weight[j][i]值
            {
                weight[j][i] = tmp;
                path[j][i] = k;
            }
        }
    }
}

如此遍历下来,weight[4][15]和path[4][15]就都计算完毕。

确定边界条件和路径回溯
边界条件如下:

对于每个句子,最后一个字的状态只可能是 E 或者 S,不可能是 M 或者 B。

所以在本文的例子中我们只需要比较 weight[1(E)][14] 和 weight[3(S)][14] 的大小即可。

在本例中:

weight[1][14] = -102.492;
weight[3][14] = -101.632;

所以 S > E,也就是对于路径回溯的起点是 path[3][14]。

回溯的路径是:

SEBEMBEBEMBEBEB

倒序一下就是:

BE/BE/BME/BE/BME/BE/S
所以切词结果就是:

小明/硕士/毕业于/中国/科学院/计算/所

到此,一个HMM模型中文分词算法过程就阐述完毕了。

也就是给定我们一个模型,我们对模型进行载入完毕之后,只要运行一遍Viterbi算法,就可以找出每个字对应的状态,根据状态也就可以对句子进行分词。

模型的训练问题
以上讲的前提是基于模型来进行切词,也就是假设我们手头上的HMM模型已经是被训练好了的(也就是InitStatus, TransProbMatrix, EmitProbMatrix这三个模型的关键参数都是已知的),没有涉及到这三个参数是如何得到的。 这三个参数其实也是基于已分词完毕的语料进行统计计算,计算出相应的频率和条件概率就可以算出这三个参数。具体在此就不讲了。

备注
HMM模型的三个基本假设如下:

  • 有限历史性假设:
P(Status[i]|Status[i-1],Status[i-2],... Status[1]) = P(Status[i]|Status[i-1])
  • 齐次性假设(状态和当前时刻无关):
P(Status[i]|Status[i-1]) = P(Status[j]|Status[j-1])
  • 观察值独立性假设(观察值只取决于当前状态值):
P(Observed[i]|Status[i],Status[i-1],...,Status[1]) = P(Observed[i]|Status[i])

词性说明

缩写 词性 说明
Ag 形语素 形容词性语素。形容词代码为 a,语素代码g前面置以A。
a 形容词 取英语形容词 adjective的第1个字母。
ad 副形词 直接作状语的形容词。形容词代码 a和副词代码d并在一起。
an 名形词 具有名词功能的形容词。形容词代码 a和名词代码n并在一起。
b 区别词 取汉字“别”的声母。
c 连词 取英语连词 conjunction的第1个字母。
dg副语素 副词性语素。副词代码为 d,语素代码g前面置以D。
d 副词 取adverb的第2个字母,因其第1个字母已用于形容词。
e 叹词 取英语叹词exclamation的第1个字母。
f 方位词 取汉字“方”
g 语素 绝大多数语素都能作为合成词的“词根”,取汉字“根”的声母。
h 前接成分 取英语head的第1个字母。
i 成语 取英语成语idiom的第1个字母。
j 简称略语 取汉字“简”的声母。
k 后接成分
l 习用语 习用语尚未成为成语,有点“临时性”,取“临”的声母。
m 数词 取英语numeral的第3个字母,n,u已有他用。
Ng 名语素 名词性语素。名词代码为 n,语素代码g前面置以N。
n 名词 取英语名词noun的第1个字母。
nr 人名名词 代码n和“人(ren)”的声母并在一起。
ns 地名名词 代码n和处所词代码s并在一起。
nt 机构团体 “团”的声母为t,名词代码n和t并在一起。
nz 其他专名 “专”的声母的第1个字母为z,名词代码n和z并在一起。
o 拟声词 取英语拟声词onomatopoeia的第1个字母。
p 介词 取英语介词prepositional的第1个字母。
q 量词 取英语quantity的第1个字母。
r 代词 取英语代词pronoun的第2个字母,因p已用于介词。
s 处所词 取英语space的第1个字母。
tg 时语素 时间词性语素。时间词代码为t,在语素的代码g前面置以T。
t 时间词 取英语time的第1个字母。
u 助词取英语助词 auxiliary
vg 动语素动词性语素。动词代码为 v。在语素的代码g前面置以V。
v 动词 取英语动词verb的第一个字母。
vd 副动 词直接作状语的动词。动词和副词的代码并在一起。
vn 名动词 指具有名词功能的动词。动词和名词的代码并在一起。
w 标点符号
x 非语素字 非语素字只是一个符号,字母 x通常用于代表未知数、符号。
y 语气词 取汉字“语”的声母。
z 状态词 取汉字“状”的声母的前一个字母。
un 未知词

相关文章

  • jieba分词-小白使用贴

    (主要内容均来源于github上的说明) 特点 支持三种分词模式:精确模式,试图将句子最精确地切开,适合文本分析;...

  • python3中文jieba分词设置说明

    jieba分词的安装 在虚拟环境中 / 本地下安装 jieba jieba分词的配置 jieba中文分词的使用 进...

  • 分词练习

    一、实验目标 尝试使用jieba对《龙族》进行分词,并进行分词效果比较分析 二、使用工具 在线分词工具、jieba...

  • 自然语言处理(NLP)相关

    ヾ(◍°∇°◍)ノ゙-参考 结巴分词使用 中文分词之结巴分词~~~附使用场景+demo(net) jieba分词、...

  • 分词练习

    使用ICTCLAS(NLPIR)在线分词工具和jieba分词组件进行分词练习。 一. ICTCLAS 1.简介 汉...

  • 使用C重写jieba结巴分词库,大幅提速50%-60%

    jieba_fast ======== 使用`python`重写了jieba分词库中计算DAG和HMM中的vitr...

  • 常用分词工具使用教程

    常用分词工具使用教程 以下分词工具均能在Python环境中直接调用(排名不分先后)。 jieba(结巴分词) 免费...

  • 中文分词系统实验报告:jieba和IK Analyzer

    Jieba使用实验 本文尝试了jieba的三种分词模式、自定义字典、计算频数并将频数较高的分词结果存入csv文件。...

  • 结巴中文分词的用法

    jieba “结巴”中文分词:做最好的 Python 中文分词组件"Jieba" (Chinese for "to...

  • python 结巴分词

    jieba “结巴”中文分词:做最好的 Python 中文分词组件“Jieba” (Chinese for “to...

网友评论

    本文标题:jieba分词-小白使用贴

    本文链接:https://www.haomeiwen.com/subject/dpwefqtx.html