NLP入门学习1——分词和词性标注

NLP入门学习1——分词和词性标注

  • 0.简介
  • 1.概念和工具
    • 1.1 词性标注
    • 1.2 NLTK
    • 1.3 jieba
    • 1.4 LAC
  • 2.代码实现
    • 2.1 分词
      • 2.1.1 使用nltk进行分词:
      • 2.1.2 使用jieba进行分词
      • 2.1.3 使用LAC进行分词
    • 2.2 词性标注
      • 2.2.1 使用nltk工具实现词性标注
      • 2.2.2 使用LAC工具实现词性标注
  • 3.遇到的问题及解决
    • 3.1 Resource punkt not found
  • 4.结束

0.简介

本文主要介绍NLP中最基础的任务分词和词性标注。难度属于入门级别。
本文的主要参考如下:
参考链接1
参考链接2
参考链接3
参考链接4

1.概念和工具

1.1 词性标注

词性标注是NLP四大基本任务中序列标注中的一项,其目的是对文本中的词汇实现词性的划分。标注的结果是一个由二元组组成的list,其中每一个二元组中标明了每个token对应的词性。

1.2 NLTK

NLTK全称natural language toolkit是一个基于python编写的自然语言处理工具箱。
安装非常简单,直接用conda或者pip安装即可。

conda install nltk

在nltk中,将词性归为以下类别:

简写 全称 含义
CC coordinating conjunction 并列连词
CD cardinal digit 基数
DT determiner 限定词
EX existentialthere 存在句
FW foreignword 外来语
IN preposition/subordinating conjunction 介词/从属连词
JJ adjective 形容词
JJR adjective, comparative 比较级形式
JJS adjective, superlative 最高级
MD modal 情态动词
NN noun 名词单数形式
NNS noun 名词复数形式
NNP propernoun 专有名词单数形式
NNPS propernoun 专有名词复数形式
PDT predeterminer 前位限定词
POS possessiveending 属有词’s
PRP personalpronoun 人称代词
PRP$ possessive pronoun 物主代词
RB adverb very 副词
RBR adverb,comparative 副词比较级
RBS adverb,superlative 副词最高级
RP particle 与动词构成短语的副词或介词
TO to to
UH interjection 感叹词
VB verb 动词
VBD verb 动词过去式
VBG verb 现在分词
VBN verb 过去分词
VBP verb 动词现在
VBZ verb 动词 第三人称
WDT wh-determiner 限定词which等
WP wh-pronoun 代词who, what 等
WP$ possessivewh-pronoun 所有格 whose
WRB wh-abverb where, when 副词

1.3 jieba

jieba是一个优秀的中文分词库,同样是基于python。
支持精确模式,全模式,搜索引擎模式等多种模式。
Github:jieba

jieba安装可以在conda命令行通过如下指令完成:

conda install --channel https://conda.anaconda.org/conda-forge jieba 

1.4 LAC

LAC全称Lexical Analysis of Chinese,是百度自然语言处理部研发的一款联合的词法分析工具,实现中文分词、词性标注、专名识别等功能。
GitHub:LAC
LAC的安装也非常简单:

pip install lac -i https://mirror.baidu.com/pypi/simple

在词性标注任务中,LAC将词性归为以下类:
NLP入门学习1——分词和词性标注_第1张图片

2.代码实现

2.1 分词

分词可以使用nltk实现,也可以使用其他工具如jieba实现。
使用nltk工具进行分词可以直接由文本到token划分,也可以先进行sentence level的分词。

2.1.1 使用nltk进行分词:

(1)直接划分

words = nltk.word_tokenize(text)
words

结果:

Out[1]: ['life', 'is', 'short', '.', 'play', 'more', 'sport', '.']

(2)先进行句子划分:

import nltk
text = 'life is short. play more sport.'
sents = nltk.sent_tokenize(text)
sents

结果:

Out[1]: ['life is short.', 'play more sport.']

再进行分词:

words = [nltk.word_tokenize(i) for i in sents]
words

结果:

Out[1]: [['life', 'is', 'short', '.'], ['play', 'more', 'sport', '.']]

但没有加载中文语料库的情况下,试图使用nltk进行中文分词就会出现问题:

words = nltk.word_tokenize('吃葡萄不吐葡萄皮,不吃葡萄倒吐葡萄皮')
words

结果可以看出分词并没有成功:

['吃葡萄不吐葡萄皮,不吃葡萄倒吐葡萄皮']

接下来就介绍可以用于中文分词的工具。

2.1.2 使用jieba进行分词

jieba的分词功能可以由两个函数实现,cut函数返回的是一个generator,lcut函数直接返回一个list,具体的使用方法:
(1) cut:

import jieba
import jieba.analyse
words = jieba.cut(text)
print('/'.join(words))

结果:

 life/ /is/ /short/./ /play/ /more/ /sport/.

(2) lcut:

words = jieba.lcut(text)
print(words)

结果:

 ['life', ' ', 'is', ' ', 'short', '.', ' ', 'play', ' ', 'more', ' ', 'sport', '.']

在这里可以看出jieba分词与nltk之间的一个区别在于,jieba的分词结果中把空格也包含进去了,不限要空格的话就把它删掉就好了。

words = jieba.lcut(text)
while ' ' in words:
    words.remove(' ')
print(words)

结果:

['life', 'is', 'short', '.', 'play', 'more', 'sport', '.']

jieba除了可以进行英文分词,也可以进行中文分词。

words = jieba.lcut('吃葡萄不吐葡萄皮,不吃葡萄倒吐葡萄皮')
words

结果:

['吃', '葡萄', '不吐', '葡萄', '皮', ',', '不吃', '葡萄', '倒', '吐', '葡萄', '皮']

2.1.3 使用LAC进行分词

使用LAC进行分词也很简单,下面是LAC官方的操作指引和样例结果。

from LAC import LAC

# 装载分词模型
lac = LAC(mode='seg')

# 单个样本输入,输入为Unicode编码的字符串
text = "LAC是个优秀的分词工具"
seg_result = lac.run(text)

# 批量样本输入, 输入为多个句子组成的list,平均速率会更快
texts = ["LAC是个优秀的分词工具", "百度是一家高科技公司"]
seg_result = lac.run(texts)

结果:

【单样本】:seg_result = [LAC, 是, 个, 优秀, 的, 分词, 工具]
【批量样本】:seg_result = [[LAC, 是, 个, 优秀, 的, 分词, 工具], [百度, 是, 一家, 高科技, 公司]]

2.2 词性标注

2.2.1 使用nltk工具实现词性标注

pos_tags =nltk.pos_tag(words)
print(pos_tags)

结果:

[('life', 'NN'), ('is', 'VBZ'), ('short', 'JJ'), ('.', '.'), ('play', 'VB'), ('more', 'JJR'), ('sport', 'NN'), ('.', '.')]

可以看出在英文分词方面nltk工具的效果还是很准确,很精细的。

上文中提到nltk在中文分词中不灵了,那么如果将分好的token输入给nltk,是否能够完成词性标注了?

words = jieba.lcut('吃葡萄不吐葡萄皮,不吃葡萄倒吐葡萄皮')
pos_tags =nltk.pos_tag(words)
pos_tags

结果:

[('吃', 'JJ'),
 ('葡萄', 'NNP'),
 ('不吐', 'NNP'),
 ('葡萄', 'NNP'),
 ('皮', 'NNP'),
 (',', 'NNP'),
 ('不吃', 'NNP'),
 ('葡萄', 'NNP'),
 ('倒', 'NNP'),
 ('吐', 'NNP'),
 ('葡萄', 'NNP'),
 ('皮', 'NN')]

尽管标注完成了,但是通过判断发现它的标注并不准确,把“吃”标注成了形容词,“不吐”标注成了名词。

2.2.2 使用LAC工具实现词性标注

from LAC import LAC

# 装载LAC模型
lac = LAC(mode='lac')

# 单个样本输入,输入为Unicode编码的字符串
text = u"LAC是个优秀的分词工具"
lac_result = lac.run(text)

# 批量样本输入, 输入为多个句子组成的list,平均速率更快
texts = [u"LAC是个优秀的分词工具", u"百度是一家高科技公司"]
lac_result = lac.run(texts)

结果:

【单样本】: lac_result = ([百度, 是, 一家, 高科技, 公司], [ORG, v, m, n, n])
【批量样本】:lac_result = [
                    ([百度, 是, 一家, 高科技, 公司], [ORG, v, m, n, n]),
                    ([LAC, 是, 个, 优秀, 的, 分词, 工具], [nz, v, q, a, u, n, n])
                ]

再来测试一下我们自己的例子:

from LAC import LAC

# 装载LAC模型
lac = LAC(mode='lac')

# 单个样本输入,输入为Unicode编码的字符串
text = u"吃葡萄不吐葡萄皮,不吃葡萄倒吐葡萄皮"
lac_result = lac.run(text)

结果:

[['吃', '葡萄', '不', '吐', '葡萄皮', ',', '不', '吃', '葡萄', '倒', '吐', '葡萄皮'],
 ['v', 'nz', 'd', 'v', 'n', 'w', 'd', 'v', 'n', 'd', 'v', 'n']]

结果同样十分准确,并且相比jieba分词的结果,吧“葡萄皮”作为一个整体保留下来了。

3.遇到的问题及解决

3.1 Resource punkt not found

使用nltk分词时,报错LookupError Resource punkt not found,按照提示下载,nltk.download(‘punkt’),提示failed。
这是因为资源在外网,所以访问不了。解决方法,手动下载,并保存在指定位置.
下载链接在git上还有很多人的博客上都可以找到,为了防止失效,我又在自己的网盘里传了一个。
地址:https://pan.baidu.com/s/14KpU-BNuST6IwAFhWOosBA 提取码:s8zt

下载之后把缺少的包放在自动搜索的路径下,如各盘的根目录,在这里我把它放在了anaconda的路径下。
在…\anaconda\share路径下创建文件夹nltk_data,以punkt为例,把下载的数据解压,把punkt中的english.pickle 放在…\anaconda\share\nltk_data\tokenizers\punkt\PY3\english.pickle,就可以了。
有一个细节需要注意一下,在解压之后的文件夹中并没有包含名为PY3的文件夹,如果不自己创建一个的话,仍然会报错。
类似的问题也采用类似的解决方法。

如果以上的内容中出现了任何错误和不准确的地方,还请帮忙指出,谢谢。

4.结束

接下来的一段时间里,我会从最基础的内容开始NLP的学习,主要会记录一些基本的概念和NLP工具和模型在使用的过程中遇到的问题。那么我们下期再见。

你可能感兴趣的:(自然语言处理,自然语言处理)