Contents

文本预处理

1. 中&英文分词

文本都是一些「非结构化数据」,需要先将这些数据转化为「结构化数据」,结构化数据就可以转化为数学问题以方便机器计算,而分词就是转化的第一步。分词就是将句子、段落、文章这种长文本,分解为以字词为单位的数据结构,方便后续的处理分析工作。

中英文分词区别

  1. 分词方式不同,中文更难。英文有天然的空格作为分隔符,但是中文没有。
  2. 英文单词有多种形态,需要词性还原和词干提取;而中文里虽然没有多种形态,但是一词多意的情况非常多,导致很容易出现歧义
  3. 中文分词需要考虑粒度问题,粒度越大,表达的意思就越准确,但是也会导致召回比较少。所以中文需要不同的场景和要求选择不同的粒度。

分词的方法

基于词典匹配的分词方式

优点:速度快、成本低

缺点:适应性不强,不同领域效果差异大

基本思想是基于词典匹配,将待分词的中文文本根据一定规则切分和调整,然后跟词典中的词语进行匹配,匹配成功则按照词典的词分词,匹配失败通过调整或者重新选择,如此反复循环即可。代表方法有基于正向最大匹配和基于逆向最大匹配及双向匹配法。

基于统计的分词方法

优点:适应性较强

缺点:成本较高,速度较慢

这类目前常用的是算法是HMM、CRF、SVM、深度学习等算法,比如stanford、Hanlp分词工具是基于CRF算法。以CRF为例,基本思路是对汉字进行标注训练,不仅考虑了词语出现的频率,还考虑上下文,具备较好的学习能力,因此其对歧义词和未登录词的识别都具有良好的效果。

基于深度学习

优点:准确率高、适应性强

缺点:成本高,速度慢

例如有人员尝试使用双向LSTM+CRF实现分词器,其本质上是序列标注,所以有通用性,命名实体识别等都可以使用该模型,据报道其分词器字符准确率可高达97.5%。

分词工具

中文分词工具

下面排名根据 GitHub 上的 star 数排名:

Hanlp Stanford ansj分词器 哈工大LTP KCWS分词器 jieba IK 清华大学THULAC ICTCLAS

英文分词工具

Keras Spacy Gensim NLTK

import jieba
import re

content = "一位布里斯托机器人实验室的机器人专家设计让机器人将名为‘人机者’的人类替身救出险境"
"""
def re.sub(pattern, repl, string, count=0, flags=0):
(1)pattern:该参数表示正则中的模式字符串;
(2)repl:该参数表示要替换的字符串(即匹配到pattern后替换为repl),也可以是个函数;
(3)string:该参数表示要被处理(查找替换)的原始字符串;
"""
content = re.sub(r'[^\u4e00-\u9fa5]', '', content) #\u4e00 是unicode中第一个汉字的码点,\u9fa5 是unicode中最后一个汉字的码点。前面加一个^表示非匹配汉字
# 万能的中文匹配方式 /\p{sc=Han}/gu
print(content)
print(jieba.cut(content))
"""   
join():    
连接字符串数组。将字符串、元组、列表中的元素以指定的字符(分隔符)连接生成一个新的字符串
"""
result = '/'.join(jieba.cut(content)) # jieba.cut(content)返回一个迭代器,join方法会遍历这个迭代器,从而访问迭代器的每个元素,达到中间插入/的目的

print(result.split("/"))
import nltk
from nltk import data
"""
data是NLTK的数据管理模块,允许你管理和访问NLTK所需的各种数据,例如语料库、词典、分词模型等
它可以帮助你下载、缓存和获取NLTK所需的各种数据资源,以便在使用NLTK进行自然语言处理任务时进行引用和使用。
"""
data.path.append('/home/mw/input/geci_82079530/nltk_data/nltk_data/packages')
import re

content="A roboticist at the Bristol Robotics Laboratory programmed a robot to save human proxies called 'H-bots' from danger."
content=re.sub('[^\w ]','',content)
print(content)
print(nltk.word_tokenize(content))               #英文句子分词
print(nltk.pos_tag(nltk.word_tokenize(content))) #对分完词的结果进行词性标注

2. 文本数字化:

获得以词为单位的数据,但是要使文字能被机器理解,还需要将文本数字化,一般有两个解决方案:传统的向量空间模型和词向量技术。

传统向量空间模型是要将一行文本转化为一个向量,典型技术有词袋模型、TF-IDF(词频逆文档频率)模型。词向量技术是将一个词表示为一个低维度、稠密的向量,能使的语义上相近的词向量距离相近,典型技术有word2vec和GloVe。

2.1.1 词袋模型

词袋模型就是要想把多个词组成的一段话转换为一个向量。首先需要给词进行编码。给单词编码一般采用one-hot编码(独热编码),其思想就是给每个不同的单词一个唯一对应的编码。

比如,“一位布里斯托机器人实验室的机器人专家”可以看成由“一位”、“布里斯托”、“机器人”、“实验室”、“的”、“专家”这6个词组成的序列。

“一位”编码为 [1,0,0,0,0,0],“布里斯托”编码为 [0,1,0,0,0,0],“机器人”编码为 [0,0,1,0,0,0],“实验室”编码为 [0,0,0,1,0,0],“的”编码为 [0,0,0,0,1,0],“专家”编码为 [0,0,0,0,0,1]。单词编码已完成,接下来考虑向量化行文本,即用一个n维的向量表示一段话,向量中的n个位置表示该编码的单词在文本中的权重。

“一位布里斯托机器人实验室的机器人专家”可以向量化为 [1,1,2,1,1,1]。在这段话中,“机器人”出现了两次,并且“机器人”的编码为 [0,0,1,0,0,0]。以上向量化文本的方式就是词袋模型,向量中每个位置的值为该编码对应的词在这段话中出现的次数。

2.1.2 TF-IDF

TF-IDF模型和词袋模型思想一样,只是向量的值不同。向量中的值为该位置对应的词在文本中的权重,词袋模型认为文本中出现次数多的词权重大,故值就是词在文本中出现的次数。但是单单由词频来决定词在文章中的重要程度是不太准确的,因为有些词在文本中出现频率高但无实际意义,比如“是”,“的”,“等等”等常见词。因此会使用TF-IDF来避免常用词出现频繁的问题。

TF(词频 - term frequency):指的是某一个给定的词语在该文件中出现的次数。这个数字通常会被归一化(一般是词频除以文章总词数), 以防止它偏向长的文件。

https://cdn.kesci.com/upload/image/rh3z87sm6p.png?imageView2/0/w/960/h/960#id=jgGms&originHeight=155&originWidth=550&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=

IDF(逆向文件频率 - inverse document frequency):包含指定词语的文档越少,IDF越大。指定词语的IDF,由总文件数目除以包含该词语之文件的数目,再将得到的商取对数得到,即:

https://cdn.kesci.com/upload/image/rh3z8p4vcp.jpeg?imageView2/0/w/960/h/960#id=ZaWIv&originHeight=120&originWidth=550&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=

TF-IDF与一个词在文档中的出现次数成正比,与该词在整个语言中的出现次数成反比。所以,自动提取关键词的算法就很清楚了,就是计算出文档的每个词的TF-IDF值,然后按降序排列,取排在最前面的几个词。

https://cdn.kesci.com/upload/image/rh3zb1u6en.png?imageView2/0/w/960/h/960#id=PDqoB&originHeight=68&originWidth=550&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=

总结一下,向量空间模型可以将一行文本转换为一个向量,常见的有词袋模型和TF-IDF模型,他们的核心思想是将词编码为唯一不同的数字,向量中的值为该位置对应的词在文本中的权重。

2.2.1 词向量

词向量(Word Embedding),是来自词汇表的单词或短语被映射到实数的向量。 从概念上讲,它涉及从每个单词一维的空间到具有更低维度的连续向量空间的数学嵌入。举个例子,比如把"food" 转为词向量 [0.0255, 0.0254, 0.0249, ……. , 0.0282]

2.2.2 Word2Vec

Word2vec 是 Word Embedding 的方法之一。他是 2013 年由谷歌的 Mikolov 提出了一套新的词嵌入方法。本质上,word2vec属于一种DNN深度神经网络,主要在NLP领域里,学习词语的泛化向量表示,做更好的语义理解

Word2Vec通过Embedding层将one-hot Encoder转化为低维度的连续值(稠密向量),并且其中意思相近的词将被映射到向量空间中相近的位置。

Word2Vec有两类训练法:CBOW和Skip-Gram

而如果是拿一个词语的上下文语境作为输入,来预测这个词语本身,则是「CBOW 模型」 论文:《Efficient Estimation of Word Representations in Vector Space》

如果是用一个词语作为输入,来预测它周围的上下文,那这个模型叫做「Skip-gram 模型」 论文:《Distributed Representations of Words and Phrases and their Compositionality》

https://cdn.kesci.com/upload/image/rh5tvey2o5.jpg?imageView2/0/w/500/h/500#id=eB5yi&originHeight=300&originWidth=500&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=

该训练营仅讲解Skip-Gram的模型:

https://cdn.kesci.com/upload/image/rh5vcc5pjy.png?imageView2/0/w/960/h/960#id=ddLsC&originHeight=529&originWidth=886&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=

假如有一个句子“The quick brown fox jumps over the lazy dog” ,首先选句子中间的一个词作为输入词,例如选取“fox”作为input word;有了input word以后,再定义一个叫做skip_window的参数,它代表着从当前输入词的左边和右边选取词的数量。最终获得滑动窗口中的词(包括input word在内)就是 [‘quick’, ’ brown’,‘fox’,’ jumps’, ’ over’],即选取左input word左侧2个词和右侧2个词进入窗口。另一个参数叫num_skips,它代表着从整个窗口中选取多少个不同的词作为output word,如图所示。

Skip-Gram模型的input word 和output word都是one-hot编码向量,最终模型的输出是一个概率分布。这个概率代表着词典中的每个词是output word的可能性。第二步中在设置skip_window和num_skips都为2的情况下获得了四组训练数据。假如先拿一组数据 (‘fox’, ‘jumps’) 来训练神经网络,那么模型通过学习这个训练样本,会告诉词汇表中每个单词是“jumps”的概率大小。模型输出的概率代表着词典中每个词有多大可能性跟input word同时出现。

/images/NLP.png