聊天視窗

數據科學的決策力:從原理到實踐 - 第 3 章

第3章 資料前處理與特徵工程

發布於 2026-02-26 20:47

# 第3章 資料前處理與特徵工程 資料前處理與特徵工程是任何數據科學專案的基石。透過清理、轉換與擴充原始資料,我們不僅能提升模型的準確度,還能在整個工作流程中降低錯誤、提升可重複性與可擴展性。本章將詳細探討三大核心面向: 1. **資料清洗**:缺失值、異常值與重複值處理。 2. **特徵轉換**:標準化、編碼、派生特徵與降維。 3. **資料管道設計**:自動化、版本控制與重複使用。 > **實務小貼士**:在進行任何變更前,先使用 **EDA**(探索性資料分析)確認資料分佈與異常點。始終保持「原始資料備份」與「變更日誌」的紀錄,方便回溯與合規檢查。 ## 3.1 資料清洗:缺失值、異常值與重複值處理 | 步驟 | 方法 | 何時使用 | 典型工具 | |------|------|----------|----------| | 缺失值處理 | 刪除、填補(平均/中位/眾數、kNN、插值、模型預測) | 資料量充足、缺失率低 | `pandas`, `scikit-learn` Imputer | | 異常值處理 | 盒鬚圖、Z-Score、IQR、Isolation Forest、DBSCAN | 需要保留潛在重要信號時 | `scipy`, `pyod` | | 重複值處理 | `drop_duplicates()` | 資料來源可能重複抓取 | `pandas` | ### 缺失值處理範例 python import pandas as pd from sklearn.impute import SimpleImputer df = pd.read_csv('data.csv') # 1. 刪除含缺失值的列 cleaned = df.dropna(subset=['age', 'salary']) # 2. 用中位數填補數值型缺失 imputer = SimpleImputer(strategy='median') df['age'] = imputer.fit_transform(df[['age']]) > **注意**:不同資料類型(數值、類別、時間序列)選擇不同的填補策略。填補不當可能引入偏差,尤其在高維資料中更需謹慎。 ### 異常值處理範例 python import numpy as np # Z-Score 方式 z_scores = np.abs((df['salary'] - df['salary'].mean()) / df['salary'].std()) threshold = 3 outliers = df[z_scores > threshold] # 可選擇刪除或轉為缺失值再填補 > **實務提示**:在金融或醫療領域,異常值往往代表重大的商業機會或錯誤。先用統計方法標記,再人工判斷,可提升決策質量。 ## 3.2 特徵轉換、標準化與編碼技術 ### 3.2.1 數值型特徵處理 | 技術 | 目的 | 典型實現 | |------|------|----------| | 正規化(Min-Max) | 將數值縮放到 [0,1] | `MinMaxScaler` | | 標準化(Z-Score) | 使均值 0、方差 1 | `StandardScaler` | | Box-Cox / Yeo-Johnson | 使資料近似正態分佈 | `scipy.stats.boxcox` | | 分箱 | 降低噪音、處理離散化 | 自訂分箱策略 | python from sklearn.preprocessing import StandardScaler, MinMaxScaler scaler = StandardScaler() X_scaled = scaler.fit_transform(df[['age', 'salary']]) > **小貼士**:若模型為樹型演算法(如 XGBoost、RandomForest),標準化與正規化不一定必要;但對於線性模型、SVM 或神經網路則必須。 ### 3.2.2 類別型特徵處理 | 編碼方式 | 何時使用 | 典型工具 | |----------|----------|----------| | One-Hot | 類別數量較少、無序 | `pandas.get_dummies`, `OneHotEncoder` | | Label | 類別具有序、資料量大 | `LabelEncoder`, `OrdinalEncoder` | | Target/Mean Encoding | 針對高頻特徵,保留預測信息 | `category_encoders.TargetEncoder` | | Frequency Encoding | 針對稀疏特徵 | 手工實現或 `category_encoders` | python from sklearn.preprocessing import OneHotEncoder encoder = OneHotEncoder(sparse=False) cat_encoded = encoder.fit_transform(df[['country']]) > **實務提醒**:One-Hot 會產生高維稀疏矩陣,若類別數量極大可考慮 Target 或 Frequency Encoding。確保避免「漏資訊」與「過擬合」。 ### 3.2.3 特徵派生(Feature Engineering) | 派生方式 | 範例 | |----------|------| | 數學運算 | `age_squared = age ** 2` | | 組合特徵 | `total_spent = order_value + shipping_cost` | | 日期拆分 | `year = order_date.year` | | 文本特徵 | TF-IDF, Word2Vec | | 時間序列衍生 | 前後期值、滯後差異 | python # 日期拆分 df['order_year'] = pd.to_datetime(df['order_date']).dt.year # 組合特徵 df['total_spent'] = df['order_value'] + df['shipping_cost'] > **案例**:在電商平台,將「最後一次購買距今天數」與「購買頻率」組合,可有效提升客戶價值預測模型的 AUC。 ### 3.2.4 降維 | 方法 | 適用場景 | |------|----------| | PCA | 需要保留方差,線性可分 | | t-SNE / UMAP | 視覺化、處理高維稀疏 | | LLE | 非線性結構 | python from sklearn.decomposition import PCA pca = PCA(n_components=5) X_pca = pca.fit_transform(df_numeric) > **實務提示**:降維後的特徵需重新檢查是否與商業語義相符;若使用於模型輸入,最好在 **管道** 內完成,確保可追蹤。 ## 3.3 建立可重複的資料管道與自動化流程 ### 3.3.1 Pipeline 與 FeatureUnion > **scikit-learn** 提供 `Pipeline` 與 `FeatureUnion`,讓我們能將預處理步驟串接、驗證與版本化。 python from sklearn.pipeline import Pipeline, FeatureUnion from sklearn.impute import SimpleImputer from sklearn.preprocessing import StandardScaler, OneHotEncoder from sklearn.compose import ColumnTransformer numeric_features = ['age', 'salary'] numeric_transformer = Pipeline([ ('imputer', SimpleImputer(strategy='median')), ('scaler', StandardScaler()) ]) categorical_features = ['country'] categorical_transformer = Pipeline([ ('imputer', SimpleImputer(strategy='most_frequent')), ('onehot', OneHotEncoder(handle_unknown='ignore')) ]) preprocessor = ColumnTransformer([ ('num', numeric_transformer, numeric_features), ('cat', categorical_transformer, categorical_features) ]) ### 3.3.2 版本控制 & 數據治理 | 工具 | 角色 | |------|------| | DVC (Data Version Control) | 跟蹤資料、模型、代碼 | `dvc` | | MLflow | 實驗記錄、模型追蹤 | `mlflow` | | Airflow / Prefect | 工作流排程、監控 | `airflow`, `prefect` | bash # 初始化 DVC 版本控制 $ dvc init $ dvc add data.csv $ git add data.csv.dvc .gitignore $ git commit -m "Add raw data to DVC" > **建議**:將 **資料來源**、**轉換腳本**、**模型** 以及 **結果** 全部納入版本控制。這不僅符合團隊開發流程,亦可作為 **合規審核** 的依據。 ### 3.3.3 自動化工作流範例 python # 假設我們使用 Prefect 建立一個簡易資料管道 from prefect import task, Flow import pandas as pd @task def load_data(path: str) -> pd.DataFrame: return pd.read_csv(path) @task def clean_data(df: pd.DataFrame) -> pd.DataFrame: return df.dropna() @task def engineer_features(df: pd.DataFrame) -> pd.DataFrame: df['order_year'] = pd.to_datetime(df['order_date']).dt.year return df with Flow('E-commerce Feature Pipeline') as flow: raw = load_data('raw_data.csv') cleaned = clean_data(raw) engineered = engineer_features(cleaned) # 執行 flow.run() > **小貼士**:在生產環境,將 **Python 腳本** 轉為 Docker 容器,並利用 CI/CD 系統(GitHub Actions / GitLab CI)自動執行測試與部署。 ## 3.4 結合實務案例:電商 CTR 預測 | 步驟 | 目標 | 主要特徵 | |------|------|----------| | 1. 資料清洗 | 去除錯誤、填補缺失 | `timestamp`, `clicks` | | 2. 特徵派生 | `time_since_last_click`, `session_duration` | | 3. 編碼 | `device_type`, `user_location` | One-Hot + Frequency | | 4. 標準化 | `price`, `session_duration` | StandardScaler | | 5. Pipeline | `ColumnTransformer` + 模型 | XGBoost | python from sklearn.pipeline import Pipeline from sklearn.compose import ColumnTransformer from sklearn.preprocessing import OneHotEncoder, StandardScaler from xgboost import XGBClassifier numeric_cols = ['price', 'session_duration'] cat_cols = ['device_type', 'user_location'] numeric_pipe = Pipeline([ ('scaler', StandardScaler()) ]) categorical_pipe = Pipeline([ ('onehot', OneHotEncoder(handle_unknown='ignore')) ]) preprocessor = ColumnTransformer([ ('num', numeric_pipe, numeric_cols), ('cat', categorical_pipe, cat_cols) ]) clf = Pipeline([ ('prep', preprocessor), ('model', XGBClassifier(n_estimators=300, learning_rate=0.05)) ]) clf.fit(X_train, y_train) > **效果**:在該案例中,通過上述清洗與特徵工程,最終 CTR 預測 AUC 從 0.72 提升至 0.81,並將模型訓練時間縮短 35%。 ## 3.5 小結 1. **資料清洗** 需要依據業務場景與資料結構選擇合適的方法。缺失值與異常值的處理不僅能避免模型過擬合,更能保留重要訊號。 2. **特徵轉換** 與 **編碼** 應配合模型特性(線性 vs 迴歸 vs 樹型)進行優化。正確的標準化與編碼能顯著提升模型表現。 3. **資料管道** 的設計決定了專案能否擴充、維護與重複使用。利用 Pipeline、DVC、MLflow 等工具可實現自動化與版本追蹤。 > **Takeaway**:特徵工程並非「藝術」,它是數據科學流程中可量化、可驗證的工程。把每一次資料處理都寫成可執行腳本,並在 CI/CD 中自動化,才能真正實現「資料為先」的數據科學。