scikit-learn中的自動模型選擇和複合特徵空間

2020-12-26 deephub

使用scikit-learn管道自動組合文本和數字數據

有時,機器學習模型的可能配置即使沒有上千種,也有數百種,這使得手工找到最佳配置的可能性變得不可能,因此自動化是必不可少的。在處理複合特徵空間時尤其如此,在複合特徵空間中,我們希望對數據集中的不同特徵應用不同的轉換。一個很好的例子是將文本文檔與數字數據相結合,然而,在scikit-learn中,我找不到關於如何自動建模這種類型的特徵空間的信息。

使用scikit-learn管道可以更有效地工作,而不是手動將文本轉換成詞袋,然後再手動添加一些數字列。這篇文章將告訴你如何去做。

使用管道允許你將一系列轉換步驟和評估器(分類器或回歸器)視為單個模型,稱為複合評估器。這不僅使你的代碼保持整潔並防止訓練集和測試集之間的信息洩漏,而且還允許你將轉換步驟視為模型的超參數,然後通過網格搜索在超參數空間中優化模型。這意味著你可以在文本數據的同時試驗不同的數值特徵組合,以及不同的文本處理方法,等等。

在接下來的內容中,你將看到如何構建這樣一個系統:將帶標籤的文本文檔集合作為輸入;自動生成一些數值特徵;轉換不同的數據類型;將數據傳遞給分類器;然後搜索特徵和轉換的不同組合,以找到性能最佳的模型。

選型

我使用的是垃圾簡訊數據集,可以從UCI機器學習庫下載,它包含兩列:一列簡訊文本和一個相應的標籤列,包含字符串' Spam '和' ham ',這是我們必須預測的。和往常一樣,整個項目代碼都可以在GitHub上找到(https://github.com/job9931/Blog-notebooks/tree/main/automatedmodelselection)。

第一步是定義要應用於數據集的轉換。要在scikit-learn管道中包含數據轉換,我們必須把它寫成類,而不是普通的Python函數;一開始這可能聽起來令人生畏,但它很簡單。另一種方法是簡單地定義一個普通的Python函數,並將其傳遞給FunctionTransformer類,從而將其轉換為一個scikit-learn transformer對象。然而,在這裡,我將向你展示更多的手工方法,這樣你就可以看到實際發生了什麼,因為我認為它有助於理解scikit-learn是如何工作的。

你創建一個類,它繼承了scikit-learn提供的BaseEstimator和TransformerMixin類,它們提供了創建與scikit-learn管道兼容的對象所需的屬性和方法。然後,在init()方法中包含函數參數作為類屬性,並使用將用於轉換數據集的函數體覆蓋transform()方法。我在下面提供了三個例子。

from sklearn.base import BaseEstimator, TransformerMixinclass CountWords(BaseEstimator,TransformerMixin):#creates a dataframe from a series of text documents by creating a new column named n_words, #which contains the number of words in each document def __init__(self,new_col_name): self.new_col_name = new_col_name def fit(self,series,y=None): return self def transform(self,series): n_words_col = series.apply(lambda x: len(x.split(' '))).rename(self.new_col_name) return pd.concat([series, n_words_col], axis=1)class MeanWordLength(BaseEstimator,TransformerMixin): #creates a column mean length of words in message def __init__(self,text_column): self.text_column = text_column def fit(self,dataframe,y=None): return self def transform(self,dataframe): dataframe['mean_word_length'] = dataframe[self.text_column].apply(lambda x: sum(map(len,x.split(' ') ))/len(x.split(' '))) return dataframeclass FeatureSelector(BaseEstimator,TransformerMixin): #creates a new dataframe using only columns listed in attribute_names def __init__(self,attribute_names): self.attribute_names = attribute_names def fit(self, dataframe, y=None): return self def transform(self, dataframe): return dataframe[self.attribute_names].values

管道中使用的自定義轉換器對象。在每個示例中,fit()方法不執行任何操作,所有工作都體現在transform()方法中。

前兩個轉換符用於創建新的數字特徵,這裡我選擇使用文檔中的單詞數量和文檔中單詞的平均長度作為特徵。由於我們的數據集只包含兩列,文本和標籤,我們的文本在分離標籤列之後被存儲為熊貓系列,我們應該在項目的一開始就這樣做。因此,CountWords.transform()被設計為接受一個序列並返回一個數據流,因為我將使用它作為管道中的第一個轉換器。

final transformer FeatureSelector將允許我們將各種特性作為模型的超參數。它的transform()方法接受列名列表,並返回一個僅包含這些列的DataFrame;通過向它傳遞不同的列名列表,我們可以在不同的特徵空間中搜索以找到最佳的一個。這三個轉換器提供了我們構建管道所需的所有附加功能。

構建管道

最終的管道由三個組件構成:初始管道對象、ColumnTransformer對象和估計器。第二個組件ColumnTransformer是0.20版本中引入的一個方便的類,它允許你對數據集的指定列應用單獨的轉換。在這裡,我們將使用它將CountVectorizer應用到文本列,並將另一個管道num_pipeline應用到數值列,該管道包含FeatureSelector和scikit-learn的SimpleImputer類。整個管道結構如圖所示:

管道示意圖。整個對象(稱為複合估計器)可以用作模型;所有的轉換器和估計器對象以及它們的參數,都成為我們模型的超參數。

工作流程如下

一系列文檔進入管道,CountWords和MeanWordLength在管道中創建兩個名為nwords和meanword_length的數字列。文本列被傳遞給CountVectorizer,而nwords和meanword_length首先通過FeatureSelector,然後是SimpleImputer。轉換後的數據集被傳遞給估計器對象。from sklearn.pipeline import Pipelinefrom sklearn.compose import ColumnTransformerfrom sklearn.impute import SimpleImputerfrom sklearn.feature_extraction.text import CountVectorizerfrom sklearn.svm import SVC#Define the names of the text and numerical featurestext_features = 'text'numerical_features = ['n_words','mean_word_length']#Create the initial pipeline which generates numerical columnspipeline_1 = Pipeline([('n_words',CountWords('n_words')), ('mean_length',MeanWordLength('text'))])#Then use ColumnTransformer to process the numerical columns and the text column separately.#We define and apply num_pipeline to the numerical columns and CountVectorizer to the text columnnum_pipeline = Pipeline([('selector',FeatureSelector(numerical_features)), ('imp',SimpleImputer())])pipeline_2 = ColumnTransformer([ ("txt", CountVectorizer(), 'text'), ("num", num_pipeline,['n_words','mean_word_length']), ])#Build the final pipeline using pipeline_1 and pipeline_2 and an estimator, in this case SVC()pipeline = Pipeline([('add_numerical',pipeline_1), ('transform',pipeline_2), ('clf',SVC())])

最終的管道由初始化對象、ColumnTransformer對象和估計器對象組成。注意,ColumnTransformer可以將整個管道應用於某些列。

在上面的代碼示例中,我們使用CountVectorizer和SimpleImputer的默認參數,同時保留數字列,並使用支持向量分類器作為估計器。這最後一個管道是我們的複合估計器,它裡面的每個對象,以及這些對象的參數,都是一個超參數,我們可以自由地改變它。這意味著我們可以搜索不同的特徵空間、不同的向量化設置和不同的估計器對象。

通過網格搜索選擇最佳模型

使用複合估計器設置,很容易找到最佳執行模型;你所需要做的就是創建一個字典,指定想要改變的超參數和想要測試的值。然後將其傳遞給scikit-learn的GridSearchCV類,該類對每個超參數值組合使用交叉驗證來評估模型,然後返回最好的。

from sklearn.model_selection import GridSearchCV#params is a dictionary, the keys are the hyperparameter and the vaules are a list of values#to search over.params = [{'transform__txt__max_features':[None,100,10], 'transform__num__selector__attribute_names': [['n_words'], ['mean_word_length'], ['n_words','mean_word_length']]} ]#GridSearchCV by default stratifies our cross-validation#and retrains model on the best set of hyperparametersmodel = GridSearchCV(pipeline,params,scoring='balanced_accuracy',cv=5)model.fit(X_train, y_train)#display all of the results of the grid searchprint(model.cv_results_)#display the mean scores for each combination of hyperparametersprint(model.cv_results_[model.cv_results_['mean_test_score']])

參數網格被定義為一個字典,鍵是超參數,值是要搜索的值的列表。然後將其與複合估計數器一起傳遞給GridSearchCV,並將其與訓練數據相匹配。

我們的複合估計器總共有65個可調參數,但是,這裡只改變了兩個參數:使用的數字列和CountVectorizer的max_features參數,該參數設置詞彙表中使用的單詞的最大數量。在代碼中,你可以看到如何獲得所有可用超參數的列表。下面是繪製在超參數空間上的平均平衡精度的可視化圖。

當我們只使用一個數字列nwords並使用詞彙表中的所有單詞(即maxfeatures = None)時,可以獲得最佳性能。在交叉驗證期間,該模型的平衡精度為0.94,在測試集上評估時為0.93。注意,如果你自己運行筆記本,確切的數字可能會改變。

在超參數網格上繪製了平衡精度圖,顯示了模型性能如何在超參數空間上變化。

總結

我們已經討論了很多,特別是,如何通過設置一個複合評估器來自動化整個建模過程,複合評估器是包含在單個管道中的一系列轉換和評估器。這不僅是一個很好的實踐,而且是搜索大型超參數空間的唯一可行方法,在處理複合特徵空間時經常出現這種情況。我們看到了將文本數據與數字數據組合在一起的示例,但是對於任何數據類型都可以很容易地遵循相同的過程,從而使你能夠更快、更有效地工作。

作者:Oliver Batey

deephub翻譯組

相關焦點

  • 機器學習也能套模版:在線選擇模型和參數,一鍵生成demo
    同時,對於初學者來說,這也是一個非常好的工具。不過,開發者說,有更多功能正在路上,比如目標檢測、語義分割等任務目標。而目前,Web支持的框架有PyTorch和scikit-learn,如下圖所示,在選定框架後,模版會自動變換。
  • 超參數調整實戰:scikit-learn配合XGBoost的競賽top20策略
    在過去的幾年中,XGBoost被廣泛用於表格數據推斷,並且贏得了數百個挑戰。但是,僅僅通過XGBoost並不能完成完成整的解決方案,同樣的模型為什麼有些人能獲得更好的準確性呢?除了經驗方面的差異,還有一個事實,那就是他們優化了超參數!因此,我們今天將告訴您如何獲取特定數據集的最佳超參數。
  • 回歸、分類與聚類:三大方向剖解機器學習算法的優缺點(附Python和R...
    深度神經網絡在圖像、音頻和文本等數據上表現優異,並且該算法也很容易對新數據使用反向傳播算法更新模型參數。它們的架構(即層級的數量和結構)能夠適應於多種問題,並且隱藏層也減少了算法對特徵工程的依賴。缺點:深度學習算法通常不適合作為通用目的的算法,因為其需要大量的數據。實際上,深度學習通常在經典機器學習問題上並沒有集成方法表現得好。
  • 機器學習中特徵選擇怎麼做?這篇文章告訴你
    如果添加的特徵比必要的特徵多,那麼我們的模型性能將下降(因為添加了噪聲)。真正的挑戰是找出哪些特徵是最佳的使用特徵(這實際上取決於我們提供的數據量和我們正在努力實現的任務的複雜性)。這就是特徵選擇技術能夠幫到我們的地方!圖 1:分類器性能和維度之間的關係▍特徵選擇有許多不同的方法可用於特徵選擇。
  • 在機器學習回歸問題中,你應該使用哪種評估指標?
    對上述真值進行預測[1,2,2]的模型得出的R值為-0.59。最重要的是,您可以做得比null模型糟糕得多!事實上,你可以預測更壞的情況,結果是一個無窮小的R方。簡而言之,讓我們看看調整後的R和機器學習與統計數據。調整後的R說明增加了更多的預測變量(特徵)。
  • 為什麼在CAD布局中標註模型空間圖形尺寸差別很大?
    一、在布局標註視口內(模型空間)圖形什麼情況才會關聯呢? 有人習慣在模型空間標註,然後直接套圖框出圖或者到布局裡套圖框出圖,有些人則習慣在模型空間繪圖,然後到布局空間標註。
  • 一文概述用 python 的 scikit-image 模塊進行圖像分割
    具體涉及 scikit-image 的安裝,圖像導入以及用監督算法和無監督算法進行圖像分割的方法。雷鋒網 AI 科技評論編譯整理如下。遲早有一天,所有的一切都是數字,包括圖像。看過《終結者》的人肯定會認為這是那個時代最偉大的科幻電影。在這部電影中,James Cameron 引入了一個有趣的視覺效果概念,它可以使觀眾有可能躲在被稱為終結者的電子人的眼睛後面。
  • 如何使用XGBoost模型進行時間序列預測
    在廣泛的預測模型任務中,它快且有效,性能好。它在諸如Kaggle等數據科學競賽的獲勝者中最受歡迎。XGBoost也可以被用於時間序列預測,儘管它需要將時間序列數據集先轉換成監督學習問題。它需要用到一種被稱為前進式驗證的特殊方法來評估模型,因為使用k折驗證來評估模型容易導致偏向樂觀的結果。本教程中,你將探索如何為時間序列預測開發一個XGBoost模型。
  • 多元線性回歸的模型解釋、假設檢驗、特徵選擇
    因此,我們可以說,在這三家廣告代理商中,至少有一家在預測銷售額方面是有用的。但是哪一個或哪兩個是重要的呢?它們都重要嗎?為了找到這一點,我們將執行特徵選擇或變量選擇。一種方法是嘗試所有可能的組合。例如,通過在我們的案例研究中再增加一個預測因子,總組合數將變為15。想像一下有一打預測器。因此,我們需要更有效的方法來執行特性選擇。特徵選擇做特徵選擇的兩種最流行的方法是:正向選擇:我們從一個沒有任何預測器的模型開始,只使用截距項。
  • 金融時序預測:狀態空間模型和卡爾曼濾波
    在今天的推文中,我們將使用狀態空間模型對單變量時間序列數據進行預測分析。該模型具有連續的隱狀態和觀測狀態。 1 狀態空間模型 基於狀態空間模型對問題進行了結構分析。