2016-12-22 25 views
7

मैंने सोचा है कि चर असाइनमेंट sess.run करने के लिए दिया एक सूची में सभी कार्यों के बाद किया जाता है, लेकिन निम्नलिखित कोड अलग निष्पादन में अलग-अलग परिणाम देता है। यह सूची में यादृच्छिक रूप से संचालन प्रतीत होता है और सूची में ऑपरेशन के चलाने के बाद चर निर्दिष्ट करता है।टेन्सफोर्लो: जब सूची में sess.run में परिवर्तनीय असाइनमेंट किया जाता है?

a = tf.Variable(0) 
b = tf.Variable(1) 
c = tf.Variable(1) 
update_a = tf.assign(a, b + c) 
update_b = tf.assign(b, c + a) 
update_c = tf.assign(c, a + b) 

with tf.Session() as sess: 
    sess.run(initialize_all_variables) 
    for i in range(5): 
    a_, b_, c_ = sess.run([update_a, update_b, update_c]) 

मैं चर असाइनमेंट का समय जानना चाहता हूं। कौन सा सही हैं: "update_x -> असाइन एक्स -> ... -> udpate_z -> z आवंटित" या "update_x -> udpate_y -> udpate_z -> आवंटित एक, ख, ग"? (जहां (एक्स, वाई, जेड) का क्रमपरिवर्तन है (ए, बी, सी)) इसके अलावा, अगर वहाँ एक तरीका है कि बाद के काम (असाइनमेंट सूची में सभी आपरेशनों किया जाता है के बाद किया जाता है) का एहसास है, तो कृपया मुझे पता चले कि इसे कैसे महसूस किया जाए।

उत्तर

9

तीन ऑपरेशंस update_a, update_b, और update_c डेटाफ्लो ग्राफ़ में कोई परस्पर निर्भरता नहीं है, इसलिए टेंसरफ्लो किसी भी क्रम में उन्हें निष्पादित करने का विकल्प चुन सकता है। (वर्तमान कार्यान्वयन में, यह संभव है कि उन सभी को तीन अलग-अलग धागे पर समानांतर में क्रियान्वित की जाएगी।) एक दूसरा निट कि चर के पढ़ता है तो अपने कार्यक्रम में मूल्य update_b में सौंपा, डिफ़ॉल्ट रूप से कैश नहीं किया जाता है (यानी c + a) परिवर्तनीय पहली बार पढ़े जाने पर निर्भर करता है कि a के मूल या अद्यतन मान का उपयोग कर सकते हैं।

आप यह सुनिश्चित करें कि आपरेशन एक विशेष क्रम में हो, तो आप with tf.control_dependencies([...]): ब्लॉकों का उपयोग कर सकते लागू करने के लिए है कि ब्लॉक के भीतर बनाई गई संचालन सूची में नाम के संचालन के बाद क्या चाहते हैं। with tf.control_dependencies([...]): ब्लॉक के अंदर आप tf.Variable.read_value() का उपयोग कर सकते हैं ताकि बिंदु को स्पष्ट किया जा सके।

इसलिए, यदि आप यह सुनिश्चित करें कि update_aupdate_b से पहले होता है चाहते हैं और update_bupdate_c से पहले होता है, तुम कर सकते हो:

update_a = tf.assign(a, b + c) 

with tf.control_dependencies([update_a]): 
    update_b = tf.assign(b, c + a.read_value()) 

with tf.control_dependencies([update_b]): 
    update_c = tf.assign(c, a.read_value() + b.read_value()) 
+0

आपके उत्तर @mrry के लिए धन्यवाद। मैंने इसकी सराहना की और समझ लिया कि मेरे कोड में संचालन के क्रम को कैसे निर्दिष्ट किया जाए। फिर, मेरे पास आपके उत्तर के बारे में एक और सवाल है। यदि किसी सूची में संचालन में कुछ परस्पर निर्भरताएं हैं, तो क्या उनके संचालन के बाद सभी मूल्यों को निष्पादित किया जाता है? और उस स्थिति में, डिफ़ॉल्ट रूप से संचालन के निष्पादन का आदेश क्या है ('tf.control_dependencies' का उपयोग किए बिना)। – Sarah

+0

"ऑपरेशन में एक सूची" से आपका क्या मतलब है? आम तौर पर, जैसे ही उनका नया मान उपलब्ध होता है, ऑप असाइन कर सकते हैं। जैसे ही चरण शुरू होता है वैरिएबल-रीड ऑप्स चला सकते हैं। हालांकि, स्पष्ट नियंत्रण (या डेटा) निर्भरताओं के बिना, एक चर के लिए असाइनमेंट एक ही चर के बाद या बाद में हो सकता है, इस पर निर्भर करता है कि ओप कैसे निर्धारित किए जाते हैं। इस मामले में डिफ़ॉल्ट ऑर्डरिंग अनिर्धारित है। – mrry

+0

संदिग्ध qustion के लिए खेद है। मेरा मतलब है एक ऑपरेशन सूची जैसे '[op1, op2, op3] '। मुझे गलतफहमी हो सकती है। छद्म कोड: 'v = tf.Variable (0), c = tf.constant (3), add = tf.add (v, c), अद्यतन = tf.assign (v, add), mul = tf.mul (जोड़ें, अपडेट करें), sess.run ([mul, mul]) '' 9, 9] 'नहीं '[9, 36]' देता है। तो मैंने सोचा कि सूची में सभी परिचालनों के बाद असाइनमेंट किया जाता है '[mul, mul] ', जैसे mul -> mul -> असाइन करें, mul -> असाइन करें -> mul -> असाइन करें। – Sarah

1

तुम्हारा 'इस उदाहरण के आधार पर,

v = tf.Variable(0) 
c = tf.constant(3) 
add = tf.add(v, c) 
update = tf.assign(v, add) 
mul = tf.mul(add, update) 

with tf.Session() as sess: 
    sess.run(tf.initialize_all_variables()) 
    res = sess.run([mul, mul]) 
    print(res) 

आउटपुट: [9, 9]

आपको [9, 9] मिलता है और यह वास्तव में हमने इसे करने के लिए कहा है। इस बारे में सोचें:

रन के दौरान, mul सूची से लिया जाता है, यह इसकी परिभाषा को देखता है और tf.mul(add, update) पाता है। अब, इसे add के मान की आवश्यकता है जो tf.add(v, c) की ओर जाता है। इसलिए, यह v और c के मूल्य में प्लग, 3.

ठीक है के रूप में add का मूल्य हो जाता है, अब हम जो tf.assign(v, add) के रूप में परिभाषित किया गया है update का मूल्य की जरूरत है। हम दोनों add के मूल्यों (जो यह अब सिर्फ अभिकलन 3 के रूप में) & v है। इसलिए, यह v के मान को 3 होने के लिए अद्यतन करता है जो update के लिए भी मूल्य है।

अब, यह जो 3. इस प्रकार हैं, गुणा पैदावार mul में 9 add और update दोनों के लिए मान होता है।

मुझे लगता है कि परिणाम में अगले आइटम (ऑपरेशन) के लिए, मुझे लगता है कि यह mul का सिर्फ गणना मूल्य लौटाता है। मुझे यकीन नहीं है कि यह फिर से कदम करता है या सिर्फ उसी (कैश किए गए?) मान को लौटाता है जो इसे mul के लिए गणना करता है, यह समझते हुए कि हमारे पास परिणाम है या ये ऑपरेशन समानांतर (सूची में प्रत्येक तत्व के लिए) में होते हैं। हो सकता है कि @mrry या @YaroslavBulatov कृपया इस भाग पर टिप्पणी कर सकते हैं?


@ mrry की टिप्पणी का हवाला देते हुए:

जब आप sess.run([x, y, z]) एक बार फोन, TensorFlow प्रत्येक सेशन कि उन tensors एक बार केवल (जब तक कि वहां आपकी ग्राफ में एक tf.while_loop()) पर निर्भर करती है निष्पादित करता है। यदि सूची में एक सेंसर दो बार दिखाई देता है (जैसे mul आपके उदाहरण में), तो टेंसरफ्लो इसे एक बार निष्पादित करेगा और परिणाम के दो प्रतियां लौटाएगा। असाइनमेंट को एक से अधिक बार चलाने के लिए, आपको या तो sess.run() कई बार कॉल करना होगा, या अपने ग्राफ में लूप डालने के लिए tf.while_loop() का उपयोग करना होगा।

संबंधित मुद्दे