sklearn.feature_extraction 模块能够被用来从包含文本或者特片的数据集中提取出适用于机器学习算法的特征。 html
注意:特征提取和特征选择是极不相同的:前者由任意数据组成,好比文本或者图片,转换为适用于机器学习的数字。后者是应用于这些特征的机器学习方法。python |
类DictVectorizer能够将由python标准的列表dict对象所表示的特征转换为由scikit-learn中经常使用的NumPy/SciPy所表示的对象。 git
虽然dict处理起来不是特别快,可是其优点在于方便的使用,建立系数矩阵(缺失值不会被存储)以及将特征名字存储与值上。 算法
DictVectorizer能够建立咱们 称之为one-of-K或者"one-hot"编码用于分类特征(又名aka nominal,discrete)特征。分类特征是"属性-值"对,值限制为一系列的无序离散变量(好比,主题标识、对象类型、标记、名字。。。) 数组
在下面的例子中,"城市"是一个分类属性,"温度"是另外一个数值特征: 数据结构
>>> measurements = [ app ... {'city': 'Dubai', 'temperature': 33.}, dom ... {'city': 'London', 'temperature': 12.}, 机器学习 ... {'city': 'San Francisco', 'temperature': 18.}, ide ... ] >>>from sklearn.feature_extration import DictVectorizer >>>vec = DictVectorizer() #声明一个字典到向量的变换
>>>vec.fit_transform(measurements).toarray() #fit_transform将上述的字典转换为一个稀疏矩阵,toarray()将稀疏矩阵转换为矩阵的形式。 array([[ 1., 0., 0., 33.], [ 0., 1., 0., 12.], [ 0., 0., 1., 18.]])
>>>vec.fit_transform(measurements) (0, 0) 1.0 (0, 3) 33.0 (1, 1) 1.0 (1, 3) 12.0 (2, 2) 1.0 (2, 3) 18.0 >>> vec.get_feature_names() #输出特征的名字 ['city=Dubai', 'city=London', 'city=San Francisco', 'temperature'] |
DictVectorizer对于天然语言处理模型来讲也是一个有用的变换,能够提提取特定的单词的特征。
举例来讲,假设咱们有一个算法能够提取出部分演讲的标签(PoS),咱们想要使用这些标签做为补充的标签来训练一个序列分类器(好比,一个chunker)。下面的字典能够做为这样的特征窗口从句子"The cat sat on the mat"中提取出单词"sat"。
>>> pos_window = [ ... { ... 'word-2': 'the', ... 'pos-2': 'DT', ... 'word-1': 'cat', ... 'pos-1': 'NN', ... 'word+1': 'on', ... 'pos+1': 'PP', ... }, ... # in a real application one would extract many such dictionaries ... ] |
该描述能够被向量化一个适用于分类器(可能会被用于text.TfidfTransformer用于正则化)的稀疏的二维矩阵。
>>> vec = DictVectorizer() #建立一个变换声明 >>> pos_vectorized = vec.fit_transform(pos_window) #将pos_window变换为稀疏矩阵表示的形式。 >>> pos_vectorized <1x6 sparse matrix of type '<... 'numpy.float64'>' with 6 stored elements in Compressed Sparse ... 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。
类FeatrueHasher是一个高速,低内存向量化程序,其使用一个名为feature hashing的技术,或者"散列方法"。不是对每一个参与的特征都创建散列表,像vectorizers那样,FeatureHasher应用一个散列功能于特征上,直接肯定他们的列索引。这样作的结果就是提升了速度,下降了内存使用,以被检查为代价。哈希方法不会记住输入特性的样子,所以也没有使用inverse_transform方法。
由于哈希功能可能会形成(不相关)特征之间的冲突,使用有符号哈希函数,哈希值的符号决定了存储在特性输出矩阵中的值的符号。
这样的话,冲突可能会抵消而不是累积偏差,而且任何输出特性的指望平均值都是零。这种机制是默认使用的alternate_sign=True,对于小的哈希表大小特别有用(n_features < 10000)。对于大的哈希表,可能不适用,容许输出传递给相似于estimators的成员相似于sklearn.naive_bayes.MultinomialNB或sklearn.feature_sele
ction.chi2指望非负输入的特性选择器。
FeatureHasher接受要么是映射(dict以及他在collection模块中的变体),(feature, value)对,或者是字符串,取决于构建参数的类型input_type。映射被看成是(feature, value)对,单一的字符串,被默认为值为1,好比,['feat1', 'feat2', 'feat3']被解释为[('feat1', 1), ('feat2', 1), ('feat3', 1)]。若是一个单一的字符串在同一个样本中出现了屡次,其对应的值将被累加,如('feat', 2) and ('feat', 3.5) become ('feat', 5.5))。FeatureHasher的输出常用CSR格式的scipy.sparse矩阵。
特征散列能够被应用于文档分类,可是不像text.CountVectorizer,FeatureHasher不会切分单词或者其余任何的预处理,处理将unicode编码转换为utf-8编码;参见用hashing trick将大型的预料库向量化,下面是一个混合的tokenizer/hasher。
做为一个例子,考虑到单词水平的天然语言处理任务,须要从(token,part_of_speech)中提出特征。可使用python生成器lai 提取特征。
def token_features(token, part_of_speech): if token.isdigit(): #isdigit()检验字符串是否只由数字构成 yield "numeric" else: yield "token={}".format(token.lower())#对字符串进行格式化 yield "token,pos={},{}".format(token, part_of_speech) if token[0].isupper(): #检验是否为大写字母 yield "uppercase_initial" if token.isupper(): yield "all_uppercase" yield "pos={}".format(part_of_speech) |
以后, raw_X使用FeatureHasher.transform进行建立:
raw_X = (token_features(tok, pos_tagger(tok)) for tok in corpus) |
并以hasher表示为:
hasher = FeatureHasher(input_type='string') X = hasher.transform(raw_X) |
获得scipy.sparse矩阵X。
FeatureHasher使用32位的变量。结果就是该特征支持的最大数字为2^31-1。
因为使用简单的模将哈希函数转换为列索引,所以建议使用2的幂做为n_features参数;不然,特性将不会均匀地映射到列。
文本分析是机器学习算法的一个主要应用领域。然而,原始数据、符号序列不能直接输入到算法自己中,由于大多数算法指望的是固定大小的数字特征向量,而不是长度不一的原始文本文档。
为了解决这个问题,scikit-learn为从文本内容中提取数字特性的最多见方法提供了实用工具,即:
在该方案中,特征和样本定义以下:
所以,一个文档语料库能够用一个矩阵表示,每一个文档有一行,每一个标记(例如单词)有一列出如今语料库中。
咱们将向量化称为将文本文档集合转换为数字特征向量的通常过程。该具体策略(标记化、计数和规范化)被称为"字袋"或"n-g袋"表示。文档是经过单词出现来描述的,而彻底忽略了文档中单词的相对位置信息。
因为大多数文档一般使用语料库中使用的单词的一个很是小的子集,所以生成的矩阵将具备许多0的特征值(一般超过99%)。
例如,包含10,000个短文本文档(如电子邮件)的集合将使用一个词汇表,其大小总计为100,000个惟一单词,而每一个文档单独使用100到1000个惟一的单词。
为了可以在内存中存储这样一个矩阵,同时也为了加快代数运算矩阵/向量,实现一般使用稀疏表示,例如scipy中可用的实现。稀疏的包。
CountVectorizer以一个简单的类实现了标记化和频率计数:
>>> from sklearn.feature_extraction.text import CountVectorizer |
这个模型有不少参数,可是默认值是至关合理的(详情请看参考文档):
>>> vectorizer = CountVectorizer() #建立一个词向量 >>> vectorizer CountVectorizer(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) |
使用CountVectorizer()统计语料中的单词:
>>> corpus = [ ... 'This is the first document.', ... 'This is the second second document.', ... 'And the third one.', ... 'Is this the first document?', ... ] >>> X = vectorizer.fit_transform(corpus) #转换成稀疏矩阵的表示形式 >>> X <4x9 sparse matrix of type '<... 'numpy.int64'>' with 19 stored elements in Compressed Sparse ... format> |
默认配置经过提取至少两个字母的单词来标记字符串。能够显式地请求执行此步骤的特定函数:
>>> analyze = vectorizer.build_analyzer() >>> analyze("This is a text document to analyze.") == ( ... ['this', 'is', 'text', 'document', 'to', 'analyze']) True #a是一个字母,所以默认忽略 |
在此过程当中,矩阵的每一列都至关于一个索引。列的解释能够按照下面的方式进行检索:
>>> vectorizer.get_feature_names() == ( ... ['and', 'document', 'first', 'is', 'one', ... 'second', 'the', 'third', 'this']) True #获取特征的名字(token的名字)
>>> 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]]...) #每一列都是一个索引,按照上面的特征名字进行排序 |
从特性名称到列索引的逆向映射存储在vectorizer的vocabulary ary_属性中:
>>> vectorizer.vocabulary_.get('document') 1 |
所以,在之后的调用中,将彻底忽略在训练语料库中没有看到的单词:
>>> vectorizer.transform(['Something completely new.']).toarray() ... array([[0, 0, 0, 0, 0, 0, 0, 0, 0]]...) |
指的注意的是,在前面的语料库中,第一个和最后一个文档的单词彻底相同,所以以相同的向量编码。特别是咱们失去了最后一份文件是疑问形式的信息。为了保存一些本地排序信息,除了1-g(单个单词)外,咱们还能够提取2-g的单词。
>>> 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']) True |
所以,该向量能够提取出更大的词汇量,从而解决本地位置模式编码歧义的问题:
>>> 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]]...) |
尤为是疑问句"Is this"只出如今最后一份文件中:
>>> feature_index = bigram_vectorizer.vocabulary_.get('is this') >>> X_2[:, feature_index] array([0, 0, 0, 1]...) |
在一个大的文本语料库中,有些单词很是常见(例如英语中的"the"、"a"、"is"),所以,对于文档的实际内容几乎没有什么有意义的信息。若是咱们将直接计数数据直接提供给一个分类器,这些高频词将会遮蔽更稀有的、关键的术语的频率。
为了将计数特性从新加权为适合于分类器使用的浮点值,常见的手段是使用tf-idf转换。
Tf表示词频率,Tf - idf表示词频乘以该词的逆文档频率。
使用TfidfTransformer的默认设置。
TfidfTransformer(norm='l2', use_idf=True, smooth_idf=True, sublinear_tf=False)
词语频率(词语在给定文档中出现的次数)与idf相乘,idf组件计算为:
where is the total number of documents,(文档的总数量) and
is the number of documents that contain term
(包含词语t的文档的数量). The resulting tf-idf vectors are then normalized by the Euclidean norm:
这最初是一种用于信息检索(做为搜索引擎结果的排序函数)的词语加权方案,在文档分类和聚类中也获得了很好的应用。
如下部分包含进一步的解释和示例,说明tf-idfs是如何精确计算的,以及scikit-learn的TfidfTransformer和TfidfVectorizer中tf-idfs是如何计算的,与定义idf的标准教科书符号略有不一样
在TfidfTransformer和TfidfVectorizer的smooth_idf=False中,"1"计数被添加到idf中,而不是idf的分母:
TfidfTransformer类实现了这种标准化:
>>> from sklearn.feature_extraction.text import TfidfTransformer >>> transformer = TfidfTransformer(smooth_idf=False) #构建一个分类器 >>> transformer TfidfTransformer(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 <6x3 sparse matrix of type '<... 'numpy.float64'>' with 9 stored elements in Compressed Sparse ... 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]]) |
每一行都归一化获得单位欧几里德范数:
例如,咱们能够计算count数组中第一个文档中第一项的tf-idf,以下所示:
#一共有6项,即有6个document
#包含第一项的文档有6个
#计算其逆文档频率
#计算其词频*逆文档频率
如今,若是咱们对文档中剩下的两项重复这个计算,咱们获得
原始tf-idfs向量:
而后,应用欧几里德(L2)范数,咱们获得了文档1的tf-idfs:
此外,默认参数smooth_idf=True在分子和分母上增长了"1",分母就像每一个文档都包含额外的词同样,这是为了防止0除的出现:
使用此修改,文档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]]) |
经过fit方法调用计算的每一个特征的权重都存储在模型属性中:
>>> transformer.idf_ array([ 1. ..., 2.25..., 1.84...])#这里指的就是单词的逆文档频率 |
虽然tf-idf常常用于文本特性,还有另外一个类TfidfVectorizer,它将CountVectorizer和TfidfTransformer的全部选项组合在一个模型中:
>>> from sklearn.feature_extraction.text import TfidfVectorizer >>> vectorizer = TfidfVectorizer() >>> vectorizer.fit_transform(corpus) ... <4x9 sparse matrix of type '<... 'numpy.float64'>' with 19 stored elements in Compressed Sparse ... format> |
虽然tf-idf规范化一般很是有用,但在某些状况下,二进制标记可能提供更好的特性。这能够经过使用CountVectorizer的二进制参数来实现。特别地,一些估计,如伯努利朴素贝叶斯显式模型离散布尔随机变量。此外,很是短的文本极可能有噪声tf-idf值,而二进制信息更稳定。
一般,调整特征提取参数的最佳方法是使用交叉验证的网格搜索,例如使用分类器流水线化特征提取器:
Sample pipeline for text feature extraction and evaluation
文本由字符组成,而文件由字节组成。这些字节根据某种编码表示字符。要使用Python中的文本文件,它们的字节必须被解码为一个称为Unicode的字符集。常见的编码有ASCII、Latin-1(西欧)、KOI8-R(俄语)和通用编码UTF-8和UTF-16。
注意:编码也能够称为"字符集",但这个术语不太准确:单个字符集能够存在多个编码。
scikit中的文本特征提取器知道如何解码文本文件,但前提是你告诉他们文件的编码是什么。CountVectorizer为此接受一个编码参数。对于许多文本文件,正确的编码多是UTF-8,所以它是默认的(编码=" UTF-8 ")。
可是,若是正在加载的文本实际上不是用UTF-8编码的,那么将获得一个UnicodeDecodeError。经过将decode_error参数设置为"ignore"或"replace",可让向量化工具对解码错误不会报错。有关Python函数bytes.decode的详细信息请参阅文档(在Python提示符处输入help(bytes.decode))。
若是你在解码文本时有困难,能够作以下尝试:
词袋表示很是简单,但在实践中很是有用。
特别是在有监督的设置中,它能够成功地与快速和可伸缩的线性模型相结合,以训练文档分类器;
在无监督的状况下,它能够经过应用K-means等聚类算法将相似的文档分组在一块儿;
最后,能够经过放松聚类的硬性分配约束来发现语料库的主要主题,例如使用非负矩阵分解(NMF或NNMF)。
一组unigram(就是一袋单词)不能捕捉短语和多词表达,忽略了词序依赖。此外,单词袋模型不考虑潜在的拼写错误或单词派生
N-gram能够克服这点!与其构建一个简单的unigrams集合(n=1),不如选择一个bigrams集合(n=2),在这里统计连续单词成对出现的次数。
能够考虑使用字符n-g的集合,这是一种抵抗拼写错误和派生的表示。
例如,假设咱们正在处理一个由两个文档组成的语料库:['words', 'wprds']。第二个文档包含单词"words"的拼写错误。一个简单的词汇表示能够将这两个文档看做是很是不一样的文档,它们在两个可能的特性上都有所不一样。然而,一个2-gram
>>> ngram_vectorizer = CountVectorizer(analyzer='char_wb', ngram_range=(2, 2)) >>> counts = ngram_vectorizer.fit_transform(['words', 'wprds']) >>> ngram_vectorizer.get_feature_names() == ( ... [' w', 'ds', 'or', 'pr', 'rd', 's ', 'wo', 'wp']) True >>> counts.toarray().astype(int) array([[1, 1, 1, 0, 1, 1, 1, 0], [1, 1, 0, 1, 1, 1, 0, 1]]) |
表示法能够在8个特征中找到4个匹配的文档,这能够帮助首选分类器更好地决定:
具备边界感知功能的变体char_wb对于使用空白分隔词的语言来讲特别有趣,由于在这种状况下,它生成的嘈杂特性要比原始char变体少得多。对于这类语言,它能够提升使用这类特性训练的分类器的预测精度和收敛速度,同时在拼写和词源方面保持鲁棒性。
而一些局部定位信息能够经过提取n-g而不是单个单词来保存,一袋一袋的单词和一袋一袋的n-g破坏了文档的大部份内部结构,从而破坏了内部结构所承载的大部分意义。
所以,为了解决更普遍的天然语言理解任务,应该考虑句子和段落的局部结构。所以,许多这样的模型将被定义为"结构化输出"问题,而这些问题目前不在scikitlearn的范围以内。
(使用哈希技巧向量化大型文本语料库)
上面的矢量化方案很简单,可是它在内存中保存了从字符串token到整数特征索引(词汇表_属性)的映射,这在处理大型数据集时形成了一些问题:
经过结合sklearn.feature_extraction实现的"哈希技巧"(特性哈希)、文本预处理及CountVectorizer的tokenization特征能够克服这些限制。
这个组合是在HashingVectorizer中实现的,一个常常结合CountVectorizer的转换类。HashingVectorizer是无状态的,这意味着没必要调用fit:
>>> from sklearn.feature_extraction.text import HashingVectorizer >>> hv = HashingVectorizer(n_features=10) >>> hv.transform(corpus) ... <4x10 sparse matrix of type '<... 'numpy.float64'>' with 16 stored elements in Compressed Sparse ... format> |
能够看到向量输出16个非零的tokens,比CountVectorizer的19个非零的tokens要少这种差别来自于哈希函数冲突,由于n_features参数的值很低。
在实际设置中,n_features参数能够保留为其默认值2 ** 20(大约100万个可能的特性)。若是内存或下游模型大小是一个问题,那么选择一个较低的值(好比2 ** 18)可能会有帮助,而不会在典型的文本分类任务中引入太多额外的冲突。
让咱们用默认设置再试一次:
>>> hv = HashingVectorizer() >>> hv.transform(corpus) ... <4x1048576 sparse matrix of type '<... 'numpy.float64'>' with 19 stored elements in Compressed Sparse ... format> |
咱们再也不获得冲突,但这是以输出空间更大维度为代价的。固然,这里使用的其余术语可能仍然会相互冲突。
HashingVectorizer也有如下限制:
使用HashingVectorizer的一个有趣的开发是执行内核外扩展的能力。这意味着咱们能够从不适合计算机主存的数据中学习。
实现核外扩展的一个策略是将数据以小批量的形式流到评估器。使用HashingVectorizer对每一个迷你批处理进行矢量化,以保证估计器的输入空间始终具备相同的维数。所以,在任什么时候候使用的内存数量都受一个迷你批处理大小的限制。虽然使用这种方法能够摄取的数据量没有限制,但从实际的角度来看,学习时间一般受但愿在任务上花费的CPU时间的限制。
有关文本分类任务中的核心外扩展的完整示例,请参阅文本文档的核心外分类。
能够经过向vectorizer构造函数传递一个可调用的函数来定制行为:
>>> def my_tokenizer(s): ... return s.split() ... >>> vectorizer = CountVectorizer(tokenizer=my_tokenizer) >>> vectorizer.build_analyzer()(u"Some... punctuation!") == ( ... ['some...', 'punctuation!']) True |
特别地,咱们作以下命名:
要使预处理器、标记器和分析器知道模型参数,能够从类派生并覆盖build_预处理器build_tokenizer'和build_analyzer方法,而不是传递定制函数。
一些提示与技巧:
>>> from nltk import word_tokenize
>>> from nltk.stem import WordNetLemmatizer
>>> class LemmaTokenizer(object):
... def __init__(self):
... self.wnl = WordNetLemmatizer()
... def __call__(self, doc):
... return [self.wnl.lemmatize(t) for t in word_tokenize(doc)]
...
>>> vect = CountVectorizer(tokenizer=LemmaTokenizer())
|
(注意,这里没有滤掉标点符号。)
例如,下面的示例将把一些英式拼写转换为美式拼写:
>>> import re >>> def to_british(tokens): ... for t in tokens: ... t = re.sub(r"(...)our$", r"\1or", t) ... t = re.sub(r"([bt])re$", r"\1er", t) ... t = re.sub(r"([iy])s(e$|ing|ation)", r"\1z\2", t) ... t = re.sub(r"ogue$", "og", t) ... yield t ... >>> class CustomVectorizer(CountVectorizer): ... def build_tokenizer(self): ... tokenize = super(CustomVectorizer, self).build_tokenizer() ... return lambda doc: list(to_british(tokenize(doc))) ... >>> print(CustomVectorizer().build_analyzer()(u"color colour")) [...'color', ...'color'] |
在处理不使用显式分隔符(如空格)的亚洲语言时,定制向量器也颇有用。
extract_patches_2d函数从存储为二维数组的图像中提取补丁,或者沿着第三轴提取具备颜色信息的三维图像。要从全部补丁中从新构建图像,请使用reconstruct_from_patches_2d。样例生成带有3个颜色通道(例如RGB格式)的4x4像素图像。
>>> import numpy as np >>> from sklearn.feature_extraction import image
>>> one_image = np.arange(4 * 4 * 3).reshape((4, 4, 3)) >>> one_image[:, :, 0] # R channel of a fake RGB picture array([[ 0, 3, 6, 9], [12, 15, 18, 21], [24, 27, 30, 33], [36, 39, 42, 45]])
>>> patches = image.extract_patches_2d(one_image, (2, 2), max_patches=2, ... random_state=0) >>> patches.shape (2, 2, 2, 3) >>> patches[:, :, :, 0] array([[[ 0, 3], [12, 15]],
[[15, 18], [27, 30]]]) >>> patches = image.extract_patches_2d(one_image, (2, 2)) >>> patches.shape (9, 2, 2, 3) >>> patches[4, :, :, 0] array([[15, 18], [27, 30]]) |
如今让咱们经过对重叠区域的平均来尝试从这些斑块中重建原始图像:
>>> reconstructed = image.reconstruct_from_patches_2d(patches, (4, 4, 3)) >>> np.testing.assert_array_equal(one_image, reconstructed) |
PatchExtractor类的工做方式与extract_patches_2d相同,只是它支持多个图像做为输入。它做为一个估计器实现,所以能够在管道中使用。
>>> five_images = np.arange(5 * 4 * 4 * 3).reshape(5, 4, 4, 3) >>> patches = image.PatchExtractor((2, 2)).transform(five_images) >>> patches.shape (45, 2, 2, 3) |
scikit-learn中的几个评估器可使用特性或示例之间的链接信息。例如,Ward聚类(分层聚类)只能将图像的相邻像素聚在一块儿,从而造成相邻的斑块:
为此,估计器使用一个"连通"矩阵,给出的样例就是连通的。
函数img_to_graph从2D或3D图像返回这样一个矩阵。相似地,grid_to_graph为给定这些图像形状的图像构建一个链接矩阵。
这些矩阵可用于在使用连通性信息(如Ward聚类(分层聚类))的估计器中强制链接,也可用于构建预先计算的内核或类似矩阵。