【Pytorch 深度學習筆記】搞懂什麼是深度學習以及 Pytorch 的基礎
【Pytorch 深度學習筆記】搞懂什麼是深度學習以及 Pytorch 的基礎
哈囉大家好我是 LukeTseng,感謝您點進本篇筆記,該篇筆記主要配合讀本 《Deep Learning with pytorch》 進行學習,另外透過網路資料作為輔助。本系列筆記是我本人奠基深度學習基礎知識的開始,若文章有誤煩請各位指正,謝謝!
深度學習(Deep Learning, DL)是什麼?
深度學習(Deep Learning)是機器學習的一個分支,是一種以人工神經網路為架構、對資料進行表徵學習的演算法。比較通俗一點的說法是說,深度學習可以透過模仿人類大腦的神經網路,讓機器能像人腦一樣進行學習。
至於「深度」這個詞指的是在網路中使用了多層結構,這些多層結構能夠處理更複雜的特徵和模式。
機器學習 vs 深度學習
《Deep Learning with pytorch》這本書中提到深度學習的變革,以及為什麼需要深度學習。
過去機器學習使用的傳統方法高度依賴於特徵工程(feature engineering)這個技術,也就是人工輸入資料的轉換方式,以利於下游演算法產生正確結果。(以下 google 的網站可以讓你玩一下機器學習,玩完後就會知道這句話是什麼意思了:https://teachablemachine.withgoogle.com)
比如說要辨別出手寫的數字,像 0 跟 1,工程師會手動設計出一套過濾器(filters),用於估計圖像中的邊緣方向(direction of edges)。
邊緣方向是什麼呢?邊緣方向是一種用來區分圖像中不同形狀或結構的特徵。以便區分 1(通常是垂直或接近垂直的邊緣)和 0(包含封閉的圓形邊緣)。
在辨別手寫數字的例子呢,另個有用的手動設計特徵可能是計算封閉孔洞(enclosed holes)的數量,因為 0, 8 以及有圈的 2 等數字中都存在此類特徵,可以提高識別率。
最後就是訓練分類器(classifier),這些手動提取的特徵隨後會被饋送給一個 classifier,classifier 會根據這些特徵的分佈來預測正確的數字。
看到這裡呢,所以機器學習他基本上就是要純手動的去輸入資料、轉換特徵,那這樣子效率不是很低嗎?但其實機器學習可以在金融業做到數據分析,或是其它像推薦引擎、天氣預測等應用。
而深度學習則帶來了範式轉移(paradigm shift, 機器學習可稱為舊的範式, 深度學習則是新的範式),它能夠從原始數據中自動學習特徵。
一樣是區分 0, 1 手寫數字的例子,深度學習中的過濾器(filters)會在訓練過程中被迭代地提煉 (refined)。ummm… 也就是用 for 迴圈一直讓他去跑 training 的意思。
訓練過程會使用一個準則(criterion,即損失函數 Loss function),該函數提供一個數值分數來衡量模型輸出與參考數據(期望輸出)之間的差異。訓練的目標是透過逐步修改深度學習機器,讓分數越來越低,以此確保在對於訓練期間未見過的數據也能維持低分數。
深度學習可以根據範例去學習,這種 refined 是透過不斷讓機器去看範例圖像(如 0, 1 的數字照片)及其目標標籤對(pairs of examples and target labels)來實現的。
:::info
標籤對(labeled pairs)是指「輸入資料」和它對應的「正確答案」配對在一起的組合。在機器學習中,標籤(label)是指一個資料樣本的正確輸出或類別,也就是想要模型預測的目標變數。
:::
小結
| 機器學習 | 深度學習 | |
|---|---|---|
| 特徵提取 | 需要人工設計特徵工程 | 自動從原始數據學習特徵 |
| 人工介入 | 需要大量人工指導和調整 | 模型可自主判斷優化 |
| 處理數據類型 | 適合結構化數據 | 擅長非結構化數據(圖像、音訊、文本) |
| 硬體需求 | 相對較低 | 需要大量數據和算力 |
基本上可以把深度學習看成是機器學習的 Pro 版,但缺點就是需要龐大的 data 去做訓練才會提高準確率。
為什麼要用 Pytorch?
Pytorch 他是目前最流行的開源深度學習框架之一,因其易用性、靈活性和強大的功能而廣受歡迎。自 2019 年起,超過 75% 的國際學術論文都使用了 Pytorch,所以就可見 Pytorch 它的強大了。
另外 Pytorch 可以做到部分實時的執行跟測試,而非等待整個 code 跑完,這對於大型深度學習模型來說,完整執行可能需要很長一段時間。所以 Pytorch 是個很好去快速設計原型的平台,而且大幅加速了 debug 的流程。
在書中也提到 Pytorch 是基於 Python 去構建的,所以具有 Pythonic 的風格。說歸說 Pytorch 是基於 Python 去構建的東西,但其實底層還是由許多 C++ 跟 CUDA,因為考量到效能的關係,所以得讓這些程式碼在 GPU 上大規模執行。
總之 Pytorch 還有相當多的優點,僅列上述就已經足夠證明為何需要使用 Pytorch 了。
Pytorch 的基礎概念
Pytorch 的基礎概念主要是以下這五個東西所組成:Tensor、Autograd、nn.Module、Optimizers 和 Device。
Tensor(張量)

Image Source:https://www.newittrendzzz.com/post/understanding-tensors-in-pytorch-a-comprehensive-guide
Tensor 是 PyTorch 的資料結構,它是一種包含多個數值的數學物體,可以視為向量和矩陣的廣義化版本。tensor 支援多維陣列的運算,並可以在 CPU 或 GPU 上進行加速計算。
張量具有三個屬性:
- 維度(Dimensionality):0 維是純量、1 維是向量、2 維是矩陣、3 維以上是高維張量。
- 形狀(Shape):每個維度上的大小,例如 (3, 4) 表示 3 行 4 列。
- 資料型態(Dtype):如
torch.float32、torch.int64等。
以下是 pytorch 的範例(建議於 colab 或是 jupyter notebook 上面實作):
1 | import torch |
Output:
1 | torch.Size([2, 2]) |
tensor 跟 numpy 的 ndarray 蠻像、蠻類似的,但差別在於 tensor 可以在 GPU 上執行,而 numpy 只能在 CPU 上執行。
另外 pytorch 也可以直接從 numpy 陣列中創建 tensor:
1 | import torch |
Output:
1 | tensor([[1, 2], |
實際上建立一個 tensor 並不只有兩種形式,以下列出所有建立 tensor 的方法:
| methods | description | example code |
|---|---|---|
torch.tensor(data) | 從 Python 列表或 NumPy 陣列建立張量。 | x = torch.tensor([[1, 2], [3, 4]]) |
torch.zeros(size) | 建立一個全為 0 的張量。 | x = torch.zeros((2, 3)) |
torch.ones(size) | 建立一個全為 1 的張量。 | x = torch.ones((2, 3)) |
torch.empty(size) | 建立一個未初始化的張量。 | x = torch.empty((2, 3)) |
torch.rand(size) | 建立一個服從均勻分佈的隨機張量,值在 $[0, 1)$ 。 | x = torch.rand((2, 3)) |
torch.randn(size) | 建立一個服從常態分配的隨機張量,平均值為 0,標準差為 1。 | x = torch.randn((2, 3)) |
torch.arange(start, end, step) | 建立一個一維序列張量,類似 Python 的 range。 | x = torch.arange(0, 10, 2) |
torch.linspace(start, end, steps) | 建立一個在指定範圍內等間隔的序列張量。 | x = torch.linspace(0, 1, 5) |
torch.eye(size) | 建立一個單位矩陣(對角線為 1,其他為 0)。 | x = torch.eye(3) |
torch.from_numpy(ndarray) | 將 NumPy 陣列轉換為張量。 | x = torch.from_numpy(np.array([1, 2, 3])) |
table from PyTorch 张量(Tensor) | 菜鸟教程
Tensor 的屬性
| 屬性名稱 | 說明 | 回傳型態 | 範例 |
|---|---|---|---|
| shape 或 size() | 張量的維度大小 | torch.Size | torch.Size([^11][^12]) |
| dtype | 數據類型 | torch.dtype | torch.float32, torch.int64 |
| device | 儲存設備(CPU/GPU) | torch.device | cpu, cuda:0 |
| requires_grad | 是否需要計算梯度 | bool | True 或 False |
| ndim | 維度數量 | int | 2(表示二維張量) |
| numel() | 元素總數 | int | 12(3×4 矩陣) |
| data | 底層數據(不追蹤梯度) | Tensor | 原始數據張量 |
| grad | 梯度值 | Tensor 或 None | 反向傳播後的梯度 |
| layout | 內存布局類型 | torch.layout | torch.strided |
| T | 轉置(2D 張量) | Tensor | 行列互換的張量 |
| is_cuda | 是否在 GPU 上 | bool | True 或 False |
| dim() | 獲取張量的維度數 | int | tensor.dim() |
| item() | 取得單元素張量的值 | number | tensor.item() |
| is_contiguous() | 檢查張量是否連續儲存 | bool | tensor.is_contiguous() |
table from PyTorch 张量(Tensor) | 菜鸟教程
接下來的範例程式碼都會在 google colab 上執行。
shape or size():
1 | import torch |
1 | torch.Size([2, 3]) |
device:
1 | x = torch.tensor([1, 2, 3]) |
1 | cpu |
requires_grad:
1 | x = torch.tensor([1.0, 2.0, 3.0], requires_grad = True) |
1 | True |
requires_grad 的作用是讓 backward 可以決定了該張量是否要加入自動微分(Autograd)機制。
當 tensor.requires_grad = True 時,代表該 tensor 在向前運算(forward pass)時,其所有用於產生它的運算都會被記錄下來,之後呼叫 tensor.backward() 時,就會自動計算該張量關於其葉張量(leaf tensor)的梯度(gradient)值。
ndim:
1 | x = torch.tensor([1, 2, 3]) |
1 | 1 |
1 表示 1 維張量,2 表示 2 維張量,以此類推。
numel():
1 | x = torch.tensor([[1, 2, 3], [4, 5, 6]]) |
1 | 6 |
這個函數主要用來表示裡面有多少個元素,輸出第一個的 6 就表示 x 裡面有 6 個元素。
data:
1 | x = torch.tensor([1.0, 2.0, 3.0], requires_grad=True) |
1 | tensor([2., 4., 6.]) |
grad:
1 | x = torch.tensor([1.0, 2.0, 3.0], requires_grad=True) |
1 | None |
layout:
1 | x = torch.tensor([[1, 2], [3, 4]]) |
1 | torch.strided |
torch.strided 為預設的密集儲存格式,若遇到稀疏 tensor 會有不同的 layout。
T:
1 | x = torch.tensor([[1, 2, 3], [4, 5, 6]]) |
1 | tensor([[1, 4], |
T 只適用於 2D 張量,對於高維張量需用 permute() 或 transpose() 函數。
is_cuda:
1 | x = torch.tensor([1, 2, 3]) |
1 | False |
dim():
1 | x = torch.tensor([1, 2, 3]) |
1 | 1 |
ndim 跟 dim() 使用上是沒什麼差別的,差別在於 ndim 是比較新的版本才出來的,他是屬於屬性的部分,而非方法。
item():
1 | x = torch.tensor([42]) |
1 | 42 |
is_contiguous():
1 | x = torch.tensor([[1, 2, 3], [4, 5, 6]]) |
Tensor 的操作
數學運算操作:
| 操作 | 功能說明 | 語法範例 | 說明 |
|---|---|---|---|
| 加法 | 元素相加 | x + y 或 torch.add(x, y) | 對應位置相加 |
| 減法 | 元素相減 | x - y 或 torch.sub(x, y) | 對應位置相減 |
| 乘法(元素) | 元素相乘 | x * y 或 torch.mul(x, y) | Hadamard 積 |
| 除法 | 元素相除 | x / y 或 torch.div(x, y) | 對應位置相除 |
| 矩陣乘法 | 矩陣相乘 | x @ y 或 torch.mm(x, y) | 線性代數的矩陣乘法 |
| matmul() | 多維矩陣乘法 | torch.matmul(x, y) | 支援批次矩陣乘法 |
| pow() | 次方運算 | x.pow(2) 或 x ** 2 | 每個元素平方 |
| sqrt() | 平方根 | torch.sqrt(x) | 每個元素開根號 |
| exp() | 指數函數 | torch.exp(x) | $e^x$ |
| log() | 自然對數 | torch.log(x) | $\ln(x)$ |
| abs() | 絕對值 | torch.abs(x) | 每個元素取絕對值 |
| sin/cos/tan | 三角函數 | torch.sin(x) | 三角運算 |
統計操作:
| 操作 | 功能說明 | 語法範例 | 說明 |
|---|---|---|---|
| sum() | 求和 | x.sum() 或 x.sum(dim=0) | 可指定維度 |
| mean() | 平均值 | x.mean() 或 x.mean(dim=1) | 需要浮點數類型 |
| max() | 最大值 | x.max() 或 x.max(dim=0) | 回傳值和索引 |
| min() | 最小值 | x.min() | 最小元素 |
| argmax() | 最大值索引 | x.argmax(dim=1) | 回傳最大值位置 |
| argmin() | 最小值索引 | x.argmin() | 回傳最小值位置 |
| std() | 標準差 | x.std() | 衡量數據分散程度 |
| var() | 變異數 | x.var() | 標準差的平方 |
| median() | 中位數 | torch.median(x) | 中間值 |
比較操作:
| 操作 | 功能說明 | 語法範例 | 返回結果 |
|---|---|---|---|
| 大於 | 元素比較 | x > y 或 torch.gt(x, y) | 布林張量 |
| 小於 | 元素比較 | x < y 或 torch.lt(x, y) | 布林張量 |
| 等於 | 元素比較 | x == y 或 torch.eq(x, y) | 布林張量 |
| 大於等於 | 元素比較 | x >= y 或 torch.ge(x, y) | 布林張量 |
| 小於等於 | 元素比較 | x <= y 或 torch.le(x, y) | 布林張量 |
| equal() | 完全相等 | torch.equal(x, y) | 單一布林值 |
| allclose() | 近似相等 | torch.allclose(x, y) | 考慮浮點誤差 |
形狀變換操作:
| 操作 | 功能說明 | 語法範例 | 實際例子 |
|---|---|---|---|
| reshape() | 改變形狀(複製數據) | x.reshape(3, 4) | 把 12 個元素重排成 3×4 |
| view() | 改變形狀(共享記憶體) | x.view(2, -1) | -1 表示自動計算 |
| squeeze() | 移除大小為 1 的維度 | x.squeeze() | (1, 3, 1, 4) → (3, 4) |
| unsqueeze() | 增加維度 | x.unsqueeze(0) | (3, 4) → (1, 3, 4) |
| transpose() | 交換兩個維度 | x.transpose(0, 1) | 交換第 0 和第 1 維 |
| permute() | 重新排列所有維度 | x.permute(2, 0, 1) | 將維度重新排序 |
| flatten() | 展平為一維 | x.flatten() | 所有元素變成一維向量 |
| expand() | 擴展張量(不複製) | x.expand(3, -1) | 廣播機制擴展 |
| repeat() | 重複張量(複製) | x.repeat(2, 3) | 沿各維度重複 |
在 tensor 上做 GPU 加速
在前面的範例有稍微介紹到 GPU 加速的部分,這邊額外講解。
要在做 GPU 加速之前,需要透過函數 torch.cuda.is_available() 確認是否有可用的 cuda GPU。
torch.cuda.device_count() 可查看 GPU 數量。
torch.cuda.get_device_name(0)查看 GPU 名稱。
做 GPU 加速的第一個方式是用 .cuda() 方法:
1 | x = torch.tensor([1.0, 2.0, 3.0]) |
1 | cpu |
第二個方式比較推薦用,是使用 .to(device) 方法:
1 | # 定義設備(自動選擇 GPU 或 CPU) |
最後是比較 CPU 與 GPU 間的速度的小範例:
1 | import time |
1 | CPU 時間: 24.7626 秒 |
所以知道為什麼要用 GPU 了吧 XD,尤其日後當層數與參數量大起來的時候,就特別需要 GPU 做運算了。
總結
PyTorch 的五大基礎概念
Tensor(張量)
PyTorch 的核心資料結構,為多維陣列的泛化形式(類似 NumPy ndarray),可在 CPU 或 GPU 上運算。
- 0 維 → 純量(scalar)
- 1 維 → 向量(vector)
- 2 維 → 矩陣(matrix)
- 3 維以上 → 高維張量
Autograd(自動微分)
透過 requires_grad=True 追蹤張量的運算過程,反向傳播時自動計算梯度(gradient)。
nn.Module(神經網路模組)
建構深度學習模型的基底類別,可封裝多層結構(如 CNN、RNN)。
Optimizers(優化器)
用於更新模型參數(如 SGD、Adam),以降低損失函數。
Device(裝置)
控制資料與模型運算位置(cpu 或 cuda)。
Tensor 操作
- 建立張量的方法
如 torch.tensor()、torch.zeros()、torch.ones()、torch.rand()、torch.eye() 等,支援從列表或 NumPy 陣列建立。
- 張量屬性
- shape / size():張量形狀
- dtype:資料型態
- device:儲存裝置
- requires_grad:是否參與梯度計算
- grad:梯度值
- is_cuda:是否位於 GPU
- 常用運算
- 數學運算(加減乘除、平方、log、sin 等)、
- 統計運算(sum、mean、std、var 等)、
- 比較運算(==, >, torch.eq() 等)。
- 張量形狀操作
reshape()、view()、squeeze()、unsqueeze()、transpose()、permute()、flatten()、expand()、repeat() 等。
GPU 加速運算
在深度學習中,GPU 能顯著加速矩陣與張量運算。
主要有兩種方式將資料移動到 GPU:
.cuda():直接將 tensor 移到 GPU。.to(device):推薦用法,可自動偵測 CPU/GPU。
參考資料
書籍《Deep Learning with PyTorch》。
PyTorch documentation — PyTorch 2.9 documentation
关于tensor.dim() 和 tensor.ndim-CSDN博客
[PyTroch系列-10]:PyTorch基础 - 张量Tensor元素的比较运算_51CTO博客_pytorch中的张量
numpy & pytotch tensor 常用操作对比_to(dtype).clone().detach().contiguous()-CSDN博客
cuda pytorch 加速 pytorch怎么用gpu加速_mob6454cc75556b的技术博客_51CTO博客




