# [DL] CNN Model 結構
* CNN Model 結構
* Conv2D vs. Conv2DTranspose
###### tags: `Deep Learning`
Ref:[卷積神經網路 (Convolutional Neural , CNN)](https://hackmd.io/@allen108108/rkn-oVGA4)

 
CNN 是普遍用於電腦視覺的深度學習模型
結構主要分成幾個部分 : 卷積層 ( Convolution layer )、池化層 (Pooling layer) 、平坦層(Flatten)、密集層 (Dense layer)
辨識蛇的特徵,我們會由以下特徵判斷(細長身體、鱗片、利牙、彎身),Convolution Layer 就是一種特徵提取的工具,去學習蛇的圖片中有什麼特徵
- 透過**卷積層**學習到一張圖片的局部小圖(細長特徵、彎曲特徵),第二層卷機會基於第一層卷積學的到特徵,來學習更高階的結構(舌頭),使 CNN 有效地學習到更抽象的視覺概念
- 透過**池化層**(資訊壓縮的方法),對 feature map 重點挑選,壓縮圖片長寬(降低維度)並保留重要特徵
- 透過**平坦層**,轉成一維向量
- 透過**密集層**,用來進行分類
```python=1
# 輸入彩色影像大小 = 100(長)x100(寬)x3(Channel數量=RGB)
model.add(Input(shape=(100, 100, 3)))
## 經過第一層卷積
# filters=16, kernel size=3x3
# filter 有16個(此層的寬度,同等於 channel 數),每個filter長寬為3*3
# 輸出:16張feature map,輸出的Channel數=16
model.add(Conv2D(filters=16, kernel_size=3, activation='relu')
## 經過第二層卷積
# filters=17, kernel size=3x3
# filter 有 7個(此層的寬度,同等於 channel 數),每個filter長寬為3*3
# 輸出:17張feature map,輸出的Channel數=17
model.add(Conv2D(filters=17, kernel_size=3, activation='relu'))
model.add(MaxPool2D(pool_size=(2, 2))
model2.add(Flatten())
# Dense=128,代表前面的東西經過這層維度轉成 128,output有 128 個數值
model2.add(Dense(128, activation='relu'))
# 進行分類,因為是轉成3類,壓成和我們labels一樣的維度3,所以最後一層神經元為3 , 此3類機率值總和為1
model2.add(Dense(3, activation='softmax'))
```
```python=1
Layer (type) Output Shape Param #
=================================================================
input_1 (InputLayer) [(None, 100, 100, 3)] 0
_________________________________________________________________
conv2d (Conv2D) (None, 98, 98, 16) 448
_________________________________________________________________
conv2d_1 (Conv2D) (None, 96, 96, 17) 2465
_________________________________________________________________
max_pooling2d (MaxPooling2D) (None, 48, 48, 17) 0
______________________________________________________________
flatten (Flatten) (None, 5184) 0
_________________________________________________________________
dense (Dense) (None, 128) 663680
_________________________________________________________________
dense_1 (Dense) (None, 3) 387
=================================================================
```
## :sandwich: Convolution Layer 卷積層
:::warning
**輸出**:Feature Map
**作用**:特徵提取
**流程**:透過 filter 在輸入圖片上滑動進行卷積運算,對圖像做特徵提取, ~~並藉由步長(Strides)與填充 (Padding)控制圖像的長寬,~~ 卷積後得到的圖片我們稱之為 feature map,若有 3 個 filter,認為這個圖像上有 3 種底層紋理模式,也就是我們用 3 個基礎模式就可描繪出一副圖像

:::
### (一)**特徵提取** 3x3 Conv
#### Image(左下):輸入影像 (batch × height × width × channel)
`model.add(Input(shape=(100, 100, 3)))`
1. 一張彩色影像大小 = 100(長)x100(寬)x3(Channel數量=RGB)
2. 若輸入 10 筆資料,每個資料都是 10*10 的彩色圖片 = (10, 100, 100, 3)
#### filter(左上) = (height × width)
1. `stride=1`:filter 卷積移動時的步伐長度
2. `filters=16, kernel size=3x3`
filter 有 16 個,每個 filter 長寬為 3*3,輸出 16 張 feature map,輸出的 Channel 數=16
3. 每一個 channel 會對應著 filter 的深度做卷積,若輸入圖片 Channel=3,則卷積的 filter 其 Channel=3,代表輸入的一張圖片有 3 層 RGB,也須對 3 層 filter 做運算
> 第一層 output 的 Channel 數:輸入圖片的 Channel 數(3)
> 第二層 output 的 Channel 數(第一次卷積): 設定的 filter 數量決定(2|16)
> 第三層 output 的 Channel 數(第二次卷積): 設定的 filter 數量決定(3|17)
:::danger
:question: Channel 是什麼
* **Channel 數**:模型寬度,同在淺層,讓單層卷積層學習到更多元的特徵,例如不同形狀紋理
Channels 數同等於 filter 數,經過多少 filter 就是經過多少特徵提取,有多少個 Channels 就代表提取了多少種特徵
* **Layer 數**:模型深度,由淺層逐漸到深層,學習更抽象的特徵,例如第一層學習到了邊緣,第二層學習到了簡單的形狀,第三層開始學習到了目標的形狀
目前的研究是模型效能對 Layer 數(深度)更加敏感,而調整 Channel數(寬度)更加有利於提升模型性能,都很重要,許多研究也表明加寬網路較易訓練(對 GPU 更友好),我們可以優先調整寬度。
:::
::: spoiler 圖片

:::
#### feature map(右):572x572 → 570x570 → 569x569
1. 經過 Convolution 層過後的 feature map 會變得比原尺寸小
2. 除了 Input image 不稱為 Feature map 外,中間產生的 image 我們都稱之為Feature map,因為他們是為了「該任務所應該**產生對應的特徵資料( representations of data )**」
3. 深度學習過程就是在**學資料的特性**,所以中間出來的結果都是特徵資料,在影像因為是2D,所以用 Feature map 來稱呼。
4. feature map = 一個tensor
3x3 Conv = 一個 3x3 的tensor (feature map 的長寬=3)

### (二)Relu:引入非線性
* 使用原因:使用 Relu 函數去掉負值,更能淬煉出物體的形狀
* ReLU只要輸入 <0 就不響應,等於神經元沒有繳活,作用類似 Dropout 增加多樣性,可以防止 Overfitting
* 「y大於0我就保留,y小於0我就丟掉」
* ReLU是訓練時訓練所有神經元,但訓練完後死了一部份的神經元,而Dropout是訓練時每次使用不同部份神經元。
1. 克服梯度消失
2. 避免過度擬合(overfit)

將負數皆歸0,正數維持原樣
## :sandwich: Pooling Layer 池化層
:::warning
**輸出**:Feature Map
**作用**:資訊壓縮的方法,對 feature map 重點挑選,壓縮長寬(降低維度)並保留重要資訊

:::
### **降低維度**:2x2 Maxpooling2D
使用原因:挑出局部圖片最明顯的特徵(影像的局部有很多不必要空白),除了減少計算資源外,還可把重要資訊保留,不重要的捨棄(去噪),以此增加模型的收斂跟穩定性。
MaxPooling2D(2x2):選範圍 2x2 中最大值的pixel

## :sandwich: Flaten Layer 平坦層
:::warning
輸出:一維向量
作用:維度的轉換(成 Dense Layer 可接受的一維向量)
:::
Output 通常為一維,中間維度的轉換就靠『扁平層』(Flatten)來處理
#### 展開(Flatten)的步驟
* 問題:把高維的資訊拉成一條直線,大量失去特徵之間的空間資訊,破壞圖片的空間結構,大打折扣
* 解決:若在 Flatten 前先經過數個卷積+池化層,現在每一個節點已經包含了空間結構的資訊在裡面,這個時候進行 Dense Layer 的分類就不會有破壞空間結構的問題
## :sandwich: Dense Layer (Fully Connected)
:::warning
輸出:一維向量(類別)
作用:分類器-將上一層的資料進行矩陣相乘的計算轉換,用來進行分類
:::
相鄰層之間的神經元兩兩之間都有連接,所以叫做 Fully Connect

分類器:做最後的特徵提取、進行分類
* Input 通常為一維,中間維度的轉換就靠『扁平層』(Flatten)來處理
* 假如要分的類別有10類,那 FC 最後一層就會接10個神經元,並且經過 Softmax function
* Softmax:數值經過 softmax function 後,其加總值會變為1
把各項的輸出值當作機率,目標=縮小預測機率值與實際 Label 值
ex. 讓 [0.7] 去接近 [1],用 Cross Entropy 計算
* 預測輸出=[0.7,0.2,0.1]
* Label=[1,0,0]

---
## Conv2D vs. Conv2DTranspose
**Downsampling**:縮小影像尺寸 → feature 長寬*1/2
* conv(stride=2):
Conv 時扔一半的 feature,減少了一半的 Conv 操作
* 速度更快,但是某些位置的feature 就永遠丟掉了
* stride = 2時,有一個filter在參與運算,**有權重參數**
* conv(stride=1) + maxpooling(stride=2):
比前一種情況耗時一倍多,但得到的 feature 直觀上更加精確
* Conv 時保留所有 feature
* Maxpool 只保留局部區域最“重要的” feature 達到 Downsample 目的
Maxpool **無需學習參數**
**Upsampling**:擴大影像尺寸 → feature 長寬*2
* conv2Dtranspose(stride=2):與 CNN 相同具有參數可學習,可視為 CNN 卷積的反向操作
* UpSampling2D(size=2)+conv(stride=1):直接複製行列的值來擴充,可看作是 Pooling 反向操
### :sandwich: Conv
:::warning
作用:縮小影像尺寸(Downsampling)
#### conv(stride=2) vs. conv(stride=1)+maxpooling(stride=2)
* conv(stride=2):速度更快,但是某些位置的feature 就永遠丟掉
* conv(stride=1)+maxpooling(stride=2):耗時,無需學習參數,只保留局部區域最“重要的” feature
:::
1. **padding == 'SAME'**:對 input 資料補0
==$output = input / stride$==
* stride=1,input_size = output_size
* input_size = 10, output_size = 10
* stride=2,可以理解為 feature map ==縮小==的倍數。
* input_size = 10, output_size = 5
2. **padding == valid**
==$output = (input-kernel+1) / stride$==
* stride=1, kernel=3, 卷積後的大小: (10–3+1)/1=8
* input_size = 10, output_size = 8
* stride=2, kernel=3, 卷積後的大小: (10–3+1)/2=4
* input_size = 10, output_size = 4
### :sandwich: Conv2DTranspose
:::warning
作用:擴大影像尺寸(Upsampling)
#### UpSampling2D vs. Conv2DTranspose
兩者雖然都可達到 Up sampling的目的,但 Conv2DTranspose 效果更好
* UpSampling2D:直接複製行列的值來擴充,可看作是 Pooling 反向操作
* Conv2DTranspose:與 CNN 相同具有參數可學習,可視為 CNN 卷積的反向操作
:::
**stride** = 2
**tensor** (高x寬) * 2

1. **padding == 'SAME'** ( padding == 某數值)
==$output = (input - 1) *stride - 2*padding + kernel$==
zero-padding的手法,讓輸入的圖不會受到kernel map的大小影響。
* stride 可以理解為 feature map ==放大==的倍數。
* input_size = 3, output_size = 5, 那麼stride就是2: 5/(2+1)=6
* stride=1 時
當kernel=3, padding=1 or kernel=5, padding=2,卷積前後 feature map 尺寸不變
* input_size = 3, output_size = 3
2. **padding == valid**
==$input = (output - kernel + 1) / stride$==
* stride=1, kernel=3, 卷積後的大小: (12–3+1)/1=10
* input_size = 10, output_size = 12
* stride=2, kernel=3, 卷積後的大小: (22–3+1)/2=10
* input_size = 10, output_size = 22
``` python=1
if padding == 'SAME':
input_size = output_size // stride + 1
elif padding == 'VALID':
input_size = (output_size - kernel + 1) // stride + 1
else:
print("wrong :3")
```
## 參考資料
:::success
### Padding
1. 卷積神經網路(Convolutional neural network, CNN):卷積計算中的步伐(stride)和填充(padding)
https://medium.com/@chih.sheng.huang821/%E5%8D%B7%E7%A9%8D%E7%A5%9E%E7%B6%93%E7%B6%B2%E8%B7%AF-convolutional-neural-network-cnn-%E5%8D%B7%E7%A9%8D%E8%A8%88%E7%AE%97%E4%B8%AD%E7%9A%84%E6%AD%A5%E4%BC%90-stride-%E5%92%8C%E5%A1%AB%E5%85%85-padding-94449e638e82
2. 如何理解maxpooling和stride等於2的優缺點以及不同點?
https://www.zhihu.com/question/270555539
3. 關於tf中的conv2d_transpose的用法
https://zhuanlan.zhihu.com/p/31988761
4. [卷積神經網路 (Convolutional Neural , CNN)](https://hackmd.io/@allen108108/rkn-oVGA4)
:::