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

2020-12-23 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翻譯組

相關焦點

  • 使用Scikit-learn 理解隨機森林
    翻譯 | 汪鵬 校對 | 餘杭 整理 | 餘杭在我以前的一篇文章中,我討論了隨機森林如何變成一個「白箱子」,這樣每次預測就能被分解為各項特徵的貢獻和,即預測=偏差+特徵 1 貢獻+ ... +特徵 n 貢獻。
  • python機器學習之使用scikit-learn庫
    引言數據分析由一連串的步驟組成,對於其中預測模型的創建和驗證這一步,我們使用scikit-learn這個功能強大的庫來完成。scikit-learning庫python庫scikit-learn整合了多種機器學習算法。
  • CDA承接的全球頂級機器學習Scikit-learn 中文社區上線啦!
    (注:scikit-learn的官網是www.scikit-learn.org,CDA承接的中文社區網址是www.scikit-learn.org.cn,這同時也標誌著CDA與全球頂級深度學習和機器學習框架更進一步融合,CDA認證更加得到全球頂級技術框架的認可!
  • Python粉都應該知道的開源機器學習框架:Scikit-learn入門指南
    目前Scikit-learn已經實現的算法包括:K-均值聚類,譜聚類,均值偏移,分層聚類,DBSCAN聚類等。數據降維是指使用主成分分析(PCA)、非負矩陣分解(NMF)或特徵選擇等降維技術來減少要考慮的隨機變量的個數,其主要應用場景包括可視化處理和效率提升。
  • 用scikit-learn解救蔡徐坤
    他只是一個被資本和流量選擇、包裝起來的」商品「,某種意義上,他只是一個符號一般的存在。真正應該負責是只顧情緒宣洩的噴子和網絡本身。自動檢測言論仇恨系統四步走,相關平臺值得擁有以某博為代表的開放式社交媒體,以及各家新聞客戶端,已經成了網友們的洩糞(憤)場。這個打字不需要負責的年代,「鍵盤俠」群雄四起。言語激戰和事件發酵正為各平臺所喜聞樂見。
  • 遊戲夜讀|Scikit-learn的2018自述
    R和Python的交誼舞曾幾何時,數據分析入門的一大討論就是R和Python的選擇。當統計學家連上了網際網路的那刻起,這種選擇一直就存在,只是主演們在換。上一代的主角,一方是R和S。大家選擇R是因為它是免費的解決方案,又能用,還有一批人維護更新,而且下載即可。概括起來,就是「開源大法好」。另一方是Matlab和Python。
  • 機器學習也能套模版:在線選擇模型和參數,一鍵生成demo
    現在,有一個Web應用程式,可以生成用於機器學習的模板代碼(demo),目前支持PyTorch和scikit-learn。同時,對於初學者來說,這也是一個非常好的工具。在模版中學習機器學習的代碼,可以少走一些彎路。
  • 在NLP中結合文本和數字特徵進行機器學習
    應用於自然語言處理的機器學習數據通常包含文本和數字輸入。例如,當您通過twitter或新聞構建一個模型來預測產品未來的銷售時,在考慮文本的同時考慮過去的銷售數據、訪問者數量、市場趨勢等將會更有效。您不會僅僅根據新聞情緒來預測股價的波動,而是會利用它來補充基於經濟指標和歷史價格的模型。
  • 使用scikitlearn、NLTK、Docker、Flask和Heroku構建食譜推薦API
    首先對數據集進行清理和解析,然後從數據中提取數字特徵,在此基礎上應用相似度函數來尋找已知食譜的配料與最終用戶給出的配料之間的相似度。最後根據相似度得分,得到最佳推薦食譜。詞幹還原和詞形還原都會產生詞根變化詞的詞根形式,區別在於詞幹還原的結果可能不是一個真正的單詞,而詞形還原的結果是一個實際的單詞。儘管詞形還原通常比較慢,但我選擇使用這種技術,因為我知道實際單詞對調試和可視化非常有用。
  • 超參數調整實戰:scikit-learn配合XGBoost的競賽top20策略
    在過去的幾年中,XGBoost被廣泛用於表格數據推斷,並且贏得了數百個挑戰。但是,僅僅通過XGBoost並不能完成完成整的解決方案,同樣的模型為什麼有些人能獲得更好的準確性呢?除了經驗方面的差異,還有一個事實,那就是他們優化了超參數!因此,我們今天將告訴您如何獲取特定數據集的最佳超參數。
  • Python 機器學習 Scikit-learn 完全入門指南
    本文將介紹安裝和運行 Scikit-learn 的大體步驟,而後重點講解 Scikit-learn 框架的幾大功能。本文的操作理論上在 Python 3.x 版本下通用,但目前建議在 Python 3.6 版本下使用。由於本文面向的對象為初學者,大多使用 Windows 系統,所以本文的所有操作,建立在為 64 位的 Windows 10 系統上。
  • 在機器學習回歸問題中,你應該使用哪種評估指標?
    對上述真值進行預測[1,2,2]的模型得出的R值為-0.59。最重要的是,您可以做得比null模型糟糕得多!事實上,你可以預測更壞的情況,結果是一個無窮小的R方。簡而言之,讓我們看看調整後的R和機器學習與統計數據。調整後的R說明增加了更多的預測變量(特徵)。
  • 比Keras更好用的機器學習「模型包」:無需預處理,0代碼上手做模型
    也就是說,用戶只需要知道各種機器學習模型的原理,但不需要再自己動手寫代碼。相比於Keras,這個項目進一步簡化了預處理、輸入輸出的工作,就像「模型包」一樣簡便。作者用了兩周的時間,做出了項目的1.0版本,一天以內已有842Star,目前還在快速上漲中。由於只是1.0版本,作者表示,這個項目仍然有很大的完善空間。
  • Scikit-learn核心開發人員:建立機器學習工作流最容易犯2點錯誤
    第三,對於像 Scikit-learn 那樣複雜的東西,你不想一開始就添加一些新的大功能。很多人都有他們最喜歡的模型,他們想通過將其添加到 Scikit-learn 中來開始他們的貢獻。但是,現在將一個模型添加到 Scikit-learn 需要大約一年的時間。所以我真的建議從小事做起。我本人是從文檔的排版開始的。改進文檔總是受歡迎的。還有很多關於問題追蹤的東西。
  • 實現Python數據化運營都需要哪些工具和組件?
    如果只是想學習或了解一下Python, Python 2和Python 3都可以。如果是企業內部應用,具體看企業用的是哪個版本。如果你的工作中需要大量的第三方庫,那麼使用Python 2會讓你有更多選擇。
  • 使用Scikit Learn的分類器探索Iris數據集
    剛毛鳶尾屬,花色鳶尾屬和維吉尼亞鳶尾屬(setosa, versicolor, virginica)?我知道我不能…但是,如果我們有一個包含這些物種實例的數據集,以及它們的萼片和花瓣的測量結果呢?換言之,我們能從這個數據集中學到什麼來幫助我們區分這三個物種嗎?目錄我們為什麼選擇這個數據集?我們想回答什麼問題?