一 .tf.variable() 在模型中每次調用都會重建變量,使其存儲相同變量而消耗內存,如:
def repeat_value():
weight=tf.variable(tf.random_normal([5,5,6]),name='weight')
return weight
如果多次調用函數如:
result1=repeat_value()
result2=repeat_value() # 重復調用
將會重復創建一份變量,卻保存相同模型參數。若使用字典可以解決此類問題,卻破壞模型封裝性(有關字典解決此問題,可留言回復)。
二 . tf.get_variable()與tf.variable_scope()方法可以解決上面問題,其中前者負責創建或獲取指定名稱的變量,后者負責傳入tf.get_variable()方法的變量名稱的名字空間。
def a(input,kernel_shape):
w=tf.get_variable('w',kernel_shape,initializer=tf.random_normal()) #創建獲取名叫w的變量
conv=tf.nn.conv2d(input,w,strides=[1,1,1,1],padding='SAME')
return conv
def b(img):
with tf.variable_scope("conv1"): #創建conv1/w變量
r1=a(img,[5,5,32,32])
with tf.variable_scope("conv2"): #創建conv2/w變量
r2=a(r1,[5,5,32,32])
return r2
# with上下文中定義的變量都會加上tf.variable_scope方法中定義的前綴,這樣能夠通過不同的變量作用域區分同類網絡的不同參數。
# 但第二次調用函數b(),tf.get_variable()就會拋出變量已存在,無法解決復用問題。因此,需要加上reuse=True,如下:
def b(img):
with tf.variable_scope("conv1",reuse=True): #創建conv1/w變量
r1=a(img,[5,5,32,32])
with tf.variable_scope("conv2",reuse=True): #創建conv2/w變量
r2=a(r1,[5,5,32,32])
return r2
# 更改后可以反復調用了。
三.共享作用域下的初始化(類似c++類中的繼承):
with tf.variable_scope("conv1",initializer=tf.constant_initializer(0.8)): #創建conv1/w變量
w=tf.get_variable('w',[1]) #此處使用外圍的initializer=tf.constant_initializer(0.8)初始化
w1 = tf.get_variable('w1', [1,2], initializer=tf.random_normal()) # 此處覆蓋initializer=tf.constant_initializer(0.8)初始化,
# 使用本身initializer=tf.random_normal()初始化。
with tf.variable_scope("conv2"): #嵌套conv1下的作用域
w2 = tf.get_variable('w2', [1,2]) #此處使用外圍的initializer=tf.constant_initializer(0.8)初始化(類似繼承)
w1 = tf.get_variable('w1', [1,2], tf.constant_initializer(0.4)) # 此處覆蓋initializer=tf.constant_initializer(0.8)初始化,
# 使用本身tf.constant_initializer(0.4)初始化。