1. 分词的概念(分词的正向最大、逆向最大、双向最大匹配法)
最大匹配法:最大匹配是指以词典为依据,取词典中最长单词为第一个次取字数量的扫描串,在词典中进行扫描(为提升扫 描效率,还可以跟据字数多少设计多个字典,然后根据字数分别从不同字典中进行扫描。下面以“我们在野生动物园玩”详细说明 一 下这几种匹配方法:
(1)正向最大匹配法
正向即从前往后取词,从7->1,每次减一个字,直到词典命中或剩下1个单字。
第1次:“我们在野生动物”,扫描7字词典,无
第2次:“我们在野生动”,扫描6字词典,无
。。。。
第6次:“我们”,扫描2字词典,有
扫描中止,输出第1个词为“我们”,去除第1个词后开始第2轮扫描,即:
第2轮扫描:
第1次:“在野生动物园玩”,扫描7字词典,无
第2次:“在野生动物园”,扫描6字词典,无
。。。。
第6次:“在野”,扫描2字词典,有
扫描中止,输出第2个词为“在野”,去除第2个词后开始第3轮扫描,即:
第3轮扫描:
第1次:“生动物园玩”,扫描5字词典,无
第2次:“生动物园”,扫描4字词典,无
第3次:“生动物”,扫描3字词典,无
第4次:“生动”,扫描2字词典,有
扫描中止,输出第3个词为“生动”,第4轮扫描,即:
第4轮扫描:
第1次:“物园玩”,扫描3字词典,无
第2次:“物园”,扫描2字词典,无
第3次:“物”,扫描1字词典,无
扫描中止,输出第4个词为“物”,非字典词数加1,开始第5轮扫描,即:
第5轮扫描:
第1次:“园玩”,扫描2字词典,无
第2次:“园”,扫描1字词典,有
扫描中止,输出第5个词为“园”,单字字典词数加1,开始第6轮扫描,即:
第6轮扫描:
第1次:“玩”,扫描1字字典词,有
扫描中止,输出第6个词为“玩”,单字字典词数加1,整体扫描结束。
正向最大匹配法,最终切分结果为:“我们/在野/生动/物/园/玩”,其中,单字字典词为2,非词典词为1。
(2)逆向最大匹配法
逆向即从后往前取词,其他逻辑和正向相同。即:
第1轮扫描:“在野生动物园玩”
第1次:“在野生动物园玩”,扫描7字词典,无
第2次:“野生动物园玩”,扫描6字词典,无
。。。。
第7次:“玩”,扫描1字词典,有
扫描中止,输出“玩”,单字字典词加1,开始第2轮扫描
第2轮扫描:“们在野生动物园”
第1次:“们在野生动物园”,扫描7字词典,无
第2次:“在野生动物园”,扫描6字词典,无
第3次:“野生动物园”,扫描5字词典,有
扫描中止,输出“野生动物园”,开始第3轮扫描
第3轮扫描:“我们在”
第1次:“我们在”,扫描3字词典,无
第2次:“们在”,扫描2字词典,无
第3次:“在”,扫描1字词典,有
扫描中止,输出“在”,单字字典词加1,开始第4轮扫描
第4轮扫描:“我们”
第1次:“我们”,扫描2字词典,有
扫描中止,输出“我们”,整体扫描结束。
逆向最大匹配法,最终切分结果为:“我们/在/野生动物园/玩”,其中,单字字典词为2,非词典词为0
(3)双向最大匹配法
正向最大匹配法和逆向最大匹配法,都有其局限性,我举得例子是正向最大匹配法局限性的例子,逆向也同样存在(如:长春药店,逆向切分为“长/春药店”),因此有人又提出了双向最大匹配法,双向最大匹配法。即,两种算法都切一遍,然后根据大颗粒度词越多越好,非词典词和单字词越少越好的原则,选取其中一种分词结果输出。
如:“我们在野生动物园玩”
正向最大匹配法,最终切分结果为:“我们/在野/生动/物/园/玩”,其中,两字词3个,单字字典词为2,非词典词为1。
逆向最大匹配法,最终切分结果为:“我们/在/野生动物园/玩”,其中,五字词1个,两字词1个,单字字典词为2,非词典词为0。
非字典词:正向(1)>逆向(0)(越少越好)
单字字典词:正向(2)=逆向(2)(越少越好)
总词数:正向(6)>逆向(4)(越少越好)
因此最终输出为逆向结果
2.词、字符频率统计(评论统计可以使用Python中的collections.Counter模块,也可以自己寻找其他好用的库)
用Python实现函数count_words(),该函数输入字符串s和数字n,返回s中n个出现频率最高的单词。返回值是一个元组列表,包含出现次数最高的n个单词及其次数,即[(<单词1>, <次数1>), (<单词2>, <次数2>), ... ],按出现次数降序排列。
假设所有输入都是小写形式,并且不含标点符号或其他字符(只包含字母和单个空格)。如果出现次数相同,则按字母顺序排列。那么可以有以下程序:
结果:
3. 文本数据向量化
我所知道的三种文本数据数值向量化的方法
(1)CounterVectorizer—one hot矩阵
在学习概率论的时候,我们不管将大自然中的什么东西变成我们所能够研究的东西,首先都是先统计构成样本空间中的所有元素得到样本元素的频率表示,简单来讲就是计数而已。现在我们将其推广到文本数值化上面来就是:使用split函数将用空格连接的文本数据分开,每个文本我们都会得到一个列表,构成词典,在第一个样本中,统计其中的包含于字典的每个元素出现的次数,这就是CounterVectorizer的文本向量化的原理。
设样本容量为n,第i个样本中含有m_i个元素。
所有元素构成的字典(是字典的形式,但是这里我们使用列表来存储)为:dict = {elem1,elem2,…elem_N} 设字典中的元素个数为N,注:字典中的所有元素是不重复的。
from sklearn.feature_extraction.text import CountVectorizer
corpus = [
'This is the first document.',
'This document is the second document.',
'And this is the third one.',
'Is this the first document?',
]
vectorizer = CountVectorizer()
X = vectorizer.fit_transform(corpus)
print(vectorizer.get_feature_names())
# ['and', 'document', 'first', 'is', 'one', 'second', 'the', 'third', 'this']
print(X.toarray()) # doctest: +NORMALIZE_WHITESPACE
# [[0 1 1 1 0 0 1 0 1]
# [0 2 0 1 0 1 1 0 1]
# [1 0 0 1 1 0 1 1 1]
# [0 1 1 1 0 0 1 0 1]]
傻瓜解释:
字典的长度就是每个样本的维度,所有样本的维度一致。样本的每个维度都代表着相应字典中的元素在每一个具体的样本中出现的频率。对应到具体的例子,This is the first document. 可以看到字典的顺序是[‘and’, ‘document’, ‘first’, ‘is’, ‘one’, ‘second’, ‘the’, ‘third’, ‘this’],将其一一对应起来,and不出现,频率是0,document出现,频率是1…this出现,频率是1。这样一个文本数据就可以转变成数值向量啦。这样一一对应的关系我们可以简单的理解为数学上面的映射,将字典中的元素映射到N+正整数域上面来。
(2)TfidfVectorizer—one hot 矩阵的变换
与2不同,tf-idf主要使用的是逆文档频率,具体计算可以自己百度,csdn看别人的解释。简单来讲,我们认为在一个文档中出
现次数越小的越能够代表一个文档,相反,一个元素在文档中频繁存在的文本的文本所拥有的权重就越小,越不能够代表一个文档。
from sklearn.feature_extraction.text import TfidfVectorizer
corpus = [
'This is the first document.',
'This document is the second document.',
'And this is the third one.',
'Is this the first document?',
]
vectorizer = TfidfVectorizer()
X = vectorizer.fit_transform(corpus) # 拟合并且转化文本
print(vectorizer.get_feature_names()) # 输出特征字典
# ['and', 'document', 'first', 'is', 'one', 'second', 'the', 'third', 'this']
print(X.shape) # 输出文本的维数,4行9列,每个文本的的维度为9,与上面的特征数量的长度相同
# (4, 9)
print(X.toarray()) # 将文本数据向量化--是9维数据
# [[0. 0.46979139 0.58028582 0.38408524 0. 0.
# 0.38408524 0. 0.38408524]
# [0. 0.6876236 0. 0.28108867 0. 0.53864762
# 0.28108867 0. 0.28108867]
# [0.51184851 0. 0. 0.26710379 0.51184851 0.
# 0.26710379 0.51184851 0.26710379]
# [0. 0.46979139 0.58028582 0.38408524 0. 0.
# 0.38408524 0. 0.38408524]]
参考:
文本挖掘预处理指TF-IDF https://www.cnblogs.com/pinard/p/6693230.html
scikit-learn:CountVectorizer提取tf都做了什么 https://blog.csdn.net/mmc2015/article/details/46866537
python 利用sklearn自带的模块 快速简单实现文章的 tfidf向量空间的表示 https://blog.csdn.net/u012448083/article/details/50955530
sklearn文本特征提取 https://blog.csdn.net/du_qi/article/details/51564303
关键词抽取 https://blog.csdn.net/kl28978113/article/details/54580838
(3)Word2Vec
将一个词语的前后单词(2/3/more个单词)连接在一起,当作一个新的元素,存放在字典中,之后用的方法就跟counterVectorizer和tfidfVectorizer差不多了
在我的论文中只是简单地了解了一下,最后内容实在是太多就没有将这个文本数据向量化的方法与前两者进行比较,学有余力的可以对比看看,这么文本向量化会对以后的分类效果产生什么样的影响
具体看的参考资料:
通俗理解word2vec https://www.jianshu.com/p/471d9bfbd72f
word2vec构建中文词向量 https://www.cnblogs.com/Newsteinwell/p/6034747.html
Word2vec基础介绍(四):CBOW和skip-gram模型 https://blog.csdn.net/lyc_yongcai/article/details/73274767
word2vec词向量原理并实践 https://blog.csdn.net/nextthen/article/details/89162333
python进行文本分类,基于word2vec,sklearn-svm对微博垃圾评论分类 https://blog.csdn.net/lrt366/article/details/81107389
(4)三者之间的差异与联系
1和2所使用的字典是一样的
3使用的词典较大一些
不过从本质上来讲,三者都是基于词典,利用频率这个基础将文本数据转化为数值向量。
参考文献: https://blog.csdn.net/qq_35167821/article/details/90549151