--- 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 ---