特征抽取:特征字典向量化和特征哈希变换

2017-11-23  本文已影响0人  cnkai

sklearn.feature_extaction模块提供了从原始数据如文本,图像等中抽取能够被机器学习算法直接处理的特征向量。

Feature extraction和Feature selection是不同的:前者将任意的数据变换成机器学习算法可用的数值型特征;后者是一个作用于特征空间上的机器学习技术,是对特征空间的再次变换。

image

Loading Features From Dicts

DictVectorizer类可以用来把标准Python dict对象表示的特征数组转换成Numpy/Scipy的表示形式,以便于scikit-learn estimators的使用。

尽管速度不是很快,Python的dict使用起来还是相当方便的,而且还可以稀疏存储(absent feature need not be stored);字典的形式便于将特征的取值和名称一一对应起来。

DictVectorizer实现了one-of-K或者叫“one-hot”编码对标称型特征。标称型特征(Categorical feature)是“attribute-value”pairs,其中value是属性的可能的取值列表,必须是有限的离散的没有大小顺序的。(e.g 男女,话题类别)

下面的例子中,‘city’是一个categorical attribute而‘temperature’是一个典型的numerical feature。

measurements = [
    {'city': 'Dubai', 'temperature': 33.0},
    {'city': 'London', 'temperature': 12.0},
    {'city': 'San Fransisco', 'temperature': 18.0},
]

from sklearn.feature_extraction import DictVectorizer
vec = DictVectorizer()

print(vec.fit_transform(measurements).toarray())
print(vec.get_feature_names())
image

Features hashing

Features hashing是一个高速的,低存储的向量化的类。
一般的vectorizer是为训练过程中遇到的特征构建一个hash table,而FeatureHasher类则直接对特征应用一个hash函数来决定特征在样本矩阵中的列索引。这样的做法使得计算速度提升并且节省了内存,the hasher无法记住输入特征的样子,而且不逊在你想变换操作:inverse_transform。

因为哈希函数可能会导致本来不相关的特征之间发生冲突,所以使用了有符号的hash函数。对一个特征,其hash值的符号决定了被存储到输出矩阵中的值的符号。通过这种方式就能够消除特征hash映射时发生的冲突而不是累计冲突。而且任意输出的值的期望均值是0.

如果non_negative=True被传入构造函数,将会取绝对值。这样会发生一些冲突(collision)但是哈希特征映射的输出就可以被传入到一些只能接受非负特征的学习器对象比如:
sklearn.naive_bayes.MultinomialNB分类器和sklearn.feature_selection.chi2特征选择器。

Features hashing接受参数类型可以使:mappings(字典或者其变体容器)或者(feature,value)对,或者strings。这取决于构造器参数:input_type。

Mapping被看做是由(feature,value)构成的一个列表,而单个字符串隐式的等于1,所以['feat1', 'feat2', 'feat3']被解释成(feature,value)的列表:[('feat1', 1), ('feat2',2), ('feat3', 3)]。 如果一个特征在一个样本中出现了多次,相关联的值就会累加起来:(比如('feat', 2)和('feat', 3.5)会累计起来成为('feat', 5.5))。

FeatureHasher的输出通常是CSR格式的scipy.sparse matrix。

Feature hashing 可被用于文档分类中去,但是与text.CountVectorizer不同,FeatureHasher不做单词切分或其他的预处理操作,除了Unicode-to-UTF-8编码以外。

Text Feature Extraction

The Bag of Words represention

文本分析是机器学习领域的重要应用。然而文本数据是由一系列符号构成的,
无法直接被计算机以及机器学习算法处理。绝大多数机器学习算法都是建立在
数值特征空间上,而且特征向量的长度也是固定的,但是文本的长度却
千差万别。

为了解决这一问题,sklearn提供了最通用的工具来从文本内容中抽取
数值型特征,这些工具如下:

  1. 标记字符串,为每一个可能的标记分配一个整型id,
    如使用white-spaces和punctuation作为token。
  2. 统计每个文档中各个token的出现次数。
  3. 归一化(Normalizing)和加权(Weighting)。

在这样的机制下,特征和样本如下定义:
每个token出现的频率被当做一个特征。
给定文本中所有token的频率组成的向量被当做多维样本。

Sparsity

绝大多数的文档都只使用了一个词汇子集,与整个语料的词汇集合相比起来,是非常小的。所以最终的特征向量矩阵中有很多的特征取值是0(通常是99%)。

例如: 对于一个有10000个短文本的集合来来说,它可能包含的所有的独立的词汇量是100000个,但是其中的任意一个独立的文档可能只有100到1000个词汇量。

为了存储这样的稀疏矩阵而且不影响矩阵/向量的运算速度,特征向量矩阵通常会使用稀疏矩阵来存储。

Common Vectorizer usage

from sklearn.feature_extraction.text import CountVectorizer
vectorizer = CountVectorizer(min_df=1)
print(vectorizer)
corpus = [
    'This is the first documents.',
    'This is the second documents.',
    'And the third document.',
    'Is this the first documents?',
]

X = vectorizer.fit_transform(corpus)
print(X)
image

在默认的设置中,提取的字符串长度至少要有两个字符,低于两个字符的会被忽略,比如'a'

analyze = vectorizer.build_analyzer()
analyze('This is a text document to analyze.') == (['this', 'is', 'text', 'document', 'to', 'analyze'])
image

在fit阶段被analyser发现的每一个词语(term)都会被分配一个独特的整数索引(unique interger index), 该索引对应于特征向量矩阵中的一列,全部小写化。

image

使用下面的方法获取某一个词语在矩阵中的第几列。

image

因此,在训练语料中没有见到过的单词将会被未来的转换方法完全忽略。

image

注意到前面的语料库中,第一个和最后一个句子中单词是一模一样的,只是顺序是不一样的。他们会被编码成相同的特征向量,所以词袋表示法丢失了单词顺序的前后相关性信息。为了保持某些局部的顺序性信息,我们可以抽取2-grams of words和1-grams(individual words)。

bigram_vectorizer = CountVectorizer(ngram_range=(1,2), 
                                    token_pattern=r'\b\w+\b', min_df=1)
analyze = bigram_vectorizer.build_analyzer()
analyze('Bi-grams are cool!') == (['bi', 'grams', 'are', 'cool', 'bi grams', 'grams are', 'are cool'])
image

这时候,vectorizer抽取的词汇表就会更大,而且可以解析编码在局部位置模式里面的模糊性和歧义性。

X_2 = bigram_vectorizer.fit_transform(corpus).toarray()
X_2
image
上一篇下一篇

猜你喜欢

热点阅读