目錄
第10章 TensorFlow高層封裝
目前比較流行的TensorFlow高層封裝主要有4個,分別是TensorFlow-Slim、TFLearn、Keras和Estimator。
TensorFlow-Slim是Google官方給出的相對較早的TensorFlow高層封裝,Google通過TensorFlow-Slim開源了一些已經訓練好的圖像分析模型,所以目前在圖像識別問題中TensorFlow-Slim仍被較多地使用。
與TesorFlow-Slim相比,TFLearn是一個更加簡潔的TensorFlow高層封裝。通過TFLearn可以更加容易地完成模型定義、模型訓練以及模型評測的全過程。以下給出使用TFLearn在MNIST數據集上實現LeNet-5模型:
import tflearn from tflearn.layers.core import input_data, dropout, fully_connected from tflearn.layers.conv import conv_2d, max_pool_2d from tflearn.layers.estimator import regression import tflearn.datasets.mnist as mnist trainX, trainY, testX, testY = mnist.load_data( data_dir="./MNIST_data", one_hot=True) # 將圖像數據resize成卷積卷積神經網絡輸入的格式。 trainX = trainX.reshape([-1, 28, 28, 1]) testX = testX.reshape([-1, 28, 28, 1]) # 構建神經網絡。 net = input_data(shape=[None, 28, 28, 1], name='input') net = conv_2d(net, 32, 5, activation='relu') net = max_pool_2d(net, 2) net = conv_2d(net, 64, 5, activation='relu') net = max_pool_2d(net, 2) net = fully_connected(net, 500, activation='relu') net = fully_connected(net, 10, activation='softmax') # 定義學習任務。指定優化器爲sgd,學習率爲0.01,損失函數爲交叉熵。 net = regression(net, optimizer='sgd', learning_rate=0.01, loss='categorical_crossentropy') # 通過定義的網絡結構訓練模型,並在指定的驗證數據上驗證模型的效果。 model = tflearn.DNN(net, tensorboard_verbose=0) model.fit(trainX, trainY, n_epoch=10, validation_set=([testX, testY]), show_metric=True)
運行結果:
Training Step: 8599 | total loss: 0.16579 | time: 29.478s | SGD | epoch: 010 | loss: 0.16579 - acc: 0.9785 -- iter: 54976/55000 Training Step: 8600 | total loss: 0.14981 | time: 31.360s | SGD | epoch: 010 | loss: 0.14981 - acc: 0.9806 | val_loss: 0.04016 - val_acc: 0.9857 -- iter: 55000/55000 --
Keras是目前使用最爲廣泛的深度學習工具之一,它的底層可以支持TensorFlow、MXNet、CNTK和Theano。Keras API訓練模型可以先定義一個Sequential類,然後在Sequential實例中通過add函數添加網絡層。Keras把卷積層、池化層、RNN結構(LSTM、GRN)、全連接層等常用的神經網絡結構都做了封裝,可以很方便地實現深層神經網絡。
除了能夠還跟方便地處理圖像問題,Keras對於循環神經網絡的支持也是非常出色。有了Keras API,循環神經網絡的循環體結構也可以通過一句命令完成。原生態的Keras API對訓練數據的處理流程支持得不太好,基本上需要一次性將數據全部加載到內存;其次,原生態Keras API無法支持分佈式訓練。爲了解決這兩個問題,Keras提供了一種與原生態TensorFlow結合得更加緊密得方式,以下代碼顯示瞭如何將Keras和原生態TensorFlow API聯合起來解決MNIST問題。
import tensorflow as tf from tensorflow.examples.tutorials.mnist import input_data mnist_data = input_data.read_data_sets('./MNIST_data', one_hot=True) # 通過TensorFlow中的placeholder定義輸入。 x = tf.placeholder(tf.float32, shape=(None, 784)) y_ = tf.placeholder(tf.float32, shape=(None, 10)) net = tf.keras.layers.Dense(500, activation='relu')(x) y = tf.keras.layers.Dense(10, activation='softmax')(net) acc_value = tf.reduce_mean( tf.keras.metrics.categorical_accuracy(y_, y)) loss = tf.reduce_mean(tf.keras.losses.categorical_crossentropy(y_, y)) train_step = tf.train.GradientDescentOptimizer(0.5).minimize(loss) with tf.Session() as sess: tf.global_variables_initializer().run() for i in range(3000): xs, ys = mnist_data.train.next_batch(100) _, loss_value = sess.run([train_step, loss], feed_dict={x: xs, y_: ys}) if i % 1000 == 0: print("After %d training step(s), loss on training batch is " "%g." % (i, loss_value)) print (acc_value.eval(feed_dict={x: mnist_data.test.images, y_: mnist_data.test.labels}))
運行結果:
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 After 0 training step(s), loss on training batch is 2.3884. After 1000 training step(s), loss on training batch is 0.0444334. After 2000 training step(s), loss on training batch is 0.0692529. 0.9781
Estimator是TensorFlow官方提供的高層API,所以它更好地整合了原生態TensorFlow提供的功能。預先定義好的Estimator功能有限,比如無法很好地實現卷積神經網絡或者循環神經網絡,也沒有辦法支持自定義的損失函數,所以一般推薦使用Estimator自定義模型。除此之外,Estimator可以原生地支持TensorFlow中數據處理流程的接口。
第11章 TensorBoard可視化
TensorBoard是TensorFlow的可視化工具,它可以通過TensorFlow程序運行過程中輸出的日誌文件可視化TensorFlow程序的運行狀態。TensorBoard和TensorFlow程序跑在不同的進程中,TensorBoard會自動讀取最新的TensorFlow日誌文件,並呈現當前TensorFlow程序運行的最新狀態。以下代碼示例完成TensorFlow日誌輸出功能:
import tensorflow as tf input1 = tf.constant([1.0, 2.0, 3.0], name="input1") input2 = tf.Variable(tf.random_uniform([3]), name="input2") output = tf.add_n([input1, input2], name="add") writer = tf.summary.FileWriter("./tf_log", tf.get_default_graph()) writer.close()
運行結果:
然後,使用TensorBoard進行可視化,運行以下命令:
tensorboard --logdir=./tf_log
爲了更好地組織可視化效果圖中的計算節點,TensorBoard支持通過TensorFlow命名空間來整理可視化效果圖上的節點。變量的命名空間有tf.variable_scope和tf.name_scope函數。TensorBoard除了展示TensorFlow計算圖的結構,還可以展示TensorFlow計算圖上每個節點的基本信息以及運行時消耗的時間和空間。
TensorBoard可以依據程序運行的過程對其相關的結果進行可視化,分別有SCALARS、IMAGES、AUDIO、TEXT、HISTOGRAMS和DISRIBUTIONS欄。下圖是其中SCALARS欄對MNIST數據集進行訓練的可視化結果:
TensorBoard提供了PROJECTOR界面來可視化高維向量之間的關係,PROJECTOR界面可以非常方便地可視化多個高維向量之間的關係。比如在圖像遷移學習中可以將一組目標問題的圖片通過訓練好的卷積層得到瓶頸層,這些瓶頸層向量就是多個高維向量。如果在目標問題圖像數據集上同一種類的圖片在經過卷積層之後得到的瓶頸層向量在空間中比較接近,那麼這樣遷移學習得到的記過就有可能會更好。
第12章 TensorFlow計算加速
在配置好GPU環境的TensorFlow中,如果操作沒有明確地指定運行設備,那麼TensorFlow會優先選擇GPU。不同版本的TensorFlow對GPU的支持不一樣,如果程序中全部使用強制指定設備的方式會降低程序的可移植性。雖然GPU可以加速TensorFlow的計算,但一般來說不會把所有的操作全部放在GPU上。一個比較好的實踐是將計算密集型的運行放在GPU上,而把其他操作放到CPU上。
常用的並行化深度學習模型訓練方式有兩種,分別是同步模式和異步模式。在並行化地訓練深度學習模型時,不同設備(GPU或CPU)可以在不同訓練數據上運行這個迭代過程,而不同並行模式的區別在於不同的參數更新方式。
異步模式:在每一輪迭代時,不同設備會讀取參數最新的取值,但因爲不同設備讀取參數取值的時間不一樣,所以得到的值也有可能不一樣。根據當前參數的取值和隨機獲取的一小部分訓練數據,不同設備各自運行反向傳播的過程並獨立地更新參數。可以簡單地認爲異步模式就是單機模式複製了多份,每一份使用不同的訓練數據進行訓練。在異步模式下,不同設備之間是完全獨立的。
同步模式:在同步模式下,所有的設備同時讀取參數的取值,並且當反向傳播算法完成之後同步更新參數的取值。單個設備不會單獨對參數進行更新,而會等待所有設備都完成反向傳播之後再同一更新參數。