NLP(二)

本节内容:

  • 分词

  • 拼写纠错

  • 停用词过滤

  • 词的标准化

智能客服

根据问题相似度去回答

  • 正则 适合没数据的时候使用
  • 计算字符串的相似度

基于搜索的问答系统

知识库中存储着问题和答案,根据相似度搜索最相似的问题,返回其答案

输入句子

分词

预处理

  • 拼写纠错
  • Lemmatisation(词性还原)/ Stemming(词干提取)
  • 停用词过滤
  • 同义词

文本表示

文本转为向量形式

  • boolean vector
  • count vector
  • tf-idf
  • word2vec
  • seq2seq

计算相似度

根据相似度排序

NLP项目一般流程:

 一、分词

常用分词工具:

  • Jieba分词https://github.com/fxsjy/jieba
  • SnowNLP https://github.com/isnowfy/snownlp
  • LTP http://www.ltp-cloud.com/
  • HanNLP https://github.com/hankcs/HanLP/
  • ...

1.1 最大匹配

前向最大匹配(forward-max matching)

例子:我们经常有意见分歧
词典:[“我们”, “经常”, “有”, “有意见”,“意见”,“分歧”]

假设max-len设为5

第一轮,选定前五个字

[我们经常有],词典中没有单词匹配,去掉最后一个字

[我们经常],词典中没有单词匹配,去掉最后一个字

[我们经],词典中没有单词匹配,去掉最后一个字

[我们],词典中有单词匹配

第二轮,选定我们后面的五个字

[经常有意见],词典中没有单词匹配,去掉最后一个字

[经常有意],词典中没有单词匹配,去掉最后一个字

[经常有],词典中没有单词匹配,去掉最后一个字

[经常],词典中有单词匹配

第三轮,选定经常后面的五个字

[有意见分歧],词典中没有单词匹配,去掉最后一个字

[有意见分],词典中没有单词匹配,去掉最后一个字

[有意见],词典中有单词匹配

第四轮,选定有意见后面的五个字

[分歧],词典有单词匹配

分词结果:我们 经常 有意见 分歧

后向最大匹配

例子:我们经常有意见分歧
词典:[“我们”, “经常”, “有”, “有意见”,“意见”,“分歧”]

假设max-len设为5

第一轮,选定最后5个子

[常有意见分歧],词典中没有单词匹配,去掉最前一个字

[有意见分歧],词典中没有单词匹配,去掉最前一个字

[意见分歧],词典中没有单词匹配,去掉最前一个字

[见分歧],词典中没有单词匹配,去掉最前一个字

[分歧],词典中有单词匹配

第二轮,选定分歧前5个字

[经常有意见],词典中没有单词匹配,去掉最前一个字

[常有意见],词典中没有单词匹配,去掉最前一个字

[有意见],词典中有单词匹配

第三轮,选定有意见前5个字

[我们经常],词典中没有单词匹配,去掉最前一个字

[们经常],词典中没有单词匹配,去掉最前一个字

[经常],词典中有单词匹配

第四轮,选定经常前5个字

[我们],词典中有单词匹配

分词结果:我们 经常 有意见 分歧

后向前向最大匹配都是贪心算法,缺点:细分,可能有更好的,局部最优,效率低,没考虑语义

1.2 考虑语义

选择其中最好的要根据工具选择

最经典的工具是语言模型(Language Model)

s1 = 经常 有 意见 分歧

s2 = 经常 有意见 分歧

语言模型可以计算概率 P(s1)、P(s2)

P(经常,有,意见,分歧) = P(经常)P(有)P(意见)P(分歧)

P(经常,有意见,分歧) = P(经常)P(有意见)P(分歧)

概率是如何得到呢?

比如,有一本大部头的书,统计每个单词出现的次数,单词出现次数/所有词的数量 就是这个单词的概率了。

某个单词的概率P往往非常小,多个单词的概率相乘容易引发溢出错误(underflow)

于是,我们往往加log,比如计算logP(经常,有,意见,分歧)=logP(经常) + logP(有) + logP(意见) + logP(分歧),转为了加法

log可以保证P(s1)>P(s2)时,logP(s1)>logP(s2)

缺点:复杂度非常高,因为要生成所有可能的分割组合。

1.3 维特比算法

上面的方法分两步:step1,生成所有可能分割;step2,选择最好的。

两步合并能不能降低复杂度呢?

蓝直线,代表一个字,上面的数字是其概率,假设词典没有出现的单词其概率为20

蓝曲线箭头,将词典中出现的词的字连起来,将词的概率标注在线的上面,比如经常的概率为2.3 

于是所有蓝线可以进行组合从1到8,每个组合都是一个分词结果,找到概率和最小的路径即可

假设

f(8):从节点1到8的最短路径的值

f(7):从节点1到7的最短路径的值

f(6):从节点1到6的最短路径的值

...

先看f(8),只用一步有几条路到第8个节点呢

5->8,6->8,7->8

因此,f(8)就是下面的最小值

那么f(7):f(6) + 2.3

f(6):

f(5):f(4) + 3

...

因此,我们可以计算f(1)、f(2)、f(3)...f(8)

 上面是最短路径,下面是最短路径对应的节点,比如f(8)最短路径值是6.2,对应的上一个节点是6,节点6最短路径值是4.6,对应节点是3,节点3最短路径值是2.3,对应节点是1

因此,1368是最佳组合,分词是: 经常 有意见 分歧

维护数组

二、错误拼写纠正(Spell Correction)

 最经典方法计算编辑距离

一般有三个操作:insert、delete、replace,成本都是1

therr变为there,需要把r替换为1,成本为1

therr变为their,需要把r替换为i,成本为1

therr变为thesis,需要r替换为s,增加一个i,r替换为s,成本为3

therr变为theirs,需要r替换为i,增加一个s,成本为2

therr变为the,需要删除两个r,成本为2

因此,there和their是最佳选择,此时需要根据上下文、词频判断,返回最佳的一个单词。

循环词典,找出最佳编辑距离的词,复杂度非常高是O(V),其中V是词典中所有的单词。

dp算法的核心是问题拆分

dp算法练习题:https://people.cs.clemson.edu/~bcdean/dp_practice/

有什么方法降低时间复杂度呢?

主动生成想要的字符串,选择编辑距离1和2,是因为这两种情况可以覆盖绝大多数场景

通过独立使用add、replace、delete三种操作生成编辑为1的字符串组合

生成编辑为1的字符串后,再重复上面操作,生成编辑距离为2的字符串

生成大量字符串后,如何选择最合适的字符串呢?

 比如,正确apple

用户1:app

用户2:appl

用户3:appl

用户4:app

用户5:appla

用户6:appl

P(appl|apple)=3/6=50%

P(app|apple)=2/6=33.3%

P(s|c):c是正确的单词,对于一个正确的字符串,有百分之多少的人写成了s的形式?

P(c):c在整个文档中出现的概率,倾向于选最可能出现的单词

三、词过虑

通常把停用词、出现频率很低的词汇过滤掉。这其实类似于特征筛选的过程。

过滤停用词

英文里的the,an,their等,但是,也需要考虑自己的应用场景。

过滤低频词

出现频率特别低的词汇对分析作用不大,所以一般也会去掉。把停用词、出现频率低的词过滤之后,既可以得到一个词典库。

四、词的标准化

常用的技术

  • Stemming
  • Lemmatization

词形还原(lemmatization),是把一个任何形式的语言词汇还原为一般形式(能表达完整语义),而词干提取(stemming)是抽取词的词干或词根形式(不一定能够表达完整语义)。

Stemming

不保证还原为有效的单词,比如

deny,denied,denying 可以还原为 deni

fly,flies 可以还原为 fli 

著名算法 PorterStemmer

https://tartarus.org/martin/PorterStemmer/java.txt

下面介绍了规则,这些规则是基于语言学家的经验

 

原文地址:https://www.cnblogs.com/aidata/p/12337844.html