词袋模型的三部曲:分词(tokenizing),统计修订词特征值(counting)与标准化(normalizing)
词袋模型(Bag of Words,简称BoW),所谓的词袋模型是一种用机器学习算法对文本进行建模时表示文本数据的方法。
词袋模型假设我们不考虑文本中词与词之间的上下文关系,仅仅只考虑所有词的权重。而权重与词在文本中出现的频率有关。
与词袋模型非常类似的一个模型是词集模型(Set of Words,简称SoW),和词袋模型唯一的不同是它仅仅考虑词是否在文本中出现,而不考虑词频。也就是一个词在文本在文本中出现1次和多次特征处理是一样的。在大多数时候,我们使用词袋模型。
词袋模型首先会进行分词,在分词之后,通过统计每个词在文本中出现的次数,我们就可以得到该文本基于词的特征,如果将各个文本样本的这些词与对应的词频放在一起,就是我们常说的向量化。向量化完毕后一般也会使用TF-IDF进行特征的权重修正,再将特征进行标准化。 再进行一些其他的特征工程后,就可以将数据带入机器学习算法进行分类聚类了。
在词袋模型的统计词频这一步,我们会得到该文本中所有词的词频,有了词频,我们就可以用词向量表示这个文本。这里我们举一个例子,例子直接用scikit-learn的CountVectorizer类来完成,这个类可以帮我们完成文本的词频统计与向量化,代码如下:
from sklearn.feature_extraction.text import CountVectorizer
vectorizer=CountVectorizer()
corpus=["I come to China to travel",
"This is a car polupar in China",
"I love tea and Apple ",
"The work is to write some papers in science"]
print vectorizer.fit_transform(corpus)
我们看看对于上面4个文本的处理输出如下:
(0, 16) 1
(0, 3) 1
(0, 15) 2
(0, 4) 1
(1, 5) 1
(1, 9) 1
(1, 2) 1
(1, 6) 1
(1, 14) 1
(1, 3) 1
(2, 1) 1
(2, 0) 1
(2, 12) 1
(2, 7) 1
(3, 10) 1
(3, 8) 1
(3, 11) 1
(3, 18) 1
(3, 17) 1
(3, 13) 1
(3, 5) 1
(3, 6) 1
(3, 15) 1
可以看出4个文本的词频已经统计出,在输出中,左边的括号中的第一个数字是文本的序号,第2个数字是词的序号,注意词的序号是基于所有的文档的。第三个数字就是我们的词频。
我们可以进一步看看每个文本的词向量特征和各个特征代表的词,代码如下:
print vectorizer.fit_transform(corpus).toarray()
print vectorizer.get_feature_names()
输出如下:
[[0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 2 1 0 0]
[0 0 1 1 0 1 1 0 0 1 0 0 0 0 1 0 0 0 0]
[1 1 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0]
[0 0 0 0 0 1 1 0 1 0 1 1 0 1 0 1 0 1 1]]
[u'and', u'apple', u'car', u'china', u'come', u'in', u'is', u'love', u'papers', u'polupar', u'science', u'some', u'tea', u'the', u'this', u'to', u'travel', u'work', u'write']
可以看到我们一共有19个词,所以4个文本都是19维的特征向量。而每一维的向量依次对应了下面的19个词。另外由于词"I"在英文中是停用词,不参加词频的统计。
由于大部分的文本都只会使用词汇表中的很少一部分的词,因此我们的词向量中会有大量的0。也就是说词向量是稀疏的。在实际应用中一般使用稀疏矩阵来存储。