找回密碼
 註冊
搜索
查看: 1402|回復: 0

[分享] [機器學習 ML ]Convolution Neural Network 卷積神經網路

[複製鏈接]
發表於 2021-2-5 15:23:28 | 顯示全部樓層 |閱讀模式
 
Push to Facebook

Convolution Neural Network (卷積神經網路)

CNN一直以來是DL中最重要的一部份,CNN 在影像辨識中甚至可以超越人類辨識的精準度,把CNN的概念理解過一遍之後,會發現其實CNN是一個很直觀的演算法,而且仔細想想,其實跟人類用眼睛去辨識有87%的相似,接下來我用CNN始祖Model => LeNet 來介紹CNN是怎麼運作的,以下是LeNet的模型架構 ( 源自Yann LeCun 1998年論文 )

機器學習 Convolution Neural Network 卷積神經網路

機器學習 Convolution Neural Network 卷積神經網路


LeNet Architecture, 1998

可以從上面的LetNet架構中,對於輸入的圖片做了2次Convolutions(卷積),2次Subsampling(采樣),跟2次的Full connection(全連結)還有1次的Gaussian connections (高斯連結),中間的Convolution跟Subsampling在對圖片做特徵擷取的動作,最後把特徵擷取出來後,後面再展開用Full connection做分類,在這裡我就不介紹Full connection了,Full connection就是所謂的分類器,而他就是跟最原始DNN 分類的概念是一樣的,如果對DNN 逆向傳播不熟的可以參考這篇文章,下面我主要Focus在卷積層跟采樣層,也就是特徵擷取的那一段。

Convolution Layers (卷積層)

什麼是卷積呢?我們先來講一些computer vision的東西,我們都知道一張圖片都可以表示成由像素值(pixel)組成的矩陣。以下是一張長毛的皮卡丘的圖片(來自即將上映的神奇寶貝真人版電影,老實說,這隻真的很不討喜… 哈哈)


機器學習 Convolution Neural Network 卷積神經網路

機器學習 Convolution Neural Network 卷積神經網路



大家應該都有用過美圖軟體,或是修圖軟體,有一些基本的特效像是”銳化”或是浮雕的特效,然而這些基本的特效跟美圖都是怎麼做到的呢?

沒錯,就是利用卷積(Convolution) 來達成的


機器學習 Convolution Neural Network 卷積神經網路

機器學習 Convolution Neural Network 卷積神經網路

銳化特效,可以看出皮卡丘的邊緣跟毛都變得更細更清楚了,有一點點怪怪的XD

機器學習 Convolution Neural Network 卷積神經網路

機器學習 Convolution Neural Network 卷積神經網路

浮雕特效,看得出來除了皮卡丘的邊緣以外都變成灰色的了,變成浮雕的感覺了

這裡你可能會想,為什麼講CNN要講到美圖,而美圖跟類神經網路又有什麼關係呢?我相信大家對於”特徵”(Feature)這二個字應該都不陌生,在訓練ML的模型或是NN的模型時,我們需要不斷的擷取”資料”的特徵,最後再進行分類或是預估的動作。

========================================

之所以我們可以做過出不同的美圖效果,是在對圖片做不同的卷積(銳化和模糊或是邊緣增強等操作),我們用銳化來舉例好了,銳化過後的圖片,我們可以看出圖片裡面物件的”邊緣”被強化了,而”邊緣”就是圖片的其中一個有效的特徵,所以我們來思考一下,不同的卷積動作是不是就可以從圖片擷取出各種不同的特徵,像是”邊緣”,”曲線”等等的特徵呢?然後我們再去對特徵做選擇,並且利用特徵來做分類跟預估,沒錯!!所以這就是為什麼Convolution Neural Network的由來,卷積就是在對圖片去做擷取特徵的動作,找出最好的特徵最後再進行分類

========================================

那卷積又是怎麼達成的呢?圖片的卷積運算其實很簡單,只要你會小學教的加減乘除就可以做到,假設我們有張圖,5X5的像素圖,和一個3X3的矩陣


機器學習 Convolution Neural Network 卷積神經網路

機器學習 Convolution Neural Network 卷積神經網路

接下來我再放上一張利用3X3矩陣做卷積的GIF圖


機器學習 Convolution Neural Network 卷積神經網路

機器學習 Convolution Neural Network 卷積神經網路


基本卷積運算(來自網站)

看完上面動圖後,可能有眼尖的人已經看出圖片卷積怎麼運作的了,沒錯,就是將3X3的矩陣在圖片上的像素一步一步移動(在卷積層中移動的步數稱為Stride步數),在每個位置的時候,計算兩個矩陣相對元素的乘積並相加,輸出一個值然後放在一個矩陣(右邊粉色的矩陣),這就是基本的卷積運算。

橘色的矩陣就是所謂的”卷積核(Kernel)”,也是所謂的Filter,然而美圖修修也就是用不同的Kernel做卷積所達成的,不過在這裡你可能會有一個問題?

★ 如果以上面那種運算方式,是不是每做一次卷積,出來後的特徵圖會越來越小呢?原本5X5的圖片跟3X3的矩陣做卷積出來後的圖變成3X3的了,如果不想經過卷積後圖變小的話,有個技術是Zero Padding,他可以將圖片向外擴張補0後再進行卷積,這樣卷積過後的特徵圖就會跟原本的圖一樣了,對於Padding有興趣的話,可以參考Tommy大寫的這篇文章,寫得非常好。

不同的卷積核對不同的圖片做出不同的效果,我們直接用openCV的code來實作一遍convolution



下面是我用不同的3X3 的卷積核做出來的效果


機器學習 Convolution Neural Network 卷積神經網路

機器學習 Convolution Neural Network 卷積神經網路


現在大家應該都懂卷積在圖片上的原理了,而在CNN上卷積其實就是在對圖片做特徵擷取,那我們回到LeNet的架構圖上看一下,我們來看第一層的卷積層,Input為32x32的image,然而經過Convolutions的時候出現6張28X28的Feature map,這是怎麼做到的呢?


機器學習 Convolution Neural Network 卷積神經網路

機器學習 Convolution Neural Network 卷積神經網路

  • 為什麼會出現6張Feature map呢?


其實很簡單的去想,就是用6個”不同的卷積核”去對Input 做卷積

★深度 = 卷積核數量

第一個卷積層出來後的feature map為 6張,因為卷積核數量為6
第二個卷積層出來後的feature map為16張,因為卷積核數量為16
P.S. 這裡妳/你可能會想,第二次的卷積層出來的深度怎麼不是6*16呢?不是應該是每張圖做16個不同的卷積核卷積嗎?=>對於卷積核來說,是有深度的,看下面這張圖應該就很好理解,然而第二個卷積層就的卷積核就是有深度的,16個深度為6的卷積核,所以出來的feature map深度就是16


機器學習 Convolution Neural Network 卷積神經網路

機器學習 Convolution Neural Network 卷積神經網路

來自此網站

2. 那為什麼做完卷積後的每一個Feature map都是28X28呢?

讓我們從上面的那個簡單例子來思考,3X3的卷積核對5X5的圖片出來的Feature map是3X3,因為卷積核由最左邊到最右邊只能走3步,這是步數為1的情況,那如果步數為2的情況呢?出來的Feature map是2X2,我們可以推測出一個公式

★Feature map width=[(Original width-Kernel width)/(Stride+1)]+1

所以5X5的Kernel,步數為1的情況出來的Feature map 就是28X28(沒有做Zero Padding的情況下)

接下來介紹什麼是Subsampling(采樣)

Subsampling/ Pooling Layer(采樣/池化層)

Subsampling,也可以稱為Pooling(池化),這次我先直接來介紹池化的基本運算方式,Pooling常用的方式有二種,Max Pooling,Mean Pooling,我這裡介紹Max Pooling的運作方式,看完應該會馬上就可以理解Mean Pooling是怎麼做的。

池化層跟卷積層一樣,有個Kernel(大多為2X2),對卷積層出來的feature map做運算,我們來看下面這張圖:


機器學習 Convolution Neural Network 卷積神經網路

機器學習 Convolution Neural Network 卷積神經網路


Max Pooling運作方式

這張圖是利用2X2的Kernel 在image上用”步數”2(Stride)進行Pooling的基本運算,沒錯,就是很直觀也很簡單的,在Kernel經過的地方,取出最大值,就達成降維了。

看懂Pooling的基本運算後,我們來講一下為什麼要做池化層:

  • 對特徵圖(Feature map)降維,並且保留重要的特徵,參數減少,可防止Overfitting。


對於Overfitting不熟的人,可以參考我之前的寫的文章,我們知道,越複雜或是參數越多的模型容易造成Overfitting,Pooling層有效降低我們的參數,而且還可以保留重要的特徵,也可以使模型對圖像微小的變換或是一些失真變得更沉穩(因為我們取了Kernel的最大值,微小的失真並不會改變結果,最大值還是最大值)。

2. 卷積跟Pooling後可對”微小”的變化保持不變性(invariance), 旋轉、平移、伸縮等的不變性。

那這是什麼意思呢?這個討論版對這部份寫得非常好,大家參考看看
https://www.zhihu.com/question/36686900

LeNet(論文連結)實作

沒錯,LetNet就是所謂的CNN之父,前面也用了LetNet來介紹了卷積跟池化,然後LeNet整個架構就是利用了卷積跟池化把圖片特徵擷取出來後,並接上全連結層做訓練,看下面的架構圖就可以簡單的把LetNet實作出來,這裡我們用簡單Mnist data來實作LeNet 模型的分類器,


機器學習 Convolution Neural Network 卷積神經網路

機器學習 Convolution Neural Network 卷積神經網路

LeNet Architecture, 1998
  1. import numpy as np
  2. import keras
  3. from keras.datasets import mnist
  4. from keras.utils import np_utils
  5. from keras.models import Sequential
  6. from keras.layers import Dense, Activation, Conv2D, MaxPooling2D, Flatten
  7. from keras.optimizers import Adam

  8. #load the MNIST dataset from keras datasets
  9. (X_train, y_train), (X_test, y_test) = mnist.load_data()

  10. #Process data
  11. X_train = X_train.reshape(-1, 28, 28, 1) # Expend dimension for 1 cahnnel image
  12. X_test = X_test.reshape(-1, 28, 28, 1)  # Expend dimension for 1 cahnnel image
  13. X_train = X_train / 255 # Normalize
  14. X_test = X_test / 255 # Normalize

  15. #One hot encoding
  16. y_train = np_utils.to_categorical(y_train, num_classes=10)
  17. y_test = np_utils.to_categorical(y_test, num_classes=10)

  18. #Build LetNet model with Keras
  19. def LetNet(width, height, depth, classes):
  20.     # initialize the model
  21.     model = Sequential()

  22.     # first layer, convolution and pooling
  23.     model.add(Conv2D(input_shape=(width, height, depth), kernel_size=(5, 5), filters=6, strides=(1,1), activation='tanh'))
  24.     model.add(MaxPooling2D(pool_size=(2, 2), strides=(2, 2)))

  25.     # second layer, convolution and pooling
  26.     model.add(Conv2D(input_shape=(width, height, depth), kernel_size=(5, 5), filters=16, strides=(1,1), activation='tanh'))
  27.     model.add(MaxPooling2D(pool_size=(2, 2), strides=(2, 2)))

  28.     # Fully connection layer
  29.     model.add(Flatten())
  30.     model.add(Dense(120,activation = 'tanh'))
  31.     model.add(Dense(84,activation = 'tanh'))

  32.     # softmax classifier
  33.     model.add(Dense(classes))
  34.     model.add(Activation("softmax"))

  35.     return model

  36. LetNet_model = LetNet(28,28,1,10)
  37. LetNet_model.summary()
  38. LetNet_model.compile(optimizer=Adam(lr=0.001, beta_1=0.9, beta_2=0.999, epsilon=1e-08),loss = 'categorical_crossentropy',metrics=['accuracy'])

  39. #Strat training
  40. History = LetNet_model.fit(X_train, y_train, epochs=5, batch_size=32,validation_data=(X_test, y_test))

  41. #Plot Loss and accuracy
  42. import matplotlib.pyplot as plt
  43. plt.figure(figsize = (15,5))
  44. plt.subplot(1,2,1)
  45. plt.plot(History.history['accuracy'])
  46. plt.plot(History.history['val_accuracy'])
  47. plt.title('model accuracy')
  48. plt.ylabel('accuracy')
  49. plt.xlabel('epoch')
  50. plt.legend(['train', 'test'], loc='upper left')

  51. plt.subplot(1,2,2)
  52. plt.plot(History.history['loss'])
  53. plt.plot(History.history['val_loss'])
  54. plt.title('model loss')
  55. plt.ylabel('loss')
  56. plt.xlabel('epoch')
  57. plt.legend(['train', 'test'], loc='upper left')
  58. plt.show()
  59. plt.show()
複製代碼



機器學習 Convolution Neural Network 卷積神經網路

機器學習 Convolution Neural Network 卷積神經網路

Train 5 個epoch就可以達到98.69的精確率


機器學習 Convolution Neural Network 卷積神經網路

機器學習 Convolution Neural Network 卷積神經網路

Loss 跟 Accuracy

最後附上一個很厲害的網站,模擬了LeNet所有層的輸出結果,超酷的!

3D Visualization of a Convolutional Neural NetworkEdit description
scs.ryerson.ca

結論

CNN不外乎跟卷積還有池化脫離不了關係,卷積跟池化把一張圖片的特徵取出來後,就可以做很多的事情,不見得只能做分類,甚至可以把分類層改成Decoder進行圖像分割。CNN對於Deep learning 用在影像上面占了非常大的重要性,理解卷積跟池化會更容易理解CNN一直到現在的演化史,我也寫了另外一篇文章來簡單介紹CNN的演化史(分類的部份),並且利用Keras來簡易實作各個CNN的演化。


文章出處



 
您需要登錄後才可以回帖 登錄 | 註冊

本版積分規則

Archiver|手機版|小黑屋|TShopping

GMT+8, 2025-5-1 02:14 , Processed in 0.029726 second(s), 24 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回復 返回頂部 返回列表