# 章節包:自然語言處理(NLP)W4(10/1)第 09 章「PyTorch:NLP 資料流與 BERT」 PyTorch 教學(助教,2024 錄影)影片 1:04:53–1:26:11,YouTube ID sg22677pUEs,逐字稿 C:\D槽\TAICA課程\自然語言處理\第四周1151001\W4_PyTorch教學_助教.逐字稿.txt。Notion 章節頁 https://app.notion.com/p/3ecfc631b0308169a03bfc1e2049b467(頁 ID 3ecfc631b0308169a03bfc1e2049b467),頁面標題「09 PyTorch:NLP 資料流與 BERT(1:04–1:26)」。 ## 1. 第一行(直接照抄,不要改) [自然語言處理](https://app.notion.com/p/3e6fc631b03081b4a9e8f91f3411f61f) › [W4(10/1)](https://app.notion.com/p/3ecfc631b03081b8aa2cf4a97467ed41) › 09|PyTorch 教學(助教,2024 錄影)影片 [1:04:53–1:26:11](https://www.youtube.com/watch?v=sg22677pUEs&t=3893s)|投影片 pytorch_tutorial_NTHU_NLP p.51–62|上一章 [08 PyTorch:自動微分與訓練迴圈(0:40–1:04)](https://app.notion.com/p/3ecfc631b030817fa3aceb0a27afd016)|下一章 無 ## 1b. 最後一行(直接照抄,放在 Self-check 後面,當全頁最後一行) 這週讀完了。回到週頁:[W4(10/1)](https://app.notion.com/p/3ecfc631b03081b8aa2cf4a97467ed41) ## 2. 各段標題(照順序;每段一個 ## 標題,直接照抄連結) - `## [1:04:53](https://www.youtube.com/watch?v=sg22677pUEs&t=3893s) 為什麼 NLP 要分批訓練` 老師講什麼:前面的例子只有一兩個參數,NLP 模型可能有上百萬到上億參數、資料上千萬筆,不可能一次全丟進去算,只能每次取一批(batch)代表整體分布;batch 越大越能代表整個資料集,只取一筆容易偏。 - `## [1:07:41](https://www.youtube.com/watch?v=sg22677pUEs&t=4061s) Dataset 與 DataLoader` 老師講什麼:Dataset 負責存資料,要寫三件事:初始化時把資料存起來、用編號取出第幾筆、回報總共幾筆。DataLoader 拿 Dataset,設定一批幾筆、怎麼打包、要不要打亂,之後用迴圈一批一批取出。 - `## [1:09:29](https://www.youtube.com/watch?v=sg22677pUEs&t=4169s) 一批資料怎麼被打包` 老師講什麼:Dataset 逐筆取出資料(可在這裡做單筆前處理),湊成一批後交給 DataLoader 的打包函式(collate function),在整批的層次再處理,例如轉成 Tensor;迴圈取到的就是打包函式的回傳值。 - `## [1:11:01](https://www.youtube.com/watch?v=sg22677pUEs&t=4261s) 文字在 RNN 裡怎麼流動` 老師講什麼:句子 I love AI 的每個 token 先有自己的 ID(等同 one-hot 稀疏向量),經過 embedding 層變成例如 768 維的稠密向量,再逐字送進 RNN,隱藏狀態一路往後傳;RNN 輸出每個 token 的結果,外加最後一個隱藏狀態 hn,可交給後面的模組(例如解碼器)。 - `## [1:13:51](https://www.youtube.com/watch?v=sg22677pUEs&t=4431s) teacher forcing 與生成式訓練` 老師講什麼:生成式訓練讓模型自己一路生成再修正,第一個字錯了(I eat apple)後面就會拿錯的上文去學,變得很奇怪又不穩定;teacher forcing 每一步都餵正確答案的上文(I → love、I love → AI),所以更穩定,助教推薦用它。 - `## [1:16:58](https://www.youtube.com/watch?v=sg22677pUEs&t=4618s) Transformer、BERT 與預訓練` 老師講什麼:Transformer 比 RNN 能力更強、更能平行運算。BERT 是 Google 用大量沒標註的文字以克漏字、判斷下一句等任務預訓練好的模型,成本很高,所以一般從 Hugging Face 下載;先學會語言再微調到下游任務,可以大幅減少需要的標註資料。 - `## [1:19:27](https://www.youtube.com/watch?v=sg22677pUEs&t=4767s) tokenizer 與載入模型` 老師講什麼:tokenizer 一行就能把句子切成 token、換成 ID、把短句補零到一樣長(padding)、把超長的截掉(truncation),並直接打包成 PyTorch Tensor,預設在 CPU 上要自己搬到 GPU。用 AutoModel 載入權重後,就是一個一般的 nn.Module,照前面的方式使用。 - `## [1:22:25](https://www.youtube.com/watch?v=sg22677pUEs&t=4945s) BERT 的資料流與分類用法` 老師講什麼:BERT 不像 RNN 一個字一個字處理,而是所有 token 同時經過多層 attention 與前饋網路,輸出和輸入一一對應的向量。整句分類取開頭的 CLS 向量再接一層線性層;每個字的分類(例如 NER)則把每個 token 的向量各接線性層。最後預告之後的助教課會再講更多工具。 ## 3. 老師強調/會考/不考的地方(原句已驗證;寫進筆記時 ASR 錯字要改正) - (1:13:53) [強調] 「我在作業的講解當中有講過就是generative learning跟teacher forcing之間的區別那麼我們這邊會建議大家用teacher forcing」 → 訓練 RNN 建議用 teacher forcing;連結的是 2024 年的作業講解,今年作業是否適用以今年說明為準 - (1:25:05) [強調] 「在之後的作業當中我們會要求大家能夠是構建一個比方說從hugging face上面下載模型」 → 2024 年的作業會要求從 Hugging Face 下載模型、寫自己的模型做分類或生成;這是 2024 年的說法,不代表今年作業 ## 3b. 數學段候選(程式抓的,只是提示;寫「跳過提示」行用) 0 段候選(門檻 3.0 字/30 秒) ## 4. 這章摘要與重要度 (助教 PyTorch 教學影片,時間是那支影片的時間)NLP 的模型和資料都很大,只能一批一批餵;這章講資料怎麼被分批取出、文字怎麼變成向量流過 RNN,為什麼訓練 RNN 建議用 teacher forcing,最後示範用 Hugging Face 拿預訓練好的 BERT 來做句子或每個字的分類。(一般) ## 5. 整堂課的提醒(ASR 錯字、老師口誤、投影片缺公式等;只用跟這章有關的) - 這支只有約 1 小時 20 分(老師 1:18:56 下課),下半場改看助教預錄的 PyTorch 教學影片(約一個半小時),筆記在第 06–09 章,章名前面有「PyTorch:」,影片時間是那支影片自己的時間。 - PyTorch 教學是 2024 年錄的舊影片,片中提到的作業說法(例如建議用 teacher forcing、之後要用 Hugging Face)不代表今年,今年作業以今年公告為準。 - 課表寫的是「Text Classification, NB, NN」,但實際上還在講 W2_Word 投影片(p.17–47)的語言模型和詞向量;Naive Bayes 只在 0:55:59 拿來對比「統計」和「模型學習」。 - 開頭 0:00:27–0:02:24 有網路和回音問題,0:03:55–0:04:32 在調整直播畫面,內容沒有缺。 - 逐字稿有語音辨識重複行(0:27:41–0:29:20 幾乎每句重複兩次、0:39:37 一句重複四次),不影響理解。 - 全片沒有下課休息,一路講完(0:00:01–1:26:08)。 - 逐字稿 0:01:32–0:01:53 有語音辨識重複句與亂碼(同一句重複五次、CUDA 版本被辨識成 ientes/analytical sci-fi/evangelical sci-fi),內容只是「別直接 pip install,到官網選版本」。 - 0:35:46 老師說「這是新的嗎」,接著改用口述講 Google Bomb。p.31 的文字檔裡已經有「Google Bomb/Data Poisoning」,可能是 10/1 更新版才加的,直播畫面也許還是舊版。不確定。 - p.33–38 的 word2vec 細節,老師是用回顧的方式講的,沒有逐頁翻:p.34 共現矩陣、p.38 SGD 那頁沒有明確講到;0:47:21 的 A、B、C softmax 計算例子,對應的是 p.35 還是 p.36(只有圖),不確定。 - 老師好幾次把模型輸出的「機率」說成 perplexity(例如 0:45:48、0:48:31),應該是口誤,寫筆記時要寫成 probability,不要寫成困惑度。 - 老師 1:08:44 已經宣布下課,接著又講了約 5 分鐘 activation function(p.46–47),1:13:47 才真正收尾,所以第 05 章沒有在 1:08:44 切開。1:13:27 說的「這一段的敘述」應該是指 p.47 的 softmax、sigmoid、tanh、ReLU 表格,只用一句帶過。p.48(In text viewpoint)沒講,下週應該從 p.48 開始。 - 第 04 章長約 13.5 分鐘,比建議的 15 分鐘短一點;它講 contextual embedding,跟第 05 章的 NN 基礎主題不同,所以沒有合併。 - [PyTorch 影片,第 06–09 章] 投影片 p.7 寫模型是 y = ax²+b,助教口頭說成「y等於ax加b」(0:04:08);投影片寫「four data points」但只列三個點 (-1,1)、(1,2)、(2,3),助教口頭念的點也對不上(0:04:36 說 -1 對 1、-1 對 2、-2 對 3)。寫筆記以投影片的 y = ax²+b 和三個點為準。 - [PyTorch 影片,第 06–09 章] 逐字稿有大量語音辨識錯字,寫手要自己還原:T度=梯度、correct function=collate function、translation=truncation、badge size=batch size、relude/Renew=ReLU、MN backward=MmBackward、nodegrade=no_grad、width.backward=with torch.no_grad()、nonpy=NumPy、viewed=view、birth=BERT、復迴圈=for 迴圈、增刮號=中括號、高雄宇=高宏宇;0:23:00 的「3e」應是 stride (3, 1)、0:22:02 的「13」是 (1, 3)。 - [PyTorch 影片,第 06–09 章] 助教把 BERT 稱為「auto encoder」(1:21:5x 起),對應投影片 p.60–61 的「Transformer Auto-encoder」,指的是編碼器式 Transformer,不是一般說的自編碼器;寫筆記時要說清楚,避免混淆。 - [PyTorch 影片,第 06–09 章] 第 2 章只有約 14 分鐘,略低於 15 分鐘下限;因為「模組」是獨立概念,而第 3 章(自動微分+訓練迴圈)已約 25 分鐘,沒有再合併。若主 session 想更細,第 3 章可在 0:51:20 切成「自動微分」與「損失函數、優化器與線性迴歸」兩章(各約 11、13.5 分鐘)。 - [PyTorch 影片,第 06–09 章] 投影片檔放在 2026 資料夾,影片是 2024 年錄的;對照下來頁序與講解內容一致(p.62 是結尾的笑話頁,沒有內容),但不確定 2026 版投影片是否和 2024 錄影時的版本完全相同。 - [PyTorch 影片,第 06–09 章] emphasis 只放了助教明講作業相關或重複強調的地方;另外兩處助教有說「注意」或「建議」但跟作業無關,沒列進去:0:53:00「不要用訓練的資料來測試」、0:24:47「儘量用矩陣運算的方式來運算」(兩句都已過 quote_check)。 - [寫手注意,第 06–09 章] 這四章是助教的程式教學,但主理人不看程式碼、考試不考寫程式:預設看得到的內容寫「這個元件在做什麼、為什麼需要它」+生活比喻(例:optimizer 像導航決定下一步往哪走);程式碼最多一小段,放進「(進階,可跳過)」摺疊。Exam-ready 只放投影片上的英文概念句(例如 tensor、autograd、loss、optimizer 的說明),不放程式碼行;投影片沒有完整英文句時用短的英文定義並標 (my wording)。Self-check 問「為什麼/比較」,不問語法。助教不是老師,不標【老師強調】,要標就寫【助教強調】+時間。 ## 6. 投影片文字(這章範圍) **這幾頁的公式或內容只在圖裡(文字檔抓不到),寫 Exam-ready 與公式前先用 Read 看這幾張圖:** - pytorch_tutorial_NTHU_NLP p.51 → C:\D槽\TAICA課程\_work\notes-v2\nlp-w4\img\brief_pytorch_tutorial_NTHU_NLP_p051.png - pytorch_tutorial_NTHU_NLP p.52 → C:\D槽\TAICA課程\_work\notes-v2\nlp-w4\img\brief_pytorch_tutorial_NTHU_NLP_p052.png - pytorch_tutorial_NTHU_NLP p.53 → C:\D槽\TAICA課程\_work\notes-v2\nlp-w4\img\brief_pytorch_tutorial_NTHU_NLP_p053.png - pytorch_tutorial_NTHU_NLP p.56 → C:\D槽\TAICA課程\_work\notes-v2\nlp-w4\img\brief_pytorch_tutorial_NTHU_NLP_p056.png - pytorch_tutorial_NTHU_NLP p.57 → C:\D槽\TAICA課程\_work\notes-v2\nlp-w4\img\brief_pytorch_tutorial_NTHU_NLP_p057.png - pytorch_tutorial_NTHU_NLP p.59 → C:\D槽\TAICA課程\_work\notes-v2\nlp-w4\img\brief_pytorch_tutorial_NTHU_NLP_p059.png --- pytorch_tutorial_NTHU_NLP p.51 --- Deep learning in NLP tasks 51 I mentioned regression tasks on a polynomial function with a few data samples. However, in NLP tasks, the model size and dataset size can reach hundreds of gigabytes or even terabytes, making it impractical to plot a hyper-curve for loss progression over the entire dataset. As a result, we need to sample batches of data that can approximate the distribution of the original dataset. --- pytorch_tutorial_NTHU_NLP p.52 --- Dataset & DataLoader 52 The Dataset object should be defined as: From torch.utils.data import DataLoader, Dataset Class myDataset(Dataset): def __init__(self, split): Super().__init__() self.data = … def __getitem__(self, index): return self.data[index] def __len__(self): return len(self.data) The Dataloader: def get_batch(sample): ... dl = DataLoader(myDataset(split=…, ), batch_size=…, collate_fn=get_batch, shuffle=...) for batch in dl: ... --- pytorch_tutorial_NTHU_NLP p.53 --- Data Flow 53 Dataset.__getitem__ Text data Text data Text data Text data Text data Text data Text data Text data Text data Text data Text data Text data Preprocess each data DataLoader collate function Processing data batch Tensor Data type: str ( {"data": "...", "label": ...}, {"data": "...", "label": ...}, {"data": "...", "label": ...}, {"data": "...", "label": ...}, … ) {"data": "...", "label": ...} {"data": "...", "label": ...} {"data": "...", "label": ...} {"data": "...", "label": ...} ... DataLoader input a tuple into the collate function. --- pytorch_tutorial_NTHU_NLP p.54 --- Data Flow in RNN model 54 One-hot vectors [0, …, 1, …, 0, 0] [0, 0, …, 1, …, 0] [0, …, 1, …, 0, 0] [0, 0, …, 1, …, 0] I love AI ! Input tensor Shape = 1X6X20000 (batch_size X seq_len X vocabs) X Embedding layer A matrix Shape = 20000X768 (vocabs X hidden_dim) Dense vectors [0.2, …, -0.5, 0.7] [0.1, …, 0.2, -0.5] [-0.3, …, 0.7, 0.5] [0.6, …, -0.2, 0.9] Embeddings Shape = (1X6X768) We assume that batch_size = 1, hidden_dim=768 and there are 20000 words in the dictionary Hidden Layers I love AI ! --- pytorch_tutorial_NTHU_NLP p.55 --- Data Flow in RNN model 55 Dense vectors [0.2, …, -0.5, 0.7] [0.1, …, 0.2, -0.5] [-0.3, …, 0.7, 0.5] [0.6, …, -0.2, 0.9] Embeddings Shape = (1X4X768) I love AI ! U W U U U Dense vectors [0.3, …, 0.1, 0.8] [-0.5, …, 0.2, -0.7] [-0.3, …, 0.3, 0.9] [0.9, …, 0.2, 0.7] Output vectors Shape = (1X4X768) I love AI ! V V V V torch.nn.RNN(input, hidden_size=768) return value: (output, h_n) h0 h1 h2 h3 h4 W W W --- pytorch_tutorial_NTHU_NLP p.56 --- Generative learning VS Teacher forcing For example. Our ground truth is: I love AI ! In generative training: 56 h0 h1 h2 h3 h4 I eat apple . eat apple . argmax argmax argmax argmax We optimize: o P (love | I) o P (AI | I eat) o P (! |I eat apple) o P ( |I eat apple !) If the model makes a mistake early on, that error will be used in later training, which makes training unstable. --- pytorch_tutorial_NTHU_NLP p.57 --- Generative learning VS Teacher forcing Our ground truth is still: I love AI ! In teacher forcing: 57 h0 h1 h2 h3 h4 I love AI ! eat you ! argmax argmax argmax argmax We optimize: o P (love | I) o P (AI | I love) o P (! | I love AI) o P ( | I love AI !) Ground truths Nothing weird here. Teacher forcing is more stable in training --- pytorch_tutorial_NTHU_NLP p.58 --- Transformer-based models Transformer-based models are more powerful and parallelable than RNN-based models. Language models (LM) need pretraining to learn the underlying structure, patterns, and relationships in a language. Huggingface is an excellent platform for accessing and downloading pretrained model weights and datasets. 58 target Pretrain Too far away Fine-tuning --- pytorch_tutorial_NTHU_NLP p.59 --- Load BERT from Huggingface import transformers as T tokenizer = T.AutoTokenizer.from_pretrained("google-bert/bert-base-uncased", cache_dir="./cache/") data = tokenizer.batch_encode_plus(text, padding=True, truncation=True, return_tensors="pt") model = T.AutoModel.from_pretrained("google-bert/bert-base-uncased", cache_dir="./cache/") 59 Import transformers package Tokenizer is used to transform tokens to ids, and it can also pack the text batch into tensors: batch_encode_plus returns a "BatchEncoding" object which can be regarded as dict. (located on CPU ram) The BERT model can be loaded by: Model name A local path to store the model --- pytorch_tutorial_NTHU_NLP p.60 --- Data Flow in Transformer Auto-encoder 60 One-hot vectors [0, …, 1, …, 0, 0] [0, …, 1, …, 0, 0] [0, 0, …, 1, …, 0] [0, …, 1, …, 0, 0] [0, 0, …, 1, …, 0] [0, …, 1, …, 0, 0] [CLS] I love AI ! [SEP] Input tensor Shape = 1X6X20000 (batch_size X seq_len X vocabs) X Embedding layer A matrix Shape = 20000X768 (vocabs X hidden_dim) Dense vectors [0.8, …, 0.7, -0.4] [0.2, …, -0.5, 0.7] [0.1, …, 0.2, -0.5] [-0.3, …, 0.7, 0.5] [0.6, …, -0.2, 0.9] [0.9, …, -0.2, 0.4] Embeddings Shape = (1X6X768) We assume that batch_size = 1, hidden_dim=768 and there are 20000 words in the dictionary Hidden Layers [CLS] I love AI ! [SEP] --- pytorch_tutorial_NTHU_NLP p.61 --- Data Flow in Transformer Auto-encoder 61 We assume that batch_size = 1, hidden_dim=768 and there are 20000 words in the dictionary Dense vectors [0.3, …, 0.4, -0.6] [0.5, …, -0.4, 0.1] [0.2, …, 0.2, -0.4] [-0.4, …, 0.2, 0.5] [0.7, …, -0.1, 0.8] [0.1, …, -0.2, 0.4] Output logits Shape = (1X6X768) [CLS] I love AI ! [SEP] For sequence classification [0.3, …, 0.4, -0.6] [CLS] logits shape = 1X1X768 X FFN (assume there are 2 classes) Shape = 768X2 (hidden_dim X classes) [0.1, 0.6] [0.5, …, -0.4, 0.1] [0.2, …, 0.2, -0.4] [-0.4, …, 0.2, 0.5] [0.7, …, -0.1, 0.8] For token classification Tokens logits shape = 1X4X768 X FFN (assume there are 2 classes) Shape = 768X2 (hidden_dim X classes) [0.7, 0.0] [0.9, -0.2] [0.1, 0.75] [-0.1, 0.7] Hidden Layers Also called pooler output in huggingface API --- pytorch_tutorial_NTHU_NLP p.62 --- Thank you for listening 62 大海為什麼是藍色的 因為海里的魚在吐泡泡,噗嚕噗嚕噗嚕 BlueBlueBlue ## 7. 逐字稿(1:04:53 前後各多 1 分鐘,原始行) [01:03:55] 我們就會通過這個weight [01:03:57] 在乘上learning rate [01:03:59] 來更新我們的 [01:04:02] 模型的參數就是 [01:04:03] 我們的w跟b [01:04:05] 那這時候我們會發現 [01:04:07] 0.41 [01:04:08] 0.65被更新到了0.4065 [01:04:13] 也就是 [01:04:13] 這個weight在乘上learning rate [01:04:16] 這個learning rate [01:04:17] 它會是10的 [01:04:20] 可能是10的-3次方之類的大小 [01:04:24] 然後 [01:04:26] 然後 [01:04:27] optimizer.step更新完模型的權重 [01:04:30] 更新完模型的權重以後 [01:04:31] 模型裡面的參數以後 [01:04:33] 再optimizer.zero grade [01:04:35] 那這個gradient [01:04:36] 就是這個 [01:04:38] t度 [01:04:39] 它又會被清空 [01:04:41] 變成none [01:04:42] 回到none [01:04:43] 然後來準備下一次的更新 [01:04:45] 那這就是我們 [01:04:47] 這就是我們那個 [01:04:49] 一個最簡單的linear regression的範例 [01:04:53] 那麼在 [01:04:54] NLP [01:04:55] 接下來我們就會引入NLP [01:04:57] 自然語言處理的任務當中 [01:04:59] 模型的訓練的行為它大概是什麼 [01:05:02] 我們之前 [01:05:04] 所 [01:05:05] 給大家的範例其實都是一些非常簡單的模型 [01:05:07] 它裡面的參數其實就那麼一兩個 [01:05:10] 就像我們之前說的 [01:05:12] 第一個範例多項式 [01:05:14] 它的參數就是a跟b [01:05:16] 第二個linear regression它的參數就是w跟b [01:05:19] 那對於我們的自然語言處理來說 [01:05:21] 因為自然語言 [01:05:22] 它實際上是一個更加複雜的非線性系統 [01:05:26] 所以 [01:05:27] 它裡面的特徵 [01:05:29] 實際上會比這種最簡單的 [01:05:31] 就在 [01:05:32] 空間裡面的點這種特徵 [01:05:34] 要更要複雜的多 [01:05:37] 所以 [01:05:39] 我們在就是 [01:05:41] 我們在訓練這個自然語言處理的時候 [01:05:43] 我們的模型不管是模型還是資料 [01:05:46] 都會 [01:05:47] 遠遠遠遠高於之前的那些linear regression [01:05:51] 它可能會到它可能會到達的量級 [01:05:54] 就模型參數的量級可能是 [01:05:57] 多少個million [01:05:58] 或者多少個billion [01:06:01] 就是有可能你這個很多就是 [01:06:04] 你看那個GPU好像有好幾十個 [01:06:07] G的 [01:06:07] 那個大小 [01:06:08] 這VRAM大小 [01:06:09] 實際上你可能 [01:06:10] 模型塞進去都不一定塞得下 [01:06:13] 然後資料量就是更加恐怖 [01:06:15] 它有可能會上億 [01:06:17] 就上 [01:06:17] 千萬上億的這個 [01:06:19] 級別 [01:06:20] 所以 [01:06:21] 這就 [01:06:22] 產生了一個問題就是我們之前算loss的時候 [01:06:24] 我們之前算loss的那個 [01:06:27] 的值 [01:06:28] 它的在空間當中的變化 [01:06:30] 的那個區面的時候 [01:06:32] 實際上 [01:06:33] 我們是把所有的data [01:06:35] 全部丟給模型來算 [01:06:37] 變化 [01:06:38] 但是 [01:06:40] 但是在 [01:06:41] 自然源處理的任務當中 [01:06:43] 我們不可能把所有的資料丟給模型 [01:06:45] 因為資料量實在是太大了 [01:06:47] 所以 [01:06:48] 我們的處理方法 [01:06:49] 就是在資料量裡面 [01:06:51] 取出一批一批的資料 [01:06:53] 通過這一批資料來代表整一個資料dataset的分佈 [01:06:58] 所以這也是為什麼 [01:06:59] 我們如果經常 [01:07:01] 就如果有接觸 [01:07:02] deep learning的話 [01:07:03] 就大家經常會聽到說 [01:07:05] 儘可能的把data的這個 [01:07:07] badge size設大 [01:07:08] 會比較好 [01:07:09] 為什麼呢 [01:07:10] 就是因為 [01:07:11] 大badge的 [01:07:12] badge size大了以後 [01:07:14] 他這個badge [01:07:15] 就更能夠 [01:07:17] 去表示這個 [01:07:18] dataset的分佈 [01:07:19] 如果小badge如果是一筆的話他有可能會有各種自己的bias [01:07:24] 所以我們需要 [01:07:26] 我們需要有的 [01:07:28] 在 [01:07:28] 在 [01:07:29] 贈源處理當中 [01:07:30] 我們需要有的其實是在 [01:07:32] 像CV領域其實像還有 [01:07:34] 訊號處理其實也是一樣 [01:07:36] 我們需要給data [01:07:38] 來 [01:07:38] 分批 [01:07:39] 位給模型 [01:07:41] 所以我們需要有這個dataset跟dataloader的 [01:07:44] 物件 [01:07:45] 那dataset就是我們用來存儲 [01:07:47] 就是PyTorch裡面自帶的 [01:07:49] 一個用來存儲 [01:07:52] 存儲 [01:07:53] 資料的這樣一個資料結構 [01:07:56] 它裡面 [01:07:58] 它裡面的 [01:08:00] 會有三個成員變量就是我們一定要寫出來的 [01:08:03] 第一個就是初始化的這樣一個 [01:08:06] 動作 [01:08:07] 他是把 [01:08:09] 他是把 [01:08:10] 我們 [01:08:11] 我們的data往往會在initialize [01:08:13] 作為一個參數給傳進來 [01:08:15] 然後存在 [01:08:16] 這邊是命為self.data [01:08:19] 存在這個self.data的 [01:08:21] 那個成員變量裡面 [01:08:22] 然後再通過這個getitem [01:08:24] 兩個下滑線getitem兩個下滑線 [01:08:26] 就是 [01:08:27] 通過這個index這個指標 [01:08:29] 這個 [01:08:31] 指標 [01:08:32] 來中括號 [01:08:33] 取出這個getitem也就是我們平常 [01:08:36] 我們寫Python list的時候 [01:08:38] 我們後面的那個 [01:08:40] 中括號一個整數來取出 [01:08:42] 幾筆的這樣一個動作 [01:08:45] 然後 [01:08:46] 接下來就是有關這個length [01:08:48] 這個length在我們 [01:08:49] 之後 [01:08:50] 獲得這個我們在之後在實作這個data loader的時候 [01:08:55] 是也會需要 [01:08:56] 寫出來的 [01:08:57] 然後當我們 [01:08:59] 去 [01:08:59] 建立一個新的data loader的變量的時候 [01:09:02] data loader的物件的時候 [01:09:04] 我們會 [01:09:04] 第一個闡述我們可以會傳入我們的 [01:09:07] dataset的 [01:09:07] 這樣一個大資料集 [01:09:11] 然後 [01:09:11] 第二個我們會定義它的 [01:09:13] 定義它的best size是多少 [01:09:16] 它會有什麼樣的correct function [01:09:18] 然後它是否 [01:09:19] 要打亂 [01:09:20] 然後再通過這個一個復迴圈我們就可以一筆一筆資料把它取出來 [01:09:27] 那具體的資料處理過程就像這樣 [01:09:29] 如圖所示 [01:09:31] 在dataset的這個物件裡面 [01:09:33] data會一筆一筆的 [01:09:35] 通過這個getitem的這個 [01:09:38] 呃 [01:09:39] 成員變量就成員函數 [01:09:41] 把它取出來然後 [01:09:43] 這個testdata [01:09:44] 第一筆取到這裡然後第二筆再取到這裡 [01:09:47] 一筆一筆取出來 [01:09:49] 那這個地方我們可以加一些 [01:09:52] 單筆資料的 [01:09:54] 預處理 [01:09:55] 然後 [01:09:58] 做取出這些data以後 [01:10:00] 相當於取出這一批data以後然後這一批data會打包成一個tuple [01:10:04] 這個tuple再位給correct function [01:10:06] correct function [01:10:08] 它 [01:10:09] 它 [01:10:10] 是定義在我們的data loader裡面的 [01:10:13] data loader去 [01:10:14] 的 [01:10:15] input就是它的 [01:10:20] data loader [01:10:21] input是這個tuple以後 [01:10:23] 然後它會 [01:10:24] 在 [01:10:25] 在batch的這個維度在資料分批的這個維度 [01:10:29] 再對資料做一些處理 [01:10:31] 比方說你可以在correct function裡面把資料打包成tensor [01:10:35] 之類的動作 [01:10:37] 然後 [01:10:38] data loader [01:10:39] 復迴圈 [01:10:41] 我們用復迴圈去 [01:10:43] 去取出data loader這樣一批一批資料的時候 [01:10:46] 實際上取出的就是correct function的return value [01:10:50] 這個return value大家 [01:10:52] 我們可以在裡面把它打包成tensor取出來的就是tensor [01:10:57] 然後呢 [01:11:00] 就是 [01:11:01] 對於一個RNN模型來說 [01:11:03] 那接下來我們就要進入這個 [01:11:05] 自然源處理的一些模型 [01:11:08] RNN模型來說 [01:11:10] 它裡面的資料的處理過程 [01:11:13] 就是 [01:11:14] 比方說我們有一筆資料叫iloveai [01:11:16] 然後 [01:11:18] 這一筆資料 [01:11:20] 它會有每一個token [01:11:22] 它一共四個token [01:11:24] 每一個token都會有自己的ID [01:11:26] 比方說 [01:11:27] i [01:11:28] 它會有一個id [01:11:30] 它會相當於一個1號vector [01:11:32] 它對應的是這個i這個token在dictionary裡面 [01:11:36] 它是第幾個字符 [01:11:37] 然後它在embedding這個層的時候 [01:11:40] 它會 [01:11:41] 相當於通過一個矩陣乘法的方式 [01:11:44] 來把這個id [01:11:45] 通過這個id取出這個 [01:11:47] token [01:11:48] 的embedding [01:11:51] 也就是 [01:11:52] 這裡相當於是1號vector實際上是一個 [01:11:55] 非常離散是一個sparse vector [01:11:58] 它取出來以後變成embedding [01:12:00] 它就會變成這個hidden size是768 [01:12:03] 那它會取出一個 [01:12:05] 768維的 [01:12:07] 呃 [01:12:08] 768維的 [01:12:10] dense factor [01:12:12] 然後再把這個dense factor [01:12:13] 位給下面的隱藏層 [01:12:17] 然後 [01:12:18] 隱藏層 [01:12:20] 隱藏層的output [01:12:22] 就隱藏層 [01:12:24] 的這個 [01:12:25] input [01:12:26] 就是我們 [01:12:27] embedding [01:12:28] embedding層 [01:12:30] output出來的這些dense factor [01:12:32] 那這些dense factor就會 [01:12:34] 經過這個rnn模型 [01:12:35] 這邊有一個hidden state [01:12:37] hidden state加上 [01:12:37] 加上第1個token [01:12:39] 然後再 [01:12:39] 傳過來再加上第2個token [01:12:41] 再傳過來再加上第3個token [01:12:42] 這個大家在課上應該 [01:12:45] 有講老師應該有講到說 [01:12:47] rnn的模型的處理方式 [01:12:49] 那對於torch.nn.rnn的這樣一個 [01:12:53] function就這樣一個 [01:12:55] 物件來說 [01:12:56] 它吃到的這個input [01:12:59] 就是 [01:13:01] 它吃到的input [01:13:02] 就是這邊的這個dense factor [01:13:05] 它吃到的output [01:13:07] 它的return value [01:13:09] 就是 [01:13:09] 模型 [01:13:10] 它 [01:13:11] 處理好的這個 [01:13:12] 它這樣子按照rnn的這樣一個處理方式 [01:13:16] 處理好的 [01:13:17] 對每一個token對應的這個output變量 [01:13:22] 然後 [01:13:24] 另外呢它後面會有個hn [01:13:26] 這個hn它就是最後一個h [01:13:29] 最後一個hidden state [01:13:30] 那麼這個hn [01:13:32] 假如說 [01:13:33] 這個hn的作用就是假如說我們 [01:13:35] 這個rnn我們的output的這個h [01:13:38] 我們要 [01:13:38] 運用到 [01:13:39] 下面可能一些其他的模組裡面那麼我們就會用這個hn [01:13:43] 來傳給下面的 [01:13:44] 模組 [01:13:45] 比方說下面可能會有一個像 [01:13:47] 類似於decoder之類的東西 [01:13:51] 然後呢訓練rnn的時候我們 [01:13:53] 我在作業的講解當中 [01:13:55] 有講過 [01:13:56] 就是generative learning跟teacher forcing之間的區別 [01:14:00] 那麼我們這邊會建議大家用teacher forcing [01:14:03] 那大家如果用generative learning [01:14:06] 訓練出來也能訓練出來的話實際上 [01:14:08] 也應該不會有大問題 [01:14:11] 但是 [01:14:12] 這邊為什麼推薦teacher forcing [01:14:14] 其實也不光是因為teacher forcing [01:14:17] 它的coding難度低 [01:14:19] 還有一個原因 [01:14:20] 就是teacher forcing [01:14:22] 它訓練起來是會更穩定的 [01:14:24] 這邊是一個簡單的理由 [01:14:25] 範例 [01:14:27] 假如說我們給模型 [01:14:28] 的ground truth是iloveai [01:14:31] 那麼我們給rnn模型的第一個token是i [01:14:35] 我們就規定它從i開始生成 [01:14:38] 那 [01:14:39] 假如說我們直接跑一遍模型的生成 [01:14:41] 那它 [01:14:43] 預測出來的結果 [01:14:44] 可不一定是iloveai [01:14:46] 它可能是ieatapple [01:14:47] 一個句號 [01:14:50] 我們讓這個模型完整的生成完了以後 [01:14:54] 再去 [01:14:54] 再去 [01:14:55] 優化它的這個模型 [01:14:57] 我們就會發現 [01:14:58] iloveai跟ieatapple [01:15:00] 它實際上從第一個token的預測開始就錯了 [01:15:05] 在這種 [01:15:06] 訓練的過程當中 [01:15:08] 它第一個token的錯誤 [01:15:10] 它就會被利用到接下來的 [01:15:11] 訓練過程 [01:15:13] 像是 [01:15:14] 我們i [01:15:15] 會生成eat [01:15:17] 那 [01:15:18] 但是我們ground truth是love [01:15:19] 所以我們要 [01:15:21] 優化的點就是 [01:15:24] i的情況下生出love [01:15:26] 這個沒有什麼問題 [01:15:28] 但是 [01:15:29] 接下來一個token就是我們 [01:15:31] input是ieat [01:15:33] 但是我們的ground truth是ai [01:15:36] 所以我們要優化的就變成了i [01:15:38] 這個其實上非常的奇怪 [01:15:42] 就是因為 [01:15:43] 如果我們直接用generative learning [01:15:45] 我們直接用生成的方式訓練的話 [01:15:47] 會產生這樣子 [01:15:49] 不穩定會產生這樣子有問題的 [01:15:51] 表達 [01:15:52] 所以 [01:15:55] 在通過生成的方式來訓練 [01:15:58] 往往會產生像這樣子的問題 [01:16:01] 也就是早期的預測結果的錯誤 [01:16:04] 會被 [01:16:05] 一步步去 [01:16:06] 影響後面的預測結果 [01:16:08] 後面的訓練過程 [01:16:09] 所以 [01:16:10] generative learning [01:16:11] 它實際上 [01:16:12] 不太 [01:16:13] 穩定 [01:16:14] 沒有teacher forcing穩定 [01:16:16] 為什麼teacher forcing會更穩定呢 [01:16:18] 是因為我們在 [01:16:19] input的時候 [01:16:20] 就直接給他ground truth [01:16:22] 所以 [01:16:23] 他的 [01:16:24] 他要optimize [01:16:25] 他要去 [01:16:26] 優化的這些內容 [01:16:27] 他並不會有那種 [01:16:28] 奇怪的像i eat ai這種 [01:16:30] 奇怪的東西出現 [01:16:32] 他就是i的情況下 [01:16:33] 優化love [01:16:35] i love的情況下 [01:16:36] 優化ai [01:16:37] i love ai [01:16:38] 優化 [01:16:38] 驚歎號 [01:16:40] 他實際上就是一個 [01:16:42] 就沒有什麼 [01:16:43] 沒有特別奇怪的東西在這裡面 [01:16:46] 所以他會更加的穩定 [01:16:47] 所以我們也會更加推薦大家用teacher forcing [01:16:50] 而不是生成 [01:16:53] 然後再優化的這樣一個過程 [01:16:58] 另外呢 [01:16:59] 接下來 [01:17:00] 就是有關我們接下來會大概的先帶到一點 [01:17:03] 怎樣在 [01:17:04] 怎樣去使 [01:17:06] 怎樣通過hugging face這個套件 [01:17:09] 就這樣一個 [01:17:10] 平臺 [01:17:12] 去調用 [01:17:13] transformer模型 [01:17:15] 那大家 [01:17:16] 在上課應該 [01:17:17] 也已經接觸也已經講到transformer模型他大概是怎樣一回事 [01:17:21] 那transformer模型他相對於 [01:17:24] 之前的循環神經網路來說 [01:17:26] 那他其實會有更強的處理能力 [01:17:28] 並且有更加好的平行化能力 [01:17:32] 所以 [01:17:34] 這邊以bert為例嘛 [01:17:36] 就是bert [01:17:37] 他是 [01:17:39] 在transformer架構 [01:17:40] 在基礎上 [01:17:42] 經過了一個 [01:17:43] pretraining的動作 [01:17:44] 也就是 [01:17:45] Google在開發這個bert的時候 [01:17:47] 他用大量的 [01:17:49] 就是大量的文本大量的沒有標註的資料 [01:17:53] 用完形填空的方式去訓練這個模型 [01:17:56] 當然還有就是預測 [01:17:58] 某個句子是不是 [01:17:59] 哪個句子接下來 [01:18:01] 某個句子是不是哪個句子 [01:18:03] 在往後接下來寫 [01:18:04] 他兩個句子 [01:18:05] 接在一起通不通順 [01:18:06] 這種 [01:18:08] 各種各樣的就是這種 [01:18:10] 多個stage的 [01:18:11] 預訓練任務 [01:18:14] 然後 [01:18:16] 這個預訓練往往會用到非常多的硬體資源 [01:18:20] 跟 [01:18:20] 時間資源還有 [01:18:22] 各種各樣的 [01:18:23] 什麼電力成本啊這些 [01:18:25] 所以 [01:18:27] 如果我們要下載這個 [01:18:30] 這個已經pretrain好的 [01:18:32] 像bert模型的話 [01:18:34] 我們一般會透過hugging face的這個平臺 [01:18:37] 來下載這個模型 [01:18:40] 那這個hugging face的 [01:18:41] 套件調用 [01:18:43] 就是我們接下來會講的 [01:18:44] 那我們下載了這個預訓練模型以後 [01:18:46] 實際上這個 [01:18:48] 通過預訓練的這個通過pretraining這個方法 [01:18:51] 讓模型先學會這個 [01:18:53] 語言的 [01:18:54] 表達方式啊文法結構啊 [01:18:56] 他會更加的能夠對下游任務有更好的理解 [01:19:00] 能力 [01:19:00] 相當於我們直接下游任務的任務 [01:19:03] 下游任務的資料其實並不會 [01:19:06] 資料量其實並 [01:19:07] 一般來說不會很充足 [01:19:08] 那 [01:19:09] 我們直接訓練過去其實就 [01:19:11] 太遙遠 [01:19:13] 所以我們會通過pretraining先讓他學會 [01:19:16] 這門語言 [01:19:17] 然後再把他 [01:19:18] 適應的任務再一點點調過去 [01:19:20] 那這樣會顯著減少 [01:19:22] 他的資料量的需求 [01:19:23] 資料的需求量 [01:19:26] 所以 [01:19:26] 在transform [01:19:27] 就在hugging face這個平臺上面其實他有打包出這樣一個transformer [01:19:33] 的這個包 [01:19:34] 透過 [01:19:35] t-transformer.autotokenizer [01:19:38] tokenizer [01:19:39] 我們就可以 [01:19:41] 把tokenizer就是 [01:19:43] 把birth模型給 [01:19:44] 給 [01:19:45] load進來 [01:19:47] 然後 [01:19:47] 可以指定一個本地的 [01:19:49] 存儲的地點來存儲這個模型 [01:19:53] 然後 [01:19:54] 什麼叫tokenizer,tokenizer所完成的目標 [01:19:57] 就是把 [01:19:58] 就像是這裡一樣就batch encode plus [01:20:01] 我經常會用這個 [01:20:03] 我個人經常會用這個 [01:20:05] 這個 [01:20:07] 就encode [01:20:08] tokenizer的方式 [01:20:09] 這個其實 [01:20:10] 確實非常的方便 [01:20:12] 他可以 [01:20:13] 直接這樣子一行 [01:20:14] 他所完成的 [01:20:16] 結果就是第一步 [01:20:18] 把 [01:20:19] 我們的比方說像iloveai就是個自然語言的段落 [01:20:23] 給變成 [01:20:24] 每一個token並且每個token他自己的ID [01:20:28] 把它切好token然後把每個token再換成自己的ID [01:20:31] 然後 [01:20:33] 並且他可以 [01:20:34] 做到padding [01:20:35] 就是假如說我們有一筆 [01:20:36] 比方說第一筆叫什麼iloveai [01:20:39] 第二筆叫做i eat apple today [01:20:43] 然後這兩筆資料 [01:20:44] 他的 [01:20:46] 他的長度是不一樣的 [01:20:48] 那麼他可以做到padding就是 [01:20:50] 把短的資料 [01:20:51] 添零補位 [01:20:53] 變成跟長的資料 [01:20:55] 一樣的長度 [01:20:56] 並且他也可以做translation [01:20:58] 就是 [01:21:00] 我們可以定義一個最大的長度 [01:21:02] 然後 [01:21:03] 超過那個長度我們就把後面給截 [01:21:05] 後面的都不要 [01:21:08] 然後 [01:21:09] 並且他也可以自動幫我們做到 [01:21:11] 就打包成一個pytorch tensor [01:21:13] 這樣一個功能 [01:21:15] 然後這個data [01:21:19] 這個data所回傳出來的是這樣一個bash encoding的這樣一個data [01:21:24] 資料結構 [01:21:25] 那這個資料結構 [01:21:27] 大家可以把它當成一個dictionary來使用 [01:21:30] 那麼 [01:21:31] 他 [01:21:31] 默認回傳出來的東西 [01:21:33] 是在cpu上面的 [01:21:36] 大家如果要在gpu上跑的話 [01:21:38] 需要把這些 [01:21:39] 資料再搬到gpu上去跑 [01:21:42] 然後有關於模型權重的下載 [01:21:44] 這邊就是 [01:21:46] transformer.automodel [01:21:49] 然後再frompretrained [01:21:52] 再通過這個指令 [01:21:54] 來 [01:21:54] 調用 [01:21:55] 這個模型的 [01:21:58] 來調用這個模型他的 [01:22:00] 內部的權重啊模型架構這些 [01:22:03] 然後 [01:22:04] 這樣子調用出來以後 [01:22:05] 他其實相當於就是一個torch.nn.module [01:22:08] 就是一個 [01:22:09] 模組的 [01:22:11] 就是一個模組的型別的東西 [01:22:14] 大家就是按照 [01:22:15] 之前所講的 [01:22:17] Pytorch的 [01:22:18] torch.nn.module [01:22:19] 的使用方式來使用 [01:22:23] 大概就可以 [01:22:25] 然後在 [01:22:26] transformer的auto encoder裡面也有一個自己的 [01:22:29] 就是 [01:22:30] 比方說我們要對他做分類任務 [01:22:33] 如果我們要對他做分類任務那麼也會有一個自己的處理方式 [01:22:37] 那auto encoder跟 [01:22:38] rnn之間的 [01:22:39] 會有一些 [01:22:40] 明顯的不一樣的點 [01:22:42] 就是auto encoder他 [01:22:44] 並不像rnn那樣 [01:22:45] 他是 [01:22:46] 先處理第1個然後第1個再 [01:22:48] encode到 [01:22:49] hidden state再處理第2個再一直往後往後一直處理到結尾 [01:22:54] auto encoder他是 [01:22:55] 所有的token平行的往前處理 [01:22:59] 所以 [01:23:00] 這邊embedding層他照樣是 [01:23:04] 通過這個embedding層 [01:23:05] 把資料變成 [01:23:07] dense vector [01:23:08] 然後 [01:23:10] 這個dense vector在這一批dense vector在位到這個hidden [01:23:15] layers裡面去 [01:23:17] 然後 [01:23:18] 這個hidden layers [01:23:20] 就是 [01:23:21] birth model他會有自己的 [01:23:23] 處理的過程他會有 [01:23:25] attention fee for network [01:23:27] 然後他會有好多好多層的這樣的 [01:23:30] 層 [01:23:31] 然後output出來以後也會是一個 [01:23:34] 同樣大小的這樣一個 [01:23:37] dense vector [01:23:38] 那這個dense vector他跟input [01:23:40] 也是一個1對應的關係就是 [01:23:43] 第1個token就是cls [01:23:45] 就是 [01:23:45] 我們在 [01:23:46] birth處理的時候他表示的是 [01:23:49] 一個能夠代表這整句話訊息的 [01:23:52] 這樣一個token [01:23:53] 然後接下來就是每一個token他對應的 [01:23:57] 向量 [01:23:58] 然後最後是給sep表示這句話的結束 [01:24:03] 如果我們要做sequence classification的話 [01:24:05] 我們會採用第1個就是他能夠表示整一個句子 [01:24:09] 訊息的這個變量 [01:24:12] 來取出來然後對這個token做down projection [01:24:15] 做一個映射 [01:24:17] 然後 [01:24:19] 獲得比方說我們是二分類任務的話 [01:24:21] 那麼會獲得這兩個類別他相應自己的 [01:24:25] 分數 [01:24:27] 如果我們要對每一個token來做 [01:24:31] 對每一個token來做分類任務的話 [01:24:34] 做分類的話 [01:24:35] 比方說是一些比方說ner任務啊 [01:24:38] 那這邊也是 [01:24:40] 就是 [01:24:41] 假設是分兩類 [01:24:41] 那麼我們就把每一個token [01:24:44] 所對應的 [01:24:45] dense factor給取出來 [01:24:47] 然後再做 [01:24:48] 再做一個 [01:24:50] linear層再過一個linear層 [01:24:52] 然後會得到每一個token他對他的分類結果 [01:24:57] OK那這個就是 [01:24:59] 一個transformer的基本的實作過程 [01:25:02] 基本的 [01:25:03] 資料的大概處理過程 [01:25:05] 在之後的作業當中 [01:25:08] 我們會 [01:25:09] 要求大家能夠 [01:25:11] 是構建 [01:25:12] 一個 [01:25:12] 比方說從hugging face上面下載模型 [01:25:14] 然後並且 [01:25:15] 並且寫出一個自己模型的這樣一個過程 [01:25:18] 並且通過這個模型 [01:25:20] 來完成各種各樣 [01:25:21] 可能是分類可能是生成 [01:25:23] 任務的 [01:25:25] 結果 [01:25:26] 這任務的這樣一個目標 [01:25:27] 所以 [01:25:29] 所以 [01:25:32] 大家可以先 [01:25:33] 從 [01:25:34] hugging face [01:25:35] 開始 [01:25:36] 來瞭解 [01:25:37] 這個transformer [01:25:39] 這個大類模型它的使用方法 [01:25:41] 是什麼樣的 [01:25:43] 那在未來的助教課當中 [01:25:45] 助教會再 [01:25:47] 進一步的去講解一些其他的API [01:25:50] 其中也包含就是transformer更細節的使用 [01:25:54] 還有一些像是 [01:25:56] 像是其他一些好用的API [01:25:59] 我們應該怎麼調用的 [01:26:00] 這樣一個實作方法 [01:26:03] 那 [01:26:03] 本場 [01:26:04] 就是本次助教課大概講的內容就是 [01:26:07] 如上所示 [01:26:08] 謝謝大家 ## 8. 寫作規則 (這是 `_筆記SOP.md` 第 3.1、4、5、6 節的濃縮版。兩者衝突時以 SOP 為準。) 讀者:碩士生,兩門課期末是英文考試。要只看筆記就能學會,講得比老師好懂。畫面要簡潔。 **概念優先(2026-09-26 主理人)**:主理人只想懂概念,不想補數學、不想看程式碼和座標圖。兩門課的考試也都是問答題、不考算式(AI W1 1:16:52;NLP W3 1:47:41、2:48:36)。所以: - 每段預設看得到的只有:白話摘要(2–4 句)+**一句生活比喻**(例:模擬退火像投資理財,年輕時敢冒險、越老越保守)+「考試可能怎麼問」一句。 - 數學推導、公式、手算、程式碼、座標圖,全部收進標題寫「(進階,可跳過)」的摺疊,例如「它到底怎麼運作?(進階,可跳過)」。每段最多一個進階摺疊,不要寫長篇計算。 - 演算法要能「用文字說出步驟」(考試可能要你描述),這一點放在預設看得到的地方,不用數字。 - **重心比例**:白話理論與概念模式(它在解決什麼問題、核心想法、跟別的方法差在哪、優缺點、生活比喻)占主要篇幅;數學與程式細節只用一兩句帶過,細節收進進階摺疊。 **圖文並茂(2026-09-26 主理人:不要只有文字)**: - 每章至少 2–3 個圖,放在**預設看得到**的地方,每個圖前後各用一兩句白話說明「這張圖在看什麼」。 - 流程、步驟、因果、比較 → 用 mermaid 流程圖(```mermaid,flowchart LR 或 TD;節點文字用中文、加雙引號;一張圖不超過 10 個節點)。 - 投影片上的示意圖、架構圖 → 用 [[IMG: …]] 放投影片圖。 - 仍守「每個 ## 段落最多一種視覺元素」。 ### 輸出兩個檔 1. `chNN.md`(Notion 寫法,不含頁面標題),結構固定: - 第一行:章節包第 1 節那行,原樣照抄。 - 第二行起(有數學段才寫):**跳過提示**,每段一行,讓主理人看影片時知道從哪跳到哪。用章節包第 3b 節的候選當提示,對照第 7 節逐字稿確認(只標老師連續講公式、推導、矩陣、微積分、機率計算、程式細節超過約 1 分鐘的段落;概念講解和比喻不算): `跳過提示:(1:31:02–1:35:40) 老師在推導梯度公式,聽不懂可以直接跳到 [1:35:40](YouTube 連結),接著講「步長 α 怎麼選」。` - `## 重點`:三點中文,每點一到兩句。 - `## Exam-ready`:3–10 行英文,**從章節包的投影片文字逐字抄**,每行 `- **Term**: "原句"(Ch3 p.14)`。老師有明確證據才在行尾加 `【老師強調】(h:mm:ss)`。 **每一行下面一定要有一行縮排的中文解釋**(主理人英文不好,看不懂的英文等於沒用): ``` - **Hill climbing**: "It keeps track of one current state and on each iteration moves to the neighboring state with highest value."(Ch4 p.5) - 中文:爬山法只記住「現在這一個狀態」,每一輪都移到分數最高的鄰居。白話:一直往比較高的地方走一步。 ``` 中文要先把句子意思講清楚,再補一句白話;最後用「英文(中文)」列出這句裡 1–3 個難字,例:sparse(稀疏)、distinct terms(不重複的字)。 **一行只放一句投影片原句**。同一頁有多句要考就拆成多行,每行各接一行中文;不要用分號串三句以上,不要把計算量 O(...) 塞進去。 - 章節包第 2 節的每一段:`## [h:mm:ss](連結) 標題`(照抄),下面 2–4 句白話摘要,其餘全部收進摺疊: ```
問句(例:用生活例子講,BFS 在做什麼?) 內容
``` 摺疊種類(需要才放):用生活例子講?/它到底怎麼運作?/要先懂什麼?(老師假設你會的數學或概念,短版教學)/老師原話是什麼?(「原話」(h:mm:ss),只放重要的,最多 5 句)。 - 「它到底怎麼運作?」要用一組小數字把這段的演算法**真的跑 1–3 步**(例:算出梯度、更新一次、比較兩個 α),不是只示範定義的加減乘除。全章盡量沿用同一組數字,讓前一段的答案能在下一段被驗證。 - 每段正文要回答讀者最可能卡住的一個「為什麼」。投影片公式方向跟題目相反、或投影片說「解不出來」時,用一兩句講出原因,自己補的標(我補充)。 - 投影片句子停在公式前(公式在圖裡)時:Exam-ready 在粗體詞條上補公式、引號內保持原句;正文寫出同一條式子。公式圖看章節包第 6 節列出的 PNG。 - `## Self-check`:2–4 題英文考題,答案收摺疊。**至少一題考老師強調的內容**;只出 explain/why/compare 這類問答題,**不出要代數字計算的題目**(考試不考算式);不出「老師和投影片哪裡不同」這類不會考的題目。每題格式: ```
Q1. English question?(中文:中文題目) **Answer**: English answer. 中文:把答案完整講一遍(不是只翻一句),讓看不懂英文的人也知道要怎麼答。
``` - **最後一行**:章節包第 1b 節那行(下一章連結),原樣照抄。讓讀完的人直接點下一章。 - 不要把章節包或這份規則裡的指示句寫進筆記(例如「寫筆記時照投影片寫」「已改正 ASR 錯字」)。 - 長度:全文不超過 16,000 字元(跟 check_note.py 同一個數字)。**不要為了壓字數反覆刪改**(實測一章最多花 12 輪在刪字);超過時只刪進階摺疊裡的第二組算例,比喻、比較表、圖說、「老師說不用背」的提醒都不刪。 - 預設看得到的正文不放計算量 O(...)、代號對照(例如 SMART 字母)、課本出處考據,一律移進進階摺疊。 2. `chNN.concepts.json`:JSON 陣列,4–12 個考試可能問的術語,每個物件: `name`(英文)、`zh`、`type`(概念/演算法/公式/人物事件/前置知識/行政)、`signal`("老師說會考"/"老師強調"/"核心(我判斷)"/"")、`evidence`(有 signal 前兩種時必填:原句+時間)、`definition_en`(投影片原句;沒有就註明 (textbook)/(lecture)/(my wording))、`plain`(一句中文)、`a4`(≤150 字元英文,可夾極短中文;期末拼貼用的小方塊)、`time`、`slides`、`prereq`(英文名陣列)。 ### 風格鐵律 - 不用 emoji 或裝飾符號(✓✗★⚠ 都不要;→ 可以)。不用 callout。不用 `$`。時間不要用 code 樣式。 - 每個 `##` 段落最多一種視覺元素:一張圖、或一個表格、或一個 mermaid。 - 摺疊標題是問句,前面不加符號。 - 圖片最多 3 張,只放文字取代不了的圖。放法:單獨一行 `[[IMG: | 中文圖說]]`,PNG 用 `slides_to_png.py <圖片資料夾> <頁> --dpi=110` 產生。 - 考試訊號只在老師明確說時標。老師只說「不用背」「不講」就寫「注意:……」。 - 老師口誤或跟投影片不同:照投影片寫,加「注意:老師口頭說的是……」。 - 引用老師的話時,ASR 錯字改成正確的字。 ### 沒有投影片時 不要憑記憶逐字重現課本段落或數值表。英文定義用自己的話寫、句尾標 (my wording);Exam-ready 每行標「(自擬,投影片待補)」。例子只用老師講的。 ### 寫完之後(只做一次) 跑檢查: `C:\Users\user\.cache\meeting-record\venv\Scripts\python.exe C:\Users\user\.claude\scripts\check_note.py --transcript <逐字稿> --slides <投影片 txt …> --start <起> --end <訖> --vid <影片 ID>` - STYLE/VISUAL/TIME/FORMAT:全部改掉。 - QUOTE:確認是不是你改正了 ASR 錯字(是就保留),不是就改成原文或拿掉引號。 - ENGLISH:確認是不是投影片斷行造成的(是就保留),不是就改成投影片原句。 **省額度守則**:章節包裡已經有你需要的全部資料。不要再去讀整份逐字稿、整份投影片、segments.json 或手冊。一次寫好整個檔(Write 一次),檢查後集中修改。