楊本顥筆記・知識・作品

首頁 / 作品 / titanic-ml-arena

個人延伸實作 · 模型訓練競技場 01 / TL;DR

機器學習實驗筆記

在 Titanic 課堂 CRUD 專案上加建模型比較、即時訓練進度與版本管理,練習把一次實驗變成可回看的操作流程。

Flask · Blueprintscikit-learnSSESQLitejoblib
GitHub 原始碼 ↗ 看架構流程 ↓操作影片位置 ↓
機器學習實驗筆記的主題示意插畫
專案主題示意圖 · 非實際操作畫面

原有課堂範例

老師提供 Titanic RESTful CRUD 底座。既有資料操作不是這次個人新增的成果。

我加建的功能

以獨立 Blueprint 加入三種演算法的訓練比較、SSE 進度、模型版本庫,以及單筆與 CSV 批次預測。

操作影片

跟著畫面走一遍

啟動訓練、比較模型、切換版本,再進行單筆或批次預測。

操作影片準備中

錄製完成後會放在這裡。

02 / WHY

模型跑完了,我還想知道怎麼選

在課堂資料操作的基礎上,我想把模型訓練變成可重複使用的流程:看得到進度、知道選模型的依據,也能留下每次實驗結果。

這個實驗主要服務自己的學習。比起追逐單次最高分,我更想理解資料切分、交叉驗證與測試集各自負責什麼,以及如何把它們放進網頁操作。

比較要公平
同樣的資料切分與評估方式,才能比較模型。
過程要可見
訓練中逐步顯示進度,不只等最後一個答案。
結果可回用
保存模型與分數,單筆和批次預測沿用前處理。
03 / ARCHITECTURE & CHOICES

架構與技術選型

從輸入到結果

由上往下沿藍色箭頭閱讀,右側是各階段的工作。小螢幕可在圖內左右滑動。

機器學習實驗筆記架構流程Titanic 資料與切分 → Pipeline 與參數搜尋 → 5 折交叉驗證 → 測試集評估與存檔 → 進度頁與預測頁01Titanic 資料與切分先保留 20% 測試資料02Pipeline 與參數搜尋前處理包進每次訓練流程035 折交叉驗證以訓練側 CV 分數選擇模型04測試集評估與存檔記錄分數、模型版本與前處理05進度頁與預測頁SSE 呈現過程,版本供後續預測
箭頭呈現資料與模型產物的主線。SSE 在搜尋期間就持續推送進度,不是等到最後才開始;保留測試集不參與選冠軍。

Blueprint 隔開新增功能

機器學習功能放在獨立模組,只把入口掛到原有 Flask 應用,保留課堂 CRUD 的邊界。

取捨:共同使用應用環境時,仍需管理設定與資源,但不用為新增功能重寫既有頁面。

Pipeline 包住前處理

補值、編碼與模型一起進入交叉驗證,讓每一折只從自己的訓練資料學習前處理參數。

取捨:特徵處理必須符合 Pipeline 介面;換模型時也要確認前處理需求是否相容。

SSE 傳送單向進度

訓練結果主要由伺服器往瀏覽器送,EventSource 就能接收事件,無須為這個流程加入雙向通訊。

取捨:重新整理與連線中斷都需要事件恢復設計;進度推送不等於訓練工作本身可持久化。

04 / DEEP DIVE

兩個實作差異與內容

A選冠軍與報分數,是兩件事

先保留測試集,再以訓練資料的交叉驗證挑模型。若看到測試分數後改選冠軍,測試集就不再是獨立的評估基準。

做法差異 · A直接挑測試集分數最高的模型。

本專案採用 · B用 CV 選模型,測試集用來報告選定模型的表現。

核心邏輯示意 · Python 風格偽程式碼,含說明註解;非原始碼節錄
# 示意:測試集先保留,不加入參數搜尋
train, holdout = split_dataset(test_size=0.20)
for candidate in sampled_pipelines:
    candidate.cv = cross_validate(candidate, train, folds=5)
# 冠軍依據是 CV,而不是 holdout 分數
winner = max(candidates, key=lambda model: model.cv)
winner.fit(train)
metrics = evaluate(winner, holdout)

每個候選包含前處理與模型。這個隔離能減少選擇偏誤;但同一測試集若被反覆拿來指導改版,也會慢慢失去獨立性。

B即時進度,也要能在重新整理後看懂

後端每完成一組參數就加入事件紀錄,前端透過 EventSource 接收。重新載入時重播既有事件,讓圖表與紀錄能恢復到目前狀態。

做法差異 · A頁面只在訓練結束後拿到最終分數。

本專案採用 · B過程逐筆更新;重新開頁面可重建目前進度。

核心邏輯示意 · Python 風格偽程式碼,含說明註解;非原始碼節錄
# 示意:先重播,再接續推送新事件
cursor = 0
while training_active() or cursor < len(events):
    if cursor < len(events):
        yield as_sse(events[cursor])
        cursor += 1
    else:
        wait_for_next_event()  # 此處省略心跳與中斷處理

這段只表達事件重播的核心概念,不是可直接部署的串流程式。真正的工作生命週期、錯誤及連線管理,需要另外處理。

05 / TROUBLESHOOTING

遇到的問題

測試準確率最高,卻不是冠軍

發現:一次實驗中邏輯迴歸的測試準確率較高,與頁面選出的梯度提升不同。

排查與處理:回頭檢查選擇依據:冠軍依 CV 分數決定,保留測試集只做評估。把這個差別寫清楚,避免誤認為排名程式壞掉。

模型版本有了,檔案卻可能沒到遠端

發現:Git LFS 指標檔與真正的模型二進位內容不是同一件事。

排查與處理:曾補做模型檔重建及 LFS 上傳。可重現交付還需要確認下載後能載入模型,不能只檢查檔名存在。

06 / IMPACT & TAKEAWAYS

成果

以下為 2026 年 9 月整理的歷史開發紀錄;數據依各自的樣本與量測情境解讀,並非即時統計。

82.45% / 83.80%

CV 與保留集準確率

歷史版本 #7:前者是模型選擇用的 CV 準確率,後者是保留測試集結果。資料共 891 筆;兩者資料與用途不同,不是前後改善幅度。

AUC 0.8441

排序辨識能力

衡量模型將正例排在負例之前的能力,與固定門檻下的準確率不同。不能把它寫成 84.41% 預測正確率。

F1 0.7786

精確率與召回率的平衡

同一歷史版本的正類 F1;它不等於整體 accuracy,也不能直接代表真實世界的預測效益。

回顧

我開始把模型分數視為有前提的結果:切分方法、選擇規則與模型版本都要一起保存。若重新做,會先把實驗記錄和工作狀態設計完整,再增加更多演算法。

07 / ROADMAP

未來展望

以下是依目前限制整理的後續方向,尚未完成,也尚未排定時程。

待規劃 · 01

把實驗條件保存完整

除了模型分數,記錄資料版本、隨機種子、特徵處理與套件版本,讓不同實驗之間能真正對照。

怎麼確認有改善:用同一份資料與設定重新執行,檢查分數差異是否來自隨機性或環境變更。

待規劃 · 02

呈現模型在哪些樣本容易錯

加入混淆矩陣、不同預測門檻與錯誤樣本分析,讓數字能連回具體案例。

怎麼確認有改善:區分錯誤類型及樣本數,避免只用一個總分判斷模型好壞。

待規劃 · 03

讓訓練工作更容易恢復

將工作狀態與事件紀錄持久化,區分瀏覽器重連、伺服器重啟及訓練失敗。

怎麼確認有改善:重開頁面能恢復進度;工作失敗有清楚原因,已完成模型仍能載入並預測。