標籤:

卷積的發展歷程,原理和基於 TensorFlow 的實現

卷積的發展歷程,原理和基於 TensorFlow 的實現

來自專欄 TensorFlowNews

稀疏交互

在生物學家休博爾和維瑟爾早期關於貓視覺皮層的研究中發現,視覺皮層中存在一些細胞對輸入空間也就是圖像中的子區域非常敏感,我們稱為感受野。在神經網路中,稀疏交互就是下一層節點只和上一層中的部分節點進行連接的操作。稀疏交互可以顯著的降低神經網路中參數的數量。

左邊是全連接方式,隱藏節點都需要所有的輸入;右邊是稀疏交互,隱藏層節點只接受一個區域內的節點輸入。

稀疏交互的實現

以 MNIST 數據集為例,來實現稀疏交互,並輸出結果對應的圖片。

MNIST 原始圖片:

為了進行局部連接,有兩個重要的參數需要選擇:

1.局部區域的大小

局部區域的大小,首先以 5 * 5 的局部區域為例:

2.局部特徵的抽取次數

針對局部區域可以進行多次特徵抽取,可以選擇局部特徵抽取的次數,首先以抽取 5 次為例。

3.步長

在確定局部區域大小之後,可以平滑的每次移動一個像素,也可以間隔 N 個像素進行移動。

如圖:

也可以使用不同的特徵提取器對同一片區域,進行多次特徵提取,如圖所示:

4.邊緣填充

在進行一次局部連接的過程中,如果不進行邊緣填充,圖像的維度將會發生變化,如圖所示:

4 * 4 的圖像,進行了 3 * 3 的局部連接,維度發生了變化。

對於邊緣的兩種處理方法:

權值共享

權值共享的由來

降低網路中參數的個數,還有一個方法就是共享參數。每一組參數都可以認為是一個特徵提取器,即使圖像有一定的偏移,還是可以將相應的特徵用同一組參數提取出來。

TensorFlow 實現局部連接和權值共享

如下圖所示:

為了演示局部連接和權值共享在特徵提取方面的作用,接下來將使用在稀疏交互中一種很常用的一組權值,它的作用是邊緣提取。

就是這個矩陣組成的權值:

1

2

3[[-1,-1,-1],

[-1,8,-1],

[-1,-1,-1]]

使用 TensorFlow 的 convolution 函數對 MNIST 數據集做卷積操作。因為這部分代碼涉及到維度相關的操作比較多,在稍後卷積網路部分會有詳細說明。這段代碼單獨實現了卷積功能:

import tensorflow as tf

import numpy as np

from tensorflow.examples.tutorials.mnist import input_data

import matplotlib.pyplot as plt

#引入 MNIST 數據集

mnist = input_data.read_data_sets("/tmp/data/", one_hot=False)

#選取訓練集中的第 1 個圖像的矩陣

mnist_one=mnist.train.images[0]

plt.subplot(121)

plt.imshow(mnist_one.reshape((28,28)), cmap=plt.cm.gray)

#輸出圖片的維度,結果是:(784,)

print(mnist_one.shape)

#因為原始的數據是長度是 784 向量,需要轉換成 1*28*28*1 的矩陣。

mnist_one_image=mnist_one.reshape((1,28,28,1))

#輸出矩陣的維度

print(mnist_one_image.shape)

#濾波器參數

filter_array=np.asarray([[-1,-1,-1],[-1,8,-1],[-1,-1,-1]])

#濾波器維度

print(filter_array.shape)

#調整濾波器維度

filter_tensor=filter_array.reshape((3,3,1,1))

#卷機操作

conv_image_tensor=tf.nn.convolution(mnist_one_image,filter=tf.to_float(filter_tensor),padding="SAME")

#返回的張量維度

print(conv_image_tensor.shape)

#調整為二維圖片

conv_image=tf.reshape(conv_image_tensor,[28,28])

with tf.Session() as sess:

#獲得張量的值

conv_image=sess.run(conv_image)

plt.subplot(122)

#使用 matplotlib 輸出為圖片

plt.imshow(conv_image, cmap=plt.cm.gray)

plt.show()

池化介紹

池化

除了之前的兩種方式,在數據量很大,類比現實生活中事情紛繁複雜的時候,我們總是想抓住重點,在圖像中,可以在一個區域選取一個重要的點。

一般是選擇值最大的點,作為這一個區域的代表:

如圖所示:

這個池化選取的是 2 * 2 的區域,留下值最大點,步長為 2。原來 4 * 4 的圖片矩陣池化之後變成了 2 * 2 的圖片矩陣。

手寫數字識別

接下來將會以 MNIST 數據集為例,使用卷積層和池化層,實現一個卷積神經網路來進行手寫數字識別,並輸出卷積和池化效果。

數據準備

  • MNIST 數據集下載

MNIST 數據集可以從 THE MNIST DATABASE of handwritten digits 的網站直接下載。

網址:yann.lecun.com/exdb/mni

train-images-idx3-ubyte.gz: 訓練集圖片

train-labels-idx1-ubyte.gz: 訓練集列標

t10k-images-idx3-ubyte.gz: 測試集圖片

t10k-labels-idx1-ubyte.gz: 測試集列標

TensorFlow 有載入 MNIST 資料庫相關的模塊,可以在程序運行時直接載入。

代碼如下:

from tensorflow.examples.tutorials.mnist import input_data

import matplotlib.pyplot as pyplot

#引入 MNIST 數據集

mnist = input_data.read_data_sets("/tmp/data/", one_hot=False)

#選取訓練集中的第 1 個圖像的矩陣

mnist_one=mnist.train.images[0]

#輸出圖片的維度,結果是:(784,)

print(mnist_one.shape)

#因為原始的數據是長度是 784 向量,需要轉換成 28*28 的矩陣。

mnist_one_image=mnist_one.reshape((28,28))

#輸出矩陣的維度

print(mnist_one_image.shape)

#使用 matplotlib 輸出為圖片

pyplot.imshow(mnist_one_image)

pyplot.show()

代碼的輸出依次是:

1.單個手寫數字圖片的維度:

(784,)

2.轉化為二維矩陣之後的列印結果:

(28, 28)

3.使用 matplotlib 輸出為圖片

最後,對深度學習感興趣,熱愛Tensorflow的小夥伴,歡迎關注我們的網站!http://www.tensorflownews.com。以及知乎專欄:zhuanlan.zhihu.com/Tens


推薦閱讀:

乾脆面君,你給我站住!你已經被TensorFlow盯上了
TensorFlow中.crf_log_likelihood()怎麼用,越具體越好?
TensorFlow 的簡單例子
TensorFlow 教程 #06 - CIFAR-10
【模型壓縮】輕量級深層神經網路MobileNets

TAG:卷積 | TensorFlow |