自然语言处理 特征提取

1. 基本文本处理技能

1.1 分词

  在语言中,语义的基本单元是单词。在英语句子中已天然就已经分割成单词(空白符和标点符号隔开),而在汉语中字和字紧紧的连在一起。所以我们需要进行分词。分词有很多种算法:基于字符串匹配算法、基于理解的算法、基于统计的算法(如HMM和n-gram)等。下面重点介绍第一种字符串匹配算法。

1.1.1 分词的正向最大匹配

  分词的正向最大匹配本质是基于分治和贪婪两种算法思想。为了便于理解,我们先讲贪婪,后讲分治+贪婪。
  如果不设立最大处理长度,就是贪婪的思想。具体流程是先以整句为单位,就去词典匹配。如果匹配不到,则减少句子的长度进行匹配。如果匹配到,则句子的起点后移,继续递归执行,直到整个句子都被若干个词匹配中(起点超过了句子的长度)。以我爱自然语言处理这句话为例:
1.匹配第一个词
  1.1 我爱自然语言处理,匹配词典,不存在。(下一步少一个字)
  1.2 我爱自然语言处,匹配词典,不存在。(下一步少一个字)
  1.3 我爱自然语言,匹配词典,不存在。(下一步少一个字)
  1.4 我爱自然语,匹配词典,不存在。(下一步少一个字)
  1.5 我爱自然,匹配词典,不存在。(下一步少一个字)
  1.6 我爱自,匹配词典,不存在。(下一步少一个字)
  1.7 我爱,匹配词典,不存在。(下一步少一个字)
  1.8 我,匹配词典,存在。(匹配到第一个词)
2.匹配第二个词
  2.1 爱自然语言处理,匹配词典,不存在。(下一步少一个字)
  2.2 爱自然语言处,匹配词典,不存在。(下一步少一个字)
  2.3 爱自然语言,匹配词典,不存在。(下一步少一个字)
  2.4 爱自然语,匹配词典,不存在。(下一步少一个字)
  2.5 爱自然,匹配词典,不存在。(下一步少一个字)
  2.6 爱自,匹配词典,不存在。(下一步少一个字)
  2.7 爱,匹配词典,存在。(匹配到第二个词)
3.匹配第三个词
  3.1 自然语言处理,匹配词典,不存在。(下一步少一个字)。
  3.2 自然语言处,匹配词典,不存在。(下一步少一个字)。
  3.3 自然语言,匹配词典,存在。(匹配到第三个词)。
4.匹配第四个词
  4.1 处理,匹配词典,存在。(匹配到第四个词)。

  只基于贪婪的方式,在实际工作中是无法使用的,句子一长需要迭代的次数就会非常多。所以需要结合分治的思想进行处理。具体来说就是会设立一个句子分段截取长度,比如qweasdzxc(每个字母代表一个汉字),截取长度为3,则分为qwe、asd、zxc三个子段。接下来分段进行处理,先处理qwe,如果qwe不在词典中,则判断qw在不在词典中,并把e给相邻的子段。假如qw在词典中,则接下来对easd进行上述的运算过程。以我爱自然语言处理为例,截取长度为4。

  1. 将句子分割为我爱自然、语言、处理三个子段。
  2. 处理第一个子段
       我爱自然,匹配词典,不存在。(下一步少一个字,并把少的字加入相邻子段中)
       我爱自,匹配词典,不存在。(下一步少一个字,并把少的字加入相邻子段中)
       我爱,匹配词典,不存在。(下一步少一个字,并把少的字加入相邻子段中)
       我,匹配词典,存在。(匹配到第一个词)
  3. 处理第二个子段
       爱自然语言,匹配词典,不存在。(下一步少一个字,并把少的字加入相邻子段中)
       爱自然语,匹配词典,不存在。(下一步少一个字,并把少的字加入相邻子段中)
       爱自然,匹配词典,不存在。(下一步少一个字,并把少的字加入相邻子段中)
       爱自,匹配词典,不存在。(下一步少一个字,并把少的字加入相邻子段中)
       爱,匹配词典,存在。(匹配到第二个词)
  4. 处理第三个子段
       自然语言,匹配词典,存在。(匹配到第三个词)
  5. 处理第四个子段
       处理,匹配词典,存在。(匹配到第四个词)

1.1.2 分词的反向最大匹配

  反向最大匹配是从后向前选取最大长度的串,从选取串开始向后匹配字典词,而删减的也便是左边的字符。还是以我爱自然语言处理为例,截取长度为3。为了让大家理解思想(避免惯性思维),特意展示从最后的子段到第一个子段进行处理。

  1. 将句子分割为我爱自、然语言、处理三个子段。
  2. 处理最后一个子段
       处理,匹配词典,存在。(匹配到第一个词)
  3. 处理倒数第二个子段
       然语言,匹配词典,不存在。(下一步少一个字,并把少的字加入相邻子段中)
       语言,匹配词典,存在。(匹配到第二个词)
  4. 处理倒数第三个子段
       我爱自然,匹配词典,不存在。(下一步少一个字,并把少的字加入相邻子段中)
       爱自然,匹配词典,不存在。(下一步少一个字,并把少的字加入相邻子段中)
       自然,匹配词典,存在。(匹配到第三个词)
  5. 处理第倒数第四个子段
       我爱,匹配词典,不存在。(下一步少一个字,并把少的字加入相邻子段中)
       爱,匹配词典,不存在。(匹配到第四个词)
  6. 处理第五个子段
       我,匹配词典,存在。(匹配到第五个词)

可以看到正向最大匹配和反向匹配的结果可能是不同的,而且会受到预设分段长度的影响。

1.1.3 分词的双向最大匹配

   双向就是结合正向最大和反向最大的结果,对两个结果进行比较,从而决定正确的分词方式,当前向和逆向分词数量不相等的时候,选择数量较少的那个分词结果。如果分词数量相同,则依次比较分词结果,相应位置如果分词相同,则选取为最后的结果中,如果相应位置分词结果不一样则选取字符较少的那个最为分词结果。

1.2 字符和词频统计

字符统计代码如下所示:

text = '我爱自然语言处理。自然语言处理是一个很有意思的研究领域'
from collections import Counter
c = Counter(text)
print(c)

结果如下所示:
Counter({‘言’: 2, ‘自’: 2, ‘然’: 2, ‘。’: 2, ‘处’: 2, ‘理’: 2, ‘语’: 2, ‘研’: 1, ‘很’: 1, ‘域’: 1, ‘爱’: 1, ‘思’: 1, ‘一’: 1, ‘领’: 1, ‘意’: 1, ‘究’: 1, ‘我’: 1, ‘个’: 1, ‘是’: 1, ‘有’: 1, ‘的’: 1})

词频统计相比字符统计而言,只是多了一步分词的过程,具体代码如下所示:

import jieba 
seg_list = list(jieba.cut('我爱自然语言处理。自然语言处理是一个很有意思的研究领域。', cut_all=False)) 
c = Counter(seg_list )
print(c)

结果如下所示:
Counter({’。’: 2, ‘自然语言’: 2, ‘处理’: 2, ‘很’: 1, ‘爱’: 1, ‘研究’: 1, ‘我’: 1, ‘领域’: 1, ‘有意思’: 1, ‘是’: 1, ‘一个’: 1, ‘的’: 1})

结果发现,里面包含了一些标点符号和停用词。如果不需要停用词,可下载停用词词典,进行过滤即可。

2. 语言模型

  n-gram是一种基于统计语言模型的算法。它的思想是将文本里面的内容按照指定的单元进行大小为N的滑动窗口操作,每次取得长度为N的序列,直到滑窗结束。模型本质上是一种近似,即第N个词只与前N-1个词相关。如果指定的单元是字,则可用来做分词任务。如果指定的单元是词,则可以计算出整个句子的概率。下面所述的语言模型,都指定单元为词,而不是字。

2.1 语言模型中unigram、bigram、trigram的概念

  • unigram指的是单个词为一个单元。每个词之间没有关联关系。
  • bigram指的是两个词为一个单元。当前词只和上一个词有关系。
  • trigram指的是三个词为一个单元。当前词只和前两个词有关系。
    sklearn CountVectorizer

2.2 unigram、bigram频率统计

  unigram等同于词频统计,而bigram频率统计只需要取n-gram,然后传入到Counter()中即可。

3. 文本矩阵化

3.1 分词

分词工具采用结巴中文分词,涉及到的算法:

  1. 基于Trie树结构实现高效的词图扫描,生成句子中汉字所有可能成词情况所构成的有向无环图(DAG);
  2. 采用了动态规划查找最大概率路径, 找出基于词频的最大切分组合;
  3. 对于未登录词,采用了基于汉字成词能力的HMM模型,使用了Viterbi算法。

结巴中文分词支持的三种分词模式包括:

  1. 精确模式:试图将句子最精确地切开,适合文本分析;
  2. 全模式:把句子中所有的可以成词的词语都扫描出来, 速度非常快,但是不能解决歧义问题;
  3. 搜索引擎模式:在精确模式的基础上,对长词再次切分,提高召回率,适合用于搜索引擎分词。

具体代码如下所示:

import jieba

# 全模式
text = "我爱深度学习的自然语言处理"
seg_list = jieba.cut(text, cut_all=True)
print(u"[全模式]: ", "/ ".join(seg_list))

# 精确模式
seg_list = jieba.cut(text, cut_all=False)
print(u"[精确模式]: ", "/ ".join(seg_list))

# 默认是精确模式
seg_list = jieba.cut(text)
print(u"[默认模式]: ", "/ ".join(seg_list))

# 搜索引擎模式
seg_list = jieba.cut_for_search(text)
print(u"[搜索引擎模式]: ", "/ ".join(seg_list))

结果如下所示:
[全模式]: 我/ 爱/ 深度/ 学习/ 的/ 自然/ 自然语言/ 语言/ 处理
[精确模式]: 我/ 爱/ 深度/ 学习/ 的/ 自然语言/ 处理
[默认模式]: 我/ 爱/ 深度/ 学习/ 的/ 自然语言/ 处理
[搜索引擎模式]: 我/ 爱/ 深度/ 学习/ 的/ 自然/ 语言/ 自然语言/ 处理

注:如果是Python3版本,jieba返回的是一个生成器,需要转换成列表。
seg_list = list(seg_list)

3.2 去停用词

不同互联网公司有不同的停用词表,如百度等。这里提供一份百度的停用词表。https://download.csdn.net/download/herosunly/11102927

with open(r'E:\BaiduNetdiskDownload\ml6_0.Teacher\Data\baidu_stopwords.txt', 'r', encoding = 'utf-8') as f:
    content = f.read()
    stop_words = content.split('\n')

3.3 向量化

from sklearn.feature_extraction.text import CountVectorizer

count_vectorizer = CountVectorizer(stop_words=stop_words) #上一步的停用词
count_vectorizer.fit(seg_list)
vec = count_vectorizer.transform(seg_list).toarray()
vocab_list = count_vectorizer.get_feature_names() #得到字典

你可能感兴趣的:(自然语言处理 特征提取)