TensorFlow में Variable और get_variable के बीच अंतर


125

जहां तक ​​मुझे पता है, Variableएक चर बनाने के लिए डिफ़ॉल्ट ऑपरेशन है, और get_variableमुख्य रूप से वजन साझा करने के लिए उपयोग किया जाता है।

एक ओर, जब भी आपको एक चर की आवश्यकता होती है तो कुछ लोग get_variableआदिम Variableसंचालन के बजाय उपयोग करने का सुझाव देते हैं । दूसरी ओर, मैं केवल get_variableTensorFlow के आधिकारिक दस्तावेजों और डेमो के किसी भी उपयोग को देखता हूं ।

इस प्रकार मैं अंगूठे के कुछ नियमों को जानना चाहता हूं कि इन दोनों तंत्रों का सही उपयोग कैसे किया जाए। क्या कोई "मानक" सिद्धांत हैं?


6
get_variable नया तरीका है, वैरिएबल पुराना तरीका है (जो हमेशा के लिए समर्थित हो सकता है) जैसा कि Lukasz कहते हैं (PS: उन्होंने TF में बहुत अधिक परिवर्तनशील नाम लिखा है)
यारोस्लाव Bulatov

जवाबों:


90

मैं हमेशा उपयोग करने की सलाह tf.get_variable(...)दूंगा - यदि आपके पास किसी भी समय चर साझा करने की आवश्यकता है, तो यह आपके कोड को रीफ़ैक्टर करने के लिए आसान बना देगा, उदाहरण के लिए, बहु-जीपीयू सेटिंग में (बहु-जीयूपी सीआईएफएआर उदाहरण देखें)। इसका कोई नकारात्मक पहलू नहीं है।

शुद्ध tf.Variableनिम्न-स्तर है; कुछ बिंदु पर tf.get_variable()मौजूद नहीं था इसलिए कुछ कोड अभी भी निम्न-स्तरीय तरीके का उपयोग करते हैं।


5
अपने जवाब के लिए आपको बहुत बहुत धन्यवाद। लेकिन मैं अभी भी कैसे को बदलने के लिए के बारे में एक सवाल है tf.Variableके साथ tf.get_variableहर जगह। यही कारण है कि जब मैं एक चर संख्या के साथ एक चर को इनिशियलाइज़ करना चाहता हूं, तो मैं इसे करने का एक साफ और कुशल तरीका नहीं पा सकता हूं जैसा कि मैं करता हूं tf.Variable। आप इसे कैसे हल करते हैं? धन्यवाद।
लिफू हुआंग

68

tf.Variable एक वर्ग है, और tf.Variable सहित tf.Variable.__init__और बनाने के कई तरीके हैं और tf.get_variable

tf.Variable.__init__: Initial_value के साथ एक नया चर बनाता है ।

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

tf.get_variable: इन मापदंडों के साथ एक मौजूदा चर हो जाता है या एक नया बनाता है। आप इनिलाइज़र का उपयोग भी कर सकते हैं।

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यह बहुत सुविधाजनक है, मुझे आश्चर्य है कि मैंने Variableइसके बजाय सबसे अधिक TensorFlow कोड का उपयोग क्यों देखा get_variable। क्या उनके बीच चयन करने पर विचार करने के लिए कोई सम्मेलन या कारक हैं। धन्यवाद!
लिफ्टू हुआंग

यदि आप एक निश्चित मान रखना चाहते हैं, तो चर का उपयोग करना सरल है: x = tf.Variable (3)।
किम

@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()वांछित परिणाम प्राप्त करने के लिए उपयोग कर सकते हैं ।
बीटा

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>}

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.