0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

基于Pandas進(jìn)行初步數(shù)據(jù)探索和準(zhǔn)備的Scikit-Learn用戶方案

DPVg_AI_era ? 來源:未知 ? 作者:李倩 ? 2018-09-10 09:45 ? 次閱讀

Scikit-Learn發(fā)布0.20預(yù)覽版,Scikit-Learn與Pandas的新融合會使以往的工作流程更為簡單,其功能也更為豐富、更具魯棒性。

Scikit-Learn的0.20版本,將會是進(jìn)行近年來最重磅的升級。

對于許多數(shù)據(jù)科學(xué)家來說,一個典型的工作流程是在Scikit-Learn進(jìn)行機(jī)器學(xué)習(xí)之前,用Pandas進(jìn)行探索性的數(shù)據(jù)分析。新版本的Scikit-Learn將會讓這個過程變得更加簡單、功能更加豐富、更魯棒以及更加標(biāo)準(zhǔn)化。

注:本文中的0.20版本的是指預(yù)覽版,最終版本目前還沒有發(fā)布。

升級到0.20版本

幾日前,官方剛剛發(fā)布這個0.20的預(yù)覽版。用戶可以通過conda命令進(jìn)行安裝:

condainstallscikit-learn=0.20rc1-cconda-forge/label/rc-cconda-forge

也可以通過pip命令進(jìn)行安裝:

pipinstall—prescikit-learn

ColumnTransformer、升級版OneHotEncoder介紹

隨著0.20版本的升級,從Pandas到Scikit-Learn的許多工作流會變得比較相似。ColumnTransformer估計(jì)器會將一個轉(zhuǎn)換應(yīng)用到Pandas DataFrame(或數(shù)組)列的特定子集。

OneHotEncoder估計(jì)器不是“新生物”,但已經(jīng)升級為編碼字符串列。以前,它只對包含數(shù)字分類數(shù)據(jù)的列進(jìn)行編碼。

接下來,讓我們看看這些新添加的功能是如何處理Pandas DataFrame中的字符串列的。

Kaggle住房數(shù)據(jù)集

Kaggle最早的機(jī)器學(xué)習(xí)競賽題目之一是《住房價格:先進(jìn)的回歸技術(shù)》。其目標(biāo)是在給定80個特征情況下,預(yù)測房價。

數(shù)據(jù)一覽

在DataFrame中讀取數(shù)據(jù)并輸出前幾行。

>>>importpandasaspd>>>importnumpyasnp>>>train=pd.read_csv(‘data/housing/train.csv’)>>>train.head()

>>>train.shape(1460,81)

從訓(xùn)練集中刪除目標(biāo)變量

目標(biāo)變量是SalePrice,我們將它作為數(shù)組移除并分配給它自己的變量。我們將在后面的機(jī)器學(xué)習(xí)中用到它。

>>>y=train.pop('SalePrice').values

編碼單個字符串列

首先,我們編碼一個字符串列HoustStyle,它具有房子外觀的值。讓我們輸出每個字符串值的唯一計(jì)數(shù)。

>>>vc=train['HouseStyle'].value_counts()>>>vc1Story7262Story4451.5Fin154SLvl65SFoyer371.5Unf142.5Unf112.5Fin8Name:HouseStyle,dtype:int64

這一列中有8個唯一值(unique value)。

scikitlearn Gotcha必須有2D數(shù)據(jù)

大多數(shù)Scikit-Learn估計(jì)器嚴(yán)格要求數(shù)據(jù)是的2D的。從技術(shù)角度講,如果我們選擇上面的列作為train[“HouseStyle”],Pandas Series是數(shù)據(jù)的單一維度。我們可以強(qiáng)制Pandas創(chuàng)建一個單列DataFrame,方法是將一個單項(xiàng)列表傳遞到方括號中,如下所示:

>>>hs_train=train[['HouseStyle']].copy()>>>hs_train.ndim2

評估器的三個步驟過程——導(dǎo)入、實(shí)例化、匹配

Scikit-Learn API對于所有的估計(jì)器都是一致的,它根據(jù)下面三個步驟來匹配(訓(xùn)練)數(shù)據(jù)。

從它所在的模塊中導(dǎo)入我們想要的估計(jì)器

實(shí)例化估計(jì)器,可能改變它的默認(rèn)值

根據(jù)數(shù)據(jù)擬合估計(jì)量。在必要情況下,可以將數(shù)據(jù)轉(zhuǎn)換到新的空間。

下面,我們導(dǎo)入一個hotencoder,將它實(shí)例化,并確保返回一個密集(而不是稀疏)的數(shù)組,然后用fit_transform方法對單個列進(jìn)行編碼。

>>>fromsklearn.preprocessingimportOneHotEncoder>>>ohe=OneHotEncoder(sparse=False)>>>hs_train_transformed=ohe.fit_transform(hs_train)>>>hs_train_transformedarray([[0.,0.,0.,...,1.,0.,0.],[0.,0.,1.,...,0.,0.,0.],[0.,0.,0.,...,1.,0.,0.],...,[0.,0.,0.,...,1.,0.,0.],[0.,0.,1.,...,0.,0.,0.],[0.,0.,1.,...,0.,0.,0.]])

正如預(yù)期的那樣,它將每個唯一的值編碼為自己的二進(jìn)制列。

>>>hs_train_transformed.shape(1460,8)

得到了NumPy數(shù)組,那么列名在哪里?

注意,我們的輸出是一個NumPy數(shù)組,而不是Pandas DataFrame。Scikit-Learn最初不是為了直接與Pandas整合而建的。所有的Pandas對象都在內(nèi)部轉(zhuǎn)換成NumPy數(shù)組,并且在轉(zhuǎn)換后總是返回NumPy數(shù)組。

我們?nèi)匀豢梢酝ㄟ^其get_feature_names方法從OneHotEncoder對象獲得列名。

>>>feature_names=ohe.get_feature_names()>>>feature_namesarray(['x0_1.5Fin','x0_1.5Unf','x0_1Story','x0_2.5Fin','x0_2.5Unf','x0_2Story','x0_SFoyer','x0_SLvl'],dtype=object)

驗(yàn)證第一行數(shù)據(jù)的正確性

接下來讓我們驗(yàn)證估計(jì)值是否正確。首先是第一行編碼的數(shù)據(jù)。

>>>row0=hs_train_transformed[0]>>>row0array([0.,0.,0.,0.,0.,1.,0.,0.])

這將數(shù)組中的第6個值編碼為1。讓我們使用布爾索引(boolean index)來顯示特征名稱。

>>>feature_names[row0==1]array(['x0_2Story'],dtype=object)

現(xiàn)在,讓我們驗(yàn)證原始DataFrame列中的第一個值是否相同。

>>>hs_train.values[0]array(['2Story'],dtype=object)

使用inverse_transform來實(shí)現(xiàn)自動化

與大多數(shù)transformer對象一樣,有一個inverse_transform方法可以返回原始數(shù)據(jù)。在這里,我們必須將row0包裝在一個列表中,使其成為一個2D數(shù)組。

>>>ohe.inverse_transform([row0])array([['2Story']],dtype=object)

我們可以通過轉(zhuǎn)置整個轉(zhuǎn)換后的數(shù)組來驗(yàn)證所有的值。

>>>hs_inv=ohe.inverse_transform(hs_train_transformed)>>>hs_invarray([['2Story'],['1Story'],['2Story'],...,['2Story'],['1Story'],['1Story']],dtype=object)>>>np.array_equal(hs_inv,hs_train.values)True

將轉(zhuǎn)換應(yīng)用到測試集中

無論我們對訓(xùn)練集做什么轉(zhuǎn)換,我們都必須應(yīng)用到測試集。

>>>test=pd.read_csv('data/housing/test.csv')>>>hs_test=test[['HouseStyle']].copy()>>>hs_test_transformed=ohe.transform(hs_test)>>>hs_test_transformedarray([[0.,0.,1.,...,0.,0.,0.],[0.,0.,1.,...,0.,0.,0.],[0.,0.,0.,...,1.,0.,0.],...,[0.,0.,1.,...,0.,0.,0.],[0.,0.,0.,...,0.,1.,0.],[0.,0.,0.,...,1.,0.,0.]])

我們又得到了8列。

>>>hs_test_transformed.shape(1459,8)

必須impute缺失數(shù)據(jù)

現(xiàn)在,我們必須impute缺失數(shù)據(jù)。預(yù)處理模塊中舊的Imputer已經(jīng)被棄用。一個新的模塊——impute,由一個新的估計(jì)值SimpleImputer和一個新的策略“常量”組成。默認(rèn)情況下,此策略將用字符串“missing_value”來填充缺失值。我們可以選擇使用fill_value參數(shù)設(shè)置它。

>>>hs_train=train[['HouseStyle']].copy()>>>hs_train.iloc[0,0]=np.nan>>>fromsklearn.imputeimportSimpleImputer>>>si=SimpleImputer(strategy='constant',fill_value='MISSING')>>>hs_train_imputed=si.fit_transform(hs_train)>>>hs_train_imputedarray([['MISSING'],['1Story'],['2Story'],...,['2Story'],['1Story'],['1Story']],dtype=object)

接下來,我們可以像以前那樣編碼啦!

>>>hs_train_transformed=ohe.fit_transform(hs_train_imputed)>>>hs_train_transformedarray([[0.,0.,0.,...,1.,0.,0.],[0.,0.,1.,...,0.,0.,0.],[0.,0.,0.,...,0.,0.,0.],...,[0.,0.,0.,...,0.,0.,0.],[0.,0.,1.,...,0.,0.,0.],[0.,0.,1.,...,0.,0.,0.]])

注意,我們現(xiàn)在有了一個額外的列和一個額外的特征名稱。

>>>hs_train_transformed.shape(1460,9)>>>ohe.get_feature_names()array(['x0_1.5Fin','x0_1.5Unf','x0_1Story','x0_2.5Fin','x0_2.5Unf','x0_2Story','x0_MISSING','x0_SFoyer','x0_SLvl'],dtype=object)

更多關(guān)于fit_transform的細(xì)節(jié)

對于所有的估計(jì)器,fit_transform方法將首先調(diào)用fit方法,然后調(diào)用transform方法。fit方法找到轉(zhuǎn)換過程中使用的關(guān)鍵屬性。例如,對于SimpleImputer,如果策略是“均值”,那么它就會在fit方法中找到每一列的均值。它會存儲每一列的均值。當(dāng)調(diào)用transform時,它使用每個列的這個存儲平均值來填充缺失值并返回轉(zhuǎn)換后的數(shù)組。

OneHotEncoder原理是類似的。在fit方法中,它會找到每個列的所有唯一值,并再次存儲這些值。在調(diào)用transform時,它使用這些存儲的惟一值來生成二進(jìn)制數(shù)組。

將兩個轉(zhuǎn)換應(yīng)用到測試集

我們可以手動應(yīng)用上面的兩個步驟,如下所示:

>>>hs_test=test[['HouseStyle']].copy()>>>hs_test.iloc[0,0]='uniquevaluetotestset'>>>hs_test.iloc[1,0]=np.nan>>>hs_test_imputed=si.transform(hs_test)>>>hs_test_transformed=ohe.transform(hs_test_imputed)>>>hs_test_transformed.shape(1459,8)>>>ohe.get_feature_names()array(['x0_1.5Fin','x0_1.5Unf','x0_1Story','x0_2.5Fin','x0_2.5Unf','x0_2Story','x0_SFoyer','x0_SLvl'],dtype=object)

使用一個Pipeline來替代

Scikit-Learn提供了一個Pipeline估計(jì)器,它獲取一個轉(zhuǎn)換列表并依次應(yīng)用它們。您還可以運(yùn)行機(jī)器學(xué)習(xí)模型作為最終評估器。在這里,我們只是簡單地impute和編碼。

>>>fromsklearn.pipelineimportPipeline

每個步驟是一個two-item元組,由一個標(biāo)記步驟和實(shí)例化估計(jì)器的字符串組成。前一個步驟的輸出是后一個步驟的輸入。

>>>si_step=('si',SimpleImputer(strategy='constant',fill_value='MISSING'))>>>ohe_step=('ohe',OneHotEncoder(sparse=False,handle_unknown='ignore'))>>>steps=[si_step,ohe_step]>>>pipe=Pipeline(steps)>>>hs_train=train[['HouseStyle']].copy()>>>hs_train.iloc[0,0]=np.nan>>>hs_transformed=pipe.fit_transform(hs_train)>>>hs_transformed.shape(1460,9)

通過簡單地將測試集傳遞給transform方法,可以輕松地通過Pipeline的每個步驟轉(zhuǎn)換測試集。

>>>hs_test=test[['HouseStyle']].copy()>>>hs_test_transformed=pipe.transform(hs_test)>>>hs_test_transformed.shape(1459,9)

為什么只對測試集轉(zhuǎn)換方法?

在轉(zhuǎn)換測試集時,重要的是只調(diào)用transform方法,而不是fit_transform。當(dāng)我們在訓(xùn)練集中運(yùn)行fit_transform時,Scikit-Learn找到了它需要的所有必要信息,以便轉(zhuǎn)換包含相同列名的任何其他數(shù)據(jù)集。

多字符串列轉(zhuǎn)換

對多列字符串進(jìn)行編碼不成問題。先選擇你要編碼的列,再通過同樣的流程傳遞新的數(shù)據(jù)框架。

>>>string_cols=['RoofMatl','HouseStyle']>>>string_train=train[string_cols]>>>string_train.head(3)RoofMatlHouseStyle0CompShg2Story1CompShg1Story2CompShg2Story>>>string_train_transformed=pipe.fit_transform(string_train)>>>string_train_transformed.shape(1460,16)

把握pipeline的每個部分

我們可以通過named_steps字典屬性中的名稱檢索pipeline中的每個轉(zhuǎn)換器。在本例中,我們可以得到一個熱門編碼器,用來輸出特征名稱。

>>>ohe=pipe.named_steps['ohe']>>>ohe.get_feature_names()array(['x0_ClyTile','x0_CompShg','x0_Membran','x0_Metal','x0_Roll','x0_Tar&Grv','x0_WdShake','x0_WdShngl','x1_1.5Fin','x1_1.5Unf','x1_1Story','x1_2.5Fin','x1_2.5Unf','x1_2Story','x1_SFoyer','x1_SLvl'],dtype=object)

使用新的列轉(zhuǎn)換器來選擇列

全新的列轉(zhuǎn)換器(屬于新組合模塊的一部分)可以讓用戶選擇要讓哪些列獲得哪些轉(zhuǎn)換。 與連續(xù)列相比,分類列幾乎總是需要單獨(dú)的轉(zhuǎn)換。

列轉(zhuǎn)換器目前是還是實(shí)驗(yàn)性的,其功能將來可能會發(fā)生變化。

ColumnTransformer獲取三項(xiàng)元組(tuple)的列表。 元組中的第一個值其標(biāo)記作用的名稱,第二個是實(shí)例化的估算器,第三個是要進(jìn)行轉(zhuǎn)換的列的列表。 元組如下所示:

('name',SomeTransformer(parameters),columns)

這里的列實(shí)際上不必一定是列名。用戶可以使用列的整數(shù)索引,布爾數(shù)組,甚至函數(shù)(它可以使用整個DataFrame作為參數(shù),并且必須返回選擇的列)。

用戶也可以將NumPy數(shù)組與列轉(zhuǎn)換器一起使用,但本教程主要關(guān)注Pandas的集成,因此我們這里繼續(xù)使用DataFrames。

將pipeline傳遞給列轉(zhuǎn)換器

我們甚至可以將多個轉(zhuǎn)換的流程傳遞給列轉(zhuǎn)換器,我們現(xiàn)在正是要這樣做,因?yàn)樵谧址猩嫌卸鄠€轉(zhuǎn)換。

下面,我們使用列轉(zhuǎn)換器重現(xiàn)上述流程和編碼。 請注意,實(shí)際流程與上面的流程完全相同,只是附加了每個變量名稱的cat。 我們將在下一章節(jié)中為數(shù)字列添加不同的流程。

>>>fromsklearn.composeimportColumnTransformer>>>cat_si_step=('si',SimpleImputer(strategy='constant',fill_value='MISSING'))>>>cat_ohe_step=('ohe',OneHotEncoder(sparse=False,handle_unknown='ignore'))>>>cat_steps=[cat_si_step,cat_ohe_step]>>>cat_pipe=Pipeline(cat_steps)>>>cat_cols=['RoofMatl','HouseStyle']>>>cat_transformers=[('cat',cat_pipe,cat_cols)]>>>ct=ColumnTransformer(transformers=cat_transformers)

將整個DataFrame傳遞給列轉(zhuǎn)換器

列轉(zhuǎn)換器實(shí)例可以選擇我們想要使用的列,因此我們只需將整個DataFrame傳遞給fit_transform方法,就可以選擇我們所需的列。

>>>X_cat_transformed=ct.fit_transform(train)>>>X_cat_transformed.shape(1460,16)

然后可以使用同樣的方法轉(zhuǎn)換測試集。

>>>X_cat_transformed_test=ct.transform(test)>>>X_cat_transformed_test.shape(1459,16)

檢索特征名

我們必須進(jìn)一步挖掘,來獲取特征名。所有的轉(zhuǎn)換器都存儲在named_transformers_ dictionary屬性中。 然后使用特征名、含有三項(xiàng)要素的元組中的第一項(xiàng),來選擇特定的轉(zhuǎn)換器。 下面的代碼就是選擇轉(zhuǎn)換器(此例中只有一個流程,名為cat)。

>>>pl=ct.named_transformers_['cat']

然后從這個流程中選擇一個熱編碼器對象,最后得到特征名。

>>>ohe=pl.named_steps['ohe']>>>ohe.get_feature_names()array(['x0_ClyTile','x0_CompShg','x0_Membran','x0_Metal','x0_Roll','x0_Tar&Grv','x0_WdShake','x0_WdShngl','x1_1.5Fin','x1_1.5Unf','x1_1Story','x1_2.5Fin','x1_2.5Unf','x1_2Story','x1_SFoyer','x1_SLvl'],dtype=object)

轉(zhuǎn)換數(shù)字列

數(shù)字列需要一組不同的轉(zhuǎn)換。我們不使用常亮來填充缺失值,而是經(jīng)常選擇中值或均值。一般不對列中的值進(jìn)行編碼,而是通常將列中的值減去每列的平均值并除以標(biāo)準(zhǔn)差,對列中的值進(jìn)行標(biāo)準(zhǔn)化。這有助于讓許多模型產(chǎn)生更好的擬合結(jié)果(比如脊回歸)。

使用所有數(shù)字列

我們可以選擇所有數(shù)字列,而不是像處理字符串列一樣,手動選擇一列或兩列。首先使用dtypes屬性查找每列的數(shù)據(jù)類型,然后測試每個dtype的類型是否為“O”。 dtypes屬性會返回一系列NumPy dtype對象,每個對象都有一個單一字符的kind屬性。我們可以利用它來查找數(shù)字或字符串列。 Pandas將其所有字符串列存儲為kind屬性等于“O”的對象。有關(guān)kind屬性的更多信息,請參閱NumPy文檔。

>>>train.dtypes.head()Idint64MSSubClassint64MSZoningobjectLotFrontagefloat64LotAreaint64dtype:object

獲取kind屬性,該屬性是表示dtype的單字字符串。

>>>kinds=np.array([dt.kindfordtintrain.dtypes])>>>kinds[:5]array(['i','i','O','f','i'],dtype='

假設(shè)所有的數(shù)字列都是非對象性的。我們可以使用同樣的方法來獲取類別列。

>>>all_columns=train.columns.values>>>is_num=kinds!='O'>>>num_cols=all_columns[is_num]>>>num_cols[:5]array(['Id','MSSubClass','LotFrontage','LotArea','OverallQual'],dtype=object)>>>cat_cols=all_columns[~is_num]>>>cat_cols[:5]array(['MSZoning','Street','Alley','LotShape','LandContour'],dtype=object)

獲取數(shù)字列列名之后,可以再次使用列轉(zhuǎn)換器。

>>>fromsklearn.preprocessingimportStandardScaler>>>num_si_step=('si',SimpleImputer(strategy='median'))>>>num_ss_step=('ss',StandardScaler())>>>num_steps=[num_si_step,num_ss_step]>>>num_pipe=Pipeline(num_steps)>>>num_transformers=[('num',num_pipe,num_cols)]>>>ct=ColumnTransformer(transformers=num_transformers)>>>X_num_transformed=ct.fit_transform(train)>>>X_num_transformed.shape(1460,37)

類別列和數(shù)字列轉(zhuǎn)換的結(jié)合

我們可以使用類轉(zhuǎn)換器對DataFrame的每個部分進(jìn)行單獨(dú)轉(zhuǎn)換。在本文的示例中,我們將使用每一列。

然后,將類別列和數(shù)字列分別創(chuàng)建單獨(dú)的流程,然后使用列轉(zhuǎn)換器進(jìn)行獨(dú)立轉(zhuǎn)換。這兩個轉(zhuǎn)換過程是并行的。最后,將每個轉(zhuǎn)換結(jié)果連接在一起。

>>>transformers=[('cat',cat_pipe,cat_cols),('num',num_pipe,num_cols)]>>>ct=ColumnTransformer(transformers=transformers)>>>X=ct.fit_transform(train)>>>X.shape(1460,305)

機(jī)器學(xué)習(xí)

本文的重點(diǎn)就是設(shè)置數(shù)據(jù),以便進(jìn)行機(jī)器學(xué)習(xí)。我們可以創(chuàng)建一個最終流程,并添加機(jī)器學(xué)習(xí)模型作為最終的估算器。這個流程的第一步就是我們上文剛剛完成的整個轉(zhuǎn)換過程。我們在本文開始處設(shè)定y表示售價。在這里,我們將使用thefit方法,而不是fit_transform方法,因?yàn)榱鞒痰淖詈笠徊绞菣C(jī)器學(xué)習(xí)模型,而且不進(jìn)行轉(zhuǎn)換。

>>>fromsklearn.linear_modelimportRidge>>>ml_pipe=Pipeline([('transform',ct),('ridge',Ridge())])>>>ml_pipe.fit(train,y)

我們可以用score方法來評估模型,它將返回一個R-Squared值:

>>>ml_pipe.score(train,y)0.92205

交叉驗(yàn)證

當(dāng)然,在訓(xùn)練集上進(jìn)行自我評分是沒有用的。我們需要做一些K重交叉驗(yàn)證,以了解如何處理不可見的數(shù)據(jù)。這里我們設(shè)置一個隨機(jī)狀態(tài),以便在整個教程的其余各部分保持同樣的狀態(tài)。

>>>fromsklearn.model_selectionimportKFold,cross_val_score>>>kf=KFold(n_splits=5,shuffle=True,random_state=123)>>>cross_val_score(ml_pipe,train,y,cv=kf).mean()0.813

在網(wǎng)格搜索時選擇參數(shù)

在Scikit-Learn中進(jìn)行網(wǎng)格搜索,要求我們將映射傳遞至到可能值的參數(shù)名稱字典中。 在流程中,我們必須將步驟的名稱加上雙下劃線,然后使用參數(shù)名。 如果流程中有多個層級,必須繼續(xù)使用雙下劃線,向上移動一級,直至到達(dá)我們想要優(yōu)化其參數(shù)的估算器為止。

>>>fromsklearn.model_selectionimportGridSearchCV>>>param_grid={'transform__num__si__strategy':['mean','median'],'ridge__alpha':[.001,0.1,1.0,5,10,50,100,1000],}>>>gs=GridSearchCV(ml_pipe,param_grid,cv=kf)>>>gs.fit(train,y)>>>gs.best_params_{'ridge__alpha':10,'transform__num__si__strategy':'median'}>>>gs.best_score_0.819

在Pandas DataFrame中獲取所有網(wǎng)格搜索結(jié)果

網(wǎng)格搜索的所有結(jié)果都存儲在cv_results_屬性中。 這是一個字典,可以轉(zhuǎn)換為Pandas DataFrame以獲得更好的顯示效果,該屬性使用一種更容易進(jìn)行手動掃描的結(jié)構(gòu)。

>>>pd.DataFrame(gs.cv_results_)

參數(shù)網(wǎng)格中每一種組合中都包含大量數(shù)據(jù)

構(gòu)建一個具備全部基礎(chǔ)功能的自定義轉(zhuǎn)換器

在上述工作流程中存在一些限制。例如,如果熱編碼器允許在使用fit方法期間忽略缺失值,那就更好了,那就可以簡單地將缺失值編碼為全零行。而目前,它還要強(qiáng)制用戶用一些字符串去填充缺失值,然后將此字符串編碼為單獨(dú)的列。

低頻字符串

此外,在訓(xùn)練集中僅出現(xiàn)幾次的字符串列,可能不是測試集中的可靠預(yù)測變量。我們可能希望將它們編碼為缺失值。

編寫自己的估算器類

Scikit-Learn可以幫助用戶編寫自己的估算器類?;灸K中的BaseEstimator類可以提供get_params和set_params方法。當(dāng)進(jìn)行網(wǎng)格搜索時,set_params方法是必需的。用戶可以自己編寫,也可以用BaseEstimator。還有一個TransformerMixin,但只是為用戶編寫fit_transform方法。

以下代碼構(gòu)建的類基本轉(zhuǎn)換器可執(zhí)行以下操作:

?使用數(shù)字列的均值或中位數(shù)填充缺失值

?對所有數(shù)字列進(jìn)行標(biāo)準(zhǔn)化

?對字符串列使用一個熱編碼

?不用再填充類別列中的缺失值,而是直接將其編碼為0

?忽略測試集中字符串列中的少數(shù)獨(dú)特值

?允許您為字符串列中值必須具有的出現(xiàn)次數(shù)選擇閾值。低于此閾值的字符串將被編碼為全0

?僅適用于DataFrames,并且只是實(shí)驗(yàn)性的,未經(jīng)過測試,因此可能會破壞某些數(shù)據(jù)集。

?之所以稱其為“基本”轉(zhuǎn)換器,是因?yàn)閷υS多數(shù)據(jù)集而言,這些操作屬于最基本的轉(zhuǎn)換。

fromsklearn.baseimportBaseEstimatorclassBasicTransformer(BaseEstimator):def__init__(self,cat_threshold=None,num_strategy='median',return_df=False):#storeparametersaspublicattributesself.cat_threshold=cat_thresholdifnum_strategynotin['mean','median']:raiseValueError('num_strategymustbeeither"mean"or"median"')self.num_strategy=num_strategyself.return_df=return_dfdeffit(self,X,y=None):#AssumesXisaDataFrameself._columns=X.columns.values#Splitdataintocategoricalandnumericself._dtypes=X.dtypes.valuesself._kinds=np.array([dt.kindfordtinX.dtypes])self._column_dtypes={}is_cat=self._kinds=='O'self._column_dtypes['cat']=self._columns[is_cat]self._column_dtypes['num']=self._columns[~is_cat]self._feature_names=self._column_dtypes['num']#Createadictionarymappingcategoricalcolumntounique#valuesabovethresholdself._cat_cols={}forcolinself._column_dtypes['cat']:vc=X[col].value_counts()ifself.cat_thresholdisnotNone:vc=vc[vc>self.cat_threshold]vals=vc.index.valuesself._cat_cols[col]=valsself._feature_names=np.append(self._feature_names,col+'_'+vals)#gettotalnumberofnewcategoricalcolumnsself._total_cat_cols=sum([len(v)forcol,vinself._cat_cols.items()])#getmeanormediannum_cols=self._column_dtypes['num']self._num_fill=X[num_cols].agg(self.num_strategy)returnselfdeftransform(self,X):#checkthatwehaveaDataFramewithsamecolumnnamesas#theonewefitifset(self._columns)!=set(X.columns):raiseValueError('PassedDataFramehasdifferentcolumnsthanfitDataFrame')eliflen(self._columns)!=len(X.columns):raiseValueError('PassedDataFramehasdifferentnumberofcolumnsthanfitDataFrame')#fillmissingvaluesnum_cols=self._column_dtypes['num']X_num=X[num_cols].fillna(self._num_fill)#Standardizenumericsstd=X_num.std()X_num=(X_num-X_num.mean())/stdzero_std=np.where(std==0)[0]#Ifthereis0standarddeviation,thenallvaluesarethe#same.Setthemto0.iflen(zero_std)>0:X_num.iloc[:,zero_std]=0X_num=X_num.values#createseparatearrayfornewencodedcategoricalsX_cat=np.empty((len(X),self._total_cat_cols),dtype='int')i=0forcolinself._column_dtypes['cat']:vals=self._cat_cols[col]forvalinvals:X_cat[:,i]=X[col]==vali+=1#concatenatetransformednumericandcategoricalarraysdata=np.column_stack((X_num,X_cat))#returneitheraDataFrameoranarrayifself.return_df:returnpd.DataFrame(data=data,columns=self._feature_names)else:returndatadeffit_transform(self,X,y=None):returnself.fit(X).transform(X)defget_feature_names():returnself._feature_names

使用基礎(chǔ)轉(zhuǎn)換器

上面構(gòu)建的基礎(chǔ)轉(zhuǎn)換器估算器應(yīng)該可以像任何其他scikit-learn估算器一樣使用。我們可以將其實(shí)例化,然后轉(zhuǎn)換數(shù)據(jù)。

>>>bt=BasicTransformer(cat_threshold=3,return_df=True)>>>train_transformed=bt.fit_transform(train)>>>train_transformed.head(3)

DataFrame中數(shù)字列和類別列相交處的列

在pipeline中使用轉(zhuǎn)換器

上文構(gòu)建的轉(zhuǎn)換器可以作為流程的一部分。

>>>basic_pipe=Pipeline([('bt',bt),('ridge',Ridge())])>>>basic_pipe.fit(train,y)>>>basic_pipe.score(train,y)0.904

用戶也可以使用它進(jìn)行交叉驗(yàn)證,獲得與上面的scikit-learn列轉(zhuǎn)換器流程相似的分?jǐn)?shù)。

>>>cross_val_score(basic_pipe,train,y,cv=kf).mean()0.816

我們也可以將其用作網(wǎng)格搜索的一部分。事實(shí)證明,將低頻字符串排除在外,并沒有明顯改善模型的表現(xiàn),盡管它可以在其他模型中使用。不過,在最佳評分方面確實(shí)有所提高,這可能是由于使用了略微不同的編碼方案。

>>>param_grid={'bt__cat_threshold':[0,1,2,3,5],'ridge__alpha':[.1,1,10,100]}>>>gs=GridSearchCV(p,param_grid,cv=kf)>>>gs.fit(train,y)>>>gs.best_params_{'bt__cat_threshold':0,'ridge__alpha':10}>>>gs.best_score_0.830

使用新的KBinsDiscretizer對數(shù)字列進(jìn)行分裝(bin)和編碼

對于包含年份的一些數(shù)字列,將其中的值視為類別列更有意義。 Scikit-Learn推出了新的估算器KBinsDiscretizer來實(shí)現(xiàn)這一點(diǎn)。它不僅可以存儲值,還可以對這些值進(jìn)行編碼。在使用Pandas cut或qcut函數(shù)手動完成此這類操作之前,一起來看看它如何處理年份數(shù)字列的。

>>>fromsklearn.preprocessingimportKBinsDiscretizer>>>kbd=KBinsDiscretizer(encode='onehot-dense')>>>year_built_transformed=kbd.fit_transform(train[['YearBuilt']])>>>year_built_transformedarray([[0.,0.,0.,0.,1.],[0.,0.,1.,0.,0.],[0.,0.,0.,1.,0.],...,[1.,0.,0.,0.,0.],[0.,1.,0.,0.,0.],[0.,0.,1.,0.,0.]])

在默認(rèn)設(shè)置下,每個bin中都包括相等數(shù)量的觀察數(shù)據(jù)。下面對每列求和來驗(yàn)證這一點(diǎn)。

>>>year_built_transformed.sum(axis=0)array([292.,274.,307.,266.,321.])

這就是“分位數(shù)策略”,用戶可以選擇“統(tǒng)一”模式,為bin邊界劃定相等的空間,也可以選擇“k平均”聚類,自定義bin邊界。

>>>kbd.bin_edges_array([array([1872.,1947.8,1965.,1984.,2003.,2010.])],dtype=object)

使用列轉(zhuǎn)換器分別處理所有年份列

現(xiàn)在有一個需要單獨(dú)處理的列子集,我們可以使用列轉(zhuǎn)換器來執(zhí)行此操作。下面的代碼為我們之前的轉(zhuǎn)換添加了一個步驟。此外還刪除了標(biāo)識列,只標(biāo)識出每一行。

>>>year_cols=['YearBuilt','YearRemodAdd','GarageYrBlt','YrSold']>>>not_year=~np.isin(num_cols,year_cols+['Id'])>>>num_cols2=num_cols[not_year]>>>year_si_step=('si',SimpleImputer(strategy='median'))>>>year_kbd_step=('kbd',KBinsDiscretizer(n_bins=5,encode='onehot-dense'))>>>year_steps=[year_si_step,year_kbd_step]>>>year_pipe=Pipeline(year_steps)>>>transformers=[('cat',cat_pipe,cat_cols),('num',num_pipe,num_cols2),('year',year_pipe,year_cols)]>>>ct=ColumnTransformer(transformers=transformers)>>>X=ct.fit_transform(train)>>>X.shape(1460,320)

通過交叉驗(yàn)證和評分,發(fā)現(xiàn)所有這些處理都沒有帶來任何改進(jìn)。

>>>ml_pipe=Pipeline([('transform',ct),('ridge',Ridge())])>>>cross_val_score(ml_pipe,train,y,cv=kf).mean()0.813

為每列使用不同數(shù)量的bin可能會改善我們的結(jié)果。盡管如此,KBinsDiscretizer還可以輕松地對數(shù)字變量進(jìn)行分裝。

標(biāo)題:Scikit-Learn 0.20的更多亮點(diǎn)

本次即將發(fā)布的版本附帶了更多新功能。更多詳細(xì)信息,請查看文檔的“新增內(nèi)容”部分。有很多變化哦。

結(jié)論

本文介紹了一個新的工作流程,提供了一個基于Pandas進(jìn)行初步數(shù)據(jù)探索和準(zhǔn)備的Scikit-Learn用戶方案。現(xiàn)在,改進(jìn)型的新估算器ColumnTransformer,SimpleImputer,OneHotEncoder和KBinsDiscretizer,讓整個數(shù)據(jù)處理流程變得更加平滑,功能也更加豐富。用戶可以獲取Pandas DataFrame,并對其進(jìn)行轉(zhuǎn)換,為機(jī)器學(xué)習(xí)做好準(zhǔn)備。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報(bào)投訴

原文標(biāo)題:AI開發(fā)最大升級:Pandas與Scikit-Learn合并,新工作流程更簡單強(qiáng)大!

文章出處:【微信號:AI_era,微信公眾號:新智元】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏

    評論

    相關(guān)推薦

    Python機(jī)器學(xué)習(xí)庫談Scikit-learn技術(shù)

    Scikit-learn API內(nèi)置了各種toy和real-world數(shù)據(jù)集[1]。這些可以便捷地通過一行代碼訪問,如果你正在學(xué)習(xí)或只是想快速嘗試新功能,這會非常有用。
    的頭像 發(fā)表于 08-27 17:34 ?3081次閱讀
    Python機(jī)器學(xué)習(xí)庫談<b class='flag-5'>Scikit-learn</b>技術(shù)

    在PyODPS DataFrame自定義函數(shù)中使用pandas、scipy和scikit-learn

    的,MaxCompute 的 Python 環(huán)境只包含了 numpy 這一個第三方包,用戶常常問的問題是,如何在自定義函數(shù)里使用 pandas、scipy 或者 scikit-learn 這樣的包含c
    發(fā)表于 05-17 19:48

    通用Python機(jī)器學(xué)習(xí)庫scikit-learn

    《利用Python進(jìn)行數(shù)據(jù)分析》 134 scikit-learn介紹
    發(fā)表于 10-25 07:58

    迅為RK3399開發(fā)板人工智能深度學(xué)習(xí)框架

    `迅為率先在RK3399 開發(fā)板上支持了Docker、TensorFlow目標(biāo)檢測API、OpenCV、Keras、scikit-learn、pytorch和Python等,組成了人工智能深度學(xué)習(xí)
    發(fā)表于 05-21 17:28

    如何在移動和嵌入式設(shè)備上部署機(jī)器學(xué)習(xí)模型

    機(jī)器學(xué)習(xí) 部署 嵌入式 介紹 (Introduction)Thanks to libraries such as Pandas, scikit-learn, and Matplotlib
    發(fā)表于 12-14 08:30

    Python機(jī)器學(xué)習(xí)回歸部分的應(yīng)用與教程

    這里,你應(yīng)該已經(jīng)安裝了 Scikit-Learn。如果沒有,安裝它,以及 Pandas 和 Matplotlib。 pip install numpy pip install scipy pip
    發(fā)表于 11-15 18:14 ?4807次閱讀
    Python機(jī)器學(xué)習(xí)回歸部分的應(yīng)用與教程

    基于Python的scikit-learn編程實(shí)例

    scikit-learn 是機(jī)器學(xué)習(xí)領(lǐng)域非常熱門的一個開源庫,基于Python 語言寫成。可以免費(fèi)使用。 網(wǎng)址: 上面有很多的教程,編程實(shí)例。而且還做了很好的總結(jié),下面這張圖基本概括了傳統(tǒng)機(jī)器學(xué)習(xí)
    發(fā)表于 11-15 19:39 ?1639次閱讀

    詳細(xì)解析scikit-learn進(jìn)行文本分類

    而多類別分類指的是y的可能取值大于2,但是y所屬類別是唯一的。它與多標(biāo)簽分類問題是有嚴(yán)格區(qū)別的。所有的scikit-learn分類器都是默認(rèn)支持多類別分類的。但是,當(dāng)你需要自己修改算法的時候,也是可以使用scikit-learn實(shí)現(xiàn)多類別分類的前期
    的頭像 發(fā)表于 12-27 08:36 ?4705次閱讀
    詳細(xì)解析<b class='flag-5'>scikit-learn</b><b class='flag-5'>進(jìn)行</b>文本分類

    機(jī)器學(xué)習(xí)和數(shù)據(jù)科學(xué)必讀的10本免費(fèi)在線電子書和書的詳細(xì)介紹

    本書介紹了在Python中處理數(shù)據(jù)所必需的核心庫:特別是IPython,NumPy,Pandas,Matplotlib,Scikit-Learn和相關(guān)軟件包。讀這本書,你需要有Python基礎(chǔ),如果
    的頭像 發(fā)表于 07-01 11:04 ?6661次閱讀

    用英特爾DAAL性能庫加速SCIKIT學(xué)習(xí)

    , and experience faster scikit-learn for your machine learning workflows.
    的頭像 發(fā)表于 10-15 03:20 ?3230次閱讀

    高性能Python代碼工具的介紹

    了解scikit-learn *,NumPy,SciPy,Pandas,mpi4py和Numba *的高性能Python *的最新發(fā)展和工具。
    的頭像 發(fā)表于 10-30 04:48 ?2554次閱讀

    scikit-learn K近鄰法類庫使用的經(jīng)驗(yàn)總結(jié)

    本文對scikit-learn中KNN相關(guān)的類庫使用做了一個總結(jié),主要關(guān)注于類庫調(diào)參時的一個經(jīng)驗(yàn)總結(jié),且非常詳細(xì)地介紹了類庫的參數(shù)含義。
    的頭像 發(fā)表于 01-13 11:49 ?3172次閱讀
    <b class='flag-5'>scikit-learn</b> K近鄰法類庫使用的經(jīng)驗(yàn)總結(jié)

    如何在線構(gòu)建共享機(jī)器學(xué)習(xí)模型

    Google Colaboratory,通常被稱為colab,由谷歌開發(fā),允許所有人在瀏覽器中創(chuàng)建并運(yùn)行python代碼。其內(nèi)置許多標(biāo)準(zhǔn)機(jī)器學(xué)習(xí)和數(shù)據(jù)科學(xué)庫,包括pandasscikit-learn,還可以安裝幾乎其他所有py
    的頭像 發(fā)表于 04-15 14:42 ?1948次閱讀

    基于Python的scikit-learn包實(shí)現(xiàn)機(jī)器學(xué)習(xí)

    基于Python的scikit-learn包實(shí)現(xiàn)機(jī)器學(xué)習(xí)。
    發(fā)表于 03-26 09:42 ?11次下載
    基于Python的<b class='flag-5'>scikit-learn</b>包實(shí)現(xiàn)機(jī)器學(xué)習(xí)

    Scikit-learn機(jī)器學(xué)習(xí)庫的概念及工作原理

    作為一個適用于 Python 編程語言的機(jī)器學(xué)習(xí) (ML) 庫,Scikit-learn 擁有大量算法,可供程序員和數(shù)據(jù)科學(xué)家在機(jī)器學(xué)習(xí)模型中輕松部署。
    的頭像 發(fā)表于 09-30 11:00 ?1408次閱讀