python pos函数_使用python+sklearn实现特征提取
生活随笔
收集整理的這篇文章主要介紹了
python pos函数_使用python+sklearn实现特征提取
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
sklearn.feature_extraction模塊可用于以機(jī)器學(xué)習(xí)算法支持的格式從原始數(shù)據(jù)集(如文本和圖像)中提取特征。**注意:**特征提取與特征選擇有很大不同:前者是將任意數(shù)據(jù)(例如文本或圖像)轉(zhuǎn)換為可用于機(jī)器學(xué)習(xí)的數(shù)字特征。后者是一種應(yīng)用在這些特征上的機(jī)器學(xué)習(xí)技術(shù)。
array([[?1.,??0.,??0.,?33.],
???????[?0.,??1.,??0.,?12.],
???????[?0.,??0.,??1.,?18.]])>>>?vec.get_feature_names()
['city=Dubai',?'city=London',?'city=San?Francisco',?'temperature']DictVectorizer對于自然語言處理模型中的訓(xùn)練序列分類器來說也是一種有用的表示形式轉(zhuǎn)換,通常通過提取圍繞特定興趣詞的特征窗口來工作。例如,假設(shè)我們具有提取我們想要用作訓(xùn)練序列分類器(例如,塊)互補(bǔ)標(biāo)簽的部分語音(PoS)標(biāo)簽的一個算法。以下字典(dict)可以是在“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',...?????},...?????#?在真實的應(yīng)用中會提取想這樣的一個字典。...?]上述描述可以被矢量化為適合于傳遞給分類器的稀疏二維矩陣(可能在通過管道之后進(jìn)行 text.TfidfTransformer歸一化)>>>?vec?=?DictVectorizer()>>>?pos_vectorized?=?vec.fit_transform(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特征),其中大部分通常將會是0。為了使產(chǎn)生的數(shù)據(jù)結(jié)構(gòu)能夠適應(yīng)內(nèi)存,DictVectorizer類默認(rèn)使用scipy.sparse矩陣而不是numpy.ndarray。
X?=?hasher.transform(raw_X)得到一個scipy.sparse類的矩陣X。這里需要注意的是,由于我們使用了Python的生成器,導(dǎo)致在特征抽取過程中引入了懶惰性:只有在哈希器有需求的時候tokens才會被處理。
CountVectorizer()我們用該類對一個簡約的文本語料庫進(jìn)行分詞(tokenize)和統(tǒng)計單詞出現(xiàn)頻數(shù):>>>?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>默認(rèn)配置是通過提取至少包含2個字母的單詞來對字符串進(jìn)行分詞。可以顯式調(diào)用能做到這一步的函數(shù):>>>?analyze?=?vectorizer.build_analyzer()>>>?analyze("This?is?a?text?document?to?analyze.")?==?(...?????['this',?'is',?'text',?'document',?'to',?'analyze'])True在擬合過程中,分析器(analyzer)找到的每個項都會被分配一個唯一的整數(shù)索引,對應(yīng)于結(jié)果矩陣(resulting matrix)中的一列。此列的一些說明可以被檢索如下:>>>?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]]...)從特征名稱到列索引的逆映射存儲在vocabulary_屬性中:>>>?vectorizer.vocabulary_.get('document')1因此,在將來對transform方法的調(diào)用中,在訓(xùn)練語料庫中沒有看到的單詞將被完全忽略:>>>?vectorizer.transform(['Something?completely?new.']).toarray()
array([[0,?0,?0,?0,?0,?0,?0,?0,?0]]...)請注意,在前面的語料庫中,第一個和最后一個文檔具有完全相同的詞,因此被編碼成相同的向量,特別是我們丟失了最后一個文件是一個疑問形式的信息。為了保留局部的詞組順序信息,除了提取一元模型(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-grams?are?cool!')?==?(...?????['bi',?'grams',?'are',?'cool',?'bi?grams',?'grams?are',?'are?cool'])True由上述向量化器(vectorizer)提取的詞匯量會變得更大,同時可以在局部定位模式時消除歧義:>>>?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”的疑問形式只出現(xiàn)在最后一個文檔中:>>>?feature_index?=?bigram_vectorizer.vocabulary_.get('is?this')>>>?X_2[:,?feature_index]
array([0,?0,?0,?1]...)
TfidfTransformer(smooth_idf=False)同樣,請參閱參考文檔以獲取所有參數(shù)的詳細(xì)信息。讓我們以下面的數(shù)量來舉個例子。第一個術(shù)語(term)出現(xiàn)次數(shù)100%,因此可能不是很感興趣。另外兩個特征出現(xiàn)的次數(shù)僅僅比50%小一點,因此有可能是更加能夠代表文檔內(nèi)容的表示:>>>?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]])每一行都被標(biāo)準(zhǔn)化(歸一化)到單位歐式范數(shù):例如,我們可以計算在counts數(shù)組中的第一個文檔中第一個術(shù)語(term)的tf-idf:現(xiàn)在,如果我們重復(fù)上述計算過程去計算文檔中剩余的2個術(shù)語(terms),我們可以得到:原始tf-idfs的向量:然后,應(yīng)用歐幾里得(L2)范數(shù),我們可以在文檔1上得到以下tf-idfs:更進(jìn)一步,默認(rèn)參數(shù)smooth_idf=True會把添加“1”到分子和分母上,就好像又看到了另一篇文檔而這篇文檔恰好包含了所有的術(shù)語(term)僅僅一次,這么做就可以避免除零的異常發(fā)生了:使用這個修改版本, 文檔1中第三個術(shù)語(term)的tf-idf變?yōu)?.8473:然后通過L2標(biāo)準(zhǔn)化(歸一化)得到tf-idf變?yōu)?#xff1a;>>>?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方法計算出的每個特征的權(quán)重被保存在模型idf_屬性中:>>>?transformer.idf_
array([1.?...,?2.25...,?1.84...])由于tf–idf在文本特征提取中被經(jīng)常使用,我們還提供了另一個類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標(biāo)準(zhǔn)化(歸一化)通常非常有用,但是在某些情況下,二元出現(xiàn)標(biāo)記( binary occurrence markers)可能會提供更好的特征。這可以通過CountVectorizer的binary參數(shù)來實現(xiàn),特別是某些估計器(例如 Bernoulli Naive Bayes)顯式的使用離散的布爾隨機(jī)變量,而且非常短的文本很可能影響tf-idf值,而二元出現(xiàn)信息(binary occurrence info)更穩(wěn)定。通常情況下,調(diào)整特征提取參數(shù)的最佳方法是使用基于網(wǎng)格搜索的交叉驗證,例如通過將特征提取器與分類器進(jìn)行流水線化:
array([[1,?1,?1,?0,?1,?1,?1,?0],
???????[1,?1,?0,?1,?1,?1,?0,?1]])在上面的例子中,使用char_wb分析器,它只能從字邊界內(nèi)的字符(每側(cè)填充空格)創(chuàng)建n-gram。char分析器可以創(chuàng)建跨越單詞的n-gram:>>>?ngram_vectorizer?=?CountVectorizer(analyzer='char_wb',?ngram_range=(5,?5))>>>?ngram_vectorizer.fit_transform(['jumpy?fox'])
<1x4?sparse?matrix?of?type?'<...>numpy.int64'>'with?4?stored?elements?in?Compressed?Sparse?...?format>>>>?ngram_vectorizer.get_feature_names()?==?(...?????['?fox?',?'?jump',?'jumpy',?'umpy?'])True>>>?ngram_vectorizer?=?CountVectorizer(analyzer='char',?ngram_range=(5,?5))>>>?ngram_vectorizer.fit_transform(['jumpy?fox'])
<1x5?sparse?matrix?of?type?'<...>numpy.int64'>'with?5?stored?elements?in?Compressed?Sparse?...?format>>>>?ngram_vectorizer.get_feature_names()?==?(...?????['jumpy',?'mpy?f',?'py?fo',?'umpy?',?'y?fox'])True對于使用空格進(jìn)行單詞分離的語言,對于語言邊界感知變體char_wb尤其有用,因為在這種情況下,它會產(chǎn)生比原始char變體更少的噪音特征。對于這樣的語言,它可以增加使用這些特征訓(xùn)練的分類器的預(yù)測精度和收斂速度,同時保持關(guān)于拼寫錯誤和詞導(dǎo)出的穩(wěn)健性。雖然可以通過提取n-gram而不是單獨的單詞來保存一些局部定位信息,但是包含n-gram的單詞和袋子可以破壞文檔的大部分內(nèi)部結(jié)構(gòu),從而破壞了內(nèi)部結(jié)構(gòu)的大部分含義。為了處理自然語言理解的更廣泛的任務(wù),應(yīng)考慮到句子和段落的局部結(jié)構(gòu)。因此,許多這樣的模型出來的問題被稱為“結(jié)構(gòu)化輸出”問題, 這些問題目前不在scikit-learn的范圍之內(nèi)。
<4x10?sparse?matrix?of?type?'<...>numpy.float64'>'with?16?stored?elements?in?Compressed?Sparse?...?format>你可以看到從向量輸出中抽取了16個非0特征標(biāo)記:與之前由CountVectorizer在同一個樣本語料庫抽取的19個非0特征要少。差異是來自哈希方法的沖突,因為n_features參數(shù)的值比較低。在真實世界的環(huán)境下,n_features參數(shù)可以使用默認(rèn)值2 ** 20(將近100萬可能的特征)。如果內(nèi)存或者下游模型的大小是一個問題,那么選擇一個較小的值比如2 ** 18可能有一些幫助,而不需要為典型的文本分類任務(wù)引入太多額外的沖突。請注意,維度并不影響CPU的算法訓(xùn)練時間,訓(xùn)練是在操作CSR矩陣(LinearSVC(dual=True), Perceptron, SGDClassifier, PassiveAggressive),但是,它對CSC度量(matrices)(LinearSVC(dual=False), Lasso()等)算法有效。讓我們使用默認(rèn)設(shè)置再試一次:>>>?hv?=?HashingVectorizer()>>>?hv.transform(corpus)
<4x1048576?sparse?matrix?of?type?'<...>numpy.float64'>'with?19?stored?elements?in?Compressed?Sparse?...?format>沖突沒有再出現(xiàn),但是,代價是輸出空間的維度值非常大。當(dāng)然,這里使用的19詞以外的其他詞之前仍會有沖突。HashingVectorizer還有以下限制:
...>>>?vectorizer?=?CountVectorizer(tokenizer=my_tokenizer)>>>?vectorizer.build_analyzer()(u"Some...?punctuation!")?==?(...?????['some...',?'punctuation!'])True特別的,我們命名:
...>>>?vect?=?CountVectorizer(tokenizer=LemmaTokenizer())??(請注意,這不會過濾掉標(biāo)點符號。)例如,下面的示例將一些英國拼寫轉(zhuǎn)換為美國拼寫:>>>?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().build_tokenizer()...?????????return?lambda?doc:?list(to_british(tokenize(doc)))
...>>>?print(CustomVectorizer().build_analyzer()(u"color?colour"))
[...'color',?...'color']用于其他樣式的預(yù)處理;例子包括詞干(stemming),詞性還原(lemmatization)或規(guī)范化數(shù)字令牌(normalizing numerical tokens),后者在以下示例中進(jìn)行說明:
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]])現(xiàn)在讓我們嘗試通過在重疊區(qū)域進(jìn)行平均來從圖像塊重建原始圖像:>>>?reconstructed?=?image.reconstruct_from_patches_2d(patches,?(4,?4,?3))>>>?np.testing.assert_array_equal(one_image,?reconstructed)PatchExtractor類的工作方式與extract_patches_2d函數(shù)相同,只是它支持多幅圖像作為輸入。它被實現(xiàn)為一個估計器(estimator),因此它可以在管道(pipelines)中使用。請看:>>>?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)
1. 從字典加載特征(Loading features from dicts)
DictVectorizer可用于將以標(biāo)準(zhǔn)Python的dict對象的列表形式表示的特征數(shù)組轉(zhuǎn)換為scikit-learn估計器使用的NumPy/SciPy表示形式。雖然處理速度不是特別快,但Python的dict對象的優(yōu)點:易于使用,稀疏(缺失的特征不需要存儲), 并且除了值之外還存儲特征名稱。DictVectorizer實現(xiàn)了對標(biāo)稱型特征(分類特征(categorical),nominal特征,離散特征)的one-of-K或“one-hot”編碼。標(biāo)稱型特征是“屬性-值(attribute-value)”對,其中值(value)的取值被限制在一個不排序的可能性離散列表中。(例如,話題標(biāo)識符,對象類型,標(biāo)簽,名稱。)在下文中,“城市”是分類屬性,而“溫度”是傳統(tǒng)的數(shù)字特征:>>>?measurements?=?[...?????{'city':?'Dubai',?'temperature':?33.},...?????{'city':?'London',?'temperature':?12.},...?????{'city':?'San?Francisco',?'temperature':?18.},...?]>>>?from?sklearn.feature_extraction?import?DictVectorizer>>>?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=San?Francisco',?'temperature']DictVectorizer對于自然語言處理模型中的訓(xùn)練序列分類器來說也是一種有用的表示形式轉(zhuǎn)換,通常通過提取圍繞特定興趣詞的特征窗口來工作。例如,假設(shè)我們具有提取我們想要用作訓(xùn)練序列分類器(例如,塊)互補(bǔ)標(biāo)簽的部分語音(PoS)標(biāo)簽的一個算法。以下字典(dict)可以是在“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',...?????},...?????#?在真實的應(yīng)用中會提取想這樣的一個字典。...?]上述描述可以被矢量化為適合于傳遞給分類器的稀疏二維矩陣(可能在通過管道之后進(jìn)行 text.TfidfTransformer歸一化)>>>?vec?=?DictVectorizer()>>>?pos_vectorized?=?vec.fit_transform(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特征),其中大部分通常將會是0。為了使產(chǎn)生的數(shù)據(jù)結(jié)構(gòu)能夠適應(yīng)內(nèi)存,DictVectorizer類默認(rèn)使用scipy.sparse矩陣而不是numpy.ndarray。
2. 特征哈希(散列)化(Feature hashing)
FeatureHasher類是一種高速,低內(nèi)存消耗的矢量化方法,它使用一種稱為 特征哈希化(或稱為“散列法(hashing trick)”)的技術(shù),不是像矢量化方法那樣構(gòu)建訓(xùn)練中遇到的特征哈希表。FeatureHasher將哈希函數(shù)應(yīng)用于特征以便直接在樣本矩陣中確定它們的列索引。結(jié)果是以犧牲可檢測性(inspectability)為代價,帶來速度的提高和內(nèi)存使用的減少。哈希器(hasher)不記得輸入特征是什么樣的,也沒有inverse_transform辦法。由于散列函數(shù)可能導(dǎo)致(不相關(guān))特征之間的沖突,因此使用帶符號散列函數(shù),并且散列值的符號確定存儲在特征的輸出矩陣中值的符號。這樣,碰撞可能會抵消而不是累積錯誤,并且任何輸出特征的值的預(yù)期平均值為零。默認(rèn)情況下,此機(jī)制將使用alternate_sign=True啟用,尤其對小型哈希表的大小( n_features < 10000)特別有用。對于大哈希表的大小,可以禁用它,以便將輸出傳遞給估計器,如sklearn.naive_bayes.MultinomialNB或sklearn.feature_selection.chi2特征選擇器,這些特征選項器希望輸入是非負(fù)的。FeatureHasher接受三種類型的輸入:mappings,(feature, value)pairs,或 strings。其中mappings就像是python的 dict或在collections模塊中的字典變體。到底使用哪種參數(shù)依賴于構(gòu)造器的input_type參數(shù)。Mapping被當(dāng)作是由 (feature, value)組成的列表(list),而單個字符串有一個內(nèi)在的值1,因此['feat1', 'feat2', 'feat3']被解釋成 [('feat1', 1), ('feat2', 1), ('feat3', 1)]。如果一個特征在一個樣本中多次出現(xiàn),那么該特征關(guān)聯(lián)的值就會被累加起來,比如像這樣(('feat', 2)和('feat', 3.5)就變成了('feat', 5.5))。FeatureHasher的輸出總是CSR格式的一個 scipy.sparse矩陣。可以在文檔分類中使用特征哈希化,但是與text.CountVectorizer不同的是,FeatureHasher除了Unicode-to-UTF-8編碼之外, 不進(jìn)行單詞分割或任何其他預(yù)處理。請參閱下面的使用哈希特征化對大型文本語料庫進(jìn)行向量化,以獲取組合的標(biāo)記器/哈希器。作為一個例子,考慮一個單詞級的自然語言處理任務(wù),它需要從(token, part_of_speech)對中抽取特征。我們可以使用一個Python生成器函數(shù)來提取特征:def?token_features(token,?part_of_speech):if?token.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)然后,要傳遞到FeatureHasher.transform方法中的raw_X可以使用下面的代碼來構(gòu)建:raw_X = (token_features(tok, pos_tagger(tok)) for tok in corpus)并通過以下方式傳給哈希器:hasher?=?FeatureHasher(input_type='string')X?=?hasher.transform(raw_X)得到一個scipy.sparse類的矩陣X。這里需要注意的是,由于我們使用了Python的生成器,導(dǎo)致在特征抽取過程中引入了懶惰性:只有在哈希器有需求的時候tokens才會被處理。
2.1. 實現(xiàn)細(xì)節(jié)
FeatureHasher使用帶符號的MurmurHash3的32比特變體。作為其結(jié)果(也因為 scipy.sparse的限制),當(dāng)前支持的特征最大數(shù)量為。散列技巧(hashing trick)的原始形式源于Weinberger et al。使用兩個分開的哈希函數(shù),和ξ分別確定特征的列索引和符號。現(xiàn)有的實現(xiàn)是基于假設(shè):MurmurHash3的符號位與其他位獨立。由于使用簡單的模數(shù)將哈希函數(shù)轉(zhuǎn)換為列索引,建議使用2次冪作為n_features參數(shù),否則特征不會被均勻的分布到列中。參考文獻(xiàn):- Kilian Weinberger, Anirban Dasgupta, John Langford, Alex Smola and Josh Attenberg (2009). Feature hashing for large scale multitask learning. Proc. ICML.
- MurmurHash3.
3. 文本特征提取
3.1. 詞袋表示法
文本分析是機(jī)器學(xué)習(xí)算法的主要應(yīng)用領(lǐng)域,然而原始數(shù)據(jù)的符號文字序列不能直接傳遞給算法,因為它們大多數(shù)要求具有固定長度的數(shù)字矩陣特征向量,而不是具有可變長度的原始文本文檔。為解決這個問題,scikit-learn提供了從文本內(nèi)容中提取數(shù)字特征的最常見方法,即:- tokenizing令牌化,即對每個可能的詞令牌(token)分成字符串并賦予整型id,例如通過使用空格和標(biāo)點符號作為令牌分隔符。
- counting統(tǒng)計計數(shù),即數(shù)出每個文檔中令牌的出現(xiàn)次數(shù)。
- normalizing標(biāo)準(zhǔn)化,即對大多數(shù)樣本/文檔中出現(xiàn)的重要性遞減的token進(jìn)行歸一化和加權(quán)
- 每個單獨的令牌發(fā)生頻率(歸一化或不歸一化)被視為一個特征 。
- 給定文檔中所有的令牌頻率向量被看做一個多元樣本
3.2. 稀疏性
由于大多數(shù)文本文檔通常只使用語料庫的詞向量全集中的一個小子集,所以得到的矩陣將具有許多零特征值(通常大于99%)。例如,10,000個短文本文檔(如電子郵件)的集合將使用總共100,000個獨特詞大小的詞匯,而每個文檔將單獨使用100到1000個獨特的單詞。為了能夠?qū)⑦@樣的矩陣存儲在存儲器中,并且還可以加速代數(shù)的矩陣/向量運(yùn)算,實現(xiàn)通常將使用諸如scipy.sparse包中的稀疏實現(xiàn)。3.3. 常見Vectorizer的用法
CountVectorizer在單個類中實現(xiàn)詞語切分(tokenization)和出現(xiàn)頻數(shù)統(tǒng)計(occurrence counting):>>>?from?sklearn.feature_extraction.text?import?CountVectorizer該模型具有許多參數(shù),但參數(shù)的默認(rèn)初始值是相當(dāng)合理的(有關(guān)詳細(xì)信息,請參見參考文檔):>>>?vectorizer?=?CountVectorizer()>>>?vectorizerCountVectorizer()我們用該類對一個簡約的文本語料庫進(jìn)行分詞(tokenize)和統(tǒng)計單詞出現(xiàn)頻數(shù):>>>?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>默認(rèn)配置是通過提取至少包含2個字母的單詞來對字符串進(jìn)行分詞。可以顯式調(diào)用能做到這一步的函數(shù):>>>?analyze?=?vectorizer.build_analyzer()>>>?analyze("This?is?a?text?document?to?analyze.")?==?(...?????['this',?'is',?'text',?'document',?'to',?'analyze'])True在擬合過程中,分析器(analyzer)找到的每個項都會被分配一個唯一的整數(shù)索引,對應(yīng)于結(jié)果矩陣(resulting matrix)中的一列。此列的一些說明可以被檢索如下:>>>?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]]...)從特征名稱到列索引的逆映射存儲在vocabulary_屬性中:>>>?vectorizer.vocabulary_.get('document')1因此,在將來對transform方法的調(diào)用中,在訓(xùn)練語料庫中沒有看到的單詞將被完全忽略:>>>?vectorizer.transform(['Something?completely?new.']).toarray()
array([[0,?0,?0,?0,?0,?0,?0,?0,?0]]...)請注意,在前面的語料庫中,第一個和最后一個文檔具有完全相同的詞,因此被編碼成相同的向量,特別是我們丟失了最后一個文件是一個疑問形式的信息。為了保留局部的詞組順序信息,除了提取一元模型(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-grams?are?cool!')?==?(...?????['bi',?'grams',?'are',?'cool',?'bi?grams',?'grams?are',?'are?cool'])True由上述向量化器(vectorizer)提取的詞匯量會變得更大,同時可以在局部定位模式時消除歧義:>>>?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”的疑問形式只出現(xiàn)在最后一個文檔中:>>>?feature_index?=?bigram_vectorizer.vocabulary_.get('is?this')>>>?X_2[:,?feature_index]
array([0,?0,?0,?1]...)
3.3.1.使用停用詞(stop words)
停用詞是指諸如“和(and)”,“該(the)”,“他(him)”之類的詞,它們被認(rèn)為在表示文本內(nèi)容方面沒有提供任何信息,可以將其刪除,以避免將其理解為對預(yù)測有用的信息。但是,有時候,這些類似的單詞可用于預(yù)測,例如在對寫作風(fēng)格或性格進(jìn)行分類時。我們提供的“英語”停用詞列表中有幾個已知問題。它并非是通用的“一刀切”的解決方案,因為某些任務(wù)可能需要一個定制的解決方案。有關(guān)更多詳細(xì)信息,請參見[NQY18]。在選擇停用詞列表時請多加注意。流行的停用詞列表可能包含對某些任務(wù)(例如計算機(jī))具有高度信息意義的詞。您還應(yīng)該確保停用詞列表的預(yù)處理和令牌化和矢量化器中使用的預(yù)處理和令牌化相同。例如,這個詞we’ve被CountVectorizer的默認(rèn)詞令牌生成器分成we和ve,所以當(dāng)we’ve在進(jìn)行文本轉(zhuǎn)化時,如果we’ve在停用詞stop_words中,但ve不在的話,ve將被會保留。我們的向量化器將嘗試識別并警告某些不一致的地方。參考文獻(xiàn)[NQY18]J. Nothman, H. Qin and R. Yurchak (2018). “Stop Word Lists in Free Open-source Software Packages”. In Proc. Workshop for NLP Open Source Software3.4. Tf–idf 術(shù)語權(quán)重(term weighting)
在一個大的文本語料庫中,一些單詞將出現(xiàn)很多次(例如,英文的“the”,“a”,“is”),因此對文檔的實際內(nèi)容沒有什么有意義的信息。如果我們直接把計數(shù)數(shù)據(jù)提供給分類器,那么這些非常頻繁的詞組會掩蓋住那些我們感興趣但卻很少出現(xiàn)的詞。為了重新計算特征權(quán)重,并將其轉(zhuǎn)化為適合分類器使用的浮點值,使用tf-idf變換是非常常見的。Tf表示術(shù)語頻率(term-frequency),而tf–idf表示術(shù)語頻率(term-frequency)乘以逆文檔頻率(inverse document-frequency):使用TfidfTransformer的默認(rèn)設(shè)置,TfidfTransformer(norm='l2', use_idf=True, smooth_idf=True,sublinear_tf=False),術(shù)語的頻率(term frequency),一個術(shù)語(term)出現(xiàn)在給定文檔的次數(shù),被乘以idf分量,計算如下其中是文檔的總數(shù)量,是包含某個術(shù)語的文檔的數(shù)量。然后計算出的tf-idf向量用歐式范數(shù)歸一化,如下所示:上面所介紹的就是用于信息檢索領(lǐng)域的原始的術(shù)語(term)加權(quán)機(jī)制。該術(shù)語(term)加權(quán)機(jī)制在文檔分類和聚類中的表現(xiàn)也比較好。接下來的各小節(jié)包含了對tf-idfs的進(jìn)一步解釋以及實驗案例來說明tf-idfs是如何準(zhǔn)確計算出來的,以及scikit-learn的TfidfTransformer是如何計算tf-idfs的。還有TfidfVectorizer與標(biāo)準(zhǔn)的idf的定義的細(xì)微差別。標(biāo)準(zhǔn)的idf的定義如下所示:在TfidfTransformer和TfidfVectorizer,如果設(shè)置了smooth_idf=False的話,那么數(shù)量“1”就被加到idf上而不是idf的分母上:該標(biāo)準(zhǔn)化(歸一化)由TfidfTransformer類實現(xiàn)的:>>>?from?sklearn.feature_extraction.text?import?TfidfTransformer>>>?transformer?=?TfidfTransformer(smooth_idf=False)>>>?transformerTfidfTransformer(smooth_idf=False)同樣,請參閱參考文檔以獲取所有參數(shù)的詳細(xì)信息。讓我們以下面的數(shù)量來舉個例子。第一個術(shù)語(term)出現(xiàn)次數(shù)100%,因此可能不是很感興趣。另外兩個特征出現(xiàn)的次數(shù)僅僅比50%小一點,因此有可能是更加能夠代表文檔內(nèi)容的表示:>>>?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]])每一行都被標(biāo)準(zhǔn)化(歸一化)到單位歐式范數(shù):例如,我們可以計算在counts數(shù)組中的第一個文檔中第一個術(shù)語(term)的tf-idf:現(xiàn)在,如果我們重復(fù)上述計算過程去計算文檔中剩余的2個術(shù)語(terms),我們可以得到:原始tf-idfs的向量:然后,應(yīng)用歐幾里得(L2)范數(shù),我們可以在文檔1上得到以下tf-idfs:更進(jìn)一步,默認(rèn)參數(shù)smooth_idf=True會把添加“1”到分子和分母上,就好像又看到了另一篇文檔而這篇文檔恰好包含了所有的術(shù)語(term)僅僅一次,這么做就可以避免除零的異常發(fā)生了:使用這個修改版本, 文檔1中第三個術(shù)語(term)的tf-idf變?yōu)?.8473:然后通過L2標(biāo)準(zhǔn)化(歸一化)得到tf-idf變?yōu)?#xff1a;>>>?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方法計算出的每個特征的權(quán)重被保存在模型idf_屬性中:>>>?transformer.idf_
array([1.?...,?2.25...,?1.84...])由于tf–idf在文本特征提取中被經(jīng)常使用,我們還提供了另一個類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標(biāo)準(zhǔn)化(歸一化)通常非常有用,但是在某些情況下,二元出現(xiàn)標(biāo)記( binary occurrence markers)可能會提供更好的特征。這可以通過CountVectorizer的binary參數(shù)來實現(xiàn),特別是某些估計器(例如 Bernoulli Naive Bayes)顯式的使用離散的布爾隨機(jī)變量,而且非常短的文本很可能影響tf-idf值,而二元出現(xiàn)信息(binary occurrence info)更穩(wěn)定。通常情況下,調(diào)整特征提取參數(shù)的最佳方法是使用基于網(wǎng)格搜索的交叉驗證,例如通過將特征提取器與分類器進(jìn)行流水線化:
- 用于文本特征提取和評估管道(pipeline)案例
3.5. 解碼文本文件(Decoding text files)
文本由字符組成,但文件由字節(jié)組成。字節(jié)轉(zhuǎn)化成字符依照一定的編碼(encoding)方式。為了在Python中的使用文本文檔,這些字節(jié)必須被解碼為Unicode的字符集。常用的編碼方式有ASCII,Latin-1(西歐),KOI8-R(俄語)和通用編碼 UTF-8和UTF-16,此外還有許多其他的編碼存在。**注意:**編碼也可以稱為‘字符集’,但是這個術(shù)語不太準(zhǔn)確:單個字符集可能存在多個編碼。scikit-learn中的文本特征提取器知道如何解碼文本文件,但前提是您告訴他們文件的編碼方式。為此,CountVectorizer需要一個encoding參數(shù)。對于現(xiàn)代文本文件,正確的編碼可能是UTF-8,因此它是默認(rèn)的解碼方式 (encoding="utf-8")。如果正在加載的文本不是使用UTF-8進(jìn)行編碼,則會得到UnicodeDecodeError。向量化器可以通過設(shè)定decode_error參數(shù)設(shè)置為"ignore"或"replace"來避免拋出解碼錯誤。有關(guān)詳細(xì)信息,請參閱Python函數(shù) bytes.decode的文檔(在Python提示符下輸入 help(bytes.decode))。如果您在解碼文本時遇到問題,請嘗試以下操作:- 找出文本的實際編碼是什么。該文件可能帶有標(biāo)題或自述文件(README),來告訴您編碼,或者您可以根據(jù)文本的來源來推斷編碼方式。
- 您可能可以使用UNIX命令file,來找出它一般使用什么樣的編碼。Python的chardet模塊附帶一個名為chardetect.py的腳本,它會猜測具體的編碼,盡管你不能總是指望猜測是正確的。
- 你可以嘗試UTF-8并忽略錯誤。您可以使用bytes.decode(errors='replace')對字節(jié)字符串進(jìn)行解碼,用無意義字符替換所有解碼錯誤,或在向量化器中設(shè)置decode_error='replace'。這可能會損壞特征的有用性。
- 真實文本可能來自各種使用不同編碼的來源,或者甚至以不同的編碼進(jìn)行粗略解碼。這在從Web檢索的文本中是常見的。Python包ftfy可以自動分類出一些解碼錯誤,因此您可以嘗試將未知文本解碼為latin-1,然后使用ftfy來修復(fù)錯誤。
- 如果文本的編碼的混合,那么它很難整理分類(20個新聞組數(shù)據(jù)集的情況),您可以把它們回到簡單的單字節(jié)編碼,如latin-1 。某些文本可能顯示不正確,但至少相同的字節(jié)序列將始終代表相同的特征。.
3.6. 應(yīng)用和案例
詞匯表達(dá)方式相當(dāng)簡單,但在實踐中卻非常有用。特別是在有監(jiān)督的應(yīng)用中,它能夠把快速和可擴(kuò)展的線性模型組合來訓(xùn)練文檔分類器,例如:- 使用稀疏特征對文本文檔進(jìn)行分類
- 使用k-means聚類文本文檔
- 使用非負(fù)矩陣分解和潛在狄利克雷分配進(jìn)行主題提取
3.7. 詞袋表示法的局限性
單個單詞(unigrams)的集合無法捕獲短語和多字表達(dá),有效地忽略了單詞順序依賴。另外,這個單詞模型不包含潛在的拼寫錯誤或詞匯推倒。N-grams 可以來救場!不去構(gòu)建一個簡單的單個單詞(unigrams)集合 (n=1),而是使用二元單詞(bigrams)集合 (n=2),計算連續(xù)單詞。還可以考慮n-gram的集合,這是一種對拼寫錯誤和派生有彈性的表示。例如,假設(shè)我們正在處理兩個文檔的語料庫:['words', 'wprds']。第二個文件包含words一詞的拼寫錯誤。一個簡單的單詞表示將把這兩個視為非常不同的文檔,兩個可能的特征都是不同的。然而,一個2-gram的表示可以找到匹配的文檔中的8個特征中的4個,這可能有助于優(yōu)選的分類器更好地決定:>>>?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]])在上面的例子中,使用char_wb分析器,它只能從字邊界內(nèi)的字符(每側(cè)填充空格)創(chuàng)建n-gram。char分析器可以創(chuàng)建跨越單詞的n-gram:>>>?ngram_vectorizer?=?CountVectorizer(analyzer='char_wb',?ngram_range=(5,?5))>>>?ngram_vectorizer.fit_transform(['jumpy?fox'])
<1x4?sparse?matrix?of?type?'<...>numpy.int64'>'with?4?stored?elements?in?Compressed?Sparse?...?format>>>>?ngram_vectorizer.get_feature_names()?==?(...?????['?fox?',?'?jump',?'jumpy',?'umpy?'])True>>>?ngram_vectorizer?=?CountVectorizer(analyzer='char',?ngram_range=(5,?5))>>>?ngram_vectorizer.fit_transform(['jumpy?fox'])
<1x5?sparse?matrix?of?type?'<...>numpy.int64'>'with?5?stored?elements?in?Compressed?Sparse?...?format>>>>?ngram_vectorizer.get_feature_names()?==?(...?????['jumpy',?'mpy?f',?'py?fo',?'umpy?',?'y?fox'])True對于使用空格進(jìn)行單詞分離的語言,對于語言邊界感知變體char_wb尤其有用,因為在這種情況下,它會產(chǎn)生比原始char變體更少的噪音特征。對于這樣的語言,它可以增加使用這些特征訓(xùn)練的分類器的預(yù)測精度和收斂速度,同時保持關(guān)于拼寫錯誤和詞導(dǎo)出的穩(wěn)健性。雖然可以通過提取n-gram而不是單獨的單詞來保存一些局部定位信息,但是包含n-gram的單詞和袋子可以破壞文檔的大部分內(nèi)部結(jié)構(gòu),從而破壞了內(nèi)部結(jié)構(gòu)的大部分含義。為了處理自然語言理解的更廣泛的任務(wù),應(yīng)考慮到句子和段落的局部結(jié)構(gòu)。因此,許多這樣的模型出來的問題被稱為“結(jié)構(gòu)化輸出”問題, 這些問題目前不在scikit-learn的范圍之內(nèi)。
3.8. 用哈希技巧矢量化大型語料庫
上述向量化方案是簡單的,但是它存在從字符串令牌到整數(shù)特征索引的內(nèi)存映射( vocabulary_屬性),在處理大型數(shù)據(jù)集時會引起幾個問題:- 語料庫越大,詞匯量越大,使用的內(nèi)存也越大。
- 擬合(fitting)需要根據(jù)原始數(shù)據(jù)集的大小等比例分配中間數(shù)據(jù)結(jié)構(gòu)的大小。
- 構(gòu)建詞映射需要完整的傳遞數(shù)據(jù)集,因此不可能以嚴(yán)格在線的方式擬合文本分類器。
- pickling和un-pickling的vocabulary的向量器會非常慢(通常比pickling/un-pickling平面數(shù)據(jù)結(jié)構(gòu)(比如同等大小的Numpy數(shù)組))還要慢。
- 將向量化任務(wù)分隔成并行的子任務(wù)很不容易實現(xiàn),因為vocabulary_屬性要共享狀態(tài)有一個細(xì)顆粒度的同步障礙:從標(biāo)記字符串中映射特征索引與每個標(biāo)記的首次出現(xiàn)順序是獨立的, 因此應(yīng)該被共享,在這點上并行工作器(worker)的性能受到了損害,使他們比串行更慢。
<4x10?sparse?matrix?of?type?'<...>numpy.float64'>'with?16?stored?elements?in?Compressed?Sparse?...?format>你可以看到從向量輸出中抽取了16個非0特征標(biāo)記:與之前由CountVectorizer在同一個樣本語料庫抽取的19個非0特征要少。差異是來自哈希方法的沖突,因為n_features參數(shù)的值比較低。在真實世界的環(huán)境下,n_features參數(shù)可以使用默認(rèn)值2 ** 20(將近100萬可能的特征)。如果內(nèi)存或者下游模型的大小是一個問題,那么選擇一個較小的值比如2 ** 18可能有一些幫助,而不需要為典型的文本分類任務(wù)引入太多額外的沖突。請注意,維度并不影響CPU的算法訓(xùn)練時間,訓(xùn)練是在操作CSR矩陣(LinearSVC(dual=True), Perceptron, SGDClassifier, PassiveAggressive),但是,它對CSC度量(matrices)(LinearSVC(dual=False), Lasso()等)算法有效。讓我們使用默認(rèn)設(shè)置再試一次:>>>?hv?=?HashingVectorizer()>>>?hv.transform(corpus)
<4x1048576?sparse?matrix?of?type?'<...>numpy.float64'>'with?19?stored?elements?in?Compressed?Sparse?...?format>沖突沒有再出現(xiàn),但是,代價是輸出空間的維度值非常大。當(dāng)然,這里使用的19詞以外的其他詞之前仍會有沖突。HashingVectorizer還有以下限制:
- 由于執(zhí)行映射的哈希函數(shù)具有單向性,因此無法反轉(zhuǎn)模型(沒有inverse_transform方法的模型),也不能訪問原始的字符串表征。
- 它不提供IDF加權(quán),因為這會在模型中引入狀態(tài)。如果需要,可以將TfidfTransformer添加到管道中。
3.9. 使用 HashingVectorizer執(zhí)行核外scaling
使用HashingVectorizer的一個有趣的開發(fā)是執(zhí)行核外(out-of-core)縮放的能力。這意味著我們可以從無法放入電腦主內(nèi)存的數(shù)據(jù)中進(jìn)行學(xué)習(xí)。實現(xiàn)核外擴(kuò)展的一個策略是將數(shù)據(jù)以流的方式以一小批提交給估計器。每批的向量化都是用HashingVectorizer。這樣來保證估計器的輸入空間的維度是相等的,因此任何時間使用的內(nèi)存數(shù)都限定在小頻次的大小。盡管用這種方法可以處理的數(shù)據(jù)沒有限制,但是從實用角度學(xué)習(xí)時間受到想要在這個任務(wù)上花費的CPU時間的限制。有關(guān)文本分類任務(wù)中核心外縮放的完整示例,請參見文本文檔的核外分類。3.10. 自定義向量化器類
通過將一個可調(diào)用對象傳遞給向量化器的構(gòu)造函數(shù),可以自定義其行為:>>>?def?my_tokenizer(s):...?????return?s.split()...>>>?vectorizer?=?CountVectorizer(tokenizer=my_tokenizer)>>>?vectorizer.build_analyzer()(u"Some...?punctuation!")?==?(...?????['some...',?'punctuation!'])True特別的,我們命名:
- preprocessor:可以將整個文檔作為輸入(作為單個字符串)的可調(diào)用對象,并返回文檔可能轉(zhuǎn)換的版本,它仍然是整個字符串。這可以用于刪除HTML標(biāo)簽,小寫整個文檔等。
- tokenizer:一個可從預(yù)處理器接收輸出并將其分成標(biāo)記的可調(diào)用對象,然后返回這些列表。
- analyzer:一個可替代預(yù)處理程序和標(biāo)記器的可調(diào)用程序。默認(rèn)analyzer都會調(diào)用預(yù)處理器,但是自定義analyzer將會跳過這個。N-gram提取和停止字過濾在analyzer級進(jìn)行,因此定制analyzer可能必須重現(xiàn)這些步驟。
- 如果文檔是由外部程序包預(yù)先標(biāo)記的,則將它們存儲在文件(或字符串)中,并用空格分隔,傳遞 analyzer=str.split
- scikit-learn代碼庫中不包含花式詞令牌分析,例如詞干,詞根分解,化合物分解,基于詞性的過濾等,但可以通過自定義詞令牌化器或分析器來添加。這是一個CountVectorizer使用NLTK的標(biāo)記器(tokenizer)和詞條分解器(lemmatizer):
...>>>?vect?=?CountVectorizer(tokenizer=LemmaTokenizer())??(請注意,這不會過濾掉標(biāo)點符號。)例如,下面的示例將一些英國拼寫轉(zhuǎn)換為美國拼寫:>>>?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().build_tokenizer()...?????????return?lambda?doc:?list(to_british(tokenize(doc)))
...>>>?print(CustomVectorizer().build_analyzer()(u"color?colour"))
[...'color',?...'color']用于其他樣式的預(yù)處理;例子包括詞干(stemming),詞性還原(lemmatization)或規(guī)范化數(shù)字令牌(normalizing numerical tokens),后者在以下示例中進(jìn)行說明:
- 使用“光譜共聚類(Spectral Co-clustering algorithm)”算法對文檔進(jìn)行聚類
4. 圖像特征提取
4.1. 圖像塊提取
extract_patches_2d函數(shù)從存儲為二維數(shù)組的灰度圖像或三維數(shù)組的彩色圖像中提取圖像塊(patches)。彩色圖像的顏色信息在第三個維度中存放。如果要從所有的圖像塊(patches)中重建圖像,請使用reconstruct_from_patches_2d函數(shù)。例如,讓我們使用生成具有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]??#?一張假的RGB圖片的R通道。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]])現(xiàn)在讓我們嘗試通過在重疊區(qū)域進(jìn)行平均來從圖像塊重建原始圖像:>>>?reconstructed?=?image.reconstruct_from_patches_2d(patches,?(4,?4,?3))>>>?np.testing.assert_array_equal(one_image,?reconstructed)PatchExtractor類的工作方式與extract_patches_2d函數(shù)相同,只是它支持多幅圖像作為輸入。它被實現(xiàn)為一個估計器(estimator),因此它可以在管道(pipelines)中使用。請看:>>>?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)
4.2. 圖像的連接圖
scikit-learn中有幾個估計器(estimators)可以使用特征或樣本之間的連接信息(connectivity information)。例如Ward clustering (層次聚類(Hierarchical clustering))可以只把相鄰像素聚集在一起,從而形成連續(xù)的斑塊:sphx_glr_plot_coin_ward_segmentation_1由于這個目的,這些估計器使用一個連接性矩陣,給出哪些樣本是連接著的。函數(shù)img_to_graph從2D或3D圖像返回這樣的矩陣。同樣,grid_to_graph函數(shù)為給定形狀的圖像構(gòu)建連接矩陣。這些矩陣可用于在使用連接信息的估計器中強(qiáng)加連接,例如Ward clustering (層次聚類(Hierarchical clustering)),而且還要構(gòu)建預(yù)計算的內(nèi)核或相似矩陣。注意:例子- 硬幣圖像上的結(jié)構(gòu)化Ward層次聚類演示
- 光譜聚類(Spectral clustering)用于圖像分割
- 特征集聚與單變量選擇
文壹由“伴編輯器”提供技術(shù)支持
☆☆☆為方便大家查閱,小編已將scikit-learn學(xué)習(xí)路線專欄文章統(tǒng)一整理到公眾號底部菜單欄,同步更新中,關(guān)注公眾號,點擊左下方“系列文章”,如圖:歡迎大家和我一起沿著scikit-learn文檔這條路線,一起鞏固機(jī)器學(xué)習(xí)算法基礎(chǔ)。(添加微信:mthler,備注:sklearn學(xué)習(xí),一起進(jìn)【sklearn機(jī)器學(xué)習(xí)進(jìn)步群】開啟打怪升級的學(xué)習(xí)之旅。)
總結(jié)
以上是生活随笔為你收集整理的python pos函数_使用python+sklearn实现特征提取的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。