NEWSIO+ 教育系列01 自己訓練一個 AI02 從照片還原 3D03 深度學習
主線 B · 模組 B1動手做 // 三個實驗台

開訓前的坑

資料還沒進模型,哪些動作已經讓結果不可信?

主線 A 講的是模型怎麼學。主線 B 講怎麼讓訓練真的成功。第一個坑在按下「開始訓練」之前就埋好了:資料怎麼切、前處理用了誰的統計量、權重一開始設成什麼。這些步驟程式都跑得動,分數還可能很漂亮,但漂亮的分數不等於模型學會了。這個模組帶你親手做出一個假高分,再把它拆穿。

SEC.01 / FIVE STEPS

五步建模:先看整條路,再找坑在哪

講義把建一個深度學習模型拆成五步:準備資料、決定網路結構、選 loss、選 optimizer、開始訓練(fit)。每一步都是一個決定,每個決定都可能出錯。下面用講義裡的 MNIST 手寫數字辨識走一遍,同一件事有 Keras 和 PyTorch 兩種寫法。點任何一步,看那一步的程式碼和它在決定什麼。

PROBE A / MNIST 的五步動手做 // 點一步,切換框架
→ → → →

把資料切好、變成數字。


        
現在看的是STEP 1 資料
這一步決定什麼切分與前處理
這一步的關鍵數字0
這一步最常見的坑先標準化再切分
框架:
右邊的「關鍵數字」是用程式碼裡的設定當場算的:參數量是逐層把 輸入 × 輸出 + bias 加起來,更新次數是 ⌈60000 ÷ batch size⌉ × epochs,起始 loss 是 ln 10。Keras 版是講義引用的 28×28 → 512 → 10 兩層網路;PyTorch 版是講義的 SimpleCNN,講義寫它「參數量約 42 萬」「測試準確率約 99.0%」。注意第一步的醒目位置:講義在第二次列五步時,把第 0 步改成了「資料先分割再前處理」。順序本身就是內容。
前四步都是設定,第五步才在學資料、結構、loss、optimizer 是你替模型做的決定。fit 只是照著這些決定去調權重。
三份資料,三種用途training 是小考(拿來調權重),validation 是模擬考(拿來挑模型和超參數),test 是大考(最後只考一次)。
結構先看任務長什麼樣影像有局部性,用 CNN;文字要看全域關係,用 Transformer;串流和長序列用 RNN 或 SSM。模型越通用,越需要更多資料。
細看 · 資料怎麼切、前處理、模型選擇、loss 怎麼選

三份資料:講義的比喻是 testing 是「大考」,用來檢驗模型的普遍性;training 是「小考」,訓練時調權重;validation 是每個 epoch 訓練完的「模擬考」,用來在不同模型、不同超參數之間挑一個。規則只有一條:不能作弊、偷看考題,validation 和 test 都不能用在訓練。validation 的核心用途是挑設定,不是「看看訓練得好不好」;一旦你依照 test 的結果回頭調整,test 就已經被洩漏進模型選擇了。

混有網路資料和自己的資料怎麼切:如果 train 和 test 都來自同一個分佈,照比例切就好。麻煩的是講義的自駕車例子:大量訓練資料來自網路各處,少量才是你真正的車拍的。規則是 validation(dev)和 test 要來自同一個分佈。validation 只從大的網路資料切,或只從小的自己的資料切,都可能和 test 對不上;講義建議兩邊各拿一部分。講義也舉了一個反例:虹膜辨識的研究裡,訓練和測試資料的來源不同,前處理就讓結果大不一樣。

前處理:神經網路的輸入要和權重相乘,所以必須是數字。名目資料用 one-hot encoding,順序資料轉成數值。輸入範圍差很多也會影響訓練:講義的例子是溫度 0 到 40 度、距離 0 到 10000 公尺,loss 的等高線會被拉成細長的橢圓,梯度下降走得很辛苦,所以建議 re-scale。兩個常見做法:

  • Mean subtraction:每一維減掉平均,讓資料以 0 為中心。X -= np.mean(X, axis=0)
  • Normalization:再除以標準差,讓每一維尺度差不多。X /= np.std(X, axis=0)。只在「各維尺度不同、但重要性差不多」時才有意義;影像的像素本來就都在 0 到 255,不一定需要這一步。MNIST 的 Keras 版直接除以 255,PyTorch 版用 Normalize(0.1307, 0.3081)。

影像增強:it depends。講義引用 MIT 6.S094 的自駕車例子:白天和黑夜、雨天和晴天的畫面差很多,所以需要 data augmentation 讓模型看過這些變化。但「調亮、去霧」這種影像增強不一定有幫助,要看任務。其他常見的影像前處理:統一尺寸和長寬比(通常保留中央)、必要時縮放、降維(要不要只用灰階)。開始前也要先清資料:刪掉重複或無關的樣本(例如只做獨棟房屋卻混進公寓)、修格式錯誤和錯字、檢查標錯的標籤;離群值要有正當理由才刪;缺值不要直接丟掉或硬補,因為「缺」本身就是資訊。

Model selection:先問 inductive bias 是否匹配。CNN 內建局部性、平移等變性、階層特徵,適合影像和語音;Transformer 做內容相關的全域互動,適合文字、語言,也能做影像;RNN 和 SSM 用固定或壓縮的狀態,適合串流和長序列。講義的提醒:模型越通用,通常需要越多資料和算力,才能學到同樣的偏好。

Loss function 怎麼選(講義:depending on your applications):

  • 分類:cross-entropy 是第一選擇,hinge loss 也可以。兩類用 binary cross-entropy:答案是 [0, 1]、預測是 [0.9, 0.1] 時,loss = −log(0.1) ≈ 2.303。多類用 categorical cross-entropy,Keras 要先把標籤轉成 one-hot,PyTorch 的 CrossEntropyLoss 直接吃整數標籤和 logits,不用自己加 softmax。
  • 回歸:L1(MAE)或 L2(MSE)是第一選擇。講義的例子:答案 [0.9, 0.1]、預測 [0.8, 0.2],MSE = 0.01、MAE = 0.1。MSE 對大誤差罰得重,MAE 對離群值比較穩;Huber loss 介於兩者之間,誤差小時像 MSE,誤差大時像 MAE。
  • 自訂 loss:資料不平衡用 focal loss;multi-task learning、物件偵測會把好幾個 loss 加起來;人臉辨識這類 metric learning 用 center loss、triplet loss。
SEC.02 / DATA LEAKAGE

Data leakage:模型偷看了考題

講義的定義:模型在訓練過程中,意外「看到」了本來不該在訓練階段出現的 test(或未來)資訊,於是評估結果虛高,模型其實沒學到泛化能力。它隱形又致命:程式能跑、分數漂亮、論文好寫,但結果無法重現、無法部署。下面這台模擬器真的在算:產生一段感測器資料,照你選的流程切分和前處理,用 kNN 分類,然後分別考 validation 和一批「真正的新資料」。

PROBE B / 洩漏模擬器動手做 // 打開開關,看分數怎麼騙你
類別 0類別 1實心小點 train空心圈 validation方框 混進 train 的重複樣本半透明大點 新資料
這一次:validation 準確率0%
這一次:真正新資料的準確率0%
落差(validation − 新資料)0
同一個流程,重抽 20 組資料的平均0
這次的切分0
0
怎麼產生的:440 個時間點的兩個感測器讀值,答案(類別)一段一段地換,讀值上疊了一個慢慢飄的偏移和雜訊,所以相鄰時間的點長得很像。前 240 點是你手上的資料(70% train、30% validation),後 200 點是部署後才來的新資料。分類器是 k = 5 的 kNN,每個點看最近的 5 個 train 點投票。先試:(1)只打開「時間序列被打亂」:validation 的鄰居就在 train 裡,相鄰時間的點幾乎一樣,分數跳上去,新資料不動。(2)只打開「重複樣本」:考題的答案直接在 train 裡。(3)前處理選第二項:差距很小,因為標準化只偷看了 x 的分佈、沒偷看答案;選第三項並打開打亂,擴增出來的點夾在 validation 的點和它的鄰居之間,差距就大了。資料、比例、k 都是為了示意而設的,數字不是講義裡的數據;「20 組平均」讓你分得出這是系統性的偏差,不是運氣。
高分 ≠ 好模型有洩漏時,accuracy、AUC、F1 都會異常好看。真正的考驗是從沒看過的資料,validation 只是它的替身。
洩漏的本質是邊界畫錯同一張圖、同一個病人、同一段時間被拆到 train 和 validation 兩邊,模型背的是「哪一個」,不是「是什麼」。
一句話原則任何和 test 或 validation 有關的資訊,都不能進入訓練過程。包括它的統計量、它的近親、它的未來。
細看 · 五種常見錯誤、實戰 checklist、為什麼研究生特別容易犯

常見錯誤 1:先做特徵工程或標準化,再切分。錯的寫法是 X = StandardScaler().fit_transform(X) 之後才 train_test_split:test 的統計量已經進了 scaler。對的寫法是先切,scaler.fit(X_train),再用同一個 scaler 去 transform train 和 test。原則:任何統計量只從 train 計算。講義的表把它延伸到資料不平衡:在 train + test 上一起做 SMOTE 或 oversampling,test 也被「改造」了;資料平衡只能在 train 上做。

常見錯誤 2:用未來的資訊做特徵。感測器和時間序列最常見:預測元件剩餘壽命(RUL),卻用到了未來時間點的振動或溫度;把整段量測的移動平均、頻譜特徵一次算完再隨機切分。講義的例子:用 2023 到 2024 年的資料訓練、2022 年的資料測試,模型等於看見了未來。對的做法是嚴格照時間切:train 用 2020 到 2022、valid 用 2023、test 用 2024,特徵只用「當下已知」的過去資料。

常見錯誤 3:目標洩漏。y 的資訊混進了特徵。例子:預測「病人是否出院」卻把「出院日期」當特徵;用最終測試良率或實際量測功耗,去預測設計階段是否過規格;影像缺陷檢測把標註或後處理結果直接當特徵。只能用「預測那個時間點已經知道」的資訊。

常見錯誤 4:交叉驗證切錯。在 K-Fold 之前就對整份資料做特徵選擇、SMOTE、缺失值填補。每個 fold 都要在自己內部獨立做這些步驟,sklearn 的 Pipeline 加 cross_val_score 是正確寫法的關鍵。

常見錯誤 5:重複或近重複樣本。同一片 PCB、同一顆晶圓的多張缺陷影像同時出現在 train 和 test,或是原圖和 resize 過的版本各在一邊,模型等於在背答案。切分前先去重、檢查近重複(影像資料集和 SPICE 模擬結果特別要查),augmentation 只在 train 做。同一類的還有群體洩漏:同一位病人的 MRI 切片一部分進 train、一部分進 test,模型學到的其實是「病人 ID」;切分要以病人、公司、用戶為單位。講義另一張表的總結:duplicate 灌高 benchmark,group 讓模型記住 identity,preprocess 偷看了 test 分佈,selection(拿 test 調模型或 prompt)讓 test 不再是 test。

實戰 checklist(講義第 34 頁):

  • 切分前,是否已經做了任何依賴整體統計量的操作?
  • 感測器、時間序列是否嚴格按時間切(而不是隨機)?
  • 特徵裡是否有任何「知道 y 之後才會有」的資訊?
  • 交叉驗證時,前處理是否放在每個 fold 內部?
  • train 和 test 之間有沒有重複或近重複的樣本?
  • 最終的 test set 是否只在最後一次評估時用過?

正確切分的五個原則:先切分再前處理(標準化、PCA、特徵選擇、缺值填補、SMOTE 都在 train 上 fit);嚴格時間順序(永遠是過去 → 未來);分層抽樣保留類別比例(stratify,同樣先切再處理);最終 test 只碰一次;用 Pipeline 把所有前處理包起來,確保每個 fold 都乾淨。

為什麼研究生特別容易犯:講義列了四個原因。表面看起來很合理,程式能跑、分數還很高,所以不會立刻察覺;評分指標會騙你,有洩漏時指標異常好看;工具的預設操作(先特徵工程再切、用整份資料做 normalization)很容易無意間造成洩漏;時間壓力和經驗不足,急著改模型架構,卻忽略最基本的資料管線。講義說很多論文被拒的主因就在這裡。

SEC.03 / WEIGHT INITIALIZATION

權重初始化:第一步站在哪裡

訓練要從一組權重開始。全部設成 0 最省事,但講義的第一個問題就是:W = 0 會怎樣?答案是每個神經元得到同樣的輸出、同樣的梯度、同樣的更新,完全學不到東西。隨機設也不夠,隨機的「大小」決定訊號穿過很多層之後還剩多少。下面是一個真的在算的 8 層全連接網路,每層 256 個神經元,丟進 128 筆隨機輸入,畫出每一層 activation 的分佈。

PROBE C / 8 層網路的 activation 直方圖動手做 // 換初始化、換 activation
每層 activation 的標準差
第 8 層:同一筆輸入,256 個神經元有幾種不同的值0
反向傳回第 1 層的梯度 ÷ 第 8 層的梯度0
0
n 是每層的輸入數(這裡是 256)。每一格是一層:tanh 的橫軸是 −1 到 1;ReLU 的橫軸是 0 到 3,剛好等於 0 的值不畫進柱子,比例寫在下面,超出 3 的值堆在最右邊那根橘色柱子。對照講義的 CS231n 圖:tanh 配太小的權重,標準差每層縮小,到後面全擠在 0;配太大的權重,幾乎全部卡在 −1 和 1(飽和),大部分神經元的斜率接近 0,梯度很不穩定;Xavier 只讓分佈慢慢變窄,八層後還攤得開。再切到 ReLU:Xavier 讓方差每層大約少一半,越來越窄;He 多乘了 √2,把被砍的那一半補回來。最右邊的梯度比例是真的做一次反向傳播量到的。網路大小和輸入筆數是為了在瀏覽器裡算得動而設的示意值。
全零 = 一個神經元抄 256 份每個神經元一模一樣,梯度也一樣,更新後還是一樣。對稱沒被打破,寬度就白費了。
每過一層,訊號乘上一個倍數倍數小於 1,八層後縮到快沒有;大於 1,爆掉或飽和。初始化的工作是讓這個倍數接近 1。
activation 決定該乘多少tanh 在 0 附近接近線性,用 Xavier;ReLU 砍掉一半,用 He,多補一個 √2。
細看 · 為什麼是 1/n、Xavier 與 He、其他初始化方法

全零的陷阱:所有權重相同時,同一層的每個神經元算出一樣的輸出,backprop 給它們一樣的梯度,更新完還是一樣。講義的原句:same output, same gradient, same update, no learning at all。只要權重是常數(不一定是 0),對稱就打不破,所以一定要隨機。

為什麼要除以 √n:一個神經元的輸出是 Y = W₁X₁ + … + WₙXₙ。如果權重和輸入彼此獨立、平均為 0,

Var(Y) = n · Var(W) · Var(X) 想要 Var(Y) = Var(X),就要 Var(W) = 1/n

講義的說法是:保持輸入和輸出的方差一致,避免所有輸出值都趨向 0。這就是 Xavier(Glorot)初始化:權重 = N(0,1) / √n。這個推導假設 activation 在 0 附近是線性的,tanh 符合(講義特別標註「tanh 的線性區」)。

He 初始化:ReLU 把負的一半全部變成 0,講義的註解是「half of the neuron is killed in ReLU」,方差每層少一半。補償的方法是讓 Var(W) = 2/n,也就是多乘 √2。講義的結論:ReLU(例如 CNN)用 He;tanh、線性這類接近對稱的 activation,以及 Transformer,常用 Xavier。

其他方法:用 autoencoder 做 pre-training 來初始化,現在已經不用了;現在最常見的是拿一個訓練好的模型(pre-trained model)當起點,再 fine-tune。講義的 TLDR:核心目標是讓訊號與梯度在層間保持合適的方差,避免消失或爆炸;好的初始化能縮短 warmup、減少不必要的正規化負擔,讓深網路更可訓練。為什麼「初始化」本身是一個研究問題?因為它和 activation、normalization(B4 的 Batch Norm)、residual connection 綁在一起,換了其中一個,最好的初始化就跟著變。

SEC.04 / MISCONCEPTIONS

常見誤解

這個模組最常被講錯的幾句話。

Validation 準確率很高,就代表模型泛化得很好。講義的標題:很多「泛化很好」其實是資料邊界錯了。重複樣本、同一個病人或同一段時間被拆到兩邊,validation 都會虛高。要問的是 validation 和真正的新資料是不是同一種「沒看過」。
標準化只是前處理,和切分的順序無關。先標準化再切,scaler 已經看過 validation。單純的標準化在 Probe B 裡差距很小,但「先處理再切」換成擴增、SMOTE、特徵選擇,洩漏可能大得多(Probe B 裡擴增配上打亂,落差比只打亂還大)。規則一律是先切,所有統計量只從 train 算。
初始化隨便設,反正訓練會把權重學好。全零時每個神經元一模一樣,完全學不到;太小,訊號幾層後縮成 0;太大,tanh 幾乎全部飽和,大部分神經元的斜率接近 0,學不動。起點錯了,訓練根本開始不了。
深度學習會自己學特徵,不用做前處理。輸入必須是數字(類別要 one-hot),尺度差很多時要 re-scale,資料要先清(重複、錯標、缺值)。講義的 MNIST 範例也有除以 255 或 Normalize。Better data > fancier algorithms。