<u>版權所有,轉載請注明出處</u>
其它相關文章:
tensorflow學習筆記系列(一):前言
tensorflow學習筆記系列(二):tensorflow簡介與安裝
tensorflow學習筆記系列(四):tensorflow實現自動編碼機
tensorflow學習筆記系列(五):tensorflow實現多層感知機
tensorflow學習筆記系列(六):tensorflow實現卷積神經網絡
tensorflow學習筆記系列(七):神經網絡的一些理論知識
tensorflow學習筆記系列(八):TensorBoard介紹
tensorflow學習筆記系列(九):tensorflow源碼解析
- <u>說明:</u>
- 目前已完成(一)~(三)
- 該內容為本人學習tensorflow過程中的筆記,皆為個人理解,難免會存在各種問題,有不當之處請大家批評指正!
基本上每一個語言或者工具都有自己的“hello world” demo,那么學習它們一般都會從這個“hello world”開始。今天我們就來看看tensorflow的“hello world”(非官網)。
在開始編寫“hello world”之前我們先看看tensorflow的編程模型。
一. tensorflow編程模型簡介
這部分的一個很好的教程是官網上的Basic Usage,講解的還是很清晰的。
Tensorflow中的計算可以表示為一個有向圖(directed graph),或稱計算圖(computation graph),其中每一個運算操作將作為一個節點(node),節點與節點之間的連接成為邊(edge),而在計算圖的邊中流動(flow)的數據被稱為張量(tensor),所以形象的看整個操作就好像數據(tensor)在計算圖(computation graphy)中沿著邊(edge)流過(flow)一個個節點(node),這就是tensorflow名字的由來的。
計算圖中的每個節點可以有任意多個輸入和任意多個輸出,每個節點描述了一種運算操作(operation, op),節點可以算作運算操作的實例化(instance)。計算圖描述了數據的計算流程,它也負責維護和更新狀態,用戶可以對計算圖的分支進行條件控制或循環操作。用戶可以使用pyton、C++、Go、Java等語言設計計算圖。tensorflow通過計算圖將所有的運算操作全部運行在python外面,比如通過c++運行在cpu或通過cuda運行在gpu 上,所以實際上python只是一種接口,真正的核心計算過程還是在底層采用c++或cuda在cpu或gpu上運行。
一個 TensorFlow圖描述了計算的過程. 為了進行計算, 圖必須在會話(session)里被啟動. 會話將圖的op分發到諸如CPU或GPU之的備上, 同時提供執行op的方法. 這些方法執行后, 將產生的tensor返回. 在Python語言中, 返回的tensor是numpy ndarray對象; 在C和C++語言中, 返回的tensor是tensorflow::Tensor實例。
從上面的描述中我們可以看到,tensorflow的幾個比較重要的概念:tensor, computation graphy, node, session。正如前面所說,整個操作就好像數據(tensor)在計算圖(computation graphy)中沿著邊(edge)流過(flow)一個個節點(node),然后通過會話(session)啟動計算。所以簡單來說,要完成這整個過程,我們需要的東西是要定義數據、計算圖和計算圖上的節點,以及啟動計算的會話。所以在實際使用中我們要做的大部分工作應該就是定義這些內容了。
二. tensorflow基本使用
正如官方教程里所說:
To use TensorFlow you need to understand how TensorFlow:
- Represents computations as graphs.
- Executes graphs in the context of Sessions.
- Represents data as tensors.
- Maintains state with Variables.
- Uses feeds and fetches to get data into and out of arbitrary operations.
我們只有理解了這些概念,明白它們分別是做什么的,才能掌握tensorflow的使用方法。下面簡單介紹下這些概念及使用。
- 計算圖(computation graphy)
計算圖是由一個個節點和連接各個節點的邊組成,因此要定義一個計算圖,只需要定義好各個節點以及節點的輸入輸出(對應計算圖的邊)。節點代表各種操作,如加法、乘法、卷積運算等等,輸入輸出主要是各種數據(tensor)。下面是一個簡單的計算圖定義方法示例(來自官網):
import tensorflow as tf
# Create a Constant op that produces a 1x2 matrix. The op is
# added as a node to the default graph.
#
# The value returned by the constructor represents the output
# of the Constant op.
matrix1 = tf.constant([[3., 3.]])
# Create another Constant that produces a 2x1 matrix.
matrix2 = tf.constant([[2.],[2.]])
# Create a Matmul op that takes 'matrix1' and 'matrix2' as inputs.
# The returned value, 'product', represents the result of the matrix
# multiplication.
product = tf.matmul(matrix1, matrix2)
當然,我們也可以添加更多更復雜的操作(operation)的節點(node)到計算圖(computation graphy)中,如果增加一些卷積網絡節點、全連接網絡節點等等就可以組建一個神經網絡計算圖了。
- 節點(node)
計算圖中的每個節點可以有任意多個輸入和任意多個輸出,每個節點描述了一種運算操作(operation, op),節點可以算作運算操作的實例化(instance)。一種運算操作代表了一種類型的抽象運算,比如矩陣乘法貨響亮加法。tensorflow內建了很多種運算操作,如下表所示:
類型 | 示例 |
---|---|
標量運算 | Add、Sub、Mul、Div、Exp、Log、Greater、Less、Equal |
向量運算 | Concat、Slice、Splot、Constant、Rank、Shape、Shuffle |
矩陣運算 | Matmul、MatrixInverse、MatrixDeterminant |
帶狀態的運算 | Variable、Assign、AssignAdd |
神經網絡組件 | SoftMax、Sigmoid、ReLU、Convolution2D、MaxPooling |
存儲、恢復 | Save、Restore |
隊列及同步運算 | Enqueue、Dequeue、MutexAcquire、MutexRelease |
控制流 | Merge、Switch、Enter、Leave、NextIteration |
在tensorflow中,也可以通過注冊機制加入新的運算操作或者運算核,這和torch上的注冊機制類似。
- 會話(session)
正如我們前面所說,計算圖里描述的計算并沒有真正執行,只是進行了定義和描述,要實際執行我們就需要在會話(session)里被啟動. 這時session才會將計算圖上的節點操作op分發到諸如CPU或GPU之類的設備上, 同時提供執行op的方法. 這些方法執行后,將產生的tensor返回.
要啟動計算圖,我們收下需要定義一個session對象:
sess = tf.Session()
啟動操作,最簡單的就是調用函數run:
result = sess.run(product)
tensorflow還支持分布式session,將計算圖布置到多個機器上進行計算。由于我這邊不具備該環境,就不介紹這部分內容了。
另外tensorflow還支持交互環境下采用InteractiveSession
定義一個交互session,然后所有的操作都默認在該session上運行,可以直接調用Tensor.eval()
和Operation.run()
兩個方法,如:
# Enter an interactive TensorFlow Session.
import tensorflow as tf
sess = tf.InteractiveSession()
x = tf.Variable([1.0, 2.0])
a = tf.constant([3.0, 3.0])
# Initialize 'x' using the run() method of its initializer op.
x.initializer.run()
# Add an op to subtract 'a' from 'x'. Run it and print the result
sub = tf.sub(x, a)
print(sub.eval())
# ==> [-2. -1.]
# Close the Session when we're done.
sess.close()
- 數據(tensor)
TensorFlow程序使用tensor數據結構來代表所有的數據, 計算圖中的節點間傳遞的數據都是tensor. 你可以把TensorFlow tensor看作是一個n維的數組或列表. 一個 tensor包含一個靜態類型rank, 和一個shape。 - 變量(Variable)
在tensorflow里有一類數據比較特殊,那就是我們需要在整個計算圖執行過程中需要保存的狀態。比如我們在進行神經網絡訓練時要時刻保存并更新的網絡參數,這時我們就需要用到Varibale來保存這些參數。其實,我們在前面的示例中已經用到了變量的定義了,它的定義關鍵字為Variable
,如上面的x = tf.Variable([1.0, 2.0])
。 - feed & fetch
我們都知道,進行機器學習或者神經網絡訓練時,都需要大量的訓練數據。細心的朋友可能注意到,我們前面一直沒講到訓練數據怎么定義,怎么輸入到網絡里。實際上,tensorflow提供了一個feed機制來將tensor直接放置到計算圖的任意節點操作上去。“feed”這個詞用的很形象啊,就像我們在上課學習時,老師拿課本里的各種例子、習題往我們腦子里喂。那么,這個利用這個feed機制我們就可以把訓練數據“喂”到計算圖的輸入中去。一般我們采用placeholder來指定一個feed操作,這個placeholder就像是一個容器一樣來接收訓練數據,然后在最終進行計算時只需要用placehoder里的數據替換計算圖的輸入量就可以了。一個簡單的例子:
input1 = tf.placeholder(tf.float32)
input2 = tf.placeholder(tf.float32)
output = tf.mul(input1, input2)
with tf.Session() as sess:
print(sess.run([output], feed_dict={input1:[7.], input2:[2.]}))
采用兩個placeholder操作來定義兩個輸入,在后面的see.run()里采用feed_dict替換成真正的訓練數據,feed_dict里的才是真正的數據。一般情況,placeholder和feed_dict是搭配使用的。
fetch,正如其字面意思,就是取回數據的意思。我們將計算圖部署到session上進行計算后,需要將計算結果取回,這就是一個fetch。下面是取回多個tensor的例子:
input1 = tf.constant(3.0)
input2 = tf.constant(2.0)
input3 = tf.constant(5.0)
intermed = tf.add(input2, input3)
mul = tf.mul(input1, intermed)
with tf.Session() as sess:
result = sess.run([mul, intermed])
print result
上面就是tensorflow編程模型的一些基本概念和內容。通過上面的介紹,我們可以用一句話來總結tensorflow的一個工作流程:
那么我們也可以簡單總結出tensorflow編程的一個基本步驟:
- 定義數據
- 定義計算圖與變量
- 定義會話
- 進行計算
三. 用tensorflow搭建神經網絡“hello world”
按照我們上一節介紹的tensorflow編程的基本步驟,我們來搭建我們的第一個神經網絡——基于mnist數據集的手寫數字識別,即基于圖片的10分類問題。
此部分可以參考官網教程MNIST For ML Beginners。
MNIST是一個簡單的機器視覺數據集,如下圖所示,它有幾萬張28×28像素的手寫數字組成,這些圖片只包含灰度信息,我們的任務就是對這些手寫數字進行分類,轉成0~9一共10類。
1.定義數據
在神經網絡里我們需要定義的數據就是輸入訓練/測試數據,而變量用來存儲網絡模型里的各種參數。如:
# 輸入數據(包括訓練數據和測試數據)
x = tf.placeholder( tf.float32, [None, 784] )
y_ = tf.placeholder( tf.float32, [None, 10] )
這里我們把圖片的2828個像素展開成一維列向量(2828-784)
2.定義計算圖與變量
對于神經網絡來說,涉及到的操作主要有三部分:網絡模型定義,損失函數定義、訓練/優化方法定義。那么我們的計算圖基本也由這三部分的定義組成。(當然還可能包括其它部分,如輸入數據初始化操作,網絡參數初始化等等,這里我們不討論)
- 網絡模型定義
這里我們定義一個最簡單的單層全連接網絡,計算公式為:y=Wx+b
,然后利用softmax來計算預測概率,預測概率最大的對應預測的分類。我需要定義兩個變量來保存網絡參數W
和b
的狀態。
W = tf.Variable( tf.zeros([784,10]) )
b = tf.Variable( tf.zeros([10]) )
y = tf.nn.softmax( tf.matmul(x,W) + b )
- 損失函數定義
采用cross-entropy作為損失函數,它的公式為:$H_{y'}\left(y\right)=-\underset{i}{{\textstyle \sum}}y'{i}\log\left(y{i}\right)$。(才發現簡書竟然不支持Latex,尷尬。。。)
cross_entropy = tf.reduce_mean( -tf.reduce_sum( y_*tf.log(y), reduction_indices=[1] ) )
- 訓練/優化方法定義
神經網絡常采用SGD(Stochastic Gradient Descent)進行網絡的優化訓練。tensorflow會自動根據前面定義的計算圖進行forward和backward計算并更新參數。
train_step = tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy)
3.定義會話
按照前面的方法,定義一個session即可。但是還要記住對所有的變量進行全局初始化。
sess = tf.InteractiveSession()
tf.global_variables_initializer().run() #由于是InteractiveSession可以直接run
或者
sess = tf.Session()
init = tf.global_variables_initializer()
sess.run()
4.進行計算
對于神經網絡來說,就是要開始迭代進行訓練和評估,降低損失函數。
# training
for i in range(10000):
batch_xs, batch_ys = mnist.train.next_batch(100)
train_step.run( {x:batch_xs, y_:batch_ys} ) #InteractiveSession
# sess.run(train_step, feed_dict={x:batch_xs, y_:batch_ys}) #非InteractiveSession
# eval
correct_prediction = tf.equal( tf.argmax(y,1), tf.argmax(y_,1) )
accuracy = tf.reduce_mean( tf.cast(correct_prediction, tf.float32) )
print(accuracy.eval( {x:mnist.test.images, y_:mnist.test.labels} )) #InteractiveSession
print(sess.run(accuracy, feed_dict={x:mnist.test.images, y_:mnist.test.labels})#非InteractiveSession
以上就是整個神經網絡的搭建過程。這里只采用的單層全連接網絡,但是準確率依然達到了92%左右,如果我們采用卷積神經網絡等更復雜的網絡,可以將準確率提高到99%。
以上只是搭建一個神經網絡的基本框架,當然實際中還是數據預處理、參數初始化、超參數設置等問題,這些就需要在實際使用過程中慢慢學習了。
以下是該網絡的全部代碼:
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("MNIST_data/",one_hot=True)
x = tf.placeholder( tf.float32, [None, 784] )
y_ = tf.placeholder( tf.float32, [None, 10] )
W = tf.Variable( tf.zeros([784,10]) )
b = tf.Variable( tf.zeros([10]) )
y = tf.nn.softmax( tf.matmul(x,W) + b )
cross_entropy = tf.reduce_mean( -tf.reduce_sum( y_*tf.log(y), reduction_indices=[1] ) )
train_step = tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy)
session = tf.InteractiveSession()
tf.global_variables_initializer().run()
for i in range(1000):
batch_xs, batch_ys = mnist.train.next_batch(100)
train_step.run( {x:batch_xs, y_:batch_ys} )
# print(i)
correct_prediction = tf.equal( tf.argmax(y,1), tf.argmax(y_,1) )
accuracy = tf.reduce_mean( tf.cast(correct_prediction, tf.float32) )
print(accuracy.eval( {x:mnist.test.images, y_:mnist.test.labels} ))
大家也可以在tensorflow.examples.tutorials下找到官方的示例代碼,或者我本人的github上查看
<div align = center>-END-</div>
<u>版權所有,轉載請注明出處</u>