機器學習中的特徵工程詳解
阿新 • • 發佈:2019-01-10
最近看完一本寫特徵工程的書,概念清晰,內容全面,所以總結如下讀書筆記,書名: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