ความแตกต่างระหว่าง Variable และ get_variable ใน TensorFlow


125

เท่าที่ฉันทราบVariableเป็นการดำเนินการเริ่มต้นสำหรับการสร้างตัวแปรและget_variableส่วนใหญ่จะใช้สำหรับการแบ่งน้ำหนัก

ในแง่หนึ่งมีบางคนแนะนำให้ใช้get_variableแทนการVariableดำเนินการดั้งเดิมเมื่อใดก็ตามที่คุณต้องการตัวแปร ในทางกลับกันฉันเห็นการใช้งานget_variableในเอกสารและการสาธิตอย่างเป็นทางการของ TensorFlow

ดังนั้นฉันต้องการทราบกฎง่ายๆในการใช้กลไกทั้งสองนี้อย่างถูกต้อง มีหลักการ "มาตรฐาน" หรือไม่?


6
get_variable เป็นวิธีใหม่ตัวแปรเป็นวิธีเก่า (ซึ่งอาจได้รับการสนับสนุนตลอดไป) ตามที่ Lukasz กล่าว (PS: เขาเขียนชื่อตัวแปรส่วนใหญ่ใน TF)
Yaroslav Bulatov

คำตอบ:


90

ฉันขอแนะนำให้ใช้เสมอtf.get_variable(...)- จะทำให้ง่ายขึ้นในการ refactor โค้ดของคุณหากคุณต้องการแบ่งปันตัวแปรเมื่อใดก็ได้เช่นในการตั้งค่า multi-gpu (ดูตัวอย่าง multi-gpu CIFAR) ไม่มีข้อเสียเลย

บริสุทธิ์tf.Variableอยู่ระดับล่าง ในบางจุดtf.get_variable()ไม่มีรหัสดังนั้นบางรหัสจึงยังคงใช้วิธีระดับต่ำ


5
ขอบคุณมากสำหรับคำตอบ แต่ฉันยังมีคำถามหนึ่งเกี่ยวกับวิธีแทนที่tf.Variableด้วยtf.get_variableทุกที่ นั่นคือเมื่อฉันต้องการที่จะเริ่มต้นตัวแปรกับอาร์เรย์ numpy tf.Variableผมไม่สามารถหาวิธีทำความสะอาดและมีประสิทธิภาพในการดำเนินการที่ผมทำกับ คุณจะแก้มันอย่างไร? ขอบคุณ
Lifu Huang

69

tf.Variable เป็นคลาสและมีหลายวิธีในการสร้าง tf ตัวแปรรวมถึงtf.Variable.__init__และtf.get_variable.

tf.Variable.__init__: สร้างตัวแปรใหม่ที่มีinitial_value

W = tf.Variable(<initial-value>, name=<optional-name>)

tf.get_variable: รับตัวแปรที่มีอยู่พร้อมกับพารามิเตอร์เหล่านี้หรือสร้างตัวแปรใหม่ คุณยังสามารถใช้ initializer

W = tf.get_variable(name, shape=None, dtype=tf.float32, initializer=None,
       regularizer=None, trainable=True, collections=None)

การใช้ initializers เช่นxavier_initializer:

W = tf.get_variable("W", shape=[784, 256],
       initializer=tf.contrib.layers.xavier_initializer())

ข้อมูลเพิ่มเติมที่นี่


ใช่Variableจริงๆแล้วฉันหมายถึงการใช้__init__ไฟล์. เนื่องจากget_variableมีความสะดวกดังนั้นฉันสงสัยว่าทำไมส่วนใหญ่รหัส TensorFlow ใช้ผมเห็นแทนVariable get_variableมีอนุสัญญาหรือปัจจัยใดบ้างที่ต้องพิจารณาเมื่อเลือกระหว่างกัน ขอบคุณ!
Lifu Huang

หากคุณต้องการมีค่าที่แน่นอนการใช้ Variable นั้นทำได้ง่าย: x = tf.Variable (3)
Sung Kim

@SungKim โดยปกติเมื่อเราใช้tf.Variable()เราสามารถเริ่มต้นเป็นค่าสุ่มจากการแจกแจงปกติที่ถูกตัดทอน w1 = tf.Variable(tf.truncated_normal([5, 50], stddev = 0.01), name = 'w1')นี่คือตัวอย่างของฉัน สิ่งนี้จะเทียบเท่ากับอะไร? ฉันจะบอกได้อย่างไรว่าฉันต้องการแบบปกติที่ถูกตัดทอน ฉันควรทำw1 = tf.get_variable(name = 'w1', shape = [5,50], initializer = tf.truncated_normal, regularizer = tf.nn.l2_loss)อย่างไร
Euler_Salter

@Euler_Salter: คุณสามารถใช้tf.truncated_normal_initializer()เพื่อให้ได้ผลลัพธ์ที่ต้องการ
Beta

46

ฉันพบความแตกต่างหลักสองประการระหว่างข้อหนึ่งและข้ออื่น ๆ

  1. อันดับแรกคือtf.Variableจะสร้างตัวแปรใหม่เสมอในขณะที่tf.get_variableรับตัวแปรที่มีอยู่พร้อมพารามิเตอร์ที่ระบุจากกราฟและหากไม่มีอยู่ให้สร้างตัวแปรใหม่

  2. tf.Variable กำหนดให้ระบุค่าเริ่มต้น

สิ่งสำคัญคือต้องชี้แจงว่าฟังก์ชันtf.get_variableนำหน้าชื่อด้วยขอบเขตตัวแปรปัจจุบันเพื่อทำการตรวจสอบการใช้ซ้ำ ตัวอย่างเช่น:

with tf.variable_scope("one"):
    a = tf.get_variable("v", [1]) #a.name == "one/v:0"
with tf.variable_scope("one"):
    b = tf.get_variable("v", [1]) #ValueError: Variable one/v already exists
with tf.variable_scope("one", reuse = True):
    c = tf.get_variable("v", [1]) #c.name == "one/v:0"

with tf.variable_scope("two"):
    d = tf.get_variable("v", [1]) #d.name == "two/v:0"
    e = tf.Variable(1, name = "v", expected_shape = [1]) #e.name == "two/v_1:0"

assert(a is c)  #Assertion is true, they refer to the same object.
assert(a is d)  #AssertionError: they are different objects
assert(d is e)  #AssertionError: they are different objects

ข้อผิดพลาดในการยืนยันครั้งสุดท้ายน่าสนใจ: ตัวแปรสองตัวที่มีชื่อเดียวกันภายใต้ขอบเขตเดียวกันควรเป็นตัวแปรเดียวกัน แต่ถ้าคุณทดสอบชื่อของตัวแปรdและeคุณจะรู้ว่า Tensorflow เปลี่ยนชื่อตัวแปรe:

d.name   #d.name == "two/v:0"
e.name   #e.name == "two/v_1:0"

ตัวอย่างยอดเยี่ยม! เกี่ยวกับd.nameและe.nameฉันเพิ่งเจอเอกสาร TensorFlow นี้เกี่ยวกับการดำเนินการตั้งชื่อกราฟเทนเซอร์ซึ่งอธิบายว่า:If the default graph already contained an operation named "answer", the TensorFlow would append "_1", "_2", and so on to the name, in order to make it unique.
Atlas7

2

ความแตกต่างอีกประการหนึ่งอยู่ที่สิ่งหนึ่งอยู่ใน('variable_store',)คอลเลกชัน แต่อีกอันไม่ใช่

โปรดดูแหล่งที่มารหัส :

def _get_default_variable_store():
  store = ops.get_collection(_VARSTORE_KEY)
  if store:
    return store[0]
  store = _VariableStore()
  ops.add_to_collection(_VARSTORE_KEY, store)
  return store

ขอยกตัวอย่างว่า:

import tensorflow as tf
from tensorflow.python.framework import ops

embedding_1 = tf.Variable(tf.constant(1.0, shape=[30522, 1024]), name="word_embeddings_1", dtype=tf.float32) 
embedding_2 = tf.get_variable("word_embeddings_2", shape=[30522, 1024])

graph = tf.get_default_graph()
collections = graph.collections

for c in collections:
    stores = ops.get_collection(c)
    print('collection %s: ' % str(c))
    for k, store in enumerate(stores):
        try:
            print('\t%d: %s' % (k, str(store._vars)))
        except:
            print('\t%d: %s' % (k, str(store)))
    print('')

ผลลัพธ์:

collection ('__variable_store',): 0: {'word_embeddings_2': <tf.Variable 'word_embeddings_2:0' shape=(30522, 1024) dtype=float32_ref>}

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.