[自然語言處理](https://app.notion.com/p/3e6fc631b03081b4a9e8f91f3411f61f) › [W4(10/1)](https://app.notion.com/p/3ecfc631b03081b8aa2cf4a97467ed41) › 07|PyTorch 教學(助教,2024 錄影)影片 [0:25:47–0:40:04](https://www.youtube.com/watch?v=sg22677pUEs&t=1547s)|投影片 pytorch_tutorial_NTHU_NLP p.24–32|上一章 [06 PyTorch:訓練主循環與 Tensor(0:00–0:25)](https://app.notion.com/p/3ecfc631b03081579f0eeb810083a514)|下一章 [08 PyTorch:自動微分與訓練迴圈(0:40–1:04)](https://app.notion.com/p/3ecfc631b030817fa3aceb0a27afd016) ## 重點 - PyTorch 的每個模型都是一個「模組」(torch.nn.Module):先寫「有哪些層」(初始化),再寫「資料進來怎麼一層層處理」(forward)。 - 很多層可以裝進 ModuleList(有編號的層清單)或 Sequential(自動依序傳下去的生產線);模組可以一層包一層,像一棵樹。 - 存參數、列參數、切換訓練/驗證模式,都是從最上層模組「遞迴」往下找每一個子模組,所以帶參數的層一定要用模組類別裝,不能用 Python 一般的 list。 ## Exam-ready - **torch.nn.Module**: "A Model in PyTorch is basically a torch.nn.Module object"(PyTorch p.24) - 中文:PyTorch 裡的模型,本質上就是一個 torch.nn.Module 物件。白話:你寫的模型都要「繼承」這個模組類別。basically(本質上)、object(物件)。 - **__init__ and forward**: "Two member functions that must be defined when constructing deep learning models"(PyTorch p.24) - 中文:建構深度學習模型時,一定要自己寫的兩個成員函式(就是初始化和 forward)。白話:一個寫「材料清單」,一個寫「做菜步驟」。member functions(成員函式)、constructing(建構)。 - **model.state_dict()**: "Return an OrderedDict contains parameter names and tensors"(PyTorch p.26) - 中文:回傳一個有順序的字典,裡面是「參數名稱 → 參數的 Tensor」。白話:模型的財產清冊。OrderedDict(有序字典)、tensors(張量,存數字的陣列)。 - **model.named_parameters()**: "Return an iterator for parameter names and tensors"(PyTorch p.26) - 中文:回傳一個迭代器,可以用 for 迴圈一組一組拿出「參數名稱+Tensor」。白話:邊看名牌邊看數值的點名表。iterator(迭代器,能一個個取出的東西)。 - **model.parameters()**: "Return an iterator for parameter tensors"(PyTorch p.26) - 中文:回傳一個迭代器,只給參數的 Tensor,不給名稱。白話:只要數值、不要名牌,常拿去交給優化器。parameter tensors(參數張量)。 - **Use Modules in Modules**: "We recommend using torch.nn.Module objects within a torch.nn.Module instead of basic Python data structures when parameters are involved."(PyTorch p.29)【助教強調】(0:39:54) - 中文:只要牽涉到參數,建議在模組裡面用模組物件來裝,而不要用 Python 的基本資料結構(例如 list)。白話:模組裡放模組。recommend(建議)、involved(牽涉到)。 - **Parameter registration**: "This ensures that the parameters are properly registered, tracked, and optimized during training."(PyTorch p.29) - 中文:這樣才能確保參數在訓練時被正確登記、追蹤和優化。白話:沒登記的參數,訓練時不會被更新。registered(登記)、tracked(追蹤)、optimized(優化)。 - **Recursive operations**: "In most of the functions in a Module object (train(), eval(), parameters() … ), the model recursively applies operations to all sub-modules. (just like a tree structure)"(PyTorch p.30) - 中文:模組大部分的函式(train、eval、parameters 等),都會遞迴地套用到所有子模組上,就像樹狀結構。白話:總部下命令,一路傳到每個分部。recursively(遞迴地)、sub-modules(子模組)。 - **Training mode**: "The training mode in PyTorch activates certain layers and behaviors that are only needed during training such as Dropout and Batch Normalization."(PyTorch p.32) - 中文:訓練模式會開啟某些只有訓練時才需要的層和行為,例如 Dropout 和 Batch Normalization。白話:練習賽專用的規則只在練習時打開。activates(啟動)、behaviors(行為)。 - **Evaluation mode**: "The evaluation mode is used for evaluation and inference, where layers like Dropout are disabled and Batch Normalization uses fixed statistics instead of updating them."(PyTorch p.32) - 中文:驗證模式用在評估和推論,這時 Dropout 被關掉,Batch Normalization 改用固定的統計值,不再更新。白話:正式比賽全員上場、規則固定。inference(推論,拿模型來預測)、disabled(關閉)、fixed statistics(固定的統計值)。 ## [0:25:47](https://www.youtube.com/watch?v=sg22677pUEs&t=1547s) 模型的骨架:nn.Module 上一章講的 Tensor(存數字的多維陣列),在模型裡的角色就是「參數」。把這些參數包起來的大結構,叫 torch.nn.Module(模組)。自己寫模型時,要繼承這個模組,並寫兩件事:初始化(宣告模型裡有哪些層)和 forward(資料進來要怎麼處理,最後產出 logits,也就是還沒轉成機率的原始分數)。 先補幾個程式名詞(我補充):類別(class)像一張設計圖,物件(object)是照設計圖做出來的成品;「繼承」是拿 PyTorch 現成的設計圖來改,不用從零寫;成員函式是這個物件自己會做的動作。Tensor(上一章學過:PyTorch 存數字的多維陣列,像可以疊很多層的表格)。logits 還要再經過 softmax 這類函數,才會變成加起來等於 1 的機率。 常見疑問:程式裡明明沒有直接呼叫 forward,它怎麼會跑?因為寫 model(input) 時,PyTorch 會先呼叫模組內建的 __call__,再由 __call__ 去呼叫你寫的 forward。下面這張投影片的紅色箭頭就是在畫這件事。 [[IMG: C:\D槽\TAICA課程\_work\notes-v2\nlp-w4\img\brief_pytorch_tutorial_NTHU_NLP_p024.png | 左邊是自己定義的模型(__init__ 宣告層、forward 寫處理步驟);右邊 model(input) 會經過 __call__ 自動呼叫 forward,得到 logits]] 看圖重點:左下角那句說這兩個函式是「一定要寫的」;右邊兩行就是平常使用模型的方式。 圖上重點: - Construct a Model(建構模型);A Model in PyTorch is basically a torch.nn.Module object(PyTorch 的模型本質上就是一個 nn.Module 物件)。 - The model is defined as(模型這樣定義):中間的程式是一個繼承 nn.Module 的類別,裡面只寫初始化和 forward 兩個函式。 - Two member functions that must be defined when constructing deep learning models(建深度學習模型時一定要寫的兩個成員函式),紅色箭頭指向初始化和 forward。 - Obtain the output logits(取得輸出的 logits):先建出模型物件 model = myModel(),再把資料丟進去 model(input)。 - 右下角是模組內建的 call 函式:model(input) 會先進到它,它再轉去呼叫 forward(往左的紅色箭頭)。 這張圖在講:自己寫模型=填好兩個函式;用模型=把資料丟進去,PyTorch 自動幫你跑 forward。 考試可能怎麼問:What two member functions must you define when building a PyTorch model, and what does each do?
用生活例子講,nn.Module 在做什麼? 模組像一份食譜。初始化是「材料與鍋具清單」:要一個炒鍋(線性層)、一個烤箱(卷積層)。forward 是「做菜步驟」:食材(資料)先下炒鍋,再進烤箱,最後裝盤(logits)。你只要說「做這道菜」(model(input)),廚房(__call__)就會照著步驟幫你做完。
## [0:28:03](https://www.youtube.com/watch?v=sg22677pUEs&t=1683s) 常用的層 初始化時能放進模型的「零件」,PyTorch 都幫你寫好了。助教帶過一張清單:有負責計算的層,也有負責「裝其他層」的容器。NLP 最常碰到的是線性層、RNN/LSTM 和 embedding。 常見疑問:embedding 為什麼說是「矩陣乘法」?因為每個字有一個 ID,embedding 層裡存一張大表(矩陣),一列是一個字的向量。拿 ID 去取第幾列,等於拿一個「只有那格是 1」的向量去乘這張表(one-hot 乘矩陣),所以本質是查表(我補充)。 要先懂的名詞(我補充):向量是一排數字(例如 [0.2, -1.3, 0.7]),矩陣是一張數字表格;「乘一個矩陣」就是用這張表把一排數字換算成另一排數字,表格裡的數字就是模型要學的參數。embedding 存的就是詞向量([第 3 週](https://app.notion.com/p/3e6fc631b03081ff9776f36fab3e6e50)學過:把每個字變成一排數字,意思相近的字數字也相近,word2vec 就是學這張表的方法)。RNN/LSTM 是一個字一個字讀、邊讀邊更新「記憶」的模型,這門課後面會正式教,現在知道它專門處理有先後順序的資料就夠了。 | 層 | 在做什麼 | 生活比喻 | |---|---|---| | Linear | 乘一個矩陣(全連接,每個輸入都連到每個輸出) | 把所有意見加權打分數 | | Conv(1D/2D/3D) | 卷積層,圖像處理常用,早期 NLP 也會用 | 拿小放大鏡掃過整張圖 | | RNN/LSTM | 處理序列資料(一個字接一個字) | 邊讀邊記筆記 | | MaxPool | 一小塊裡只留最大值,圖像常用 | 每組只派最強的代表 | | Embedding | 把 ID 換成向量(查表) | 用學號查學生資料卡 | | BatchNorm | 減平均、除以標準差,避免數值發散 | 把各班成績換成標準分數 | | Sequential | 把多層上下串成一個大層 | 生產線 | | ModuleList/ModuleDict | 模組版的 Python list/dictionary | 有編號(或有名字)的置物櫃 | 考試可能怎麼問:What does an embedding layer do, and why can it be seen as a matrix multiplication? ## [0:30:14](https://www.youtube.com/watch?v=sg22677pUEs&t=1814s) 模型的成員函式 模型建好以後,自帶幾個常用功能。state_dict 回傳「參數名稱 → 參數值」的有序字典,常用來存檔。named_parameters 是一個迭代器(可以用 for 迴圈一個一個拿),每次給「名稱+Tensor」;parameters 只給 Tensor,不給名稱。train 和 eval 用來切換訓練模式和驗證模式。 常見疑問:為什麼要三種看參數的方法?因為用途不同。存檔需要名字,才能載回同一個位置(state_dict);除錯時想邊看名字邊看數值(named_parameters);交給優化器(決定參數怎麼更新的工具)時只需要參數本身(parameters)。 要先懂的名詞(我補充):字典(dictionary)是「名稱 → 內容」的對照表,像電話簿用名字查號碼;「有序」是指它記得東西放進去的先後順序。迭代器像自助餐的取餐夾,一次夾一樣,適合用 for 迴圈(重複做同一件事、每次處理一個)一個一個處理。 | 函式 | 給你什麼 | 常見用途(我補充) | |---|---|---| | state_dict() | 有序字典:名稱 → Tensor | 存檔、載入模型 | | named_parameters() | 迭代器:一次一組(名稱, Tensor) | 印出來檢查每層 | | parameters() | 迭代器:只有 Tensor | 交給優化器 | | train()/eval() | 切換模式 | 訓練前/驗證前呼叫 | 考試可能怎麼問:Compare state_dict(), named_parameters() and parameters().
用生活例子講,state_dict 是什麼? 像公司的財產清冊:左欄是品名(例如 linear1.weight),右欄是實物(那一層的權重矩陣)。搬家(存檔)時照清冊打包,到新家(載入)時照品名放回原位。
## [0:31:29](https://www.youtube.com/watch?v=sg22677pUEs&t=1889s) ModuleList 與 Sequential 兩種容器都是「把很多層裝在一起」,但用法不同。ModuleList 像一排有編號的置物櫃,用 [0]、[1]、[2] 取出某一層,怎麼用由你在 forward 裡自己決定;層很多時可以少寫很多重複的程式。Sequential 像生產線,資料丟進去會自動依序經過每一層,前一層的輸出就是下一層的輸入。 常見疑問:既然 ModuleList 也能一層層跑,為什麼還要 Sequential?因為 Sequential 自帶 forward,你不用自己寫迴圈;但它只能「直直串下去」。像投影片 p.27 那種「同一個輸入分別丟給三層」的分岔用法,就要用 ModuleList。 下面是投影片 p.28 的例子:線性層 → ReLU(激活函數,把負數變 0)→ 線性層,包成一個 Sequential。 (我補充)「128 維」就是一排 128 個數字;「Linear 128→2」是把 128 個數字壓成 2 個分數,例如「正面/負面」兩類各一個分數。激活函數(本週前半講神經網路基礎時提過)是夾在線性層中間的「非直線」轉換;如果沒有它,疊幾層線性層都等於一層,模型學不到複雜的規律。 ```mermaid flowchart LR A["輸入(128 維)"] --> B["Linear 128→128"] B --> C["ReLU"] C --> D["Linear 128→2"] D --> E["輸出 logits(2 維)"] ``` 看圖重點:每個箭頭都是「前一層的輸出直接當下一層的輸入」,這段傳遞 Sequential 會自動幫你做。 考試可能怎麼問:Compare ModuleList and Sequential. When would you use each? 下面進階摺疊在做什麼(白話):用兩個小數字實際跑一遍「線性層 → ReLU → 線性層」,讓你看到資料怎麼一層傳一層、最後變成一個輸出;再附上 Sequential 內部只有三行的迴圈。看懂結論就好:Sequential 就是自動把上一層的結果丟給下一層。
它到底怎麼運作?(進階,可跳過) 把維度縮小成 2 維,跑一次 Sequential: 1. 輸入 x = [1, -2]。第一個線性層假設算「[x1+x2, x1−x2]」→ [-1, 3]。 2. ReLU 把負數變 0 → [0, 3]。 3. 第二個線性層假設算「兩個數相加」→ 3,就是最後輸出。 Sequential 內部的 forward 只有三行(投影片 p.28): ```python def forward(self, input): for module in self: input = module(input) return input ``` 意思就是:for 迴圈依序拿出每一層,把上一輪的結果餵進去。
## [0:34:07](https://www.youtube.com/watch?v=sg22677pUEs&t=2047s) 為什麼不能用 Python 的 list ModuleList 看起來跟 Python 的 list 差不多,為什麼不能直接用 list?因為 state_dict 這類功能是「遞迴」往下找參數:它只看模型登記在 _modules(子模組名冊)裡的東西,再一個個呼叫子模組的 state_dict。用 Python list 裝的層不會被登記,名冊是空的,所以參數清單也是空的。 遞迴是什麼(我補充):把一件事「交給下一層,用同樣的方法再做一次」。像總經理要統計全公司人數,只問各部門經理,經理再問各組組長,一路問到最底層再把數字往上加。PyTorch 的模組一層包一層,用這種方式就能找到每一個參數;前提是每一層都在名冊上,沒登記的就問不到。 助教下的結論(0:37:30 說一次,0:39:54 又重複一次):只要成員變數裡有參數、是一個層的定義,就要用 torch.nn.Module 類別來裝。【助教強調】(0:39:54) 下面這張投影片把兩種寫法並排,印出 _modules 來比較: [[IMG: C:\D槽\TAICA課程\_work\notes-v2\nlp-w4\img\brief_pytorch_tutorial_NTHU_NLP_p031.png | 左邊用 ModuleList,_modules 裡看得到 3 個 Linear;右邊用 Python list,_modules 是空的 OrderedDict()]] 看圖重點:兩邊程式幾乎一樣,只差一個 torch.nn.ModuleList(...),結果右邊整個「消失」。 圖上重點: - Use Modules in Modules(模組裡放模組):這頁的標題就是這段的結論。 - ModuleList version(ModuleList 版):左邊用 torch.nn.ModuleList 裝三個 Linear(128, 128),也就是三個「128 個數字進、128 個數字出」的線性層。 - List version(List 版):右邊只用 Python 的中括號裝同樣三層。 - print(model._modules):把模型的子模組名冊印出來。左邊印出「3 x Linear(in_features=128, out_features=128, bias=True)」,意思是 3 個線性層、輸入 128、輸出 128、有偏差項;右邊印出空的 OrderedDict(),表示名冊上一個都沒有。 這張圖在講:同樣三層,只因為裝的容器不同,一邊被模型認得,一邊完全隱形。 常見疑問:空的又怎樣,forward 不是照樣能跑?能跑,但這些層「沒人管」。投影片 p.29 說登記才能讓參數被追蹤與優化;所以 parameters() 交給優化器時也拿不到它們,訓練時這三層永遠不會更新,存檔時也不會被存(我補充)。 考試可能怎麼問:Why should you use nn.ModuleList instead of a Python list to hold layers? 下面進階摺疊在做什麼(白話):實際算一下投影片那三層到底有多少參數(約 5 萬個;權重是線性層那張表格裡的數字,偏差是最後再加上的一排常數),再對照兩種寫法:ModuleList 版找得到全部,Python list 版一個都找不到。結論是用 list 會讓 5 萬個參數「隱形」,存檔和訓練都碰不到它們。
用生活例子講,為什麼 list 不行? 公司年終盤點只看「正式員工名冊」。用 ModuleList 裝的層是正式員工,有登記;用 Python list 裝的層像沒登記的臨時工,每天照樣上班(forward 能跑),但盤點(state_dict)、發薪調薪(優化器更新參數)、人事命令(train/eval)都輪不到他。
它到底怎麼運作?(進階,可跳過) 用投影片 p.31 的三個 Linear(128, 128) 算算看參數數量: 1. 一個 Linear(128, 128) 有權重 128 × 128 = 16,384 個,加偏差 128 個,共 16,512 個參數。 2. ModuleList 版:三層都登記了,state_dict 收到 3 × 16,512 = 49,536 個參數。 3. Python list 版:_modules 是空的,state_dict 收到 0 個參數。這 49,536 個數字存在,但模型「不知道」它們。 state_dict 的原始碼重點(p.30)只有一行:for name, module in self._modules.items(),對每個子模組再呼叫一次 state_dict,名稱前面加上 name 和一個點。所以只有在 _modules 名冊裡的才會被找到。
## [0:38:01](https://www.youtube.com/watch?v=sg22677pUEs&t=2281s) 訓練模式與驗證模式 有些層在訓練和驗證時行為不一樣。Dropout 在訓練時隨機丟掉一部分元素,防止過擬合(模型把訓練資料背起來、遇到新資料就失準);Batch Normalization 也是訓練時才更新統計值。所以訓練前要呼叫 model.train(),用驗證集驗證時要呼叫 model.eval()。投影片 p.32 也說:訓練模式下模型會透過反向傳播更新參數;驗證模式讓模型行為一致、輸出固定(deterministic),不改動內部狀態。 要先懂的名詞(我補充):驗證集是訓練時故意不給模型看的資料,用來檢查模型遇到新題目的實力,像模擬考。反向傳播是從「答錯多少」往回推、算出每個參數該往哪邊調的方法,下一章會細講。Batch Normalization 的「統計值」就是平均和標準差:訓練時每批資料都重算一次,驗證時改用訓練期間累積下來的固定數字。 注意:助教口頭說驗證模式下 Dropout 和 Batch Normalization「都不起作用」;投影片的說法比較精確:Dropout 是被關掉,Batch Normalization 則是改用固定的統計值,不再更新(它還是會做正規化)。考試照投影片答。 常見疑問:只在最上層呼叫一次 train(),裡面幾十層怎麼都切換了?因為 train/eval 也是遞迴的:它會往下找每一個子模組,逐一呼叫它們的 train/eval。這又再次說明為什麼要「模組裡放模組」。 ```mermaid flowchart TD A["model.train()"] --> B["子模組:Sequential"] A --> C["子模組:ModuleList"] B --> D["Linear"] B --> E["Dropout(開始隨機丟)"] C --> F["Linear"] C --> G["BatchNorm(開始更新統計值)"] A -.-> H["Python list 裡的層:收不到命令"] ``` 看圖重點:命令從最上層一路往下傳;虛線那一格就是上一段講的「沒登記的層」,它收不到切換命令。 考試可能怎麼問:Why must you call model.eval() before validation or inference? 下面進階摺疊在做什麼(白話):用一排 4 個數字示範 Dropout 在兩種模式下的差別:訓練模式會隨機把一半變成 0、剩下的放大兩倍;驗證模式原封不動。重點是:忘了切到驗證模式,同一題每次答案都不一樣。
用生活例子講,訓練模式和驗證模式差在哪? Dropout 像球隊練習時,教練每次隨機叫幾個人坐板凳,逼其他人學會補位,不會只靠一個明星球員。正式比賽(驗證)時全員上場,不再隨機換人。model.train() 和 model.eval() 就是總教練喊「練習開始」「比賽開始」,命令一路傳到每個球員。
它到底怎麼運作?(進階,可跳過) 假設某層輸出 [2, 4, 6, 8],Dropout 丟掉的比例是 0.5: 1. 訓練模式:隨機丟掉一半,例如第 2、4 格 → [2, 0, 6, 0]。PyTorch 會把留下的乘以 1/(1−0.5) = 2 → [4, 0, 12, 0],讓整體大小跟平常差不多(我補充)。 2. 驗證模式:不丟、不放大 → [2, 4, 6, 8],每次結果都一樣(投影片說的 deterministic,確定不變)。 如果忘了呼叫 eval(),驗證時還在隨機丟東西,同一筆資料每次預測都不一樣,分數也會偏低。
助教原話是什麼? - 「這個成員變量它裡面有參數,它是一個層的定義、模組的定義,那我們就要用 Module、Torch.nn.Module 這一個類別的東西」(0:37:38) - 「所以這也是印證了我們之前說的,要在模組裡面寫模組,不要在模組裡面寫 Python 基本型別。」(0:39:54)
## Self-check
Q1. Why should layers with parameters be stored in nn.ModuleList rather than a plain Python list?(中文:為什麼帶參數的層要用 nn.ModuleList 裝,而不是 Python 的 list?) **Answer**: Functions such as state_dict(), parameters(), train() and eval() work recursively: they walk through the sub-modules registered in the model's _modules and apply the same operation to each one. Layers inside a plain Python list are not registered as sub-modules, so their parameters are missing from state_dict() and parameters(). They will not be saved, will not be updated by the optimizer, and will not switch between training and evaluation mode. nn.ModuleList is itself an nn.Module, so its layers are properly registered and tracked. 中文:state_dict、parameters、train、eval 這些功能都是遞迴的,會沿著模型 _modules 名冊裡登記的子模組,一個個往下做同一件事。放在 Python list 裡的層沒有被登記成子模組,所以 state_dict 和 parameters 裡找不到它們的參數:存檔不會存、優化器不會更新、也不會跟著切換訓練/驗證模式。ModuleList 本身就是一個 nn.Module,裡面的層會被正確登記和追蹤。
Q2. Compare nn.ModuleList and nn.Sequential.(中文:比較 nn.ModuleList 和 nn.Sequential。) **Answer**: Both are containers that register a group of layers as sub-modules. nn.ModuleList works like a Python list: you access layers by index and decide yourself in forward() how to use them, so it supports flexible patterns such as feeding the same input to several layers. nn.Sequential has its own forward(): the input passes through the layers in order, and each layer's output becomes the next layer's input. It is simpler for a straight chain (e.g., Linear → ReLU → Linear) but cannot express branching by itself. 中文:兩者都是容器,會把一組層登記成子模組。ModuleList 像 Python 的 list,用編號取出某一層,怎麼用由你在 forward 裡自己決定,所以可以做比較彈性的用法,例如同一個輸入分別丟給好幾層。Sequential 自帶 forward:資料依序經過每一層,前一層的輸出就是下一層的輸入。直直串下去(例如 線性→ReLU→線性)時寫起來最省事,但本身沒辦法做分岔。
Q3. Why do we call model.train() before training and model.eval() before evaluation?(中文:為什麼訓練前要呼叫 model.train(),驗證前要呼叫 model.eval()?) **Answer**: Some layers behave differently during training and evaluation. In training mode, Dropout randomly drops elements to reduce overfitting, and Batch Normalization updates its statistics from each batch. In evaluation mode, Dropout is disabled and Batch Normalization uses fixed statistics, so the model gives consistent, deterministic outputs. Both calls apply recursively to all sub-modules, so one call on the top-level model switches every layer. 中文:有些層在訓練和驗證時行為不同。訓練模式下,Dropout 會隨機丟掉部分元素來降低過擬合,Batch Normalization 會用每一批資料更新統計值。驗證模式下,Dropout 關掉,Batch Normalization 改用固定的統計值,所以同一筆資料每次的輸出都一樣。這兩個函式都會遞迴套用到所有子模組,所以只要對最上層模型呼叫一次,每一層都會切換。
Q4. What are the two member functions you must define in a custom nn.Module, and how is forward() called?(中文:自訂 nn.Module 一定要寫哪兩個函式?forward 是怎麼被呼叫的?) **Answer**: __init__() declares the layers (sub-modules) the model contains, and forward() describes how input data is processed through those layers to produce the output logits. We do not call forward() directly; writing model(input) triggers nn.Module.__call__, which calls forward(). 中文:__init__ 宣告模型有哪些層(子模組);forward 描述資料進來後怎麼經過這些層、最後產出 logits。我們不會直接呼叫 forward,而是寫 model(input),這會觸發模組內建的 __call__,再由它去呼叫 forward。
讀完了嗎?下一章:[08 PyTorch:自動微分與訓練迴圈(0:40–1:04)](https://app.notion.com/p/3ecfc631b030817fa3aceb0a27afd016)|回到週頁:[W4(10/1)](https://app.notion.com/p/3ecfc631b03081b8aa2cf4a97467ed41)