---
# System prepended metadata

title: CNN原理
tags: [深度學習筆記]

---

---
tags: 深度學習筆記
---

# CNN原理

![](https://i.imgur.com/RU0vSKu.png)

* 輸入層
輸入資料(Data)的特徵值 (Features)
* 隱藏層
隱藏層在做運算，由神經元(Neuron)組成，透過**前向傳播(Forward propagation)** 計算出我們的**Output值。**
* 輸出層
透過輸入特徵，經過隱藏層的運算所得到的預測值，我們藉由**縮小預測值與實際標註值**(Label)，**更新**我們隱藏層的**參數**，最終**訓練**出一組**權重(weights)**。

---

## CNN (Convolutional Neural Network)

#### 權值共享

一般的FC架構，輸入一張**28*28*1的灰階照片(784個特徵)**，隱藏層使用100個神經元，那麼需要多少個參數？
：
**100*784 (weights)+100 (bias)= 78500個參數

在一般的圖像內有**許多的特徵是相同的**，如特定的輪廓或線條，那我們就可以讓相同幾個神經元組成的**卷積核**去學這個特徵，透過滑動窗口(filters、kernel)對整張圖片進行卷積，進而達到節省參數的效果

#### 保留位置資訊

CNN還有一大特色就是能保留圖像的位置資訊

圖片中的像素 (Pixels)與其鄰近的像素會有一定的關聯度

如果使用FC的結構來訓練圖像資訊的話，要先通過一個展開(Flatten)的步驟，把高維的資訊拉成一條直線，如此一來就會大量失去特徵之間的空間資訊，效果不佳。 *(大部分FC變成最後一層*


## 卷積(Convolution)的基本概念

> 透過卷積核(Kernels)滑動對圖像做訊息提取，並藉由步長(Strides)與填充 (Padding)控制圖像的長寬

卷積核
卷積核(Kernel)又稱為Filters、Features Detectors

1. 可以藉由選擇Kernel的**張數**控制 Feature maps (圖像經由Kernel卷積後的結果，也就是下圖中粉紅色的部分)的**深度**
1. 藉由調整Kernel**大小**決定Kernels的特徵接受域 (Receptive field)。

![](https://i.imgur.com/UOZ5Rl4.gif)

### Kernel的起始值與運算
上圖中黃色區塊就是一個3*3的Kernel，其中的值就是我們**預訓練的權重**，通常用常態分佈隨機產生，再經由訓練更新。
![](https://i.imgur.com/on2iqtb.png)


**Kernel的張數**

控制張數主要就是控制學習的參數量，沒有一定幾張就是對的，常見是16、32或64

如果16就能達到很好的效果，就不需要浪費額外的參數去增加學習和計算量

**Kernel大小**

現在普遍流行的方式是選用**不同大小**的Kernel對圖像做卷積後，再把**輸出的Feature maps合併或平均**。

常見的Kernel大小有1*1, 3*3, 5*5, 7*7。

然而也有人提出，兩層3*3的Kernel 卷積與一層的5*5Kernel 卷積擁有相近的Receptive field，並且使用較少的參數量，因此不妨去嘗試看看不同組合的效果。

**步長**

步長(Strides)為控制圖像長寬尺寸的方式之一，下圖中的Kernel步長分別為1、2，可以觀察到輸出的Feature map大小也不同，雖然通**常長寬上的步長會設為相等**，但我們也可以透過不同的**長寬步長**控制Feature map不同維度尺度的變化。
![](https://i.imgur.com/yTsUTEe.gif)

**填充 (Padding)**

[1]填充 (Padding)是透過在圖像周圍補值為0的像素，其與[2]Strides及[3]Kernel 尺寸**決定輸出Feature map的大小**。

下圖為3*3的Kernel， Stride為 『1』，Padding也為 『1』，可以發現輸出的Feature map與輸入的圖像擁有一樣的尺寸。
![](https://i.imgur.com/hrnHIwA.gif)

通常Padding 又可以分為兩類，分別為： (這部分尚未了解，待查)
* Same Padding
『Same Padding』在Stride為1時，會讓輸出Feature map與輸入圖像**維持一樣的尺寸**，可參考下方程式碼。而當Stride大於1時，輸出Feature map寬、高等於輸入影像寬、高/Stride(小數值無條件進位)。
* Valid Padding
『Valid Padding』不會特別去補邊，因此會讓輸出的Feature map尺寸下降，而當遇到卷積無法完整卷積的狀況則會直接捨棄多出來的像素。
```python=
import tensorflow as tf
import numpy as np
input_image = tf.constant([[1., 2., 3., 4.],
                           [4., 5., 6., 4.],
                           [3., 4., 5., 4.],
                           [3., 4., 5., 4.]])
input_image = tf.reshape(input_image, [1, 4, 4, 1]) 
output_valid=tf.layers.conv2d(inputs=input_image,filters=1,kernel_size=(3,3),strides=(1, 1), padding='valid')
output_same=tf.layers.conv2d(inputs=input_image,filters=1,kernel_size=(3,3),strides=(1, 1), padding='same')
output_valid.get_shape() == [1, 2, 2, 1]  
output_same.get_shape() == [1, 4, 4, 1]  
```

公式化輸出尺寸:

* SAME Padding

![](https://i.imgur.com/Q87X13K.png)

* Valid Padding

![](https://i.imgur.com/MlW51zv.png)

### 輸出Feature map尺寸

卷積過後Feature map尺寸可藉由下方公式計算，其中 input=輸入圖像、p=Padding、f=Filters size、s=Strides。
如果我們使用3*3 filter size， Padding =1, Stride=1，經過計算後會發現Output=Input。

<font size="6">Output = (Input+2p-f)/s+1 </font>


## CNN圖像辨識

![](https://i.imgur.com/YR05U7y.png)

展示一個簡單的CNN圖像辨識模型架構，主要可以拆解為：

---

[卷積層→激勵函數(activation function)→Batch Normalization]= <a style="color:red;" > **卷積組合** </a>

<font size="8"> 輸入圖像→[卷積組合→最大池化(Max Pooling)]*n→攤平(Flatten)→全連接層(Fully Connected layers)→分類 </font>

---

### 輸入圖像
一般來說CNN的輸入圖像為四維的Tensor

Tensorflow:[Batch_size,Height,Width,Channels]
Pytorch:[Batch_size,Channels,Height,Width]

**Batch_size**是你的一個Batch放了幾張照片，可以不用先設定，**height、width**就是輸入圖像的長寬尺寸，**channels**指輸入圖像的深度，一般RGB彩色圖像為3，灰階圖為1。

### 卷積組合

卷積層如同上面所敘述的，通常還會經過**激勵函數(增加非線性性**)與**Batch Normalization**(加速收斂並同時達到一定的regularization效果)。

### 最大池化
常見Pooling 為 Average Pooling 與 Max Pooling

其中又以Max Pooling 最常見，其原理是透過window對應Feature map並提取其最大值。

**Max Pooling主要用於提取重要特徵、加速收斂並縮小Feature map尺寸。** 通常都會使用2*2的window，並且設置Stride為2，如此一來output size就會變為原本的1/2。
不過近期也有諸多學者提出，Max Pooling會導致大量特徵消失，因此逐漸採用其他方式代替Max Pooling來降低Feature map尺度。

![](https://i.imgur.com/GlyDqPn.jpg)


### 攤平
攤平(Flatten)這個步驟主要是要**銜接CNN層與全連接層**，主要是因為FC層需要**一維的輸入**，常見其他方式還有Global average pooling。
### 全連接層
全連接層(FC)主要在做**最後的特徵提取**，並且利用最後一層FC當作分類器。
### 分類
要怎麼使用FC最後一層作為分類器？

假如要分的類別有10類，那FC最後一層就會接10個神經元，並且經過Softmax function。
下圖為Softmax原理，數值經過softmax function後，其加總值會變為1，因此我們可以把**各項的輸出值當作機率**，而目標就是要**縮小預測機率值與實際Label值**。

以下圖為例，預測輸出為[0.7,0.2,0.1]，Label可能為[1,0,0]，因此要讓0.7去接近1 *(這就是訓練的目的)*，實際做法是用Cross Entropy計算。
Cross Entropy 常用在分類器的Loss Function上面，相較於Mean Square Error(MSE)更能凸顯機率分佈之間的差異。

<font face="Times New Roman"> **Softmax** </font>
![](https://i.imgur.com/vyJRzWq.png)


由於我們是多類的問題，所以使用Categorical Cross Entropy。

<font face="Times New Roman"> Cross Entropy </font>
![](https://i.imgur.com/9ISILDQ.png)


Dice loss
$(2x^Ty+e)/(x^Tx+y^Ty+e)$
 
---

Reference
https://cinnamonaitaiwan.medium.com/%E6%B7%B1%E5%BA%A6%E5%AD%B8%E7%BF%92-cnn%E5%8E%9F%E7%90%86-keras%E5%AF%A6%E7%8F%BE-432fd9ea4935

---