Appearance
Q&A 問答集 — micrograd
Q1:為什麼梯度要用 += 而不是 =?
一個節點可能被多個節點當作輸入。例如 c = a + b 且 d = a * e,那麼 a 的梯度來自 c 和 d 兩條路徑,必須累加。
Q2:為什麼 _prev 用 set?
避免重複。當同一個值被多次使用時(如 c = a + a),a 的 _prev 不應重複出現。
Q3:什麼是「葉節點」?
葉節點是沒有 _prev 的節點(如輸入資料或權重)。它們的 _backward 是 lambda: None,因為不需要再往後傳播。
Q4:為什麼 __pow__ 限制指數必須是 int/float?
簡化實作。如果支援 Value 作為指數,需要先計算 exp(log(a) * b),這需要實作 exp 和 log 運算及其反向傳播。
Q5:ReLU 的梯度為什麼用 out.data > 0 而非 self.data > 0?
當 self.data < 0 時 out.data = 0,兩者等價。但使用 out.data 更符合封裝原則:每個節點自己決定梯度計算方式。
Q6:為什麼訓練最後一層不用 ReLU?
因為輸出是 logit(類別分數),需要正負值來表達分類信心。ReLU 會把負數截斷為 0,丟失資訊。
Q7:337 個參數怎麼算出來的?
MLP(2, [16, 16, 1]):
- Layer 1:
2*16 + 16 = 48(權重 + 偏置) - Layer 2:
16*16 + 16 = 272 - Layer 3:
16*1 + 1 = 17 - 總計:
48 + 272 + 17 = 337
Q8:為什麼需要 zero_grad()?
每次 backward() 會累加梯度。如果不歸零,下一次的梯度會和上一次混在一起,導致更新錯誤。
Q9:micrograd 和 PyTorch 的核心差異?
micrograd 只在標量上操作,而 PyTorch 在張量上操作。這就是為什麼 micrograd 的神經元需要顯式地 sum() 加權和 — 因為它沒有矩陣乘法。
Q10:學完 micrograd 後下一步該看什麼?
→ Phase 2: microgpt(純 Python 實作 GPT)。