聊天視窗

數據洞察:從基礎到實踐的資料科學全書 - 第 3 章

第 3 章:資料前處理的藝術與科學

發布於 2026-02-28 02:30

# 第 3 章:資料前處理的藝術與科學 > **為什麼前處理如此重要?**\n資料科學的成功往往取決於「乾淨」與「結構化」的輸入。即使是最先進的機器學習模型,也無法在缺失值、異常值或不一致的編碼面前保持良好表現。這一章將帶你從實際案例出發,學習如何將雜亂的資料轉換為機器學習友好的結構。 ## 3.1 前言 - **前處理**:資料從收集到模型訓練的「橋樑」。 - 目標:降低噪音、提升模型泛化、加速迭代。\n > **案例啟示**:在 2024 年的「客戶流失預測」專案中,缺失值佔 12% 的特徵若不處理,模型召回率下降 7%。 ## 3.2 缺失值處理 | 方法 | 適用情境 | 代碼範例 | |------|----------|----------| | 刪除 | 缺失值比例極低,且不會引起樣本偏差 | python import pandas as pd df = df.dropna(subset=['age', 'salary']) | | 代入均值/中位數 | 數值型特徵,缺失分布大致對稱 | python from sklearn.impute import SimpleImputer imp = SimpleImputer(strategy='median') df['age'] = imp.fit_transform(df[['age']]) | | 代入常數 / 最頻值 | 分類特徵,缺失代表「未知」 | python imp = SimpleImputer(strategy='most_frequent') df['gender'] = imp.fit_transform(df[['gender']]) | | 迭代插補 | 變數間高度相關,需保持結構 | python from sklearn.experimental import enable_iterative_imputer from sklearn.impute import IterativeImputer imp = IterativeImputer(random_state=0) df = pd.DataFrame(imp.fit_transform(df), columns=df.columns) | > **小技巧**:在 `pandas` 中使用 `df.isna().sum()` 先統計缺失分布,視情況選擇方法。 ## 3.3 標準化與歸一化 | 方法 | 效果 | 適用場景 | |------|------|----------| | Z‑Score 標準化 | 平均值 0,標準差 1 | 需要距離度量的模型(SVM、KNN) | | Min‑Max 歸一化 | 將值壓縮至 [0,1] | 對於 Neural Network 的輸入層 | | Robust Scaling | 以 IQR 為基準 | 異常值較多的資料 | python from sklearn.preprocessing import StandardScaler, MinMaxScaler, RobustScaler scaler = StandardScaler() X_scaled = scaler.fit_transform(df[['age', 'salary']]) > **實務提醒**:將縮放器納入 `Pipeline`,確保訓練/測試的統一流程。 ## 3.4 類別編碼技巧 | 編碼 | 原理 | 何時使用 | |------|------|----------| | One‑Hot | 為每類別建立二進制向量 | 類別無序(例如顏色) | | Ordinal | 為類別賦予順序 | 有明確排序(例如教育程度) | | Target Encoding | 用目標變量的平均值替換 | 避免高維度、稀疏特徵 | python from sklearn.preprocessing import OneHotEncoder enc = OneHotEncoder(sparse=False) encoded = enc.fit_transform(df[['city']]) > **警示**:Target Encoding 需做 K‑Fold 交叉驗證,防止資訊洩漏。 ## 3.5 特徵工程與篩選 1. **派生特徵**:組合、交互、數學轉換。 - `df['age_group'] = pd.cut(df['age'], bins=[0,20,40,60,100], labels=['0-20','20-40','40-60','60+'])` 2. **特徵重要性排序**:使用 `RandomForestRegressor` 或 `XGBoost` 的 `feature_importances_`。 3. **遞迴特徵刪除 (RFE)**:逐步移除低重要性特徵。 4. **主成份分析 (PCA)**:降維保留 95% 變異。 > **實例**:在房價預測中,將 `sqft_living` 與 `sqft_above` 組合成 `total_sqft`,可顯著提升模型 R²。 ## 3.6 數據質量檢查 - **重複資料**:`df.duplicated().sum()`。 - **不一致值**:字元大小寫、前後空白,使用 `str.strip()`、`str.lower()`。 - **邏輯檢查**:例如 `age` 不能為負,`birth_year` 與 `current_year` 的差值合理。 - **離群值檢測**:箱型圖、IQR 方法、Z‑Score 超過 3。 python q1 = df['salary'].quantile(0.25) q3 = df['salary'].quantile(0.75) iqr = q3 - q1 lower, upper = q1 - 1.5 * iqr, q3 + 1.5 * iqr outliers = df[(df['salary'] < lower) | (df['salary'] > upper)] > **記錄與追蹤**:使用 `data.dvc` 或 `git lfs` 版本化資料,保證可回溯。 ## 3.7 建立可重複流程 - **使用 `Pipeline`**:將缺失處理、標準化、編碼串接。 - **保存**:`joblib.dump(pipeline, 'pipeline.pkl')`,部署時直接 `joblib.load()`。 - **測試**:分離測試集,確保資料流不混入訓練資訊。 - **日志**:`logging` 模組追蹤前處理步驟與參數。 python from sklearn.pipeline import Pipeline from sklearn.compose import ColumnTransformer numeric_features = ['age', 'salary'] numeric_transformer = Pipeline(steps=[ ('imputer', SimpleImputer(strategy='median')), ('scaler', StandardScaler()), ]) categorical_features = ['gender', 'city'] categorical_transformer = Pipeline(steps=[ ('imputer', SimpleImputer(strategy='most_frequent')), ('onehot', OneHotEncoder(handle_unknown='ignore')), ]) preprocessor = ColumnTransformer( transformers=[ ('num', numeric_transformer, numeric_features), ('cat', categorical_transformer, categorical_features), ]) pipeline = Pipeline(steps=[('preprocessor', preprocessor)]) > **部署**:將 pipeline 包裝成 `setup.py` 或 `pyproject.toml`,轉成 Python package,確保團隊協作一致。 ## 3.8 小結 - **前處理** 不是「雜項」工作,而是構建堅實基礎的關鍵環節。\n- **缺失值** 需要根據資料特性靈活處理。\n- **標準化** 與 **編碼** 要與模型選型相匹配。\n- **特徵工程** 既是創造性工作,也是系統化的迭代。\n- **數據質量檢查** 是防止後續模型失效的第一道防線。\n- **可重複流程** 的建立,保障團隊從實驗到部署的順暢與可追溯。 > **下一步**:第 4 章將深入機器學習算法,從線性模型到樹模型,並在前處理基礎上進行模型訓練、評估與調參。