sklearn數據預處理


 

 

 

1、數據預處理概述

 

數據預處理是構建特征工程的基本環境,並且是提高算法精確度的有效手段。數據預處理需要根據數據本身的特性進行,不同的格式有不同的處理要求,比如無效的要剔除,缺失值要回填和冗余維度的選擇等。大致主要分為三個步驟:數據的准備、轉換和輸出。本文主要利用sklearn講解轉換數據的常用方法。

 

2、無量綱化

 

在機器學習算法實踐中,我們往往有着將不同規格的數據轉換到同一規格,或不同分布的數據轉換到某個特定分布的需求,這種需求統稱為將數據無量綱化。數據的無量綱化可以是線性的,也可以是非線性的。線性的無量綱化包括中心化(Zero-centered或者Mean-subtraction)處理和縮放處理(Scale)。中心化的本質是讓所有記錄減去一個固定值,即讓數據樣本數據平移到某個位置。縮放的本質是通過除以一個固定值,將數據固定在某個范圍之中,取對數也算是一種縮放處理。

 

(1)preprocessing.MinMaxScaler類

 

在scikit-learn中,可以通過數據MinMaxScaler來調整數據尺度,將屬性縮放到一個指定的范圍,或者將數據標准化並將數據都聚集到0附近,方差為1。即先將數據移動了$min(x)$個單位,按極差$max(x)-min(x)$縮放,則數據會被收斂到[0,1]之間。而這個過程,就叫做數據歸一化。歸一化之后的數據服從正態分布,公式如下:

 
$$x^*=\frac{x-min(x)}{max(x)-min(x)}$$
In [170]:
from sklearn.preprocessing import MinMaxScaler  #導入類
data = [[-1, 2], [-0.5, 6], [0, 10], [1, 18]]      #測試數據准備
scaler = MinMaxScaler()                            #實例化
scaler = scaler.fit(data)                          #fit,在這里本質是生成min(x)和max(x)
result = scaler.transform(data)                    #通過接口導出結果
result
Out[170]:
array([[0.  , 0.  ],
       [0.25, 0.25],
       [0.5 , 0.5 ],
       [1.  , 1.  ]])
In [171]:
result_ = scaler.fit_transform(data)                #訓練和導出結果一步達成
result
Out[171]:
array([[0.  , 0.  ],
       [0.25, 0.25],
       [0.5 , 0.5 ],
       [1.  , 1.  ]])
In [172]:
scaler.inverse_transform(result)                    #將歸一化后的結果逆轉
Out[172]:
array([[-1. ,  2. ],
       [-0.5,  6. ],
       [ 0. , 10. ],
       [ 1. , 18. ]])
In [173]:
#使用MinMaxScaler的參數feature_range實現將數據歸一化到[0,1]以外的范圍中
data = [[-1, 2], [-0.5, 6], [0, 10], [1, 18]]
scaler = MinMaxScaler(feature_range=[5,10])         #依然實例化
result = scaler.fit_transform(data)                 #fit_transform一步導出結果
result
Out[173]:
array([[ 5.  ,  5.  ],
       [ 6.25,  6.25],
       [ 7.5 ,  7.5 ],
       [10.  , 10.  ]])
 

(2)preprocessing.StandardScaler類

 

正態化數據是有效的處理符合高斯分布的數據的手段,輸出結果以0為中位數,方差為1,並作為假定數據符合高斯分布的算法的輸入。當數據$x$按均值$\mu$中心化后,再按標准差$\sigma$縮放,數據就會服從為均值為0,方差為1的正態分布(即標准正態分布),而這個過程,就叫做數據標准化(Standardization,又稱Z-score normalization),公式如下:

 
$$x^*=\frac{x-\mu}{\sigma}$$
In [174]:
from sklearn.preprocessing import StandardScaler   #導入包
data = [[-1, 2], [-0.5, 6], [0, 10], [1, 18]]         #測試數據准備
scaler = StandardScaler()                             #實例化
scaler.fit(data)                                      #fit,本質是生成均值和方差
Out[174]:
StandardScaler(copy=True, with_mean=True, with_std=True)
In [175]:
scaler.mean_                             #查看均值的屬性mean_
Out[175]:
array([-0.12,  9.  ])
In [176]:
scaler.var_                             #查看方差的屬性var_
Out[176]:
array([ 0.55, 35.  ])
In [177]:
x_std = scaler.transform(data)         #通過接口導出結果
x_std
Out[177]:
array([[-1.18, -1.18],
       [-0.51, -0.51],
       [ 0.17,  0.17],
       [ 1.52,  1.52]])
In [178]:
x_std.mean()                           #導出的結果是一個數組,用mean()查看均值
Out[178]:
0.0
In [179]:
x_std.std()                            #用std()查看方差
Out[179]:
1.0
In [180]:
scaler.fit_transform(data)             #使用fit_transform(data)一步達成結果
Out[180]:
array([[-1.18, -1.18],
       [-0.51, -0.51],
       [ 0.17,  0.17],
       [ 1.52,  1.52]])
In [181]:
scaler.inverse_transform(x_std)        #使用inverse_transform逆轉標准化
Out[181]:
array([[-1. ,  2. ],
       [-0.5,  6. ],
       [ 0. , 10. ],
       [ 1. , 18. ]])
 

注意:

1.對於StandardScaler和MinMaxScaler來說,空值NaN會被當做是缺失值,在fit的時候忽略,在transform的時候保持缺失NaN的狀態顯示。

2.fit接口中,依然只允許導入至少二維數組,一維數組導入會報錯。

 

3、缺失值處理

 

數據處理過程中,不可避免的會出現很多空值,這時就需要我們通過業務經驗選擇性的進行數值填充,盡量保證模型的准確性。

 

參數說明:

class sklearn.impute.SimpleImputer(missing_values=nan, strategy=’mean’, fill_value=None, verbose=0, copy=True)

1.missing_values:告訴SimpleImputer,數據中的缺失值長什么樣,默認空值np.nan

2.strategy:我們填補缺失值的策略,默認均值。

  • 輸入“mean”使用均值填補(僅對數值型特征可用)

  • 輸入“median"用中值填補(僅對數值型特征可用)

  • 輸入"most_frequent”用眾數填補(對數值型和字符型特征都可用)

  • 輸入“constant"表示請參考參數“fill_value"中的值(對數值型和字符型特征都可用)

3.fill_value:當參數startegy為”constant"的時候可用,可輸入字符串或數字表示要填充的值,常用0。

4.copy:默認為True,將創建特征矩陣的副本,反之則會將缺失值填補到原本的特征矩陣中去。

In [ ]:
#缺失值處理代碼
from sklearn.impute import SimpleImputer
import pandas as pd
#導入數據
filename = 'pima_indian.csv'
names = ['preg','plas','pres','skin','test','mass','pedi','age','class']
data = pd.read_csv(filename,names=names)
data.head()
 

image

In [183]:
#以填補年齡為例,sklearn當中特征矩陣必須是二維
Age = data.loc[:,"age"].values.reshape(-1,1)
Age[0:5]
Out[183]:
array([[50],
       [31],
       [32],
       [21],
       [33]], dtype=int64)
In [184]:
#實例化,默認均值填補
imp_mean = SimpleImputer()                             
imp_mean = imp_mean.fit_transform(Age)   
data.loc[:,"age"] = imp_median
In [185]:
#用中位數填補
imp_median = SimpleImputer(strategy="median")           
imp_median = imp_median.fit_transform(Age) 
data.loc[:,"age"] = imp_median
In [186]:
#用眾數填補
imp_median = SimpleImputer(strategy="most_frequent")           
imp_median = imp_median.fit_transform(Age) 
data.loc[:,"age"] = imp_median
In [187]:
#用0填補
imp_0 = SimpleImputer(strategy="constant",fill_value=0)
imp_0 = imp_0.fit_transform(Age) 
data.loc[:,"age"] = imp_0
 

當然,此處均已年齡這個特征為例進行填充,實際應用的時候要根據業務經驗來進行選擇填充缺失值的方案。

 

4、分類型特征處理

 

由於很多的機器學習算法是計算數值型數據的,但現實情況下特征數據中包含很多文本數據,又不能忽略掉。比如說學歷的取值可以是["小學",“初中”,“高中”,"大學"]。在這種情況下,為了讓數據適應算法和庫,我們必須將數據進行編碼,即是說,將文字型數據轉換為數值型。

 

首先介紹下編碼變量類型:

名義變量:變量取值是相互獨立的,彼此之間完全沒有聯系。比如性別男和性別女。

有序變量:變量取值不完全獨立的,彼此之間有一些聯系,但沒有計算關系。比如本科、碩士、博士。

有距變量:各個取值之間是聯系的,且是可以互相計算的。比如重量10kg、20kg、30kg。

 

(1)preprocessing.LabelEncoder類

標簽專用,能夠將分類轉換為分類數值,是對不連續的數字或者文本進行編號(連續的會是同一個編號)。

In [ ]:
from sklearn.preprocessing import LabelEncoder
import pandas as pd
#導入數據
filename = 'info.csv'
names = ['segment','weight','building','class']
data = pd.read_csv(filename,names=names,index_col=0)
data.head()
 

image

In [189]:
#LabelEncoder編碼標簽
y = data.iloc[:,-1]                #要輸入的是標簽,不是特征矩陣,所以允許一維
le = LabelEncoder()                #實例化
le = le.fit(y)                     #導入數據
label = le.transform(y)            #transform接口調取結果
label
Out[189]:
array([0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0])
In [190]:
le.classes_                        #屬性.classes_查看標簽中究竟有多少類別
Out[190]:
array(['否', '是'], dtype=object)
In [191]:
data.iloc[:,-1] = label            #讓標簽等於我們運行出來的結果
 

(2)preprocessing.OrdinalEncoder類

特征專用,能夠將分類特征轉換為分類數值,其主要處理有序變量。

In [193]:
#OrdinalEncoder編碼有序變量{青年,中年,老年}
Ordinal = OrdinalEncoder()
Ordinal = Ordinal.fit(data.iloc[:,0:1])
In [194]:
Ordinal.categories_                               #接口categories_對應LabelEncoder的接口classes_,一模一樣的功能
Out[194]:
[array(['中年', '老年', '青年'], dtype=object)]
In [195]:
data.iloc[:,0:1] = OrdinalEncoder().fit_transform(data.iloc[:,0:1])   #讓特征數據等於我們運行出來的結果
 

(3)preprocessing.OneHotEncoder類

獨熱編碼,創建啞變量,其處理名義變量

In [197]:
from sklearn.preprocessing import OneHotEncoder
enc = OneHotEncoder(categories='auto')
enc.fit(data.iloc[:,1:3])
ans = enc.transform(data.iloc[:,1:3]).toarray() 
ans[0:5]           #顯示編碼后的前5行
Out[197]:
array([[1., 0., 0., 1., 0.],
       [0., 1., 0., 1., 0.],
       [0., 0., 1., 1., 0.],
       [0., 0., 1., 0., 1.],
       [0., 1., 0., 1., 0.]])
 

參數說明:

OneHotEncoder(n_values=’auto’, categorical_features=’all’, dtype=<class ‘numpy.float64’>, sparse=True, handle_unknown=’error’)

1.n_values=’auto’,表示每個特征使用幾維的數值由數據集自動推斷,即幾種類別就使用幾位來表示。可以設定維度比正常維度多,將未編碼到的數據分類到一起。

2.categorical_features = 'all',這個參數指定了對哪些特征進行編碼,默認對所有類別都進行編碼。

3.dtype=<class ‘numpy.float64’> 表示編碼數值格式,默認是浮點型。

4.sparse=True 表示編碼的格式,默認為True,即為稀疏的格式,指定False 則就不用 toarray() 了。

5.handle_unknown=’error’,其值可以指定為 "error" 或者 "ignore",即如果碰到未知的類別,是返回一個錯誤還是忽略它。

 

5、連續型特征處理

 

(1)sklearn.preprocessing.Binarizer類

根據閾值將數據二值化(將特征值設置為0或1),用於處理連續型變量。大於閾值的值映射為1,而小於或等於閾值的值映射為0。默認閾值為0時,特征中所有的正值都映射到1。二值化是對文本計數數據的常見操作,分析人員可以決定僅考慮某種現象的存在與否。它還可以用作考慮布爾隨機變量的估計器的預處理步驟(例如,使用貝葉斯設置中的伯努利分布建模)。

In [198]:
from sklearn import preprocessing
import numpy as np
# 創建一組特征數據,每一行表示一個樣本,每一列表示一個特征
x = np.array([[1., -1., 2.],
              [2., 0., 0.],
              [0., 1., -1.]])
 
binarizer = preprocessing.Binarizer().fit(x)
binarizer.transform(x)
Out[198]:
array([[1., 0., 1.],
       [1., 0., 0.],
       [0., 1., 0.]])
In [199]:
#當然也可以自己設置這個閥值,只需傳出參數threshold即可
binarizer = preprocessing.Binarizer(threshold=1.5)
binarizer.fit_transform(x)
Out[199]:
array([[0., 0., 1.],
       [1., 0., 0.],
       [0., 0., 0.]])
 

(2)preprocessing.KBinsDiscretizer

這是將連續型變量划分為分類變量的類,能夠將連續型變量排序后按順序分箱后編碼。總共包含三個重要參數:

 

1.n_bins:每個特征中分箱的個數,默認5,一次會被運用到所有導入的特征

2.encode:編碼的方式,默認onehot。

  • onehot:做啞變量,之后返回一個稀疏矩陣,每一列是一個特征中的一個類別,含有該 類別的樣本表示為1,不含的表示為0

  • ordinal:每個特征的每個箱都被編碼為一個整數,返回每一列是一個特征,每個特征下含 有不同整數編碼的箱的矩陣

  • onehot-dense:做啞變量,之后返回一個密集數組。

3.strategy:用來定義箱寬的方式,默認quantile。

  • uniform:表示等寬分箱,即每個特征中的每個箱的最大值之間的差為 (特征.max() - 特征.min())/(n_bins)

  • quantile:表示等位分箱,即每個特征中的每個箱內的樣本數量都相同

  • kmeans:表示按聚類分箱,每個箱中的值到最近的一維k均值聚類的簇心得距離都相同

In [200]:
from sklearn.preprocessing import KBinsDiscretizer
import numpy as np
# 創建一組特征數據,每一行表示一個樣本,每一列表示一個特征
X = np.array([[1., -1., 2.],
              [2., 0., 0.],
              [0., 1., -1.]])
est = KBinsDiscretizer(n_bins=3, encode='ordinal', strategy='uniform')
est.fit_transform(X)
Out[200]:
array([[1., 0., 2.],
       [2., 1., 1.],
       [0., 2., 0.]])
In [201]:
#查看轉換后分的箱:變成了一列中的三箱
set(est.fit_transform(X).ravel())
Out[201]:
{0.0, 1.0, 2.0}
In [202]:
est = KBinsDiscretizer(n_bins=3, encode='onehot', strategy='uniform')
#查看轉換后分的箱:變成了啞變量
est.fit_transform(X).toarray()
Out[202]:
array([[0., 1., 0., 1., 0., 0., 0., 0., 1.],
       [0., 0., 1., 0., 1., 0., 0., 1., 0.],
       [1., 0., 0., 0., 0., 1., 1., 0., 0.]])


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM