TensorFlow極簡教程:創建、保存和恢復機器學習模型
創建所需的變數後,數據和線之間的誤差是可以被定義(計算)的。定義的誤差被嵌入到優化器(optimizer)中。然後啟動 TensorFlow,並重複調用優化器。通過不斷迭代最小化誤差來達到數據與直線的最佳擬合。
按照順序閱讀下列腳本:
serial.py
tensor.py
bigdata.py
Serial.py
這個腳本的目的是說明 TensorFlow 模型的基本要點。這個腳本使你更容易理解模型是如何組合在一起的。我們使用 for 循環來定義數據與線之間的誤差。由於定義誤差的方式為循環,該腳本以序列化(串列)計算的方式運行。
Tensor.py
這個腳本比 serial.py 更進一步,雖然實際上這個腳本的代碼行更少。代碼的結構與之前相同,唯一不同的是這次使用張量(tensor)操作來定義誤差。使用張量可以並行(parallel)運行代碼。
每個數據點被看作是來自獨立同分布的樣本。因為每個數據點假定是獨立的,所以計算也是獨立的。當使用張量時,每個數據點都在分隔的計算內核上運行。我們有 8 個數據點,所以如果你有一個有八個內核的計算機,它的運行速度應該快八倍。
BigData.py
你現在距離專業水平僅有一個流行語之遙。我們現在不需要將一條線擬合到 8 個數據點,而是將一條線擬合到 800 萬個數據點。歡迎來到大數據時代。
代碼中有兩處主要的修改。第一點變化是簿記(bookkeeping),因為所有數據必須使用佔位符(placeholder)而不是實際數據來定義誤差。在代碼的後半部分,數據需要通過佔位符饋送(feed)入模型。第二點變化是,因為我們的數據量是巨大的,在給定的任意時間我們僅將一個樣本數據傳入模型。每次調用梯度下降操作時,新的數據樣本將被饋送到模型中。通過對數據集進行抽樣,TensorFlow 不需要一次處理整個數據集。這樣抽樣的效果出奇的好,並有理論支持這種方法:
Stochastic gradient descent
理論上需要滿足一些重要的條件,如步長(step size)必須隨每次迭代而縮短。不管是否滿足條件,這種方法至少是有效的。
結論
當你運行腳本時,你可能看到怎樣定義任何你想要的誤差。它可能是一組圖像和卷積神經網路(convolutional neural network)之間的誤差。它可能是古典音樂和循環神經網路(recurrent neural network)之間的誤差。它讓你的想像力瘋狂。一旦定義了誤差,你就可以使用 TensorFlow 進行嘗試並最小化誤差。
希望你從這個教程中得到啟發。
需求
Python3 (Welcome to Python.org)
TensorFlow (https://www.tensorflow.org/)
NumPy (NumPy - NumPy)
TensorFlow:保存/恢復和混合多重模型
在第一個模型成功建立並訓練之後,你或許需要了解如何保存與恢復這些模型。繼續之前,也可以閱讀這個 Tensorflow 小入門:
https://blog.metaflow.fr/tensorflow-a-primer-4b3fa0978be3#.wxlmweb8h
你有必要了解這些信息,因為了解如何保存不同級別的代碼是非常重要的,這可以避免混亂無序。
如何實際保存和載入
保存(saver)對象
可以使用 Saver 對象處理不同會話(session)中任何與文件系統有持續數據傳輸的交互。構造函數(constructor)允許你控制以下 3 個事物:
目標(target):在分散式架構的情況下用於處理計算。可以指定要計算的 TF 伺服器或「目標」。
圖(graph):你希望會話處理的圖。對於初學者來說,棘手的事情是:TF 中總存在一個默認的圖,其中所有操作的設置都是默認的,所以你的操作範圍總在一個「默認的圖」中。
配置(config):你可以使用 ConfigProto 配置 TF。查看本文最後的鏈接資源以獲取更多詳細信息。
Saver 可以處理圖的元數據和變數數據的保存和載入(又稱恢復)。它需要知道的唯一的事情是:需要使用哪個圖和變數?
默認情況下,Saver 會處理默認的圖及其所有包含的變數,但是你可以創建儘可能多的 Saver 來控制你想要的任何圖或子圖的變數。這裡是一個例子:
import tensorflow as tf
import os
dir = os.path.dirname(os.path.realpath(__file__))
# First, you design your mathematical operations
# We are the default graph scope
# Lets design a variable
v1 = tf.Variable(1. , name="v1")
v2 = tf.Variable(2. , name="v2")
# Lets design an operation
a = tf.add(v1, v2)
# Lets create a Saver object
# By default, the Saver handles every Variables related to the default graph
all_saver = tf.train.Saver()
# But you can precise which vars you want to save under which name
v2_saver = tf.train.Saver({"v2": v2})
# By default the Session handles the default graph and all its included variables
with tf.Session() as sess:
# Init v and v2
sess.run(tf.global_variables_initializer())
# Now v1 holds the value 1.0 and v2 holds the value 2.0
# We can now save all those values
all_saver.save(sess, dir + /data-all.chkp)
# or saves only v2
v2_saver.save(sess, dir + /data-v2.chkp)
如果查看你的文件夾,它實際上每創建 3 個文件調用一次保存操作並創建一個檢查點(checkpoint)文件,我會在附錄中講述更多的細節。你可以簡單理解為權重被保存到 .chkp.data 文件中,你的圖和元數據被保存到 .chkp.meta 文件中。
恢復操作和其它元數據
一個重要的信息是,Saver 將保存與你的圖相關聯的任何元數據。這意味著載入元檢查點還將恢復與圖相關聯的所有空變數、操作和集合(例如,它將恢復訓練優化器)。
當你恢復一個元檢查點時,實際上是將保存的圖載入到當前默認的圖中。現在你可以通過它來載入任何包含的內容,如張量、操作或集合。
import tensorflow as tf
# Lets load a previously saved meta graph in the default graph
# This function returns a Saver
saver = tf.train.import_meta_graph(results/model.ckpt-1000.meta)
# We can now access the default graph where all our metadata has been loaded
graph = tf.get_default_graph()
# Finally we can retrieve tensors, operations, collections, etc.
global_step_tensor = graph.get_tensor_by_name(loss/global_step:0)
train_op = graph.get_operation_by_name(loss/train_op)
hyperparameters = tf.get_collection(hyperparameters)
恢復權重
請記住,實際的權重只存在於一個會話中。這意味著「恢復」操作必須能夠訪問會話以恢復圖內的權重。理解恢復操作的最好方法是將其簡單地當作一種初始化。
with tf.Session() as sess:
# To initialize values with saved data
saver.restore(sess, results/model.ckpt.data-1000-00000-of-00001)
print(sess.run(global_step_tensor)) # returns 1000
在新圖中使用預訓練圖
現在你知道了如何保存和載入,你可能已經明白如何去操作。然而,這裡有一些技巧能夠幫助你走得更快。
一個圖的輸出可以是另一個圖的輸入嗎?
是的,但有一個缺點:我還不知道使梯度流(gradient flow)在圖之間容易傳遞的一種方法,因為你將必須評估第一個圖,獲得結果,並將其饋送到下一個圖。
這樣一直下去是可以的,直到你需要重新訓練第一個圖。在這種情況下,你將需要將輸入梯度饋送到第一個圖的訓練步驟……
我可以在一個圖中混合所有這些不同的圖嗎?
是的,但你需要對命名空間(namespace)倍加小心。好的一點是,這種方法簡化了一切:例如,你可以載入預訓練的 VGG-16,訪問圖中的任何節點,嵌入自己的操作和訓練整個圖!
如果你只想微調(fine-tune)節點,你可以在任意地方停止梯度來避免訓練整個圖。
import tensorflow as tf
# Load the VGG-16 model in the default graph
vgg_saver = tf.train.import_meta_graph(dir + gg/resultsgg-16.meta)
# Access the graph
vgg_graph = tf.get_default_graph()
# Retrieve VGG inputs
self.x_plh = vgg_graph.get_tensor_by_name(input:0)
# Choose which node you want to connect your own graph
output_conv =vgg_graph.get_tensor_by_name(conv1_2:0)
# output_conv =vgg_graph.get_tensor_by_name(conv2_2:0)
# output_conv =vgg_graph.get_tensor_by_name(conv3_3:0)
# output_conv =vgg_graph.get_tensor_by_name(conv4_3:0)
# output_conv =vgg_graph.get_tensor_by_name(conv5_3:0)
# Stop the gradient for fine-tuning
output_conv_sg = tf.stop_gradient(output_conv) # Its an identity function
# Build further operations
output_conv_shape = output_conv_sg.get_shape().as_list()
W1 = tf.get_variable(W1, shape=[1, 1, output_conv_shape[3], 32], initializer=tf.random_normal_initializer(stddev=1e-1))
b1 = tf.get_variable(b1, shape=[32], initializer=tf.constant_initializer(0.1))
z1 = tf.nn.conv2d(output_conv_sg, W1, strides=[1, 1, 1, 1], padding=SAME) + b1
a = tf.nn.relu(z1)
附錄:更多關於 TF 數據生態系統的內容
我們在這裡談論谷歌,他們主要使用內部構建的工具來處理他們的工作,所以數據保存的格式為 ProtoBuff 也是不奇怪的。
協議緩衝區
協議緩衝區(Protocol Buffer/簡寫 Protobufs)是 TF 有效存儲和傳輸數據的常用方式。
我不在這裡詳細介紹它,但可以把它當成一個更快的 JSON 格式,當你在存儲/傳輸時需要節省空間/帶寬,你可以壓縮它。簡而言之,你可以使用 Protobufs 作為:
一種未壓縮的、人性化的文本格式,擴展名為 .pbtxt
一種壓縮的、機器友好的二進位格式,擴展名為 .pb 或根本沒有擴展名
這就像在開發設置中使用 JSON,並且在遷移到生產環境時為了提高效率而壓縮數據一樣。用 Protobufs 可以做更多的事情,如果你有興趣可以查看教程
整潔的小技巧:在張量流中處理 protobufs 的所有操作都有這個表示「協議緩衝區定義」的「_def」後綴。例如,要載入保存的圖的 protobufs,可以使用函數:tf.import_graph_def。要獲取當前圖作為 protobufs,可以使用:Graph.as_graph_def()。
文件的架構
回到 TF,當保存你的數據時,你會得到 5 種不同類型的文件:
「檢查點」文件
「事件(event)」文件
「文本 protobufs」文件
一些「chkp」文件
一些「元 chkp」文件
現在讓我們休息一下。當你想到,當你在做機器學習時可能會保存什麼?你可以保存模型的架構和與其關聯的學習到的權重。你可能希望在訓練或事件整個訓練架構時保存一些訓練特徵,如模型的損失(loss)和準確率(accuracy)。你可能希望保存超參數和其它操作,以便之後重新啟動訓練或重複實現結果。這正是 TensorFlow 的作用。
在這裡,檢查點文件的三種類型用於存儲模型及其權重有關的壓縮後數據。
檢查點文件只是一個簿記文件,你可以結合使用高級輔助程序載入不同時間保存的 chkp 文件。
元 chkp 文件包含模型的壓縮 Protobufs 圖以及所有與之關聯的元數據(集合、學習速率、操作等)。
chkp 文件保存數據(權重)本身(這一個通常是相當大的大小)。
如果你想做一些調試,pbtxt 文件只是模型的非壓縮 Protobufs 圖。
最後,事件文件在 TensorBoard 中存儲了所有你需要用來可視化模型和訓練時測量的所有數據。這與保存/恢復模型本身無關。
下面讓我們看一下結果文件夾的屏幕截圖:
一些隨機訓練的結果文件夾的屏幕截圖
該模型已經在步驟 433,858,1000 被保存了 3 次。為什麼這些數字看起來像隨機?因為我設定每 S 秒保存一次模型,而不是每 T 次迭代後保存。
chkp 文件比元 chkp 文件更大,因為它包含我們模型的權重
pbtxt 文件比元 chkp 文件大一點:它被認為是非壓縮版本!
TF 自帶多個方便的幫助方法,如:
在時間和迭代中處理模型的不同檢查點。它如同一個救生員,以防你的機器在訓練結束前崩潰。
注意:TensorFlow 現在發展很快,這些文章目前是基於 1.0.0 版本編寫的。
--------文章來源:TensorFlow極簡教程:創建、保存和恢復機器學習模型
推薦閱讀:
※用戶數據使用合規實務指南
※大數據那些事(2):三駕馬車之永垂不朽的GFS
※卷積?神經?網路?教你從讀懂詞語開始了解計算機視覺識別最火模型 | CNN入門手冊(上)
※這大概是史上最全的「大數據」學習資源了!
※有了大數據加智能,你願把荷包交給機器打理嗎?
TAG:大数据 | 机器学习 | TensorFlow |