【NLP】自然语言处理_NLP入门——分词和词性标注

【NLP】自然语言处理_NLP入门——分词和词性标注


1. 介绍

NLP 四大任务:

  • 序列标注:分词,词性标注,命名实体识别
  • 分类任务:文本分类,情感计算
  • 句子关系判断:entailment(分类为蕴含或矛盾),相似度计算
  • 生成式任务:机器翻译,问答系统,文本摘要

本文主要介绍NLP中最基础的任务分词和词性标注。难度属于入门级别。


2. 概念和工具

2.1 分词

分词是 NLP 的重要步骤。

  • 分词就是将句子、段落、文章这种长文本,分解为以字词为单位的数据结构,方便后续的处理分析工作。
  • 分词获得的就是由词语组成的 list,而不是原来的句子。

2.2 词性标注

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

2.3 NLTK

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

pip install -i https://pypi.tuna.tsinghua.edu.cn/simple nltk
  • 在nltk中,将词性归为以下类别:
    在这里插入图片描述

2.4 Jieba

jieba是一个优秀的中文分词库,同样是基于python。

  • 支持精确模式,全模式,搜索引擎模式等多种模式。
  • Github:jieba

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

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

2.5 LAC

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

  • GitHub:LAC
    LAC的安装也非常简单:
pip install lac -i https://mirror.baidu.com/pypi/simple
  • 在词性标注任务中,LAC将词性归为以下类:
    在这里插入图片描述

3. 代码实现+举例

3.1 分词

分词可以使用nltk实现,也可以使用其他工具如jieba实现。

  • 使用nltk工具进行分词可以直接由文本到token划分,
  • 也可以先进行sentence level的分词。

3.1.1 使用nltk进行分词

1)直接划分:

words = nltk.word_tokenize(text)
words
  • 结果:['life', 'is', 'short', '.', 'play', 'more', 'sport', '.']

2)1. 先进行句子划分:

import nltk
text = 'life is short. play more sport.'
sents = nltk.sent_tokenize(text)
sents
  • 结果:['life is short.', 'play more sport.']

2)2. 再进行分词

words = [nltk.word_tokenize(i) for i in sents]
words
  • 结果:[['life', 'is', 'short', '.'], ['play', 'more', 'sport', '.']]

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

words = nltk.word_tokenize('吃葡萄不吐葡萄皮,不吃葡萄倒吐葡萄皮')
words
  • 结果可以看出,分词并没有成功:['吃葡萄不吐葡萄皮,不吃葡萄倒吐葡萄皮']

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


3.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', '.']

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

words = jieba.lcut('吃葡萄不吐葡萄皮,不吃葡萄倒吐葡萄皮')
words
  • 结果:['吃', '葡萄', '不吐', '葡萄', '皮', ',', '不吃', '葡萄', '倒', '吐', '葡萄', '皮']

3.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, 是, 个, 优秀, 的, 分词, 工具], [百度, 是, 一家, 高科技, 公司]]

3.2 词性标注

3.2.1 使用 nltk 实现词性标注

1)英文

pos_tags =nltk.pos_tag(words)
print(pos_tags)
  • 结果:[('life', 'NN'), ('is', 'VBZ'), ('short', 'JJ'), ('.', '.'), ('play', 'VB'), ('more', 'JJR'), ('sport', 'NN'), ('.', '.')]

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

2)中文
那么如果将分好的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')]

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

3.2.2 使用LAC实现词性标注

1)例子1

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]) ]

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

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 分词的结果,把“葡萄皮”作为一个整体保留下来了。

4. 可能的问题及解决

4.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的文件夹,如果不自己创建一个的话,仍然会报错。
类似的问题也采用类似的解决方法。

上面内容参考:https://blog.csdn.net/weixin_44826203/article/details/107484634

5. 参考

【1】https://blog.csdn.net/weixin_44826203/article/details/107484634
【2】https://blog.csdn.net/jasonjarvan/article/details/79955664
【3】https://blog.csdn.net/zzulp/article/details/77150129
【4】https://blog.csdn.net/qq_41595507/article/details/104123975
【5】https://github.com/baidu/lac

猜你喜欢

转载自blog.csdn.net/qq_51392112/article/details/130086873