計算圖
計算圖是「一個結果如何被計算出來」的地圖,畫成一個由運算構成的網路。每個節點要不是輸入或參數,就是一個運算(加、乘、矩陣乘、ReLU 等),箭頭顯示哪些值餵進哪些運算。由左到右讀這張圖,就知道如何算出輸出;這張圖就是讓框架記住它所走的每一步的記帳簿,而這正是稍後自動計算導數所需的東西。
嚴格說它是一個有向無環圖(DAG):有向是因為資料沿邊單向流動,無環是因為沒有迴圈(一個值不能依賴它自己)。葉節點是輸入與可學習參數;內部節點是局部導數已知的基本運算;根節點是輸出(訓練時即純量損失)。每個節點儲存足夠的資訊,既能算出它的前向值,也能在梯度回流入它時,算出要送給其輸入的梯度(它的向量-Jacobian 乘積)。整個神經網路,每一層、每個激活、以及損失,都是這樣一張圖。
框架以兩種風格建圖。靜態圖(TensorFlow 1.x,以及 torch.compile、JAX 的 jit、ONNX 匯出等追蹤或編譯所產生的圖)定義一次後反覆執行,這使整圖最佳化、融合與部署成為可能。動態圖(PyTorch 的 eager 模式,即邊跑邊定義)在每次前向傳播、隨 Python 程式碼執行時重新建構,因此能隨資料改變形狀並使用一般的控制流程,較易除錯,但有一些執行時開銷。現代系統藉由把動態程式碼追蹤成靜態圖以求速度,模糊了這條界線。
這張圖是自動微分的底層基質:反向傳播不過是反向走過這張圖一遍。它也使深度學習在系統層級的魔法成為可能:運算子融合、記憶體規劃、梯度檢查點(gradient checkpointing,以計算換取儲存較少中間節點,對訓練大型 ViT 與擴散模型至關重要),以及把同一張圖編譯到 GPU、TPU 或行動裝置的 NPU。當你在視覺模型中除錯形狀不符或記憶體不足錯誤時,你其實是在除錯這張圖。
為何重要:在動態圖框架中,圖每次迭代都重建,並在反向傳播後被釋放。持有對某個圖節點的參照(例如累加損失張量本身、而非其純量 .item() 值)會讓整張圖一直存活,是經典的記憶體洩漏/記憶體不足成因。