1.簡介與基礎
深度學習的框架有很多:TensorFlow、Caffe、Theano、Torch等,其中Keras是在TensorFlow基礎上構建的高層API,Keras在TensorFlow中,本次使用的tensorflow為1.12.0。
tensorflow包括兩個階段:
-
構建計算圖(tf.Graph):
-
張量/數據(Tensor):主要包括[名稱、維度、類型],即[name,shape,type]
-
操作(OPeration):我們構建的計算圖的節點
-
-
運行計算圖/會話(tf.Session)
-
以下為一個簡單的tensorflow示例:
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)
print('b', b)
print('c', c)
#第二階段,運行計算圖(默認圖)
with tf.Session() as sess:
print(sess.run(b))
print('在會話中run后的加法結果', sess.run(c))
#運行結果
a Tensor("Const:0", shape=(), dtype=float32)
b Tensor("Const_1:0", shape=(), dtype=float32)
c Tensor("Add:0", shape=(), dtype=float32)
3.0
在會話中run后的加法結果 5.0
1.1 構建計算圖(Graph)
1.1.1默認圖
通常Tensorflow會默認幫我們創建一張圖,查看默認圖有兩種方法;
-
default_g = tf.get_default_graph() #創建一個默認圖,賦值給default_g
-
使用上面代碼的a與sess,a.graph或sess.graph,因為這兩個便是節點與運行,且都有默認的graph屬性。
其運行的代碼如下(拼接上面的代碼,下面沒有重新import的都一樣,之后不重復說明):
default_g = tf.get_default_graph()
print('attribute', default_g)
print('attribute', a.graph)
print('attribute', sess.graph)
#結果顯示
attribute <tensorflow.python.framework.ops.Graph object at 0x000001CB0F8DE748>
attribute <tensorflow.python.framework.ops.Graph object at 0x000001CB0F8DE748>
attribute <tensorflow.python.framework.ops.Graph object at 0x000001CB0F8DE748>
1.1.2創建新圖
與上面的默認圖差不多的形式:
new_g = tf.Graph() #創建一個新的圖,賦值給new_g
如果要對新圖進行相關處理,則用new_g.as_default()。
代碼如下:
new_g = tf.Graph()
with new_g.as_default():
a_new = tf.constant([15])
print('a_new', a_new)
#結果顯示
a_new Tensor("Const:0", shape=(1,), dtype=int32)
1.1.3Tensor張量/數據
張量Tensor有3個屬性(attrtibute):名稱(name)、維度(shape)、類型(type)
(1). 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)
print(mammal, type(mammal))
print(ignition, type(ignition))
print(floating, type(floating))
print(its_complicated, type(its_complicated))
#結果顯示
<tf.Variable 'Variable:0' shape=() dtype=string_ref> <class 'tensorflow.python.ops.variables.Variable'>
<tf.Variable 'Variable_1:0' shape=() dtype=int32_ref> <class 'tensorflow.python.ops.variables.Variable'>
<tf.Variable 'Variable_2:0' shape=() dtype=float32_ref> <class 'tensorflow.python.ops.variables.Variable'>
<tf.Variable 'Variable_3:0' shape=() dtype=complex128_ref> <class 'tensorflow.python.ops.variables.Variable'>
0階張量就是一個數,其中tf.variable就是構造一個variable(變量)添加進圖中,而variable()則是構造函數所需要的變量的初始值可以是一個任意形狀、任意類型的張量/數據Tensor,而括號里的格式形如(initialization,name)分別是初始化的參數,即我們要的數據值,和數據的名字,所以下面一階、二階都用了,具體使用方法在下方變量相關操作中提到。
(2). 1階張量
myst = 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)
print(myst, type(myst))
print(cool_numbers, type(cool_numbers))
print(first_primes, type(first_primes))
print(its_very_complicated, type(its_very_complicated))
#結果顯示
<tf.Variable 'Variable_4:0' shape=(1,) dtype=string_ref> <class 'tensorflow.python.ops.variables.Variable'>
<tf.Variable 'Variable_5:0' shape=(2,) dtype=float32_ref> <class 'tensorflow.python.ops.variables.Variable'>
<tf.Variable 'Variable_6:0' shape=(5,) dtype=int32_ref> <class 'tensorflow.python.ops.variables.Variable'>
<tf.Variable 'Variable_7:0' shape=(2,) dtype=complex128_ref> <class 'tensorflow.python.ops.variables.Variable'>
(3). 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_squares = tf.Variable([ [4, 9], [16, 25] ], tf.int32)
rank = tf.rank(squarish_squares)
print(mymat, type(mymat))
print(myxor, type(myxor))
print(linear,type(linear))
print(squarish_squares,type(squarish_squares))
print(rank, type(rank))
#結果顯示
<tf.Variable 'Variable_8:0' shape=(2, 1) dtype=int32_ref> <class 'tensorflow.python.ops.variables.Variable'>
<tf.Variable 'Variable_9:0' shape=(2, 2) dtype=bool_ref> <class 'tensorflow.python.ops.variables.Variable'>
<tf.Variable 'Variable_10:0' shape=(4, 1) dtype=int32_ref> <class 'tensorflow.python.ops.variables.Variable'>
<tf.Variable 'Variable_11:0' shape=(2, 2) dtype=int32_ref> <class 'tensorflow.python.ops.variables.Variable'>
Tensor("Rank:0", shape=(), dtype=int32) <class 'tensorflow.python.framework.ops.Tensor'>
其中tf.rank()為返回矩陣秩的函數, 注意:張量的秩與矩陣的秩不一樣。張量的秩是唯一選擇張量的每個元素所需的索引的數量。秩也被稱為 “order”,“degree” 或 “ndims”。
在圖像處理過程中,還有很多4階張量,形如:
my_image = tf.zeros([10, 299, 299, 3]) #參數依次為:批處理大小、圖像寬、圖像高、圖像顏色通道數
(4). 關於張量的一些操作
1.tf.reshape(x,shape)
作用是改變形狀
matrix = tf.ones([3, 4, 5])
matrixA = tf.reshape(matrix, [6, 10]) #重塑成 6*10
matrixB = tf.reshape(matrixA, [3, -1]) # 重塑成 3x20
print(matrix)
print(matrixA)
print(matrixB)
#結果顯示
Tensor("ones:0", shape=(3, 4, 5), dtype=float32)
Tensor("Reshape:0", shape=(6, 10), dtype=float32)
Tensor("Reshape_1:0", shape=(3, 20), dtype=float32)
2.Tensor中的常量(constant)
-
生成0的張量函數 tf.zeros(shape=[2,2], dtypt=tf.float32, namhanghe=None)
-
生成1的張量函數 tf.ones(shape=[2,2], dtypt=tf.float32, namhanghe=None)
-
生成常數 tf.constant(value, dtype=None, Shape=None, name="Const")
-
numpy變為tensorflow數:data_tensor= tf.convert_to_tensor(data_numpy)
-
生成都是value值的dims形狀的張量 tf.fill(dims, value, name=None) ,形如:
import tensorflow as tf
t1 = tf.fill([2, 3], 3)
print(t1)
sess = tf.Session()#這部分其實是計算部分,先用,看我們的t1變成了什么
print(sess.run(t1))
#結果顯示
Tensor("Fill:0", shape=(2, 3), dtype=int32)
[[3 3 3]
[3 3 3]]
3.Tensor中的隨機數(random)
-
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要洗牌的張量
4.Tensor中的初始化(initialize)
-
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.ranndom_normal_initializer (mean=0.0, stddev=1.0, seed=None, dtype=tf.float32)
使用正態分布張量的初始化器,參數依次為:均值、方差、隨機種子、數據類型
-
tf.random_uniform_initializer(minval=0, maxval=None, seed=None, dtype=tf.float32)
使用均勻分布張量的初始化器,參數依次為:最小值、最大值、隨機種子、數據類型
-
tf.cast(x, dtype, name=None)
把張量x,變成任何的dtype,這里要與reshap分開,cast是變類型,如float32變成float16;reshap變的是維度,也就是我們說的形狀,如zero[2, 3]變成zero[1, 6]。
注意:這些數據的類型都為float32,如果直接用都應該在tf.get_variable()中的initializer中
(5). 關於變量的一些操作
注意:所有變量進行相關操作都需要進行初始化。
1.變量創建variable相關
tf.Variable(initial_value=None, trainable=None, collections=None, validate_shape=True, caching_device=None, name=None, variable_def=None, dtype=None, expected_shape=None, import_scope=None, constraint=None, use_resource=None, shape=None)
在graph中創建變量,詳細講述請點擊函數名,以下介紹了其常用參數。
-
initial_value:Tensor,定義Variable的初始值。
-
trainable:如果為True,則會默認將變量添加到圖形集合GraphKeys.TRAINABLE_VARIABLES中,此集和用於優化器優化的默認變量列表 。
-
collections:graph集合列表的關鍵字。新變量將添加到這個集合中。默認為[GraphKeys.GLOBAL_VARIABLES]。
-
validate_shape:如果為True,則默認為initial_value的形狀必須已知。如果為False,則允許使用未知形狀的值初始化變量。
-
name:變量名,可選,默認為“Variable”並自動獲取
-
dtype:數據類型
tf.get_variable(name,shape=None, dtype=None, initializer=None, regularizer=None, trainable=None, collections=None, caching_device=None, partitioner=None, validate_shape=True, use_resource=None, custom_getter=None, constraint=None)
這也是獲取或創建一個變量的形式,與tf.Variable參數區別最主要在於如果新建變量名稱原來存在,就會顯示錯誤,不會像Variable一樣,自動處理相同的變量名稱,另外tf.get_variable還可以讀取以前有的變量,也可以創建新的變量,而Variable只是直接創建,不管之前有沒有存在,以下介紹了其常用參數。
-
name:新變量或現有變量的name
-
shape:新變量或現有變量的shape
-
dtype:新變量或現有變量的類型(默認為DT_FLOAT)。
-
initializer:變量的初始化方式
-
regularizer:函數(tensor-->tensor),將函數應用於新創建的變量,結果將添加到集合tf.GraphKeys.REGULARIZATION_LOSSES中,並可用於正則化。
-
trainable:如果為True,還將變量添加到圖形集合GraphKeys.TRAINABLE_VARIABLES,此集和用於優化器優化的默認變量列表 。
-
collections:要將變量添加到的圖表集合列表。默認為[GraphKeys.GLOBAL_VARIABLES](參見tf.Variable) 。
-
validate_shape:如果為True,則默認為initial_value的形狀必須已知。如果為False,則允許使用未知形狀的值初始化變量。
-
use_resource:如果為False,則創建常規變量。如果為true,則使用定義良好的語義創建實驗性ResourceVariable。默認為False(以后版本中將更改為True)。在Eager模式下,此參數始終強制為True。
v = tf.get_variable("v", shape=(), initializer=tf.zeros_initializer())
u = tf.Variable([1, 2], trainable=True, validate_shape=True, name='u')
w = v + 1
w1 = u + 2
print(v, type(v))
print(u, type(u))
print(w, type(w))
print(w1, type(w1))
#結果顯示
<tf.Variable 'v:0' shape=() dtype=float32_ref> <class 'tensorflow.python.ops.variables.Variable'>
<tf.Variable 'u:0' shape=(2,) dtype=int32_ref> <class 'tensorflow.python.ops.variables.Variable'>
Tensor("add:0", shape=(), dtype=float32) <class 'tensorflow.python.framework.ops.Tensor'>
Tensor("add_1:0", shape=(2,), dtype=int32) <class 'tensorflow.python.framework.ops.Tensor'>
tf.global_variables_initializer(),一般只用於統一初始化,因為其不會指定變量的初始化順序,當一個變量的初始值取決於另一個變量的值時,使用這種方法可能會出現錯誤,所以我們要在命名時就進行初始化。
#形如:init = tf.global_variables_initializer()
使用assign與assign_add方法對tf.Variable進行值的變換
import tensorflow as tf
a = tf.Variable(initial_value=0, name='counter') # 創建一個變量,初始化為標量0
b = tf.constant(1)
c = tf.get_variable('c', shape=(), initializer=tf.zeros_initializer())
assignment = c.assign_add(1) # 利用assign_add實現變量c初始值+1
new_value = tf.add(a, b) # 利用add實現a與b的相加
update = tf.assign(a, new_value) # 將新的值new_value賦值給a,只是描繪圖,並不會執行
#啟動圖前,變量必須經過初始化(init)
init = tf.global_variables_initializer() # 統一初始化
#啟動圖,運行op,這部分在運行計算圖中會再詳細介紹
with tf.Session() as sess:
sess.run(init) # 運行‘init’
print(sess.run(a)) # 打印‘a’的值
print(sess.run(assignment)) # 打印‘assignment’的值
#運行op,更新a,並打印a
for _ in range(2): # 補充一個小知識,range是一種與list與tuple同等類型的數據類型
sess.run(update)
print(sess.run(update))
#結果顯示
0
1.0
2
4
2.對列表中變量的相關操作
-
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(2))
tf.add_to_collection('loss', v1) # 將v1放入loss列表中
v2 = tf.get_variable(name='v2', shape=[1], initializer=tf.constant_initializer(1))
tf.add_to_collection('loss', v2)
init = tf.global_variables_initializer()
with tf.Session() as sess:
sess.run(init)
print(tf.get_collection('loss')) # 將上面加進去的v1與v2從loss列表取出並打印
print(sess.run(tf.get_collection('loss')))
print(sess.run(tf.add_n(tf.get_collection('loss')))) # 將v1與v2取出相加再打印最后運行的結果
#結果顯示
[<tf.Variable 'v1:0' shape=(1,) dtype=float32_ref>,
<tf.Variable 'v2:0' shape=(1,) dtype=float32_ref>]
[array([2.], dtype=float32),
array([1.], dtype=float32)]
[3.]
3.變量命名空間
-
tf.name_scope() # 修改變量的命名空間
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, 44], name='bias')
print(weights1.name)
print(weights2.name)
#如果重復執行,則會生成新的命名空間
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, 44], name='bias')
print(weights1.name)
print(weights2.name)
#結果顯示
conv1/weights:0
conv2/weights:0
conv1_1/weights:0
conv2_1/weights:0
-
tf.variable_scope('scope_name')
這種方法主要是與tf.get_variable()來使用,實現變量共享,以下為它的一個簡單示例:
with tf.variable_scope('v_scope'):
Weights1 = tf.get_variable('Weights', shape=[2, 3])
bias1 = tf.get_variable('bias', shape=[3, ])
# print(Weights1, type(Weights1))
# print(bias1, type(bias1))
# 下面共享上面已經定義好的變量
# 在下面的scope中的變量必須經過get.variable()定義過了,才能設置reuse=True,否則會報錯
with tf.variable_scope('v_scope', reuse=True):
Weights2 = tf.get_variable('Weights')
print(Weights1.name)
print(Weights2.name)
#結果顯示
v_scope/Weights:0
v_scope/Weights:0
共享變量有兩種方法:
#方法一:
with tf.variable_scope('name') as scope:
我們定義的變量,最好使用tf.get_variable生成
#方法二:
with tf.variable_scope('name', reuse=True):
我們定義的變量,只有tf.get_variable定義變量,才能是reuse(重復使用)為真的必要條件
總結:這兩種都是變量空間操作,但是name_scope一般是與Variable一起用,variable_scope一般與tf.get_variable一起使用。
1.2 會話/運行計算圖(Session)
要評估張量,就需要實例化一個tf.Session()對象,在會話/運行計算圖中,調用run方法來運行圖節點以及查看張量。
-
sess.run(張量)與Tensor.eval(),即張量.eval(),都是返回與張量內容相同的numpy數組。
-
Tensor.eval與sess.run方法能運行的前提都是tf.Session處於活躍狀態。
下面是兩種方法的簡單示例(接的是一開始的總體簡單示例):
with tf.Session() as sess:
print(a.eval())
print(sess.run(a))
#結果顯示
2.0
2.0
1.2.1會話/運行計算圖的兩種方式
-
tf.Session(graph=None, config=None) #如果括號內什么都不寫就默認為None。
也可以graph=new_graph # new_graph是自定義創建的新的圖的對象實例
config:清晰地顯示操作運行在哪些設備上 如果想要知道設備信息,把config設置成config = tf.ConfigProto(allow_soft_placement=True, log_device_placement=True)
-
tf.InteractiveSession() #用於在交互模式中打開會話,ipython,shell,jupyter Notebook。
最后,會話/運行計算圖(Session)在使用完后需要釋放資源,除了使用sess.close()外,一般使用“with代碼塊”來自動關閉。
1.2.2會話/運行計算圖的run
run(fetches, feed_dict=None, options=None, run_metadata=None)
其中的幾個參數介紹:
-
fetches:單一的operation(操作或者叫節點),或者元組operation、列表operation
-
feed_dict:參數允許調用者覆蓋圖中張量的值,運行時賦值。與tf.placeholder(),即我們所說的feed操作配合使用,則會檢測值的形狀是否與占位符匹配。
以下為run的簡單示例:
import tensorflow as tf
a = tf.constant(2.)
b = tf.constant(3.)
c = a + b
sess = tf.Session() # 等價與with tf.Session() as sess:
s = sess.run(c)
print(s)
print(c.eval(session=sess)) # 如果上面用的是with則Session是活躍的不用在()中再聲明
#結果顯示
5.0
5.0
以下是feed_dict的相關操作(接上面的代碼):
input1 = tf.constant(2.0)
input2 = tf.constant(3.0)
input3 = tf.constant(4.0)
input4 = tf.add(input2, input3)
input5 = tf.multiply(input1, input4)
with tf.Session() as sess:
result = sess.run([input5, input4])#通過run取回多個張量
print(result, type(result))
#結果顯示
[14.0, 7.0] <class 'list'>
結合tf.placeholder()進行相關操作:
import tensorflow as tf
a = tf.placeholder(tf.float32) # 就是用placeholder創建一個占位符,最后必須通過feed_dict進行參數替換
b = tf.placeholder(tf.float32)
c = tf.add(a, b)
with tf.Session() as sess:
re1 = sess.run(c, feed_dict={a: 1, b: 2.5})
print(re1)
print(sess.run(c, feed_dict={a: [1., 2.], b: [2., 2.]}))
#結果顯示
3.5
[3. 4.]
2.TensorBoard:可視化學習
TensorBoard是tensorflow的可視化工具,實現程序可視化的過程。
2.1數據序列化-event文件
tf.summary.FileWriter('path', garph=sess.graph) #在會話/運行計算圖中寫入事件文件,然后在path路徑創建一個even文件。
-
path 事件文件的寫入地址
-
graph 選擇描繪的計算圖,sess.graph或tf.get_default_graph()都是默認圖,tf.graph()是新圖
以下是一個簡單示例:
import tensorflow as tf
a = tf.constant(20, name='ax')
b = tf.constant(30, name='bx')
c = a + b
with tf.Session() as sess:
c = sess.run(c)
writer = tf.summary.FileWriter('./', sess.graph) # 寫入事件文件
writer.close() # 寫完之后的關閉操作,必須要有
#這只是寫入事件的代碼,並沒有打印什么結果
2.2啟動TensorBoard
-
將項目中的.py文件(這個py文件是擁有寫入事件語句的)運行,生成event文件,如圖:
-
在cmd中或者Git Bash中運行 tensorboard --logdir="path" (注意,一定要是在event存在的文件夾中打開cmd,在命令中path一定要用雙引號,單引號會出錯),如圖:
-
然后在谷歌瀏覽器中 localhost:6006 就可以看到圖了 ,如圖:
下面是一個py文件顯示tensorboard示例:
# 實現一個線性回歸
import tensorflow as tf
import os
os.environ["TF_CPP_MIN_LOG_LEVEL"] = "2"
# 准備數據
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.global_variables_initializer() # 構建變量初始化操作init
with tf.Session() as sess:
sess.run(init)
writer = tf.summary.FileWriter("D:/project-minyuan/study/logs", 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中觀察模型參數、損失值等變量的變化
-
收集變量用於tensorboard可視化
-
tf.summary.scalar(name="", tensor) # 收集標量,例:loss、accuary、learing_rate
-
tf.summary.histogram(name="", tensor) # 收集高維度的變量,例:訓練過程中的變量, 以直方圖的形式顯示變量分布情況 。
-
tf.summaty.image(name="", tensor) # 收集圖片張量[image_num, height, width, channels],展示訓練過程中記錄的圖像
-
tf.summaty.audio(name="", tensor) # 收集音頻張量[audio_num, frames, channels],播放訓練過程中記錄的音頻
數據的tensorboard可視化展現 :網址
import tensorflow as tf
import os
os.environ["TF_CPP_MIN_LOG_LEVEL"] = "2"
# 准備數據
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.global_variables_initializer() # 變量初始化操作
with tf.Session() as sess:
sess.run(init)
event_file = tf.summary.FileWriter("D:/project-minyuan/study/logs", 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()
其中一些參數的解釋:
-
merged = tf.summary.merge_all() # 將所有的summary保存到磁盤,以便tensorboard可視化
-
event_file = tf.summary.FileWriter("./", sess.graph) # 在會話中創建事件文件保存圖
-
summary = sess.run(merged) # 在會話中運行合並操作
-
event_file.add_summary(summary, step) # 將每次迭代更新后的summary寫入事件文件
-
event_file.close() # 最后記得關閉事件文件
結果如圖:
3.模型的保存與加載
3.1 模型保存
-
saver = tf.train.Saver(var_list=None, max_to_keep=5) # 保存和加載模型
其中相關參數:
-
var_list:指定要保存的變量,可以作為一個dict或列表傳遞,如果為None,就是保存所有變量。
-
max_to_keep:保留檢查點文件的數量,創建新文件時會刪除舊的文件 。
-
saver.save(sess, save_path="./liner.ckpt", global_step=step) # 保存模型
-
sess:會話名字 。
-
save_path:設定權重參數保存的路徑和文件名。
-
global_step=step:將訓練的次數作為后綴加入到模型名字中。
以下是一個簡單訓練模型並保存的示例:
import tensorflow as tf
import os
os.environ["TF_CPP_MIN_LOG_LEVEL"] = "2"
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
a = tf.constant(1.0)
b = tf.add(v1, a)
inc_v1 = tf.assign(v1, b)
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, save_path="./model/model.ckpt", global_step=epoch)
print("Model saved in path: %s" % save_path)
運行完代碼在model文件夾中生成下列幾個文件:
其中幾個文件名的意思如下:
-
checkpoint 記錄最新的模型
-
().data/ ().index 存儲訓練好的參數
-
().meta 存儲網絡結構
3.2 模型加載
-
saver.restore(sess, "./liner.ckpt") # 加載模型
-
checkpoint = tf.train.latest_checkpoint("./model/") # 獲取最新的模型
import tensorflow as tf
import os
os.environ["TF_CPP_MIN_LOG_LEVEL"] = "2"
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)
else:
checkpoint = ckpt
print(checkpoint) # ./model/model.ckpt-290
meta = checkpoint + '.meta' # ./model/model.ckpt-290.meta
print(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())
#結果顯示
./model/model.ckpt-290
./model/model.ckpt-290.meta
<tf.Variable 'v1:0' shape=(3,) dtype=float32_ref> <tf.Variable 'v2:0' shape=(5,) dtype=float32_ref>
模型恢復....
v1 : [-0.30017233 0.87121487 -0.7292707 ]
v2 : [-0.301401 -0.7233736 0.5275371 0.37816596 -0.61047554]
3.3 通過checkpoint找到模型文件名
tf.train.get_checkpoint_state(checkpoint_dir,latest_filename=None)
其中參數解釋:
-
checkpoint_dir:checkpoint文件的路徑
-
latest_filename:指定checkpoint的名字,返回的是CheckpointState proto對象,CheckpointState proto對象有兩個可用屬性。
命令行參數的使用
tensorflow支持程序從命令行接受參數,即使用tf.app.flag,tf.app.flag可以定義各種參數類型
-
整形參數 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)
4.一些小技巧
-
tf.app.run()可以自動運行腳本中的main(argv)函數,如果腳本沒有main(argv)函數,會報錯。
-
運行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"