词袋模型(BOW, bag of words)
词集模型:单词构成的集合,每个单词只出现一次。
词袋模型:把每一个单词都进行统计,同时计算每个单词出现的次数。
在train_x中,总共有6篇文档,每一行代表一个样本即一篇文档。我们的目标是将train_x转化为可训练矩阵,即生成每个样本的词向量。可以对train_x分别建立词集模型,词袋模型来解决。
train_x = [["my", "dog", "has", "flea", "problems", "help", "please"],
["maybe", "not", "take", "him", "to", "dog", "park", "stupid"],
["my", "dalmation", "is", "so", "cute", "I", "love", "him"],
["stop", "posting", "stupid", "worthless", "garbage"],
["him", "licks", "ate", "my", "steak", "how", "to", "stop", "him"],
["quit", "buying", "worthless", "dog", "food", "stupid"]]
1. 词集模型
算法步骤:
1)整合所有的单词到一个集合中,假设最终生成的集合长度为wordSetLen = 31。
2)假设文档/样本数为sampleCnt = 6,则建立一个sampleCnt * wordSetLen = 6 * 31的矩阵,这个矩阵被填入有效值之后,就是最终的可训练矩阵m。
3)遍历矩阵m,填入0,1有效值。0代表当前列的单词没有出现在当前行的样本/文档中,1代表当前列的单词出现在当前行的样本/文档中。
4)最终生成一个6 * 31的可训练矩阵。
2. 词袋模型
词袋模型中,训练矩阵不仅仅只出现0,1还会出现其他数字,这些数字代表的是当前样本中单词出现的次数。
- # -*- coding: utf-8 -*-
- import numpy as np
- def load_data():
- """ 1. 导入train_x, train_y """
- train_x = [["my", "dog", "has", "flea", "problems", "help", "please"],
- ["maybe", "not", "take", "him", "to", "dog", "park", "stupid"],
- ["my", "dalmation", "is", "so", "cute", "I", "love", "him"],
- ["stop", "posting", "stupid", "worthless", "garbage"],
- ["him", "licks", "ate", "my", "steak", "how", "to", "stop", "him"],
- ["quit", "buying", "worthless", "dog", "food", "stupid"]]
- label = [0, 1, 0, 1, 0, 1]
- return train_x, label
- def setOfWord(train_x):
- """ 2. 所有单词不重复的汇总到一个列表
- train_x: 文档合集, 一个样本构成一个文档
- wordSet: 所有单词生成的集合的列表
- """
- wordList = []
- length = len(train_x)
- for sample in range(length):
- wordList.extend(train_x[sample])
- wordSet = list(set(wordList))
- return wordSet
- def create_wordVec(sample, wordSet, mode="wordSet"):
- """ 3. 将一个样本生成一个词向量 """
- length = len(wordSet)
- wordVec = [0] * length
- if mode == "wordSet":
- for i in range(length):
- if wordSet[i] in sample:
- wordVec[i] = 1
- elif mode == "wordBag":
- for i in range(length):
- for j in range(len(sample)):
- if sample[j] == wordSet[i]:
- wordVec[i] += 1
- else:
- raise(Exception("The mode must be wordSet or wordBag."))
- return wordVec
- def main(mode="wordSet"):
- train_x, label = load_data()
- wordSet = setOfWord(train_x)
- sampleCnt = len(train_x)
- train_matrix = []
- for i in range(sampleCnt):
- train_matrix.append(create_wordVec(train_x[i], wordSet, "wordBag"))
- return train_matrix
- if __name__ == "__main__":
- train_x, label = load_data()
- wordSet = setOfWord(train_x)
- train_matrix = main("wordSet")
词袋模型的提出是为了解决文档分类,主要应用在 NLP(Natural Language Process), IR(Information Retrival),CV(Computer Vision)等领域。
以计算机视觉领域为例进行讲解。
模型假设
一个文本或文档可以看做是一袋子单词,不考虑其语法和词序关系,每个词都是独立的。(这里要尤其注意,BoW不考虑词序的时间和空间上的信息)
示例
这样两个文本
John likes to watch movies. Mary likes too.
John also likes to watch football games.
对以上构造词典:
{
"John": 1,
"likes": 2,
"to": 3,
"watch": 4,
"movies": 5,
"also": 6,
"football": 7,
"games": 8,
"Mary": 9,
"too": 10
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
则之前的两个文本可以表示为
[1, 2, 1, 1, 1, 0, 0, 0, 1, 1]
[1, 1, 1, 1, 0, 1, 1, 1, 0, 0]
上面这种向量的表示方法,就是词袋模型了,其中每个分量表示该词在文本中出现的次数,可以看到词序信息已经丢失,每个文档看做一系列不相关的词的集合。
应用举例
在计算机视觉领域,图片分类是很典型的应用,在视觉分类系统中,由于图像的特征并非像文档中能够直接对单词进行赋值,一般直接对图像的像素进行特征表示,得到特征向量。因此需要四人步骤:特征检测-特征表示-词汇表生成-分类器设计,一般的特征表示大都采用局部不变特征表示方法(SIFT特征)进行特征表示。
例如,一个图片可以由若干个local features(或者叫做patch)表示,用K-means方法把相似的patch聚类,每个聚类中心叫做 codeword,类比于 NLP 中的 word;同样的,图片就类比文本文档。用每个图片得到的 codeword 构建词典,叫做 codebook,得到真正无冗余的特征表示-视觉词袋,类比 NLP 中的词典。随后结合视觉词袋和词频概念得到每个待分类图像的词袋直方图模型对图像进行表示,如下图,之后依次训练分类器,对新输入的图像进行分类。