目錄
第5章 MNIST數字識別問題
MNIST是一個非常有名的手寫體數字識別數據集,在很多資料中,這個數據集都會被用作深度學習的入門樣例。MNIST數據集是NIST數據集的一個子集,它包含了60000張圖片作爲訓練數據,10000張圖片作爲測試數據。以下代碼是使用TensorFlow讀取MNIST數據集,如果本地不存在則自動下載到本地指定的目錄,並打印數據集的訓練集、驗證集和測試集的維度大小。
from tensorflow.examples.tutorials.mnist import input_data mnist = input_data.read_data_sets("./MNIST_data/", one_hot=True) print ("Training data size: ", mnist.train.num_examples) print ("Validating data size: ", mnist.validation.num_examples) print ("Testing data size: ", mnist.test.num_examples)
運行結果:
Extracting ./MNIST_data/train-images-idx3-ubyte.gz Extracting ./MNIST_data/train-labels-idx1-ubyte.gz Extracting ./MNIST_data/t10k-images-idx3-ubyte.gz Extracting ./MNIST_data/t10k-labels-idx1-ubyte.gz Training data size: 55000 Validating data size: 5000 Testing data size: 10000
TensorFlow提供了通過變量名稱來創建或者獲取一個變量的機制。通過這個機制,在不同函數中可以直接通過變量名稱來創建或者獲取一個變量的機制。通過這個機制,在不同的函數中可以直接通過變量的名字來使用變量,而不需要將變量通過參數的形式到處傳遞。TensorFlow中通過變量名稱獲取變量的機制主要是通過tf.get_variable和tf.variable_scope函數來實現,還可以同規格tf.Variable函數來創建變量。
通過tf.variable_scope函數可以控制tf.get_variable函數的語義。當tf.variable_scope函數使用參數reuse=True生成上下文管理器時,這個上下文管理器內所有的tf.get_variable函數會直接獲取已經創建的變臉。如果變量不存在,則tf.get_variable函數將報錯;相反,如果tf.variable_scope函數使用參數reuse=None或者reuse=False創建上下文管理器,tf.get_variable操作將創建新的變量。如果同名變量已經存在,則tf.get_variable函數將報錯。以下代碼示例說明了通過variable_scope來管理變量:
import tensorflow as tf v1 = tf.get_variable("v", [1]) print (v1.name) with tf.variable_scope("foo"): v2 = tf.get_variable("v", [1]) print (v2.name) with tf.variable_scope("foo"): with tf.variable_scope("bar"): v3 = tf.get_variable("v", [1]) print (v3.name) v4 = tf.get_variable("v1", [1]) print (v4.name)
運行結果:
v:0 foo/v:0 foo/bar/v:0 v1:0
TensorFlow提供了一個非常簡單的API來保存和還原一個神經網絡模型。這個API就是tf.train.Saver類。下面代碼給出了保存和加載計算圖的方法:
import tensorflow as tf v1 = tf.Variable(tf.random_normal([1], stddev=1, seed=1)) v2 = tf.Variable(tf.random_normal([1], stddev=1, seed=1)) result = v1 + v2 init_op = tf.global_variables_initializer() saver = tf.train.Saver() with tf.Session() as sess: sess.run(init_op) saver.save(sess, "./Saved_model/model.ckpt")
運行結果:
加載保存的模型:
ith tf.Session() as sess: saver.restore(sess, "./Saved_model/model.ckpt") print (sess.run(result))
運行結果:
INFO:tensorflow:Restoring parameters from ./Saved_model/model.ckpt [-1.6226364]
第6章 圖像識別與卷積神經網絡
全連接神經網絡處理圖像的最大問題在於全連接層的參數太多,參數增多除了導致計算速度減慢,還很容易導致過擬合問題。所以需要一個更合理的神經網絡結構來有效地減少神經網絡中參數個數,卷積神經網絡就可以達到這個目的。
卷積神經網絡主要由5種結構組成:輸出層、卷積層、池化層、全連接層和Softmax層。
輸入層:輸入層是整個神經網絡的輸入,在處理圖像的卷積神經網絡中,它一般代表了一張圖片的像素矩陣。
卷積層:從名字可以看出。卷積層是一個卷積神經網絡中最爲重要的部分。和傳統全連接層不同,卷積層中每一個節點的輸入只是上一層神經網絡的一小塊,這個小塊常用的大小有3*3或者5*5。卷積層試圖將神經網絡中的每一小塊進行更加深入地分析從而得到抽象程度更高的特徵。一般來說,通過卷積層處理過的節點矩陣會變得更深。
池化層:池化層神經網絡不會改變三維矩陣的深度,但是它可以縮小矩陣的大小。池化操作可以認爲是將一張分辨率較高的圖片轉化爲分辨率較低的圖片。通過池化層,可以進一步縮小最後全連接層中節點的個數,從而達到減少整個神經網絡中參數的目的。
全連接層:我可以將卷積層和池化層看成自動圖像特徵提取的過程。在特徵提取完成之後,仍然需要使用全連接層來完成分類任務。
Softmax層:Softmax層主要用於分類問題,通過Softmax層可以得到當前樣例屬於不同種類的概率分佈情況。
卷積層神經網絡結構中最重要的部分,稱之爲過濾器(filter)或者內核(kernel)。過濾器可以將當前層神經網絡上的一個子節點矩陣轉化爲下一層神經網絡上的一個單位節點矩陣。單位節點矩陣指的是一個長和寬都爲1,但深度不限的節點矩陣。子節點矩陣的尺寸也被稱之爲過濾器的尺寸,常用的過濾器尺寸有3*3或5*5。因爲過濾器處理的矩陣深度和當前層神經網絡節點矩陣的深度是一致的,所以雖然節點矩陣是三維的,但過濾器的尺寸只需要指定兩個維度。過濾器中另外一個需要人工指定的設置是處理得到的單位節點矩陣的深度,這個設置稱之爲過濾器的深度。
卷積層的參數個數要遠遠小於全連接層,而且卷積層的參數個數和圖片的大小無關,它只和過濾器的尺寸、深度以及當前層節點矩陣的深度有關,這使得卷積神經網絡可以很好地擴展到更大的圖像數據上。
在卷積層之間往往會加上一個池化層,池化層可以非常有效地縮小矩陣的尺寸,從而減少最後全連接層中的參數。使用池化層可以加快計算速度,也有防止過擬合問題的作用。池化層前向傳播過程也是通過移動一個類似過濾器的結構完成的,不過池化層過濾器中的計算不是節點的加權和,而實採用更加簡單的最大值或者平均值計算。
卷積層和池化層中過濾器移動的方式是相似的,唯一的區別在於卷積層使用的過濾器是橫跨整個深度的,而池化層使用的過濾器隻影響一個深度上的節點。所以池化層的過濾器除了在長和寬兩個維度移動,它還需要在深度這個維度上移動。
以下正則表達式公式總結了一些經典的用於圖片分類問題的卷積神經網絡結構:
輸入層—>(卷積層+—>池化層?) +—>全連接層+
在以上公式中,“卷積層+”表示一層或者多層卷積層,大部分卷積神經網絡中一般最多連續使用三層卷積層。“池化層?”表示沒有或者一層池化層。池化層雖然可以起到減少參數防止過擬合問題,但是在部分論文中也發現可以直接通過調整卷積步長來完成。在多輪卷積層和池化層後,卷積神經網絡在輸出之前一般會經過1~2個全連接層。比如LeNet-5模型就可以表示爲以下結構:
輸入層—>卷積層—>池化層—>卷積層—>池化層—>全連接層—>全連接層—>輸出層
Inception結構是一種和LeNet-5結構完全不同的卷積神經網絡結構。在LeNet-5模型中,不同卷積層通過串聯的方式連接在一起,而Inception-v3模型中的Inception結構是將不同的卷積層通過並聯的方式結合在一起。Inception模塊中一般會使用不同尺寸的過濾器處理輸入矩陣,通過使用全零填充且步長爲1,那麼前向傳播得到的結果矩陣的長和寬都與輸入矩陣一致。這樣經過不同過濾器處理的結果矩陣可以拼接成一個更深的矩陣。一般推薦使用TensorFlow-Slim工具來更加簡潔地實現一個卷積層。例如:
net = slim.conv2d(input, 32, [3, 3])
第7章 圖像數據處理
TensorFlow提供了一種統一的格式來存儲數據,這個格式就是TFRecord。
一般圖像的原始輸入數據是直接使用圖像原始的像素矩陣,但是可以通過對圖像的預處理,可以儘量避免受到無關因素的影響。TensorFlow提供了幾類圖像處理函數,分別爲圖像編碼處理、圖像大小調整、圖像翻轉、圖像色彩調整和處理標註框。