標籤:開發 calling 一個 pytho scope span iter model example
筆者提交到gitHub上的問題描述地址是:https://github.com/tensorflow/tensorflow/issues/20140
問題描述(英文版):
write the code below, and save it to a ,ckpt as a model
import tensorflow as tf`v1 = tf.Variable(tf.constant(1.0, shape=[1]), name = "v1")v2 = tf.Variable(tf.constant(2.0, shape=[1]), name = "v2")v3 = tf.Variable(tf.constant(3.0, shape=[1]), name = "v3")result=v1+v2result2= result + v3init_op = tf.global_variables_initializer()saver = tf.train.Saver()with tf.Session() as sess: sess.run(init_op) writer = tf.summary.FileWriter(‘./graphs/const_add‘, sess.graph) saver.save(sess, "Saved_model/model.ckpt")`
then in another .py, we restore the model from the model.ckpt file
import tensorflow as tfsaver = tf.train.import_meta_graph("Saved_model/model.ckpt.meta")with tf.Session() as sess: saver.restore(sess, "Saved_model/model.ckpt") print (sess.run(tf.get_default_graph().get_tensor_by_name("add:0"))) #sess.run(tf.assign(v1,[10])) #直接這樣使用v1,會提示v1沒有定義 #with tf.variable_scope("",reuse=tf.AUTO_REUSE): with tf.variable_scope("",reuse=False): v1=tf.get_variable(name="v1",shape=[1]) print(v1.name) sess.run(tf.assign(v1,[10])) """④輸出所有可訓練的變數名稱,也就是神經網路的參數""" trainable_variables=tf.trainable_variables() variable_list_name = [c.name for c in tf.trainable_variables()] variable_list = sess.run(variable_list_name) for k,v in zip(variable_list_name,variable_list): print("variable name:",k) print("shape:",v.shape) #print(v) """④輸出所有可訓練的變數名稱,也就是神經網路的參數""" print (sess.run(tf.get_default_graph().get_tensor_by_name("v1:0"))) print (sess.run(tf.get_default_graph().get_tensor_by_name("add:0"))) print (sess.run(tf.get_default_graph().get_tensor_by_name("add_1:0"))) print (sess.run(tf.get_default_graph().get_tensor_by_name("v1_1:0")))
the results will be as below:
we will find that:
if we restore some variables from the already existed model file ""Saved_model/model.ckpt.meta")",
such as v1,v2,v3 in this example.
it will influence the process of calling get_variable. Because of these two causes as below:
- the variables restored from the model file such as v1,v2 and v3 will not exist in the scope of get_variable, it means you can only use
with tf.variable_scope("",reuse=False): v1=tf.get_variable(name="v1",shape=[1])
and create a new variable. you can not reuse the restored variable v1 from the model file unless you define a v1 , before you restore from the model file. like below
v1=tf.get_variable(name="v1",shape=[1])saver = tf.train.Saver()with tf.Session() as sess: saver.restore(sess, "Saved_model/model.ckpt") print (sess.run(result))
that is , you can not reuse the restored variable v1 which is from restoring the model file unless you define it befor you restore.
2. although tensorflow doesnot allow reusing the restored variable v1 which is from restoring the model file if you don‘t define v1 before you restore the model file.
But if you call get_varialbe after you restore the model file, it will create a variable whose name is "v1_1" but not as name=‘v1‘ which you specify.
in my opinion, it should be corrected because it is so confusing. how to correct it?
i think get_variable should also reuse the variables which is loaded by restoring some model file.
the last sentence is what i finally want to say.
My english is to bad, you can run the code i offer and will find what i want to convey.
Thanks.
總結
假定一個持久化模型中存在一個V1命名的變數,此時如果使用import_meta_graph方式載入持久化模型。
- 首先,使用import_meta_graph要載入的持久化模型中的變數命名不能與當前代碼預設計算圖中的變數命名發生衝突
- 其次,如果此時希望通過利用tf.get_variable的方式,來建立python變數與計算圖變數節點之間的關係,即:
我再補充一下,就是說,載入持久化模型的三種方式:
第一,saver.restore:屬於當前代碼計算圖已經定義,我需要將持久化模型中變數的值載入到當前代碼計算圖中的變數中去。所以,兩者只能是持久化模型中的變數是當前代碼計算圖中變數集合的一個子集,必須是一種嚴格包含的關係。
第二,import_meta_graph則完全不允許當前代碼計算圖已經定義的變數節點和要載入的持久化模型中的節點存在衝突,因為它價值的是整個圖。不是單純將變數的值進行載入。
第三,使用pb檔案的方式,即使持久化模型中的變數節點和當前代碼計算圖中定義的變數節點發生衝突,也是毛事沒有,沒有任何關係。因為pb檔案的方式載入進來的計算圖,
會全部加上import/首碼。也就是說,從命名空間上就隔開了這種衝突。
上述三點是很重要的結論,自己調試和觀察的。(是市面上書中找不到的結論。)
所以,使用別人的模型,最好的方式就是用pb檔案。因為不會有衝突的可能!但是,有一個弊端就是,import命名空間下的變數不能參與到當前的訓練!!!記住,不能參與訓練!
with tf.variable_scope("",reuse=False): v1=tf.get_variable(name="v1",shape=[1]) print(v1.name)
是不可能做到的。而且你只能用reuse=False,就好像:載入持久化模型以後,計算圖中沒有V1變數節點一樣。
同時,你使用v1=tf.get_variable(name="v1",shape=[1])方式,會在當前代碼的計算圖中產生一個新的變數節點V1_1,並非載入的持久化模型中的變數節點V1。此時,就會出現函數功能失效。也就是,你希望調用get_variable函數使得:python的變數v1和計算圖中的變數節點v1是綁定的,但是情況並非如此,綁定的是變數節點v1_1。
所以訪問計算圖中的V1節點,就只能使用tf.get_default_graph().get_tensor_by_name("v1:0")的方式。
很多人可能並不理解這個:0,這是一個operation的輸出。也就是說變數節點的輸出只有一個,所以用0表示引用計算圖中這個變數節點的輸出tensor。
事實上,可以自訂tensorflow中的operation,也就是我可以輸出多個tensor。那個時候:0,:1就可以用起來了。
總的來說,筆者將此問題提交到gitHub,目前仍然處於歡迎討論狀態。即tensorflow的開發人員需要更多tensorflow使用者的意見,來回答:有沒有必要對這個問題進行修複。
6_1 持久化模型與再次載入_探討(1)_import_meta_graph方式載入持久化模型會存在的變數管理命名混淆的問題