深度學習利器:TensorFlow實戰
深度學習及TensorFlow簡介
深度學習目前已經被應用到圖像識別,語音識別,自然語言處理,機器翻譯等場景并取得了很好的行業應用效果。至今已有數種深度學習框架,如TensorFlow、Caffe、Theano、Torch、MXNet,這些框架都能夠支持深度神經網絡、卷積神經網絡、深度信念網絡和遞歸神經網絡等模型。TensorFlow最初由Google Brain團隊的研究員和工程師研發,目前已成為GitHub上最受歡迎的機器學習項目。
TensorFlow開源一周年以來,已有500+contributors,以及11000+個commits。目前采用TensorFlow平臺,在生產環境下進行深度學習的公司有ARM、Google、UBER、DeepMind、京東等公司。目前谷歌已把TensorFlow應用到很多內部項目,如谷歌語音識別,GMail,谷歌圖片搜索等。TensorFlow主要特性有:
使用靈活:TensorFlow是一個靈活的神經網絡學習平臺,采用圖計算模型,支持High-Level的API,支持Python、C++、Go、Java接口。
跨平臺:TensorFlow支持CPU和GPU的運算,支持臺式機、服務器、移動平臺的計算。并從r0.12版本支持Windows平臺。
產品化:TensorFlow支持從研究團隊快速遷移學習模型到生產團隊。實現了研究團隊發布模型,生產團隊驗證模型,構建起了模型研究到生產實踐的橋梁。
高性能:TensorFlow中采用了多線程,隊列技術以及分布式訓練模型,實現了在多CPU、多GPU的環境下分布式訓練模型。
本文主要介紹TensorFlow一些關鍵技術的使用實踐,包括TensorFlow變量、TensorFlow應用架構、TensorFlow可視化技術、GPU使用,以及HDFS集成使用。
TensorFlow變量
TensorFlow中的變量在使用前需要被初始化,在模型訓練中或訓練完成后可以保存或恢復這些變量值。下面介紹如何創建變量,初始化變量,保存變量,恢復變量以及共享變量。
#創建模型的權重及偏置
weights = tf.Variable(tf.random_normal([784, 200], stddev=0.35), name="weights")
biases = tf.Variable(tf.zeros([200]), name="biases")
指定變量所在設備為CPU:0
with tf.device("/cpu:0"):
v = tf.Variable(...)
初始化模型變量
init_op = tf.global_variables_initializer()
sess=tf.Session()
sess.run(init_op)
保存模型變量,由三個文件組成model.data,model.index,model.meta
saver = tf.train.Saver()
saver.restore(sess, "/tmp/model")
恢復模型變量
saver.restore(sess, "/tmp/model")</code></pre>
在復雜的深度學習模型中,存在大量的模型變量,并且期望能夠一次性地初始化這些變量。TensorFlow提供了tf.variable_scope和tf.get_variable兩個API,實現了共享模型變量。tf.get_variable(<name>, <shape>, <initializer>):表示創建或返回指定名稱的模型變量,其中name表示變量名稱,shape表示變量的維度信息,initializer表示變量的初始化方法。tf.variable_scope(<scope_name>):表示變量所在的命名空間,其中scope_name表示命名空間的名稱。共享模型變量使用示例如下:
#定義卷積神經網絡運算規則,其中weights和biases為共享變量
def conv_relu(input, kernel_shape, bias_shape):
# 創建變量"weights".
weights = tf.get_variable("weights", kernel_shape, initializer=tf.random_normal_initializer())
# 創建變量 "biases".
biases = tf.get_variable("biases", bias_shape, initializer=tf.constant_initializer(0.0))
conv = tf.nn.conv2d(input, weights, strides=[1, 1, 1, 1], padding='SAME')
return tf.nn.relu(conv + biases)
定義卷積層,conv1和conv2為變量命名空間
with tf.variable_scope("conv1"):
# 創建變量 "conv1/weights", "conv1/biases".
relu1 = conv_relu(input_images, [5, 5, 32, 32], [32])
with tf.variable_scope("conv2"):
# 創建變量 "conv2/weights", "conv2/biases".
relu1 = conv_relu(relu1, [5, 5, 32, 32], [32])</code></pre>
TensorFlow應用架構
TensorFlow的應用架構主要包括模型構建,模型訓練,及模型評估三個方面。模型構建主要指構建深度學習神經網絡,模型訓練主要指在TensorFlow會話中對訓練數據執行神經網絡運算,模型評估主要指根據測試數據評估模型精確度。如下圖所示:

網絡模型,損失方程,模型訓練操作定義示例如下:
#兩個隱藏層,一個logits輸出層
hidden1 = tf.nn.relu(tf.matmul(images, weights) + biases)
hidden2 = tf.nn.relu(tf.matmul(hidden1, weights) + biases)
logits = tf.matmul(hidden2, weights) + biases
損失方程,采用softmax交叉熵算法
cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits( logits, labels, name='xentropy')
loss = tf.reduce_mean(cross_entropy, name='xentropy_mean')
選定優化算法及定義訓練操作
optimizer = tf.train.GradientDescentOptimizer(learning_rate)
global_step = tf.Variable(0, name='global_step', trainable=False)
train_op = optimizer.minimize(loss, global_step=global_step)
模型訓練及模型驗證示例如下:
加載訓練數據,并執行網絡訓練
for step in xrange(FLAGS.max_steps):
feed_dict = fill_feed_dict(data_sets.train, images_placeholder, labels_placeholder)
_, loss_value = sess.run([train_op, loss], feed_dict=feed_dict)
加載測試數據,計算模型精確度
for step in xrange(steps_per_epoch):
feed_dict = fill_feed_dict(data_set, images_placeholder, labels_placeholder)
true_count += sess.run(eval_correct, feed_dict=feed_dict)</code></pre>
TensorFlow可視化技術
大規模的深度神經網絡運算模型是非常復雜的,并且不容易理解運算過程。為了易于理解、調試及優化神經網絡運算模型,數據科學家及應用開發人員可以使用TensorFlow可視化組件:TensorBoard。TensorBoard主要支持TensorFlow模型可視化展示及統計信息的圖表展示。TensorBoard應用架構如下:

TensorFlow可視化技術主要分為兩部分:TensorFlow摘要模型及TensorBoard可視化組件。在摘要模型中,需要把模型變量或樣本數據轉換為TensorFlow summary操作,然后合并summary操作,最后通過Summary Writer操作寫入TensorFlow的事件日志。TensorBoard通過讀取事件日志,進行相關摘要信息的可視化展示,主要包括:Scalar圖、圖片數據可視化、聲音數據展示、圖模型可視化,以及變量數據的直方圖和概率分布圖。TensorFlow可視化技術的關鍵流程如下所示:
#定義變量及訓練數據的摘要操作
tf.summary.scalar('max', tf.reduce_max(var))
tf.summary.histogram('histogram', var)
tf.summary.image('input', image_shaped_input, 10)
定義合并變量操作,一次性生成所有摘要數據
merged = tf.summary.merge_all()
定義寫入摘要數據到事件日志的操作
train_writer = tf.train.SummaryWriter(FLAGS.log_dir + '/train', sess.graph)
test_writer = tf.train.SummaryWriter(FLAGS.log_dir + '/test')
執行訓練操作,并把摘要信息寫入到事件日志
summary, _ = sess.run([merged, train_step], feed_dict=feed_dict(True))
train_writer.add_summary(summary, i)
下載示例code,并執行模型訓練
python mnist_with_summaries.py
啟動TensorBoard,TensorBoard的UI地址為http://ip_address:6006
tensorboard --logdir=/path/to/log-directory</code></pre>
TensorBoard Scalar圖如下所示,其中橫坐標表示模型訓練的迭代次數,縱坐標表示該標量值,例如模型精確度,熵值等。TensorBoard支持這些統計值的下載。

TensorFlow Image摘要信息如下圖所示,該示例中顯示了測試數據和訓練數據中的手寫數字圖片。

TensorFlow圖模型如下圖所示,可清晰地展示模型的訓練流程,其中的每個方框表示變量所在的命名空間。包含的命名空間有input(輸入數據),input_reshape(矩陣變換,用于圖形化手寫數字), layer1(隱含層1), layer2(隱含層2), dropout(丟棄一些神經元,防止過擬合), accuracy(模型精確度), cross_entropy(目標函數值,交叉熵), train(訓練模型)。例如,input命名空間操作后的tensor數據會傳遞給input_reshape,train,accuracy,layer1,cross_entropy命名空間中的操作。

TensorFlow變量的概率分布如下圖所示,其中橫坐標為迭代次數,縱坐標為變量取值范圍。圖表中的線表示概率百分比,從高到底為[maximum, 93%, 84%, 69%, 50%, 31%, 16%, 7%, minimum]。例如,圖表中從高到底的第二條線為93%,對應該迭代下有93%的變量權重值小于該線對應的目標值。

上述TensorFlow變量概率分布對應的直方圖如下圖所示:

TensorFlow GPU使用
GPU設備已經廣泛地應用于圖像分類,語音識別,自然語言處理,機器翻譯等深度學習領域,并實現了開創性的性能改進。與單純使用CPU相比,GPU 具有數以千計的計算核心,可實現 10-100 倍的性能提升。TensorFlow支持GPU運算的版本為tensorflow-gpu,并且需要先安裝相關軟件:GPU運算平臺CUDA和用于深度神經網絡運算的GPU加速庫CuDNN。在TensorFlow中,CPU或GPU的表示方式如下所示:
"/cpu:0":表示機器中第一個CPU。
"/gpu:0":表示機器中第一個GPU卡。
"/gpu:1":表示機器中第二個GPU卡。
TensorFlow中所有操作都有CPU和GPU運算的實現,默認情況下GPU運算的優先級比CPU高。如果TensorFlow操作沒有指定在哪個設備上進行運算,默認會優選采用GPU進行運算。下面介紹如何在TensorFlow使用GPU:
# 定義使用gpu0執行a*b的矩陣運算,其中a,b,c都在gpu0上執行
with tf.device('/gpu:0'):
a = tf.constant([1.0, 2.0, 3.0, 4.0, 5.0, 6.0], shape=[2, 3], name='a')
b = tf.constant([1.0, 2.0, 3.0, 4.0, 5.0, 6.0], shape=[3, 2], name='b')
c = tf.matmul(a, b)
通過log_device_placement指定在日志中輸出變量和操作所在的設備
sess = tf.Session(config=tf.ConfigProto(log_device_placement=True))
print sess.run(c)</code></pre>
本實驗環境下只有一個GPU卡,設備的Device Mapping及變量操作所在設備位置如下:
#設備的Device Mapping
/job:localhost/replica:0/task:0/gpu:0 -> device: 0, name: Tesla K20c, pci bus id: 0000:81:00.0
變量操作所在設備位置
a: (Const): /job:localhost/replica:0/task:0/gpu:0
b: (Const): /job:localhost/replica:0/task:0/gpu:0
(MatMul)/job:localhost/replica:0/task:0/gpu:0</code></pre>
默認配置下,TensorFlow Session會占用GPU卡上所有內存。但TesnorFlow提供了兩個GPU內存優化配置選項。config.gpu_options.allow_growth:根據程序運行情況,分配GPU內存。程序開始的時候分配比較少的內存,隨著程序的運行,增加內存的分配,但不會釋放已經分配的內存。config.gpu_options.per_process_gpu_memory_fraction:表示按照百分比分配GPU內存,例如0.4表示分配40%的GPU內存。示例代碼如下:
#定義TensorFlow配置
config = tf.ConfigProto()
配置GPU內存分配方式
config.gpu_options.allow_growth = True
config.gpu_options.per_process_gpu_memory_fraction = 0.4
session = tf.Session(config=config, ...)</code></pre>
TensorFlow與HDFS集成使用
HDFS是一個高度容錯性的分布式系統,能提供高吞吐量的數據訪問,非常適合大規模數據集上的應用。TensorFlow與HDFS集成示例如下:
#配置JAVA和HADOOP環境變量
source $HADOOP_HOME/libexec/hadoop-config.sh
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$JAVA_HOME/jre/lib/amd64/server
執行TensorFlow運行模型
CLASSPATH=$($HADOOP_HDFS_HOME/bin/hadoop classpath --glob) python tensorflow_model.py
在TensorFlow模型中定義文件的讀取隊列
filename_queue = tf.train.string_input_producer(["hdfs://namenode:8020/path/to/file1.csv", "hdfs://namenode:8020/path/to/file2.csv"])
從文件中讀取一行數據,value為所對應的行數據
reader = tf.TextLineReader()
key, value = reader.read(filename_queue)
把讀取到的value值解碼成特征向量,record_defaults定義解碼格式及對應的數據類型
record_defaults = [[1], [1], [1], [1], [1]]
col1, col2, col3, col4, col5 = tf.decode_csv(value, record_defaults=record_defaults)
features = tf.pack([col1, col2, col3, col4])
with tf.Session() as sess:
定義同步對象,并啟動相應線程把HDFS文件名插入到隊列
coord = tf.train.Coordinator()
threads = tf.train.start_queue_runners(coord=coord)
for i in range(1200):
# 從文件隊列中讀取一行數據
example, label = sess.run([features, col5])
請求停止隊列的相關線程(包括進隊及出隊線程)
coord.request_stop()
等待隊列中相關線程結束(包括進隊及出隊線程)
coord.join(threads)</code></pre>
參考文獻
來自:http://www.infoq.com/cn/articles/deeplearning-tensorflow-actual-combat