1. 程式人生 > >機器學習中的特徵工程詳解

機器學習中的特徵工程詳解

最近看完一本寫特徵工程的書,概念清晰,內容全面,所以總結如下讀書筆記,書名:Feature Engineering Made Easy,可免費試用線上閱讀。

1 特徵認識(Feature understanding)

  • 結構化資料:可分解為觀測記錄和屬性的資料,如表格資料,行為觀測,列為屬性
  • 非結構化資料:資料形式隨意,不遵循特定規則,如一堆資料(log檔案),部落格資訊,或者只有一個特徵的資料
  • 定量資料:有明確數值的資料
  • 定性資料:類別資料
1.1 探索性資料分析(Exploratory data analysis)&描述性分析(Descriptive analysis)

常用的函式有(呼叫pandas包):head()info()describe()isnull()corr()

1.2 四種資料級別
  • 名義級別(The nominal level):全部為定性資料,不能進行加減乘除數學運算,但可以做計數(count)統計,如血型資料,可採用餅圖、直方圖視覺化
  • 序列級別(The ordinal level):與名義級別基本一致,但資料可自然排序,為類別(category)資料,數學上資料可比較(compare),如大學成績A、B、C、D,可採用Box-plot視覺化
  • 間隔級別(The interval level):除了名義級別和序列級別的特性,間隔級別資料還可進行加減運算,如溫度
  • 比例級別(The ratio level):除了上述級別的特性,比例級別可進行乘除運算(擁有0物理含義),如重量,錢,100塊是50塊的2倍


2 特徵改進(Feature improvement)

2.1 缺失值處理
  • 刪除缺失值記錄:呼叫pandas包的dropna()
  • (定量資料)填充均值或中值:(pandas包)data.fillna(value),(sklearn包)Imputer().fit_transform(data)
  • (定性資料)填充眾數:(pandas包)data.fillna(data.value_counts().index[0])

注意:缺失值的填補應該在劃分訓練集和測試集之後,即用訓練集的某一特徵均值代入測試集的缺失值。

2.2 標準化和正態化(Standardization and Normalization)
  • Z-score standardization:\( z=(x-\mu )/\sigma \),sklearn包呼叫StandardScaler().fit_transform(data)
  • Min-max scaling:\( m=(x-min)/(max-min) \),sklearn包呼叫MinMaxScaler().fit_transform(data)
  • Row normalization:使每一行資料的L2範數(L2 Norm)\( \left| x \right|=\sqrt{(x_{1}^{2}+x_{2}^{2}+\cdots +x_{n}^{2})} \)一致,sklearn包呼叫Normalizer().fit_transform(data)

3 特徵構建(Feature Construction)

在做資料變換時,sklearn實現了一種名為Pipelines的流水線處理模式,使得在嘗試模型引數進行交叉檢驗時,多個處理步驟可整合一體,在具體可參考官網sklearn.pipeline.Pipeline的說明。以定性資料的缺失值處理為例:

from sklearn.base import TransformerMixin

class CustomCategoryImputer(TransformerMixin):
    def __init__(self, cols=None):
        self.cols = cols

    def transform(self, df):
        X = df.copy()
        for col in self.cols:
            X[col].fillna(X[col].value_counts().index[0], inplace=True)
        return X

    def fit(self, *_):
        return self

cci = CustomCategoryImputer(cols=['col1', 'col2'])
imputer = Pipeline([('category', cci), ('xxx', xxx)]) 
imputer.fit_transform(X)
3.1 類別資料編碼(Encoding categorical variables)
  • 名義級別編碼:將類別資料轉換為啞變數(Dummy Variable),如(性別:男or女)=>(男:0 or 1;女:0 or 1)(注意這個例子中其實(女:0 or 1)為多餘的),類似於One-hot編碼,在pandas中可呼叫get_dummies()
  • 序列級別編碼:可採用標籤編碼(Label Encoder),將序列按0~(n-1)編碼
  • 數值特徵組合:有時也可將數值特徵按多項式組合,生成新的特徵,可呼叫sklearn包的PolynomialFeatures()


3.2 文字特徵編碼

文字特徵的處理常採用bag-of-words的方法,基本思想是採用單詞出現的頻率來表示一段文字,一般都如下三個步驟:

  • 標記(Tokenizing):將一段文字(英文)按標點符號和空格進行分割,獲取標記單詞
  • 計數(Counting):統計標記出現的頻率
  • 標準化(Normalizing):消除文字長度對標記重要性的影響

具體可呼叫sklearn包的CountVectorizer()CountVectorizer()

4 特徵選擇

4.1 模型效能評估指標

特徵選擇的依據是模型效能的好壞,下面首先介紹分類模型的評估指標:

  • 精確率(precision):TP / (TP+FP)
  • 召回率(recall):TP / (TP+FN)
  • 準確率(accuracy,ACC):(TP + TN) / (TP + TN + FP + FN)
  • F1 Score:精準率和召回率的調和均值,2 / F1 = 1 / P + 1 / R


  • True Positive Rate: TPR = TP / (TP+FN) → 將正例分對的概率
  • Fales Positive Rate: FPR = FP / (FP+TN) → 將負例錯分為正例的概率
  • ROC曲線:在ROC空間中,每個點的橫座標是FPR,縱座標是TPR,ROC曲線越靠近左上角,模型越好。ROC曲線有個很好的特性:當測試集中的正負樣本的分佈變化的時候,ROC曲線能夠保持不變,解決類不平衡(class imbalance)的問題
  • AUC:ROC曲線下的面積,AUC越接近1模型越好


對於迴歸問題的評估指標,常用的有:

  • \( R^2 \)
  • 平均絕對誤差MAE(Mean Absolute Error):L1範數損失
  • 平均平方誤差MSE(Mean Squared Error):L2範數損失

除此以外,一些其他因素也值得考慮,如:

  • 資料訓練時間
  • 資料預測時間
  • 所需的計算機記憶體等
4.2 特徵選擇方法

(1)基於概率統計理論的特徵選擇

  • 根據特徵與預測目標的相關性係數挑選
from sklearn.base import TransformerMixin, BaseEstimator
class CustomCorrelationChooser(TransformerMixin, BaseEstimator):
    def __init__(self, response, cols_to_keep=[], threshold=None):
        self.response = response
        self.threshold = threshold
        self.cols_to_keep = cols_to_keep

    def transform(self, X):
        return X[self.cols_to_keep]

    def fit(self, X, *_):
        df = pd.concat([X, self.response], axis=1)
        self.cols_to_keep = df.columns[df.corr()[df.columns[-1]].abs() > self.threshold]
        self.cols_to_keep = [c for c in self.cols_to_keep if c in X.columns]
        return self
  • 採用不同假設檢驗方法挑選特徵,如ANOVA、Chi2檢驗等
from sklearn.feature_selection import SelectKBest
from sklearn.feature_selection import f_classif
k_best = SelectKBest(f_classif, k=5)
k_best.fit_transform(X, y)
p_values = pd.DataFrame({'column': X.columns, 'p_value': k_best.pvalues_}).sort_values('p_value')
p_values[p_values['p_value'] < .05]

(2)基於機器學習模型的特徵選擇

一般的,基於概率統計理論的特徵選擇,在特徵數量特別多的時候效果不是很好。

  • 根據決策樹一類模型的特徵選擇
from sklearn.feature_selection import SelectFromModel
select_from_model = SelectFromModel(DecisionTreeClassifier(), threshold=.05)
selected_X = select_from_model.fit_transform(X, y)
  • 根據線性模型的特徵選擇,如線性迴歸、邏輯迴歸、支援向量機等,引入正則項能防止過擬合,提高模型泛化能力
    • L1正則(lasso正則)
    • L2正則(ridge正則)
from sklearn.feature_selection import SelectFromModel
logistic_selector = SelectFromModel(LogisticRegression(penalty=l1), threshold=.05)
selected_X = logistic_selector.fit_transform(X, y)
4.3 特徵選擇經驗
  • 如果大部分特徵為類別特徵,可採用Chi2檢驗或者決策樹之類的模型進行選擇
  • 如果大部分特徵為數值特徵,可採用線性模型進行選擇
  • 如果為二分類問題,採用SelectFromModel()函式和支援向量機模型
  • 有些情況下,也可進行探索性資料分析,手工選擇特徵,或根據專業知識選擇特徵

5 特徵變換(Feature Transformation)

  • 主成分分析(principal components analysis):sklearn包的PCA
  • 線性判別分析(linear discriminant analysis):sklearn包的LinearDiscriminantAnalysis

PCA是從特徵的協方差角度,希望主成分方向攜帶儘量多的資訊量;而LDA則是在已知樣本的類標註, 希望投影到新的基後使得不同的類別之間的資料點的距離更大,同一類別的資料點更緊湊。

6 特徵學習(Feature Learning)

特徵變換和特徵學習均資料特徵提起範疇,特徵變換的PCA和LDA方法只能處理線性變換,且新的特徵數量受限於輸入特徵數量;而特徵學習則採用深度學習的方法,可以提取更復雜的特徵。

  • 受限玻爾茲曼機(Restricted Boltzmann Machine,RBM):包含兩層的神經網路,可見層(visible layer)和隱藏層(hidden layer),可見層神經元數量等於輸入的特徵數,隱藏層神經元數量等於希望提取的特徵數量,sklearn包的BernoulliRBM
6.1 文字特徵學習
  • Word2Vec
  • GloVe