---
# System prepended metadata

title: 【Pytorch 深度學習筆記】神經網路的基礎知識與建立神經網路
tags: [python, 程式設計, DL, Python, 深度學習, 程式語言, AI]

---

# 【Pytorch 深度學習筆記】神經網路的基礎知識與建立神經網路

[TOC]

哈囉大家好我是 LukeTseng，感謝您點進本篇筆記，該篇筆記主要配合讀本 《Deep Learning with pytorch》 進行學習，另外透過網路資料作為輔助。本系列筆記是我本人奠基深度學習基礎知識的開始，若文章有誤煩請各位指正，謝謝！

## 神經網路（Neural Network, NN）是什麼？

> 神經網路（Neural Network，簡稱 NN），也稱為類神經網路或人工神經網路（Artificial Neural Network, ANN），是一種模仿人類大腦神經系統運作的計算模型，透過類似「人腦分層結構」中的互連節點或神經元（neuron），來學習、分析並預測各類數據。它使用數學模型來模擬大腦神經元的運作，由大量神經元組成，經由外部輸入資料後，神經網路會調整內部參數來獲得學習結果。

在這邊把神經網路稱作是類神經網路會比較好一些，因為在 AI 的世界中，所建構的神經網路其實是一種非線性的統計模型，他是一個去模仿人類神經網路的東西，所以叫做類神經網路比較沒啥毛病 XD。

**神經網路最大的功用是從資料中自動學習，並做到預測這件事。**

正好神經網路也是深度學習當中最核心的概念之一。

### 神經元（neuron）

![image](https://hackmd.io/_uploads/HyGqkL4JWg.png)

Image Source：[The general structure of MLP neural network architecture | Download Scientific Diagram](https://www.researchgate.net/figure/The-general-structure-of-MLP-neural-network-architecture_fig4_352418597)

神經元（neuron）是建構類神經網路（NN）的基本單元，具體示意圖如上所示，它接收輸入訊號（Input），透過加權（Weights）求和後與偏移量（bias）相加，然後透過激活函數（Activation Function）處理以產生輸出。神經元的**權重**和**偏移量**是 NN 在學習過程中需要調整的參數。

* 輸入（Input）：輸入是 NN 的起始點，可以是特徵數據，如圖像的像素值或文字的詞向量。
* 輸出（Output）：輸出是 NN 的終點，表示模型的預測結果，如分類任務中的類別標籤。

神經元的輸出基本上可以看作以下的數學式： $$Output = \sum_{j}w_jx_j+Bias$$

可以把這個概念想像在做決策時，會考慮多個因素（輸入），而每個因素的必要性、優先性肯定會不同（權重），最後綜合判斷得出結論（輸出）。

而這種形式也稱為 Perceptron（感知器），是一種二元線性分類器。

### 層（Layer）

![image](https://hackmd.io/_uploads/HyKGMDEkZx.png)

Image Source：[Artificial Neural Networks and its Applications - GeeksforGeeks](https://www.geeksforgeeks.org/artificial-intelligence/artificial-neural-networks-and-its-applications/)

NN 主要有三個組成部分：

* 輸入層（Input Layer）：接收原始數據的地方。像在影像辨識的應用中，可以輸入圖像。
* 隱藏層（Hidden Layer）：一個或多個中間層，可有多個隱藏層，負責特徵提取和對輸入數據處理。
* 輸出層（Output Layer）：產生最終預測結果。

如果隱藏層越多，NN 能學習和理解的模式就越複雜，每個隱藏層會將資料轉換成更抽象的資訊。像是一張貓的圖片，假設有三個隱藏層，那這三個隱藏層可以分別對圖像做切割，比如說擷取貓的耳朵的特徵、貓的眼睛周圍特徵、貓的嘴部附近特徵。

輸出層產生最終預測結果，也就是經過圖像處理過後，會判別一張圖片是不是貓。

### 激活函數（Activation Function）

> 激活函數（Activation Function），也稱為啟動函數、激勵函數或活化函數，是神經網路中每個神經元用來將輸入轉換為輸出的數學函數。它的核心任務是為神經網路引入非線性能力，幫助模型理解世界的複雜性。

如果一個神經網路可以用線性運算去表示，那還要神經網路幹嘛對吧，因為無論去堆疊多少層網路，最終仍等同於一個單層的線性模型。

所以需要激活函數來幫助神經網路做非線性轉換，最終得到輸出層。

神經網路中每一層的運作可以用這個公式表示： $$\sigma(Wx+b)$$ 

當中 $\sigma$ 是激活函數，而 $(Wx+b)$ 是線性運算（加權求和加上偏移量）。

常見的激活函數有以下這些：

1. ReLU（Rectified Linear Unit）目前最常用的激活函數。
2. Sigmoid 是一種平滑的 S 型曲線函數。
3. Tanh（雙曲正切）。
4. Softmax。

### 前饋神經網路（Feedforward Neural Network, FNN）

![image](https://hackmd.io/_uploads/SJe0aw4JWx.png)

Image Source：[Feedforward Neural Network - GeeksforGeeks](https://www.geeksforgeeks.org/nlp/feedforward-neural-network/)

接下來介紹幾個比較重要且基礎的 NN，首先第一個就是 FNN。

FNN 是 NN 家族裡面的基本單元。它的特點是資訊只能單向流動，從 Input Layer 開始前向移動，通過 Hidden Layer（如果有的話），最終到達 Output Layer，在整個 NN 中沒有循環或迴路。

FNN 有三層架構：

- 輸入層（Input Layer）：輸入層由接收輸入資料的神經元組成。輸入層中的每個神經元（如上圖的圓圈圈、代表一個節點）代表輸入資料的一個特徵。
- 隱藏層（Hidden Layer）：可以有一個或多個以上的隱藏層，用於捕獲資料的非線性特徵。每個隱藏層由多個神經元組成，每個神經元透過激活函數進行非線性轉換。
- 輸出層（Output Layer）：產生預測結果。

FNN 通常被拿來做一些基礎、簡單的任務，比如說像分類、迴歸、模式識別等等。

FNN 的目的是透過構建一個多層次的神經網路結構來學習和逼近複雜的函數或映射關係。網路結構的單向流動使 FNN 可處理複雜的輸入數據，並透過學習來逼近目標函數。

### 循環神經網路（Recurrent Neural Network, RNN）

![image](https://hackmd.io/_uploads/S124idVkWl.png)

Image Source：[Applications and Enhancement of Document-Based Sentiment Analysis in Deep learning Methods: Systematic Literature Review - ScienceDirect](https://www.sciencedirect.com/science/article/pii/S2667305322000308)

> 循環神經網路（Recurrent Neural Network, RNN），是一種專門用來處理**序列數據**的神經網路。它最大的特點是擁有「記憶能力」，能夠記住並運用先前的輸入內容，在短期記憶元件中進行未來預測。

RNN 由三個主要部分組成：

* 輸入層（Input Layer）：接收序列數據的地方。
* 隱藏層（Hidden Layer）：負責處理數據並保存記憶。
* 輸出層（Output Layer）：產生預測結果。

RNN 的輸入不是單一個向量，而是一整個序列如 $X = [x_0, x_1, \cdots, x_{t-1}, x_t, x_{t+1}, \cdots,x_T]$ 。

以語言模型（Language Model）來說，每個 $x_t$ 代表一個詞向量（Word Embedding），一整個序列就代表一句話。不過這又是 NLP（自然語言處理）的領域了。

RNN 最重要的特性是循環機制（Recurrent Mechanism）。神經網路透過讀取某個時間（狀態）的輸入 $x_t$ ，然後輸出一個值 $h_t$ ，這個循環可以使得訊息從當前時間步傳遞到下一時間步。

#### RNN 與傳統神經網路的差別

傳統神經網路（如 FNN）從輸入層到隱藏層再到輸出層，層與層間是全連接的，但每層之間的節點在時間上是沒有任何連接的，所以這種神經網路在很多問題上是比較沒有辦法解決的。

如要預測句子的下一個單字是什麼，一般需要用到前面的單字，因為一個句子中前後單字並不是獨立的。相較於 FNN 模型，RNN 可以考慮到詞的先後順序對預測的影響。

這也就是 RNN 在處理序列能力上的優勢。

當然 RNN 的優點不只這個，還有非常多種，篇幅因素所以不講了。

#### RNN 的應用

1. 自然語言處理（NLP）：語音辨識、機器翻譯、文字生成等等。
2. 時間序列預測：預測天氣、股票價格等。

### 卷積神經網路（Convolutional Neural Network, CNN）

![image](https://hackmd.io/_uploads/ByDtLtE1bg.png)

Image Source：[What is Convolutional Neural Network — CNN (Deep Learning) | by Kh. Nafizul Haque | Medium](https://nafizshahriar.medium.com/what-is-convolutional-neural-network-cnn-deep-learning-b3921bdd82d5)

> CNN 是深度學習領域中最具代表性的模型之一，主要用於處理視覺相關的任務，例如圖像辨識、物體檢測和影像分類。CNN 是一種前饋神經網路（FNN），其靈感來自於動物視覺皮層組織的神經連接方式，單個神經元只對有限區域內的刺激作出反應，不同神經元的感知區域相互重疊從而覆蓋整個視野。

傳統的影像辨識中，會導致計算的成本大幅增加，為了解決這個問題，CNN 就出現了。

CNN 的運作原理大致上如下：

假設要辨識貓的圖片，CNN 會先把貓拆成不同部位（如頭、身體、手），接著再針對個別部位拆成更細的項目（如頭部再拆成眼睛、鼻子、耳朵），等細分得差不多之後，機器會開始分析各個部位特徵，就會慢慢建立起貓的概念，然後就能辨識貓這個動物了。

然後 CNN 主要由以下這三層架構所組成：

- 卷積層（Convolutional Layer）：使用一組特別的權重和過濾器（filter），使得 CNN 可以從輸入數據中提取特徵。卷積層會包含很多層，每一層會負責提取不同層次的特徵，然後透過過濾器掃描影像，每次找到指定特徵時就會記錄下來，最終會產生一組特徵圖。
- 池化層（Pooling Layer）：作用為降低資料維度，減少計算量，同時保留重要的特徵資訊。這一結構可使 CNN 能利用輸入資料的二維結構。
- 全連接層（Fully Connected Layer）：在卷積層跟池化層之後，CNN 的頂端是全連接層，對應經典的神經網路結構。全連接層負責將提取的特徵做最終的分類或預測。

以上這三種 NN：FNN、RNN、CNN 是在 NN 領域當中算是比較基礎的 NN，阿然後就簡單介紹就好了，因為裡面的技術細節實在是有點複雜，本系列主題主要還是圍繞在利用 Pytorch 學習並實現這些 NN。

## 用 Pytorch 建構第一個神經網路

在建構 NN 之前呢，先匯入以下的模組：

```python=
import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import DataLoader, TensorDataset
```

* `torch.nn`：建構 NN 的工具。
* `torch.optim`：優化器（用於訓練）。
* `DataLoader`：載入數據的工具。

在 PyTorch 中，所有神經網路都必須繼承 `nn.Module` 這個基礎類別。

而在自己的 NN 當中，需要撰寫兩個東西：

* `__init__` 方法：定義神經網路有哪些層。
* `forward` 方法：定義資料如何通過這些層。

如下範例：

```python=
class MyFirstNN(nn.Module):
    def __init__(self):
        super(MyFirstNN, self).__init__()  # 呼叫父類的 constructor
        
        # 定義 NN Layers
        self.layer1 = nn.Linear(10, 64)    # 輸入層 -> 隱藏層1 (10維 -> 64維)
        self.layer2 = nn.Linear(64, 32)    # 隱藏層1 -> 隱藏層2 (64維 -> 32維)
        self.layer3 = nn.Linear(32, 2)     # 隱藏層2 -> 輸出層 (32維 -> 2維)
        
    def forward(self, x):
        # 定義前向傳播：資料如何流經網路
        x = torch.relu(self.layer1(x))     # 通過第一層 + ReLU激活
        x = torch.relu(self.layer2(x))     # 通過第二層 + ReLU激活
        x = self.layer3(x)                 # 通過輸出層（不加激活函數）
        return x
```

定義好類別後，之後就可以來建立他的實例了：

```python=
model = MyFirstNN()

print(model)
```

打印出來的結果長這樣：

```
MyFirstNN(
  (layer1): Linear(in_features=10, out_features=64, bias=True)
  (layer2): Linear(in_features=64, out_features=32, bias=True)
  (layer3): Linear(in_features=32, out_features=2, bias=True)
)
```

MyFirstNN 是模型類別名稱，也就是 NN 叫做 MyFirstNN。

接下來三行分別代表模型的三層結構，每層都是 `Linear` （線性層 / 全連接層）。

而 `layer1`、`layer2`、`layer3` 是在建構子 `__init__` 當中定義的層的名字。

`in_features` 表示輸入特徵數量，像 layer1 會接收 10 個輸入。

`out_features` 表示輸出特徵數量，像 layer1 這層會產生 64 個輸出。

`bias` 表示偏移量，像是每個神經元的基準值，如果輸入為 0，神經元也能有一個初始輸出。

然後來準備一些數據，這邊用隨機生成的亂數當作訓練數據（基於學習用途）：

```python=
x_train = torch.randn(100, 10) # 100筆樣本，每筆10個特徵
y_train = torch.randint(0, 2, (100,)) # 100個標籤（0或1）

# 創建數據集和數據載入器
dataset = TensorDataset(x_train, y_train) 
dataloader = DataLoader(dataset, batch_size=16, shuffle=True)
```

當中 `DataLoader` 的 `batch_size` 表示批次大小，也就是每次訓練的時候，模型一次會處理多少筆資料，而 `batch_size` 越大，也就代表你需要更多的記憶體去處理數據。對於較大的 `batch_size` 來說的話，則可以用到 GPU 平行運算的能力去加快訓練速度，但也會吃到顯存（顯示卡記憶體）。

而另一個參數 `shuffle=True` 表示在每個 epoch（訓練週期）開始時，會隨機打亂資料的順序。

這樣做的原因是為了避免順序偏差跟過擬合的情形發生，前者的資料若有經過特定排序，則機器很可能會學到錯誤規律，而後者則為隨機打亂可以讓模型看到更多樣化的資料組合，避免過擬合特定的資料順序。

那這邊過擬合（overfitting）的意思是機器學習模型在訓練數據上表現得非常好，但在處理未見過的測試數據或新數據時表現不佳的現象。

簡言之，就是模型學得太仔細，把訓練數據中的細節、噪聲甚至巧合都當成規律來學習，導致無法很好地泛化到新數據。或是想像成考試刷題猛刷狂刷，就連答案是什麼、還有他的順序都背下來了，結果最後卻考不好，因為沒有真正去了解一個知識點過。

接下來定義損失函數（Loss Function）跟優化器（Optimizer）：

```python=
# 定義損失函數（交叉熵適合分類問題）
loss_fn = nn.CrossEntropyLoss()

# 定義優化器（Adam 是常用的優化器）
optimizer = optim.Adam(model.parameters(), lr=0.001) # lr 代表學習率
```

:::info
損失函數（Loss）是用來衡量模型預測與真實值之間的差異或誤差的數學函數。會告訴模型說你預測的值有多糟，數值越小代表預測越準確。
:::

損失函數有相當多種，其中交叉熵損失（CrossEntropyLoss）是最常用於分類問題的損失函數。衡量模型預測的機率分布與實際標籤之間的相似度，是這次建構神經網路會用到的 Loss Function。

:::info
優化器（Optimizer）是用來調整模型參數以減少損失的演算法。會根據損失函數計算出的梯度（gradient），決定如何更新權重和偏移量。
:::

再來設計訓練模型的迴圈：

```python=
# 設定訓練參數
num_epochs = 10

# 開始訓練
for epoch in range(num_epochs):
    model.train()  # 設定為訓練模式
    total_loss = 0
    
    for batch_X, batch_y in dataloader:
        # 1. 前向傳播：計算預測值
        predictions = model(batch_X)
        
        # 2. 計算損失
        loss = loss_fn(predictions, batch_y)
        
        # 3. 反向傳播前先清空梯度
        optimizer.zero_grad()
        
        # 4. 反向傳播：計算梯度
        loss.backward()
        
        # 5. 更新參數
        optimizer.step()
        
        total_loss += loss.item()
    
    # 每個 epoch 結束後顯示平均損失
    avg_loss = total_loss / len(dataloader)
    print(f'Epoch [{epoch+1}/{num_epochs}], Loss: {avg_loss:.4f}')
```

最後就可以利用訓練完的模型，來預測新數據：

```python=
# 切換到評估模式（關閉 dropout 等訓練專用功能）
model.eval()

# 測試數據（可自行修改）
X_test = torch.randn(5, 10)

# 進行預測
with torch.no_grad():
    predictions = model(X_test)
    predicted_classes = torch.argmax(predictions, dim=1)
    
print("預測結果:", predicted_classes)
```

其中將寫好完整的程式碼執行下來後，可能會輸出以下這些東西：

```
Epoch [1/10], Loss: 0.6959
Epoch [2/10], Loss: 0.6787
Epoch [3/10], Loss: 0.6813
Epoch [4/10], Loss: 0.6818
Epoch [5/10], Loss: 0.6620
Epoch [6/10], Loss: 0.6574
Epoch [7/10], Loss: 0.6434
Epoch [8/10], Loss: 0.6450
Epoch [9/10], Loss: 0.6253
Epoch [10/10], Loss: 0.6177

預測結果: tensor([1, 0, 1, 1, 0])
```

在訓練流程部分就不再多細講，因為不是今天主要的主題。

先到這裡了，因為我的小腦袋瓜快承受不住了XD。

## 參考資料

[神經網路是什麼？神經網路原理、7 大模型及應用解析 | Solwen AI](https://solwen.ai/posts/what-is-neural-network)

[神經網路（Neural Networks）：模仿人類大腦運作的數學模型 - iT 邦幫忙::一起幫忙解決難題，拯救 IT 人的一天](https://ithelp.ithome.com.tw/articles/10356829)

[高中資訊教師黃建庭的教學網站 - 神經網路(Neural Network , NN)](https://sites.google.com/view/zsgititit/home/ji-qi-xue-xi/%E7%A5%9E%E7%B6%93%E7%B6%B2%E8%B7%AFneural-network-nn)

[AI 入門：21 深度學習的主力 — 神經網路 |PTSC北祥科技服務股份有限公司](https://www.pershing.com.tw/ai-%E5%85%A5%E9%96%80%EF%BC%9A21-%E6%B7%B1%E5%BA%A6%E5%AD%B8%E7%BF%92%E7%9A%84%E4%B8%BB%E5%8A%9B-%E7%A5%9E%E7%B6%93%E7%B6%B2%E8%B7%AF/)

[Day 16 - 神經網路的種類 - iT 邦幫忙::一起幫忙解決難題，拯救 IT 人的一天](https://ithelp.ithome.com.tw/articles/10344073)

[前饋神經網路 - 維基百科，自由的百科全書](https://zh.wikipedia.org/zh-tw/%E5%89%8D%E9%A6%88%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C)

[[DeepLearning]各種神經網路概要－Programmer Style｜痞客邦](https://gaexp251546.pixnet.net/blog/post/66501711)

[前馈神经网络（Feedforward neural network）-CSDN博客](https://blog.csdn.net/zhangzzqliumin/article/details/126508775)

[Feedforward Neural Network - GeeksforGeeks](https://www.geeksforgeeks.org/nlp/feedforward-neural-network/)

[【AI60問】Q43什麼是循環神經網路 Recurrent Neural Networks, RNN？ | 緯育TibaMe Blog](https://blog.tibame.com/?p=19075)

[【RNN】深入浅出讲解循环神经网络（介绍、原理）-CSDN博客](https://blog.csdn.net/kevinjin2011/article/details/125069293)

[循環神經網路 - 維基百科，自由的百科全書](https://zh.wikipedia.org/zh-tw/%E5%BE%AA%E7%8E%AF%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C)

[Pytorch 筆記 : 建構神經網路、訓練 - HackMD](https://hackmd.io/@kk6333/Hy9lmVnZi)

[卷積神經網路 - 維基百科，自由的百科全書](https://zh.wikipedia.org/zh-tw/%E5%8D%B7%E7%A7%AF%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C)

[CNN 神經網路介紹：卷積神經網路原理,架構,應用案例懶人包](https://www.pcschool.com.tw/blog/it/what-is-about-cnn)

[卷積神經網路 (Convolutional Neural , CNN) - HackMD](https://hackmd.io/@allen108108/rkn-oVGA4)

