文章目录
处理文本数据
表示数据属性的两种类型的特征:连续特征和分类特征,前者用于描述数量,后者是固定列表中的元素。在许多应用中还可以见到第三种类型的特征:文本。文本数据通常被表示为由字符组成的字符串。在上面给出的所有例子中,文本数据的长度可能都不相同。这个特征显然与前面讨论过的数值特征由很大的不同,我们需要先处理数据然后才能对其应用机器学习算法。
用字符串表示的数据类型
文本通常只是数据集中的字符串,并非所有字符串特征都应该被当作文本来处理。
可能遇到的四种类型的字符串数据:
分类数据,可以在语义上映射为类别的自由字符串,结构化字符串数据,文本数据。
分类数据(categorical data)是来自固定列表的数据。可以在语义上映射为类别的自由字符串:折中字符串预处理过程可能需要大量的人力,并且不容易自动化。文本数据(text data),由短语或句子组成。在文本分析的语境中,数据集通常被称为语料库,每个由单个文本表示数据点被称为文档。这些术语来自于信息检索和自然语言处理的社区。
电影评论的情感分析
电影评论数据集:4 这个数据集包含评论文本,还有一个标签,用于表示该评论是“正面(positive)还是“负面的”(negative)。为了简化建模,这些评论打分被归纳为一个二分类数据集,评分大于7的被标记为正面的,评论小于4的被标记为负面的,中性评论没有包含在数据集中。我们不讨论这种方法是否是一种好的数据表示,只是使用这个数据。
将数据解压之后,数据集包含两个独立文件夹中的文本文件,一个是训练数据一个是测试数据。每个文件夹又都包含两个子文件夹,一个叫做pos,一个叫做neg。pos文件夹包含所有正面的评论,每条评论都是一个单独的文本文件,neg文件夹与之类似。scikit-learn中有一个辅助韩叔叔可以加载这种文件夹结构保存的文件,其中每个子文件夹对应于一个标签,这个函数叫做load_files。
将文本数据表示为词袋
用于机器学习的文本表示有一种最简单的方法,也是最有效的且常用的方法,使用词袋表示。使用这种表示方式时,我们舍弃了输入文本中的大部分结构,如章节、段落、句子和格式,只计算语料库中每个单词在每个文本中出现的频次。
对于文档语料库,计算词袋表示包括以下三个步骤:
1.分词:将每个文档划分为出现在其中的单词,比如:按空格和标点划分。
2.构建词表:收集一个词表。里面包含出现在任意文档中的所有词并对它们进行编号(按字母顺序进行排序)。
3.编码:对于每个文档,计算词表中每个单词在该文档中出现的频次。
输出时包含每个文档中单词计数的一个向量。对于词表中的每个单词,我们都有它在每个文档中的出现词素和。也就是说整个数据集中的每个唯一单词都对应于这种数值表示的一个特征。请注意,原始字符串中的单词顺序与词袋特征表示完全无关。
将词袋应用于玩具数据集
词袋表示是在 CountVectorizer 中实现的,它是一个变换器(transformer)。我们首先将它应用于一个包含两个样本的玩具数据集,来看一下它的工作原理。
# 玩具数据集
bards_words =["The fool doth think he is wise,",
"but the wise man knows himself to be a fool"]
# 导入 CountVectorizer 并将其实例化,然后对玩具数据进行拟合
from sklearn.feature_extraction.text import CountVectorizer
vect = CountVectorizer()
vect.fit(bards_words)
# 拟合 CountVectorizer 包括训练数据的分词与词表的构建,我们可以通过 vocabulary_ 属性来访问词表
print("Vocabulary size: {}".format(len(vect.vocabulary_)))
print("Vocabulary content:\n {}".format(vect.vocabulary_))
# 可以调用 transform 方法来创建训练数据的词袋表示
bag_of_words = vect.transform(bards_words)
print("bag_of_words: {}".format(repr(bag_of_words)))
# 要想查看稀疏矩阵的实际内容,可以使用 toarray 方法将其转换为“密集的”NumPy 数组
print("Dense representation of bag_of_words:\n{}".format(bag_of_words.toarray()))
运行结果:
Vocabulary size: 13
Vocabulary content:
{
'the': 9, 'fool': 3, 'doth': 2, 'think': 10, 'he': 4, 'is': 6, 'wise': 12, 'but': 1, 'man': 8, 'knows': 7, 'himself': 5, 'to': 11, 'be': 0}
bag_of_words: <2x13 sparse matrix of type '<class 'numpy.int64'>'
with 16 stored elements in Compressed Sparse Row format>
Dense representation of bag_of_words:
[[0 0 1 1 1 0 1 0 0 1 1 0 1]
[1 1 0 1 0 1 0 1 1 1 0 1 1]]
词袋表示保存在一个SciPy稀疏矩阵中,这种数据格式只保存非零元素。这个矩阵的形状是2*13,每行对应于两个数据点之一,每个特征对应于此表种的一个单词,这里使用稀疏矩阵,是因为大多数文档都只包含词表中的一个单词。也就是说特征数组中的大部分元素都为0。
每个单词的计数都是 0 或 1。bards_words 中的两个字符串都没有包含相同的单词。第一个字符串(“The fool doth think he is wise,”)被表示为第一行,对于词表中的第一个单词 “be”,出现 0 次。对于词表中的第二个单词 “but”,出现 0 次。对于词表中的第三个单词 “doth”,出现 1 次,以此类推。通过观察这两行可以看出,第 4 个单词 “fool”、第 10 个单词 “the” 与第 13 个单词 “wise” 同时出现在两个字符串中。
将词袋应用于电影评论
# 应用于电影评论数据集
vect = CountVectorizer().fit(text_train)
X_train = vect.transform(text_train)
print("X_train:\n{}".format(repr(X_train)))
'''
访问词表的另一种方法是使用向量器(vectorizer)的 get_feature_name 方法,
它将返回一个列表,每个元素对应于一个特征
'''
feature_names = vect.get_feature_names()
print("Number of features: {}".format(len(feature_names)))
print("First 20 features:\n{}".format(feature_names[:20]))
print("Features 20010 to 20030:\n{}".format(feature_names[20010: