2(1).數據預處理方法


(一)數值特征 

數值特征(numerical feature),可以是連續的(continuous),也可以是離散的(discrete),一般表示為一個實數值。

例:年齡、價格、身高、體重、測量數據。

不同算法對於數值特征的處理要求不同。下文中的一些數據處理方法,因為是針對某一特征列的單調變換,所以不會對基於決策樹的算法(隨機森林、gbdt)產生任何影響。一般而言,決策樹類算法不需要預處理數值特征。

一、數值特征縮放

適用場景:

  • 基於距離的算法
  • 算法用到了梯度下降

1.Rescaling(最小最大標准化/歸一化,不免疫outlier)

(1)將訓練集中某一列數值特征(假設是第i列)的值縮放到0和1之間

適用場景:

  • 如果對輸出結果范圍有要求,用歸一化
  • 如果數據較為穩定,不存在極端的最大最小值,用歸一化

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

參考

from sklearn.preprocessing import MinMaxScaler

#初始化一個scaler對象
scaler = MinMaxScaler()

#調用scaler的fit_transform方法,把我們要處理的列作為參數傳進去
data['標准化后的A列數據'] = scaler.fit_transform(data['A列數據'])

 

(2)要重新縮放任意值集[a,b]之間的范圍,公式將變為:

a,b是最小-最大值

 

2.Mean normalization(均值歸一化,不免疫outlier)

將訓練集中某一列數值特征(假設是第i列)的值縮放到[-1,1]零均值之間

適用場景:

  • 矩陣分解

參考

 

3.Standardization(標准化/z-score標准化,不免疫outlier)   

將訓練集中某一列數值特征(假設是第i列)的值縮放成均值為0,方差為1的狀態。

適用場景:

  • SVM、LR、神經網絡
  • 如果數據存在異常值和較多噪音,用標准化,可以間接通過中心化避免異常值和極端值的影響

參考

# 方法1
from sklearn.proprocessing import scale
df_train['feature'] = scale(df_train['feature'])

# 方法2
# 一般會把train和test集放在一起做標准化,或者在train集上做標准化后,用同樣的標准化器去標准化test集,此時可以用scaler
from sklearn.proprocessing import StandardScaler
scaler = StandardScaler().fit(df_train)
scaler.transform(df_train)
scaler.transform(df_test)

 

4.scaling to unit length(縮放到單位長度,不免疫outlier)

在機器學習中廣泛使用的另一種選擇是縮放特征向量的分量,使得完整向量具有長度1。這通常意味着將每個組件除以向量歐幾里德長度

使用場景:

  • 在一些應用中(例如直方圖特征),使用特征向量的L1范數(即曼哈頓距離,城市塊長度或出租車幾何可能更實際如果在以下學習步驟中將標量度量用作距離度量,則這尤其重要。

參考

sklearn.preprocessing.Normalizer(norm=’l2’, copy=True) 

參數:

  • norm:'l1','l2',或'max',可選,默認='l2'
  • copy:boolean,可選,默認=True

 

5.絕對值標准化(不免疫outlier)

  專為稀疏數據而生。將每個要素縮放到[-1,1]范圍,它不會移動/居中數據,因此不會破壞任何稀疏性。該估計器單獨地縮放每個特征,使得訓練集中的每個特征的最大絕對值將是1.0。該縮放器也可以應用於稀疏CSR或CSC矩陣

參考

 

6.魯棒性標准化(免疫outlier)

  專為異常值而生。標准差標准化(第一種,最常用的那種)對數據中出現的異常值處理能力不佳,因此誕生了robust_scale,這種不怕異常值擾動的數據縮放法。此Scaler根據分位數范圍(默認為IQR:Interquartile Range)刪除中位數並縮放數據。 IQR是第1四分位數(第25個分位數)和第3個四分位數(第75個分位數)之間的范圍。

參考

 

7.對數/平方根縮放:

適用場景:對數縮放對於處理長尾分布且取值為正數的數值變量非常有效,它將大端長尾壓縮為短尾,並將小端進行延伸,平方根或者對數變換是冪變換的特例,在統計學中都稱為方差穩定的變換

舉例:對數縮放

import numpy as np
data["log_feature1"] = np.log10(data["feature1"])

 

8.box-cox變換 

適用場景:基於極大似然法的冪轉換,其作用是讓分布在不丟失信息的前提下,具有更好的性質(獨立性、方差齊性、正態性等),以便得到更好的模型。

要求:

  Box-Cox變換的要求是數據要大於0,否則無法變換,解決的辦法是加一個常數,把數據變成正數;

  變換后,必須再做正態性檢驗,確認變換的有效性;

求$\lambda$:假設經過轉換后的因變量就是服從正態分布的,然后畫出關於$\lambda$的似然函數,似然函數值最大的時候$\lambda$的取值就是這里需要確定的值。

 

9.上下界截斷:

  • clipping:可以用pandas dataframe的.clip(low, upper)方法,把特征值的取值限制在一定范圍內 
  • data.ix[data['feature1']>10,'feature1'] = 10
    data.ix[data['feature2']<-20,'feature2'] = -20

 

 

三、數值特征離散化

這對於決策樹類型的模型沒太多意義

1.二值化

設定一個閾值,大於閾值的賦值為1,小於等於閾值的賦值為0;默認閾值為0時,只有正值映射到1。

class sklearn.preprocessing.Binarizer(threshold=0.0, copy=True)

參數:

  • threshold:float,可選,默認=0.0,對於稀疏矩陣上的操作,閾值可能不小於0。
  • copy:boolean,可選,默認=True

舉例:

from sklearn.datasets import load_iris
import pandas as pd
from sklearn.preprocessing import Binarizer

X,y = load_iris(return_X_y=True)    
df_X = pd.DataFrame(X,columns=list("ABCD"))
bn = Binarizer(threshold=5.843333)
df_X["A"] = bn.transform(df_X["A"].values.reshape(-1,1))

  

2.分桶

(1)等寬/非等寬分桶

  如商品的評論次數、年齡

參考

 

(2)等頻率分桶

  如果數值變量的取值存在很大間隔時,有些桶里沒有數據,可以基於數據的分布進行分桶,.

將相同數據的記錄放進每個區間,先求分位數,再用cut函數

dataframe結構

dataframe.describe(percentiles=w)來計算分位數

w=[ i/k for i in range(k+1)]
w=data.describe (percentiles=w) [ 4:4+k+1] #取幾個分位數的值作為不等長列表,用於cut函數
d2=pd.cut(data,w,labels=range(k))

列表、數組結構

#用np.percentile(data,百分比)來求
temp=[ i/k*100 for i in range(k+1)]
w=[]
for item in temp:
    w.append(np.percentile(data,item))
d3=pd.cut(data,w,labels=range(k))

參考:

 

(3)一維聚類離散化

先聚類(如k-means),然后對每一類的連續值進行標記

①k-means求聚類中心,並排序,將相鄰兩項的中點作為邊界點,把首末邊界點加上,整合成w列表

②cut函數

from sklearn.cluster import KMeans
kmodel=KMeans(n_clusters=k)  #k為聚成幾類
kmodel.fit(data.reshape(len(data),1))) #訓練模型
c=pd.DataFrame(kmodel.cluster_centers_) #求聚類中心
c=c.sort_values(by=’列索引') #排序  
w=pd.rolling_mean(c,2).iloc[1:] #用滑動窗口求均值的方法求相鄰兩項求中點,作為邊界點
w=[0] +list(w[0] + [ data.max() ]  #把首末邊界點加上
d3= pd.cut(data,w,labels=range(k)) #cut函數

 

四、缺失值處理

 數值特征缺失值處理

 

五、特征交叉

1. 數值特征的簡單變換

  • 單獨特征列乘以一個常數(constant multiplication)或者加減一個常數:對於創造新的有用特征毫無用處;只能作為對已有特征的處理。
  • 任何針對單獨特征列的單調變換(如對數):不適用於決策樹類算法。對於決策樹而言,$X、X^3、X^5$之間沒有差異,$|X|、X^2、X^4$ 之間沒有差異,除非發生了舍入誤差。
  • 線性組合(linear combination):僅適用於決策樹以及基於決策樹的ensemble(如gradient boosting, random forest),因為常見的axis-aligned split function不擅長捕獲不同特征之間的相關性;不適用於SVM、線性回歸、神經網絡等。
  • 多項式特征(polynomial feature):
    • sklearn.preprocessing.PolynomialFeatures - scikit-learn 0.18.1 documentation
    • 捕獲特征之間的相關性, 使用sklearn.preprocessing.PolynomialFeatures來進行特征的構造。它是使用多項式的方法來進行的,如果有a,b兩個特征,那么它的2次多項式為(1,a,b,a^2,ab, b^2),這個多項式的形式是使用poly的效果。

      • PolynomialFeatures有三個參數
      • degree:控制多項式的度
      • interaction_only: 默認為False,如果指定為True,那么就不會有特征自己和自己結合的項,上面的二次項中沒有a^2和b^2。
      from sklearn.datasets import load_iris
      import pandas as pd
      X,y = load_iris(return_X_y=True)    
      df_X = pd.DataFrame(X,columns=list("ABCD"))
      
      from sklearn.preprocessing import PolynomialFeatures
      
      pnf = PolynomialFeatures(degree=2,interaction_only=True)
      temp  = pnf.fit_transform(df_X[["A","B"]].values)
      for i,column in enumerate(list("EFGH")):
          df_X[column] = temp[:,i]
  • 比例特征(ratio feature):$X_1/X_2$
  • 絕對值(absolute value)
  • $max(X_1,X_2),min(X_1,X_2),X_1xorX_2$

 

2. 類別特征與數值特征的組合

用N1和N2表示數值特征,用C1和C2表示類別特征,利用pandas的groupby操作,可以創造出以下幾種有意義的新特征:(其中,C2還可以是離散化了的N1)

median(N1)_by(C1)  \\ 中位數
mean(N1)_by(C1)  \\ 算術平均數
mode(N1)_by(C1)  \\ 眾數
min(N1)_by(C1)  \\ 最小值
max(N1)_by(C1)  \\ 最大值
std(N1)_by(C1)  \\ 標准差
var(N1)_by(C1)  \\ 方差
freq(C2)_by(C1)  \\ 頻數

freq(C1) \\這個不需要groupby也有意義
View Code

 

僅僅將已有的類別和數值特征進行以上的有效組合,就能夠大量增加優秀的可用特征。

將這種方法和線性組合等基礎特征工程方法結合(僅用於決策樹),可以得到更多有意義的特征,如:

N1 - median(N1)_by(C1)
N1 - mean(N1)_by(C1)
View Code

 

 

3.用基因編程創造新特征

Welcome to gplearn’s documentation!

基於genetic programming的symbolic regression,具體的原理和實現參見文檔。目前,python環境下最好用的基因編程庫為gplearn。基因編程的兩大用法:

  • 轉換(transformation):把已有的特征進行組合轉換,組合的方式(一元、二元、多元算子)可以由用戶自行定義,也可以使用庫中自帶的函數(如加減乘除、min、max、三角函數、指數、對數)。組合的目的,是創造出和目標y值最“相關”的新特征。這種相關程度可以用spearman或者pearson的相關系數進行測量。spearman多用於決策樹(免疫單特征單調變換),pearson多用於線性回歸等其他算法。
  • 回歸(regression):原理同上,只不過直接用於回歸而已。

 

4. 用決策樹創造新特征

在決策樹系列的算法中(單棵決策樹、gbdt、隨機森林),每一個樣本都會被映射到決策樹的一片葉子上。因此,我們可以把樣本經過每一棵決策樹映射后的index(自然數)或one-hot-vector(啞編碼得到的稀疏矢量)作為一項新的特征,加入到模型中。

具體實現:apply()以及decision_path()方法,在scikit-learn和xgboost里都可以用。

 

 

六、非線性編碼

 

七、行統計量

DataFrame.nunique(),DataFrame.count

 

 

 

 (二)類別特征

一、編碼

1.one-hot

  如果類別特征本身有順序(例:優秀、良好、合格、不合格),那么可以保留單列自然數編碼。如果類別特征沒有明顯的順序(例:紅、黃、藍),則可以使用one-hot編碼:

  • 作用:將類別變量轉換為機器學習算法容易處理的形式
  • 為什么one-hot編碼可以用來處理非連續(離散)特征?
    • 在使用one-hot編碼中,我們可以將離散特征的取值擴展到歐式空間,在機器學習中,我們的研究范圍就是在歐式空間中,首先這一步,保證了能夠適用於機器學習中;另外對於one-hot處理的離散的特征的某個取值也就對應了歐式空間的某個點.
  • 怎么用?
  • sklearn.preprocessing.OneHotEncoder(n_values=None, categorical_features=None, categories=None, drop=None, sparse=True, dtype=<class ‘numpy.float64’>, handle_unknown=’error’)
    • View Code 
    • 如果需要修改編碼后的列名
    • categorical_features =['cardIndex','is_abnormal']
      dummies = pd.get_dummies(data,columns=categorical_features)
      dummies = dummies.add_prefix("{}_".format('cardIndex'))
      data.drop('animal',axis=1,inplace=True)
      data = data .join(dummies)
      data 
      View Code

 運行結果與LabelBinarizer相似,不過在參數以及輸入輸出的格式上有細微的差別,參見文檔。輸出的矩陣是稀疏的,含有大量的0。 

 

2.自然數編碼(LabelEncoder)

  默認的編碼方式,消耗內存小,訓練時間快,但是特征的質量不高。用於label encoding,生成一個(n_examples)大小的0~(n_classes-1)矢量,每個樣本僅對應一個label。

sklearn.preprocessing.LabelEncoder

 

3.LabelBinarizer

  用於one vs all的label encoding,類似於獨熱編碼,生成一個(n_examples * n_classes)大小的0~1矩陣,每個樣本僅對應一個label。

sklearn.preprocessing.LabelBinarizer

 

4.MultiLabelBinarizer

  用於label encoding,生成一個(n_examples * n_classes)大小的0~1矩陣,每個樣本可能對應多個label。

sklearn.preprocessing.MultiLabelBinarizer

 

5.聚類編碼

  和獨熱編碼相比,聚類編碼試圖充分利用每一列0與1的信息表達能力。聚類編碼時一般需要特定的專業知識(domain knowledge),例如ZIP碼可以根據精確度分層為ZIP3、ZIP4、ZIP5、ZIP6,然后按層次進行編碼。

 

6.平均數編碼

  平均數編碼(mean encoding),針對高基數類別特征的有監督編碼。當一個類別特征列包括了極多不同類別時(如家庭地址,動輒上萬)時,可以采用。優點:和獨熱編碼相比,節省內存、減少算法計算時間、有效增強模型表現。

平均數編碼:針對高基數類別特征(類別特征)的數據預處理/特征工程 - 知乎專欄

 

7.只出現一次的類別

  在類別特征列里,有時會有一些類別,在訓練集和測試集中總共只出現一次,例如特別偏僻的郊區地址。此時,保留其原有的自然數編碼意義不大,不如將所有頻數為1的類別合並到同一個新的類別下。

注意:如果特征列的頻數需要被當做一個新的特征加入數據集,請在上述合並之前提取出頻數特征。

  

 

 

(三)標簽

一、標簽二值化

 

二、標簽編碼

 

 

 

參考文獻:

【1】wiki:Feature scaling

【2】特征工程中的「歸一化」有什么作用?

【3】數據規范化——sklearn.preprocessing

【4】Python數據分析4------------數據變換

【5】數據預處理之One-Hot

【6】【持續更新】機器學習特征工程實用技巧大全

【7】Python下的機器學習工具sklearn--數據預處理(標簽)

【8】特征工程步驟——以二分類問題為例

【9】【Python數據分析基礎】: 數據缺失值處理

【10】5種方法教你用Python玩轉histogram直方圖

【11】【持續更新】機器學習特征工程實用技巧大全

【12】經典比較篇之八:數據不正態怎么辦? - 知乎


免責聲明!

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



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