(一)數值特征
數值特征(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、神經網絡
- 如果數據存在異常值和較多噪音,用標准化,可以間接通過中心化避免異常值和極端值的影響
參考:
- sklearn.preprocessing.scale
- sklearn.preprocessing.StandardScaler(兩個基本一樣,但一般用這個就ok了,比較高級、方法比較齊全)
# 方法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.normalize(X, norm=’l2’, axis=1, copy=True, return_norm=False)
- sklearn.preprocessing.Normalizer(norm=’l2’, copy=True)
sklearn.preprocessing.Normalizer(norm=’l2’, copy=True)
參數:
- norm:'l1','l2',或'max',可選,默認='l2'
- copy:boolean,可選,默認=True
5.絕對值標准化(不免疫outlier)
專為稀疏數據而生。將每個要素縮放到[-1,1]范圍,它不會移動/居中數據,因此不會破壞任何稀疏性。該估計器單獨地縮放每個特征,使得訓練集中的每個特征的最大絕對值將是1.0。該縮放器也可以應用於稀疏CSR或CSC矩陣
參考:
- sklearn.preprocessing.maxabs_scale(X, axis=0, copy=True)
- sklearn.preprocessing.MaxAbsScaler(copy=True)(這兩者的關系同上)
6.魯棒性標准化(免疫outlier)
專為異常值而生。標准差標准化(第一種,最常用的那種)對數據中出現的異常值處理能力不佳,因此誕生了robust_scale,這種不怕異常值擾動的數據縮放法。此Scaler根據分位數范圍(默認為IQR:Interquartile Range)刪除中位數並縮放數據。 IQR是第1四分位數(第25個分位數)和第3個四分位數(第75個分位數)之間的范圍。
參考:
- sklearn.preprocessing.robust_scale(X, axis=0, with_centering=True, with_scaling=True, quantile_range=(25.0, 75.0), copy=True)
- sklearn.preprocessing.RobustScaler(with_centering=True, with_scaling=True, quantile_range=(25.0, 75.0), copy=True)
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)等寬/非等寬分桶
如商品的評論次數、年齡
參考:
pandas.
cut
(x, bins, right=True, labels=None, retbins=False, precision=3, include_lowest=False, duplicates='raise')- 當bins為int型數字時,會生成等寬的bin;當bins=標量序列時,為用戶自定義bin的區間
(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也有意義
僅僅將已有的類別和數值特征進行以上的有效組合,就能夠大量增加優秀的可用特征。
將這種方法和線性組合等基礎特征工程方法結合(僅用於決策樹),可以得到更多有意義的特征,如:

N1 - median(N1)_by(C1)
N1 - mean(N1)_by(C1)
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
運行結果與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的類別合並到同一個新的類別下。
注意:如果特征列的頻數需要被當做一個新的特征加入數據集,請在上述合並之前提取出頻數特征。
(三)標簽
一、標簽二值化
二、標簽編碼
參考文獻:
【3】數據規范化——sklearn.preprocessing
【4】Python數據分析4------------數據變換
【7】Python下的機器學習工具sklearn--數據預處理(標簽)