簡介
深度學習的框架有不少:TensorFlow、Caffe、Theano、Torch...TensorFlow做爲谷歌重要的開源項目,有很是火熱的開源的開源社區推進着開源項目的發展,它能讓項目有旺盛的生命力並在生命週期中不斷涌現新的功能並以較快的迭代來更新Bug修復。Keras是在TensorFlow基礎上構建的高層API,Keras在TensorFlow中。html
Tensorflow中實現代碼可能跟咱們python程序有那麼一點不同,由於tensorflow有他本身的框架和體系,會用本身更加適配的方式來表達描述過程。python
基本用法
tensorflow的程序一般被組織成兩個相互獨立的階段,一個構建計算圖(tf.Graph
)的階段,一個運行計算圖(tf.Session
)的階段算法
在構建計算圖階段:由張量與操做,張量Tensor主要保存了3個屬性: 名字(name)、維度(shape)、類型(type);操做OP,圖中的節點。
shell
在運行計算圖階段:使用會話執行構建好的圖中的操做api
TensorFlow圖描述了計算的過程。爲了進行計算, 圖必須在會話
裏被啓動。會話
將圖的OP分發到諸如CPU或GPU之類的設備
上, 同時提供執行OP的方法。這些方法執行後, 將產生的tensor返回。數組
import tensorflow as tf # 構建加法 計算圖 a = tf.constant(2.0, dtype=tf.float32) b = tf.constant(3.0) c = tf.add(a, b) print("a", a) # a Tensor("Const:0", shape=(), dtype=float32) print("b", b) # b Tensor("Const_1:0", shape=(), dtype=float32) print("c", c) # c Tensor("add:0", shape=(), dtype=int32) # 開啓會話,在會話中運行計算圖 with tf.Session() as sess: c_t = sess.run(c) # 把run以後的結果保存在c_t中 print(sess.run(b)) # 3.0 print("在會話中run後的加法結果", c_t) # 5
以上的圖中,有是三個節點,兩個constant節點,一個add節點,爲了獲得加法結果,再次強調咱們必須在會話中run這個圖瀏覽器
計算圖(graph)
圖中包含了操做(tf.Operation)和數據(tf.Tensor)網絡
默認圖
一般TensorFlow會默認幫咱們建立一張圖,session
查看默認圖有兩種方法:app
一、default_g = tf.get_default_graph() # 建立一個默認圖的實例,綁定在default_g
二、op、sess都有graph屬性,默認在一張圖中
a.graph # <tensorflow.python.framework.ops.Graph object at 0x000001E3D5D12940>
sess.graph # <tensorflow.python.framework.ops.Graph object at 0x000001E3D5D12940>
建立圖
new_g = tf.Graph() 建立一張新的圖的實例,綁定在new_g
若是要在這張圖上定義數據和操做,可使用new_g.as_default(),上下文管連器
要在tf.session(graph=new_g)選擇自定義的圖
# 自定義圖 new_g = tf.Graph() # 在本身的圖中定義數據和操做 with new_g.as_default(): a_new = tf.constant([[20]]) # 開啓new_g的會話 with tf.Session(graph=new_g) as new_sess: a_new_value = new_sess.run(a_new) print("新的圖的a的值", a_new_value)
會話(Session)
要評估張量,須要實例化一個tf.Session()對象,在會話中,調用 run 方法來運行圖節點以及查看張量,
sess.run(a) 和Tensor.eval(a) 返回與張量內容相同的numpy 數組
Tensor.eval方法和sess.run()僅在tf.Session處於活躍時才起做用。
with tf.Session() as sess: # 啓動默認圖 print(a.eval()) # 3 print(sess.run(a)) # 3
會話有兩種開啓的方式
一、tf.Session()
二、tf.InteractiveSession(),用於在交互模式中打開會話,ipython,shell,jupyter Notebook。
Session在使用完後須要釋放資源,除了使用sess.close()外,通常使用「with代碼塊」來自動關閉。
tf.Session(graph=None, config=None)
graph=new_graph # new_graph是自定義建立的新的圖的對象實例
config:清晰地顯示操做運行在哪些設備上 若是想要知道設備信息,把config設置成config = tf.ConfigProto(allow_soft_placement=True, log_device_placement=True)
會話的run()
run(fetches, feed_dict=None, options=None, run_metadata=None)
fetches:單一的operation,或者元組operation、列表operation
a = tf.constant(2.) b = tf.constant(3.) c = a+b sess = tf.Session() s = sess.run(c) print(s) print(c.eval(session=sess))
feed_dict:參數容許調用者覆蓋圖中張量的值,運行時賦值。
與tf.placeholder()配合使用,則會檢測值的形狀是否與佔位符匹配。
咱們能夠經過sess.run取回多個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(): result = sess.run([mul, intermed]) print result # 輸出: # [array([ 21.], dtype=float32), array([ 7.], dtype=float32)]
feed操做
使用 tf.placeholder() 爲這些操做建立佔位符,run時候經過feed_dict指定參數替換佔位符。
a = tf.placeholder(tf.float32) b = tf.placeholder(tf.float32) c = tf.add(a,b) with tf.Session() as sess: re = sess.run(c, feed_dict={a:1, b:2.5}) print(re) # 3.5 print(sess.run(c, feed_dict={a:[1., 3.], b:[2., 3.]})) # [3. 6.]
Tensor 張量
張量Tensor有3個屬性: 名字(name)、維度(shape)、類型(type);
0 階張量
一個數字的大小
mammal = tf.Variable("Elephant", tf.string) ignition = tf.Variable(451, tf.int16) floating = tf.Variable(3.14159265359, tf.float64) its_complicated = tf.Variable(12.3 - 4.85j, tf.complex64)
1 階張量
mystr = tf.Variable(["Hello"], tf.string) cool_numbers = tf.Variable([3.14159, 2.71828], tf.float32) first_primes = tf.Variable([2, 3, 5, 7, 11], tf.int32) its_very_complicated = tf.Variable([12.3 - 4.85j, 7.5 - 6.23j], tf.complex64)
2 階張量
mymat = tf.Variable([[7],[11]], tf.int16) myxor = tf.Variable([[False, True],[True, False]], tf.bool) linear = tf.Variable([[4], [9], [16], [25]], tf.int32) squarish = tf.Variable([ [4, 9], [16, 25] ], tf.int32) rank = tf.rank(squarish_squares)
在圖像處理的過程當中,會使用許多4階張量,維度對應批次大小、圖像寬度、圖像高度和顏色通道。
my_image = tf.zeros([10, 299, 299, 3]) # batch x height x width x color
改變形狀:tf.reshape(x, shape)
three = tf.ones([3, 4, 5]) matrix = tf.reshape(three, [6, 10]) #重塑成 6*10 matrixB = tf.reshape(matrix, [3, -1]) # 重塑成 3x20
切片索引的時候[3, -1]列表示重塑成3行任意列。
constant 常量 Tensor
生成0的張量函數 tf.zeros(shape=[2,2], dtypt=tf.float32, namhanghe=None)
生成1的張量函數 tf.ones(shape=[2,2], dtypt=tf.float32, namhanghe=None)
生成都是value值的dims形狀的張量 tf.fill(dims, value, name=None)
import tensorflow as tf t1 = tf.fill([2,3], 3) sess = tf.Session() print(sess.run(t1)) # [[3 3 3] # [3 3 3]]
生成常數 tf.constant(value, dtype=None, Shape=None, name="Const")
numpy數據轉換爲tensorflow數據:data_tensor= tf.convert_to_tensor(data_numpy)
tensorflow數據轉換爲numpy數據:data_numpy = data_tesor.eval()在會話中運行
random 隨機 Tensor
tf.random_normal(shape, mean=0.0, stddev=1.0, dtype=tf.float32, seed=None, name=None)
生成標準正太分佈的隨機張量
tf.truncated_normal(shape, mean=0.0, stddev=1.0, dtype=tf.float32, seed=None, name=None)
shape表示生成張量的維度,mean是均值,stddev是標準差。這個函數產生截斷的正太分佈,就是說產生正太分佈的值與均值的差值大於兩倍的標準差,那就從新生成。和通常的正太分佈的產生隨機數據比起來,這個函數產生的隨機數與均值的差距不會超過兩倍的標準差,可是通常的別的函數是可能的。
tf.random_uniform(shape, minval=0, maxval=None, dtype=tf.float32, seed=None, name=None)
從均勻分佈中返回隨機值,shape形狀、minval最小值、maxval最大值
tf.random_shuffle(value, seed=None, name=None)
沿着要被洗牌的張量的第一個維度,隨機打亂。value要洗牌的張量
initialize 初始化Tensor
tf.constant_initializer(value=0, dtype=tf.float32)
也能夠簡寫爲tf.Constant(),初始化爲常數,這個很是有用,一般偏置項就是用它初始化的。
由它衍生出的兩個初始化方法:
- tf.zeros_initializer(shape, dtype=tf.float32, partition_info=None)
- tf.ones_initializer(dtype=tf.float32, partition_info=None)
- tf.constant_initializer(0),tf.Constant(0)
tf.truncated_normal_initializer(mean=0.0, stddev=1.0, seed=None, dtype=tf.float32)
也可簡寫爲tf.TruncatedNormal(),生成截斷正態分佈的隨機數,這個初始化方法好像在tf中用得比較多。
tf.random_normal_initializer(mean=0.0, stddev=1.0, seed=None, dtype=tf.float32)
用正態分佈產生張量的初始化器,mean均值、stddev方差、seed隨機種子、dtype數據類型。
tf.random_uniform_initializer(minval=0, maxval=None, seed=None, dtype=tf.float32)
初始化均勻分佈的隨機Tensor,參數分別用於指定minval最小值、maxval最大值、seed隨機數種子、dtype類型。
tf.cast(x, dtype, name=None) # 把張量x,變成任何的dtype
變量
變量也是張量的一種
建立變量 variable;get_variable
tensorflow中建立變量的函數有tf.get_variable;tf.Variable
tf.get_variable(name, validate_shape=True, dtype=None, initializer=None, trainable=True, collections=None, caching_device=None, regularizer=None, partitioner=None, custom_getter=None, shape=None)
- name: 變量名(必須設置)
- initializer: 初始化的值
- trainable: 是否能被訓練
- shape: 形狀
例如:建立一個名爲「my_variable」的變量,shape爲[1,2,3]的三維張量。默認狀況下dtype=tf.float32
my_int_variable = tf.get_variable("my_int_variable", shape=[1, 2, 3], dtype=tf.int32, initializer=tf.zeros_initializer)
咱們還能夠將Tensor變量做爲初始化對象,但此時咱們不能初始化形狀,而須要使用初始化張量的形狀
other_variable = tf.get_variable("other_variable", dtype=tf.int32, initializer=tf.constant([23, 42]))
使用tf.Varizble 建立變量
tf.Variable(name=None, validate_shape=True, dtype=None, initial_value=None, trainable=True, collections=None, caching_device=None, variable_def=None, expected_shape=None, import_scope=None)
- dtype: 數據類型
- initial_value: 初始化的值
- trainable: 是否能被訓練
v = tf.get_variable("v", shape=(), initializer=tf.zeros_initializer()) w = v + 1 # 這樣一來w也是tf.Tensor
咱們可使用assign、assign_add方法爲變量tf.Variable賦值
import tensorflow as tf # 建立一個變量, 初始化爲標量 0. state = tf.Variable(0, name="counter") one = tf.constant(1) v = tf.get_variable("v", shape=(), initializer=tf.zeros_initializer()) assignment = v.assign_add(1) # 變量加1 new_value = tf.add(state, one) # new_value = state + 1 update = tf.assign(state, new_value) # state = new_value 只是在描繪圖,並不會真正的執行 # 啓動圖後, 變量必須先通過'初始化'(init) init = tf.global_variables_initializer() # 啓動圖, 運行 op with tf.Session() as sess: sess.run(init) # 運行 'init' print(sess.run(state)) # 打印'state'的初始值 0 print(sess.run(assignment)) # assignment.eval() # 運行 op, 更新 'state', 並打印 'state' for _ in range(3): sess.run(update) print(sess.run(state)) # 0 # 1 # 2 # 3
區別1、使用tf.Variable時候,若是檢測到命名衝突,系統會本身處理。使用tf.get_variable()時,系統不會處理相同變量名的衝突,而會報錯。
tf.Variable() 建立變量
w_1 = tf.Variable(3, name="w_1") w_2 = tf.Variable(1, name="w_1") print(w_1.name) # w_1:0 print(w_2.name) # w_1:0
tf.get_variable() 建立變量
w_1 = tf.get_variable(name="w_1", initializer=1) w_2 = tf.get_variable(name="w_1", initializer=2) # ValueError: Variable w_1 already exists, disallowed. Did you mean to set reuse=True in VarScope?
區別2、tf.Variable()每次都在建立新對象,因此reuse=True和它沒有什麼關係,對於get_vatiable(),若是是一個已經建立的變量對象,就把那個對象返回,若是是以前沒有建立的變量對象的話,就建立一個新的。
with tf.variable_scope("scope1"): w1 = tf.get_variable("w1", shape=[]) w2 = tf.Variable(0.0, name="w2") with tf.variable_scope("scope1", reuse=True): w1_p = tf.get_variable("w1", shape=[]) w2_p = tf.Variable(1.0, name="w2") print(w1 is w1_p) # True w1和w1_p 指向同一個對象 print(w2 is w2_p) # False w2和w2_p 指向不一樣對象
代碼中建立了變量的,「變量」必須通過初始化,而後在會話中運行下面一段進行初始化,一次性初始化全部變量,初始化後,才能調用與顯示。
a = tf.Variable(initial_value=50) b = tf.Variable(initial_value=50) c = tf.add(a, b) init = tf.global_variables_initializer() # 初始化變量 with tf.Session() as sess: # 開啓會話 sess.run(init) # 容許初始化 a_value, b_value, c_value = sess.run([a,b,c]) print("a_value",a_value) print("b_value", b_value) print("c_value", c_value)
tf.global_variables_initializer不會指定變量的初始化順序,所以若是變量的初始值取決另外一個變量的值,那麼頗有可能出現錯誤,因此咱們最好使用variable.initialized_value(),而非veriable,也就是在建立變量的時候給變量初始化。
v = tf.get_variable("v", shape=(), initializer=tf.zeros_initializer()) w = tf.get_variable("w", initializer=v.initialized_value() + 1)
固然咱們也能夠自行初始化變量
session.run(my_variable.initializer) my_variable.initializer.run()
tf.add_to_collection:把變量放入一個集合,把不少變量變成一個列表
tf.get_collection:從一個列表中取出所有變量,是一個列表
tf.add_n:把一個列表的東西都依次加起來
import tensorflow as tf v1 = tf.get_variable(name='v1', shape=[1], initializer=tf.constant_initializer(0)) tf.add_to_collection('loss', v1) v2 = tf.get_variable(name='v2', shape=[1], initializer=tf.constant_initializer(2)) tf.add_to_collection('loss', v2) init = tf.global_variables_initializer() with tf.Session() as sess: sess.run(init) print(tf.get_collection("loss")) # [<tf.Variable 'v1:0' shape=(1,) dtype=float32_ref>, # <tf.Variable 'v2:0' shape=(1,) dtype=float32_ref>] print(sess.run(tf.add_n(tf.get_collection("loss")))) # [2.]
變量命名空間 variable_scope;tf.name_scope
tensorflow中建立變量命名空間域的函數有 tf.name_scope;tf.variable_scope
使用tf.variable_scope()修改變量的命名空間,使得代碼的結構更加清晰,還可以使得TensorBoard更加整潔。同時給變量取名name也可使得TensorBoard更加整潔。
首先看看比較簡單的tf.name_scope("scope_name")
tf.name_scope主要結合tf.Variable()來使用,它的主要目的是爲了方便管理參數命名。
import tensorflow as tf with tf.name_scope('conv1'): weights1 = tf.Variable([1.0, 2.0], name='weights') bias1 = tf.Variable([0.3], name='bias') # 下面是在另一個命名空間來定義變量的 with tf.name_scope('conv2'): weights2 = tf.Variable([4.0, 2.0], name='weights') bias2 = tf.Variable([0.33], name='bias') # 因此,實際上weights1 和 weights2 這兩個引用名指向了不一樣的空間,不會衝突 print(weights1.name) # conv1/weights:0 print(weights2.name) # conv2/weights:0 # 這時候若是再次執行上面的代碼,就會再生成其餘命名空間 with tf.name_scope('conv1'): weights1 = tf.Variable([1.0, 2.0], name='weights') bias1 = tf.Variable([0.3], name='bias') with tf.name_scope('conv2'): weights2 = tf.Variable([4.0, 2.0], name='weights') bias2 = tf.Variable([0.33], name='bias') print(weights1.name) # conv1_1/weights:0 print(weights2.name) # conv2_1/weights:0
咱們再來看看tf.variable_scope("scope_name")
tf.variable_scope()主要結合tf.get_variable()來使用,實現 變量共享。
with tf.variable_scope('v_scope'): Weights1 = tf.get_variable('Weights', shape=[2,3]) bias1 = tf.get_variable('bias', shape=[3]) # 下面來共享上面已經定義好的變量 # 在下面的 scope 中的get_variable()變量必須通過get_variable()定義過了,才能設置 reuse=True,不然會報錯reuse=True,不然會報錯 with tf.variable_scope('v_scope', reuse=True): Weights2 = tf.get_variable('Weights') print(Weights1.name) # v_scope/Weights:0 print(Weights2.name) # v_scope/Weights:0
咱們能夠看到這兩個變量命名空間名都是 v_scope,reuse=True只是讓後一個v_scope重用上一個v_scope的全部變量。在後一個v_scope中定義的變量,必須是已經在上一個v_scope中通過get_variable定義過的,不然會報錯。tf.Variable()每次都在建立新對象,而tf.get_variable()若是變量存在,則使用之前建立的變量,若是不存在,則新建立一個變量。
從輸出咱們能夠看出來,這兩個引用名稱指向的是同一個內存對象
共享變量有兩種方法
# 方法一 with tf.variable_scope("name") as scope: scope.reuse_variables() # 方法二 with tf.variable_scope("name", reuse=True): scope.reuse_variables()
咱們同時使用Variable和get_variable看看輸出結果:
with tf.variable_scope('v_scope') as scope1: Weights1 = tf.get_variable('Weights', shape=[2,3]) bias1 = tf.Variable([0.52], name='bias') # 下面來共享上面已經定義好的變量 with tf.variable_scope('v_scope', reuse=True) as scope2: Weights2 = tf.get_variable('Weights') bias2 = tf.Variable([0.52], name='bias') print(Weights1.name) # v_scope/Weights:0 print(Weights2.name) # v_scope/Weights:0 print(bias1.name) # v_scope/bias:0 print(bias2.name) # v_scope_1/bias:0
若是reuse=True的scope中的變量沒有通過get_variable定義,則會報錯。
with tf.variable_scope('v_scope') as scope1: Weights1 = tf.get_variable('Weights', shape=[2,3]) bias1 = tf.Variable([0.52], name='bias') # bias1 的定義方式是使用Variable print(Weights1.name) # v_scope/Weights:0 print(bias1.name) # v_scope/bias:0 # 下面來共享上面已經定義好的變量 # 在下面的 scope 中的get_variable()變量必須通過get_variable()定義過了,才能設置 reuse=True,不然會報錯 with tf.variable_scope('v_scope', reuse=True) as scope2: Weights2 = tf.get_variable('Weights') bias2 = tf.get_variable('bias', [1]) # ‘bias print(Weights2.name) print(bias2.name) # Variable v_scope/bias does not exist, or was not created with tf.get_variable()
總結:若是咱們使用tf.variable_scope定義變量命名空間,儘可能使用tf.get_variable建立變量。
TensorFlow裏面的變量OP
常見的tensorflow的OP
類型 |
實例 |
標量運算 |
add、sub、mul、div、exp、log、greater、less、equal |
向量運算 |
concat、slice、splot、constant、rank、spape、shuffle、 |
矩陣運算 |
matmul、matrixinverse、matrixdateminant |
帶狀態的運算 |
Variable、assgin、assginadd |
神經元組件 |
softmax、sigmoid、relu、convolution、max_pool |
存儲、恢復 |
Save、Restroe |
隊列與同步運算 |
Equeue、Dequeue、MutexAxquire、MutexRelease |
控制流 |
Merge、Switch、Enter、Leave、Nextiteration |
用tensorflow作一個簡單的線性迴歸
import tensorflow as tf # .rand生成一個[0~1]之間2行100列的數組 # .randn生成服從正態分佈的數組 x_data = tf.random_normal(shape=[100,1]) y_data = tf.matmul(x_data, [[0.4]]) + 5 # 構造一個線性模型 b = tf.Variable(initial_value=tf.random_normal(shape=[1, 1])) W = tf.Variable(initial_value=tf.random_normal(shape=[1, 1])) y = tf.matmul(x_data, W) + b # 最小化方差 loss = tf.reduce_mean(tf.square(y - y_data)) # 設置學習率0.5的梯度降低算法,求最小值 optimizer = tf.train.GradientDescentOptimizer(0.01).minimize(loss) init = tf.global_variables_initializer() # 初始化變量 # 開啓會話 with tf.Session() as sess: sess.run(init) print("訓練前的w: %f 和b:%f" % (W.eval(), b.eval())) for i in range(0, 1000): sess.run(optimizer) if i % 20 == 0: # 每20次打印一次 print("第 %d 次訓練前的w: %f 和b:%f 損失值%f" % (i, W.eval(), b.eval(), loss.eval()))
TensorBoard:可視化學習
TensorFlow是tensorflow的可視化工具,實現程序可視化的過程
一、數據序列化-events文件
在會話中寫入事件文件,而後在path路徑建立一個even文件
tf.summary.FileWriter("path", graph=sess.graph)
- path 事件文件的寫入地址
- graph 選擇描繪的計算圖,graph=sess.graph 或者 graph=tf.get_default_graph() 選擇的都是默認圖
import tensorflow as tf a = tf.constant(20, name="a") b = tf.constant(30, name="b") c = a + b with tf.Session() as sess: c = sess.run(c) writer = tf.summary.FileWriter("./", sess.graph) # 寫入事件文件 writer.close() # 寫完以後最後要記得關閉
二、啓動TensorBoard
在cmd中或者Git Bash中運行 tensorboard --logdir="path"
而後在谷歌瀏覽器中 localhost:6006 就能夠看到圖了
咱們來看一個更復雜的TensorBoard圖,代碼以下
# 實現一個線性迴歸 import tensorflow as tf # 準備數據 X = tf.random_normal(shape=[100, 1]) y_true = tf.matmul(X, [[0.8]]) + 0.7 # 構建線性模型的tensor變量Weight, bias Weight = tf.Variable(initial_value=tf.random_normal(shape=[1, 1])) bias = tf.Variable(initial_value=tf.random_normal(shape=[1, 1])) y_predict = tf.matmul(X, Weight) + bias # 構建損失方程,優化器及訓練模型操做train loss = tf.reduce_mean(tf.square(y_predict - y_true)) optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.5) train = optimizer.minimize(loss) init = tf.initialize_all_variables() # 構建變量初始化操做init with tf.Session() as sess: sess.run(init) writer = tf.summary.FileWriter("./", sess.graph) for step in range(1000): sess.run(train) if step % 20 == 0: # 每20次打印一次 print(step, sess.run(Weight), sess.run(bias)) writer.close()
三、增長變量顯示功能
目的:在TensorBoard中觀察模型參數、損失值等變量的變化
步驟:
一、收集變量
tf.summary.scalar(name="", tensor) # 收集對於對於損失函數和準確率等單值變量,tensor爲要收集的tnesor對象
tf.summary.histogram(name="", tensor) # 收集高維度的變量
tf.summaty.image(name="", tensor) # 收集輸入的圖片張量
二、合併變量並寫入事件文件
一、合併變量:merged = tf.summary.merge_all()
二、在會話中建立事件文件:event_file = tf.summary.FileWriter("./", sess.graph) # 建立事件文件
三、在會話中運行合併操做:summary = sess.run(merged) # 每次迭代都須要運行
四、將每次迭代後的變量寫入事件文件:event_file.add_summary(summary, step) # step表示第幾回運行
五、最後記得關閉事件文件:event_file.close()
# 實現一個線性迴歸 import tensorflow as tf # 準備數據 X = tf.random_normal(shape=[100, 1]) y_true = tf.matmul(X, [[0.8]]) + 0.7 # 構建線性模型的tensor變量Weight, bias Weight = tf.Variable(initial_value=tf.random_normal(shape=[1, 1])) bias = tf.Variable(initial_value=tf.random_normal(shape=[1, 1])) y_predict = tf.matmul(X, Weight) + bias # 構建損失方程,優化器及訓練模型操做train loss = tf.reduce_mean(tf.square(y_predict - y_true)) optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.01) train = optimizer.minimize(loss) # 收集變量 tf.summary.scalar("error", loss) # 收集標量 tf.summary.histogram("Weight", Weight) # 收集高維變量 tf.summary.histogram("bias", bias) merged = tf.summary.merge_all() # 合併變量 init = tf.initialize_all_variables() # 變量初始化操做 with tf.Session() as sess: sess.run(init) event_file = tf.summary.FileWriter("./", sess.graph) # 建立事件文件 for step in range(100): sess.run(train) if step % 20 == 0: # 每20次打印一次 print(step, sess.run(Weight), sess.run(bias)) summary = sess.run(merged) # 運行合併變量操做 event_file.add_summary(summary, step) # 將每次迭代後的變量寫入事件文件 event_file.close()
菜單欄多了 scalars(標量)、distributions(分佈圖)、histogram(直方圖)
咱們先來看看scalars
咱們再來看看 distributions和histogram
咱們能夠看到,咱們所看到的grapth圖結構是比較亂的,咱們添加變量命名空間讓圖結構顯示的更整齊。
模型的保存與加載
模型保存
saver = tf.train.Saver(var_list=None, max_to_keep=5) 保存和加載模型(保存文件格式:checkpoint文件)
- var_list:指定要保存的變量,能夠做爲一個dict或列表傳遞,若是爲None,就是保存全部變量。
- max_to_keep:保留檢查點文件的數量,建立新文件時會刪除舊的文件
saver.save(sess, save_path="./liner.ckpt", global_step=step) 保存模型
- sess:會話名字
- save_path:設定權重參數保存的路徑和文件名;
- global_step=step:將訓練的次數做爲後綴加入到模型名字中。
一次 saver.save() 後能夠在文件夾中看到新增的四個文件,
checkpoint 記錄最新的模型
***.meta 存儲網絡結構
***.data/***.index 存儲訓練好的參數
import tensorflow as tf v1 = tf.get_variable("v1", shape=[3], initializer=tf.zeros_initializer) v2 = tf.get_variable("v2", shape=[5], initializer=tf.zeros_initializer) inc_v1 = v1.assign(v1+1) # v1變量+1 dec_v2 = v2.assign(v2-1) # v2變量-1 init = tf.global_variables_initializer() saver = tf.train.Saver() # 建立Saver對象 with tf.Session() as sess: sess.run(init) inc_v1.op.run() dec_v2.op.run() for epoch in range(300): if epoch % 10 ==0: # 在會話中保存模型 save_path = saver.save(sess, "./model/model.ckpt", global_step=epoch) print("Model saved in path: %s" % save_path)
下圖是訓練過程當中生成的幾個模型文件列表
模型加載
加載模型:saver.restore(sess, "./liner.ckpt")
獲取最新的模型:checkpoint = tf.train.latest_checkpoint("./model/")
import tensorflow as tf import os v1 = tf.get_variable("v1", shape=[3]) v2 = tf.get_variable("v2", shape=[5]) tf.add_to_collection("variable", v1) tf.add_to_collection("variable", v2) def load_model(sess, ckpt): # ckpt是模型路徑 if os.path.isdir(ckpt): # 獲取最新的模型 checkpoint = tf.train.latest_checkpoint(ckpt) # ./model/model.ckpt-290 else: checkpoint = ckpt print(checkpoint) meta = checkpoint + '.meta' # './model/model.ckpt-290.meta' saver = tf.train.import_meta_graph(meta) # 加載graph圖結構 saver.restore(sess, checkpoint) # 加載模型參數 with tf.Session() as sess: sess.run(tf.global_variables_initializer()) model_dir = "./model/" load_model(sess, model_dir) # 從變量集和名爲"variable"的集和中取出變量 a, b = tf.get_collection('variable') print(a,b) print("模型恢復....") print("v1 : %s" % v1.eval()) print("v2 : %s" % v2.eval())
sv = tf.train.Supervisor(logdir="./my_dir", init_op=init)
通常咱們在訓練模型以前,都會檢查本地是否有以前已經訓練好並保存了的模型,因此會作一次if判斷,可是Supervisor能夠節省這一步,sv = tf.train.Supervisor(logdir=log_path, init_op=init)會判斷模型是否存在.若是存在,會自動讀取模型.不用顯式地調用restore,具體以下:
log_path = "./Source/model/supervisor" log_name = "linear.ckpt" saver = tf.train.Saver() # 建立saver init = tf.global_variables_initializer() sess = tf.Session() sess.run(init) if len(os.listdir(log_path)) != 0: # 若是已經有模型,則直接讀取 saver.restore(sess, os.path.join(log_path, log_name)) for step in range(201): sess.run(train) if step % 20 == 0: print(step, sess.run(W), sess.run(b)) saver.save(sess, os.path.join(log_path, log_name))
用Supervisor
log_path = "./Source/model/supervisor" log_name = "linear.ckpt" init = tf.global_variables_initializer() sv = tf.train.Supervisor(logdir=log_path, init_op=init) # logdir用來保存checkpoint和summary saver = sv.saver # 建立saver sess = sv.managed_session() # 會自動去logdir中去找checkpoint,若是沒有的話,自動執行初始化 for i in range(201): sess.run(train) if i % 20 == 0: print(i, sess.run(W), sess.run(b)) saver.save(sess, os.path.join(log_path, log_name))
經過checkpoint找到模型文件名
tf.train.get_checkpoint_state(checkpoint_dir,latest_filename=None)
參數:
- checkpoint_dir:checkpoint文件的路徑
- latest_filename:指定checkpoint的名字
返回的是CheckpointState proto對象,CheckpointState proto對象有兩個可用屬性。
- model_checkpoint_path:最新的chechpoint路徑
- all_model_checkpoint_paths:文件中全部的checkpoints路徑列表
ckpt = tf.train.get_checkpoint_state('./model/') if ckpt and ckpt.model_checkpoint_path: print(ckpt.model_checkpoint_path) # ./model/model.ckpt-1000(1000是訓練步數) print(ckpt.all_model_checkpoint_paths) # ['./model/model.ckpt-500', './model/model.ckpt-1000']
global_step = ckpt.model_checkpoint_path.split('/')[-1].split('-')[-1]
獲得了global_step以後,就能夠恢復模型,繼續在原來的模型基礎上,訓練後面的步驟了。
命令行參數的使用
tensorflow支持程序從命令行接受參數,即便用tf.app.flag,tf.app.flag能夠定義各類參數類型
tf.app.flag.DEFINE_integer(參數名, 默認值, 參數說明文檔 字符串)
整形參數 tf.app.flag.DEFINE_integer(flag_name, default, docstring)
字符串參數 tf.app.flag.DEFINE_string(flag_name, default, docstring)
布爾值參數 tf.app.flag.DEFINE_boolean(flag_name, default, docstring)
浮點值參數 tf.app.flag.DEFINE_float(flag_name, default, docstring)
...
二、tf.app.flags,flags有一個FLAGS標誌,能夠調用到咱們前面具體定義的參數名flag_name。
import tensorflow as tf # 定義命令行參數 tf.app.flags.DEFINE_integer("step", 100, "訓練模型的步數") tf.app.flags.DEFINE_string("model_dir", "Unknown", "模型保存的路徑") FLAGS = tf.app.flags.FLAGS # 簡化變量名 print("step:", FLAGS.step) # step: 100 print("model_dir:", FLAGS.model_dir) # model_dir: Unknown
tf.app.run()能夠自動運行腳本中的main(argv)函數,若是腳本沒有main(argv)函數,會報錯。
main函數中的argv參數打印出來是腳本的地址
import tensorflow as tf def main(argv): print(argv) # ['C:\\Users\\Never\\Desktop\\temp\\temp.py'] tf.app.run() # 自動調用腳本中的main(argv)函數
關於多個GPU的分類使用
TensorFlow通常你不須要顯式指定使用CPU仍是GPU,TensorFlow能自動檢測。若是檢測到 GPU,TensorFlow會盡量地利用找到的第一個GPU來執行操做。
若是你的電腦有兩個GPU,tensorflow默認是不會使用的,爲了讓 TensorFlow 使用這些 GPU, 你必須將 op 明確指派給它們執行. with.Device
語句用來指派特定的 CPU 或 GPU 執行操做:
with tf.Session() as sess: with tf.device("/gpu:1"): matrix1 = tf.constant([[3., 3.]]) matrix2 = tf.constant([[2.],[2.]]) product = tf.matmul(matrix1, matrix2) ...
關於IPython的tensorflow的使用
爲了便於使用諸如IPython之類的Python交互環境,好比jupyter notebook。可使用InteractiveSession
代替Session
類,使用Tensor.eval()
和Operation.run()
方法代替Session.run()。
這樣能夠避免使用一個變量來持有會話。
# 進入一個交互式 TensorFlow 會話. import tensorflow as tf sess = tf.InteractiveSession() x = tf.Variable([1.0, 2.0]) a = tf.constant([3.0, 3.0]) # 使用初始化器 initializer op 的 run() 方法初始化 'x' x.initializer.run() # 增長一個減法 sub op, 從 'x' 減去 'a'. 運行減法 op, 輸出結果 sub = tf.subtract(x, a) print(sub.eval()) # [-2. -1.]
運行tensorflow的時候,會出現紅色警告I tensorflow/core/platform/cpu_feature_guard.cc:141] Your CPU supports instructions that this TensorFlow binary was not compiled to use: AVX2
若是不想看到這個,在腳本開始的時候,加
import os os.environ["TF_CPP_MIN_LOG_LEVEL"]= "2" # 或者 import os os.environ["KERAS_BACKEND"] = "tensorflow"