tensorflow筆記 :常用函式說明
本文章內容比較繁雜,主要是一些比較常用的函式的用法,結合了網上的資料和原始碼,還有我自己寫的示例程式碼。建議照著目錄來看。
1.矩陣操作
1.1矩陣生成
這部分主要將如何生成矩陣,包括全0矩陣,全1矩陣,隨機數矩陣,常數矩陣等
tf.ones | tf.zeros
tf.ones(shape,type=tf.float32,name=None)
tf.zeros([2, 3], int32)
用法類似,都是產生尺寸為shape的張量(tensor)
sess = tf.InteractiveSession()
x = tf.ones([2, 3], int32)
print(sess.run(x))
#[[1 1 1],
# [1 1 1]]
tf.ones_like | tf.zeros_like
tf.ones_like(tensor,dype=None,name=None)
tf.zeros_like(tensor,dype=None,name=None)
新建一個與給定的tensor型別大小一致的tensor,其所有元素為1和0
tensor=[[1, 2, 3], [4, 5, 6]]
x = tf.ones_like(tensor)
print(sess.run(x))
#[[1 1 1],
# [1 1 1]]
tf.fill
tf.fill(shape,value,name=None)
建立一個形狀大小為shape的tensor,其初始值為value
print(sess.run(tf.fill([2,3],2)))
#[[2 2 2],
# [2 2 2]]
tf.constant
tf.constant(value,dtype=None,shape=None,name=’Const’)
建立一個常量tensor,按照給出value來賦值,可以用shape來指定其形狀。value可以是一個數,也可以是一個list。
如果是一個數,那麼這個常亮中所有值的按該數來賦值。
如果是list,那麼len(value)一定要小於等於shape展開後的長度。賦值時,先將value中的值逐個存入。不夠的部分,則全部存入value的最後一個值。
a = tf.constant(2 ,shape=[2])
b = tf.constant(2,shape=[2,2])
c = tf.constant([1,2,3],shape=[6])
d = tf.constant([1,2,3],shape=[3,2])
sess = tf.InteractiveSession()
print(sess.run(a))
#[2 2]
print(sess.run(b))
#[[2 2]
# [2 2]]
print(sess.run(c))
#[1 2 3 3 3 3]
print(sess.run(d))
#[[1 2]
# [3 3]
# [3 3]]
tf.random_normal | tf.truncated_normal | tf.random_uniform
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)
tf.random_uniform(shape,minval=0,maxval=None,dtype=tf.float32,seed=None,name=None)
這幾個都是用於生成隨機數tensor的。尺寸是shape
random_normal: 正太分佈隨機數,均值mean,標準差stddev
truncated_normal:截斷正態分佈隨機數,均值mean,標準差stddev,不過只保留[mean-2*stddev,mean+2*stddev]範圍內的隨機數
random_uniform:均勻分佈隨機數,範圍為[minval,maxval]
sess = tf.InteractiveSession()
x = tf.random_normal(shape=[1,5],mean=0.0,stddev=1.0,dtype=tf.float32,seed=None,name=None)
print(sess.run(x))
#===>[[-0.36128798 0.58550537 -0.88363433 -0.2677258 1.05080092]]
tf.get_variable
get_variable(name, shape=None, dtype=dtypes.float32, initializer=None,
regularizer=None, trainable=True, collections=None,
caching_device=None, partitioner=None, validate_shape=True,
custom_getter=None):
如果在該命名域中之前已經有名字=name的變數,則呼叫那個變數;如果沒有,則根據輸入的引數重新建立一個名字為name的變數。在眾多的輸入引數中,有幾個是我已經比較瞭解的,下面來一一講一下
name: 這個不用說了,變數的名字
shape: 變數的形狀,[]表示一個數,[3]表示長為3的向量,[2,3]表示矩陣或者張量(tensor)
dtype: 變數的資料格式,主要有tf.int32, tf.float32, tf.float64等等
initializer: 初始化工具,有tf.zero_initializer, tf.ones_initializer, tf.constant_initializer, tf.random_uniform_initializer, tf.random_normal_initializer, tf.truncated_normal_initializer等
1.2 矩陣變換
tf.shape
tf.shape(Tensor)
Returns the shape of a tensor.返回張量的形狀。但是注意,tf.shape函式本身也是返回一個張量。而在tf中,張量是需要用sess.run(Tensor)
來得到具體的值的。
labels = [1,2,3]
shape = tf.shape(labels)
print(shape)
sess = tf.InteractiveSession()
print(sess.run(shape))
# >>>Tensor("Shape:0", shape=(1,), dtype=int32)
# >>>[3]
tf.expand_dims
tf.expand_dims(Tensor, dim)
為張量+1維。官網的例子:’t’ is a tensor of shape [2]
shape(expand_dims(t, 0)) ==> [1, 2]
shape(expand_dims(t, 1)) ==> [2, 1]
shape(expand_dims(t, -1)) ==> [2, 1]
sess = tf.InteractiveSession()
labels = [1,2,3]
x = tf.expand_dims(labels, 0)
print(sess.run(x))
x = tf.expand_dims(labels, 1)
print(sess.run(x))
#>>>[[1 2 3]]
#>>>[[1]
# [2]
# [3]]
tf.pack
tf.pack(values, axis=0, name=”pack”)
Packs a list of rank-R
tensors into one rank-(R+1)
tensor
將一個R維張量列表沿著axis軸組合成一個R+1維的張量。
# 'x' is [1, 4]
# 'y' is [2, 5]
# 'z' is [3, 6]
pack([x, y, z]) => [[1, 4], [2, 5], [3, 6]] # Pack along first dim.
pack([x, y, z], axis=1) => [[1, 2, 3], [4, 5, 6]]
tf.concat
tf.concat(concat_dim, values, name=”concat”)
Concatenates tensors along one dimension.
將張量沿著指定維數拼接起來。個人感覺跟前面的pack用法類似
t1 = [[1, 2, 3], [4, 5, 6]]
t2 = [[7, 8, 9], [10, 11, 12]]
tf.concat(0, [t1, t2])
#==> [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]
tf.concat(1, [t1, t2])
#==> [[1, 2, 3, 7, 8, 9], [4, 5, 6, 10, 11, 12]]
tf.sparse_to_dense
稀疏矩陣轉密集矩陣
定義為:
def sparse_to_dense(sparse_indices,
output_shape,
sparse_values,
default_value=0,
validate_indices=True,
name=None):
幾個引數的含義:
sparse_indices: 元素的座標[[0,0],[1,2]] 表示(0,0),和(1,2)處有值
output_shape: 得到的密集矩陣的shape
sparse_values: sparse_indices座標表示的點的值,可以是0D或者1D張量。若0D,則所有稀疏值都一樣。若是1D,則len(sparse_values)應該等於len(sparse_indices)
default_values: 預設點的預設值
tf.random_shuffle
tf.random_shuffle(value,seed=None,name=None)
沿著value的第一維進行隨機重新排列
sess = tf.InteractiveSession()
a=[[1,2],[3,4],[5,6]]
x = tf.random_shuffle(a)
print(sess.run(x))
#===>[[3 4],[5 6],[1 2]]
tf.argmax | tf.argmin
tf.argmax(input=tensor,dimention=axis)
找到給定的張量tensor中在指定軸axis上的最大值/最小值的位置。
a=tf.get_variable(name='a',
shape=[3,4],
dtype=tf.float32,
initializer=tf.random_uniform_initializer(minval=-1,maxval=1))
b=tf.argmax(input=a,dimension=0)
c=tf.argmax(input=a,dimension=1)
sess = tf.InteractiveSession()
sess.run(tf.initialize_all_variables())
print(sess.run(a))
#[[ 0.04261756 -0.34297419 -0.87816691 -0.15430689]
# [ 0.18663144 0.86972666 -0.06103253 0.38307118]
# [ 0.84588599 -0.45432305 -0.39736366 0.38526249]]
print(sess.run(b))
#[2 1 1 2]
print(sess.run(c))
#[0 1 0]
tf.equal
tf.equal(x, y, name=None):
判斷兩個tensor是否每個元素都相等。返回一個格式為bool的tensor
tf.cast
cast(x, dtype, name=None)
將x的資料格式轉化成dtype.例如,原來x的資料格式是bool,那麼將其轉化成float以後,就能夠將其轉化成0和1的序列。反之也可以
a = tf.Variable([1,0,0,1,1])
b = tf.cast(a,dtype=tf.bool)
sess = tf.InteractiveSession()
sess.run(tf.initialize_all_variables())
print(sess.run(b))
#[ True False False True True]
tf.matmul
用來做矩陣乘法。若a為l*m的矩陣,b為m*n的矩陣,那麼通過tf.matmul(a,b) 結果就會得到一個l*n的矩陣
不過這個函式還提供了很多額外的功能。我們來看下函式的定義:
matmul(a, b,
transpose_a=False, transpose_b=False,
a_is_sparse=False, b_is_sparse=False,
name=None):
可以看到還提供了transpose和is_sparse的選項。
如果對應的transpose項為True,例如transpose_a=True,那麼a在參與運算之前就會先轉置一下。
而如果a_is_sparse=True,那麼a會被當做稀疏矩陣來參與運算。
tf.reshape
reshape(tensor, shape, name=None)
顧名思義,就是將tensor按照新的shape重新排列。一般來說,shape有三種用法:
如果 shape=[-1], 表示要將tensor展開成一個list
如果 shape=[a,b,c,…] 其中每個a,b,c,..均>0,那麼就是常規用法
如果 shape=[a,-1,c,…] 此時b=-1,a,c,..依然>0。這表示tf會根據tensor的原尺寸,自動計算b的值。
官方給的例子已經很詳細了,我就不寫示例程式碼了
# tensor 't' is [1, 2, 3, 4, 5, 6, 7, 8, 9]
# tensor 't' has shape [9]
reshape(t, [3, 3]) ==> [[1, 2, 3],
[4, 5, 6],
[7, 8, 9]]
# tensor 't' is [[[1, 1], [2, 2]],
# [[3, 3], [4, 4]]]
# tensor 't' has shape [2, 2, 2]
reshape(t, [2, 4]) ==> [[1, 1, 2, 2],
[3, 3, 4, 4]]
# tensor 't' is [[[1, 1, 1],
# [2, 2, 2]],
# [[3, 3, 3],
# [4, 4, 4]],
# [[5, 5, 5],
# [6, 6, 6]]]
# tensor 't' has shape [3, 2, 3]
# pass '[-1]' to flatten 't'
reshape(t, [-1]) ==> [1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6]
# -1 can also be used to infer the shape
# -1 is inferred to be 9:
reshape(t, [2, -1]) ==> [[1, 1, 1, 2, 2, 2, 3, 3, 3],
[4, 4, 4, 5, 5, 5, 6, 6, 6]]
# -1 is inferred to be 2:
reshape(t, [-1, 9]) ==> [[1, 1, 1, 2, 2, 2, 3, 3, 3],
[4, 4, 4, 5, 5, 5, 6, 6, 6]]
# -1 is inferred to be 3:
reshape(t, [ 2, -1, 3]) ==> [[[1, 1, 1],
[2, 2, 2],
[3, 3, 3]],
[[4, 4, 4],
[5, 5, 5],
[6, 6, 6]]]
2. 神經網路相關操作
tf.nn.embedding_lookup
embedding_lookup(params, ids, partition_strategy=”mod”, name=None,
validate_indices=True):
簡單的來講,就是將一個數字序列ids轉化成embedding序列表示。
假設params.shape=[v,h], ids.shape=[m], 那麼該函式會返回一個shape=[m,h]的張量。用數學來表示,就是
那麼這個有什麼用呢?如果你瞭解word2vec的話,就知道我們可以根據文件來對每個單詞生成向量。單詞向量可以進一步用來測量單詞的相似度等等。那麼假設我們現在已經獲得了每個單詞的向量,都存在param中。那麼根據單詞id序列ids,就可以通過embedding_lookup來獲得embedding表示的序列。
tf.trainable_variables
返回所有可訓練的變數。
在創造變數(tf.Variable, tf.get_variable 等操作)時,都會有一個trainable的選項,表示該變數是否可訓練。這個函式會返回圖中所有trainable=True的變數。
tf.get_variable(…), tf.Variable(…)的預設選項是True, 而 tf.constant(…)只能是False
import tensorflow as tf
from pprint import pprint
a = tf.get_variable('a',shape=[5,2]) # 預設 trainable=True
b = tf.get_variable('b',shape=[2,5],trainable=False)
c = tf.constant([1,2,3],dtype=tf.int32,shape=[8],name='c') # 因為是常量,所以trainable=False
d = tf.Variable(tf.random_uniform(shape=[3,3]),name='d')
tvar = tf.trainable_variables()
tvar_name = [x.name for x in tvar]
print(tvar)
# [<tensorflow.python.ops.variables.Variable object at 0x7f9c8db8ca20>, <tensorflow.python.ops.variables.Variable object at 0x7f9c8db8c9b0>]
print(tvar_name)
# ['a:0', 'd:0']
sess = tf.InteractiveSession()
sess.run(tf.initialize_all_variables())
pprint(sess.run(tvar))
#[array([[ 0.27307487, -0.66074866],
# [ 0.56380701, 0.62759042],
# [ 0.50012994, 0.42331111],
# [ 0.29258847, -0.09185416],
# [-0.35913971, 0.3228929 ]], dtype=float32),
# array([[ 0.85308731, 0.73948073, 0.63190091],
# [ 0.5821209 , 0.74533939, 0.69830012],
# [ 0.61058474, 0.76497936, 0.10329771]], dtype=float32)]
tf.gradients
用來計算導數。該函式的定義如下所示
def gradients(ys,
xs,
grad_ys=None,
name="gradients",
colocate_gradients_with_ops=False,
gate_gradients=False,
aggregation_method=None):
雖然可選引數很多,但是最常使用的還是ys和xs。根據說明得知,ys和xs都可以是一個tensor或者tensor列表。而計算完成以後,該函式會返回一個長為len(xs)的tensor列表,列表中的每個tensor是ys中每個值對xs[i]求導之和。如果用數學公式表示的話,那麼
g = tf.gradients(y,x)
可以表示成
tf.clip_by_global_norm
修正梯度值,用於控制梯度爆炸的問題。梯度爆炸和梯度彌散的原因一樣,都是因為鏈式法則求導的關係,導致梯度的指數級衰減。為了避免梯度爆炸,需要對梯度進行修剪。
先來看這個函式的定義:
def clip_by_global_norm(t_list, clip_norm, use_norm=None, name=None):
- 1
- 1
輸入引數中:t_list為待修剪的張量, clip_norm 表示修剪比例(clipping ratio).
函式返回2個引數: list_clipped,修剪後的張量,以及global_norm,一箇中間計算量。當然如果你之前已經計算出了global_norm值,你可以在use_norm選項直接指定global_norm的值。
那麼具體如何計算呢?根據原始碼中的說明,可以得到
list_clipped[i]=t_list[i] * clip_norm / max(global_norm, clip_norm),其中
global_norm = sqrt(sum([l2norm(t)**2 for t in t_list]))
如果你更熟悉數學公式,則可以寫作
其中,
Lic和Lig代表t_list[i]和list_clipped[i],
Nc和Ng代表clip_norm 和 global_norm的值。
其實也可以看到其實Ng就是t_list的L2模。上式也可以進一步寫作
Lic={Lit,(Ng<=Nc)Lit∗NcNg,(Ng>