42 特征提取scikitlearn 019.docx

上传人:b****5 文档编号:29329098 上传时间:2023-07-22 格式:DOCX 页数:21 大小:107.11KB
下载 相关 举报
42 特征提取scikitlearn 019.docx_第1页
第1页 / 共21页
42 特征提取scikitlearn 019.docx_第2页
第2页 / 共21页
42 特征提取scikitlearn 019.docx_第3页
第3页 / 共21页
42 特征提取scikitlearn 019.docx_第4页
第4页 / 共21页
42 特征提取scikitlearn 019.docx_第5页
第5页 / 共21页
点击查看更多>>
下载资源
资源描述

42 特征提取scikitlearn 019.docx

《42 特征提取scikitlearn 019.docx》由会员分享,可在线阅读,更多相关《42 特征提取scikitlearn 019.docx(21页珍藏版)》请在冰豆网上搜索。

42 特征提取scikitlearn 019.docx

42特征提取scikitlearn019

4.2.特征提取

模块sklearn.feature_extraction可用于提取符合机器学习算法支持的特征,比如文本和图片。

Note

特征特征提取与特征选择有很大的不同:

前者包括将任意数据(如文本或图像)转换为可用于机器学习的数值特征。

后者是将这些特征应用到机器学习中。

4.2.1.从字典类型加载特征

类DictVectorizer可用于将标准的Python字典(dict)对象列表的要素数组转换为scikit-learn估计器使用的NumPy/SciPy表示形式。

虽然Python的处理速度不是特别快,但Python的dict优点是使用方便,稀疏(不需要存储的特征),并且除了值之外还存储特征名称。

类DictVectorizer实现了“one-of-K”或“one-hot”编码,用于分类(也称为标称,离散)特征。

分类功能是“属性值”对,其中该值被限制为不排序的可能性的离散列表(例如主题标识符,对象类型,标签,名称…)。

在下面的例子,”城市”是一个分类属性,而“温度”是传统的数字特征:

>>>

>>>measurements=[...{'city':

'Dubai','temperature':

33.},...{'city':

'London','temperature':

12.},...{'city':

'SanFrancisco','temperature':

18.},...]>>>fromsklearn.feature_extractionimportDictVectorizer>>>vec=DictVectorizer()>>>vec.fit_transform(measurements).toarray()array([[1.,0.,0.,33.],[0.,1.,0.,12.],[0.,0.,1.,18.]])>>>vec.get_feature_names()['city=Dubai','city=London','city=SanFrancisco','temperature']

类DictVectorizer也是对自然语言处理模型中训练序列分类器的有用的表示变换,通常通过提取围绕感兴趣的特定的词的特征窗口来工作。

例如,假设我们具有提取我们想要用作训练序列分类器(例如:

块)的互补标签的部分语音(PoS)标签的第一算法。

以下dict可以是在“坐在垫子上的猫”的句子,围绕“sat”一词提取的这样一个特征窗口:

>>>

>>>pos_window=[...{...'word-2':

'the',...'pos-2':

'DT',...'word-1':

'cat',...'pos-1':

'NN',...'word+1':

'on',...'pos+1':

'PP',...},...#inarealapplicationonewouldextractmanysuchdictionaries...]

该描述可以被矢量化为适合于呈递分类器的稀疏二维矩阵(可能在被管道text.TfidfTransformer进行归一化之后):

>>>

>>>vec=DictVectorizer()>>>pos_vectorized=vec.fit_transform(pos_window)>>>pos_vectorized<1x6sparsematrixoftype'<...'numpy.float64'>'with6storedelementsinCompressedSparse...format>>>>pos_vectorized.toarray()array([[1.,1.,1.,1.,1.,1.]])>>>vec.get_feature_names()['pos+1=PP','pos-1=NN','pos-2=DT','word+1=on','word-1=cat','word-2=the']

你可以想象,如果一个文本语料库的每一个单词都提取了这样一个上下文,那么所得的矩阵将会非常宽(许多one-hot-features),其中大部分通常将会是0。

为了使结果数据结构能够适应内存,该类``DictVectorizer``的scipy.sparse默认使用一个矩阵而不是一个numpy.ndarray。

4.2.2.特征哈希(相当于一种降维技巧)

类FeatureHasher是一种高速,低内存消耗的向量化方法,它使用了`特征散列featurehashing

//en.wikipedia.org/wiki/Feature_hashing>`_技术,或可称为“散列法”(hashingtrick)的技术。

代替在构建训练中遇到的特征的哈希表,如向量化所做的那样FeatureHasher将哈希函数应用于特征,以便直接在样本矩阵中确定它们的列索引。

结果是以牺牲可检测性为代价,提高速度和减少内存的使用;哈希表不记得输入特性是什么样的,没有inverse_transform办法。

由于散列函数可能导致(不相关)特征之间的冲突,因此使用带符号散列函数,并且散列值的符号确定存储在特征的输出矩阵中的值的符号。

这样,碰撞可能会抵消而不是累积错误,并且任何输出要素的值的预期平均值为零。

默认情况下,此机制将使用alternate_sign=True启用,对于小型哈希表大小(n_features<10000)特别有用。

对于大的哈希表大小,可以禁用它,以便将输出传递给估计器,如sklearn.naive_bayes.MultinomialNB或sklearn.feature_selection.chi2特征选择器,这些特征选项器可以使用非负输入。

类FeatureHasher接受映射(如Python的dict及其在collections模块中的变体),使用键值对(feature,value)或字符串,具体取决于构造函数参数input_type。

映射被视为(feature,value)对的列表,而单个字符串的隐含值为1,因此['feat1','feat2','feat3']被解释为[('feat1',1),('feat2',1),('feat3',1)]。

如果单个特征在样本中多次出现,相关值将被求和(所以('feat',2)和('feat',3.5)变为('feat',5.5))。

FeatureHasher的输出始终是CSR格式的scipy.sparse矩阵。

特征散列可以在文档分类中使用,但与text.CountVectorizer不同,FeatureHasher不执行除Unicode或UTF-8编码之外的任何其他预处理;请参阅下面的哈希技巧向量化大文本语料库,用于组合的tokenizer/hasher。

例如,有一个词级别的自然语言处理任务,需要从(token,part_of_speech)键值对中提取特征。

可以使用Python生成器函数来提取功能:

deftoken_features(token,part_of_speech):

iftoken.isdigit():

yield"numeric"else:

yield"token={}".format(token.lower())yield"token,pos={},{}".format(token,part_of_speech)iftoken[0].isupper():

yield"uppercase_initial"iftoken.isupper():

yield"all_uppercase"yield"pos={}".format(part_of_speech)

然后,raw_X为了可以传入FeatureHasher.transform可以通过如下方式构造:

raw_X=(token_features(tok,pos_tagger(tok))fortokincorpus)

并传入一个hasher:

hasher=FeatureHasher(input_type='string')X=hasher.transform(raw_X)

得到一个scipy.sparse类型的矩阵X。

注意使用发生器的理解,它将懒惰引入到特征提取中:

词令牌(token)只能根据需要从哈希值进行处理。

4.2.2.1.实现细节

类FeatureHasher使用签名的32-bit变体的MurmurHash3。

因此导致(并且由于限制scipy.sparse),当前支持的功能的最大数量.

特征哈希的原始形式源于Weinbergeretal,使用两个单独的哈希函数,和分别确定特征的列索引和符号。

现有的实现是基于假设:

MurmurHash3的符号位与其他位独立。

由于使用简单的模数将哈希函数转换为列索引,建议使用2次幂作为n_features参数;否则特征不会均匀的分布到列中。

参考文献:

KilianWeinberger,AnirbanDasgupta,JohnLangford,AlexSmola和JoshAttenberg(2009)。

用于大规模多任务学习的特征散列。

PROC。

ICML。

MurmurHash3。

参考文献:

●KilianWeinberger,AnirbanDasgupta,JohnLangford,AlexSmolaandJoshAttenberg(2009).用于大规模多任务学习的特征散列.Proc.ICML.

●MurmurHash3.

4.2.3.文本特征提取

4.2.3.1.话语表示

文本分析是机器学习算法的主要应用领域。

然而,原始数据,符号文字序列不能直接传递给算法,因为它们大多数要求具有固定长度的数字矩阵特征向量,而不是具有可变长度的原始文本文档。

为解决这个问题,scikit-learn提供了从文本内容中提取数字特征的最常见方法,即:

●令牌化(tokenizing)对每个可能的词令牌分成字符串并赋予整数形的id,例如通过使用空格和标点符号作为令牌分隔符。

●统计(counting)每个词令牌在文档中的出现次数。

●标准化(normalizing)在大多数的文档/样本中,可以减少重要的次令牌的出现次数的权重。

在该方案中,特征和样本定义如下:

●每个**单独的令牌发生频率**(归一化或不归零)被视为一个**特征**。

●给定**文档**中所有的令牌频率向量被看做一个多元sample**样本**。

因此,文本的集合可被表示为矩阵形式,每行对应一条文本,每列对应每个文本中出现的词令牌(如单个词)。

我们称**向量化**是将文本文档集合转换为数字集合特征向量的普通方法。

这种特殊思想(令牌化,计数和归一化)被称为BagofWords或“Bagofn-grams”模型。

文档由单词出现来描述,同时完全忽略文档中单词的相对位置信息。

4.2.3.2.稀疏

由于大多数文本文档通常只使用文本词向量全集中的一个小子集,所以得到的矩阵将具有许多特征值为零(通常大于99%)。

例如,10,000个短文本文档(如电子邮件)的集合将使用总共100,000个独特词的大小的词汇,而每个文档将单独使用100到1000个独特的单词。

为了能够将这样的矩阵存储在存储器中,并且还可以加速代数的矩阵/向量运算,实现通常将使用诸如scipy.sparse包中的稀疏实现。

4.2.3.3.常见Vectorizer使用方法

类CountVectorizer在单个类中实现了tokenization(词语切分)和occurrencecounting(出现频数统计):

>>>

>>>fromsklearn.feature_extraction.textimportCountVectorizer

这个模型有很多参数,但参数的默认初始值是相当合理的(请参阅参考文档了解详细信息):

>>>

>>>vectorizer=CountVectorizer()>>>vectorizerCountVectorizer(analyzer=...'word',binary=False,decode_error=...'strict',dtype=<...'numpy.int64'>,encoding=...'utf-8',input=...'content',lowercase=True,max_df=1.0,max_features=None,min_df=1,ngram_range=(1,1),preprocessor=None,stop_words=None,strip_accents=None,token_pattern=...'(?

u)\\b\\w\\w+\\b',tokenizer=None,vocabulary=None)

我们用它来对简约的文本语料库进行tokenize(分词)和统计单词出现频数:

>>>

>>>corpus=[...'Thisisthefirstdocument.',...'Thisisthesecondseconddocument.',...'Andthethirdone.',...'Isthisthefirstdocument?

',...]>>>X=vectorizer.fit_transform(corpus)>>>X<4x9sparsematrixoftype'<...'numpy.int64'>'with19storedelementsinCompressedSparse...format>

默认配置通过提取至少2个字母的单词来对string进行分词。

做这一步的函数可以显式地被调用:

>>>

>>>analyze=vectorizer.build_analyzer()>>>analyze("Thisisatextdocumenttoanalyze.")==(...['this','is','text','document','to','analyze'])True

analyzer在拟合过程中找到的每个term(项)都会被分配一个唯一的整数索引,对应于resultingmatrix(结果矩阵)中的一列。

此列的一些说明可以被检索如下:

>>>

>>>vectorizer.get_feature_names()==(...['and','document','first','is','one',...'second','the','third','this'])True>>>X.toarray()array([[0,1,1,1,0,0,1,0,1],[0,1,0,1,0,2,1,0,1],[1,0,0,0,1,0,1,1,0],[0,1,1,1,0,0,1,0,1]]...)

从feature名称到columnindex(列索引)的逆映射存储在vocabulary_属性中:

>>>

>>>vectorizer.vocabulary_.get('document')1

因此,在未来对transform方法的调用中,在trainingcorpus(训练语料库)中没有看到的单词将被完全忽略:

>>>

>>>vectorizer.transform(['Somethingcompletelynew.']).toarray()...array([[0,0,0,0,0,0,0,0,0]]...)

请注意,在前面的corpus(语料库)中,第一个和最后一个文档具有完全相同的词,因为被编码成相同的向量。

特别是我们丢失了最后一个文件是一个疑问的形式的信息。

为了防止词组顺序颠倒,除了提取一元模型1-grams(个别词)之外,我们还可以提取2-grams的单词:

>>>

>>>bigram_vectorizer=CountVectorizer(ngram_range=(1,2),...token_pattern=r'\b\w+\b',min_df=1)>>>analyze=bigram_vectorizer.build_analyzer()>>>analyze('Bi-gramsarecool!

')==(...['bi','grams','are','cool','bigrams','gramsare','arecool'])True

由vectorizer(向量化器)提取的vocabulary(词汇)因此会变得更大,同时可以在定位模式时消除歧义:

>>>

>>>X_2=bigram_vectorizer.fit_transform(corpus).toarray()>>>X_2...array([[0,0,1,1,1,1,1,0,0,0,0,0,1,1,0,0,0,0,1,1,0],[0,0,1,0,0,1,1,0,0,2,1,1,1,0,1,0,0,0,1,1,0],[1,1,0,0,0,0,0,0,1,0,0,0,1,0,0,1,1,1,0,0,0],[0,0,1,1,1,1,0,1,0,0,0,0,1,1,0,0,0,0,1,0,1]]...)

特别是“Isthis”的疑问形式只出现在最后一个文档中:

>>>

>>>feature_index=bigram_vectorizer.vocabulary_.get('isthis')>>>X_2[:

feature_index]array([0,0,0,1]...)

4.2.3.4.Tf–idf项加权

在一个大的文本语料库中,一些单词将出现很多次(例如“the”,“a”,“is”是英文),因此对文档的实际内容没有什么有意义的信息。

如果我们将直接计数数据直接提供给分类器,那么这些频繁词组会掩盖住那些我们关注但很少出现的词。

为了为了重新计算特征权重,并将其转化为适合分类器使用的浮点值,因此使用tf-idf变换是非常常见的。

Tf表示**术语频率**,而tf-idf表示术语频率乘以**转制文档频率**:

.

使用TfidfTransformer的默认设置,TfidfTransformer(norm='l2',use_idf=True,smooth_idf=True,sublinear_tf=False)术语频率,一个术语在给定文档中出现的次数乘以idf组件,计算为

其中是文档的总数,是包含术语的文档数。

然后,所得到的tf-idf向量通过欧几里得范数归一化:

.

它源于一个词权重的信息检索方式(作为搜索引擎结果的评级函数),同时也在文档分类和聚类中表现良好。

以下部分包含进一步说明和示例,说明如何精确计算tf-idfs以及如何在scikit-learn中计算tf-idfs,TfidfTransformer并TfidfVectorizer与定义idf的标准教科书符号略有不同

在TfidfTransformer和TfidfVectorizer中smooth_idf=False,将“1”计数添加到idf而不是idf的分母:

该归一化由类TfidfTransformer实现:

>>>

>>>fromsklearn.feature_extraction.textimportTfidfTransformer>>>transformer=TfidfTransformer(smooth_idf=False)>>>transformerTfidfTransformer(norm=...'l2',smooth_idf=False,sublinear_tf=False,use_idf=True)

有关所有参数的详细信息,请参阅参考文档。

让我们以下方的词频为例。

第一个次在任何时间都是100%出现,因此不是很有重要。

另外两个特征只占不到50%的比例,因此可能更具有代表性:

>>>

>>>counts=[[3,0,1],...[2,0,0],...[3,0,0],...[4,0,0],...[3,2,0],...[3,0,2]]...>>>tfidf=transformer.fit_transform(counts)>>>tfidf<6x3sparsematrixoftype'<...'numpy.float64'>'with9storedelementsinCompressedSparse...format>>>>tfidf.toarray()array([[0.81940995,0.,0.57320793],[1.,0.,0.],[1.,0.,0.],[1.,0.,0.],[0.47330339,0.88089948,0.],[0.58149261,0.,0.81355169]])

每行都被正则化,使其适应欧几里得标准:

例如,我们可以计算`计数`数组中第一个文档中第一个项的tf-idf,如下所示:

现在,如果我们对文档中剩下的2个术语重复这个计算,我们得到:

和原始tf-idfs的向量:

然后,应用欧几里德(L2)规范,我们获得文档1的以下tf-idfs:

此外,默认参数smooth_idf=True将“1”添加到分子和分母,就好像一个额外的文档被看到一样包含集合中的每个术语,这样可以避免零分割:

使用此修改,文档1中第三项的tf-idf更改为1.8473:

而L2标准化的tf-idf变为

:

>>>

>>>transformer=TfidfTransformer()>>>transformer.fit_transform(counts).toarray()array([[0.85151335,0.,0.52433293],[1.,0.,0.],[1.,0.,0.],[1.,0.,0.],[0.55422893,0.83236428,0.],[0.63035731,0.,0.77630514]])

通过拟合方法调用计算的每个特征的权重存储在模型属性中:

>>>

>>>transformer.idf_array([1....,2.25...,1.84...])

由于tf-idf经常用于文本特征,所以还有一个类TfidfVectorizer,它将CountVectorizer和TfidfTransformer的所有选项组合在一个单例模型中:

>>>

>>>fromsklearn.feature_extraction

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > PPT模板 > 自然景观

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1