特征工程-1-數(shù)據(jù)預處理

0、前言

數(shù)據(jù)和特征決定了機器學習的上限,而模型和算法只是逼近這個上限而已。

由此可見,特征工程在機器學習中占有相當重要的地位。在實際應用當中,可以說特征工程是機器學習成功的關鍵。

那特征工程是什么?

特征工程是利用數(shù)據(jù)領域的相關知識來創(chuàng)建能夠使機器學習算法達到最佳性能的特征的過程。

雖然我們也有自動的機器學習框架,如 AutoML(但該框架也強調(diào)了它需要好的特征才能跑出好的效果?。?。特征工程永不過時,即使對于自動化方法,其中也有一部分經(jīng)常需要根據(jù)數(shù)據(jù)類型、領域和要解決的問題而設計特殊的特征。

特征工程又包含了Data PreProcessing(數(shù)據(jù)預處理)、Feature Extraction(特征提?。?、Feature Selection(特征選擇)和Feature construction(特征構(gòu)造)等子問題,而數(shù)據(jù)預處理又包括了數(shù)據(jù)清洗和特征預處理等子問題。詳情可參考下圖:


特征與處理的步驟

本篇文章我們討論特征預處理中的無量綱化、特征分桶、統(tǒng)計變換和特征編碼。

1、數(shù)據(jù)無量綱化

1.1、 數(shù)據(jù)無量綱化的介紹

Tree-based models doesn’t depend on scaling

Non-tree-based models hugely depend on scaling

在機器學習算法實踐中,我們往往有著將不同規(guī)格的數(shù)據(jù)轉(zhuǎn)換到同一規(guī)格,或不同分布的數(shù)據(jù)轉(zhuǎn)換到某個特定分布的需求,這種需求統(tǒng)稱為將數(shù)據(jù)“無量綱化”。譬如梯度和矩陣為核心的算法中,譬如邏輯回歸,支持向量機,神經(jīng)網(wǎng)絡,無量綱化可以加快求解速度;而在距離類模型,譬如K近鄰,K-Means聚類中,無量綱化可以幫我們提升模型精度,避免某一個取值范圍特別大的特征對距離計算造成影響。(一個特例是決策樹和樹的集成算法們,對決策樹我們不需要無量綱化,決策樹可以把任意數(shù)據(jù)都處理得很好。)

數(shù)據(jù)的無量綱化可以是線性的,也可以是非線性的。線性的無量綱化包括中心化(Zero-centered或者Mean-subtraction)處理和縮放處理(Scale)。中心化的本質(zhì)是讓所有記錄減去一個固定值,即讓數(shù)據(jù)樣本數(shù)據(jù)平移到某個位置??s放的本質(zhì)是通過除以一個固定值,將數(shù)據(jù)固定在某個范圍之中,取對數(shù)也算是一種縮放處理。常見的無量綱化方法有標準化和歸一化。

數(shù)據(jù)標準化的原因:

  • 某些算法要求樣本具有零均值和單位方差;
  • 需要消除樣本不同屬性具有不同量級時的影響。

    • 歸一化有可能提高精度;
      數(shù)量級的差異將導致量級較大的屬性占據(jù)主導地位,從而與實際情況相悖(比如這時實際情況是值域范圍小的特征更重要);

    • 歸一化有可能提升收斂速度;
      數(shù)量級的差異將導致迭代收斂速度減慢,當使用梯度下降法尋求最優(yōu)解時,很有可能走“之字型”路線(垂直等高線走),從而導致需要迭代很多次才能收斂;

    • 依賴于樣本距離的算法對于數(shù)據(jù)的數(shù)量級非常敏感。



比較這兩個圖,前者是沒有經(jīng)過歸一化的,在梯度下降的過程中,走的路徑更加的曲折,而第二個圖明顯路徑更加平緩,收斂速度更快。

1.2、數(shù)據(jù)標準化(Standardization)

1)定義

標準化數(shù)據(jù)通過減去均值然后除以方差(或標準差),這種數(shù)據(jù)標準化方法經(jīng)過處理后數(shù)據(jù)符合標準正態(tài)分布,即均值為0,標準差為1,轉(zhuǎn)化函數(shù)為:

x =\frac {(x - ??)}{??}

適用于:如果數(shù)據(jù)的分布本身就服從正態(tài)分布,就可以用這個方法。

通常這種方法基本可用于有outlier的情況,但是,在計算方差和均值的時候outliers仍然會影響計算。所以,在出現(xiàn)outliers的情況下可能會出現(xiàn)轉(zhuǎn)換后的數(shù)的不同feature分布完全不同的情況。

2)效果

如下圖,經(jīng)過StandardScaler之后,橫坐標與縱坐標的分布出現(xiàn)了很大的差異,這可能是outliers造成的。

標準化1.png

3)優(yōu)缺點

優(yōu)點:

Z-Score最大的優(yōu)點就是簡單,容易計算,Z-Score能夠應用于數(shù)值型的數(shù)據(jù),并且不受數(shù)據(jù)量級的影響,因為它本身的作用就是消除量級給分析帶來的不便。

缺點:

  • 估算Z-Score需要總體的平均值與方差,但是這一值在真實的分析與挖掘中很難得到,大多數(shù)情況下是用樣本的均值與標準差替代;
  • Z-Score對于數(shù)據(jù)的分布有一定的要求,正態(tài)分布是最有利于Z-Score計算的;
  • Z-Score消除了數(shù)據(jù)具有的實際意義,A的Z-Score與B的Z-Score與他們各自的分數(shù)不再有關系,因此Z-Score的結(jié)果只能用于比較數(shù)據(jù)間的結(jié)果,數(shù)據(jù)的真實意義還需要還原原值;
  • 在存在異常值時無法保證平衡的特征尺度。

4)實現(xiàn)代碼-sklearn中的StandardScaler:

from sklearn.preprocessing import StandardScaler
import numpy as np

np.random.seed(1)
data = np.random.randint(0,100,10).reshape(-1, 2)
print(data)
# data = [[-1, 3], [-0.5, 96], [0, 10], [1, 18]]

scaler = StandardScaler()               #實例化
scaler.fit(data)                        #fit,本質(zhì)是生成均值和方差

print(scaler.mean_)                            #查看均值的屬性mean_
print(scaler.var_)                             #查看方差的屬性var_

x_std = scaler.transform(data)          #通過接口導出結(jié)果
print(x_std)

# print(x_std.mean())                     #導出的結(jié)果是一個數(shù)組,用mean()查看均值
# print(x_std.std())                      #用std()查看方差

scaler.fit_transform(data)              #使用fit_transform(data)一步達成結(jié)果

# scaler.inverse_transform(x_std)         #使用inverse_transform逆轉(zhuǎn)標準化

對于StandardScaler和MinMaxScaler來說,空值NaN會被當做是缺失值,在fit的時候忽略,在transform的時候保持缺失NaN的狀態(tài)顯示。并且,盡管去量綱化過程不是具體的算法,但在fit接口中,依然只允許導入至少二維數(shù)組,一維數(shù)組導入會報錯。通常來說,我們輸入的X會是我們的特征矩陣,現(xiàn)實案例中特征矩陣不太可能是一維所以不會存在這個問題。

1.3、數(shù)據(jù)歸一化

1.3.1、MinMax歸一化

將特征縮放至特定區(qū)間,將特征縮放到給定的最小值和最大值之間,或者也可以將每個特征的最大絕對值轉(zhuǎn)換至單位大小。這種方法是對原始數(shù)據(jù)的線性變換,將數(shù)據(jù)歸一到[0,1]中間。轉(zhuǎn)換函數(shù)為:

x = \frac {(x-min)}{(max-min)}

這種方法有個缺陷就是當有新數(shù)據(jù)加入時,可能導致max和min的變化,需要重新定義。

敲黑板,這種方法對于outlier非常敏感,因為outlier影響了max或min值,所以這種方法只適用于數(shù)據(jù)在一個范圍內(nèi)分布的情況

from sklearn.preprocessing import MinMaxScaler
import pandas as pd

data = [[-1, 2], [-0.5, 6], [0, 10], [1, 18]]
pd.DataFrame(data)


#實現(xiàn)歸一化
scaler = MinMaxScaler()             #實例化
scaler = scaler.fit(data)           #fit,在這里本質(zhì)是生成min(x)和max(x)
result = scaler.transform(data)     #通過接口導出結(jié)果
result

array([[0.  , 0.  ],
       [0.25, 0.25],
       [0.5 , 0.5 ],
       [1.  , 1.  ]])
result_ = scaler.fit_transform(data)                #訓練和導出結(jié)果一步達成

scaler.inverse_transform(result_)                    #將歸一化后的結(jié)果逆轉(zhuǎn)

array([[-1. ,  2. ],
       [-0.5,  6. ],
       [ 0. , 10. ],
       [ 1. , 18. ]])
#使用MinMaxScaler的參數(shù)feature_range實現(xiàn)將數(shù)據(jù)歸一化到[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一步導出結(jié)果
result

#當X中的特征數(shù)量非常多的時候,fit會報錯并表示,數(shù)據(jù)量太大了我計算不了
#此時使用partial_fit作為訓練接口
#scaler = scaler.partial_fit(data)
array([[ 5.  ,  5.  ],
       [ 6.25,  6.25],
       [ 7.5 ,  7.5 ],
       [10.  , 10.  ]])

使用numpy來實現(xiàn)歸一化

import numpy as np
X = np.array([[-1, 2], [-0.5, 6], [0, 10], [1, 18]])

#歸一化
X_nor = (X - X.min(axis=0)) / (X.max(axis=0) - X.min(axis=0))
X_nor

#逆轉(zhuǎn)歸一化
X_returned = X_nor * (X.max(axis=0) - X.min(axis=0)) + X.min(axis=0)
X_returned
array([[-1. ,  2. ],
       [-0.5,  6. ],
       [ 0. , 10. ],
       [ 1. , 18. ]])

1.3.2、MaxAbs歸一化歸一化

單獨地縮放和轉(zhuǎn)換每個特征,使得訓練集中的每個特征的最大絕對值將為1.0,將屬性縮放到[-1,1]。它不會移動/居中數(shù)據(jù),因此不會破壞任何稀疏性。

x^‘= \frac {x}{|MAX|}

缺點:

  • 這種方法有一個缺陷就是當有新數(shù)據(jù)加入時,可能導致max和min的變化,需要重新定義;

  • MaxAbsScaler與先前的縮放器不同,絕對值映射在[0,1]范圍內(nèi)。

  • 在僅有正數(shù)據(jù)時,該縮放器的行為MinMaxScaler與此類似,因此也存在大的異常值。

from sklearn.preprocessing import MinMaxScaler
#區(qū)間縮放,返回值為縮放到[0, 1]區(qū)間的數(shù)據(jù)
minMaxScaler  = MinMaxScaler().fit(data)
minMaxScaler.transform(data)
array([[0.  , 0.  ],
       [0.25, 0.25],
       [0.5 , 0.5 ],
       [1.  , 1.  ]])

1.3.1、RobustScaler歸一化

如果你的數(shù)據(jù)包含許多異常值,使用均值和方差縮放可能并不是一個很好的選擇。這種情況下,你可以使用 robust_scale 以及 RobustScaler 作為替代品。它們對你的數(shù)據(jù)的中心和范圍使用更有魯棒性的估計。

1.4、標準化與歸一化的對比

1.4.1、標準化與歸一化的異同

相同點:

它們的相同點在于都能取消由于量綱不同引起的誤差;都是一種線性變換,都是對向量X按照比例壓縮再進行平移。

不同點:

  • 目的不同,歸一化是為了消除綱量壓縮到[0,1]區(qū)間;標準化只是調(diào)整特征整體的分布;
  • 歸一化與最大,最小值有關;標準化與均值,標準差有關;
  • 歸一化輸出在[0,1]之間;標準化無限制。

1.4.2、什么時候用歸一化?什么時候用標準化?

  • 如果對輸出結(jié)果范圍有要求,用歸一化;
  • 如果數(shù)據(jù)較為穩(wěn)定,不存在極端的最大最小值,用歸一化;
  • 如果數(shù)據(jù)存在異常值和較多噪音,用標準化,可以間接通過中心化避免異常值和極端值的影響。

1.4.3、歸一化與標準化的應用場景

  • 在分類、聚類算法中,需要使用距離來度量相似性的時候(如SVM、KNN)、或者使用PCA技術進行降維的時候,標準化(Z-score standardization)表現(xiàn)更好;
  • 在不涉及距離度量、協(xié)方差計算、數(shù)據(jù)不符合正太分布的時候,可以使用第一種方法或其他歸一化方法。比如圖像處理中,將RGB圖像轉(zhuǎn)換為灰度圖像后將其值限定在[0 255]的范圍;
  • 基于樹的方法不需要進行特征的歸一化。例如隨機森林,bagging與boosting等方法如果是基于參數(shù)的模型或者基于距離的模型,因為需要對參數(shù)或者距離進行計算,都需要進行歸一化。

1.5、sklearn中的數(shù)據(jù)預處理和特征工程

  • 模塊preprocessing:幾乎包含數(shù)據(jù)預處理的所有內(nèi)容
  • 模塊Impute:填補缺失值專用
  • 模塊feature_selection:包含特征選擇的各種方法的實踐
  • 模塊decomposition:包含降維算法
    無量綱化方法.png

2、缺失值處理

機器學習和數(shù)據(jù)挖掘中所使用的數(shù)據(jù),永遠不可能是完美的。很多特征,對于分析和建模來說意義非凡,但對于實際收集數(shù)據(jù)的人卻不是如此,因此數(shù)據(jù)挖掘之中,常常會有重要的字段缺失值很多,但又不能舍棄字段的情況。因此,數(shù)據(jù)預處理中非常重要的一項就是處理缺失值。

2.1、 使用Pandas和Numpy處理缺失值

import pandas as pd
import numpy as np
arr = pd.DataFrame(np.array([[1,np.nan],[np.nan,2],[100,np.nan],[np.nan,2],[1,np.nan],[np.nan,2]]))
# arr.drop_duplicates()
arr.iloc[:,0].fillna(axis=0,value=arr.iloc[:,0].mean(), inplace=True)

arr.dropna(axis=0,inplace=True)
#.dropna(axis=0)刪除所有有缺失值的行,
# dropna(axis=1)刪除所有有缺失值的列
#參數(shù)inplace,為True表示在原數(shù)據(jù)集上進行修改,為False表示生成一個復制對象,不修改原數(shù)據(jù),默認False
arr.iloc[:,0].values
array([34., 34., 34.])
arr = np.array([[1,np.nan],[np.nan,2]
                             ,[100,np.nan],[np.nan,2]
                             ,[200,np.nan],[50,2]
                             ,[1,np.nan],[70,2]
                             ,[1,np.nan],[70,2]
                             ,[1,np.nan],[np.nan,2]])
arr[:,0]

array([  1.,  nan, 100.,  nan, 200.,  50.,   1.,  70.,   1.,  70.,   1.,
        nan])

2.2、 使用sklearn中的Imputer處理缺失值

arr = np.array([[1,np.nan],[np.nan,2]
                             ,[100,np.nan],[np.nan,2]
                             ,[200,np.nan],[50,2]
                             ,[1,np.nan],[70,2]
                             ,[1,np.nan],[70,2]
                             ,[1,np.nan],[np.nan,2]])

from sklearn.preprocessing import Imputer
# from sklearn.impute import SimpleImputer

imp_mean = Imputer(missing_values='NaN', strategy='mean', axis=0,verbose=0)
imp_median = Imputer(missing_values='NaN', strategy='median', axis=0)
imp_mode = Imputer(missing_values='NaN', strategy='most_frequent', axis=0)
# imp_median = SimpleImputer(strategy="median")           #用中位數(shù)填補
# imp_0 = Imputer(missing_values='NaN', strategy="constant",fill_value=0) #用0填補

imp_mean = imp_mean.fit_transform(arr[:,0].reshape(-1,1))                  #fit_transform一步完成調(diào)取結(jié)果
imp_median = imp_median.fit_transform(arr[:,0].reshape(-1,1))
imp_mode = imp_mode.fit_transform(arr[:,0].reshape(-1,1))
# print(arr[:,0].reshape(-1,1))
# print("*****")
print(imp_mean)
# print("*****")
# print(imp_median)
# print("*****")
# print(imp_mode)

[[  1.        ]
 [ 54.88888889]
 [100.        ]
 [ 54.88888889]
 [200.        ]
 [ 50.        ]
 [  1.        ]
 [ 70.        ]
 [  1.        ]
 [ 70.        ]
 [  1.        ]
 [ 54.88888889]]

3、處理分類型特征:編碼與啞變量

在機器學習中,大多數(shù)算法,譬如邏輯回歸,支持向量機SVM,k近鄰算法等都只能夠處理數(shù)值型數(shù)據(jù),不能處理文字,在sklearn當中,除了專用來處理文字的算法,其他算法在fit的時候全部要求輸入數(shù)組或矩陣,也不能夠?qū)胛淖中蛿?shù)據(jù)(其實手寫決策樹和普斯貝葉斯可以處理文字,但是sklearn中規(guī)定必須導入數(shù)值型)。然而在現(xiàn)實中,許多標簽和特征在數(shù)據(jù)收集完畢的時候,都不是以數(shù)字來表現(xiàn)的。比如說,學歷的取值可以是["小學",“初中”,“高中”,"大學"],付費方式可能包含["支付寶",“現(xiàn)金”,“微信”]等等。在這種情況下,為了讓數(shù)據(jù)適應算法和庫,我們必須將數(shù)據(jù)進行編碼,即是說,將文字型數(shù)據(jù)轉(zhuǎn)換為數(shù)值型。

preprocessing.LabelEncoder:標簽專用,能夠?qū)⒎诸愞D(zhuǎn)換為分類數(shù)值

from sklearn.preprocessing import LabelEncoder

y = ["支付寶", "現(xiàn)金", "微信"]                         #要輸入的是標簽,不是特征矩陣,所以允許一維

le = LabelEncoder()                         #實例化
le = le.fit(y)                              #導入數(shù)據(jù)
label = le.transform(y)                     #transform接口調(diào)取結(jié)果

le.classes_                                 #屬性.classes_查看標簽中究竟有多少類別
label                                       #查看獲取的結(jié)果label

# le.fit_transform(y)                         #也可以直接fit_transform一步到位

# le.inverse_transform(label)                 #使用inverse_transform可以逆轉(zhuǎn)

# data.iloc[:,-1] = label                     #讓標簽等于我們運行出來的結(jié)果

# data.head()

# #如果不需要展示的話我會這么寫:
# from sklearn.preprocessing import LabelEncoder
# data.iloc[:,-1] = LabelEncoder().fit_transform(data.iloc[:,-1])
array([1, 2, 0], dtype=int64)

preprocessing.OneHotEncoder:獨熱編碼,創(chuàng)建啞變量

在泰坦尼克號生存預測數(shù)據(jù)集艙門Embarked這一列中,艙門分別為S、C、G,我們可以用LabelEncoder把分類變量都轉(zhuǎn)換成數(shù)字對應的類別。假設我們使用[0,1,2]代表了三個不同的艙門,然而這種轉(zhuǎn)換是正確的嗎?

我們來思考三種不同性質(zhì)的分類數(shù)據(jù):

1) 艙門(S,C,Q)

三種取值S,C,Q是相互獨立的,彼此之間完全沒有聯(lián)系,表達的是S≠C≠Q(mào)的概念。這是名義變量。

2) 學歷(小學,初中,高中)

三種取值不是完全獨立的,我們可以明顯看出,在性質(zhì)上可以有高中>初中>小學這樣的聯(lián)系,學歷有高低,但是學歷取值之間卻不是可以計算的,我們不能說小學 + 某個取值 = 初中。這是有序變量。

3) 體重(>45kg,>90kg,>135kg)

各個取值之間有聯(lián)系,且是可以互相計算的,比如120kg - 45kg = 90kg,分類之間可以通過數(shù)學計算互相轉(zhuǎn)換。這是有距變量

然而在對特征進行編碼的時候,這三種分類數(shù)據(jù)都會被我們轉(zhuǎn)換為[0,1,2],這三個數(shù)字在算法看來,是連續(xù)且可以計算的,這三個數(shù)字相互不等,有大小,并且有著可以相加相乘的聯(lián)系。所以算法會把艙門,學歷這樣的分類特征,都誤會成是體重這樣的分類特征。這是說,我們把分類轉(zhuǎn)換成數(shù)字的時候,忽略了數(shù)字中自帶的數(shù)學性質(zhì),所以給算法傳達了一些不準確的信息,而這會影響我們的建模。

對于名義變量,我們只有使用啞變量的方式來處理,才能夠盡量向算法傳達最準確的信息,下面使用sklearn中的方法和pandas中的方法分別對字段進行啞變量處理

from sklearn.preprocessing import OneHotEncoder
from sklearn.preprocessing import LabelEncoder
data_np = np.array([[1, '語文'], [2, '英語']
                    , [3, '語文'], [4, '英語']
                    , [3, '語文'], [4, '數(shù)學']])
data = pd.DataFrame({'A' : 1,
                     'B' : pd.Timestamp('20130102'),
                     'C' : pd.Series(1,index=list(range(4)),dtype='float32'),
                     'D' : np.array([3] * 4,dtype='int32'),
                     'E' : pd.Categorical(["test","train","test","train"]),
                     'F' : ['foo1', 'foo1', 'foo2', 'foo2'],
                     'G' : pd.Series([1, 2, 1, 3], dtype='object')})
from sklearn.preprocessing import OneHotEncoder
from sklearn.preprocessing import LabelEncoder


data_np[:,-1] = le.fit_transform(data_np[:,-1])
# print(data_np)

enc = OneHotEncoder(n_values='auto').fit(data_np[:,-1].reshape(-1, 1))
result = enc.transform(data_np[:,-1].reshape(-1,1))


data_np = np.concatenate((data_np, result.toarray()), axis=1)
data_np
#依然可以直接一步到位,但為了給大家展示模型屬性,所以還是寫成了三步
# OneHotEncoder(n_values='auto').fit_transform(data_np[:,-1].reshape(-1,1)).toarray()

# #依然可以還原
# enc.inverse_transform(result)
array([['1', '2', '0.0', '0.0', '1', '0.0', '1.0'],
       ['2', '1', '0.0', '1.0', '0', '1.0', '0.0'],
       ['3', '2', '0.0', '0.0', '1', '0.0', '1.0'],
       ['4', '1', '0.0', '1.0', '0', '1.0', '0.0'],
       ['3', '2', '0.0', '0.0', '1', '0.0', '1.0'],
       ['4', '0', '1.0', '0.0', '0', '1.0', '0.0']], dtype='<U32')
data.F = le.fit_transform(data.F)
print(data)
res = enc.fit_transform(data.F.values.reshape(-1,1))
# res
# pd.DataFrame(res.toarray())
newdata = pd.concat([data,pd.DataFrame(res.toarray())],axis=1)
newdata
   A          B    C  D      E  F  G
0  1 2013-01-02  1.0  3   test  0  1
1  1 2013-01-02  1.0  3  train  0  2
2  1 2013-01-02  1.0  3   test  1  1
3  1 2013-01-02  1.0  3  train  1  3

4、處理連續(xù)型特征--數(shù)據(jù)離散化

離散化是數(shù)值型特征非常重要的一個處理,其實就是要將數(shù)值型數(shù)據(jù)轉(zhuǎn)化成類別型數(shù)據(jù)。連續(xù)值的取值空間可能是無窮的,為了便于表示和在模型中處理,需要對連續(xù)值特征進行離散化處理。

數(shù)據(jù)離散化的優(yōu)點:

  1. 離散特征的增加和減少都很容易,易于模型的快速迭代;
  1. 稀疏向量內(nèi)積乘法運算速度快,計算結(jié)果方便存儲,容易擴展;
  1. 離散化后的特征對異常數(shù)據(jù)有很強的魯棒性;比如一個特征是年齡>30是1,否則0。如果特征沒有離散化,一個異常數(shù)據(jù)“年齡300歲”會給模型造成很大的干擾;
  1. 對于線性模型,表達能力受限;單變量離散化為N個后,每個變量有單獨的權重,相當于模型引入了非線性,能夠提升模型表達能力,加大擬合;離散化后可以進行特征交叉,由M+N個變量變?yōu)镸*N個變量,進一步引入非線性,提升表達能力;
  1. 特征離散化后,模型會更穩(wěn)定;比如如果對用戶年齡離散化,20-30作為一個區(qū)間,不會因為一個用戶年齡長了一歲就變成一個完全不同的人。當然處于區(qū)間相鄰處的樣本會剛好相反,所以怎么劃分區(qū)間是門學問;特征離散化以后,起到了簡化了邏輯回歸模型的作用,降低了模型過擬合的風險;
  1. 可以將缺失作為獨立的一類帶入模型;
  1. 將所有變量變換到相似的尺度上。

sklearn.preprocessing.Binarizer:二值化

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

data_2 = data.copy()

from sklearn.preprocessing import Binarizer

data_bin = np.random.randint(0,100,20)
print(data_bin)
X = data_bin.reshape(-1,1)               #類為特征專用,所以不能使用一維數(shù)組
transformer = Binarizer(threshold=30).fit_transform(X)
# transformer
[44 15 30 91 14 19 26 86  7 99 53 47 60 34 32 19 67 24 83 94]

常見的分箱方法:

  1. 無監(jiān)督分想法

    • 自定義分箱:根據(jù)業(yè)務經(jīng)驗或者常識等自行設定劃分的區(qū)間,然后將原始數(shù)據(jù)歸類到各個區(qū)間中。

    • 等距分箱:按照相同寬度將數(shù)據(jù)分成幾等份。缺點是受到異常值的影響比較大

    • 等頻分箱:將數(shù)據(jù)分成幾等份,每等份數(shù)據(jù)里面的個數(shù)是一樣的。區(qū)間的邊界值要經(jīng)過選擇,使得每個區(qū)間包含大致相等的實例數(shù)量。比如說 N=10 ,每個區(qū)間應該包含大約10%的實例。

    • 聚類分箱:基于k均值聚類的分箱:k均值聚類法將觀測值聚為k類,但在聚類過程中需要保證分箱的有序性:第一個分箱中所有觀測值都要小于第二個分箱中的觀測值,第二個分箱中所有觀測值都要小于第三個分箱中的觀測值,等等。

  2. 有監(jiān)督分想法

    • 卡方分箱法:自底向上的(即基于合并的)數(shù)據(jù)離散化方法。它依賴于卡方檢驗:具有最小卡方值的相鄰區(qū)間合并在一起,直到滿足確定的停止準則。對于精確的離散化,相對類頻率在一個區(qū)間內(nèi)應當完全一致。因此,如果兩個相鄰的區(qū)間具有非常類似的類分布,則這兩個區(qū)間可以合并;否則,它們應當保持分開。而低卡方值表明它們具有相似的類分布。

    • 最小熵法分箱:需要使總熵值達到最小,也就是使分箱能夠最大限度地區(qū)分因變量的各類別。熵是信息論中數(shù)據(jù)無序程度的度量標準,提出信息熵的基本目的是找出某種符號系統(tǒng)的信息量和冗余度之間的關系,以便能用最小的成本和消耗來實現(xiàn)最高效率的數(shù)據(jù)存儲、管理和傳遞。數(shù)據(jù)集的熵越低,說明數(shù)據(jù)之間的差異越小,最小熵劃分就是為了使每箱中的數(shù)據(jù)具有最好的相似性。給定箱的個數(shù),如果考慮所有可能的分箱情況,最小熵方法得到的箱應該是具有最小熵的分箱。

preprocessing.KBinsDiscretizer 分箱

這是將連續(xù)型變量劃分為分類變量的類,能夠?qū)⑦B續(xù)型變量排序后按順序分箱后編碼??偣舶齻€重要參數(shù):

參數(shù) 含義&輸入
n_bins 每個特征中分箱的個數(shù),默認5,一次會被運用到所有導入的特征
encode 編碼的方式,默認“onehot” "onehot":做啞變量,之后返回一個稀疏矩陣,每一列是一個特征中的一個類別,含有該 類別的樣本表示為1,不含的表示為0 “ordinal”:每個特征的每個箱都被編碼為一個整數(shù),返回每一列是一個特征,每個特征下含 有不同整數(shù)編碼的箱的矩陣 "onehot-dense":做啞變量,之后返回一個密集數(shù)組。
strategy 用來定義箱寬的方式,默認"quantile" "uniform":表示等寬分箱,即每個特征中的每個箱的最大值之間的差為 (特征.max() - 特征.min())/(n_bins) "quantile":表示等位分箱,即每個特征中的每個箱內(nèi)的樣本數(shù)量都相同 "kmeans":表示按聚類分箱,每個箱中的值到最近的一維k均值聚類的簇心得距離都相同
最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容