कभी-कभी एक TensorFlow कार्यक्रम के दौरान NaN से जुड़ी विनाशकारी घटनाएं हो सकती हैं, जो मॉडल प्रशिक्षण प्रक्रियाओं को पंगु बना देती हैं। ऐसी घटनाओं का मूल कारण अक्सर अस्पष्ट होता है, खासकर गैर-तुच्छ आकार और जटिलता के मॉडल के लिए। इस प्रकार के मॉडल बग्स को डीबग करना आसान बनाने के लिए, TensorBoard 2.3+ (TensorFlow 2.3+ के साथ) Debugger V2 नामक एक विशेष डैशबोर्ड प्रदान करता है। यहां हम प्रदर्शित करते हैं कि TensorFlow में लिखे गए एक तंत्रिका नेटवर्क में NaN को शामिल करने वाले वास्तविक बग के माध्यम से काम करके इस उपकरण का उपयोग कैसे करें।
इस ट्यूटोरियल में वर्णित तकनीकें अन्य प्रकार की डिबगिंग गतिविधियों पर लागू होती हैं जैसे कि जटिल कार्यक्रमों में रनटाइम टेंसर आकृतियों का निरीक्षण करना। यह ट्यूटोरियल उनके अपेक्षाकृत उच्च आवृत्ति के कारण NaN पर केंद्रित है।
बग का अवलोकन
TF2 प्रोग्राम का सोर्स कोड जिसे हम डिबग करेंगे , GitHub पर उपलब्ध है । उदाहरण कार्यक्रम को टेंसरफ़्लो पाइप पैकेज (संस्करण 2.3+) में भी पैक किया जाता है और इसे इसके द्वारा लागू किया जा सकता है:
python -m tensorflow.python.debug.examples.v2.debug_mnist_v2
यह TF2 प्रोग्राम एक बहु-परत धारणा (MLP) बनाता है और इसे MNIST छवियों को पहचानने के लिए प्रशिक्षित करता है। यह उदाहरण कस्टम लेयर कंस्ट्रक्शन, लॉस फंक्शन और ट्रेनिंग लूप को परिभाषित करने के लिए TF2 के निम्न-स्तरीय एपीआई का उद्देश्यपूर्ण रूप से उपयोग करता है, क्योंकि NaN बग्स की संभावना अधिक होती है जब हम इस अधिक लचीले लेकिन अधिक त्रुटि-प्रवण एपीआई का उपयोग करते हैं जब हम आसान का उपयोग करते हैं। उपयोग के लिए लेकिन थोड़े कम लचीले उच्च-स्तरीय API जैसे tf.keras ।
कार्यक्रम प्रत्येक प्रशिक्षण चरण के बाद एक परीक्षण सटीकता प्रिंट करता है। हम कंसोल में देख सकते हैं कि पहले चरण के बाद परीक्षण सटीकता निकट-मौका स्तर (~0.1) पर अटक जाती है। यह निश्चित रूप से नहीं है कि मॉडल प्रशिक्षण कैसे व्यवहार करता है: हम उम्मीद करते हैं कि सटीकता धीरे-धीरे 1.0 (100%) तक पहुंच जाएगी क्योंकि कदम बढ़ता है।
Accuracy at step 0: 0.216
Accuracy at step 1: 0.098
Accuracy at step 2: 0.098
Accuracy at step 3: 0.098
...
एक शिक्षित अनुमान यह है कि यह समस्या संख्यात्मक अस्थिरता, जैसे NaN या अनंत के कारण होती है। हालाँकि, हम कैसे पुष्टि करते हैं कि यह वास्तव में मामला है और हम संख्यात्मक अस्थिरता पैदा करने के लिए TensorFlow ऑपरेशन (op) को कैसे जिम्मेदार पाते हैं? इन सवालों के जवाब देने के लिए, आइए डीबगर V2 के साथ बग्गी प्रोग्राम को इंस्ट्रुमेंट करें।
डीबगर V2 के साथ टेन्सरफ्लो कोड को इंस्ट्रुमेंट करना
tf.debugging.experimental.enable_dump_debug_info() डीबगर V2 का एपीआई प्रवेश बिंदु है। यह कोड की एक पंक्ति के साथ एक TF2 प्रोग्राम को इंस्ट्रूमेंट करता है। उदाहरण के लिए, प्रोग्राम की शुरुआत के पास निम्न पंक्ति जोड़ने से डिबग जानकारी लॉग डायरेक्टरी (logdir) को /tmp/tfdbg2_logdir पर लिखी जाएगी। डिबग जानकारी में TensorFlow रनटाइम के विभिन्न पहलुओं को शामिल किया गया है। TF2 में, इसमें उत्सुक निष्पादन का पूरा इतिहास, @ tf.function द्वारा निष्पादित ग्राफ़ बिल्डिंग, ग्राफ़ का निष्पादन, निष्पादन घटनाओं द्वारा उत्पन्न टेंसर मान, साथ ही उन घटनाओं के कोड स्थान (पायथन स्टैक ट्रेस) शामिल हैं। . डिबग जानकारी की प्रचुरता उपयोगकर्ताओं को अस्पष्ट बग को सीमित करने में सक्षम बनाती है।
tf.debugging.experimental.enable_dump_debug_info(
"/tmp/tfdbg2_logdir",
tensor_debug_mode="FULL_HEALTH",
circular_buffer_size=-1)
tensor_debug_mode तर्क नियंत्रित करता है कि डीबगर V2 प्रत्येक उत्सुक या इन-ग्राफ़ टेंसर से कौन सी जानकारी निकालता है। "FULL_HEALTH" एक ऐसा मोड है जो प्रत्येक फ्लोटिंग-टाइप टेंसर के बारे में निम्नलिखित जानकारी को कैप्चर करता है (उदाहरण के लिए, आमतौर पर देखा जाने वाला फ्लोट32 और कम सामान्य bfloat16 dtype):
- डी टाइप
- पद
- तत्वों की कुल संख्या
- निम्नलिखित श्रेणियों में फ्लोटिंग-प्रकार के तत्वों का टूटना: नकारात्मक परिमित (
-), शून्य (0), सकारात्मक परिमित (+), नकारात्मक अनंत (-∞), सकारात्मक अनंत (+∞), औरNaN।
"FULL_HEALTH" मोड NaN और अनंत से जुड़े बग डीबग करने के लिए उपयुक्त है। अन्य समर्थित tensor_debug_mode s के लिए नीचे देखें।
circular_buffer_size तर्क नियंत्रित करता है कि लॉगडिर में कितने टेंसर ईवेंट सहेजे गए हैं। यह डिफ़ॉल्ट रूप से 1000 है, जिसके कारण इंस्ट्रूमेंटेड TF2 प्रोग्राम के अंत से पहले केवल अंतिम 1000 टेंसर डिस्क पर सहेजे जाते हैं। यह डिफ़ॉल्ट व्यवहार डीबग-डेटा पूर्णता का त्याग करके डीबगर ओवरहेड को कम करता है। यदि पूर्णता को प्राथमिकता दी जाती है, जैसा कि इस मामले में, हम तर्क को नकारात्मक मान पर सेट करके सर्कुलर बफर को अक्षम कर सकते हैं (उदाहरण के लिए, -1 यहां)।
debug_mnist_v2 उदाहरण इसे कमांड-लाइन फ़्लैग पास करके enable_dump_debug_info() को आमंत्रित करता है। इस डिबगिंग इंस्ट्रूमेंटेशन को सक्षम करके हमारे समस्याग्रस्त TF2 प्रोग्राम को फिर से चलाने के लिए, यह करें:
python -m tensorflow.python.debug.examples.v2.debug_mnist_v2 \
--dump_dir /tmp/tfdbg2_logdir --dump_tensor_debug_mode FULL_HEALTH
TensorBoard में डीबगर V2 GUI प्रारंभ करना
डिबगर इंस्ट्रूमेंटेशन के साथ प्रोग्राम चलाना /tmp/tfdbg2_logdir पर एक लॉगडिर बनाता है। हम TensorBoard शुरू कर सकते हैं और इसे logdir पर इंगित कर सकते हैं:
tensorboard --logdir /tmp/tfdbg2_logdir
वेब ब्राउज़र में, http://localhost:6006 पर TensorBoard के पेज पर नेविगेट करें। "डीबगर V2" प्लगइन डिफ़ॉल्ट रूप से निष्क्रिय होगा, इसलिए इसे ऊपर दाईं ओर "निष्क्रिय प्लगइन्स" मेनू से चुनें। एक बार चुने जाने के बाद, यह निम्न जैसा दिखना चाहिए:

NaNs के मूल कारण का पता लगाने के लिए डीबगर V2 GUI का उपयोग करना
TensorBoard में डीबगर V2 GUI छह खंडों में व्यवस्थित है:
- अलर्ट : इस टॉप-लेफ्ट सेक्शन में इंस्ट्रूमेंटेड TensorFlow प्रोग्राम के डीबग डेटा में डिबगर द्वारा पता लगाए गए "अलर्ट" इवेंट्स की एक सूची है। प्रत्येक अलर्ट एक निश्चित विसंगति को इंगित करता है जो ध्यान देने योग्य है। हमारे मामले में, यह खंड मुख्य गुलाबी-लाल रंग के साथ 499 NaN/∞ घटनाओं पर प्रकाश डालता है। यह हमारे संदेह की पुष्टि करता है कि मॉडल अपने आंतरिक टेंसर मूल्यों में NaN और/या अनंत की उपस्थिति के कारण सीखने में विफल रहता है। हम शीघ्र ही इन चेतावनियों की पड़ताल करेंगे।
- पायथन निष्पादन समयरेखा : यह शीर्ष-मध्य खंड का ऊपरी आधा भाग है। यह ऑप्स और ग्राफ़ के उत्सुक निष्पादन का पूरा इतिहास प्रस्तुत करता है। टाइमलाइन के प्रत्येक बॉक्स को ऑप या ग्राफ के नाम के प्रारंभिक अक्षर से चिह्नित किया जाता है (उदाहरण के लिए, "TensorSliceDataset" सेशन के लिए "T", "मॉडल"
tf.functionके लिए "m")। हम नेविगेशन बटन और टाइमलाइन के ऊपर स्क्रॉलबार का उपयोग करके इस टाइमलाइन को नेविगेट कर सकते हैं। - ग्राफ़ निष्पादन : GUI के ऊपरी-दाएँ कोने में स्थित, यह खंड हमारे डिबगिंग कार्य के लिए केंद्रीय होगा। इसमें ग्राफ़ के अंदर गणना किए गए सभी फ़्लोटिंग-डीटाइप टेंसर का इतिहास होता है (यानी,
@tf-functions द्वारा संकलित)। - ग्राफ संरचना (शीर्ष-मध्य खंड का निचला आधा), स्रोत कोड (नीचे-बाएं अनुभाग), और स्टैक ट्रेस (नीचे-दाएं अनुभाग) प्रारंभ में खाली हैं। जब हम जीयूआई के साथ बातचीत करेंगे तो उनकी सामग्री आबाद हो जाएगी। ये तीन खंड हमारे डिबगिंग कार्य में भी महत्वपूर्ण भूमिका निभाएंगे।
UI के संगठन के लिए खुद को उन्मुख करने के बाद, आइए NaN के प्रकट होने की तह तक जाने के लिए निम्नलिखित कदम उठाएं। सबसे पहले, अलर्ट सेक्शन में NaN/∞ अलर्ट पर क्लिक करें। यह स्वचालित रूप से ग्राफ़ निष्पादन अनुभाग में 600 ग्राफ़ टेंसर की सूची को स्क्रॉल करता है और #88 पर ध्यान केंद्रित करता है, जो Log (प्राकृतिक लॉगरिदम) सेशन द्वारा उत्पन्न Log:0 नामक एक टेंसर है। 2डी फ्लोट32 टेंसर के 1000 तत्वों में से एक प्रमुख गुलाबी-लाल रंग एक -∞ तत्व को हाइलाइट करता है। यह TF2 प्रोग्राम के रनटाइम इतिहास में पहला टेंसर है जिसमें कोई भी NaN या अनंत शामिल है: इससे पहले गणना किए गए टेंसर में NaN या ∞ नहीं होता है; बाद में गणना किए गए कई (वास्तव में, अधिकांश) टेंसर में NaN होते हैं। हम ग्राफ़ निष्पादन सूची को ऊपर और नीचे स्क्रॉल करके इसकी पुष्टि कर सकते हैं। यह अवलोकन एक मजबूत संकेत प्रदान करता है कि Log ऑप इस TF2 कार्यक्रम में संख्यात्मक अस्थिरता का स्रोत है।

यह Log ऑप एक -∞ क्यों थूकता है? उस प्रश्न का उत्तर देने के लिए ऑप को इनपुट की जांच करने की आवश्यकता है। टेंसर के नाम पर क्लिक करने से ( Log:0 ) ग्राफ़ स्ट्रक्चर सेक्शन में इसके टेंसरफ़्लो ग्राफ़ में Log ऑप के आसपास के क्षेत्र का एक सरल लेकिन सूचनात्मक विज़ुअलाइज़ेशन लाता है। सूचना प्रवाह की ऊपर से नीचे की दिशा पर ध्यान दें। बीच में ही ऑप को बोल्ड में दिखाया गया है। इसके ठीक ऊपर, हम देख सकते हैं कि प्लेसहोल्डर ऑप Log ऑप को एक और केवल इनपुट प्रदान करता है। ग्राफ निष्पादन सूची में इस जांच प्लेसहोल्डर द्वारा उत्पन्न probs कहां है? एक दृश्य सहायता के रूप में पीले रंग की पृष्ठभूमि के रंग का उपयोग करके, हम देख सकते हैं कि probs:0 टेंसर Log:0 टेंसर के ऊपर तीन पंक्तियाँ हैं, अर्थात पंक्ति 85 में।

probs:0 tensor in row 85 पर अधिक ध्यान से देखने पर पता चलता है कि इसका उपभोक्ता Log:0 क्यों एक -∞ उत्पन्न करता है: probs:0 के 1000 तत्वों में से, एक तत्व का मान 0 होता है। -∞ है 0 के प्राकृतिक लघुगणक की गणना का परिणाम! अगर हम किसी तरह यह सुनिश्चित कर सकते हैं कि Log ऑप केवल सकारात्मक इनपुट के संपर्क में आता है, तो हम NaN/∞ को होने से रोकने में सक्षम होंगे। इसे प्लेसहोल्डर probs टेंसर पर क्लिपिंग (उदाहरण के लिए, tf.clip_by_value() का उपयोग करके) लागू करके प्राप्त किया जा सकता है।
हम बग को हल करने के करीब पहुंच रहे हैं, लेकिन अभी तक काफी कुछ नहीं किया गया है। फिक्स को लागू करने के लिए, हमें यह जानना होगा कि पायथन सोर्स कोड में Log ऑप और इसके प्लेसहोल्डर इनपुट की उत्पत्ति कहाँ से हुई है। डीबगर V2 ग्राफ़ ऑप्स और निष्पादन ईवेंट को उनके स्रोत तक ट्रेस करने के लिए प्रथम श्रेणी का समर्थन प्रदान करता है। जब हमने ग्राफ़ निष्पादन में Log:0 टेंसर पर क्लिक किया, तो स्टैक ट्रेस अनुभाग Log ऑप के निर्माण के मूल स्टैक ट्रेस से भर गया था। स्टैक ट्रेस कुछ बड़ा है क्योंकि इसमें TensorFlow के आंतरिक कोड (जैसे, gen_math_ops.py और dumping_callback.py) से कई फ़्रेम शामिल हैं, जिन्हें हम अधिकांश डिबगिंग कार्यों के लिए सुरक्षित रूप से अनदेखा कर सकते हैं। डिबग_mnist_v2.py (यानी, पायथन फ़ाइल जिसे हम वास्तव में डीबग करने का प्रयास कर रहे हैं) की रुचि का फ्रेम लाइन 216 है। "लाइन 216" पर क्लिक करने से सोर्स कोड सेक्शन में कोड की संबंधित लाइन का एक दृश्य सामने आता है।

यह अंत में हमें उस स्रोत कोड पर लाता है जिसने अपने probs इनपुट से समस्याग्रस्त Log ऑप बनाया है। यह हमारा कस्टम श्रेणीबद्ध क्रॉस-एन्ट्रॉपी लॉस फंक्शन है @tf.function से सजाया गया है और इसलिए इसे TensorFlow ग्राफ में बदल दिया गया है। प्लेसहोल्डर ऑप probs लॉस फंक्शन के पहले इनपुट तर्क से मेल खाता है। Log सेशन tf.math.log() API कॉल के साथ बनाया गया है।
इस बग का वैल्यू-क्लिपिंग फिक्स कुछ इस तरह दिखेगा:
diff = -(labels *
tf.math.log(tf.clip_by_value(probs), 1e-6, 1.))
यह इस TF2 कार्यक्रम में संख्यात्मक अस्थिरता को हल करेगा और MLP को सफलतापूर्वक प्रशिक्षित करने का कारण बनेगा। संख्यात्मक अस्थिरता को ठीक करने का एक अन्य संभावित तरीका tf.keras.losses.CategoricalCrossentropy का उपयोग करना है।
यह एक TF2 मॉडल बग को देखने से लेकर एक कोड परिवर्तन के साथ आने तक की हमारी यात्रा को समाप्त करता है, जो डीबगर V2 टूल द्वारा सहायता प्राप्त बग को ठीक करता है, जो संख्यात्मक सारांश सहित इंस्ट्रूमेंटेड TF2 प्रोग्राम के उत्सुक और ग्राफ निष्पादन इतिहास में पूर्ण दृश्यता प्रदान करता है। ऑप्स, टेंसर और उनके मूल स्रोत कोड के बीच टेंसर मान और जुड़ाव।
डीबगर V2 . की हार्डवेयर संगतता
डीबगर V2 CPU और GPU सहित मुख्यधारा के प्रशिक्षण हार्डवेयर का समर्थन करता है। tf.distributed.MirroredStrategy के साथ मल्टी-जीपीयू प्रशिक्षण भी समर्थित है। TPU के लिए समर्थन अभी भी प्रारंभिक चरण में है और इसके लिए कॉल करने की आवश्यकता है
tf.config.set_soft_device_placement(True)
enable_dump_debug_info() को कॉल करने से पहले। टीपीयू पर इसकी अन्य सीमाएँ भी हो सकती हैं। यदि आपको डीबगर V2 का उपयोग करने में समस्या आती है, तो कृपया हमारे GitHub समस्या पृष्ठ पर बग की रिपोर्ट करें।
डीबगर V2 की API संगतता
डीबगर V2 को TensorFlow के सॉफ़्टवेयर स्टैक के अपेक्षाकृत निम्न स्तर पर कार्यान्वित किया जाता है, और इसलिए यह tf.keras , tf.data , और TensorFlow के निचले स्तरों के शीर्ष पर निर्मित अन्य API के साथ संगत है। डीबगर V2 भी TF1 के साथ पिछड़ा संगत है, हालांकि TF1 प्रोग्राम द्वारा जेनरेट किए गए डीबग लॉगडिर्स के लिए ईगर एक्ज़ीक्यूशन टाइमलाइन खाली होगी।
एपीआई उपयोग युक्तियाँ
इस डिबगिंग एपीआई के बारे में अक्सर पूछे जाने वाले प्रश्न यह है कि TensorFlow कोड में किसी को कॉल को enable_dump_debug_info() में सम्मिलित करना चाहिए। आम तौर पर, एपीआई को आपके टीएफ2 प्रोग्राम में जितनी जल्दी हो सके कॉल किया जाना चाहिए, अधिमानतः पायथन आयात लाइनों के बाद और ग्राफ निर्माण और निष्पादन शुरू होने से पहले। यह उन सभी ऑप्स और ग्राफ़ का पूर्ण कवरेज सुनिश्चित करेगा जो आपके मॉडल और उसके प्रशिक्षण को शक्ति प्रदान करते हैं।
वर्तमान में समर्थित tensor_debug_modes हैं: NO_TENSOR , CURT_HEALTH , CONCISE_HEALTH , FULL_HEALTH , और SHAPE । वे प्रत्येक टेंसर से निकाली गई जानकारी की मात्रा और प्रदर्शन ओवरहेड से डीबग किए गए प्रोग्राम में भिन्न होते हैं। कृपया enable_dump_debug_info() के दस्तावेज़ीकरण का args अनुभाग देखें।
प्रदर्शन ओवरहेड
डिबगिंग API इंस्ट्रूमेंटेड TensorFlow प्रोग्राम में परफॉर्मेंस ओवरहेड पेश करता है। ओवरहेड tensor_debug_mode , हार्डवेयर प्रकार और इंस्ट्रूमेंटेड TensorFlow प्रोग्राम की प्रकृति के अनुसार बदलता रहता है। एक संदर्भ बिंदु के रूप में, GPU पर, NO_TENSOR मोड एक ट्रांसफॉर्मर मॉडल के प्रशिक्षण के दौरान बैच आकार 64 के तहत 15% ओवरहेड जोड़ता है। अन्य tensor_debug_modes के लिए प्रतिशत ओवरहेड अधिक है: CURT_HEALTH , CONCISE_HEALTH , FULL_HEALTH और SHAPE के लिए लगभग 50% मोड। CPU पर, ओवरहेड थोड़ा कम होता है। टीपीयू पर, वर्तमान में ओवरहेड अधिक है।
अन्य TensorFlow डिबगिंग API से संबंध
ध्यान दें कि TensorFlow डिबगिंग के लिए अन्य टूल और API प्रदान करता है। आप एपीआई डॉक्स पेज पर tf.debugging.* नेमस्पेस के तहत ऐसे एपीआई ब्राउज़ कर सकते हैं। इन एपीआई में सबसे अधिक इस्तेमाल किया जाने वाला tf.print() है। डीबगर V2 का उपयोग कब करना चाहिए और इसके बजाय tf.print() का उपयोग कब किया जाना चाहिए? tf.print() उस स्थिति में सुविधाजनक है जहां
- हम ठीक-ठीक जानते हैं कि कौन से टेंसर प्रिंट करने हैं,
- हम जानते हैं कि वास्तव में स्रोत कोड में उन
tf.print()कथनों को सम्मिलित करने के लिए कहां है, - ऐसे टेंसरों की संख्या बहुत बड़ी नहीं है।
अन्य मामलों के लिए (उदाहरण के लिए, कई टेंसर मानों की जांच करना, TensorFlow के आंतरिक कोड द्वारा उत्पन्न टेंसर मानों की जांच करना, और संख्यात्मक अस्थिरता की उत्पत्ति की खोज करना जैसा कि हमने ऊपर दिखाया है), डीबगर V2 डिबगिंग का एक तेज़ तरीका प्रदान करता है। इसके अलावा, डीबगर V2 उत्सुक और ग्राफ टेंसरों का निरीक्षण करने के लिए एक एकीकृत दृष्टिकोण प्रदान करता है। यह अतिरिक्त रूप से ग्राफ संरचना और कोड स्थानों के बारे में जानकारी प्रदान करता है, जो tf.print() की क्षमता से परे हैं।
एक अन्य एपीआई जिसका उपयोग और NaN से जुड़े मुद्दों को डीबग करने के लिए किया जा सकता है, वह है tf.debugging.enable_check_numerics() । enable_dump_debug_info() के विपरीत, enable_dump_debug_info() enable_check_numerics() पर डिबग जानकारी को सेव नहीं करता है। इसके बजाय, यह केवल TensorFlow रनटाइम के दौरान ∞ और NaN की निगरानी करता है और जैसे ही कोई भी ऑप इस तरह के खराब संख्यात्मक मान उत्पन्न करता है, मूल कोड स्थान के साथ त्रुटियां होती हैं। इसमें enable_dump_debug_info() की तुलना में कम प्रदर्शन ओवरहेड है, लेकिन प्रोग्राम के निष्पादन इतिहास का पूरा पता नहीं लगाता है और डीबगर वी 2 जैसे ग्राफिकल यूजर इंटरफेस के साथ नहीं आता है।
कभी-कभी एक TensorFlow कार्यक्रम के दौरान NaN से जुड़ी विनाशकारी घटनाएं हो सकती हैं, जो मॉडल प्रशिक्षण प्रक्रियाओं को पंगु बना देती हैं। ऐसी घटनाओं का मूल कारण अक्सर अस्पष्ट होता है, खासकर गैर-तुच्छ आकार और जटिलता के मॉडल के लिए। इस प्रकार के मॉडल बग्स को डीबग करना आसान बनाने के लिए, TensorBoard 2.3+ (TensorFlow 2.3+ के साथ) Debugger V2 नामक एक विशेष डैशबोर्ड प्रदान करता है। यहां हम प्रदर्शित करते हैं कि TensorFlow में लिखे गए एक तंत्रिका नेटवर्क में NaN को शामिल करने वाले वास्तविक बग के माध्यम से काम करके इस उपकरण का उपयोग कैसे करें।
इस ट्यूटोरियल में वर्णित तकनीकें अन्य प्रकार की डिबगिंग गतिविधियों पर लागू होती हैं जैसे कि जटिल कार्यक्रमों में रनटाइम टेंसर आकृतियों का निरीक्षण करना। यह ट्यूटोरियल उनके अपेक्षाकृत उच्च आवृत्ति के कारण NaN पर केंद्रित है।
बग का अवलोकन
TF2 प्रोग्राम का सोर्स कोड जिसे हम डिबग करेंगे , GitHub पर उपलब्ध है । उदाहरण कार्यक्रम को टेंसरफ़्लो पाइप पैकेज (संस्करण 2.3+) में भी पैक किया जाता है और इसे इसके द्वारा लागू किया जा सकता है:
python -m tensorflow.python.debug.examples.v2.debug_mnist_v2
यह TF2 प्रोग्राम एक बहु-परत धारणा (MLP) बनाता है और इसे MNIST छवियों को पहचानने के लिए प्रशिक्षित करता है। यह उदाहरण कस्टम लेयर कंस्ट्रक्शन, लॉस फंक्शन और ट्रेनिंग लूप को परिभाषित करने के लिए TF2 के निम्न-स्तरीय एपीआई का उद्देश्यपूर्ण रूप से उपयोग करता है, क्योंकि NaN बग्स की संभावना अधिक होती है जब हम इस अधिक लचीले लेकिन अधिक त्रुटि-प्रवण एपीआई का उपयोग करते हैं जब हम आसान का उपयोग करते हैं। उपयोग के लिए लेकिन थोड़े कम लचीले उच्च-स्तरीय API जैसे tf.keras ।
कार्यक्रम प्रत्येक प्रशिक्षण चरण के बाद एक परीक्षण सटीकता प्रिंट करता है। हम कंसोल में देख सकते हैं कि पहले चरण के बाद परीक्षण सटीकता निकट-मौका स्तर (~0.1) पर अटक जाती है। यह निश्चित रूप से नहीं है कि मॉडल प्रशिक्षण कैसे व्यवहार करता है: हम उम्मीद करते हैं कि सटीकता धीरे-धीरे 1.0 (100%) तक पहुंच जाएगी क्योंकि कदम बढ़ता है।
Accuracy at step 0: 0.216
Accuracy at step 1: 0.098
Accuracy at step 2: 0.098
Accuracy at step 3: 0.098
...
एक शिक्षित अनुमान यह है कि यह समस्या संख्यात्मक अस्थिरता, जैसे NaN या अनंत के कारण होती है। हालाँकि, हम कैसे पुष्टि करते हैं कि यह वास्तव में मामला है और हम संख्यात्मक अस्थिरता पैदा करने के लिए TensorFlow ऑपरेशन (op) को कैसे जिम्मेदार पाते हैं? इन सवालों के जवाब देने के लिए, आइए डीबगर V2 के साथ बग्गी प्रोग्राम को इंस्ट्रुमेंट करें।
डीबगर V2 के साथ टेन्सरफ्लो कोड को इंस्ट्रुमेंट करना
tf.debugging.experimental.enable_dump_debug_info() डीबगर V2 का एपीआई प्रवेश बिंदु है। यह कोड की एक पंक्ति के साथ एक TF2 प्रोग्राम को इंस्ट्रूमेंट करता है। उदाहरण के लिए, प्रोग्राम की शुरुआत के पास निम्न पंक्ति जोड़ने से डिबग जानकारी लॉग डायरेक्टरी (logdir) को /tmp/tfdbg2_logdir पर लिखी जाएगी। डिबग जानकारी में TensorFlow रनटाइम के विभिन्न पहलुओं को शामिल किया गया है। TF2 में, इसमें उत्सुक निष्पादन का पूरा इतिहास, @ tf.function द्वारा निष्पादित ग्राफ़ बिल्डिंग, ग्राफ़ का निष्पादन, निष्पादन घटनाओं द्वारा उत्पन्न टेंसर मान, साथ ही उन घटनाओं के कोड स्थान (पायथन स्टैक ट्रेस) शामिल हैं। . डिबग जानकारी की प्रचुरता उपयोगकर्ताओं को अस्पष्ट बग को सीमित करने में सक्षम बनाती है।
tf.debugging.experimental.enable_dump_debug_info(
"/tmp/tfdbg2_logdir",
tensor_debug_mode="FULL_HEALTH",
circular_buffer_size=-1)
tensor_debug_mode तर्क नियंत्रित करता है कि डीबगर V2 प्रत्येक उत्सुक या इन-ग्राफ़ टेंसर से कौन सी जानकारी निकालता है। "FULL_HEALTH" एक ऐसा मोड है जो प्रत्येक फ्लोटिंग-टाइप टेंसर के बारे में निम्नलिखित जानकारी को कैप्चर करता है (उदाहरण के लिए, आमतौर पर देखा जाने वाला फ्लोट32 और कम सामान्य bfloat16 dtype):
- डी टाइप
- पद
- तत्वों की कुल संख्या
- निम्नलिखित श्रेणियों में फ्लोटिंग-प्रकार के तत्वों का टूटना: नकारात्मक परिमित (
-), शून्य (0), सकारात्मक परिमित (+), नकारात्मक अनंत (-∞), सकारात्मक अनंत (+∞), औरNaN।
"FULL_HEALTH" मोड NaN और अनंत से जुड़े बग डीबग करने के लिए उपयुक्त है। अन्य समर्थित tensor_debug_mode s के लिए नीचे देखें।
circular_buffer_size तर्क नियंत्रित करता है कि लॉगडिर में कितने टेंसर ईवेंट सहेजे गए हैं। यह डिफ़ॉल्ट रूप से 1000 है, जिसके कारण इंस्ट्रूमेंटेड TF2 प्रोग्राम के अंत से पहले केवल अंतिम 1000 टेंसर डिस्क पर सहेजे जाते हैं। यह डिफ़ॉल्ट व्यवहार डीबग-डेटा पूर्णता का त्याग करके डीबगर ओवरहेड को कम करता है। यदि पूर्णता को प्राथमिकता दी जाती है, जैसा कि इस मामले में, हम तर्क को नकारात्मक मान पर सेट करके सर्कुलर बफर को अक्षम कर सकते हैं (उदाहरण के लिए, -1 यहां)।
debug_mnist_v2 उदाहरण इसे कमांड-लाइन फ़्लैग पास करके enable_dump_debug_info() को आमंत्रित करता है। इस डिबगिंग इंस्ट्रूमेंटेशन को सक्षम करके हमारे समस्याग्रस्त TF2 प्रोग्राम को फिर से चलाने के लिए, यह करें:
python -m tensorflow.python.debug.examples.v2.debug_mnist_v2 \
--dump_dir /tmp/tfdbg2_logdir --dump_tensor_debug_mode FULL_HEALTH
TensorBoard में डीबगर V2 GUI प्रारंभ करना
डिबगर इंस्ट्रूमेंटेशन के साथ प्रोग्राम चलाना /tmp/tfdbg2_logdir पर एक लॉगडिर बनाता है। हम TensorBoard शुरू कर सकते हैं और इसे logdir पर इंगित कर सकते हैं:
tensorboard --logdir /tmp/tfdbg2_logdir
वेब ब्राउज़र में, http://localhost:6006 पर TensorBoard के पेज पर नेविगेट करें। "डीबगर V2" प्लगइन डिफ़ॉल्ट रूप से निष्क्रिय होगा, इसलिए इसे ऊपर दाईं ओर "निष्क्रिय प्लगइन्स" मेनू से चुनें। एक बार चुने जाने के बाद, यह निम्न जैसा दिखना चाहिए:

NaNs के मूल कारण का पता लगाने के लिए डीबगर V2 GUI का उपयोग करना
TensorBoard में डीबगर V2 GUI छह खंडों में व्यवस्थित है:
- अलर्ट : इस टॉप-लेफ्ट सेक्शन में इंस्ट्रूमेंटेड TensorFlow प्रोग्राम के डीबग डेटा में डिबगर द्वारा पता लगाए गए "अलर्ट" इवेंट्स की एक सूची है। प्रत्येक अलर्ट एक निश्चित विसंगति को इंगित करता है जो ध्यान देने योग्य है। हमारे मामले में, यह खंड मुख्य गुलाबी-लाल रंग के साथ 499 NaN/∞ घटनाओं पर प्रकाश डालता है। यह हमारे संदेह की पुष्टि करता है कि मॉडल अपने आंतरिक टेंसर मूल्यों में NaN और/या अनंत की उपस्थिति के कारण सीखने में विफल रहता है। हम शीघ्र ही इन चेतावनियों की खोज करेंगे।
- पायथन निष्पादन समयरेखा : यह शीर्ष-मध्य खंड का ऊपरी आधा भाग है। यह ऑप्स और ग्राफ़ के उत्सुक निष्पादन का पूरा इतिहास प्रस्तुत करता है। टाइमलाइन के प्रत्येक बॉक्स को ऑप या ग्राफ के नाम के प्रारंभिक अक्षर से चिह्नित किया जाता है (उदाहरण के लिए, "TensorSliceDataset" सेशन के लिए "T", "मॉडल"
tf.functionके लिए "m")। हम नेविगेशन बटन और टाइमलाइन के ऊपर स्क्रॉलबार का उपयोग करके इस टाइमलाइन को नेविगेट कर सकते हैं। - ग्राफ़ निष्पादन : GUI के ऊपरी-दाएँ कोने में स्थित, यह खंड हमारे डिबगिंग कार्य के लिए केंद्रीय होगा। इसमें ग्राफ़ के अंदर गणना किए गए सभी फ़्लोटिंग-डीटाइप टेंसर का इतिहास होता है (यानी,
@tf-functions द्वारा संकलित)। - ग्राफ संरचना (शीर्ष-मध्य खंड का निचला आधा), स्रोत कोड (नीचे-बाएं अनुभाग), और स्टैक ट्रेस (नीचे-दाएं अनुभाग) प्रारंभ में खाली हैं। जब हम जीयूआई के साथ बातचीत करेंगे तो उनकी सामग्री आबाद हो जाएगी। ये तीन खंड हमारे डिबगिंग कार्य में भी महत्वपूर्ण भूमिका निभाएंगे।
UI के संगठन के लिए खुद को उन्मुख करने के बाद, आइए NaN के प्रकट होने की तह तक जाने के लिए निम्नलिखित कदम उठाएं। सबसे पहले, अलर्ट सेक्शन में NaN/∞ अलर्ट पर क्लिक करें। यह स्वचालित रूप से ग्राफ़ निष्पादन अनुभाग में 600 ग्राफ़ टेंसर की सूची को स्क्रॉल करता है और #88 पर ध्यान केंद्रित करता है, जो Log (प्राकृतिक लॉगरिदम) सेशन द्वारा उत्पन्न Log:0 नामक एक टेंसर है। 2डी फ्लोट32 टेंसर के 1000 तत्वों में से एक प्रमुख गुलाबी-लाल रंग एक -∞ तत्व को हाइलाइट करता है। यह TF2 प्रोग्राम के रनटाइम इतिहास में पहला टेंसर है जिसमें कोई भी NaN या अनंत शामिल है: इससे पहले गणना किए गए टेंसर में NaN या ∞ नहीं होता है; बाद में गणना किए गए कई (वास्तव में, अधिकांश) टेंसर में NaN होते हैं। हम ग्राफ़ निष्पादन सूची को ऊपर और नीचे स्क्रॉल करके इसकी पुष्टि कर सकते हैं। यह अवलोकन एक मजबूत संकेत प्रदान करता है कि Log ऑप इस TF2 कार्यक्रम में संख्यात्मक अस्थिरता का स्रोत है।

यह Log ऑप एक -∞ क्यों थूकता है? उस प्रश्न का उत्तर देने के लिए ऑप को इनपुट की जांच करने की आवश्यकता है। टेंसर के नाम पर क्लिक करने से ( Log:0 ) ग्राफ़ स्ट्रक्चर सेक्शन में इसके टेंसरफ़्लो ग्राफ़ में Log ऑप के आसपास के क्षेत्र का एक सरल लेकिन सूचनात्मक विज़ुअलाइज़ेशन लाता है। सूचना प्रवाह की ऊपर से नीचे की दिशा पर ध्यान दें। बीच में ही ऑप को बोल्ड में दिखाया गया है। इसके ठीक ऊपर, हम देख सकते हैं कि प्लेसहोल्डर ऑप Log ऑप को एक और केवल इनपुट प्रदान करता है। ग्राफ निष्पादन सूची में इस जांच प्लेसहोल्डर द्वारा उत्पन्न probs कहां है? एक दृश्य सहायता के रूप में पीले रंग की पृष्ठभूमि के रंग का उपयोग करके, हम देख सकते हैं कि probs:0 टेंसर Log:0 टेंसर के ऊपर तीन पंक्तियाँ हैं, अर्थात पंक्ति 85 में।

probs:0 tensor in row 85 पर अधिक ध्यान से देखने पर पता चलता है कि इसका उपभोक्ता Log:0 क्यों एक -∞ उत्पन्न करता है: probs:0 के 1000 तत्वों में से, एक तत्व का मान 0 होता है। -∞ है 0 के प्राकृतिक लघुगणक की गणना का परिणाम! अगर हम किसी तरह यह सुनिश्चित कर सकते हैं कि Log ऑप केवल सकारात्मक इनपुट के संपर्क में आता है, तो हम NaN/∞ को होने से रोकने में सक्षम होंगे। इसे प्लेसहोल्डर probs टेंसर पर क्लिपिंग (उदाहरण के लिए, tf.clip_by_value() का उपयोग करके) लागू करके प्राप्त किया जा सकता है।
हम बग को हल करने के करीब पहुंच रहे हैं, लेकिन अभी तक काफी कुछ नहीं किया गया है। फिक्स को लागू करने के लिए, हमें यह जानना होगा कि पायथन सोर्स कोड में Log ऑप और इसके प्लेसहोल्डर इनपुट की उत्पत्ति कहाँ से हुई है। डीबगर V2 ग्राफ़ ऑप्स और निष्पादन ईवेंट को उनके स्रोत तक ट्रेस करने के लिए प्रथम श्रेणी का समर्थन प्रदान करता है। जब हमने ग्राफ़ निष्पादन में Log:0 टेंसर पर क्लिक किया, तो स्टैक ट्रेस अनुभाग Log ऑप के निर्माण के मूल स्टैक ट्रेस से भर गया था। स्टैक ट्रेस कुछ बड़ा है क्योंकि इसमें TensorFlow के आंतरिक कोड (जैसे, gen_math_ops.py और dumping_callback.py) से कई फ़्रेम शामिल हैं, जिन्हें हम अधिकांश डिबगिंग कार्यों के लिए सुरक्षित रूप से अनदेखा कर सकते हैं। डिबग_mnist_v2.py (यानी, पायथन फ़ाइल जिसे हम वास्तव में डीबग करने का प्रयास कर रहे हैं) की रुचि का फ्रेम लाइन 216 है। "लाइन 216" पर क्लिक करने से सोर्स कोड सेक्शन में कोड की संबंधित लाइन का एक दृश्य सामने आता है।

यह अंत में हमें उस स्रोत कोड पर लाता है जिसने अपने probs इनपुट से समस्याग्रस्त Log ऑप बनाया है। यह हमारा कस्टम श्रेणीबद्ध क्रॉस-एन्ट्रॉपी लॉस फंक्शन है @tf.function से सजाया गया है और इसलिए इसे TensorFlow ग्राफ में बदल दिया गया है। प्लेसहोल्डर ऑप probs लॉस फंक्शन के पहले इनपुट तर्क से मेल खाता है। Log सेशन tf.math.log() API कॉल के साथ बनाया गया है।
इस बग का वैल्यू-क्लिपिंग फिक्स कुछ इस तरह दिखेगा:
diff = -(labels *
tf.math.log(tf.clip_by_value(probs), 1e-6, 1.))
यह इस TF2 कार्यक्रम में संख्यात्मक अस्थिरता को हल करेगा और MLP को सफलतापूर्वक प्रशिक्षित करने का कारण बनेगा। संख्यात्मक अस्थिरता को ठीक करने का एक अन्य संभावित तरीका tf.keras.losses.CategoricalCrossentropy का उपयोग करना है।
यह एक TF2 मॉडल बग को देखने से लेकर एक कोड परिवर्तन के साथ आने तक की हमारी यात्रा को समाप्त करता है, जो डीबगर V2 टूल द्वारा सहायता प्राप्त बग को ठीक करता है, जो संख्यात्मक सारांश सहित इंस्ट्रूमेंटेड TF2 प्रोग्राम के उत्सुक और ग्राफ निष्पादन इतिहास में पूर्ण दृश्यता प्रदान करता है। ऑप्स, टेंसर और उनके मूल स्रोत कोड के बीच टेंसर मान और जुड़ाव।
डीबगर V2 . की हार्डवेयर संगतता
डीबगर V2 CPU और GPU सहित मुख्यधारा के प्रशिक्षण हार्डवेयर का समर्थन करता है। tf.distributed.MirroredStrategy के साथ मल्टी-जीपीयू प्रशिक्षण भी समर्थित है। TPU के लिए समर्थन अभी भी प्रारंभिक चरण में है और इसके लिए कॉल करने की आवश्यकता है
tf.config.set_soft_device_placement(True)
enable_dump_debug_info() को कॉल करने से पहले। टीपीयू पर इसकी अन्य सीमाएँ भी हो सकती हैं। यदि आपको डीबगर V2 का उपयोग करने में समस्या आती है, तो कृपया हमारे GitHub समस्या पृष्ठ पर बग की रिपोर्ट करें।
डीबगर V2 की API संगतता
डीबगर V2 को TensorFlow के सॉफ़्टवेयर स्टैक के अपेक्षाकृत निम्न स्तर पर कार्यान्वित किया जाता है, और इसलिए यह tf.keras , tf.data , और TensorFlow के निचले स्तरों के शीर्ष पर निर्मित अन्य API के साथ संगत है। डीबगर V2 भी TF1 के साथ पिछड़ा संगत है, हालांकि TF1 प्रोग्राम द्वारा जेनरेट किए गए डीबग लॉगडिर्स के लिए ईगर एक्ज़ीक्यूशन टाइमलाइन खाली होगी।
एपीआई उपयोग युक्तियाँ
इस डिबगिंग एपीआई के बारे में अक्सर पूछे जाने वाले प्रश्न यह है कि TensorFlow कोड में किसी को कॉल को enable_dump_debug_info() में सम्मिलित करना चाहिए। आम तौर पर, एपीआई को आपके टीएफ2 प्रोग्राम में जितनी जल्दी हो सके कॉल किया जाना चाहिए, अधिमानतः पायथन आयात लाइनों के बाद और ग्राफ निर्माण और निष्पादन शुरू होने से पहले। यह उन सभी ऑप्स और ग्राफ़ का पूर्ण कवरेज सुनिश्चित करेगा जो आपके मॉडल और उसके प्रशिक्षण को शक्ति प्रदान करते हैं।
वर्तमान में समर्थित tensor_debug_modes हैं: NO_TENSOR , CURT_HEALTH , CONCISE_HEALTH , FULL_HEALTH , और SHAPE । वे प्रत्येक टेंसर से निकाली गई जानकारी की मात्रा और प्रदर्शन ओवरहेड से डीबग किए गए प्रोग्राम में भिन्न होते हैं। कृपया enable_dump_debug_info() के दस्तावेज़ीकरण का args अनुभाग देखें।
प्रदर्शन ओवरहेड
डिबगिंग API इंस्ट्रूमेंटेड TensorFlow प्रोग्राम में परफॉर्मेंस ओवरहेड पेश करता है। ओवरहेड tensor_debug_mode , हार्डवेयर प्रकार और इंस्ट्रूमेंटेड TensorFlow प्रोग्राम की प्रकृति के अनुसार बदलता रहता है। एक संदर्भ बिंदु के रूप में, GPU पर, NO_TENSOR मोड एक ट्रांसफॉर्मर मॉडल के प्रशिक्षण के दौरान बैच आकार 64 के तहत 15% ओवरहेड जोड़ता है। अन्य tensor_debug_modes के लिए प्रतिशत ओवरहेड अधिक है: CURT_HEALTH , CONCISE_HEALTH , FULL_HEALTH और SHAPE के लिए लगभग 50% मोड। CPU पर, ओवरहेड थोड़ा कम होता है। टीपीयू पर, वर्तमान में ओवरहेड अधिक है।
अन्य TensorFlow डिबगिंग API से संबंध
ध्यान दें कि TensorFlow डिबगिंग के लिए अन्य टूल और API प्रदान करता है। आप एपीआई डॉक्स पेज पर tf.debugging.* नेमस्पेस के तहत ऐसे एपीआई ब्राउज़ कर सकते हैं। इन एपीआई में सबसे अधिक इस्तेमाल किया जाने वाला tf.print() है। डीबगर V2 का उपयोग कब करना चाहिए और इसके बजाय tf.print() का उपयोग कब किया जाना चाहिए? tf.print() उस स्थिति में सुविधाजनक है जहां
- हमें ठीक-ठीक पता है कि कौन से टेंसर प्रिंट करने हैं,
- हम जानते हैं कि वास्तव में स्रोत कोड में उन
tf.print()कथनों को सम्मिलित करने के लिए कहां है, - ऐसे टेंसरों की संख्या बहुत बड़ी नहीं है।
अन्य मामलों के लिए (उदाहरण के लिए, कई टेंसर मानों की जांच करना, TensorFlow के आंतरिक कोड द्वारा उत्पन्न टेंसर मानों की जांच करना, और संख्यात्मक अस्थिरता की उत्पत्ति की खोज करना जैसा कि हमने ऊपर दिखाया है), डीबगर V2 डिबगिंग का एक तेज़ तरीका प्रदान करता है। इसके अलावा, डीबगर V2 उत्सुक और ग्राफ टेंसरों का निरीक्षण करने के लिए एक एकीकृत दृष्टिकोण प्रदान करता है। यह अतिरिक्त रूप से ग्राफ संरचना और कोड स्थानों के बारे में जानकारी प्रदान करता है, जो tf.print() की क्षमता से परे हैं।
एक अन्य एपीआई जिसका उपयोग और NaN से जुड़े मुद्दों को डीबग करने के लिए किया जा सकता है, वह है tf.debugging.enable_check_numerics() । enable_dump_debug_info() के विपरीत, enable_dump_debug_info() enable_check_numerics() पर डिबग जानकारी को सेव नहीं करता है। इसके बजाय, यह केवल TensorFlow रनटाइम के दौरान ∞ और NaN की निगरानी करता है और जैसे ही कोई भी ऑप इस तरह के खराब संख्यात्मक मान उत्पन्न करता है, मूल कोड स्थान के साथ त्रुटियां होती हैं। इसमें enable_dump_debug_info() की तुलना में कम प्रदर्शन ओवरहेड है, लेकिन प्रोग्राम के निष्पादन इतिहास का पूरा पता नहीं लगाता है और डीबगर वी 2 जैसे ग्राफिकल यूजर इंटरफेस के साथ नहीं आता है।