iT邦幫忙

2024 iThome 鐵人賽

DAY 24
1
AI/ ML & Data

征服機器學習的終極秘技系列 第 24

Day 24 - 應用實作練習:特徵選擇及數據切分

  • 分享至 

  • xImage
  •  

📌 前言

在前一篇文章中,我們討論了如何進行特徵創建、轉換和縮放。然而,隨著特徵的增加,模型可能變得過於複雜且容易過擬合。這時,我們需要進行特徵選擇,以確保只使用對模型預測最有幫助的特徵,並提高模型的性能和解釋性。完成後,我們也要將數據分割為訓練集和測試集,這是評估模型性能的重要步驟。

🔍特徵選擇

由於我們之前已採用 One Hot Encoding 方式將特徵擴增,為了避免一些不重要的參數影響,我們需要進行特徵選擇。這包括之前提過的 Pearson 係數卡方檢驗(Chi-squared)遞歸特徵消除法(RFE),以及嵌入法(Embedded methods),這些方法涉及不同的演算法,如邏輯回歸、隨機森林等。筆者喜好將這些都計算完並放在 DataFrame 裡一次比較。首先要先拆分 X 和 y,以確保程式知道輸入和輸出分別是什麼,才能了解它們之間的關係。程式碼如下:

X = cleaning_data_filtered.drop('Test Results', axis=1) # 我們要預測 Normal/Abnirmal,這些都是輸出,所以要把這個欄位移除才是輸入
y = cleaning_data_filtered['Test Results'] # 輸出是 Test Results

接下來,我們將使用不同的方法來進行特徵選擇:

1. 🧑‍💻Pearson 係數特徵選擇

這個方法通過計算每個特徵 X 與目標變量 y 的相關性來篩選特徵。以下是相應的程式碼:

import numpy as np
def cor_selector(X, y,num_feats):
    cor_list = []
    feature_name = X.columns.tolist()
    # 計算每個特徵與 y 的相關性
    for i in X.columns.tolist():
        cor = np.corrcoef(X[i], y)[0, 1]
        cor_list.append(cor)
    # 將 NaN 替換為 0
    cor_list = [0 if np.isnan(i) else i for i in cor_list]
    # 篩選出相關性最高的特徵 
    cor_feature = X.iloc[:,np.argsort(np.abs(cor_list))[-num_feats:]].columns.tolist()
    # 特徵篩選  0 不選擇, 1 選擇
    cor_support = [True if i in cor_feature else False for i in feature_name]
    return cor_support, cor_feature
cor_support, cor_feature = cor_selector(X, y, 12)
print(str(len(cor_feature)), 'selected features')

2. 📊卡方檢驗特徵選擇

使用卡方檢驗來評估每個特徵的顯著性:

from sklearn.feature_selection import SelectKBest
from sklearn.feature_selection import chi2
from sklearn.preprocessing import MinMaxScaler
X_norm = MinMaxScaler().fit_transform(X)
chi_selector = SelectKBest(chi2, k=12)
chi_selector.fit(X_norm, y)
chi_support = chi_selector.get_support()
chi_feature = X.loc[:,chi_support].columns.tolist()
print(str(len(chi_feature)), 'selected features')

🧮3. 遞歸特徵消除法 (RFE)

這個方法利用一個基於邏輯回歸的模型,通過遞歸地消除最不重要的特徵來選擇特徵:

from sklearn.feature_selection import RFE
from sklearn.linear_model import LogisticRegression
rfe_selector = RFE(estimator=LogisticRegression(), n_features_to_select=12, step=10, verbose=5)
rfe_selector.fit(X_norm, y)
rfe_support = rfe_selector.get_support()
rfe_feature = X.loc[:,rfe_support].columns.tolist()
print(str(len(rfe_feature)), 'selected features')

🔥4. 嵌入法特徵選擇

使用邏輯回歸和隨機森林進行嵌入法特徵選擇:

  • 邏輯回歸
from sklearn.feature_selection import SelectFromModel
from sklearn.linear_model import LogisticRegression

embeded_lr_selector = SelectFromModel(LogisticRegression(penalty="l2"), max_features=12)
embeded_lr_selector.fit(X_norm, y)

embeded_lr_support = embeded_lr_selector.get_support()
embeded_lr_feature = X.loc[:,embeded_lr_support].columns.tolist()
print(str(len(embeded_lr_feature)), 'selected features')
  • 隨機森林
from sklearn.feature_selection import SelectFromModel
from sklearn.ensemble import RandomForestClassifier

embeded_rf_selector = SelectFromModel(RandomForestClassifier(n_estimators=100), max_features=12)
embeded_rf_selector.fit(X, y)

embeded_rf_support = embeded_rf_selector.get_support()
embeded_rf_feature = X.loc[:,embeded_rf_support].columns.tolist()
print(str(len(embeded_rf_feature)), 'selected features')

✨綜合特徵選擇結果

最後,我們將所有特徵選擇方法的結果彙總在一起,以便進行比較:

feature_name = X.columns
# 將所有選擇的結果放在 DataFrame 中
feature_selection_df = pd.DataFrame({'Feature':feature_name, 'Pearson':cor_support, 'Chi-2':chi_support, 'RFE':rfe_support, 'Logistics':embeded_lr_support,
                                    'Random Forest':embeded_rf_support})
# 計算每個特徵被選擇的次數
# 在加總數量時先轉換 Boolean 為 integer
feature_selection_df['Total'] = feature_selection_df[['Pearson', 'Chi-2', 'RFE', 'Logistics', 'Random Forest']].astype(int).sum(axis=1)
# 排序顯示前 12 個特徵 (可以嘗試顯示不同的特徵數)
feature_selection_df = feature_selection_df.sort_values(['Total','Feature'] , ascending=False)
feature_selection_df.index = range(1, len(feature_selection_df)+1)
feature_selection_df.head(12)

得出的結果:
https://ithelp.ithome.com.tw/upload/images/20240925/20168116LSF6xsi69S.png

結果解釋
總選擇次數反映了每個特徵在不同特徵選擇方法中的重要性。例如,Age 特徵被所有五種方法選擇,表明它對預測目標變數極其重要。

方法分析:

  • Pearson:所有特徵中,大部分都被認為與目標變數有線性關聯,只有 Room Number 未被選中,這顯示出其與目標變數之間的相關性較弱。
  • Chi-2:所有與健康狀況相關的特徵和 Gender_Male 被選中,表示這些特徵對於類別預測具有顯著性。
  • RFE (遞歸特徵消除法):大多數特徵在此方法中也被選中,顯示它們對於模型的預測準確性具有影響力。
  • Logistics:雖然大部分特徵在此方法中被選中,但 Insurance Provider_Cigna 和 Insurance Provider_Blue Cross 未被選中,可能表明它們在預測中相對不重要。
  • Random Forest:此方法強調特徵的重要性,Room Number 被選中,但它在其他方法中未顯示重要性,顯示出這個特徵在某些模型中可能對預測有所幫助。

特徵重要性:

  • Age 是最重要的特徵,因為它被所有五種方法選中,建議保留。
  • Medical Condition 相關的特徵(如 Obesity、Hypertension 等)在大多數方法中都顯示出高重要性,值得在模型中保留。
  • Billing Amount 在多數方法中被選中,可能與預測結果有關聯。
  • Room Number 僅在少數方法中被選中,重要性較低,可能可以考慮移除。

筆者決定嘗試在模型訓練前將 Room Number 特徵刪除,並保留其他特徵。因此:

cleaning_data_filtered.drop('Room Number', axis=1, inplace=True)

📐🗂️數據切分

最終在建立演算法之前,最重要的一步是切分數據集

1. 🎲📊隨機切分法 (Random Split)

隨機切分法是最常見的數據切分方法,通常將數據按照 7:3 或 8:2 的比例分為訓練集和測試集。以 7:3 切分的程式碼如下,random_state 設定任意數值,目的是為了後續要跟模型進行比較時,可以確保切分後運用的數據是一樣的。若讀者沒有要用不同模型進行比較時,可以不需設定 random_state。

from sklearn.model_selection import train_test_split
# 將數據分為訓練集和測試集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)

2. ⚖️🔄分層抽樣法 (Stratified Sampling)

在類別不平衡的數據集中,分層抽樣法可以確保訓練集和測試集中的每個類別比例一致,這樣可以避免模型在某些類別上表現過於偏差。程式碼如下:

# 分層抽樣切分數據 
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, stratify=y, random_state=42) 

注意:除了上述方法,還有更複雜的驗證方法,如K-fold交叉驗證。這種方法在模型選擇和評估階段特別有用,我們將在後續的模型訓練和評估章節中介紹。

由於此 Kaggle 數據集類別是平衡的,筆者將採用隨機切分法來進行。

📝✅結論

通過特徵選擇,我們可以提高模型的效率和解釋性;通過適當的數據切分,我們可以確保模型評估的可靠性和泛化能力🌍。在實際應用中,我們需要根據具體的數據特性和問題需求,選擇合適的特徵選擇方法和數據切分策略🎯。這個階段也是需要嘗試不同的組合,包含特徵數量及不同方法🔧。接下來,我們將進入演算法選擇和模型訓練的階段,利用我們精心準備的數據集來構建預測模型🚀💻。


上一篇
Day 23 - 應用實作練習:特徵工程
下一篇
Day 25 - 應用實作練習:演算法選擇
系列文
征服機器學習的終極秘技30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言