南京音乐推荐联合社

汉语分词01 | 当你在计算机上输入一句话时,计算机是怎么理解的.

2019-07-10 15:43:10

算上Python主题首更吧,感谢蔡老师给我一个接触人工智能的机会,上个月蔡老师给我的安排的任务,到今天才算完成。


Python,这个词在从去年开始非非常火。春节和一些帮程序猿同学聊天,把这个读成了“ 呸腾“,被嘲笑了好久。十天的时间,看了一些视频和书籍,总算理解了一点皮毛。人工智能这个四个字包含了太多的东西,这么大的一个概念,是由很多个功能搭建起来的。蔡老师给我的第一个任务就是学习汉语分词


当我们在计算机或者手机输入一句汉语时候,计算机是怎么识别的呢?汉语不像英语一样,有天然的空格,计算机一看就知道。而汉字,既难以划分句子成分,也难以理解特定语境下的语意。比如:


冬天:能穿多少穿多少;夏天:能穿多少穿多少。

单身人的来由:原来是喜欢一个人,现在是喜欢一个人。


看吧,这就是依然语言处理的魅力,如何能让计算机理解你输入的是什么意思,在某些情况下是很难的。自然语言处理分为五个层次:分词、标注词性、命名实体识别、依存句法分析、语义分析。如果把这五个层次都做到位了,计算机就能很好的理解文本。现在很多技术,比如关键字提取、搜索引擎、机器翻译等都依赖于分词的准确率,可以说汉语分词是这些技术的根基。


了解了汉语分词的重要性,我们就来谈谈如何进行分词。中华文化博大精深,一个词在这里是一个意思,换句话,意思就相差很多。有时候连我们也无法确切理解,何况计算机。


 结婚的和尚为结婚的

切分一:结婚/的/和尚/未/结婚/的

切分二:结婚/的/和/尚未/结婚/的


这两个拆分对于计算机而言都比较合理,选择哪个呢?现在中文分词遇到的最大的困难就是,歧义词选择和未收录词识别。


歧义词识别一般有三类,交叉歧义词、组合歧义词、真歧义词


交叉歧义词,比如:你说的确实对,的确 和 确实  都是一个独立的词。


组合歧义词,比如:这个人手上有个泡&现在人手不够。同样的人手,因为人和手本来就是独立的词。


真歧义词:羽毛球拍卖完了。球拍  和 拍卖 这个就是真歧义,无论你选择哪个,都是正确的。


未收录词的挑战要比歧义大的多,每一天都有很多新词产生,如果不把这些词收录进来,就会出现很多错误。还有一些新增加的姓名、地名、书名等,当然要想全部收录,也是不现实的,能做的就是尽量识别,所以有时候评价一个分词程序的号=好坏就看这两个做的是不是好。


今天就来谈谈如何实现中文分词:


当时蔡老师问我的时候,我试着给出了一些答案,后来自己查阅资料,竟然发现已经有很多的科学理论了,正向最大匹配,逆向最大匹配,最少词切分法,双向匹配法。以正向最大匹配为例:沈阳航空航天大学是我的硕士学校。这句话,从左到右,一共16个字,计算机会识别这十六个字是不是一个词,答案当然不是。然后进一步缩小范围,当缩小到前八个字时,发现这是个词了,沈阳航空航天大学,是一个专有词汇,接下来从“是我的硕士学校”开始继续分,最终划分为 沈阳航空航天大学\是\我的\硕士\学校


其他几个也类似,这种是机械分词的方法,错误率非常高。随着词典的增大,词与词之间的交叉会变得更加严重,歧义带来的负面影响会更加严重。同时,基于规则的切分方法对于新词的切分是完全无能为力的。


现在主流的是基于统计的分词、基于理解的分词、基于语义的分词。


后两种感觉比较困难,还没来的即学习,现阶段的Python技术也不行,还是重点放在学习编程语言上。


就简单说说我今天用第一个分词程序,是基于统计的,也是被广大程序袁一致好评的程序——jieba,后续还会提到别的分词方法。


看到这个名字,你就能想到这个程序有多形象了,很多人在结巴的时候都会一个字一个词的往出蹦。


先来说说这个程序


这个程序有三种模式,一种是全模式,一种是精确模式,一种是搜索引擎模式。很容易理解。另外这个程序还支持繁体字和自定义词典。



#coding=utf-8

#Version:python3.6.0

#Tools:Pycharm 2017.3.2

__date__ = '2018/5/9 15:00'

__aythor__ = 'Yaobing'


import jieba


seg_list = jieba.cut("我来到北京清华大学", cut_all=True)

print("Full Mode: " + "/ ".join(seg_list))  # 全模式


seg_list = jieba.cut("我来到北京清华大学", cut_all=False)

print("Default Mode: " + "/ ".join(seg_list))  # 精确模式


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


print(", ".join(seg_list))




Full Mode: 我/ 来到/ 北京/ 清华/ 清华大学/ 华大/ 大学

Default Mode: 我/ 来到/ 北京/ 清华大学

小明, 硕士, 毕业, 于, 中国, 科学, 学院, 科学院, 中国科学院, 计算, 计算所, ,, 后, 在, 日本, 京都, 大学, 日本京都大学, 深造


增加词典有两种,一可以建立一个txt文件,包含你的词汇,也可以直接在程序中说明你的词汇是自定的。


要用Utf-8编码




import jieba

jieba.load_userdict("C:/Users/YB/Desktop/test.txt")


test_sent = (

"李小福是创新办主任也是云计算方面的专家; 什么是八一双鹿\n"

"「台中」正確應該不會被切開。mac上可分出「石墨烯」;此時又可以分出來凱特琳了。"

)

words = jieba.cut(test_sent)

print('/'.join(words))




李小福/是/创新办/主任/也/是/云计算/方面/的/专家/;/ /什么/是/八/一双/鹿/

/「/台中/」/正確/應該/不會/被/切開/。/mac/上/可/分出/「/石墨/烯/」/;/此時/又/可以/分出/來/凱特琳/了/。


Loading model cost 2.387 seconds.

Prefix dict has been built succesfully.




  • 使用 add_word(word, freq=None, tag=None) 和 del_word(word) 可在程序中动态修改词典。


  • 使用 suggest_freq(segment, tune=True) 可调节单个词语的词频,使其能(或不能)被分出来。


也可以提取关键字,有两种方便的方式:


基于extract:


from jieba import analyse

# 引入TF-IDF关键词抽取接口

tfidf = analyse.extract_tags


# 原始文本

text = "线程是程序执行时的最小单位,它是进程的一个执行流,\

        是CPU调度和分派的基本单位,一个进程可以由很多个线程组成,\

        线程间共享进程的所有资源,每个线程有自己的堆栈和局部变量。\

        线程由CPU独立调度执行,在多CPU环境下就允许多个线程同时运行。\

        同样多线程也可以实现并发操作,每个请求分配一个线程来处理。"


# 基于TF-IDF算法进行关键词抽取

keywords = tfidf(text)

print ("keywords by tfidf: ")

# 输出抽取出的关键词

for keyword in keywords:

    print (keyword + "/")



keywords by tfidf: 

线程/

CPU/

进程/

调度/

多线程/

程序执行/

每个/

执行/

堆栈/

局部变量/

单位/

并发/

分派/

一个/

共享/

请求/

最小/

可以/

允许/

分配/




基于textrank


from jieba import analyse

# 引入TextRank关键词抽取接口

textrank = analyse.textrank


# 原始文本

text = "线程是程序执行时的最小单位,它是进程的一个执行流,\

        是CPU调度和分派的基本单位,一个进程可以由很多个线程组成,\

        线程间共享进程的所有资源,每个线程有自己的堆栈和局部变量。\

        线程由CPU独立调度执行,在多CPU环境下就允许多个线程同时运行。\

        同样多线程也可以实现并发操作,每个请求分配一个线程来处理。"


print ("\nkeywords by textrank:")

# 基于TextRank算法进行关键词抽取

keywords = textrank(text)

# 输出抽取出的关键词

for keyword in keywords:

    print (keyword + "/",)


Prefix dict has been built succesfully.

线程/

进程/

调度/

单位/

操作/

请求/

分配/

允许/

基本/

并发/

独立/

资源/

共享/

执行/

堆栈/

分派/

运行/

实现/

处理/

程序执行/


这两种统计算法,之后再学习。


词性标注


import jieba.posseg as pseg

words= pseg.cut("我现在是研究生")

for w in words:

    print (w.word,w.flag)




我 r

现在 t

是 v

研究生 n



当然结巴还有很多有用的地方,接下来我还会继续学习分词。



Copyright © 南京音乐推荐联合社@2017