《TensorFlow實戰Google深度學習框架》API整理(三)

目錄

 

Ch5:MNIST數字識別問題

from tensorflow.examples.tutorials.mnist import input_data

tf.nn.relu()

tf.truncated_normal()

tf.argmax()

tf.nn.sparse_softmax_cross_entropy_with_logits()

tf.contrib.layers.l2_regularizer()

tf.control_dependencies()/tf.no_op()

tf.cast()

tf.train.Saver()

tf.train.import_meta_graph()

tf.assign()

其它

參考


Ch5:MNIST數字識別問題

from tensorflow.examples.tutorials.mnist import input_data

#將數據集提取爲三個部分:mnist.trainmnist.testmnist.validation,每個部分包含有imageslabelstraintestvalidation中樣本的數量分別爲55000100005000

mnist = input_data.read_data_sets("../../datasets/MNIST_data/", one_hot=True)
batch_size = 100
xs, ys = mnist.train.next_batch(batch_size)    # 從train的集合中選取batch_size個訓練數據。

tf.nn.relu()

線性整流函數(Rectified Linear Unit, ReLU),又稱修正線性單元。等同於max(0,x),將輸入小於0的值賦值爲0,輸入大於0的值不變。

import tensorflow as tf
 
a = tf.constant([-1.0, 2.0,-3.6])
with tf.Session() as sess:
    b = tf.nn.relu(a)
    print(sess.run(b))

#實際上是上一章調用ema的average接口,來獲取當前時序數據的指數滑動平均值

avg_class.average(weights2)

tf.truncated_normal()

tf.truncated_normal(shape, mean, stddev) :shape表示生成張量的維度,mean是均值,stddev是標準差。這個函數產生正態分佈,均值和標準差自己設定。這是一個截斷的產生正態分佈的函數,就是說產生正態分佈的值如果與均值的差值大於兩倍的標準差,那就重新生成。和一般的正態分佈的產生隨機數據比起來,這個函數產生的隨機數與均值的差距不會超過兩倍的標準差,但是一般的別的函數是可能的。

tf.argmax()

tf.argmax(vector, 1):返回的是vector中的最大值的索引號,如果vector是一個向量,那就返回一個值,如果是一個矩陣,那就返回一個向量,這個向量的每一個維度都是相對應矩陣行的最大值元素的索引號。

import tensorflow as tf
import numpy as np
 
A = [[1,3,4,5,6]]
B = [[1,3,4], [2,4,1]]
 
with tf.Session() as sess:
    print(sess.run(tf.argmax(A, 1)))
print(sess.run(tf.argmax(B, 1)))

輸出:
[4]
[2 1]

tf.nn.sparse_softmax_cross_entropy_with_logits()

注意與tf.nn.sigmoid_cross_entropy_with_logits以及tf.nn.softmax_cross_entropy_with_logits的區別和聯繫。首先顧名思義,tf.nn.sparse_softmax_cross_entropy_with_logits和tf.nn.softmax_cross_entropy_with_logits都是將輸入送到softmax層,再利用softmax層的輸入和實際的標籤數據,來計算交叉熵,交叉熵是分類問題中常見的損失函數。二者的區別主要在於二者使用的標籤真值形式是不同的

  • sparse_softmax_cross_entropy_with_logits:

使用的是實數來表示類別,數據類型爲int16,int32,或者 int64,標籤大小範圍爲[0,num_classes-1],標籤的維度爲[batch_size]大小

  • softmax_cross_entropy_with_logits

使用的是one-hot二進制碼來表示類別,數據類型爲float16,float32,或者float64,維度爲[batch_size, num_classes]。這裏需要說明一下的時,標籤數據類型並不是Bool型的。這是因爲實際上在tensorflow中,softmax_cross_entropy_with_logits中的每一個類別是一個概率分佈,tensorflow中對該模塊的說明中明確指出了這一點,Each row labels[i] must be a valid probability distribution。很顯然,one-hot的二進碼也可以看是一個有效的概率分佈。

import tensorflow as tf

sess = tf.InteractiveSession()
logits = tf.constant([[1.0, 2.0, 3.0], [1.0, 2.0, 3.0], [1.0, 2.0, 3.0]])
labels = tf.constant([[0.0, 0.0, 1.0], [0.0, 0.0, 1.0], [0.0, 0.0, 1.0]])
softmax = tf.nn.softmax(logits)
sparse_labels = tf.argmax(labels, 1)
cross_entropy = -tf.reduce_sum(labels * tf.log(softmax))
cross_entropy2 = tf.reduce_sum(tf.nn.softmax_cross_entropy_with_logits(logits=logits, labels=labels))
cross_entropy3 = tf.reduce_sum(tf.nn.sparse_softmax_cross_entropy_with_logits(logits=logits, labels=sparse_labels))
print("sparse_labels                        : {}".format(sparse_labels.eval()))
print("cross entropy by tf                  : %.4f" % cross_entropy.eval())
print("cross entropy by softmax_cross       : %.4f" % cross_entropy2.eval())
print("cross entropy by sparse_softmax_cross: %.4f" % cross_entropy3.eval())

注意:tf.nn.softmax函數默認(dim=-1)是對張量最後一維的shape=(p,)向量進行softmax計算,得到一個概率向量。不同的是,tf.nn.sigmoid函數對一個張量的每一個標量元素求得一個概率。也就是說tf.nn.softmax默認針對1階張量進行運算,可以通過指定dim來針對1階以上的張量進行運算,但不能對0階張量進行運算。而tf.nn.sigmoid是針對0階張量,。

下面說說tf.nn.sigmoid_cross_entropy_with_logits:不同於softmax系列函數是張量中向量與向量間的運算。sigmoid_cross_entropy_with_logits函數則是張量中標量與標量間的運算。

z = 0.8
x = 1.3
cross_entropy4 = tf.nn.sigmoid_cross_entropy_with_logits(labels=z, logits=x)
# tf.nn.sigmoid_cross_entropy_with_logits的具體實現:
cross_entropy5 = - z * tf.log(tf.nn.sigmoid(x)) \
                 - (1-z) * tf.log(1-tf.nn.sigmoid(x))
sess = tf.InteractiveSession()
print(sess.run(cross_entropy4))
print(sess.run(cross_entropy5))

cross_entropy4 與cross_entropy5 的值是相等的。sigmoid_cross_entropy_with_logits的具體實現就是

如果sigmoid_cross_entropy_with_logits的labels和logits是相同shape的張量,輸出結果則是與labels和logits有相同shape的張量。張量的每個元素都是labels和logits相對的值捉對按上述方法計算出來的交叉熵。

tf.contrib.layers.l2_regularizer()

創建一個L2正則化方法

tf.control_dependencies()/tf.no_op()

在有些機器學習程序中我們想要指定某些操作執行的依賴關係,這時我們可以使用tf.control_dependencies()來實現。control_dependencies(control_inputs)返回一個控制依賴的上下文管理器,使用with關鍵字可以讓在這個上下文環境中的操作都在control_inputs 執行。

with g.control_dependencies([a, b, c]):
  # `d` and `e` will only run after `a`, `b`, and `c` have executed.
  d = ...
  e = ...

可以嵌套control_dependencies 使用

with g.control_dependencies([a, b]):
  # Ops constructed here run after `a` and `b`.
  with g.control_dependencies([c, d]):
# Ops constructed here run after `a`, `b`, `c`, and `d`.

可以傳入None 來消除依賴:

with g.control_dependencies([a, b]):
  # Ops constructed here run after `a` and `b`.
  with g.control_dependencies(None):
    # Ops constructed here run normally, not waiting for either `a` or `b`.
    with g.control_dependencies([c, d]):
      # Ops constructed here run after `c` and `d`, also not waiting
      # for either `a` or `b`.

在訓練模型時,我們每步訓練可能要執行兩種操作,op a,b這時我們就可以使用如下代碼

with tf.control_dependencies([a, b]):
    c= tf.no_op(name='train') # tf.no_op;什麼也不做
sess.run(c)
# 也可以將其替換爲
c= tf.group([a, b])
sess.run(c)

tf.cast()

tf.cast()函數的作用是執行 tensorflow 中張量數據類型轉換,比如讀入的圖片如果是int8類型的,一般在要在訓練前把圖像的數據格式轉換爲float32。

cast定義:

cast(x, dtype, name=None)

第一個參數 x:   待轉換的數據(張量)

第二個參數 dtype: 目標數據類型

第三個參數 name: 可選參數,定義操作的名稱

tf.train.Saver()

模型保存,先要創建一個Saver對象:如

saver = tf.train.Saver(max_to_keep=0)

這裏的max_keep參數代表的是保存模型的個數,默認爲5。

TensorFlow中的Saver對象是用於參數保存和恢復的。其實 創建 saver對象時使用的鍵值對就是表達了一種對應關係:

save時, 表示:variable的值應該保存到 checkpoint文件中的哪個 key

restore時,表示:checkpoint文件中key對應的值,應該restore到哪個variable

參數會保存到 checkpoint 文件中,通過鍵值對的形式在 checkpoint中存放着。如果 Saver 的構造函數中傳的是 dict,那麼在 save 的時候,checkpoint文件中存放的就是對應的 key-value。如下:

import tensorflow as tf
# Create some variables.
v1 = tf.Variable(1.0, name="v1")
v2 = tf.Variable(2.0, name="v2")

saver = tf.train.Saver({"variable_1":v1, "variable_2": v2})
# Use the saver object normally after that.
with tf.Session() as sess:
    tf.global_variables_initializer().run()
saver.save(sess, 'test-ckpt/model-2')

我們利用官方提供的工具來查看一下checkpoint中保存了什麼

from tensorflow.python.tools.inspect_checkpoint import print_tensors_in_checkpoint_file

print_tensors_in_checkpoint_file("test-ckpt/model-2", None, True)
# 輸出:
#tensor_name:  variable_1
#1.0
#tensor_name:  variable_2
#2.0

如果構建saver對象的時候,我們傳入的是 list, 那麼將會用對應 Variable 的 variable.op.name 作爲 key。

import tensorflow as tf
# Create some variables.
v1 = tf.Variable(1.0, name="v1")
v2 = tf.Variable(2.0, name="v2")

saver = tf.train.Saver([v1, v2])
# Use the saver object normally after that.
with tf.Session() as sess:
    tf.global_variables_initializer().run()
saver.save(sess, 'test-ckpt/model-2')
我們再使用官方工具打印出 checkpoint 中的數據,得到

tensor_name:  v1
1.0
tensor_name:  v2
2.0

如果我們現在想將 checkpoint 中v2的值restore到v1 中,v1的值restore到v2中,我們該怎麼做?

這時,我們只能採用基於 dict 的 saver

import tensorflow as tf
# Create some variables.
v1 = tf.Variable(1.0, name="v1")
v2 = tf.Variable(2.0, name="v2")

saver = tf.train.Saver({"variable_1":v1, "variable_2": v2})
# Use the saver object normally after that.
with tf.Session() as sess:
    tf.global_variables_initializer().run()
saver.save(sess, 'test-ckpt/model-2')

restore的代碼和save的代碼有所不同

import tensorflow as tf
# Create some variables.
v1 = tf.Variable(1.0, name="v1")
v2 = tf.Variable(2.0, name="v2")
#restore的時候,variable_1對應到v2,variable_2對應到v1,就可以實現目的了。
saver = tf.train.Saver({"variable_1":v2, "variable_2": v1})
# Use the saver object normally after that.
with tf.Session() as sess:
    tf.global_variables_initializer().run()
    saver.restore(sess, 'test-ckpt/model-2')
    print(sess.run(v1), sess.run(v2))
# 輸出的結果是 2.0 1.0,如我們所期望的那樣

回顧總結:

save時, 表示:variable的值應該保存到 checkpoint文件中的哪個 key下;restore時,表示:checkpoint文件中key對應的值,應該restore到哪個variable。

tf.train.import_meta_graph()

import_meta_graph將定義在.meta的網絡導入到當前圖中。所以,這會替你創造圖/網絡,但我們仍然需要導入在這張圖上訓練好的參數。一般來說加載完成模型之後,會需要手動加載參數,所以會和saver.restore()api聯合使用。

with tf.Session() as sess:
  new_saver = tf.train.import_meta_graph('my_test_model-1000.meta')
  new_saver.restore(sess, tf.train.latest_checkpoint('./'))

tf.assign()

tf.assign(A, new_number): 這個函數的功能主要是把A的值變爲new_number

直接在保存模型時保存時序數據的ema值

v = tf.Variable(0, dtype = tf.float32, name="v")
ema = tf.train.ExponentialMovingAverage(0.99)
print(ema.variables_to_restore())

saver = tf.train.Saver(ema.variables_to_restore())
with tf.Session() as sess:
saver.restore(sess, "Saved_model/model2.ckpt")

其它

tf.get_default_graph().as_graph_def():得到當前圖的計算節點信息

graph_util.convert_variables_to_constants():將相關節點的values固定

tf.gfile.GFile(): # 保存模型

graph_def.ParseFromString(f.read())通過得到模型中的圖和變量數據

tf.import_graph_def()加載目前的圖

gfile.FastGFile()

tf.gfile.FastGFile(path,decodestyle)

函數功能:實現對圖片的讀取。

函數參數:(1)path:圖片所在路徑 (2)decodestyle:圖片的解碼方式。(‘r’:UTF-8編碼; ‘rb’:非UTF-8編碼)

saver.export_meta_graph():詳見https://zhuanlan.zhihu.com/p/31308381

tf.train.NewCheckpointReader() 用於創建一個reader對象,進而導出持久化模型的所有變量

reader = tf.train.NewCheckpointReader("/home/penglu/Desktop/lp/model.ckpt")
variables = reader.get_variable_to_shape_map() 
for ele in variables:
	print(ele)

reader.get_tensor(key) 用於查看ckpt模型文件中的變量

參考

Saver(保存與加載模型)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章