TensorFlow में ढाल क्लिपिंग कैसे लागू करें?


96

उदाहरण कोड को ध्यान में रखते हुए ।

मैं जानना चाहता हूं कि आरएनएन पर इस नेटवर्क पर ग्रेडिएंट क्लिपिंग कैसे लागू करें जहां ग्रेडिएंट्स में विस्फोट होने की संभावना है।

tf.clip_by_value(t, clip_value_min, clip_value_max, name=None)

यह एक उदाहरण है जिसका उपयोग किया जा सकता है लेकिन मैं इसे कहां प्रस्तुत कर सकता हूं? आरएनएन के बचाव में

    lstm_cell = rnn_cell.BasicLSTMCell(n_hidden, forget_bias=1.0)
    # Split data because rnn cell needs a list of inputs for the RNN inner loop
    _X = tf.split(0, n_steps, _X) # n_steps
tf.clip_by_value(_X, -1, 1, name=None)

लेकिन इसका कोई मतलब नहीं है क्योंकि टेंसर _X इनपुट है और ग्रेड नहीं है जिसे क्लिप करना है?

क्या मुझे इसके लिए अपने स्वयं के ऑप्टिमाइज़र को परिभाषित करना होगा या क्या कोई सरल विकल्प है?

जवाबों:


143

ग्रैडिएंट क्लिपिंग को ग्रेडिएंट की गणना के बाद होने की जरूरत है, लेकिन मॉडल के मापदंडों को अपडेट करने के लिए उन्हें लागू करने से पहले। आपके उदाहरण में, उन दोनों चीजों को AdamOptimizer.minimize()विधि द्वारा नियंत्रित किया जाता है ।

अपने ग्रेडिएंट्स को क्लिप करने के लिए आपको TensorFlow के एपीआई डॉक्यूमेंट में इस खंड में बताए अनुसार, क्लिप करना और उन्हें लागू करना होगा । विशेष रूप से आपको कॉल को minimize()विधि में बदलने की आवश्यकता होगी जैसे कि निम्नलिखित कुछ:

optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate)
gvs = optimizer.compute_gradients(cost)
capped_gvs = [(tf.clip_by_value(grad, -1., 1.), var) for grad, var in gvs]
train_op = optimizer.apply_gradients(capped_gvs)

4
स्टायरके, पोस्ट के लिए धन्यवाद। क्या आप जानते हैं कि अगले कदम वास्तव में ऑप्टिमाइज़र के पुनरावृत्ति को चलाने के लिए क्या हैं? आमतौर पर, एक ऑप्टिमाइज़र के रूप में त्वरित किया जाता है optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(cost) और फिर ऑप्टिमाइज़र का एक पुनरावृत्ति किया जाता है, optimizer.run()लेकिन optimizer.run()इस मामले में काम करना प्रतीत नहीं होता है?
Applecider 3

6
ठीक है यह मिला है optimizer.apply_gradients(capped_gvs)कि कुछ करने के लिए सौंपा जाना चाहिए x = optimizer.apply_gradients(capped_gvs)तो अपने सत्र के भीतर आप के रूप में प्रशिक्षित कर सकते हैंx.run(...)
Apple 4

3
अच्छा संपादन सुझाव के लिए @ रेमी-क्यूटनेट को चिल्लाओ । (जो दुर्भाग्य से जल्दबाजी में समीक्षकों द्वारा खारिज कर दिया गया था)
स्टायरके

यह मुझे देता है UserWarning: Converting sparse IndexedSlices to a dense Tensor with 148331760 elements. This may consume a large amount of memory.इसलिए किसी भी तरह मेरे विरल ग्रेडिएंट को घने में बदल दिया जाता है। किसी भी विचार कैसे इस समस्या को दूर करने के लिए?
पेका

8
असल में ग्रेडिएंट्स (टेनसफ़्लो डॉक्स, कंप्यूटर वैज्ञानिकों और लॉजिक के अनुसार) का सही तरीका tf.clip_by_global_norm@danijar द्वारा सुझाया गया है
gdelab

116

क्या लोकप्रिय होने के बावजूद, आप संभवतः इसके वैश्विक मानक द्वारा संपूर्ण ढाल को क्लिप करना चाहते हैं:

optimizer = tf.train.AdamOptimizer(1e-3)
gradients, variables = zip(*optimizer.compute_gradients(loss))
gradients, _ = tf.clip_by_global_norm(gradients, 5.0)
optimize = optimizer.apply_gradients(zip(gradients, variables))

प्रत्येक ढाल मैट्रिक्स को अलग-अलग करने से उनके सापेक्ष पैमाने में परिवर्तन होता है लेकिन यह भी संभव है:

optimizer = tf.train.AdamOptimizer(1e-3)
gradients, variables = zip(*optimizer.compute_gradients(loss))
gradients = [
    None if gradient is None else tf.clip_by_norm(gradient, 5.0)
    for gradient in gradients]
optimize = optimizer.apply_gradients(zip(gradients, variables))

TensorFlow 2 में, एक टेप ग्रेडिएंट्स की गणना करता है, ऑप्टिमाइज़र केरस से आते हैं, और हमें अपडेट सेशन को स्टोर करने की आवश्यकता नहीं है क्योंकि यह एक सत्र में इसे पास किए बिना स्वचालित रूप से चलता है:

optimizer = tf.keras.optimizers.Adam(1e-3)
# ...
with tf.GradientTape() as tape:
  loss = ...
variables = ...
gradients = tape.gradient(loss, variables)
gradients, _ = tf.clip_by_global_norm(gradients, 5.0)
optimizer.apply_gradients(zip(gradients, variables))

10
साथ अच्छा उदाहरण clip_by_global_norm()! इसे the correct way to perform gradient clippingटेंसोफ़्लो डॉक्स के रूप में भी वर्णित किया गया है: टेंसोरफ़्लो.org
versions

9
@Escachator यह आनुभविक है और यह आपके मॉडल और संभवतः कार्य पर निर्भर करेगा। मैं क्या कर रहा हूँ tf.global_norm(gradients)यह सामान्य सीमा को देखने के लिए ढाल के मानक की कल्पना करना है और फिर थोड़ा ऊपर क्लिप करना है ताकि आउटलेर को प्रशिक्षण को गड़बड़ाने से रोका जा सके।
दानीजेर

1
क्या आप अभी भी opt.minimize()बाद में फोन करेंगे या आप कुछ अलग कहेंगे जैसा opt.run()कि अन्य उत्तरों में से कुछ टिप्पणियों में सुझाया गया है?
reese0106

3
@ reese0106 नहीं, optimizer.minimize(loss)केवल कंप्यूटिंग के लिए और ग्रेडर लगाने के लिए एक शॉर्टहैंड है। आप मेरे उत्तर में उदाहरण चला सकते हैं sess.run(optimize)
14

1
इसलिए यदि मैं tf.estimator.EstimatorSpec(mode, loss=loss, train_op=train_op)एक प्रयोग समारोह में उपयोग कर रहा था , तो आपकी optimizeजगह मेरा train_opसही होगा? अभी मेरी train_op = optimizer.minimize(loss, global_step=global_step))कोशिश है कि मैं यह सुनिश्चित करूं कि मैं उसके अनुसार समायोजित
करूं

10

यह वास्तव में प्रलेखन में ठीक से समझाया गया है। :

कॉलिंग मिनिमम () ग्रेडिएंट्स की गणना करने और उन्हें वैरिएबल पर लागू करने दोनों का ख्याल रखती है। यदि आप उन्हें लागू करने से पहले ग्रेडिएंट को संसाधित करना चाहते हैं तो आप तीन चरणों में अनुकूलक का उपयोग कर सकते हैं:

  • कंप्यूटर्स की गणना कंप्यूट_ग्रेडिएंट्स () के साथ करें।
  • अपनी इच्छानुसार ग्रेडिएंट्स को प्रोसेस करें।
  • संसाधित ग्रेडिएंट्स को apply_gradients () के साथ लागू करें।

और उदाहरण में वे इन 3 चरणों का उपयोग करते हैं:

# Create an optimizer.
opt = GradientDescentOptimizer(learning_rate=0.1)

# Compute the gradients for a list of variables.
grads_and_vars = opt.compute_gradients(loss, <list of variables>)

# grads_and_vars is a list of tuples (gradient, variable).  Do whatever you
# need to the 'gradient' part, for example cap them, etc.
capped_grads_and_vars = [(MyCapper(gv[0]), gv[1]) for gv in grads_and_vars]

# Ask the optimizer to apply the capped gradients.
opt.apply_gradients(capped_grads_and_vars)

यहां MyCapperकोई भी फ़ंक्शन है जो आपके ग्रेडिएंट को कैप करता है। उपयोगी कार्यों (की तुलना में अन्य tf.clip_by_value()) की सूची यहाँ है


क्या आप अभी भी opt.minimize()बाद में फोन करेंगे या आप कुछ अलग कहेंगे जैसा opt.run()कि अन्य उत्तरों में से कुछ टिप्पणियों में सुझाया गया है?
reese0106

@ reese0106 नहीं, आपको उदाहरण के opt.apply_gradients(...)लिए एक वैरिएबल को असाइन करने की आवश्यकता है train_step(जैसे आप चाहते हैं opt.minimize()। और अपने मुख्य लूप में आप इसे सामान्य रूप से ट्रेन करने के लिए कहते हैंsess.run([train_step, ...], feed_dict)
dsalaj

ध्यान रखें कि ग्रेडिएंट को मॉडल में सभी मापदंडों के लिए नुकसान wrt के डेरिवेटिव के वेक्टर के रूप में परिभाषित किया गया है। TensorFlow इसे पायथन सूची के रूप में दर्शाता है जिसमें प्रत्येक चर और इसके ढाल के लिए एक टपल शामिल है। इसका मतलब है कि ग्रेडिएंट मानदंड को क्लिप करना, आप प्रत्येक टेंसर को अलग-अलग क्लिप नहीं कर सकते हैं, आपको एक बार सूची पर विचार करने की आवश्यकता है (उदाहरण के लिए tf.clip_by_global_norm(list_of_tensors))।
दानीझार

8

उन लोगों के लिए जो ढाल क्लिपिंग के विचार को समझना चाहते हैं (आदर्श द्वारा):

जब भी ग्रेडिएंट मान किसी विशेष सीमा से अधिक होता है, तो हम ग्रेडिएंट मान को क्लिप करते हैं ताकि यह सीमा के भीतर रहे। यह सीमा कभी-कभी निर्धारित की जाती है 5

ग्रेडिएंट जी हो और max_norm_threshold j हो

अब, अगर || जी || > जे , हम करते हैं:

g = ( j * g ) / || जी ||

यह कार्यान्वयन में किया गया है tf.clip_by_norm


अगर मुझे हाथ से दहलीज का चयन करने की आवश्यकता है, तो क्या ऐसा करने के लिए कोई सामान्य तरीका है?
ningyuwhut

यह कुछ कागजों में सुझाए गए काले जादू की तरह है। अन्यथा, आपको बहुत सारे प्रयोग करने हैं और यह पता लगाना है कि कौन सा बेहतर काम करता है।
kmario23

4

IMO सबसे अच्छा समाधान TF के अनुमानक डेकोरेटर के साथ अपने अनुकूलक को लपेट रहा है tf.contrib.estimator.clip_gradients_by_norm:

original_optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate)
optimizer = tf.contrib.estimator.clip_gradients_by_norm(original_optimizer, clip_norm=5.0)
train_op = optimizer.minimize(loss)

इस तरह से आपको केवल एक बार इसे परिभाषित करना है, और हर ग्रेडिएंट गणना के बाद इसे नहीं चलाना है।

प्रलेखन: https://www.tensorflow.org/api_docs/python/tf/contrib/estimator/clip_gradients_by_norm


2

ग्रैडिएंट क्लिपिंग मूल रूप से ग्रेडिएंट्स के विस्फोट या गायब होने की स्थिति में मदद करता है। आपके नुकसान की मात्रा बहुत अधिक है, जिसके परिणामस्वरूप घातीय ग्रेडिएंट्स नेटवर्क के माध्यम से प्रवाहित होंगे जिसके परिणामस्वरूप नैनो मान हो सकता है। इसे दूर करने के लिए हम एक विशिष्ट सीमा (-1 से 1 या किसी भी सीमा के अनुसार हालत में) ग्रेडिएंट को क्लिप करते हैं।

clipped_value=tf.clip_by_value(grad, -range, +range), var) for grad, var in grads_and_vars

जहां ग्रेड _and_vars ग्रेडिएंट्स के जोड़े हैं (जो आप tf.compute_gradients के माध्यम से गणना करते हैं) और उनके चर जिन्हें वे लागू किया जाएगा।

कतरन के बाद हम बस एक अनुकूलक का उपयोग करके इसके मूल्य को लागू करते हैं। optimizer.apply_gradients(clipped_value)

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