# 章節包:自然語言處理(NLP)W4(10/1)第 06 章「PyTorch:訓練主循環與 Tensor」
PyTorch 教學(助教,2024 錄影)影片 0:00:01–0:25:47,YouTube ID sg22677pUEs,逐字稿 C:\D槽\TAICA課程\自然語言處理\第四周1151001\W4_PyTorch教學_助教.逐字稿.txt。Notion 章節頁 https://app.notion.com/p/3ecfc631b03081579f0eeb810083a514(頁 ID 3ecfc631b03081579f0eeb810083a514),頁面標題「06 PyTorch:訓練主循環與 Tensor(0:00–0:25)」。
## 1. 第一行(直接照抄,不要改)
[自然語言處理](https://app.notion.com/p/3e6fc631b03081b4a9e8f91f3411f61f) › [W4(10/1)](https://app.notion.com/p/3ecfc631b03081b8aa2cf4a97467ed41) › 06|PyTorch 教學(助教,2024 錄影)影片 [0:00:01–0:25:47](https://www.youtube.com/watch?v=sg22677pUEs&t=1s)|投影片 pytorch_tutorial_NTHU_NLP p.1–23|上一章 [05 神經網路訓練基礎(1:03–1:19)](https://app.notion.com/p/3ecfc631b0308157b691e69c735de4b4)|下一章 [07 PyTorch:用模組搭模型(0:25–0:40)](https://app.notion.com/p/3ecfc631b03081d0869df37240433e19)
## 1b. 最後一行(直接照抄,放在 Self-check 後面,當全頁最後一行)
讀完了嗎?下一章:[07 PyTorch:用模組搭模型(0:25–0:40)](https://app.notion.com/p/3ecfc631b03081d0869df37240433e19)|回到週頁:[W4(10/1)](https://app.notion.com/p/3ecfc631b03081b8aa2cf4a97467ed41)
## 2. 各段標題(照順序;每段一個 ## 標題,直接照抄連結)
- `## [0:00:01](https://www.youtube.com/watch?v=sg22677pUEs&t=1s) 環境建置` 老師講什麼:推薦用 Anaconda/Miniconda 建 Python 環境,到 PyTorch 官網依作業系統與 CUDA 版本選安裝指令;PyTorch 已內含 CUDA,不像 TensorFlow 要自己對版本。
- `## [0:03:31](https://www.youtube.com/watch?v=sg22677pUEs&t=211s) 深度學習在做什麼:梯度下降` 老師講什麼:用 y = ax²+b 和三個資料點示範:任選 a、b 會得到一組預測,和標準答案的差距用均方誤差(MSE)量化;把 a、b 與誤差畫成曲面,找最低點的方法就是梯度下降。並定義三個名詞:模型、損失函數(loss function)、優化器(optimizer)。
- `## [0:07:36](https://www.youtube.com/watch?v=sg22677pUEs&t=456s) 訓練主循環與 Tensor 的由來` 老師講什麼:資料→模型→預測→和標準答案算 loss→算梯度→optimizer 更新模型,循環往復就是主循環(main loop)。為了能計算、記住計算過程以便算梯度、又能在 GPU 上跑,誕生了 Tensor(張量)這種資料結構,可以想成維度自由的矩陣。
- `## [0:10:12](https://www.youtube.com/watch?v=sg22677pUEs&t=612s) 建立 Tensor 與它的屬性` 老師講什麼:Tensor 可以從 Python list、NumPy 或隨機、全 0、全 1、對角矩陣建立,但形狀必須方方正正;建立後可以查它的形狀、資料型別、放在 CPU 還是 GPU、要不要算梯度、目前的梯度。
- `## [0:13:04](https://www.youtube.com/watch?v=sg22677pUEs&t=784s) 底層資料和「視角」分開存` 老師講什麼:Tensor 底層是一條連續的記憶體,上面再蓋一層 view(決定怎麼把這條資料排成矩陣)。複製 tensor.data 只複製 view,底層沒複製,所以改 A 的值 B 也跟著變。
- `## [0:15:46](https://www.youtube.com/watch?v=sg22677pUEs&t=946s) Tensor 的運算` 老師講什麼:加減乘除對每個元素各算各的,矩陣乘法另用專門符號;另有拼接(cat)、切塊(split,除不盡時最後一塊放餘數)、增減維度(unsqueeze/squeeze)、轉置(transpose)等操作。
- `## [0:19:32](https://www.youtube.com/watch?v=sg22677pUEs&t=1172s) 連續儲存、轉置與 reshape` 老師講什麼:stride 表示沿某個維度走一步,底層記憶體要跳幾格,用來判斷 Tensor 是否連續存放。轉置只換 view 不搬資料,所以會變不連續;contiguous 會重新排一份連續的。view 只能用在連續的 Tensor,reshape 則會在需要時先重排再換形狀,所以功能更強。
- `## [0:24:47](https://www.youtube.com/watch?v=sg22677pUEs&t=1487s) 用整批矩陣運算取代迴圈` 老師講什麼:以「減平均除以標準差」為例,用兩層迴圈一格一格算比整批矩陣運算慢很多,因為 PyTorch 內部對矩陣運算有平行加速;寫法上盡量整批算。
## 3. 老師強調/會考/不考的地方(原句已驗證;寫進筆記時 ASR 錯字要改正)
(無)
## 3b. 數學段候選(程式抓的,只是提示;寫「跳過提示」行用)
0:16:00–0:19:00 (180s, score 19) 矩陣 維度 次方 等於
這邊呢其實我們會經常會假如說Tensor是一個矩陣運算的話這邊會多一個符號叫做這個小老鼠那矩陣運算比方說我舉個例子叫A矩陣是1234那B矩陣是0123如果說它是小老鼠的話它OP出來是他們矩陣乘法的結果但如果是單單是這個星號星星那麼他們return出來就是一個
1 段候選(門檻 3.6 字/30 秒)
## 4. 這章摘要與重要度
(助教 PyTorch 教學影片,時間是那支影片的時間)先用一個兩參數的小例子說明深度學習就是「模型吃資料、算誤差、用梯度改參數」的循環,再介紹撐起這個循環的資料容器 Tensor:它像可以任意維度的矩陣,能記住計算過程、算梯度、放到 GPU 上加速。(一般)
## 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.4 → C:\D槽\TAICA課程\_work\notes-v2\nlp-w4\img\brief_pytorch_tutorial_NTHU_NLP_p004.png
- pytorch_tutorial_NTHU_NLP p.7 → C:\D槽\TAICA課程\_work\notes-v2\nlp-w4\img\brief_pytorch_tutorial_NTHU_NLP_p007.png
- pytorch_tutorial_NTHU_NLP p.8 → C:\D槽\TAICA課程\_work\notes-v2\nlp-w4\img\brief_pytorch_tutorial_NTHU_NLP_p008.png
- pytorch_tutorial_NTHU_NLP p.9 → C:\D槽\TAICA課程\_work\notes-v2\nlp-w4\img\brief_pytorch_tutorial_NTHU_NLP_p009.png
- pytorch_tutorial_NTHU_NLP p.11 → C:\D槽\TAICA課程\_work\notes-v2\nlp-w4\img\brief_pytorch_tutorial_NTHU_NLP_p011.png
- pytorch_tutorial_NTHU_NLP p.13 → C:\D槽\TAICA課程\_work\notes-v2\nlp-w4\img\brief_pytorch_tutorial_NTHU_NLP_p013.png
- pytorch_tutorial_NTHU_NLP p.15 → C:\D槽\TAICA課程\_work\notes-v2\nlp-w4\img\brief_pytorch_tutorial_NTHU_NLP_p015.png
- pytorch_tutorial_NTHU_NLP p.18 → C:\D槽\TAICA課程\_work\notes-v2\nlp-w4\img\brief_pytorch_tutorial_NTHU_NLP_p018.png
- pytorch_tutorial_NTHU_NLP p.20 → C:\D槽\TAICA課程\_work\notes-v2\nlp-w4\img\brief_pytorch_tutorial_NTHU_NLP_p020.png
- pytorch_tutorial_NTHU_NLP p.22 → C:\D槽\TAICA課程\_work\notes-v2\nlp-w4\img\brief_pytorch_tutorial_NTHU_NLP_p022.png
- pytorch_tutorial_NTHU_NLP p.23 → C:\D槽\TAICA課程\_work\notes-v2\nlp-w4\img\brief_pytorch_tutorial_NTHU_NLP_p023.png
--- pytorch_tutorial_NTHU_NLP p.1 ---
Natural Language Processing
PyTorch tutorial
--- pytorch_tutorial_NTHU_NLP p.2 ---
Download anaconda (https://www.anaconda.com/download)
or miniconda (https://docs.anaconda.com/free/miniconda/miniconda-install/)
2
Environment setup
--- pytorch_tutorial_NTHU_NLP p.3 ---
Open Anaconda prompt
3
Environment setup
Current environment
--- pytorch_tutorial_NTHU_NLP p.4 ---
Basic Commands
After installing Anaconda, you can open the Anaconda Prompt and manage environments
using commands. Alternatively, you can use the graphical interface, Anaconda Navigator, to
perform operations directly.
1.
Create python environment
conda create –n (name) python=3.X.X
2.
Activate python environment
conda activate (name)
3.
Exit environment
conda deactivate
4.
Check environments
conda env list
4
--- pytorch_tutorial_NTHU_NLP p.5 ---
Install PyTorch
Install PyTorch: https://pytorch.org/
5
--- pytorch_tutorial_NTHU_NLP p.6 ---
Install PyTorch
You can also choose an earlier version, but the main consideration is that your
computer's hardware must support the corresponding version of CUDA.
6
--- pytorch_tutorial_NTHU_NLP p.7 ---
Deep learning
Consider the polynomial relationship between y and x defined by the equation:
y = ax2+b
Here, a and b are the parameters we want to learn, and x is the input variable.
We are given four data points to train this model:
(-1, 1), (1, 2), (2, 3)
These data points represent pairs of x values and corresponding y values.
For example, when a=1 and b=1, the predictions of –1, 1, 2 are respectively 2, 2, 5.
We define the difference between predictions and ground truths as:
L = (Σi(yi-y'i)2)/n
7
--- pytorch_tutorial_NTHU_NLP p.8 ---
Gradient decend
We can visualize how the difference (error)
changes with respect to different values of the
parameters a and b by plotting a surface, or plane.
In deep learning, we optimize the parameters a
and b using gradient descent.
We define:
y = ax2+b --> model
L = (Σi(yi-y'i)2)/n --> Loss function
The tool used to update a and b using
gradient descent. --> Optimizer
8
L
b
a
--- pytorch_tutorial_NTHU_NLP p.9 ---
Problem description
In a deep learning project, we need to:
1. Define a model
oInput a batch of data, and compute the results.
2. Train the model
oRecord the derivation procedures.
oBack propagate & Compute the gradients.
oOptimize the parameters.
oGPU acceleration.
9
A special data structure was invented.
Called "Tensor"(張量)
--- pytorch_tutorial_NTHU_NLP p.10 ---
The bricks of building models: Tensors
• Tensors are very similar to arrays and matrices.
• Tensors can run on GPUs or other hardware accelerators.
10
--- pytorch_tutorial_NTHU_NLP p.11 ---
Initialize a Tensor
There are many ways to initialize a PyTorch tensor:
From existed python list
From numpy
Randomly initialized
11
T = torch.tensor([[1, 2], [3, 4]])
T = torch.from_numpy(numpy.array([[1, 2], [3, 4]]))
Normal distributed: T = torch.randn(size=(2,2))
Uniform distributed: T = torch.rand(size=(2,2))
--- pytorch_tutorial_NTHU_NLP p.12 ---
Initialize a Tensor
Other methods
All of the elements are 1
All of the elements are 0
Diagonalized matrix
12
T = torch.ones(size=(2,2))
T = torch.zeros(size=(2,2))
T = torch.eye(n=2, m=3)
--- pytorch_tutorial_NTHU_NLP p.13 ---
Tensors
Initialize:
•
Data (Return a copy of tensor)
•
Data (Scalar only)
•
Shape (return a tuple)
•
Data type
13
T = torch.tensor([[1, 2], [3, 4]])
T.data => tensor([[1, 2], [3, 4]])
t = torch.tensor(1.1), t.item() => 1.1
T.shape => torch.Size([2, 2])
T.dtype => torch.int64
--- pytorch_tutorial_NTHU_NLP p.14 ---
Tensors
•
Device
•
Require gradient
•
Gradient
14
T.device => device(type='cpu')
T.requires_grad => False
T.grad => tensor([...])
--- pytorch_tutorial_NTHU_NLP p.15 ---
An interesting insight of tensor.data
Consider the following code:
a = torch.arange(4).reshape(2, 2) # initialize
b = a.data
print(f"{id(a)}, {id(b)}") # print the memory locations
a[0, 1] = 100
print(a)
print(b)
The output is:
Which means that a.data just creates a new view of tensor.
15
0
1
2
3
0
1
2
3
Variable a
A view
of
tensor
Storage
0
1
2
3
copy
Variable b
--- pytorch_tutorial_NTHU_NLP p.16 ---
Matrix operations
Tensor & scalar
16
A = torch.tensor([[1, 2], [3, 4]])
A+1 => tensor([[2, 3], [4, 5]])
A*2 => tensor([[2, 4], [6, 8]])
The operation is applied equaly to every elements in
the tensor except matrix multiplication(@).
--- pytorch_tutorial_NTHU_NLP p.17 ---
Matrix operations
+, -
Matrix multipliy
Element-wise multiply
17
A = torch.tensor([[1, 2], [3, 4]])
B = torch.tensor([[0, 1], [2, 3]])
A+B => tensor([[1, 3], [5, 7]])
A-B => tensor([[1, 1], [1, 1]])
A@B => tensor([[4, 7], [8, 15]])
A*B => tensor([[0, 2], [6, 12]])
--- pytorch_tutorial_NTHU_NLP p.18 ---
Matrix operations
Concatenation (equivalent to torch.concat)
Split
Squeeze, Unsqueeze
Transpose
18
torch.cat((A,B), dim=0) => tensor([[1, 2], [3, 4], [0, 1], [2, 3]])
torch.cat((A,B), dim=1) => tensor([[1, 2, 0, 1], [3, 4, 2, 3]])
T = torch.randn((5,6,7))
out = torch.split(T, 2, dim=0)
A.unsqueeze(dim=-1) => tensor([[[1], [2]], [[3], [4]]])
A.squeeze(dim=-1) => tensor([[1, 2], [3, 4]])
A.transpose(dim0=0, dim1=1) => tensor([[1, 3], [2, 4]])
A tuple of tensors and their size are:
torch.Size([2, 6, 7]), torch.Size([2, 6, 7]), torch.Size([1, 6, 7])
--- pytorch_tutorial_NTHU_NLP p.19 ---
Matrix operations
Stride: defines the step (in RAM) size used to access the next token along a given
dimension.
19
A = torch.arange(9).reshape(3, 3)
A.stride() => (3, 1)
0
1
2
3
4
5
6
7
8
0
1
2
3
4
5
6
7
8
In memory
dim: 0, stride = 3
dim: 1, stride = 3
--- pytorch_tutorial_NTHU_NLP p.20 ---
Matrix operations
contiguous:
20
A.transpose(0, 1)
A = A.contiguous()
transpose
stride = (3,1)
contiguous
stride = (1,3)
non-contiguous
contiguous
0
1
2
3
4
5
6
7
8
0
3
6
1
4
7
2
5
8
0
1
2
3
4
5
6
7
8
0
1
2
3
4
5
6
7
8
0
1
2
3
4
5
6
7
8
stride = (3,1)
contiguous
Create new
--- pytorch_tutorial_NTHU_NLP p.21 ---
Matrix operations
Reshape
21
A = torch.tensor([[1, 2], [3, 4]])
A.view(4, 1) => tensor([[1], [2], [3], [4]])
A.view(1, 4) => tensor([[1, 2, 3, 4]])
A.reshape(4, 1) => tensor([[1], [2], [3], [4]])
A.reshape(1, 4) => tensor([[1, 2, 3, 4]])
--- pytorch_tutorial_NTHU_NLP p.22 ---
Matrix operations
The difference between view and reshape.
The view function does not modify the tensor's data in memory or create a new
tensor; it simply reshapes the existing tensor by changing how the data is
interpreted.
o
It cannot be applied to non-contiguous tensors.
The reshape function can reshape non-contiguous tensors.
o
For contiguous tensors, it is equivalent to view.
o
For non-contiguous tensors, it will be a copy and the result is equivalent to
contiguous+view.
22
--- pytorch_tutorial_NTHU_NLP p.23 ---
Matrix operations
Note: All PyTorch computations are performed in a matrix operation mode.
e.g. Randomly initialize a tensor(100X100) and normalize it:
Sequentially: 0.127 s
Matrix Operation: 0.000088s
23
## 7. 逐字稿(0:00:01 前後各多 1 分鐘,原始行)
[00:00:01] 歡迎來到國立清華大學自然語言處理課程,本次助教課給大家講的主要是PyTorch的使用方法、模型的訓練方法等實際操作的內容,那這裡是高雄宇老師的助教。
[00:00:15] 在講實際的code該怎麼寫之前,我們先大概介紹一下Python環境的架設。
[00:00:22] 假如大家要在自己的電腦上面跑Python,或者跑深度學習的話,這邊推薦Anaconda或者MiniConda來構建Python的環境。
[00:00:34] 這邊以Windows系統為例,大家可以直接去他們的官網下載安裝包,然後也可以通過指令來下載。
[00:00:46] 下載完了以後,在Windows系統上這邊會有一個Anaconda prompt的檔,打開檔以後大家可以看到一個像Shell一樣的黑框,那這個黑框就是我們可以操作環境的窗口。
[00:01:03] 左上角的括號base就是現在我們所處的環境的名稱,大家如果創建了自己的環境的話,在這邊它的base就會換成你自己環境的名稱。
[00:01:16] 那這邊大家可以通過一些指令來操作環境,這裡有簡單的列出幾個,比方說可以通過create,conda create,來創建環境,或者是conda activate來激活環境。
[00:01:32] 然後我們創建好了基本的Python環境以後,接下來就是安裝PyTorch。
[00:01:41] 這裡的PyTorch不推薦大家直接用PIP install來安裝,也不推薦什麼。
[00:01:46] 這裡的PyTorch不推薦大家直接用PIP install來安裝,也不推薦什麼。
[00:01:47] 這裡的PyTorch不推薦大家直接用PIP install來安裝,也不推薦什麼。
[00:01:47] 這裡的PyTorch不推薦大家直接用PIP install來安裝,也不推薦什麼。
[00:01:47] 這裡的PyTorch不推薦大家直接用PIP install來安裝,也不推薦什麼。
[00:01:50] 因為直接用PIP或者conda你很難指定安裝什麼版本的PyTorch,而我們這裡可以看到PyTorch有支援Linux、Mac、Windows有不同的作業系統版本,然後也有支持不同ientes版本的PyTorch。
[00:01:50] 而我們這裡可以看到PyTorch有支援Linux、Mac、Windows有不同的作業系統版本,然後也有支持不同 analytical sci-fi版本的PyTorch。
[00:01:53] 而我們這裡可以看到PyTorch有支援Linux、Mac、Windows有不同的作業系統版本,然後也有支持不同 evangelical sci-fi版本的PyTorch。
[00:02:09] 所以大家最好是上官網去選擇一個符合自己電腦需求的
[00:02:16] 這樣一個PyTorch版本
[00:02:17] 選好自己的需求以後
[00:02:21] 下面就會有對應的安裝指令
[00:02:24] 那裝好
[00:02:25] 那大家直接把這個安裝指令輸入到Anaconda Prompt
[00:02:31] 就是可以操作環境的窗口當中
[00:02:34] 就可以安裝PyTorch了
[00:02:36] 那這邊要提醒大家的是
[00:02:38] 安裝PyTorch不需要額外安裝CUDA
[00:02:41] 因為PyTorch裡面有整合CUDA的內容
[00:02:44] 這是PyTorch跟TensorFlow不同的地方
[00:02:48] 因為TensorFlow它裡面並沒有去整合這些內容
[00:02:52] 所以當我們裝TensorFlow的時候
[00:02:54] 我們要去查TensorFlow跟CUDA有哪些版本的對應關係
[00:02:58] 並安裝對應版本的CUDA
[00:03:00] 但是PyTorch就不需要這麼做
[00:03:05] 但相比之下
[00:03:07] PyTorch的包
[00:03:08] 其實會有點難受
[00:03:08] 可能會更大一點
[00:03:10] 然後安裝
[00:03:12] 那麼接下來
[00:03:14] 如果大家想要安裝早些版本的PyTorch
[00:03:17] 或者是安裝一些其他CUDA版本之類的
[00:03:21] 那麼就可以點擊這裡
[00:03:23] 這邊有個鏈接
[00:03:24] 點進去以後就會看到過去各個版本的PyTorch的安裝指令
[00:03:31] 那安裝好了基本的環境架設以後
[00:03:35] 接下來呢
[00:03:35] 就是有關於Deep Learning
[00:03:38] 我們先從Deep Learning開始介紹
[00:03:41] 那Deep Learning
[00:03:42] 我們大概可以有這樣一個印象
[00:03:44] 就是我們會有一個模型
[00:03:45] 那我們也會有一堆資料
[00:03:49] 模型呢
[00:03:49] 他會不斷的去吃資料
[00:03:51] 然後讓自己的效能不斷的提升
[00:03:53] 就是我們相當於我們不斷的給模型範例
[00:03:58] input是什麼樣
[00:03:58] output應該要是什麼樣
[00:04:00] 不斷的給他這種範例以後
[00:04:02] 模型會自我調整裡面的參數
[00:04:04] 然後讓自己的效能越來越好
[00:04:07] 那這裡wide
[00:04:08] 就等於ax加b
[00:04:09] 假如說這個模型
[00:04:11] 他的input跟output是像這樣的一個多項式關係
[00:04:16] 他有兩個參數
[00:04:17] 一個是A一個是B
[00:04:20] 那那這樣的話
[00:04:23] 這個模型他我們要訓練的就是這兩個參數
[00:04:27] A跟B這兩個參數
[00:04:28] 那用什麼來訓練
[00:04:29] 他我們這裡面給了三個資料
[00:04:32] 其實是在空間當中的三個點
[00:04:36] 當input是-1的時候
[00:04:38] output需要是1
[00:04:40] 當input是-1的時候
[00:04:41] output是2
[00:04:42] 當input是-2的時候
[00:04:43] output是3
[00:04:44] 給出這三個點以後
[00:04:47] 我們就可以發現當A跟B
[00:04:49] 我們取一個固定的A跟B以後
[00:04:52] 把x把橫座標輸入進去
[00:04:55] 我們就可以獲得他重座標的值
[00:04:58] 如果A跟B都是-1
[00:05:00] A跟B都是1的話
[00:05:01] 那output出來的重座標就是225
[00:05:05] 那明顯這個225
[00:05:06] 他是不符合我們的期待的
[00:05:08] 因為我們希望他是123
[00:05:10] 那我們要如何衡量
[00:05:12] 這個225他跟123中間有多大的距離呢
[00:05:16] 我們需要去衡量出這個量化的距離
[00:05:19] 並且最小化這個距離
[00:05:21] 所以這邊的距離
[00:05:23] 我們把它表示成
[00:05:26] 標準答案減去預測結果的平方
[00:05:29] 再取平均值
[00:05:31] 也就是這三個點會取平均值
[00:05:34] 獲得我們最終跟結果的誤差
[00:05:37] 也就是L
[00:05:38] 那這個方式
[00:05:40] 其實我們之後會介紹到叫做mean square error
[00:05:43] 那這邊我們把它表示成一個L
[00:05:47] 然後我們就會發現
[00:05:48] 當A跟B各取一個值的時候
[00:05:52] A跟B取任何不同的實數
[00:05:54] 我們都可以獲得一組225
[00:05:57] 就是一組這個output prediction
[00:06:00] 一組預測結果
[00:06:02] 那有了這種預測結果
[00:06:03] 我們就會有一個對應的誤差
[00:06:06] 就是一個對應的L
[00:06:09] 那麼問題就來了
[00:06:10] 就是我們是不是可以把A跟B和L的對應關係
[00:06:16] 畫成一張圖
[00:06:17] 就像這樣
[00:06:20] A跟B在取不同的座標點的時候
[00:06:24] 都會有一個對應的L
[00:06:26] 那這是我通過3D的繪圖
[00:06:30] 軟體來畫出來的一張圖
[00:06:32] 畫出來的一個區面
[00:06:34] 這個區面我們要找的就是它A跟B
[00:06:39] 在某個值的位置中
[00:06:40] 在某個值的時候
[00:06:41] L的算出的結果會最低
[00:06:44] 也就是最底下這個點
[00:06:46] 我們如何獲得最底下這個點
[00:06:48] 就是通過梯度下降的方式
[00:06:50] 那梯度下降
[00:06:51] 大家肯定在微積分裡面有學過
[00:06:55] 通過偏微分來算出梯度
[00:06:58] 然後再通過梯度來更新
[00:07:02] 來尋找出最低的那個點
[00:07:06] 所以這邊Y等於AX加B
[00:07:09] 就是我們描述XY等於B
[00:07:10] 我們把這個點定為一個等式
[00:07:11] 我們把它叫做模型
[00:07:13] 我們定義模型的預測結果
[00:07:17] 和標準答案之間距離的這樣一個等式
[00:07:20] 叫做loss function
[00:07:22] 損失函數
[00:07:25] 另外我們用來做梯度下降的工具
[00:07:30] 叫做optimizer
[00:07:31] 就是優化器
[00:07:33] 中文翻譯叫優化器
[00:07:36] 所以我們可以用一張圖來表示
[00:07:39] 這個訓練的過程
[00:07:40] 首先data會餵給模型
[00:07:44] data會餵給模型
[00:07:45] 然後模型會產出預測結果
[00:07:48] 預測結果跟ground truth
[00:07:51] 跟標準答案之間會算出一個loss值
[00:07:54] 這個loss值
[00:07:55] 我們為了最小化這個loss值
[00:07:57] 會用梯度下降的方法
[00:07:59] 所以loss值會獲得一個梯度
[00:08:01] 那梯度再通過這個optimizer
[00:08:05] 來更新模型的參數
[00:08:07] 像這樣一個模型獲得預測的參數
[00:08:09] 預測在獲得梯度
[00:08:10] 梯度在更新模型
[00:08:11] 這樣循環往復的這個過程
[00:08:13] 就是我們深度學習當中的主循環
[00:08:16] 也就是main loop
[00:08:18] 為了完成這個main loop
[00:08:20] 我們就可以想說
[00:08:21] 我們需要一個特殊的資料結構
[00:08:23] 那這個資料結構需要做什麼呢
[00:08:25] 就是首先
[00:08:26] 它需要能夠計算
[00:08:28] 我data餵給模型以後
[00:08:30] 我們通過一個基本的資料結構去算出一個預測結果
[00:08:36] 另外這個資料結果還
[00:08:39] 這個資料結構
[00:08:40] 它可以保存我們的計算過程
[00:08:43] 並且通過這個計算過程來算出梯度
[00:08:47] 這個梯度
[00:08:48] 還能繼續回來更新這個
[00:08:52] 資料結構裡面的數值
[00:08:55] 那當我們這個模型越來越大
[00:08:58] 就是參數量越來越大的時候
[00:09:00] 我們會希望
[00:09:01] 這個模型能夠加速運算
[00:09:04] 所以
[00:09:05] 也就是說在GPU上運算
[00:09:08] 所以這裡
[00:09:09] 就誕生了一個資料結構
[00:09:10] 叫做Tensor
[00:09:12] 就是張量
[00:09:13] 所謂的張量
[00:09:14] 我們大名鼎鼎的TensorFlow
[00:09:16] 大家應該都有聽過
[00:09:18] 叫做張
[00:09:18] 中文直譯叫張量流
[00:09:21] 那意思就是說
[00:09:22] 在它這個資料
[00:09:23] 在它這個包裡面
[00:09:24] 數
[00:09:25] 就是data都是通過張量的方式
[00:09:28] 就通過Tensor的方式
[00:09:30] 來進行處理的
[00:09:32] 所以
[00:09:33] 大家理解Tensor
[00:09:35] 可以把它大概的理解成矩陣
[00:09:38] 只不過它是
[00:09:40] 維度特別自由
[00:09:41] 就是它可以是很高維的矩陣
[00:09:43] 它跟我們平常會
[00:09:45] 在現代裡面接觸過那種二維矩
[00:09:48] 大多數都是二維矩陣的
[00:09:50] 還不太一樣
[00:09:52] 它可以非常高維
[00:09:55] 它的基本運算方式其實也就是矩陣的運算方式
[00:09:59] 我們之後會介紹到
[00:10:00] 那它確實完成了可以計算T度
[00:10:03] 並且在GPU上運行的這樣一個需求
[00:10:08] 然後我們就
[00:10:10] 我們介紹了大概Tensor的由來
[00:10:12] 那接下來就是我們如何先創建一個Tensor
[00:10:16] Tensor的創建可以通過這個Python的基本型別
[00:10:20] 就是list
[00:10:21] 來創建
[00:10:22] 但是要注意這邊因為Tensor它
[00:10:25] 我們大概理解成的是一個矩陣
[00:10:28] 所以它不能是
[00:10:30] 參差不齊的list
[00:10:32] 什麼意思呢就是
[00:10:34] 現在這裡是一個二乘二的list
[00:10:37] 那
[00:10:37] 我不能說
[00:10:39] 第一個
[00:10:40] 第一個維度它只有一個數
[00:10:42] 第二個維度它有兩個三個數
[00:10:44] 它必須是要對齊
[00:10:46] 就是
[00:10:46] 二乘二
[00:10:47] 那在這個方方正正的
[00:10:49] 矩陣當中
[00:10:50] 每一個它都有一個
[00:10:52] 就每一個它都不是空的
[00:10:54] 它至少都是有一個數的
[00:10:57] 然後並
[00:10:58] 另外呢它也可以通過nonpy來
[00:11:01] 初始化
[00:11:01] 然後也可以隨機初始化就是torch.ran
[00:11:06] 這個
[00:11:07] randn
[00:11:08] 後面多了一個n的
[00:11:10] 它是
[00:11:11] 以normal distribution
[00:11:13] 的機率分佈來初始化的
[00:11:15] 然後後面沒有多一個n的
[00:11:17] 它是均勻初始化的
[00:11:22] 然後
[00:11:23] 我們也可以創建全都是1的Tensor
[00:11:27] 也可以也有全都是0的
[00:11:29] 還有就是對角矩陣
[00:11:31] 這個在我們
[00:11:32] 往往深度學習
[00:11:34] 的一些中間
[00:11:36] 變量的處理當中
[00:11:38] 是經常會遇到的
[00:11:41] 然後呢
[00:11:42] 創建好了一個Tensor以後
[00:11:45] 我們就可以
[00:11:46] 通過一些Tensor當中的一些成員變量
[00:11:49] 去獲得Tensor的一些屬性
[00:11:51] 比方說data
[00:11:53] 就是
[00:11:54] 相當於是return一個Tensor的copy
[00:11:57] 就return它自己
[00:11:59] 那
[00:12:01] 這個
[00:12:01] 這邊還有一個如果說你是單一的變量的話
[00:12:05] 你不是一個
[00:12:06] 一串
[00:12:07] 一個vector或者一個矩陣
[00:12:09] 那麼
[00:12:10] 你可以用
[00:12:11] item來
[00:12:12] 回傳出它裡面的數值
[00:12:15] 那另外呢你也可以通過這個.shape來看它是幾乘幾
[00:12:19] 像這個就是二乘二
[00:12:21] 然後也有這個裡面是什麼數值
[00:12:24] 像假如說
[00:12:26] 它是一點二點就是
[00:12:28] 它是float的話這邊也會
[00:12:30] return出這個
[00:12:32] torch.float
[00:12:33] 那
[00:12:36] 然後再往後
[00:12:37] 也可以看說這個
[00:12:39] Tensor它在CPU上還是GPU上
[00:12:42] 畢竟因為Tensor它
[00:12:43] 需要能夠滿足
[00:12:44] 我們在GPU上運算的這樣一個需求
[00:12:48] 然後
[00:12:48] 我們也可以看說這個Tensor它是不是一個需要回傳T度的Tensor
[00:12:54] 然後
[00:12:56] 這個
[00:12:59] 我們也可以把它的T度
[00:13:01] 給
[00:13:01] 回傳出來
[00:13:04] 然後這邊有一個比較有趣的insight
[00:13:07] 有關於Tensor.data
[00:13:09] 那Tensor.data我們
[00:13:11] 之前有講過
[00:13:12] 它是
[00:13:13] 把這個Tensor裡面的
[00:13:14] 相當於它裡面的一些
[00:13:16] 內容給回傳出來的這樣一個動作
[00:13:19] 我剛剛解釋說
[00:13:20] 是把Tensor給複製一份
[00:13:22] 那在
[00:13:23] 它實作的過程當中
[00:13:25] 也確實有複製的這個動作
[00:13:27] Tensor的儲存方式
[00:13:29] 是底層有一個
[00:13:31] 最底層有一個
[00:13:33] Tensor內部data的儲存
[00:13:37] 它往往是一個連續的空間
[00:13:40] 是一字排開的空間
[00:13:42] 那在這個空間之上會有一個view
[00:13:44] 所謂的view就是說
[00:13:46] 這一串的data
[00:13:49] 它要通過怎樣的組合
[00:13:51] 來構成我們這個Tensor
[00:13:54] 然後在我們實際寫code的時候
[00:13:56] 我們會有一個變量
[00:13:57] 比方說它這個變量叫A
[00:13:59] A來指向這個view
[00:14:02] 這邊有個簡單的範例
[00:14:05] 假如說我們命出一個A
[00:14:07] A是
[00:14:09] 一個二乘二的矩陣
[00:14:10] 就是0123
[00:14:12] 這樣一個二乘二的矩陣
[00:14:14] 那B把A.data的這個
[00:14:18] A.data的這個屬性
[00:14:20] 給複製給B
[00:14:21] 然後再把A跟B
[00:14:23] 他們中間的
[00:14:25] 在memory當中的位置給print出來
[00:14:28] 然後
[00:14:30] 再把A的01這個位置
[00:14:33] 也就是
[00:14:34] 因為0123把1的那個位置
[00:14:37] 改成100
[00:14:38] 再把A跟B給print出來
[00:14:40] 那從這個結果當中我們可以發現
[00:14:44] A跟B
[00:14:45] 它雖然A.data把它複製給了B
[00:14:50] 但是A跟B中間
[00:14:53] 他們用的並不是同一塊記憶體
[00:14:56] 但是我們修改A的時候
[00:14:59] B的值也會一起改
[00:15:00] 意思是什麼呢
[00:15:01] 意思就是說
[00:15:03] 在我們當我們把A.data給B的時候
[00:15:06] 它實際上是把A的這個view給複製了一份
[00:15:12] 複製了一份新的view
[00:15:14] 給了B
[00:15:16] 但它的底層
[00:15:18] 0123這個最底層的資料
[00:15:20] 存儲
[00:15:22] 並沒有重新複製一份
[00:15:24] 所以
[00:15:25] A跟B它的
[00:15:27] 在memory當中
[00:15:28] 它這個view在memory當中的位置是不一樣的
[00:15:30] 但是
[00:15:31] 當我們改A裡面的值的時候
[00:15:33] B也會跟著一起改
[00:15:35] 因為它的
[00:15:36] 底層的
[00:15:37] 資料存儲
[00:15:38] 並沒有改變
[00:15:42] 然後
[00:15:43] 接下來就是
[00:15:44] 有關於
[00:15:45] 就是
[00:15:46] Tensor的運算
[00:15:48] Tensor加上一個常量
[00:15:50] 就是Tensor
[00:15:51] 加上一個具體的數
[00:15:52] 或者減具體的數
[00:15:54] 就是在Tensor當中的每一個
[00:15:57] 數值
[00:15:58] 做同樣的
[00:15:59] 加減乘除的操作
[00:16:03] 這邊呢其實我們會經常會
[00:16:06] 假如說Tensor是一個
[00:16:08] 矩陣運算的話
[00:16:10] 這邊會多一個符號叫做這個小老鼠
[00:16:13] 那
[00:16:14] 矩陣運算
[00:16:15] 比方說我舉個例子叫
[00:16:16] A矩陣是1234
[00:16:18] 那B矩陣是0123
[00:16:20] 如果說它是小老鼠的話
[00:16:22] 它OP出來是他們矩陣乘法的結果
[00:16:26] 但如果是
[00:16:26] 單單是這個星號
[00:16:28] 星星
[00:16:29] 那麼他們return出來就是一個
[00:16:32] 元素相加的結果
[00:16:33] 就是
[00:16:34] 元素相乘的結果
[00:16:35] 就是0乘1 2乘1
[00:16:38] 3乘2
[00:16:40] 4乘3的這樣一個結果
[00:16:43] 只有這個
[00:16:44] 除了這個例外以外
[00:16:46] 其他像加減啊
[00:16:48] 還有除啊這些
[00:16:50] 還有乘次方啊
[00:16:52] 都是
[00:16:54] 矩陣兩個矩陣當中對應元素的加減
[00:16:57] 加減乘除次方
[00:17:01] 然後
[00:17:03] 在Tensor
[00:17:05] 除了它基本的矩陣運算以外
[00:17:07] 還有一些自己的一些
[00:17:09] 操作
[00:17:10] 比方說CAT
[00:17:12] CAT就是把兩個Tensor給拼起來
[00:17:14] Concatenate
[00:17:16] 那麼
[00:17:17] A跟B
[00:17:18] 都是2乘2的矩陣
[00:17:20] 那
[00:17:21] 他們
[00:17:22] 在shape就是2乘2
[00:17:23] shape在0這個位置是
[00:17:25] 的大小是2
[00:17:26] 1的這個大小也是2
[00:17:29] 我們把它在
[00:17:31] 維度為0的這個地方拼接
[00:17:34] 它就會變成4乘2的矩陣
[00:17:37] 也就是它在shape等於0
[00:17:39] 那個第一個2
[00:17:40] 的這個位置拼接起來
[00:17:42] 那它在
[00:17:43] 它就會變成4乘2
[00:17:45] 如果說它在
[00:17:46] 第二個2
[00:17:47] 就是
[00:17:47] 維度為1的這個地方拼接起來
[00:17:49] 它就會變成2乘4
[00:17:51] 另外它還可以split
[00:17:53] 把一個Tensor給切成很多塊
[00:17:56] 像這邊
[00:17:57] 初始化一個Tensor是567
[00:18:00] 5乘6乘7的Tensor
[00:18:02] 它在維度為0的時候
[00:18:04] 去切分
[00:18:05] 並且我們希望它切出來的Tensor
[00:18:07] 在這個維度的大小
[00:18:09] 是2這個值
[00:18:11] 所以
[00:18:12] 它切的是維度是5
[00:18:14] 並且我們希望切出來的大小是2
[00:18:16] 那我會
[00:18:17] 我們會不難想象就是5
[00:18:18] 它其實是沒有辦法被2整除的
[00:18:21] 所以我們切
[00:18:22] 就切出一個267
[00:18:24] 在第二個還是267
[00:18:26] 在
[00:18:27] 最後一個只剩1了
[00:18:28] 它實際上
[00:18:29] 並不會報錯
[00:18:30] 而是把最後那個1
[00:18:32] 給
[00:18:32] 也給放在後面
[00:18:34] 最後一個會是它的
[00:18:36] 就是
[00:18:37] 它是會是一個餘數
[00:18:40] 那這邊還有squeeze跟unsqueeze
[00:18:42] 這個是加
[00:18:43] 加維度跟減維度
[00:18:45] A是一個2乘2的矩陣
[00:18:47] 那A在最後一個維度
[00:18:50] unsqueeze
[00:18:51] 那麼它就會最後一個維度加一個
[00:18:53] 加一個1就變成2乘2乘1的矩陣
[00:18:56] 然後A再squeeze
[00:18:58] 它就又會變成1234
[00:19:00] 就又會變成2乘2的矩陣
[00:19:04] 然後
[00:19:04] 這邊還有transpose
[00:19:06] 那transpose
[00:19:08] 就是我們常說矩陣
[00:19:10] 矩陣
[00:19:11] 運算當中的轉制
[00:19:14] 把1234變成1324
[00:19:18] 就是按對角線翻轉一下
[00:19:23] 然後
[00:19:25] 我們可以
[00:19:25] 然後以上是一些有關tensor的基本操作
[00:19:30] 那接下來
[00:19:31] 這樣這個
[00:19:32] stride函數
[00:19:34] 它主要介紹的是
[00:19:35] tensor它在底
[00:19:37] tensor它是否
[00:19:38] 連續或者說它在底層是怎樣存儲的這樣一個
[00:19:42] function
[00:19:44] stride它返回的是什麼呢
[00:19:45] 假如說我們有一個3乘3的
[00:19:47] tensor
[00:19:48] 3乘3是就是
[00:19:49] 012
[00:19:50] 345678
[00:19:52] 對吧
[00:19:53] 就像這樣的一個tensor
[00:19:57] 這邊
[00:19:57] 它底層
[00:19:58] 它在
[00:19:59] 它在
[00:20:00] 存儲的時候
[00:20:01] 它會
[00:20:03] 它會有
[00:20:05] 先是第一排
[00:20:07] 在前面
[00:20:08] 然後是第二排
[00:20:09] 然後是第三排
[00:20:10] 它是一排二排三排這樣子連成一條
[00:20:14] 連成一串的存儲方式
[00:20:17] 那
[00:20:18] stride
[00:20:19] 就是說
[00:20:20] 在
[00:20:21] stride它會回傳一個tuple
[00:20:24] tuple在第零個維度的時候
[00:20:26] 它在第一個維度就表示
[00:20:29] 在這個維度在零維度的時候
[00:20:32] index加1
[00:20:33] 它在底層存儲的時候會跳幾格
[00:20:37] 在這邊
[00:20:40] 第零個維度就是零跳到3
[00:20:44] 這一步
[00:20:45] 它在底層會跳三格
[00:20:47] 0到1到2到3
[00:20:49] 會跳三格
[00:20:50] 它在
[00:20:52] 它在第一維度的時候
[00:20:55] 也就是說從零到一
[00:20:57] 那麼它在底層會跳一格
[00:21:00] 那
[00:21:01] 這樣
[00:21:01] 如果我們可以通過檢查stride這個函數來判斷這個
[00:21:06] tensor它是否
[00:21:08] 是所謂的連續的tensor
[00:21:11] 也就是說是否是像這樣子存儲方式
[00:21:13] 第一排第二排第三排的
[00:21:15] 存儲方式的這樣一個tensor
[00:21:19] 然後
[00:21:20] 我們就可以再看就是transpose這個tensor
[00:21:22] 這邊還有另外一個有趣的inside
[00:21:26] 就是transpose這個function
[00:21:31] 它實際上並不會創建新的tensor
[00:21:34] 而是創建了一個新的view
[00:21:36] 其實tensor的操作有很多
[00:21:40] 都不是創建新的tensor
[00:21:42] 而是創建新的view
[00:21:44] 像是
[00:21:45] 本來是012345678
[00:21:48] 它的底層是這樣存的
[00:21:50] 它通過transpose以後
[00:21:52] 把上面的翻到旁邊來
[00:21:55] 變成這樣
[00:21:57] 但是它們底層的其實並沒有改變
[00:21:59] 它只是創建了一個新的view出來
[00:22:02] 那這時候它的stride就變成了13
[00:22:04] 就是在第0維度從0跳到1的時候
[00:22:07] 它在底層只會跳一格
[00:22:11] 從0跳到3它會跳三格
[00:22:13] 也就是說它從連續變成了不連續的矩陣
[00:22:19] 那這邊呼叫contiguous
[00:22:21] contiguous就是把
[00:22:23] 一個不連續的矩陣
[00:22:24] 變成連續的矩陣
[00:22:25] 如果a本身就是連續的話
[00:22:29] 那麼
[00:22:29] 它其實不會做任何處理
[00:22:31] 就是把a給return出來
[00:22:35] 所以這邊
[00:22:37] 這邊就是說
[00:22:38] 它呼叫了contiguous
[00:22:40] 那麼它會在底層的存儲
[00:22:42] 又
[00:22:43] 創建一個新的存儲空間
[00:22:46] 並且把它存成
[00:22:48] 像
[00:22:49] 這樣子排列方式的
[00:22:50] 也就是
[00:22:51] 把這邊的第1排變成
[00:22:54] 變到開頭
[00:22:55] 然後再是第2排
[00:22:56] 再是第3排的這樣一個連續的存儲
[00:22:58] 然後這樣的話
[00:23:00] 它的stride
[00:23:01] 就變回了3e
[00:23:03] 也就是說它變回了連續的
[00:23:05] 連續空間存儲的這樣一個
[00:23:09] 存儲方式
[00:23:11] 然後
[00:23:12] 接下來是有關於reshape
[00:23:14] 一個2x2的矩陣
[00:23:15] 它可以被reshape成
[00:23:17] 1x4或者4x1
[00:23:20] 的
[00:23:20] 形狀
[00:23:22] 那PyTorch在reshape這個功能之下
[00:23:26] 是做了兩個函數
[00:23:27] 一個叫做viewed
[00:23:28] 還有一個叫reshape
[00:23:30] 之前我們有介紹過PyTorch
[00:23:32] 它是底層的
[00:23:33] 資料
[00:23:34] 在上面再蓋一個view
[00:23:36] 那這個view我們就很好理解
[00:23:38] 它實際上也是一個創建view的一個動作
[00:23:41] 然後reshape呢
[00:23:43] 它的
[00:23:44] 功能會比view要更強一些
[00:23:47] 在這邊有一個介紹就是
[00:23:49] view
[00:23:50] 它
[00:23:51] 無法
[00:23:51] 去操作不連續的矩陣
[00:23:55] 它只能去操作連續的
[00:23:57] 並且
[00:23:58] 它是在一個連續矩陣的基礎之上
[00:24:01] 再創建一個新的view
[00:24:05] 然後它不會去改變底層的存儲
[00:24:07] 但是reshape不一樣
[00:24:09] reshape是contiguous加view
[00:24:12] 假如說你的這個input data
[00:24:13] 它並不是連續的
[00:24:16] 那麼它就會創建一個新的
[00:24:19] 那麼它就會創建一個新的內部存儲空間
[00:24:22] 相當於它先contiguous
[00:24:24] 再跑view
[00:24:25] 所以
[00:24:27] reshape就加了這樣一個判斷
[00:24:29] 它的功能也會比view要強大一些
[00:24:35] 然後
[00:24:37] 接下來
[00:24:37] 我們介紹了一些有關於
[00:24:40] tensor的
[00:24:40] 基本的
[00:24:41] 操作以後
[00:24:42] 這邊會建議說大家
[00:24:45] 在做tensor的運算的時候
[00:24:47] 儘量用矩陣運算的方式來運算
[00:24:50] 而不要用循序的方式來運算
[00:24:52] 因為tensor它內部
[00:24:55] 它對於這個矩陣運算有自己的
[00:24:58] 並行化的一些加速過程
[00:25:01] 假如我們這邊舉的一個範例是我們要normalize
[00:25:05] 所謂的normalize
[00:25:06] 就是
[00:25:07] 減平均除以標準差
[00:25:11] 這個過程我們可以
[00:25:12] 寫兩個套兩個復迴圈來寫
[00:25:15] 也可以
[00:25:15] 就是
[00:25:16] 用矩陣
[00:25:18] 矩陣運算的方式來寫
[00:25:20] 那這邊我們會發現
[00:25:22] 它的效能會差很多
[00:25:24] 因為這就是
[00:25:25] 我們就
[00:25:26] 因為矩陣運算它實際上
[00:25:28] 相當於利用了PyTorch內部的一些加速功能
[00:25:31] 但是如果你是循序的話
[00:25:34] 它實際上就是你就是強制它一個一個來算
[00:25:37] 這其實是
[00:25:40] 相當耗時間的
[00:25:41] 也是一個相當沒有效率的做法
[00:25:45] 然後
[00:25:47] 接下來我們介紹了
[00:25:50] 建構模型的或者和資料的一個基本單位就是Tensor
[00:25:55] 那接下來我們就是要
[00:25:57] 通過這個Tensor來建構一個模型
[00:25:59] 那Tensor在模型當中的主要的一個
[00:26:03] 角色
[00:26:03] 就是
[00:26:04] 就是它的參數
[00:26:07] 在一個模型當中
[00:26:08] 它底層的參數
[00:26:10] 就是通過Tensor來存儲的
[00:26:12] 並且在Tensor的這個參數之上
[00:26:16] 有一個大的資料結構
[00:26:18] 叫做torch.nn.module
[00:26:21] 也就是
[00:26:22] 模組
[00:26:23] 所謂的模組
[00:26:25] 我們所有的模型它都是
[00:26:28] 它都需要是一個模組的物件
[00:26:31] 那假如說我們要創建一個新的
[00:26:33] 我們自己的模型
[00:26:34] 我們就繼承著這個模組
[00:26:37] torch.nn.module
[00:26:39] 然後再去複寫它的
[00:26:43] 我們自己特有的這樣一個
[00:26:46] 初始化的函數跟
## 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 一次),檢查後集中修改。