
帶著大家簡單地看過整個機器學習流程之後,相信每個人對於機器學習在幹嘛還是很模糊,因此這章節來個實際範例,讓大家更了解在每一個流程中資料科學家究竟都在做什麼。
這裡我使用機器學習中很有名的”鳶尾花”資料集,這部分內容會比較多,希望大家可以跟著我的步驟慢慢地操作,細細地去體驗如何完成一個基本的機器學習專案。
🧩 1. 載入資料與探索性分析 (EDA)
了解資料結構與特性,是機器學習模型成功的關鍵第一步!
資料集介紹:
鳶尾花資料包含 150 筆資料,每筆有四個特徵:
- 花萼長度(sepal length)
- 花萼寬度(sepal width)
- 花瓣長度(petal length)
- 花瓣寬度(petal width)
對應到三種花種(target):setosa(0), versicolor(1), virginica(2)
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
from sklearn.datasets import load_iris
# 載入資料
iris = load_iris()
X = pd.DataFrame(iris.data, columns=iris.feature_names)
y = pd.Series(iris.target, name='target')
# 合併為一份資料集
df = pd.concat([X, y], axis=1)
# 初步檢視
print(df.head())
print(df.describe())
print(df['target'].value_counts())
# 輸出
sepal length (cm) sepal width (cm) petal length (cm) petal width (cm) \
0 5.1 3.5 1.4 0.2
1 4.9 3.0 1.4 0.2
2 4.7 3.2 1.3 0.2
3 4.6 3.1 1.5 0.2
4 5.0 3.6 1.4 0.2
target
0 0
1 0
2 0
3 0
4 0
sepal length (cm) sepal width (cm) petal length (cm) \
count 150.000000 150.000000 150.000000
mean 5.843333 3.057333 3.758000
std 0.828066 0.435866 1.765298
min 4.300000 2.000000 1.000000
25% 5.100000 2.800000 1.600000
50% 5.800000 3.000000 4.350000
75% 6.400000 3.300000 5.100000
max 7.900000 4.400000 6.900000
petal width (cm) target
count 150.000000 150.000000
mean 1.199333 1.000000
std 0.762238 0.819232
min 0.100000 0.000000
25% 0.300000 0.000000
50% 1.300000 1.000000
75% 1.800000 2.000000
max 2.500000 2.000000
target
0 50
1 50
2 50
Name: count, dtype: int64
說明
透過基本的統計分析可以初步了解以下資料特性:
- 有哪些數值型特徵? 有哪些類別型特徵?
- 各品種之間的差異
- 標籤(label)數量是否均衡: 每個品種的數量是否比例差不多
視覺化分析
由於此資料集特徵數量較少,我們可以使用Pair Plot來觀察兩兩特徵對於品種的分類影響力。 在圖上面如果點分得越開,代表此特徵對於品種的分類效果越好!
# 載入鳶尾花資料
iris = load_iris()
df_plot = pd.DataFrame(iris.data, columns=iris.feature_names)
df_plot['species'] = pd.Categorical.from_codes(iris.target, iris.target_names)
# 畫圖:使用 pairplot 查看四個特徵對於分類的區別性
sns.set(style="whitegrid")
pairplot_fig = sns.pairplot(df_plot, hue='species', diag_kind='hist', corner=True)
plt.suptitle("Iris Dataset Feature Pairplot", y=1.02)
plt.tight_layout()
plt.show()

🔍觀察到什麼?
- Petal length(花瓣長度)與 Petal width(花瓣寬度)幾乎可以明確區分三個物種,是最有辨識力的特徵。
- Sepal length 和 Sepal width 分類效果相對較差,特別是 Versicolor 與 Virginica 之間容易混淆。
💡這表示花瓣的長度與寬度會是機器學習模型訓練時的重要特徵!
🧹 2. 資料前處理
確保模型能夠讀懂並處理資料的格式、範圍、缺失值和異常值等問題,使資料處於"乾淨"的狀態。
# 檢查空值
print(df.isnull().sum())
# 特徵與標籤拆分
X = df.drop('target', axis=1)
y = df['target']
# 輸出
sepal length (cm) 0
sepal width (cm) 0
petal length (cm) 0
petal width (cm) 0
target 0
說明
檢查後發現四種特徵都沒有缺失值,如果有缺失值可以填補平均數、中位數等有意義的數值。
# 以視覺化來檢查異常值
import seaborn as sns
import matplotlib.pyplot as plt
# Boxplot 查看每個欄位的異常值
plt.figure(figsize=(12, 6))
sns.boxplot(data=X)
plt.title("Iris Outlier")
plt.xticks(rotation=45)
plt.show()

說明
以Boxplot(盒鬚圖)檢查是否有淺在異常值(Outlier),以超出盒鬚圖上下界線為判斷基準。可以看到只有Sepal Width特徵有少數資料超出界線,但並沒有超出非常多,因此可以自行選擇剃除或不剃除這些資料。 如果是第一次建模,可先保留並觀察模型能力再做後續處理。
🛠️ 3. 特徵工程(本例無須額外處理)
本資料特徵皆為數值且無缺失,無需進一步編碼或填補。若是非結構化資料或類別欄位,可能需做 One-Hot Encoding、標準化等處理。
特徵篩選
透過探索性分析中的視覺化圖表,我們可以利用 Pair-Plot 的結果來進行特徵篩選,根據特徵的可分性、相關性、與目標變數的關聯強度,挑選最具代表性與區辨力的特徵。
我們觀察 Pair-Plot 後發現:
- petal length (cm) 和 petal width (cm):三類花種分布明顯區隔,是高區辨力特徵
- sepal length (cm):對 virginica 和 versicolor 有些微區分
- sepal width (cm):分布重疊多,對分類幫助較小
因此有以下篩選建議:

X_selected = df[['petal length (cm)', 'petal width (cm)']]
✂️ 4. 資料切分
將資料切分為訓練集與測試集,避免過擬合並驗證模型泛化能力。 依照模型再訓練集和測試集中的表現可以分為過擬合(Overfitting)和欠擬合(Underfitting)兩種異常狀況,在這裡暫不討論。
切分比例可以是(80/20)或是(70/30),沒有絕對的標準,需要依照資料集狀況調整,並且記得使用特徵篩選後的X來切分資料!
from sklearn.model_selection import train_test_split
# 切分資料(80%訓練 / 20%測試)
X_train, X_test, y_train, y_test = train_test_split(X_selected, y, test_size=0.2, random_state=42)
print(f'訓練集筆數: {X_train.shape}')
print(f'測試集筆數: {X_test.shape}')
# 輸出
訓練集筆數: (120, 2)
測試集筆數: (30, 2)
說明
訓練集筆數中的120代表有120筆資料,2代表有兩個特徵。
🧠 5. 模型選擇與訓練
可以作為分類使用的模型非常多種,例如Logistic Regression、SVM、Neural Network等演算法,這部分我們使用簡單但強大的 RandomForestClassifier!暫時先不要考慮需要調整什麼參數,直接訓練即可!!!
from sklearn.ensemble import RandomForestClassifier
# 建立模型
model = RandomForestClassifier(n_estimators=100, random_state=42)
model.fit(X_train, y_train)
📈 6. 模型評估
由於此資料集是分類任務,因此使用 Accuracy、混淆矩陣等指標來評估模型的表現。 若是迴歸任務,則需要採用MSE、MAE、MAPE...等指標來進行評估。
from sklearn.metrics import accuracy_score, confusion_matrix, ConfusionMatrixDisplay
# 預測
y_pred = model.predict(X_test)
cm = confusion_matrix(y_test, y_pred)
# 顯示帶標籤的混淆矩陣
disp = ConfusionMatrixDisplay(confusion_matrix=cm, display_labels=iris.target_names)
disp.plot()
# 評估
print("Accuracy:", accuracy_score(y_test, y_pred))
# 輸出
Accuracy: 1.0

說明
- Accuracy等於1.0,代表模型訓練完美,以這個資料集來說這是合理的,但如果這個數字出現在實務的資料上,很大機率代表非常有問題!!!
- 混淆矩陣中,對角線上的數字就代表分類正確的筆數,例如10表示實際標籤為Setosa,模型預測也是Setosa的筆數。
- 以這結果來說,模型的表現很好,全部預測正確。
🧠7. 模型優化(Optional)
在訓練模型時,通常會訓練很多個模型來做比較,不同的超參數(Hyperparameters)會導致模型表現有明顯差異。
GridSearchCV 是一種系統化搜尋的方式,會:
- 把你指定的一組參數組合全部試過一次(Grid Search)
- 用交叉驗證(Cross Validation)方式評估每組組合的表現
- 幫你找出最佳參數組合
在這個範例中由於鳶尾花資料集太過簡單,因此可以不做模型優化的動作,以下提供一個簡單範例供大家參考:
Random Forest 的常見參數

from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split, GridSearchCV
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import classification_report
# 載入資料
iris = load_iris()
X = iris.data
y = iris.target
# 切分訓練與測試資料
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 建立模型
rf = RandomForestClassifier(random_state=42)
# 定義參數網格(Grid)
param_grid = {
'n_estimators': [10, 50, 100],
'max_depth': [2, 4, 6],
'criterion': ['gini', 'entropy']
}
# 設定 GridSearchCV
grid_search = GridSearchCV(
estimator=rf,
param_grid=param_grid,
cv=5, # 5-fold 交叉驗證
scoring='accuracy', # 使用準確率作為評估指標
n_jobs=-1 # 使用所有 CPU 平行處理
)
# 執行參數搜尋
grid_search.fit(X_train, y_train)
# 最佳參數
print("最佳參數:", grid_search.best_params_)
print("最佳交叉驗證準確率:", grid_search.best_score_)
# 測試集評估
y_pred = grid_search.predict(X_test)
print("\n測試集表現:")
print(classification_report(y_test, y_pred, target_names=iris.target_names))
執行流程說明:
- 建立模型 (RandomForestClassifier)
- 設定參數網格(不同 n_estimators, max_depth 組合)
- 使用 GridSearchCV 自動遍歷每組參數
- 使用交叉驗證評估準確率
- 最後選出最佳參數組合
- 使用最佳模型做預測與測試
GridSearchCV 的好處
- 自動化參數優化,避免手動試錯
- 使用交叉驗證更穩定評估模型
- 可與任何 sklearn 支援的模型搭配(SVM, XGBoost, LogisticRegression 等)
💾 8. 模型儲存
使用 joblib 將模型序列化儲存成pkl格式,使用時載入即可!
import joblib
# 儲存模型
joblib.dump(model, 'iris_model.pkl')
# 預測新資料
# 讀取模型
model = joblib.load('iris_model.pkl')
new_predict = model.predict(new_x)
🌐 9. 模型部署與推論
經過了一系列漫長的資料前處理和模型訓練等步驟之後,最後一步就是將訓練好的模型部署到某個地方(本機或是遠端server)提供給前端介面的人串接使用,這樣就完成資料科學家在專案中的任務了! 這裡只簡單的說明什麼是部署,不提供範例練習。
建立API (Application Programming Interface)
API簡單的說就是工程師提供給工程師的某種軟體功能,寫網頁的部門想在他們的網頁中加入AI功能但是他們不會做,於是我們就可以將AI功能做好並且以API的形式提供給他們使用。
將資料前處理、特徵工程、模型載入和模型預測等功能寫成一支可以部署的API,讓想調用的人只需要呼叫API並輸入新資料就可以得到模型的預測結果。
比如:你去餐廳點餐
- 你是使用者
- 菜單是 API(你能點的東西)
- 廚房是伺服器(真正在處理資料)
- 服務生也是 API:你告訴他你想吃什麼,他幫你送到廚房,再把食物拿回來
💡你不用知道廚房怎麼煮,只要知道怎麼「透過服務生(API)」來點菜就好。
測試API
建好API之後還需要經過測試,確保串接你API的人可以得到正確的資訊,通常會透過"curl"指令或是"Postman"軟體來做測試。 如果你的資料處理、特徵工程和模型參數等操作沒有跟訓練時的處理一致,造成訓練資料跟要預測的新資料長得不一樣,那麼這裡很常會測試失敗!因為你的模型只認得訓練資料這種長相的資料。 自己做完測試之後,必須撰寫一份API串接文件提供給串接的人員,仔細說明你API的使用方法以及資料格式。現在較流行是方法是使用FastAPI(建立API)+Swagger(說明文件),之後有機會的話會再詳細說明這部分的用法。