機器學習與Tensorflow(4)——卷積神經網絡與tensorflow實現

1.標準卷積神經網絡

標準的卷積神經網絡由輸入層、卷積層(convolutional layer)、下采樣層(downsampling layer)、全鏈接層(fully—connected layer)和輸出層構成。git

  • 卷積層也稱爲檢測層
  • 下采樣層也稱爲池化層(pooling layer)

2.卷積神經網絡的優點:

第一個特色和優點就是:局部感知網絡

  • 在傳統神經網絡中每一個神經元都要與圖片上每一個像素相鏈接,
  • 這樣的話就會形成權重的數量巨大形成網絡難以訓練。
  • 而在含有卷積層的神經網絡中每一個神經元的權重個數都時卷積核的大小,
  • 這樣就至關於神經元只與對應圖片部分的像素相鏈接。
  • 這樣就極大的減小了權重的數量。同時咱們能夠設置卷積操做的步長,
  • 可是步長的設置並沒有定值須要使用者本身嘗試


第二個特色和優點就是:參數共享ide

  • 卷積核的權重是通過學習獲得的,而且在卷積過程當中卷積核的權重是不會改變的,這就是參數共享的思想。
  • 經過一個卷積核的操做提取了原圖的不一樣位置的一樣特徵。
  • 簡單來講就是在一幅圖片中的不一樣位置的相同目標,它們的特徵是基本相同的

第三個特色和優點就是:多卷積核函數

  • 咱們用一個卷積核操做只能獲得一部分特徵可能獲取不到所有特徵,
  • 因此爲了可以獲得圖像更多的特徵信息咱們引入了多核卷積。
  • 用多個卷積核來學習圖像更多的不一樣的特徵(每一個卷積核學習到不一樣的權重)。
  • 主要注意的是在多核卷積的過程當中每一層的多個卷積核的大小應該是相同的。


3.關於卷積

先了解卷積運算:內卷積和外卷積(具體以下圖)學習

內卷積:優化

外卷積:spa

 

卷積層的做用:code

  • 卷積層的每個卷積濾波器做用於整個感覺野中,對輸入圖像進行卷積,
  • 卷積的結果構成了輸入圖像的特徵圖,從而通過卷積層後就提取出了圖像的局部特徵。
  • 因此卷積層的主要做用就是能夠利用不一樣的卷積核(也叫濾波器)來提取圖像不一樣的特徵。
  • 它是識別圖像最核心的部分。

 

4.關於池化

池化方式:(最大池化、平均池化)orm

  • 池化層的具體操做與卷基層的操做基本相同,只不過池化層的卷積核爲只取對應位置的最大值或平均值(最大池化、平均池化),
  • 而且不會隨着反向傳播發生變化。通常池化層的filter取2*2,最大取3*3,stride取2,特徵信息壓縮爲原來的1/4。

最大池化方式(每一個小塊中的最大值):blog

 

平均池化方式(每一個小塊中的平均值):

 


池化層的做用:

  • 池化層可對提取到的特徵信息進行降維,
  • 一方面使特徵圖變小,簡化網絡計算複雜度並在必定程度上避免過擬合的出現;一方面進行特徵壓縮,提取主要特徵。
  • 最大池採樣在計算機視覺中的價值體如今兩個方面:(1)、它減少了來自上層隱藏層的計算複雜度;(2)、這些池化單元具備平移不變性,即便圖像有小的位移,提取到的特徵依然會保持不變。因爲加強了對位移的魯棒性,這樣能夠忽略目標的傾斜、旋轉之類的相對位置的變化,以此提升精度,最大池採樣方法是一個高效的下降數據維度的採樣方法。
  • 須要注意的是:這裏的pooling操做是特徵圖縮小,有可能影響網絡的準確度。


5.Tensorflow實現

def conv2d(input, filter, strides, padding, use_cudnn_on_gpu=None,data_format=None, name=None)

除去name參數用以指定該操做的name,與方法有關的一共五個參數:

第一個參數input:

  • 指須要作卷積的輸入圖像,它要求是一個Tensor,具備[batch, in_height, in_width, in_channels]這樣的shape,
  • 具體含義是[訓練時一個batch的圖片數量, 圖片高度, 圖片寬度, 圖像通道數],
  • 注意這是一個4維的Tensor,要求類型爲float32和float64其中之一

第二個參數filter:

  • 至關於CNN中的卷積核,它要求是一個Tensor,具備[filter_height, filter_width, in_channels, out_channels]這樣的shape,
  • 具體含義是[卷積核的高度,卷積核的寬度,圖像通道數,卷積核個數],
  • 要求類型與參數input相同,
  • 有一個地方須要注意,第三維in_channels,就是參數input的第四維

第三個參數strides:

  • 卷積時在圖像每一維的步長,這是一個一維的向量,長度4
  • strides[0] = strides[3] = 1
  • strides[1]表明x方向的步長,strides[2]表明y方向的步長


第四個參數padding:

  • string類型的量,只能是"SAME","VALID"其中之一,這個值決定了不一樣的卷積方式
  • 對於卷積操做:
    • SAME PADDING表明給平面外部補0,卷積窗口採樣後獲得一個跟原來平面大小相同的平面
    • VALID PADDING表明不會超出平面外部,卷積窗口採樣後獲得比原來平面小的平面。
  • 對於池化操做:
    • SAME PADDING表明可能會給平面外部補0
    • VALID PADDING表明不會超出平面外部

舉例理解:
假若有一個28*28的平面,用2*2而且步長爲2的窗口對其進行pooling操做

使用SAME PADDING的方式,獲得14*14的平面
使用VALID PADDING的方式,獲得14*14的平面


假若有一個2*3的平面,用2*2而且步長爲2的窗口對其進行pooling操做

使用SAME PADDING的方式,獲得1*2的平面
使用VALID PADDING的方式,獲得1*1的平面

 



第五個參數:use_cudnn_on_gpu:bool類型,是否使用cudnn加速,默認爲true

結果返回一個Tensor,這個輸出,就是咱們常說的feature map

 

6.卷積神經網絡對MNIST手寫數據集識別優化

實現代碼:

  1 import os
  2 os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
  3 import tensorflow as tf
  4 from tensorflow.examples.tutorials.mnist import input_data
  5 
  6 #載入數據集
  7 mnist = input_data.read_data_sets('MNIST_data', one_hot=True)
  8 
  9 #每一個批次的大小
 10 batch_size = 100
 11 
 12 #計算一個有多少個批次
 13 n_batch = mnist.train.num_examples // batch_size
 14 
 15 #初始化權值
 16 def weight_variable(shape):
 17     initial = tf.truncated_normal(shape, stddev=0.1)#生成一個截斷的正態分佈
 18     return tf.Variable(initial)
 19 
 20 #初始化偏置
 21 def bias_variable(shape):
 22     initial = tf.constant(0.1, shape=shape)
 23     return tf.Variable(initial)
 24 
 25 #卷積層
 26 def conv2d(x,W):
 27     # x input tensor of shape `[batch, in_height, in_width, in_channels]`
 28     # W filter / kernel tensor of shape [filter_height, filter_width, in_channels, out_channels]
 29     # `strides[0] = strides[3] = 1`. strides[1]表明x方向的步長,strides[2]表明y方向的步長
 30     # padding: A `string` from: `"SAME", "VALID"`
 31     return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding='SAME')
 32 
 33 #池化層
 34 def max_pool_2x2(x):
 35     # ksize [1,x,y,1]
 36     return tf.nn.max_pool(x, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')
 37 
 38 #定義兩個placeholder
 39 x = tf.placeholder(tf.float32, [None, 784]) #28*28
 40 y = tf.placeholder(tf.float32, [None,10])
 41 
 42 #改變x的格式轉爲4D的向量[batch,in_height,in_width,in_channels]
 43 x_image = tf.reshape(x, [-1, 28, 28, 1])
 44 
 45 #初始化第一個卷積層的權值和偏置
 46 W_conv1 = weight_variable([5, 5, 1, 32])  #5*5的採樣窗口,32個卷積核從1個平面抽取特徵
 47 b_conv1 = bias_variable([32]) #每個卷積核一個偏置值
 48 
 49 #把x_image和權值向量進行卷積,再加上偏置值,而後應用於relu激活函數
 50 h_conv1 = tf.nn.relu(conv2d(x_image, W_conv1) + b_conv1)
 51 h_pool1 = max_pool_2x2(h_conv1)
 52 
 53 #初始第二個卷積層的權值和偏置值
 54 W_conv2 = weight_variable([5, 5, 32, 64])#5*5的採樣窗口,64個卷積核從32個平面抽取特徵
 55 b_conv2 = bias_variable([64])
 56 
 57 #把h_pool1和權值向量進行卷積,再加上偏置值,而後應用於relu激活函數
 58 h_conv2 = tf.nn.relu(conv2d(h_pool1, W_conv2) + b_conv2)
 59 h_pool2 = max_pool_2x2(h_conv2)
 60 
 61 #28*28的圖片第一次卷積後仍是28*28,第一次池化後變成14*14
 62 #第二次卷積爲14*14,第二次池化後變成可7*7
 63 #通過上面的操做後獲得64張7*7的平面
 64 
 65 #初始化第一個全鏈接層的權值
 66 W_fc1 = weight_variable([7*7*64, 1024])#上一層有7*7*64個神經元,全鏈接層有1024個神經元
 67 b_fc1 = bias_variable([1024])#1024個節點
 68 
 69 #把池化層2的輸出扁平化爲1維
 70 h_pool2_flat = tf.reshape(h_pool2, [-1, 7*7*64])
 71 
 72 #求第一個全鏈接層的輸出
 73 h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, W_fc1) + b_fc1)
 74 
 75 #keep_prob用來表示神經元的輸出機率
 76 keep_prob = tf.placeholder(tf.float32)
 77 h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)
 78 
 79 #初始化第二個全鏈接層
 80 W_fc2 = weight_variable([1024, 10])
 81 b_fc2 = bias_variable([10])
 82 
 83 #計算輸出
 84 prediction = tf.nn.softmax(tf.matmul(h_fc1_drop, W_fc2) + b_fc2)
 85 
 86 #交叉熵代價函數
 87 cross_entropy = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=y, logits=prediction))
 88 
 89 #使用AdmaOptimizer進行優化
 90 train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)
 91 
 92 #結果存放在一個布爾列表中
 93 correct_prediction = tf.equal(tf.argmax(prediction, 1), tf.argmax(y, 1))
 94 
 95 #求準確率
 96 accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
 97 
 98 #變量初始化
 99 init = tf.global_variables_initializer()
100 
101 with tf.Session() as sess:
102     sess.run(init)
103     for epoch in range(21):
104         for batch in range(n_batch):
105             batch_xs, batch_ys = mnist.train.next_batch(batch_size)
106             sess.run(train_step, feed_dict={x: batch_xs, y: batch_ys, keep_prob: 0.7})
107         acc = sess.run(accuracy, feed_dict={x: mnist.test.images[:5000], y: mnist.test.labels[:5000], keep_prob: 1.0})
108         print('Iter : ' + str(epoch) + ',Testing Accuracy = ' + str(acc))
View Code

#寫在後面:

很久沒有作學習總結

最近一直在給老師處理軸承數據,而後用深度學習作分類

天天就是忙忙忙

而後還要去健身

昨天是本身的生日,吃了一個超級可愛的小蛋糕

感受本身還像個孩子

永遠18歲

最近煩心事有點多

不少時候沒必要向別人解釋本身

懂你的人天然而然就會懂

不懂得人解釋也不懂

加油吧!小夥郭

加油,每個爲了生活而努力向前的人!

相關文章
相關標籤/搜索