sklearn.preprocessing
包提供了幾個常用的實(shí)用函數(shù)和轉(zhuǎn)換器類,用以將原始特征向量更改為更適合下游估計器的表示形式。
通常,學(xué)習(xí)算法受益于數(shù)據(jù)集的標(biāo)準(zhǔn)化。如果數(shù)據(jù)集中存在一些異常值,則更適合使用健壯的縮放器或轉(zhuǎn)換器。不同縮放器,轉(zhuǎn)換器和規(guī)范化器在包含邊緣異常值的數(shù)據(jù)集上的行為突出顯示了比較不同縮放器對含有異常值數(shù)據(jù)的效果。
數(shù)據(jù)集的標(biāo)準(zhǔn)化是scikit-learn中實(shí)現(xiàn)許多機(jī)器學(xué)習(xí)估計器的普遍要求;如果個別特征看起來或多或少不像標(biāo)準(zhǔn)正態(tài)分布數(shù)據(jù):均值和單位方差為零的高斯分布,則它們的性能可能不好。
在實(shí)踐中,我們通常會忽略分布的形狀,而只是通過刪除每個特征的平均值來實(shí)現(xiàn)特征數(shù)據(jù)中心化,然后除以非常數(shù)特征的標(biāo)準(zhǔn)差來縮放數(shù)據(jù)。
例如,學(xué)習(xí)算法的目標(biāo)函數(shù)中使用的許多元素(例如支持向量機(jī)的RBF內(nèi)核或線性模型的l1和l2正則化器)都假定所有特征都圍繞零為中心并且具有相同階數(shù)的方差。如果某個特征的方差比其他特征大幾個數(shù)量級,則它可能會極大影響目標(biāo)函數(shù),并使估計器無法按預(yù)期從其他特征中正確學(xué)習(xí)。
scale
函數(shù)提供了一種簡單快捷的方法來對單個類似數(shù)組的數(shù)據(jù)集執(zhí)行此操作:
>>> from sklearn import preprocessing
>>> import numpy as np
>>> X_train = np.array([[ 1., -1., 2.],
... [ 2., 0., 0.],
... [ 0., 1., -1.]])
>>> X_scaled = preprocessing.scale(X_train)
>>> X_scaled
array([[ 0. ..., -1.22..., 1.33...],
[ 1.22..., 0. ..., -0.26...],
[-1.22..., 1.22..., -1.06...]])
縮放的數(shù)據(jù)具有0均值和單位方差:
>>> X_scaled.mean(axis=0)
array([0., 0., 0.])
>>> X_scaled.std(axis=0)
array([1., 1., 1.])
preprocessing
模塊還提供了一個實(shí)用程序類StandardScaler
,它使Transformer
API來計算訓(xùn)練集上的均值和標(biāo)準(zhǔn)差,以便以后能夠在測試集上重新應(yīng)用相同的轉(zhuǎn)換。因此,該類適用于 sklearn.pipeline.Pipeline
的早期步驟:
>>> scaler = preprocessing.StandardScaler().fit(X_train)
>>> scaler
StandardScaler()
>>> scaler.mean_
array([1. ..., 0. ..., 0.33...])
>>> scaler.scale_
array([0.81..., 0.81..., 1.24...])
>>> scaler.transform(X_train)
array([[ 0. ..., -1.22..., 1.33...],
[ 1.22..., 0. ..., -0.26...],
[-1.22..., 1.22..., -1.06...]])
然后可以將縮放器實(shí)例用于新數(shù)據(jù)以實(shí)現(xiàn)與訓(xùn)練集相同的轉(zhuǎn)換方式:
>>> X_test = [[-1., 1., 0.]]
>>> scaler.transform(X_test)
array([[-2.44..., 1.22..., -0.26...]])
可以通過將with_mean=False
或with_std=False
傳遞給StandardScaler
的構(gòu)造函數(shù)來取消居中或縮放。
另一種標(biāo)準(zhǔn)化方法是將特征值縮放到給定的最小值和最大值之間,通常介于零和一之間,或者將每個特征的最大絕對值縮放到單位大小,上述操作可以分別使用MinMaxScaler
或MaxAbsScaler
來實(shí)現(xiàn)。
使用這種縮放的目的包括對特征極小標(biāo)準(zhǔn)偏差的穩(wěn)健性以及在稀疏數(shù)據(jù)中保留零元素。
這是將簡單的數(shù)據(jù)矩陣縮放到[0, 1]
范圍的示例:
>>> X_train = np.array([[ 1., -1., 2.],
... [ 2., 0., 0.],
... [ 0., 1., -1.]])
...
>>> min_max_scaler = preprocessing.MinMaxScaler()
>>> X_train_minmax = min_max_scaler.fit_transform(X_train)
>>> X_train_minmax
array([[0.5 , 0. , 1. ],
[1. , 0.5 , 0.33333333],
[0. , 1. , 0. ]])
然后,相同的轉(zhuǎn)換實(shí)例可以被用與在訓(xùn)練過程中不可見的測試數(shù)據(jù):實(shí)現(xiàn)和訓(xùn)練數(shù)據(jù)一致的縮放和移位操作:
>>> X_test = np.array([[-3., -1., 4.]])
>>> X_test_minmax = min_max_scaler.transform(X_test)
>>> X_test_minmax
array([[-1.5 , 0. , 1.66666667]])
可以檢查縮放器(scaler)屬性,以找到在訓(xùn)練數(shù)據(jù)上學(xué)習(xí)到的轉(zhuǎn)換的確切性質(zhì):
>>> min_max_scaler.scale_
array([0.5 , 0.5 , 0.33...])
>>> min_max_scaler.min_
array([0. , 0.5 , 0.33...])
如果給MinMaxScaler
一個明確的feature_range=(min, max)
,則完整公式為:
X_std = (X - X.min(axis=0)) / (X.max(axis=0) - X.min(axis=0))
X_scaled = X_std * (max - min) + min
MaxAbsScaler
的工作方式都非常相似,通過除以每個特征中的最大值來使訓(xùn)練數(shù)據(jù)位于[-1, 1]
范圍內(nèi)的方式進(jìn)行縮放。這意味著它適用于已經(jīng)以零為中心的數(shù)據(jù)或稀疏數(shù)據(jù)。
這是在此縮放器上使用上一示例中少量數(shù)據(jù)的示例:
>>> X_train = np.array([[ 1., -1., 2.],
... [ 2., 0., 0.],
... [ 0., 1., -1.]])
...
>>> max_abs_scaler = preprocessing.MaxAbsScaler()
>>> X_train_maxabs = max_abs_scaler.fit_transform(X_train)
>>> X_train_maxabs
array([[ 0.5, -1. , 1. ],
[ 1. , 0. , 0. ],
[ 0. , 1. , -0.5]])
>>> X_test = np.array([[ -3., -1., 4.]])
>>> X_test_maxabs = max_abs_scaler.transform(X_test)
>>> X_test_maxabs
array([[-1.5, -1. , 2. ]])
>>> max_abs_scaler.scale_
array([2., 1., 2.])
與scale
一樣,如果您不想創(chuàng)建對象,該模塊進(jìn)一步提供了 minmax_scale
和maxabs_scale
函數(shù)。
中心化稀疏數(shù)據(jù)會破壞數(shù)據(jù)的稀疏結(jié)構(gòu),因此明智的做法是少做這樣的操作。但是,縮放稀疏輸入是有意義的,尤其是當(dāng)特征處于不同的縮放比例時。
MaxAbsScaler
和maxabs_scale
是專門為縮放稀疏數(shù)據(jù)而設(shè)計的,并且是實(shí)現(xiàn)此目的的推薦方法。然而,只要with_mean=False
顯式地傳遞給構(gòu)造函數(shù),scale
和StandardScaler
可以接受scipy.sparse
的矩陣作為輸入。否則,將引發(fā)ValueError
,因?yàn)殪o默居中會破壞稀疏性,并經(jīng)常由于無意中分配過多的內(nèi)存而使執(zhí)行崩潰。 RobustScaler
不能適合稀疏輸入,但是可以在稀疏輸入上使用transform
方法。
請注意,縮放器接受壓縮的稀疏行和壓縮的稀疏列格式(請參閱scipy.sparse.csr_matrix
和 scipy.sparse.csc_matrix
)。任何其他稀疏輸入都將轉(zhuǎn)換為“壓縮稀疏行”表示形式。為避免不必要的內(nèi)存副本,建議在初期選擇CSR或CSC表示形式。
最后,如果已經(jīng)中心化的數(shù)據(jù)足夠小,則使用稀疏矩陣的toarray
方法將輸入的數(shù)據(jù)顯式轉(zhuǎn)換為數(shù)組是另一種選擇。
如果數(shù)據(jù)中包含許多離群值,使用數(shù)據(jù)的均值和方差進(jìn)行縮放可能效果不佳。在這種情況下,可以使用 robust_scale
和RobustScaler
作為替代產(chǎn)品。他們對數(shù)據(jù)的中心和范圍的估計更可靠。
參考文獻(xiàn):
常見問題解答中提供了有關(guān)對數(shù)據(jù)進(jìn)行居中和縮放的重要性的進(jìn)一步討論:是否應(yīng)該對數(shù)據(jù)進(jìn)行標(biāo)準(zhǔn)化/標(biāo)準(zhǔn)化/縮放
Scaling vs Whitening
有時候獨(dú)立地中心化和縮放數(shù)據(jù)是不夠的,因?yàn)橄掠文P涂梢赃M(jìn)一步對特征間的線性獨(dú)立性做出一些假設(shè)。
要解決此問題,您可以使用
sklearn.decomposition.PCA
并指定參數(shù)whiten=True
以進(jìn)一步消除特征間的線性相關(guān)性。縮放一維數(shù)組
所有上述功能(即
scale
,minmax_scale
,和robust_scale
)都接受一維數(shù)組,這在某些特定的情況下很有用。
如果您擁有一個內(nèi)核 的內(nèi)核矩陣,可以在函數(shù)定義的特征空間中計算點(diǎn)積,[](https://scikit-learn.org.cn/view/724.html)類可以轉(zhuǎn)換該內(nèi)核矩陣使其包含由函數(shù) 定義的特征空間中的內(nèi)部乘積,然后刪除該空間中的均值。
有兩種類型的轉(zhuǎn)換是可行的:分位數(shù)轉(zhuǎn)換和冪轉(zhuǎn)換。分位數(shù)和冪變換都基于特征的單調(diào)變換,從而保持了每個特征值的秩。
分位數(shù)變換基于公式 將所有特征置于相同的期望分布中,其中 是特征的累積分布函數(shù),并且 是期望輸出分布的 分位數(shù)函數(shù)。該公式使用了以下兩個事實(shí):(i)如果 是具有連續(xù)累積分布函數(shù) 的隨機(jī)變量,則 均勻分布在上; (ii)如果 是在 上符合均勻分布的一個隨機(jī)變量,則 有分布。通過執(zhí)行秩變換,分位數(shù)變換可以平滑不尋常的分布,并且與縮放方法相比,離群值的影響較小。但是,它確實(shí)扭曲了特征之間的相關(guān)性和距離。
冪變換是一組參數(shù)變換,旨在將數(shù)據(jù)從任何分布映射到接近高斯分布。
QuantileTransformer
和quantile_transform
提供了一種非參數(shù)轉(zhuǎn)換,以將數(shù)據(jù)映射到值介于0和1之間的均勻分布:
>>> from sklearn.datasets import load_iris
>>> from sklearn.model_selection import train_test_split
>>> X, y = load_iris(return_X_y=True)
>>> X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=0)
>>> quantile_transformer = preprocessing.QuantileTransformer(random_state=0)
>>> X_train_trans = quantile_transformer.fit_transform(X_train)
>>> X_test_trans = quantile_transformer.transform(X_test)
>>> np.percentile(X_train[:, 0], [0, 25, 50, 75, 100])
array([ 4.3, 5.1, 5.8, 6.5, 7.9])
此特征對應(yīng)以厘米為單位的花萼長度。一旦應(yīng)用了分位數(shù)轉(zhuǎn)換,這些界標(biāo)便會接近先前定義的百分位數(shù):
>>> np.percentile(X_train_trans[:, 0], [0, 25, 50, 75, 100])
...
array([ 0.00... , 0.24..., 0.49..., 0.73..., 0.99... ])
可以在帶有類似注釋的獨(dú)立測試集上對此進(jìn)行確認(rèn):
>>> np.percentile(X_test[:, 0], [0, 25, 50, 75, 100])
...
array([ 4.4 , 5.125, 5.75 , 6.175, 7.3 ])
>>> np.percentile(X_test_trans[:, 0], [0, 25, 50, 75, 100])
...
array([ 0.01..., 0.25..., 0.46..., 0.60... , 0.94...])
在許多建模場景中,需要對數(shù)據(jù)集中特征進(jìn)行正態(tài)化。冪變換是一組參數(shù)化的單調(diào)變換,旨在將數(shù)據(jù)從任何分布映射到盡可能接近高斯分布,以穩(wěn)定方差并最小化偏度。
PowerTransformer
目前提供兩種這樣的冪變換,即Yeo-Johnson變換和Box-Cox變換。
以下為Yeo-Johnson 變換:
以下為Box-Cox變換:
Box-Cox僅可應(yīng)用于嚴(yán)格的正數(shù)據(jù)。在這兩種方法中,變換都是通過最大似然估計確定的的參數(shù)化。這是使用Box-Cox將從服從對數(shù)正態(tài)分布的樣本映射到正態(tài)分布的示例:
>>> pt = preprocessing.PowerTransformer(method='box-cox', standardize=False)
>>> X_lognormal = np.random.RandomState(616).lognormal(size=(3, 3))
>>> X_lognormal
array([[1.28..., 1.18..., 0.84...],
[0.94..., 1.60..., 0.38...],
[1.35..., 0.21..., 1.09...]])
>>> pt.fit_transform(X_lognormal)
array([[ 0.49..., 0.17..., -0.15...],
[-0.05..., 0.58..., -0.57...],
[ 0.69..., -0.84..., 0.10...]])
雖然以上示例將standardize
參數(shù)設(shè)置為False
,但 PowerTransformer
默認(rèn)將零均值,單位方差歸一化應(yīng)用于轉(zhuǎn)換后的輸出。
以下是適用于各種概率分布的Box-Cox和Yeo-Johnson的示例。請注意,將冪變換應(yīng)用于某些分布時,會獲得非常類似于高斯的結(jié)果,但是對于其他一些分布,結(jié)果是無效的。這突出了在轉(zhuǎn)換之前和之后可視化數(shù)據(jù)的重要性。
QuantileTransformer
通過設(shè)置 output_distribution='normal'
也可以將數(shù)據(jù)映射到正態(tài)分布。將先前的示例與iris數(shù)據(jù)集結(jié)合使用:
>>> quantile_transformer = preprocessing.QuantileTransformer(
... output_distribution='normal', random_state=0)
>>> X_trans = quantile_transformer.fit_transform(X)
>>> quantile_transformer.quantiles_
array([[4.3, 2. , 1. , 0.1],
[4.4, 2.2, 1.1, 0.1],
[4.4, 2.2, 1.2, 0.1],
...,
[7.7, 4.1, 6.7, 2.5],
[7.7, 4.2, 6.7, 2.5],
[7.9, 4.4, 6.9, 2.5]])
因此,輸入的中位數(shù)變?yōu)橐?為中心輸出的平均值。正常輸出被裁剪,以便輸入的最小和最大值(分別對應(yīng)于1e-7和1-1e-7分位數(shù))在轉(zhuǎn)換后不會變成無窮。
歸一化是將縮放單個樣本至單位范數(shù)的過程。如果計劃使用點(diǎn)積或任何其他核的二次形式來量化任何一對樣本的相似性,則此過程可能會很有用。
該假設(shè)是向量空間模型的基礎(chǔ),該向量空間模型經(jīng)常用于文本分類和內(nèi)容聚類中。
函數(shù)normalize
提供了一種快速簡便的方法,可以使用l1
或l2
范式在單個類似于數(shù)組的數(shù)據(jù)集上執(zhí)行此操作:
>>> X = [[ 1., -1., 2.],
... [ 2., 0., 0.],
... [ 0., 1., -1.]]
>>> X_normalized = preprocessing.normalize(X, norm='l2')
>>> X_normalized
array([[ 0.40..., -0.40..., 0.81...],
[ 1. ..., 0. ..., 0. ...],
[ 0. ..., 0.70..., -0.70...]])
preprocessing
模塊還提供了一個實(shí)用程序類Normalizer
,它使用Transformer
API 來實(shí)現(xiàn)相同的操作 (即使在這種情況下fit
方法無用:該類是無狀態(tài)的,因?yàn)榇瞬僮鳘?dú)立地處理樣本)。
因此,該類適用于 sklearn.pipeline.Pipeline
的前期步驟:
>>> normalizer = preprocessing.Normalizer().fit(X) # fit does nothing
>>> normalizer
Normalizer()
然后,可以將normalizer實(shí)例用作任何轉(zhuǎn)換器的樣本矢量:
>>> normalizer.transform(X)
array([[ 0.40..., -0.40..., 0.81...],
[ 1. ..., 0. ..., 0. ...],
[ 0. ..., 0.70..., -0.70...]])
>>> normalizer.transform([[-1., 1., 0.]])
array([[-0.70..., 0.70..., 0. ...]])
注意:L2歸一化也稱為空間符號預(yù)處理。
稀疏輸入
normalize
和Normalizer
都接受來自scipy.sparse的密集數(shù)組式數(shù)據(jù)和稀疏矩陣作為輸入。對于稀疏輸入,在將數(shù)據(jù)饋入有效的Cython例程之前,將數(shù)據(jù)轉(zhuǎn)換為“壓縮的稀疏行”表示形式(請參閱
scipy.sparse.csr_matrix
參考資料)。為避免不必要的內(nèi)存復(fù)制,建議選擇上游的CSR表示形式。
通常,特征不是連續(xù)值,而是分類值。例如,一個人可能具備以下特征,["male", "female"]``["from Europe", "from US", "from Asia"]``["uses Firefox", "uses Chrome", "uses Safari", "uses Internet Explorer"]
。這樣的特征可以有效地編碼為整數(shù),例如 ["male", "from US", "uses Internet Explorer"]
可以表示為[0, 1, 3]
,而["female", "from Asia", "uses Chrome"]
表示為[1, 2, 1]
。
要將分類特征轉(zhuǎn)換為這樣的整數(shù)代碼,我們可以使用 OrdinalEncoder
。此估計器將每個分類特征轉(zhuǎn)換為一個新的整數(shù)特征(0到n_categories-1):
>>> enc = preprocessing.OrdinalEncoder()
>>> X = [['male', 'from US', 'uses Safari'], ['female', 'from Europe', 'uses Firefox']]
>>> enc.fit(X)
OrdinalEncoder()
>>> enc.transform([['female', 'from US', 'uses Safari']])
array([[0., 1., 1.]])
但是,此類整數(shù)表示不能直接在所有的scikit-learn估計器使用,因?yàn)檫@樣連續(xù)型數(shù)值的輸入,估計器會將類別解釋為有序的,而通常是無序的(例如,瀏覽器的類別數(shù)據(jù)是任意無序的)。
將分類特征轉(zhuǎn)換為可與scikit-learn估計器一起使用的特征的另一種方法是使用one-of-K,也稱為獨(dú)熱或偽編碼。這種類型的編碼可以通過OneHotEncoder
來獲得,它將具有n_categories
個可能值的每個分類特征轉(zhuǎn)換為n_categories
個二進(jìn)制特征,其中一個位置為1,所有其他位置為0。
繼續(xù)上面的示例:
>>> enc = preprocessing.OneHotEncoder()
>>> X = [['male', 'from US', 'uses Safari'], ['female', 'from Europe', 'uses Firefox']]
>>> enc.fit(X)
OneHotEncoder()
>>> enc.transform([['female', 'from US', 'uses Safari'],
... ['male', 'from Europe', 'uses Safari']]).toarray()
array([[1., 0., 0., 1., 0., 1.],
[0., 1., 1., 0., 0., 1.]])
默認(rèn)情況下,每個特征可以采用的值是從數(shù)據(jù)集中自動推斷出來的,并且可以在categories_
屬性中找到:
[array(['female', 'male'], dtype=object), array(['from Europe', 'from US'], dtype=object), array(['uses Firefox', 'uses Safari'], dtype=object)]
可以使用參數(shù)categories
顯式的指定,我們的數(shù)據(jù)集中有兩種性別,四個可能的大陸和四個Web瀏覽器:
>>> genders = ['female', 'male']
>>> locations = ['from Africa', 'from Asia', 'from Europe', 'from US']
>>> browsers = ['uses Chrome', 'uses Firefox', 'uses IE', 'uses Safari']
>>> enc = preprocessing.OneHotEncoder(categories=[genders, locations, browsers])
>>> # Note that for there are missing categorical values for the 2nd and 3rd
>>> # feature
>>> X = [['male', 'from US', 'uses Safari'], ['female', 'from Europe', 'uses Firefox']]
>>> enc.fit(X)
OneHotEncoder(categories=[['female', 'male'],
['from Africa', 'from Asia', 'from Europe',
'from US'],
['uses Chrome', 'uses Firefox', 'uses IE',
'uses Safari']])
>>> enc.transform([['female', 'from Asia', 'uses Chrome']]).toarray()
array([[1., 0., 0., 1., 0., 0., 1., 0., 0., 0.]])
如果訓(xùn)練數(shù)據(jù)有可能缺少分類特征,則通常最好指定handle_unknown='ignore'
而不是如上所述手動設(shè)置categories
。如果指定 handle_unknown='ignore'
且在轉(zhuǎn)換過程中遇到未知類別,則不會引發(fā)任何錯誤,但此功能生成的一鍵編碼列將全為零(handle_unknown='ignore'
僅支持一鍵編碼):
>>> enc = preprocessing.OneHotEncoder(handle_unknown='ignore')
>>> X = [['male', 'from US', 'uses Safari'], ['female', 'from Europe', 'uses Firefox']]
>>> enc.fit(X)
OneHotEncoder(handle_unknown='ignore')
>>> enc.transform([['female', 'from Asia', 'uses Chrome']]).toarray()
array([[1., 0., 0., 0., 0., 0.]])
也可以通過使用 drop
參數(shù)將每一列編碼為n_categories - 1
列而不是n_categories
列。該參數(shù)允許用戶為每個要刪除的特征指定一個類別。在某些分類器中,這有助于避免輸入的矩陣存在共線性。例如,當(dāng)使用非正則回歸(LinearRegression
)時,此類功能很有用,因?yàn)楣簿€性會導(dǎo)致協(xié)方差矩陣不可逆。當(dāng)此參數(shù)不為None時,必須設(shè)置handle_unknown
為 :error
>>> X = [['male', 'from US', 'uses Safari'],
... ['female', 'from Europe', 'uses Firefox']]
>>> drop_enc = preprocessing.OneHotEncoder(drop='first').fit(X)
>>> drop_enc.categories_
[array(['female', 'male'], dtype=object), array(['from Europe', 'from US'], dtype=object), array(['uses Firefox', 'uses Safari'], dtype=object)]
>>> drop_enc.transform(X).toarray()
array([[1., 1., 1.],
[0., 0., 0.]])
有時可能只想刪除具有2個類別特征的兩列之一。在這種情況下,可以設(shè)置參數(shù)drop='if_binary'
。
>>> X = [['male', 'US', 'Safari'],
... ['female', 'Europe', 'Firefox'],
... ['female', 'Asia', 'Chrome']]
>>> drop_enc = preprocessing.OneHotEncoder(drop='if_binary').fit(X)
>>> drop_enc.categories_
[array(['female', 'male'], dtype=object), array(['Asia', 'Europe', 'US'], dtype=object), array(['Chrome', 'Firefox', 'Safari'], dtype=object)]
>>> drop_enc.transform(X).toarray()
array([[1., 0., 0., 1., 0., 0., 1.],
[0., 0., 1., 0., 0., 1., 0.],
[0., 1., 0., 0., 1., 0., 0.]])
在轉(zhuǎn)換后的X
中,第一列是類別為“ male” /“ female”的特征編碼,而其余六列則是分別具有3個類別2個特征的編碼。
請參閱從字典中加載特征以獲取表示為字典而不是標(biāo)量的分類特征。
離散化 (也稱為量化或分箱)提供了一種將連續(xù)特征劃分為離散值的方法。某些具有連續(xù)特征的數(shù)據(jù)集可能會從離散化中受益,因?yàn)殡x散化可以將連續(xù)屬性的數(shù)據(jù)集轉(zhuǎn)換為僅具有名義屬性的數(shù)據(jù)集。
One-hot編碼的離散特征可以使模型更具表現(xiàn)力,同時保持可解釋性。例如,使用離散器的預(yù)處理可以將非線性引入線性模型。
KBinsDiscretizer
將特征離散到k
個容器中:
>>> X = np.array([[ -3., 5., 15 ],
... [ 0., 6., 14 ],
... [ 6., 3., 11 ]])
>>> est = preprocessing.KBinsDiscretizer(n_bins=[3, 2, 2], encode='ordinal').fit(X)
默認(rèn)情況下,輸出是one-hot編碼成的稀疏矩陣(請參閱編碼分類特征),并且可以使用encode
參數(shù)進(jìn)行配置。對于每個特征,在箱體的邊緣和箱體數(shù)量是在fit
過程中計算出來的,它們將定義區(qū)間。因此,對于當(dāng)前示例,這些區(qū)間定義為:
特征1:
特征2:
特征3:
根據(jù)這些bin區(qū)間,X
轉(zhuǎn)換如下:
>>> est.transform(X)
array([[ 0., 1., 1.],
[ 1., 1., 1.],
[ 2., 0., 0.]])
結(jié)果數(shù)據(jù)集包含可以在sklearn.pipeline.Pipeline
進(jìn)一步使用的序數(shù)屬性。
離散化類似于構(gòu)造連續(xù)數(shù)據(jù)的直方圖。但是,直方圖著重于對落入特定區(qū)域的特征進(jìn)行計數(shù),而離散化則著重于為這些區(qū)域分配特征值。
KBinsDiscretizer
可以通過strategy
參數(shù)選擇實(shí)現(xiàn)不同的分箱策略。“uniform”策略使用固定寬度的箱體?!皅uantile”策略使用分位數(shù)值在每個特征中具有均等填充的bin。“ kmeans”策略基于對每個特征執(zhí)行獨(dú)立的k均值聚類過程來定義箱體。
例子:
特征二值化是將數(shù)字特征用閾值過濾以獲得布爾值的過程。這對于下游概率估計器很有用,這些估計器假設(shè)輸入數(shù)據(jù)是根據(jù)多元Bernoulli分布進(jìn)行分布的。例如sklearn.neural_network.BernoulliRBM
這個例子。
即使歸一化計數(shù)(又稱術(shù)語頻率)或TF-IDF值的特征通常在實(shí)踐中表現(xiàn)得稍好一些,在文本處理過程中常常使用二進(jìn)制特征值(可能是為了簡化概率推理)。
至于Normalizer
,實(shí)用程序類 Binarizer
在 sklearn.pipeline.Pipeline
的前期步驟中使用。由于每個樣本都獨(dú)立于其他樣本進(jìn)行處理,因此fit
方法無濟(jì)于事:
>>> X = [[ 1., -1., 2.],
... [ 2., 0., 0.],
... [ 0., 1., -1.]]
>>> binarizer = preprocessing.Binarizer().fit(X) # fit does nothing
>>> binarizer
Binarizer()
>>> binarizer.transform(X)
array([[1., 0., 1.],
[1., 0., 0.],
[0., 1., 0.]])
可以調(diào)整二值化器的閾值:
>>> binarizer = preprocessing.Binarizer(threshold=1.1)
>>> binarizer.transform(X)
array([[0., 0., 1.],
[1., 0., 0.],
[0., 0., 0.]])
對于StandardScaler
和Normalizer
類,預(yù)處理模塊提供了一個伴隨函數(shù)binarize
,以便在不需要轉(zhuǎn)換器API時使用。
請注意,當(dāng)k = 2
且bin邊緣處于該閾值threshold
時,Binarizer
與KBinsDiscretizer
類似。
稀疏輸入
binarize
和Binarizer
接受來自scipy.sparse的密集數(shù)組數(shù)據(jù)和稀疏矩陣作為輸入。對于稀疏輸入,數(shù)據(jù)將轉(zhuǎn)換為“壓縮的稀疏行”表示形式(請參見參考資料
scipy.sparse.csr_matrix
)。為避免不必要的內(nèi)存復(fù)制,建議選擇上游的CSR表示形式。
插補(bǔ)缺失值的工具在插補(bǔ)缺失值中進(jìn)行了討論。
通常,考慮輸入數(shù)據(jù)的非線性特征會增加模型的復(fù)雜性。多項(xiàng)式特征是一種簡單而常用的方法,它可以獲取特征的高階和相互作用項(xiàng)。它在PolynomialFeatures
中實(shí)現(xiàn):
>>> import numpy as np
>>> from sklearn.preprocessing import PolynomialFeatures
>>> X = np.arange(6).reshape(3, 2)
>>> X
array([[0, 1],
[2, 3],
[4, 5]])
>>> poly = PolynomialFeatures(2)
>>> poly.fit_transform(X)
array([[ 1., 0., 1., 0., 0., 1.],
[ 1., 2., 3., 4., 6., 9.],
[ 1., 4., 5., 16., 20., 25.]])
特征已經(jīng)從轉(zhuǎn)換成。
在某些情況下,僅需要特征之間的交互項(xiàng),并且可以通過設(shè)置interaction_only=True
獲得:
>>> X = np.arange(9).reshape(3, 3)
>>> X
array([[0, 1, 2],
[3, 4, 5],
[6, 7, 8]])
>>> poly = PolynomialFeatures(degree=3, interaction_only=True)
>>> poly.fit_transform(X)
array([[ 1., 0., 1., 2., 0., 0., 2., 0.],
[ 1., 3., 4., 5., 12., 15., 20., 60.],
[ 1., 6., 7., 8., 42., 48., 56., 336.]])
X的特征已從 轉(zhuǎn)換成。
請注意,使用多項(xiàng)式內(nèi)核函數(shù)時,多項(xiàng)式特征在 kernel methods 中被隱含調(diào)用(例如sklearn.svm.SVC
,sklearn.decomposition.KernelPCA
)。
有關(guān)使用創(chuàng)建的多項(xiàng)式特征的Ridge回歸的信息,請參見多項(xiàng)式插值。
通常,需要將現(xiàn)有的Python函數(shù)轉(zhuǎn)換為轉(zhuǎn)換器,以幫助進(jìn)行數(shù)據(jù)清理或處理??梢允褂?a rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" style="text-decoration: none; color: #1e6bb8; word-wrap: break-word; font-weight: bold; border-bottom: 1px solid #1e6bb8;">FunctionTransformer
將任意函數(shù)轉(zhuǎn)化成轉(zhuǎn)換器。例如,要構(gòu)建在管道中應(yīng)用對數(shù)轉(zhuǎn)換的轉(zhuǎn)換器,請執(zhí)行以下操作:
>>> import numpy as np
>>> from sklearn.preprocessing import FunctionTransformer
>>> transformer = FunctionTransformer(np.log1p, validate=True)
>>> X = np.array([[0, 1], [2, 3]])
>>> transformer.transform(X)
array([[0. , 0.69314718],
[1.09861229, 1.38629436]])
在進(jìn)行轉(zhuǎn)換之前需要通過設(shè)置check_inverse=True
和調(diào)用fit
來確保func
和inverse_func
是彼此的逆。請注意,一個警告會被拋出,并且可以通過一個 filterwarnings
將其轉(zhuǎn)化為錯誤。
>>> import warnings
>>> warnings.filterwarnings("error", message=".*check_inverse*.",
... category=UserWarning, append=False)
有關(guān)演示如何使用FunctionTransformer
進(jìn)行自定義特征選擇的完整代碼示例,請參見使用FunctionTransformer選擇列
更多建議: