iT邦幫忙

2021 iThome 鐵人賽

DAY 12
0
AI & Data

學資料科學的小孩不會變壞- 從入門到實戰全攻略系列 第 12

DAY12 特徵工程-資料化約(特徵選取)

特徵工程可以分為兩大部分,一是根據現有的資料特徵進行篩選,選出較有影響力的特徵進行訓練,另一個是根據現有的資料特徵,去衍生出資料集中沒有的特徵來讓模型學習。今天我們會將重點放在前者。

有時候一個數據集可能可以蒐集到海量的特徵資料,例如一個實驗往往有上百個感測器(Sensor)在記錄資料,但那麼多的特徵不見得對模型的訓練有幫助,甚至還會造成過度擬合(Over-fitting)問題,因此我們今天介紹特徵選取,來對資料進行化約,保留重要的特徵。


一、特徵選取(Feature Selection)

特徵選取是依據所訂定的特徵衡量條件,刪除不相關的特徵或屬性,以選取用於分析資料最佳特徵的過程,使用特徵選取的目的與時機有以下幾點:

1. 用少量的變數/特徵來保有原有的重要資訊

2. 當變數/特徵個數(# of p)遠大於樣本數(# of n)

3. Avoiding Curse of Dimensionality (避免維度災難)

其操作步驟依序為:
https://ithelp.ithome.com.tw/upload/images/20210908/20140427CzEoviwoeo.png
下面我們介紹幾種特徵選取的方法,並運用套件sklearn.feature_selection 裡的函數來實現。


二、過濾法(Filter)

過濾法是列入一些篩選特徵的標準,檢測與目標變數相關的特徵,挑選出具變化性以及中高度相關的特徵,方法包含:

▲移除低變異數的特徵

什麼是低變異數的特徵呢?就是一些資料幾乎沒有變化的特徵,像是:

常數特徵(Constant Feature):一個特徵下的值完全一樣,沒有變化。

from sklearn.feature_selection import VarianceThreshold
constant = VarianceThreshold(threshold=0)
constant.fit(x_train) #fit我們的資料集
# 得到常數特徵的欄位
constant_columns = [column for column in x_train.columns
                    if column not in 
                    x_train.columns[constant.get_support()]]

print(constant_columns)

半常數特徵(Quasi-Constant Feature):特徵裡大部分都是同一個數值。


# 設定門檻,要刪除幾%的資料
threshold = 0.95
quasi_constant_feature = [] #用來記錄的list

for i in x_train.columns: #每個特徵依序看

    # 計算比率
    predominant = (x_train[i].value_counts() /
    np.float(len(x_train))).sort_values(ascending=False).values[0]
    
    # 假如大於門檻 加入 list
    if predominant >= threshold:
        quasi_constant_feature.append(i)

print(quasi_constant_feature)

重複特徵(Duplicated Feature):資料集有兩個以上完全一樣的特徵。

# 轉置特徵矩陣
train_features_T = x_train.T

#找出重複的欄位
duplicated_columns = train_features_T[train_features_T.duplicated()].index.values

print(duplicated_columns )

▲單變量特徵選取

利用一些判斷指標來衡量變數與目標變數之間的關係

挑選方法

● SelectKBest:選取 K 個最好的特徵,k 為參數,代表選擇的特徵數。

● SelectPercentile:選取多少百分比的特徵,percentile 為參數,代表百分比,用 10 代表 10%。

卡方檢定(Chi2)-用於離散型目標變數

以鐵達尼號資料集為例:

from sklearn.feature_selection import SelectKBest
from sklearn.feature_selection import chi2
#離散型資料要先轉成數值

x=_train_df[['Pclass', 'Sex', 'Age', 'Fare', 'Embarked', 'IsAlone','Cabin']]
y=data['Survived']

x_new = SelectKBest(chi2, k=2).fit_transform(x, y) #挑選2個最好的特徵
display(x_new)

f_regression-用於連續型目標變數

假設預測股價

from sklearn.feature_selection import SelectKBest
from sklearn.feature_selection import f_regression

x=data[['前一天價格','前一季價格', '前一年價格','同性質股票價格']]
y=data['Price']

x_new = SelectPercentile(chi2, percentile=50).fit_transform(x, y) #取前50%的特徵

display(x_new)

三、包裝法(Wrapper)

是一種特徵選擇和演算法訓練同時進行的方法,根據某一種評量標準,每次選擇某些特徵或排除某些特徵,常用的方法為遞歸特徵消除(RFE)。

RFE是根據問題為離散或連續,利用機器學習的模型進行挑選,為一貪婪優化演算法,目的在找尋最佳的特徵子集。

RFE

#RFE
from sklearn.feature_selection import RFE
rf = RandomForestClassifier()
rfe = RFE(rf, 6) #篩選6個特徵
rfe.fit(X_train, Y_train)

print(f"Number of selected features: {rfe.n_features_}\n\
Selected Features:", [feature for feature, rank in zip(X_train.columns.values, rfe.ranking_) if rank==1]) #列出挑選的6個變數

以鐵達尼號資料集為例,我們找到以下6個特徵
https://ithelp.ithome.com.tw/upload/images/20210908/20140427jpXvIgLsQR.jpg

Stepwise Selection

運作方式為:一開始模型有全部k個變數,一個接一個從k個變數中選取對 y (label)變異最沒顯著影響的變數刪除,直到剩餘的變數對解釋y (label)剩餘變異皆有顯著影響才停止。

程式碼實現

import statsmodels.api as sm
import pandas as pd
#Stepwise
def stepwise_selection(data, target,SL_in=0.05,SL_out = 0.05):
    initial_features = data.columns.tolist()
    best_features = []
    while (len(initial_features)>0):
        remaining_features = list(set(initial_features)-set(best_features))
        new_pval = pd.Series(index=remaining_features)
        for new_column in remaining_features:
            model = sm.OLS(target, sm.add_constant(data[best_features+[new_column]])).fit()
            new_pval[new_column] = model.pvalues[new_column]
        min_p_value = new_pval.min()
        if(min_p_value<SL_in):
            best_features.append(new_pval.idxmin())
            while(len(best_features)>0):
                best_features_with_constant = sm.add_constant(data[best_features])
                p_values = sm.OLS(target, best_features_with_constant).fit().pvalues[1:]
                max_p_value = p_values.max()
                if(max_p_value >= SL_out):
                    excluded_feature = p_values.idxmax()
                    best_features.remove(excluded_feature)
                else:
                    break 
        else:
            break
    return best_features

https://ithelp.ithome.com.tw/upload/images/20210908/201404273BMXv76aRI.jpg


四、結論

今天介紹了幾種方法用於特徵選取,有時候我們拿到的資料集的特徵很多,模型訓練起來狀況不佳的話,就可以考慮使用特徵選取來篩選好的特徵,但也要注意閥值、參數的控制,不要弄巧成拙的把好特徵刪除。

篩選出壞的特徵並不難,但當我們手邊的資料特徵沒有這麼多時,就要想辦法生出新的特徵,舉例來說:我們可以透過身高及體重資料生成出BMI的資料,這個"衍生"資料的步驟比特徵選取還難的多,卻也更重要,需要結合對於分析行業的知識量以及對數據的敏感度,當然,接觸過越多資料分析專案就能越上手!


上一篇
DAY11 資料前處理-資料不平衡處理方法
下一篇
DAY13 特徵工程-資料標準化與降維
系列文
學資料科學的小孩不會變壞- 從入門到實戰全攻略30

尚未有邦友留言

立即登入留言