計算圖有向無環圖 (DAG) 拓撲排序實現
Agent 輔助工程檢查
前置要求
第 31 天計算圖概念與深度優先搜尋 (DFS) 演算法基礎。
學習目標
理解反向傳播為何必須依賴後序遍歷拓撲排序,確保每一個節點的所有下游消費節點的梯度全部傳回後,才執行該節點的反向傳播。
操作指引
使用 CLI 檢視多路徑共享節點圖的結構:
python3 projects/autograd/cli.py graph --preset shared-node --format ascii
觀察節點 a 同時作為加法項 $(a+b)$ 和乘法項 $(a+b) \cdot a$ 的輸入。任意亂序或簡單廣度優先搜尋都會導致 a._backward() 在未接收完全部下游梯度前提前觸發。
自主實作與記錄
對於表達式 $f = (a + b) \cdot a$,其中 $a = 3.0, b = 4.0$:
1. 追蹤從根節點 $f$ 出發的深度優先搜尋 (DFS) 遍歷過程。
2. 列出後序遍歷存取節點的序列。
3. 驗證將其反轉後的逆拓撲序:保證根節點 $f$ 在最前,加法節點在中間,輸入葉節點 $a, b$ 在最後。
後序 DFS 的核心邏輯:遞迴存取當前節點 _prev 中的所有子節點;僅當所有子節點都完全處理完畢後,才將當前節點追加到清單中。將最終清單反轉,即可保證每個節點排在依賴它的所有後代節點之後。
參考解答:
1. 根節點 $f$ 的依賴集合為 $\{sum, a\}$。
2. 中間節點 $sum$ 的依賴集合為 $\{a, b\}$。
3. DFS 遍歷存取 $a$、$b$,處理完畢後將 $sum$ 加入清單,最後加入 $f$。
4. 反轉後的反向執行序列:$[f, sum, b, a]$。
當呼叫 backward() 時,依序執行 $f._backward()$、$sum._backward()$,最終節點 $a$ 完整累加了來自兩個方向的全部梯度。
學習者能夠不依賴第三方圖論庫,獨立手寫 DFS 後序拓撲排序演算法建構正確的計算節點執行鏈。
權威來源資源與權利證明
micrograd: A tiny scalar-valued autograd engine
對應章節 / 時間戳: micrograd/engine.py: class Value (_backward closures and backward() topological sort); README 'Example usage'
驗證版本與日期: commit a9a9f94 (Verified: 2026-10-30)
Clear reference implementation of recursive DFS topological sort for reverse-mode ordering.
Graph traversal fundamentals (DFS/BFS)
Local implementation in projects/autograd/engine.py.
對比候選資源與選型分析 (2)
Production scale, but too large and complex for tracing by hand in introductory lessons.
Vectorized autograd; micrograd's pure scalar model is pedagogical for hand backprop.