參考極客時間 彭靖田老師:TensorFlow快速入門與實戰
0 數據流圖
TensorFlow 是一個編程系統, 使用圖來表示計算任務。圖中每個節點稱作operation。
通過一個可執行隊列,藉助拓撲排序的方式,把所有入度爲0的節點放入執行隊列中,每執行一個節點,就會更新它的入度和所連接的節點,然後執行下一層次入度爲0的執行隊列,可以進行並行運算。
0.1 有向邊:數據流向
-
張量(Tensor):使用高維數組表示數據。
-
稀疏張量(SparseTensor):有意義的數值存下來索引和值。然後存下來矩陣形狀,不用把所有的值都存下來。
0.2 節點:
- 計算節點(Operation):計算操作,邏輯操作等
- 存儲節點(Variable):變量,訓練對象等,存儲迭代更新的數據
- 數據節點(Placeholder):描述額外輸入的數據
1 基本結構
1.1 張量(Tensor)
就是標量,向量,數組,多維數組的通用表示說法。
張量的描述有兩個重要屬性:
- 數據類型(內部數據類型要一樣)
- 數組形狀
Tensor("Const:0", shape=(1,), dtype=float32)
常見的張量操作:
- tf.constant() 常量,不可變
- tf.Variable() 變量,運行中一直在內存中
- tf.placeholder() 先佔位,高維數據殼
animal = tf.Variable("dog", tf.string)
num = tf.Variable(451, tf.int32)
類型:tf.float,tf.string,tf.int,tf.complex,tf.bool
聲明張量的時候要給定數據和類型。也可以指定在tensorflow裏的名字name=’’,不是變量名
張量的階和維度
注意看 shape=()裏面的部分,裏面有幾個數就是幾階,然後看數的內容判斷數據維度和每維的結構。
0階和1階
# 0 階 數學標量 shape爲空
pai = tf.Variable(3.14159265359, tf.float64)
<tf.Variable 'Variable_1:0' shape=() dtype=float32_ref>
# 1階 數學向量,shape裏一個數,數5表示5個元素
first_primes = tf.Variable([2, 3, 5, 7, 11],tf.int32)
<tf.Variable 'Variable_2:0' shape=(5,) dtype=int32_ref>
2 階和 3 階
# 2 階數組,shape裏兩個數,表示第1維2個元素,下一維每維1個數
m = tf.Variable([[6],[12]], tf.int32)
<tf.Variable 'Variable_3:0' shape=(2, 1) dtype=int32_ref>
# 3 階,shape裏3個數,3維,數表示每個維度對應的元素個數
aaa = tf.Variable([[[1,2],[3,4]],[[1,2],[3,4]]],tf.int32,name='aaa')
<tf.Variable 'aaa_6:0' shape=(2, 2, 2) dtype=int32_ref>
1.2 變量(Variable)
普通的張量(Tensor)在計算結束後內存就會被釋放,變量會被保存在內存之中,每一步訓練的時候進行迭代更新。
-
創建
w = tf.Variable(value,type,name) W = tf.Variable(tf.random_normal(shape=(1, 4), mean=100, stddev=0.5), name="W") b = tf.Variable(tf.zeros([4]), name="b") [<tf.Variable 'W_4:0' shape=(1, 4) dtype=float32_ref>, <tf.Variable 'b_4:0' shape=(4,) dtype=float32_ref>]
-
重新賦值
w.assign(1.0) w.assign_add(2.4)
變量的使用圖:
變量保存與使用(Saver):
-
創建
saver = tf.train.Saver({'W': W, 'b': b}) saver = tf.train.Saver([v1, v2]) saver = tf.train.Saver({v.op.name: v for v in [v1, v2]})
-
保存變量
saver.save(sess, 'MODEL_SAVE_PATH', global_step=global_step)
-
複用變量
saver.restore(sess, ckpt.model_checkpoint_path)
變量創建後啓動sess會話後必須經過初始化(init_op):
init_op = tf.initialize_all_variables()
恢復數據流圖的圖結構:tf.train.import_meta_graph,還有索引index等恢復方法。
1.3 操作(operation)
數據流圖中的節點對應一個具體的操作,是模型訓練運行的實際載體。包含存儲、計算和數據節點。
- 存儲:放模型參數,存儲有狀態的變量
- 數據:佔位描述輸入數據屬性,之後喂數據
- 計算:運算控制操作,負責邏輯表達流程控制
在數據流圖裏,操作的輸入和輸出都是張量,所以在圖內需要使用TF的指定函數來查看某一個變量的值。數據流圖輸入的訓練和測試數據需要用佔位操作符提前聲明。
name = tf.placeholder(dtype, shape, name)
x = tf.placeholder(tf.int32, shape=(), name="x")
在內部用字典的形式填充數據(Feed)後需要run執行才能更新值:
with tf.Session() as sess:
print(sess.run(add, feed_dict={x: 10, y: 5}))
常用的操作:
1.4 會話(Operation)
就是一個運行環境,分配資源去真正執行運算操作,之前只是聲明瞭規則和值,並沒有真的把值賦給變量。
-
創建會話:
sess = tf.Session() with tf.Session() as sess:
-
初始化全局變量
init = tf.initialize_all_variables() sess.run(init) #或 sess.run(tf.global_variables_initializer())
-
更新運算
for step in stepsepoch: sess.run(train_op計算式、節點、變量)
-
關閉會話
sess.close()
先更新值,更新了之後要sess.run()才能取出來值。
sess.run(tf.assign_add(b, [1, 1, 1, 1]))
sess.run(b)
array([1., 1., 1., 1.], dtype=float32)
如果之前數據是使用佔位符placeholder定義的變量,在會話裏run的時候要真正喂入feed_dict數據。
feed_dict = {
images_placeholder: images_feed,
labels_placeholder: labels_feed,
} #佔位的字典,用來作爲每輪batch喂入的數據
with tf.Session() as sess:
print(sess.run(mul, feed_dict={x: 2, y: 3}))
也可以使用估算張量Tensor.eval()和Operation.run()的形式執行,他們最終都是調用的底層:Sess.run()
tf.global_variables_initializer().run() # Operation.run
fetch = y.eval(feed_dict={x: 3.0}) # Tensor.eval
print(fetch) # fetch = w * x + b
可以指定某個執行模塊是用GPU\CPU哪個執行的:
#存儲用CPU
with tf.device("/cpu:0"):
v=tf.Variable(...)
# 大規模運算用GPU
with tf.device("/gpu:0"):
z=tf.matmul(x,y)
1.5 優化器(Optimizer)
模型的優化目標:降低損失函數loss。
cross_entropy = tf.nn.softmax_cross_entropy_with_logits(logits,
onehot_labels,name='xentropy')
#比較前向推理計算輸出和one-hot化標籤的距離
loss = tf.reduce_mean(cross_entropy, name='xentropy_mean')
一般使用迭代求解,設定一個初始解,然後基於特定函數模型計算可行解,直到找到最優解或者達到預設收斂條件。
不同優化算法的迭代策略不同:常見牛頓法、梯度下降法、Adam等。
optimizer = tf.train.GradientDescentOptimizer(FLAGS.learning_rate)
global_step = tf.Variable(0, name='global_step', trainable=False)
# 保存全局訓練步數
train_op = optimizer.minimize(loss, global_step=global_step)
優化器的使用步驟:計算梯度》處理梯度()》應用梯度。
常用優化器:
1.6 評估函數
傳入的logits和標籤參數要與loss函數的一致。
eval_correct = mnist.evaluation(logits, labels_placeholder)
在K個最有可能的預測中可以發現真的標籤,那麼這個操作就會將模型輸出標記爲正確。
eval_correct = tf.nn.in_top_k(logits, labels, 1)
準確率:
true_count += sess.run(eval_correct, feed_dict=feed_dict)
precision = float(true_count) / float(num_examples)
2 TensorBoard 可視化工具
數據處理過程中可視化工具,幫助理解算法提升工作效率。
- 查看數據集分佈
- 數據流圖是否正確實現
- 模型參數和超參數變化趨勢
- 查看評估指標
使用
使用時需要從會話(session)中加載,然後使用FileWriter實例寫入事件文件,最後加載到Tensorboard獲取實例文件中的序列化數據進行展示。
2.1 典型應用形式:
1)首先創建數據流圖:
可以使用tf.name_scope()抽象層節點。
展示的時候可以將一些節點進行抽象,使輸出TF圖像看起來層次關係更明確,之後可以再將抽象層的細節展開顯示。
#只需要定義的時候將參數變量聲明放置在指定的抽象節點之下。
With tf.name_scope('name'):
定義變量。。。。。
w = tf。。。。。。。。。
2)然後創建FileWriter實例
創建filewriter實例,加載到當前數據流圖(graph):
tf.reset_default_graph()
writer = tf.summary.FileWriter(savepath,sess.graph)
在數據流圖會話(sess)中加載的實例寫入到eventfile之中,寫完需要關閉FileWriter的輸出流:
writer.close()
3)啓動tensorboard
將eventfile所在的目錄傳給tensorboard,能夠獲取相關的參數可視化展示。需要制定文件位置和打開的host。
tensorboard --logdir ./ --host localhost
默認本地位置,打開瀏覽器複製進去地址就可以。
可能出現的問題
windows10 打開tensorboard 遇到的問題,在瀏覽器打開提示沒有圖(不能用360,用Chrome)。No scalar data was found.
找到文件保存的位置:
writer = tf.summary.FileWriter(r'D:\project\UCIPre\summary\lr2', sess.graph)
進入cmd,cd到最後一級文件夾上一級,轉到文件夾下後直接用logdir=最後name名。
cd D:\project\UCIPre\summary\
summary>tensorboard --logdir=lr2
剛開始用的anaconda prompt 一直提示打不開,用cmd就可以了。
奇葩的是時好時壞。
2.2 官方文檔推薦形式
1)創建事件文件
所有的即時數據都要在圖表構建階段合併至一個操作(op)中。
summary_op = tf.merge_all_summaries()
2) 實例化FileWriter
在創建好會話(session)之後,可以實例化一個tf.train.SummaryWriter,用於寫入包含了圖表本身和即時數據具體值的事件文件。
summary_writer = tf.train.SummaryWriter(FLAGS.train_dir,
graph_def=sess.graph_def)
3)寫入最新的數據
每次運行summary_op時,都會往事件文件中寫入最新的即時數據,函數的輸出會傳入事件文件讀寫器(writer)的add_summary()函數。
summary_str = sess.run(summary_op, feed_dict=feed_dict)
summary_writer.add_summary(summary_str, step)
參考:中文手冊
動手實現一個簡單的全連接神經網:
只看 Fullnet.py 部分即可。 girhub文件