sklearn-文本特征提取
模块
sklearn.feature_extraction
可用于提取符合机器学习算法支持的特征
CountVectorizer
计算机编码文本思路
- 对文本编码,就是让词语与数字对应起来,建立基于给定文本的词典。(fit方法 )
- 再根据词典对所有的文本数据进行转码。(transform方法)
首先给出一个语料(list结构)
corpus = [
'This is the first document.',
'This document is the second document.',
'And this is the third one.',
'Is this the first document?',
]
根据上述思路对文本进行编码
利用给定的语料corpus生成词典,使用方法get_feature_names查看所有特征词
from sklearn.feature_extraction.text import CountVectorizer
vectorize = CountVectorizer()
vectorize.fit(corpus)
vectorize.get_feature_names()
Output:
['and', 'document', 'first', 'is', 'one', 'second', 'the', 'third', 'this']
这里,特征集(get_feature——name)返回的结果,有要注意的事情:
- 所有的单词都是小写
- 单词长度小于两个字母的,会被剔除掉
- 标点符号会剔除掉
- 不重复
- 这个特征集是有顺序的
接下来会按照这个顺序去编码文本数据,这里会出现一个新概念文档-词频矩阵(document-term matrix),英文简写为dtm。我们让机器挖掘文本中的规律时,喂给机器的数据就是 这文档-词频矩阵(document-term matrix)。
dtm = vectorize.transform(corpus)
Output:
<4x9 sparse matrix of type '<class 'numpy.int64'>'
with 21 stored elements in Compressed Sparse Row format>
可以看到这是一个(4*9)的矩阵,为了更直观地展示数据,使用pandas将其表现出来
import pandas as pd
pd.DataFrame(dtm.toarray(), columns = vectorize.get_feature_names())
表中的每一行代表一个文档(即一个sample),列表示特征词,单元格中是该文档对应特征词的词频。
这里需要注意一点,transform的语料中无法编码fit生成的字典中不包含的特征词,这里举一个例子:
new_corpus = ['I think this document is good']
new_dtm = vectorize.transform(new_corpus)
pd.DataFrame(new_dtm.toarray(), columns=vectorize.get_feature_names())
这里只解析了拟合vectorize时所包含的词(corpus中包含的词),[I, think, good]没有显示
我们机器学习所用的数据,一般被分成训练集和测试集。训练集是为了让机器学习数据的规律,测试集是为了验证规律的有效性。训练集本质上代表的是过去及现在已知的数据,测试集本质上代表的是未来的未知数据(现在不存在的数据),我们是用已知的数据预测未来。所以我们只能让fit方法操作于训练集,构建基于过去或已知数据的特征集。
使用停用词
停止词是像“and”、“the”、“him”这样的词,这些词在表示文本内容时被认为是没有信息的,可以删除它们,以避免它们被理解为预测的信号。然而,有时,类似的词对预测很有用,比如在对写作风格或性格进行分类时。
在选择停用词时应当尽可能地谨慎,流行的停止词列表可能包括对某些任务(如计算机)具有高度信息性的词。
同时还应该确保停止单词列表具有与矢量化器中使用的相同的预处理和标记。单词"we’ve"被CountVectorizer
的默认记号分配器分割成"we"和"ve",所以如果"we’ve"在停止词列表中,但"ve"不在,"ve"会被保留在转换后的文本中。我们的矢量化器将尝试识别和警告某些类型的不一致性。
TfidfVectorizer & TfidfTransformer
上述模型有很多缺点,它没有考虑单词之间的顺序,也无法反映出一个句子的关键词。在这里,我们继续学习scikit库的另一个编码器——TfidfVectorizer
。
词频 - 逆向文档频率(term frequency–inverse document frequency,tf-idf)方法,对在某个特定文档中经常出现的术语给予很高的权重,但对在语料库的许多文档中都经常出现的术语给予的权重却不高。
这里在分母加一是因为在实际工作中,可能先有词表,再处理文档语料, 目标词有可能是不存在任何文档中的。
TF-IDF就是同时考虑以上两个统计方法:
scikit-learn 在两个类中实现了TF-IDF 方法:TfidfTransformer
和TfidfVectorizer
,前者接受 CountVectorizer
生成的稀疏矩阵并将其变换,后者接受文本数据并完成词袋特征提取与 TF-IDF变换,二者都以文档为处理单位默认进行了l2正则化,具体参数可参见文档。
TfidfVectorizer
为了体现TF-IDF的优越性,重新定义训练语料,这里使用了fit_transform
,即对同一语料进行两个过程。
from sklearn.feature_extraction.text import TfidfVectorizer
corpus = ['I am a good student', 'I am going to zoo today']
def get_dtm(doc):
vectorize = TfidfVectorizer()
dtm = vectorize.fit_transform(doc)
return pd.DataFrame(dtm.toarray(), columns=vectorize.get_feature_names())
get_dtm(corpus)
输出的结果中,I
由于长度小于2,没有进入特征词字典中,同时,由于am
在两个document中均有出现,在每个document(每行)中,am
的取值最小,这也体现了该统计方法的合理性。
TfidfTransformer
TfidfTransformer
接收的对象不再像前者一样是一个document的list,它接收CountVectorizer
统计后的词频矩阵,此处将上文使用CountVectorizer
生成的dtm
作为编码器的输入:
from sklearn.feature_extraction.text import TfidfTransformer
transformer = TfidfTransformer(smooth_idf=False)
tfidf = transformer.fit_transform(dtm)
pd.DataFrame(dtm.toarray(), columns=vectorize.get_feature_names())
其对同一语料得到的结果与TfidfVectorizer
相同,也可以用上述理论进行分析。
虽然tf-idf标准化通常非常有用,但是可能有一种情况是二元变量显示会提供更好的特征。 这可以使用类 CountVectorizer
的 二进制
参数来实现。 特别地,一些估计器,诸如 伯努利朴素贝叶斯 显式的使用离散的布尔随机变量。 而且,非常短的文本很可能影响 tf-idf 值,而二进制出现信息更稳定。
REFERENCES
sklearn-Feature extraction
如何从文本中提取特征信息?