歡迎來到Scikit-learn教學系列的第二篇文章!在上篇中,我們介紹了Scikit-learn與機器學習基礎,並探索了Iris資料集。這一篇將聚焦於資料預處理,這是機器學習流程中最關鍵的一環。我們將學習如何使用Scikit-learn清理資料、處理缺失值、進行特徵縮放與類別編碼,並以真實資料集進行實作。準備好讓你的資料變得乾淨又高效吧!
為什麼需要資料前處理?
機器學習模型的表現高度依賴於資料品質。原始資料往往存在以下問題:- 缺失值:資料中可能有遺漏的欄位。
- 不同尺度:特徵的數值範圍差異大(例如年齡0-100,收入0-100萬)。
- 類別資料:文字或類別標籤無法直接輸入模型。
- 雜訊與異常值:可能影響模型訓練。
Scikit-learn提供了強大的工具來解決這些問題,讓資料適合模型訓練。
資料前處理的核心步驟
我們將介紹以下四個關鍵技術,並使用Scikit-learn的工具進行實作:
- 處理缺失值:使用SimpleImputer填補缺失資料。
- 特徵縮放:使用StandardScaler與MinMaxScaler標準化特徵。
- 類別資料編碼:使用LabelEncoder與OneHotEncoder轉換類別資料。
- 實作:應用於真實資料集(Titanic)。
1. 處理缺失值:SimpleImputer
缺失值可能導致模型無法訓練。SimpleImputer
允許你用均值、中位數或指定值填補缺失值。
範例程式碼:
from sklearn.impute import SimpleImputer
import numpy as np
# 模擬資料(包含缺失值)
X = np.array([[1, 2, np.nan], [4, np.nan, 6], [7, 8, 9]])
# 使用均值填補缺失值
imputer = SimpleImputer(strategy='mean')
X_imputed = imputer.fit_transform(X)
print("填補後的資料:\n", X_imputed)
說明:strategy
可設為'mean'
(均值)、'median'
(中位數)、'most_frequent'
(眾數)或'constant'
(指定值)。

2. 特徵縮放:StandardScaler與MinMaxScaler
特徵的數值範圍差異可能影響模型表現(例如梯度下降收斂速度)。Scikit-learn提供兩種常見縮放方法:
- StandardScaler:將資料標準化為均值0、標準差1。
- MinMaxScaler:將資料縮放到指定範圍(預設為0到1)。
範例程式碼:
from sklearn.preprocessing import StandardScaler, MinMaxScaler
import numpy as np
# 模擬資料
X = np.array([[1, 200], [3, 400], [5, 600]])
# 標準化
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
print("標準化後:\n", X_scaled)
# 最小-最大縮放
minmax_scaler = MinMaxScaler()
X_minmax = minmax_scaler.fit_transform(X)
print("最小-最大縮放後:\n", X_minmax)
說明:StandardScaler
適合正態分佈資料,MinMaxScaler
適合有界範圍的資料。

3. 類別資料編碼:LabelEncoder與OneHotEncoder
許多模型無法直接處理文字或類別資料,因此需要將其轉為數值形式:
- LabelEncoder:將類別標籤轉為整數(例如['male', 'female'] → [0, 1])。
- OneHotEncoder:將類別轉為二元向量(例如['red', 'blue'] → [[1, 0], [0, 1]])。
範例程式碼:
from sklearn.preprocessing import LabelEncoder, OneHotEncoder
import pandas as pd
# 模擬類別資料
data = pd.DataFrame({'color': ['red', 'blue', 'red'], 'size': ['S', 'M', 'L']})
# LabelEncoder
label_encoder = LabelEncoder()
data['size_encoded'] = label_encoder.fit_transform(data['size'])
print("LabelEncoder結果:\n", data[['size', 'size_encoded']])
# OneHotEncoder
onehot_encoder = OneHotEncoder(sparse_output=False)
color_encoded = onehot_encoder.fit_transform(data[['color']])
color_df = pd.DataFrame(color_encoded, columns=onehot_encoder.get_feature_names_out(['color']))
print("OneHotEncoder結果:\n", color_df)
說明:LabelEncoder
適合有序類別或標籤,OneHotEncoder
適合無序類別,避免模型誤解數值大小。

實作:清理Titanic資料集
讓我們應用上述技術,清理一個真實資料集——Titanic乘客資料(可從Kaggle下載或使用Seaborn內建版本)。目標是準備資料以預測乘客是否存活。
程式碼範例
以下程式碼展示如何對Titanic資料集進行前處理:
import pandas as pd
import seaborn as sns
from sklearn.impute import SimpleImputer
from sklearn.preprocessing import StandardScaler, OneHotEncoder
from sklearn.compose import ColumnTransformer
from sklearn.pipeline import Pipeline
# 載入Titanic資料集
titanic = sns.load_dataset('titanic')
X = titanic[['pclass', 'sex', 'age', 'fare']]
y = titanic['survived']
# 定義前處理流程
numeric_features = ['age', 'fare']
categorical_features = ['pclass', 'sex']
# 數值特徵:填補缺失值並標準化
numeric_transformer = Pipeline(steps=[
('imputer', SimpleImputer(strategy='median')),
('scaler', StandardScaler())
])
# 類別特徵:OneHot編碼
categorical_transformer = OneHotEncoder(drop='first', sparse_output=False)
# 結合前處理
preprocessor = ColumnTransformer(
transformers=[
('num', numeric_transformer, numeric_features),
('cat', categorical_transformer, categorical_features)
])
# 應用前處理
X_processed = preprocessor.fit_transform(X)
# 轉為DataFrame以便檢視
feature_names = (numeric_features +
preprocessor.named_transformers_['cat'].get_feature_names_out(categorical_features).tolist())
X_processed_df = pd.DataFrame(X_processed, columns=feature_names)
print("前處理後的資料:\n", X_processed_df.head())
# 視覺化:年齡分佈
import matplotlib.pyplot as plt
plt.figure(figsize=(8, 6))
sns.histplot(X_processed_df['age'], kde=True)
plt.title('Standardized Age Distribution')
plt.xlabel('Standardized Age')
plt.ylabel('Count')
plt.savefig('titanic_age_distribution.png')
plt.show()
程式碼解釋
- 載入資料:使用Seaborn的Titanic資料集,選擇部分特徵(艙等、性別、年齡、票價)與標籤(存活與否)。
- 前處理管道: 數值特徵(年齡、票價):填補缺失值(中位數)並標準化。 類別特徵(艙等、性別):進行OneHot編碼,drop='first'避免多重共線性。
- ColumnTransformer:整合數值與類別特徵的前處理。
- 視覺化:繪製標準化後的年齡分佈,確認前處理效果。
運行程式碼後,你會得到乾淨的資料集,並看到年齡分佈圖。

練習:處理另一個資料集
請完成以下練習:
- 載入Scikit-learn的load_diabetes()資料集,作為回歸問題的資料。
- 檢查資料是否有缺失值,若有,使用SimpleImputer填補(策略自選)。
- 對所有特徵應用MinMaxScaler進行縮放。
- 繪製任一特徵(例如bmi)縮放後的分佈圖,保存為diabetes_bmi_distribution.png。
以下是起點程式碼:
from sklearn.datasets import load_diabetes
from sklearn.impute import SimpleImputer
from sklearn.preprocessing import MinMaxScaler
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
# 載入Diabetes資料集
diabetes = load_diabetes()
X = diabetes.data
feature_names = diabetes.feature_names
# 你的程式碼從這裡開始...
總結
恭喜你掌握了資料前處理的基礎!本篇文章介紹了如何使用Scikit-learn處理缺失值、縮放特徵與編碼類別資料,並通過Titanic資料集展示了完整的前處理流程。這些技術是構建高效機器學習模型的基石。
在下一篇文章中,我們將進入監督學習 - 分類模型入門,學習如何訓練分類模型並評估其表現。請完成練習,並在留言區分享你的Diabetes資料集分佈圖!
資源與進階學習
- Scikit-learn前處理文件:https://scikit-learn.org/stable/modules/preprocessing.html
- 資料清理實務:《Data Wrangling with Python》
- 練習平台:Kaggle Titanic競賽(https://www.kaggle.com/c/titanic)