TPU पर Keras और मॉडर्न कन्वर्ज़न

1. खास जानकारी

इस लैब में, आपको Keras और TensorFlow 2 की मदद से, कॉन्वलूशनल न्यूरल नेटवर्क को स्क्रैच से बनाने, ट्रेन करने, और ट्यून करने का तरीका बताया जाएगा. अब टीपीयू की मदद से, यह काम कुछ ही मिनटों में किया जा सकता है. आपको ट्रांसफ़र लर्निंग के बहुत आसान तरीकों से लेकर, Squeezenet जैसे आधुनिक कनवोल्यूशनल आर्किटेक्चर के बारे में भी जानने को मिलेगा. इस लैब में, न्यूरल नेटवर्क के बारे में सिद्धांत के हिसाब से जानकारी दी गई है. साथ ही, यह डीप लर्निंग के बारे में जानने वाले डेवलपर के लिए एक अच्छा शुरुआती पॉइंट है.

डीप लर्निंग से जुड़े पेपर पढ़ना मुश्किल और उलझाने वाला हो सकता है. आइए, मॉडर्न कनवोल्यूशनल न्यूरल नेटवर्क आर्किटेक्चर के बारे में विस्तार से जानते हैं.

ca8cc21f6838eccc.png

आपको क्या सीखने को मिलेगा

  • कस्टम मॉडल को तेज़ी से बनाने के लिए, Keras और Tensor Processing Units (TPUs) का इस्तेमाल करें.
  • ट्रेनिंग डेटा को असरदार तरीके से लोड करने के लिए, tf.data.Dataset API और TFRecord फ़ॉर्मैट का इस्तेमाल करना.
  • धोखाधड़ी 😈 करने के लिए, अपने मॉडल बनाने के बजाय ट्रांसफ़र लर्निंग का इस्तेमाल करना.
  • Keras के सीक्वेंशियल और फ़ंक्शनल मॉडल स्टाइल का इस्तेमाल करने के लिए.
  • सॉफ्टमैक्स लेयर और क्रॉस-एंट्रॉपी लॉस के साथ अपना Keras क्लासिफ़ायर बनाने के लिए.
  • कन्वलूशनल लेयर के सही विकल्प के साथ अपने मॉडल को बेहतर बनाने के लिए.
  • मॉड्यूल, ग्लोबल एवरेज पूलिंग वगैरह जैसे आधुनिक कनवनेट आर्किटेक्चर के आइडिया एक्सप्लोर करने के लिए
  • Squeezenet आर्किटेक्चर का इस्तेमाल करके, एक आसान मॉडर्न कॉन्वनेट बनाने के लिए.

सुझाव, राय या शिकायत

अगर आपको इस कोड लैब में कोई गड़बड़ी दिखती है, तो कृपया हमें बताएं. GitHub की समस्याओं [ सुझाव/राय देने या शिकायत करने का लिंक] के ज़रिए सुझाव/राय दी जा सकती है या शिकायत की जा सकती है.

2. Google Colaboratory को तुरंत इस्तेमाल करना शुरू करना

इस लैब में Google Colaboratory का इस्तेमाल किया जाता है. इसके लिए, आपको कोई सेटअप करने की ज़रूरत नहीं है. इसे Chromebook से चलाया जा सकता है. कृपया यहां दी गई फ़ाइल खोलें और Colab notebook के बारे में जानने के लिए, सेल को एक्ज़ीक्यूट करें.

c3df49e90e5a654f.png Welcome to Colab.ipynb

कोई टीपीयू बैकएंड चुनना

8832c6208c99687d.png

Colab मेन्यू में, रनटाइम > रनटाइम का टाइप बदलें को चुनें. इसके बाद, टीपीयू को चुनें. इस कोड लैब में, आपको एक पावरफ़ुल टीपीयू (टेंसर प्रोसेसिंग यूनिट) का इस्तेमाल करना होगा. यह हार्डवेयर की मदद से ट्रेनिंग को तेज़ करने के लिए काम करता है. पहली बार कोड चलाने पर, रनटाइम से कनेक्शन अपने-आप हो जाएगा. इसके अलावा, सबसे ऊपर दाएं कोने में मौजूद "कनेक्ट करें" बटन का इस्तेमाल करके भी कनेक्शन किया जा सकता है.

नोटबुक को एक्ज़ीक्यूट करना

76d05caa8b4db6da.png

एक बार में एक सेल को चलाने के लिए, किसी सेल पर क्लिक करें और Shift-ENTER का इस्तेमाल करें. रनटाइम > सभी सेल चलाएं का इस्तेमाल करके, पूरी नोटबुक को भी चलाया जा सकता है

विषय सूची

429f106990037ec4.png

सभी नोटबुक में विषय सूची होती है. बाईं ओर मौजूद काले ऐरो का इस्तेमाल करके, इसे खोला जा सकता है.

छिपे हुए सेल

edc3dba45d26f12a.png

कुछ सेल में सिर्फ़ उनका टाइटल दिखेगा. यह Colab की नोटबुक से जुड़ी सुविधा है. इनके अंदर मौजूद कोड देखने के लिए, इन पर दो बार क्लिक किया जा सकता है. हालांकि, यह आम तौर पर ज़्यादा दिलचस्प नहीं होता. आम तौर पर, ये सहायता या विज़ुअलाइज़ेशन फ़ंक्शन होते हैं. हालांकि, फ़ंक्शन को तय करने के लिए, आपको अब भी इन सेल को चलाना होगा.

पुष्टि करना

cdd4b41413100543.png

Colab, आपके निजी Google Cloud Storage बकेट को ऐक्सेस कर सकता है. इसके लिए, आपको किसी ऐसे खाते से पुष्टि करनी होगी जिसे अनुमति मिली हुई है. ऊपर दिया गया कोड स्निपेट, पुष्टि करने की प्रोसेस को ट्रिगर करेगा.

3. [INFO] टेंसर प्रोसेसिंग यूनिट (टीपीयू) क्या होती हैं?

कम शब्दों में

f88cf6facfc70166.png

Keras में TPU पर मॉडल को ट्रेन करने का कोड. अगर TPU उपलब्ध नहीं है, तो GPU या CPU पर वापस आएं:

try: # detect TPUs
    tpu = tf.distribute.cluster_resolver.TPUClusterResolver.connect()
    strategy = tf.distribute.TPUStrategy(tpu)
except ValueError: # detect GPUs
    strategy = tf.distribute.MirroredStrategy() # for CPU/GPU or multi-GPU machines

# use TPUStrategy scope to define model
with strategy.scope():
  model = tf.keras.Sequential( ... )
  model.compile( ... )

# train model normally on a tf.data.Dataset
model.fit(training_dataset, epochs=EPOCHS, steps_per_epoch=...)

आज हम टीपीयू का इस्तेमाल करके, फूलों को पहचानने वाला एक क्लासिफ़ायर बनाएंगे और उसे ऑप्टिमाइज़ करेंगे. इससे ट्रेनिंग बहुत तेज़ी से होगी (ट्रेनिंग रन में कुछ मिनट लगेंगे).

688858c21e3beff2.png

TPU का इस्तेमाल क्यों करें ?

मॉडर्न जीपीयू को प्रोग्राम किए जा सकने वाले "कोर" के हिसाब से व्यवस्थित किया जाता है. यह एक बहुत ही फ़्लेक्सिबल आर्किटेक्चर है, जिसकी मदद से कई तरह के टास्क मैनेज किए जा सकते हैं. जैसे, 3D रेंडरिंग, डीप लर्निंग, फ़िज़िकल सिमुलेशन वगैरह. दूसरी ओर, टीपीयू में क्लासिक वेक्टर प्रोसेसर को मैट्रिक्स मल्टिप्लाई यूनिट के साथ जोड़ा जाता है. साथ ही, ये ऐसे किसी भी टास्क को बेहतर तरीके से पूरा कर सकते हैं जिनमें मैट्रिक्स मल्टिप्लिकेशन का इस्तेमाल ज़्यादा होता है. जैसे, न्यूरल नेटवर्क.

8eb3e718b8e2ed08.png

इलस्ट्रेशन: मैट्रिक्स मल्टिप्लिकेशन के तौर पर डेंस न्यूरल नेटवर्क लेयर. इसमें एक साथ आठ इमेज के बैच को न्यूरल नेटवर्क के ज़रिए प्रोसेस किया जाता है. कृपया एक लाइन x कॉलम का गुणा करके देखें, ताकि यह पुष्टि की जा सके कि यह वाकई में किसी इमेज के सभी पिक्सल की वैल्यू का वेटेड सम कर रहा है. कनवोल्यूशनल लेयर को मैट्रिक्स मल्टिप्लिकेशन के तौर पर भी दिखाया जा सकता है. हालांकि, यह थोड़ा मुश्किल है ( यहां सेक्शन 1 में जानकारी दी गई है).

हार्डवेयर

MXU और VPU

TPU v2 कोर, मैट्रिक्स मल्टिप्लाई यूनिट (एमएक्सयू) से बनी होती है. यह मैट्रिक्स मल्टिप्लिकेशन को चलाती है. साथ ही, इसमें एक वेक्टर प्रोसेसिंग यूनिट (वीपीयू) होती है, जो ऐक्टिवेशन, सॉफ़्टमैक्स वगैरह जैसे अन्य सभी टास्क के लिए होती है. वीपीयू, फ़्लोट32 और int32 कंप्यूटेशन को हैंडल करता है. दूसरी ओर, MXU 16-32 बिट फ़्लोटिंग पॉइंट फ़ॉर्मैट में काम करता है.

7d68944718f76b18.png

फ़्लोटिंग पॉइंट और bfloat16 की मिली-जुली सटीक जानकारी

MXU, bfloat16 इनपुट और float32 आउटपुट का इस्तेमाल करके मैट्रिक्स के गुणनफल की गणना करता है. इंटरमीडिएट एक्युमुलेशन, फ़्लोट32 प्रेसिज़न में किए जाते हैं.

19c5fc432840c714.png

आम तौर पर, न्यूरल नेटवर्क ट्रेनिंग पर फ़्लोटिंग पॉइंट की कम सटीक वैल्यू से होने वाले नॉइज़ का असर नहीं पड़ता. कुछ मामलों में, नॉइज़ से ऑप्टिमाइज़र को कन्वर्ज होने में मदद मिलती है. आम तौर पर, कंप्यूटेशन को तेज़ करने के लिए 16-बिट फ़्लोटिंग पॉइंट प्रेसिज़न का इस्तेमाल किया जाता है. हालांकि, float16 और float32 फ़ॉर्मैट की रेंज बहुत अलग होती हैं. आम तौर पर, float32 से float16 में बदलने पर, ओवरफ़्लो और अंडरफ़्लो की समस्याएं होती हैं. इसके समाधान मौजूद हैं, लेकिन float16 को काम करने के लिए आम तौर पर अतिरिक्त काम की ज़रूरत होती है.

इसलिए, Google ने टीपीयू में bfloat16 फ़ॉर्मैट लॉन्च किया है. bfloat16, float32 का छोटा किया गया वर्शन है. इसमें एक्स्पोनेंट बिट और रेंज, float32 के जैसी ही होती है. इसके अलावा, टीपीयू, bfloat16 इनपुट के साथ मिक्स प्रिसिशन में मैट्रिक्स मल्टिप्लिकेशन की गणना करते हैं, लेकिन float32 आउटपुट देते हैं. इसका मतलब है कि आम तौर पर, कम प्रिसिशन से परफ़ॉर्मेंस में होने वाले फ़ायदों का इस्तेमाल करने के लिए, कोड में कोई बदलाव करने की ज़रूरत नहीं होती.

सिस्टोलिक ऐरे

MXU, हार्डवेयर में मैट्रिक्स मल्टिप्लिकेशन लागू करता है. इसके लिए, "सिस्टोलिक ऐरे" आर्किटेक्चर का इस्तेमाल किया जाता है. इसमें डेटा एलिमेंट, हार्डवेयर कंप्यूटेशन यूनिट की ऐरे से होकर गुज़रते हैं. (चिकित्सा विज्ञान में, "सिस्टोलिक" का मतलब दिल के सिकुड़ने और खून के प्रवाह से है. यहां इसका मतलब डेटा के प्रवाह से है.)

मैट्रिक्स को गुणा करने का बुनियादी तरीका यह है कि एक मैट्रिक्स की लाइन और दूसरी मैट्रिक्स के कॉलम के बीच डॉट प्रॉडक्ट निकाला जाए. इस सेक्शन में सबसे ऊपर दिया गया इलस्ट्रेशन देखें. मैट्रिक्स गुण Y=X*W के लिए, नतीजे का एक एलिमेंट यह होगा:

Y[2,0] = X[2,0]*W[0,0] + X[2,1]*W[1,0] + X[2,2]*W[2,0] + ... + X[2,n]*W[n,0]

जीपीयू पर, इस डॉट प्रॉडक्ट को जीपीयू "कोर" में प्रोग्राम किया जाता है. इसके बाद, इसे समानांतर रूप से उपलब्ध ज़्यादा से ज़्यादा "कोर" पर एक्ज़ीक्यूट किया जाता है, ताकि नतीजे वाली मैट्रिक्स की हर वैल्यू को एक साथ कंप्यूट किया जा सके. अगर नतीजे के तौर पर मिलने वाला मैट्रिक्स 128x128 बड़ा है, तो इसके लिए 128x128=16 हज़ार "कोर" उपलब्ध होने चाहिए. आम तौर पर, ऐसा नहीं हो पाता. सबसे बड़े जीपीयू में करीब 4,000 कोर होते हैं. दूसरी ओर, टीपीयू, MXU में कंप्यूट यूनिट के लिए कम से कम हार्डवेयर का इस्तेमाल करता है: सिर्फ़ bfloat16 x bfloat16 => float32 मल्टीप्लाय-ऐक्युमुलेटर. ये इतने छोटे होते हैं कि टीपीयू, 128x128 MXU में 16 हज़ार को लागू कर सकता है. साथ ही, इस मैट्रिक्स गुणन को एक बार में प्रोसेस कर सकता है.

f1b283fc45966717.gif

उदाहरण: MXU सिस्टोलिक ऐरे. कंप्यूट एलिमेंट, मल्टीप्लाय-ऐक्युमुलेटर होते हैं. एक मैट्रिक्स की वैल्यू को ऐरे (लाल बिंदु) में लोड किया जाता है. अन्य मैट्रिक्स की वैल्यू, ऐरे (ग्रे रंग के बिंदु) से होकर जाती हैं. वर्टिकल लाइनें, वैल्यू को ऊपर की ओर बढ़ाती हैं. हॉरिज़ॉन्टल लाइनें, आंशिक योग को आगे बढ़ाती हैं. यह उपयोगकर्ता के लिए एक टास्क है कि वह पुष्टि करे कि डेटा ऐरे से होकर गुज़रता है, तो आपको मैट्रिक्स के गुणन का नतीजा दाईं ओर मिलता है.

इसके अलावा, MXU में डॉट प्रॉडक्ट का हिसाब लगाने के दौरान, इंटरमीडिएट सम सिर्फ़ आस-पास की कंप्यूट यूनिट के बीच ट्रांसफ़र होते हैं. इन्हें मेमोरी या रजिस्टर फ़ाइल में सेव करने और वहां से वापस लाने की ज़रूरत नहीं होती. आखिर में, मैट्रिक्स को गुणा करने के दौरान, टीपीयू सिस्टोलिक ऐरे आर्किटेक्चर में जीपीयू की तुलना में ज़्यादा घनत्व और पावर का फ़ायदा मिलता है. साथ ही, इसकी स्पीड भी काफ़ी ज़्यादा होती है.

Cloud TPU

Google Cloud Platform पर " Cloud TPU v2" का अनुरोध करने पर, आपको एक वर्चुअल मशीन (वीएम) मिलती है. इसमें पीसीआई से जुड़ा TPU बोर्ड होता है. TPU बोर्ड में, ड्यूअल-कोर वाले चार TPU चिप होते हैं. हर टीपीयू कोर में एक वीपीयू (वेक्टर प्रोसेसिंग यूनिट) और एक 128x128 MXU (मैट्रिक्स मल्टिप्लाई यूनिट) होता है. इसके बाद, इस "Cloud TPU" को आम तौर पर नेटवर्क के ज़रिए उस वीएम से कनेक्ट किया जाता है जिसने इसके लिए अनुरोध किया था. इसलिए, पूरी जानकारी कुछ ऐसी दिखती है:

dfce5522ed644ece.png

इमेज: नेटवर्क से जुड़ा "Cloud TPU" ऐक्सलरेटर वाला वीएम. "Cloud TPU" में एक वीएम होता है. इसमें पीसीआई से जुड़ा एक टीपीयू बोर्ड होता है. इस बोर्ड पर दोहरे कोर वाले चार टीपीयू चिप लगे होते हैं.

TPU पॉड

Google के डेटा सेंटर में, टीपीयू को हाई-परफ़ॉर्मेंस कंप्यूटिंग (एचपीसी) इंटरकनेक्ट से कनेक्ट किया जाता है. इससे वे एक बहुत बड़े ऐक्सलरेटर की तरह दिख सकते हैं. Google इन्हें पॉड कहता है. इनमें ज़्यादा से ज़्यादा 512 टीपीयू v2 कोर या 2048 टीपीयू v3 कोर हो सकती हैं.

2ec1e0d341e7fc34.jpeg

इलस्ट्रेशन: TPU v3 पॉड. एचपीसी इंटरकनेक्ट के ज़रिए कनेक्ट किए गए टीपीयू बोर्ड और रैक.

ट्रेनिंग के दौरान, सभी रिड्यूस एल्गोरिदम का इस्तेमाल करके टीपीयू कोर के बीच ग्रेडिएंट बदले जाते हैं ( सभी रिड्यूस एल्गोरिदम के बारे में यहां अच्छी तरह बताया गया है). ट्रेनिंग के लिए इस्तेमाल किए जा रहे मॉडल को हार्डवेयर का फ़ायदा मिल सकता है. इसके लिए, उसे बड़े बैच साइज़ पर ट्रेन किया जाता है.

d97b9cc5d40fdb1d.gif

उदाहरण: Google के टीपीयू के 2-डी टोरॉइडल मेश एचपीसी नेटवर्क पर, ऑल-रिड्यूस एल्गोरिदम का इस्तेमाल करके ट्रेनिंग के दौरान ग्रेडिएंट का सिंक्रनाइज़ेशन.

सॉफ़्टवेयर

बड़े बैच साइज़ के साथ ट्रेनिंग

टीपीयू के लिए सबसे सही बैच साइज़, टीपीयू कोर के हिसाब से 128 डेटा आइटम होता है. हालांकि, हार्डवेयर, टीपीयू कोर के हिसाब से आठ डेटा आइटम से भी अच्छी परफ़ॉर्मेंस दिखा सकता है. ध्यान दें कि एक Cloud TPU में आठ कोर होते हैं.

इस कोडलैब में, हम Keras API का इस्तेमाल करेंगे. Keras में, आपके तय किए गए बैच का साइज़, पूरे टीपीयू के लिए ग्लोबल बैच साइज़ होता है. आपके बैच अपने-आप आठ हिस्सों में बंट जाएंगे और टीपीयू के आठ कोर पर चलेंगे.

da534407825f01e3.png

परफ़ॉर्मेंस को बेहतर बनाने के बारे में ज़्यादा सलाह पाने के लिए, टीपीयू की परफ़ॉर्मेंस गाइड देखें. बहुत बड़े बैच साइज़ के लिए, कुछ मॉडल में खास ध्यान रखने की ज़रूरत हो सकती है. ज़्यादा जानकारी के लिए, LARSOptimizer देखें.

बारीकियों के बारे में जानें: XLA

Tensorflow प्रोग्राम, कंप्यूटेशन ग्राफ़ तय करते हैं. टीपीयू, Python कोड को सीधे तौर पर नहीं चलाता है. यह आपके TensorFlow प्रोग्राम से तय किए गए कंप्यूटेशन ग्राफ़ को चलाता है. XLA (ऐक्सलरेटेड लीनियर अलजेब्रा कंपाइलर) नाम का कंपाइलर, कंप्यूटेशन नोड के Tensorflow ग्राफ़ को TPU मशीन कोड में बदलता है. यह कंपाइलर, आपके कोड और मेमोरी लेआउट को बेहतर बनाने के लिए कई अडवांस ऑप्टिमाइज़ेशन भी करता है. टीपीयू को काम भेजे जाने पर, कंपाइल करने की प्रोसेस अपने-आप होती है. आपको अपनी बिल्ड चेन में XLA को साफ़ तौर पर शामिल करने की ज़रूरत नहीं है.

edce61112cd57972.png

उदाहरण: टीपीयू पर चलाने के लिए, आपके TensorFlow प्रोग्राम से तय किए गए कंप्यूटेशन ग्राफ़ को पहले XLA (ऐक्सलरेटेड लीनियर अलजेब्रा कंपाइलर) के तौर पर ट्रांसलेट किया जाता है. इसके बाद, XLA इसे टीपीयू मशीन कोड में कंपाइल करता है.

Keras में टीपीयू का इस्तेमाल करना

Tensorflow 2.1 से, Keras API के ज़रिए टीपीयू इस्तेमाल किए जा सकते हैं. Keras का इस्तेमाल, टीपीयू और टीपीयू पॉड पर किया जा सकता है. यहां एक ऐसा उदाहरण दिया गया है जो टीपीयू, जीपीयू, और सीपीयू पर काम करता है:

try: # detect TPUs
    tpu = tf.distribute.cluster_resolver.TPUClusterResolver.connect()
    strategy = tf.distribute.TPUStrategy(tpu)
except ValueError: # detect GPUs
    strategy = tf.distribute.MirroredStrategy() # for CPU/GPU or multi-GPU machines

# use TPUStrategy scope to define model
with strategy.scope():
  model = tf.keras.Sequential( ... )
  model.compile( ... )

# train model normally on a tf.data.Dataset
model.fit(training_dataset, epochs=EPOCHS, steps_per_epoch=...)

इस कोड स्निपेट में:

  • TPUClusterResolver().connect() नेटवर्क पर मौजूद टीपीयू को ढूंढता है. यह ज़्यादातर Google Cloud सिस्टम पर बिना पैरामीटर के काम करता है. जैसे, AI Platform की जॉब, Colaboratory, Kubeflow, और ‘ctpu up' यूटिलिटी के ज़रिए बनाए गए डीप लर्निंग वीएम. इन सिस्टम को यह पता होता है कि उनका टीपीयू कहां है. ऐसा TPU_NAME एनवायरमेंट वैरिएबल की वजह से होता है. अगर टीपीयू को मैन्युअल तरीके से बनाया जाता है, तो टीपीयू का इस्तेमाल करने वाली वर्चुअल मशीन पर TPU_NAME env. var. सेट करें या साफ़ तौर पर पैरामीटर के साथ TPUClusterResolver को कॉल करें: TPUClusterResolver(tp_uname, zone, project)
  • TPUStrategy, डिस्ट्रिब्यूशन और "ऑल-रिड्यूस" ग्रेडिएंट सिंक्रनाइज़ेशन एल्गोरिदम को लागू करने वाला हिस्सा है.
  • यह रणनीति, स्कोप के ज़रिए लागू की जाती है. मॉडल को strategy scope() के अंदर तय किया जाना चाहिए.
  • tpu_model.fit फ़ंक्शन को टीपीयू ट्रेनिंग के लिए, tf.data.Dataset ऑब्जेक्ट की ज़रूरत होती है.

टीपीयू पर पोर्ट करने से जुड़े सामान्य टास्क

  • Tensorflow मॉडल में डेटा लोड करने के कई तरीके हैं. हालांकि, टीपीयू के लिए tf.data.Dataset एपीआई का इस्तेमाल करना ज़रूरी है.
  • टीपीयू बहुत तेज़ होते हैं और उन पर चलाते समय डेटा डालना अक्सर बॉटलनेक बन जाता है. डेटा बॉटलनेक और परफ़ॉर्मेंस से जुड़ी अन्य सलाह का पता लगाने के लिए, टूल उपलब्ध हैं. इनके बारे में टीपीयू परफ़ॉर्मेंस गाइड में बताया गया है.
  • int8 या int16 संख्याओं को int32 के तौर पर माना जाता है. टीपीयू में, 32 बिट से कम पर काम करने वाला पूर्णांक हार्डवेयर नहीं होता है.
  • Tensorflow की कुछ कार्रवाइयां काम नहीं करती हैं. सूची यहां दी गई है. अच्छी बात यह है कि यह सीमा सिर्फ़ ट्रेनिंग कोड पर लागू होती है. इसका मतलब है कि यह सीमा, आपके मॉडल के फ़ॉरवर्ड और बैकवर्ड पास पर लागू होती है. हालांकि, डेटा इनपुट पाइपलाइन में अब भी सभी TensorFlow ऑपरेशनों का इस्तेमाल किया जा सकता है, क्योंकि इन्हें सीपीयू पर एक्ज़ीक्यूट किया जाएगा.
  • tf.py_func को टीपीयू पर इस्तेमाल नहीं किया जा सकता.

4. डेटा लोड हो रहा है

c0ecb860e4cad0a9.jpeg cc4781a7739c49ae.jpeg 81236b00f8bbf39e.jpeg 961e2228974076bb.jpeg 7517dc163bdffcd5.jpeg 96392df4767f566d.png

हम फूलों की तस्वीरों के डेटासेट का इस्तेमाल करेंगे. इसका लक्ष्य, उन्हें पांच तरह के फूलों में बांटना है. डेटा लोड करने के लिए, tf.data.Dataset API का इस्तेमाल किया जाता है. सबसे पहले, हम एपीआई के बारे में जान लेते हैं.

खुद करके सीखना

कृपया इस नोटबुक को खोलें, सेल (Shift-ENTER) को एक्ज़ीक्यूट करें, और जहां भी आपको "WORK REQUIRED" लेबल दिखे वहां दिए गए निर्देशों का पालन करें.

c3df49e90e5a654f.png Fun with tf.data.Dataset (playground).ipynb

ज़्यादा जानकारी

"फूल" डेटासेट के बारे में जानकारी

डेटासेट को पांच फ़ोल्डर में व्यवस्थित किया गया है. हर फ़ोल्डर में एक तरह के फूल हैं. इन फ़ोल्डर के नाम सूरजमुखी, डेज़ी, डेंडलायन, ट्यूलिप, और गुलाब हैं. यह डेटा, Google Cloud Storage पर मौजूद सार्वजनिक बकेट में होस्ट किया जाता है. अंश:

gs://flowers-public/sunflowers/5139971615_434ff8ed8b_n.jpg
gs://flowers-public/daisy/8094774544_35465c1c64.jpg
gs://flowers-public/sunflowers/9309473873_9d62b9082e.jpg
gs://flowers-public/dandelion/19551343954_83bb52f310_m.jpg
gs://flowers-public/dandelion/14199664556_188b37e51e.jpg
gs://flowers-public/tulips/4290566894_c7f061583d_m.jpg
gs://flowers-public/roses/3065719996_c16ecd5551.jpg
gs://flowers-public/dandelion/8168031302_6e36f39d87.jpg
gs://flowers-public/sunflowers/9564240106_0577e919da_n.jpg
gs://flowers-public/daisy/14167543177_cd36b54ac6_n.jpg

tf.data.Dataset का इस्तेमाल क्यों करें?

Keras और Tensorflow, अपने सभी ट्रेनिंग और आकलन फ़ंक्शन में डेटासेट स्वीकार करते हैं. डेटासेट में डेटा लोड करने के बाद, एपीआई उन सभी सामान्य सुविधाओं को उपलब्ध कराता है जो न्यूरल नेटवर्क ट्रेनिंग डेटा के लिए फ़ायदेमंद होती हैं:

dataset = ... # load something (see below)
dataset = dataset.shuffle(1000) # shuffle the dataset with a buffer of 1000
dataset = dataset.cache() # cache the dataset in RAM or on disk
dataset = dataset.repeat() # repeat the dataset indefinitely
dataset = dataset.batch(128) # batch data elements together in batches of 128
AUTOTUNE = tf.data.AUTOTUNE
dataset = dataset.prefetch(AUTOTUNE) # prefetch next batch(es) while training

आपको परफ़ॉर्मेंस से जुड़ी सलाह और डेटासेट के सबसे सही तरीके इस लेख में मिल सकते हैं. रेफ़रंस दस्तावेज़ यहां दिया गया है.

tf.data.Dataset की बुनियादी बातें

डेटा आम तौर पर कई फ़ाइलों में होता है. यहां इमेज में दिखाया गया है. फ़ाइल के नामों का डेटासेट बनाने के लिए, यह तरीका अपनाएं:

filenames_dataset = tf.data.Dataset.list_files('gs://flowers-public/*/*.jpg')
# The parameter is a "glob" pattern that supports the * and ? wildcards.

इसके बाद, हर फ़ाइल के नाम पर एक फ़ंक्शन "मैप" किया जाता है. यह फ़ंक्शन, फ़ाइल को मेमोरी में मौजूद असल डेटा में लोड और डिकोड करता है:

def decode_jpeg(filename):
  bits = tf.io.read_file(filename)
  image = tf.io.decode_jpeg(bits)
  return image

image_dataset = filenames_dataset.map(decode_jpeg)
# this is now a dataset of decoded images (uint8 RGB format)

किसी डेटासेट पर बार-बार काम करने के लिए:

for data in my_dataset:
  print(data)

टपल के डेटासेट

सुपरवाइज़्ड लर्निंग में, ट्रेनिंग डेटासेट आम तौर पर ट्रेनिंग डेटा और सही जवाबों के जोड़े से बना होता है. इसकी अनुमति देने के लिए, डिकोडिंग फ़ंक्शन टपल दिखा सकता है. इसके बाद, आपके पास टपल का डेटासेट होगा. साथ ही, इस पर बार-बार काम करने पर टपल वापस मिल जाएंगे. लौटाई गई वैल्यू, TensorFlow टेंसर होती हैं. इन्हें आपका मॉडल इस्तेमाल कर सकता है. रॉ वैल्यू देखने के लिए, इन पर .numpy() कॉल किया जा सकता है:

def decode_jpeg_and_label(filename):
  bits = tf.read_file(filename)
  image = tf.io.decode_jpeg(bits)
  label = ... # extract flower name from folder name
  return image, label

image_dataset = filenames_dataset.map(decode_jpeg_and_label)
# this is now a dataset of (image, label) pairs 

for image, label in dataset:
  print(image.numpy().shape, label.numpy())

नतीजा:एक-एक करके इमेज लोड करने में समय लगता है !

इस डेटासेट को दोहराने पर, आपको पता चलेगा कि हर सेकंड में एक से दो इमेज लोड की जा सकती हैं. यह बहुत धीमा है! ट्रेनिंग के लिए इस्तेमाल किए जाने वाले हार्डवेयर ऐक्सलरेटर, इस दर को कई बार बनाए रख सकते हैं. हम इस लक्ष्य को कैसे हासिल करेंगे, यह जानने के लिए अगले सेक्शन पर जाएं.

समाधान

यहां समाधान वाली नोटबुक दी गई है. अगर आपको कोई समस्या आ रही है, तो इसका इस्तेमाल किया जा सकता है.

c3df49e90e5a654f.png Fun with tf.data.Dataset (solution).ipynb

हमने क्या-क्या बताया

  • 🤔 tf.data.Dataset.list_files
  • 🤔 tf.data.Dataset.map
  • 🤔 टपल के डेटासेट
  • 😀 डेटासेट के ज़रिए इटरेट करना

कृपया इस चेकलिस्ट को एक बार ध्यान से पढ़ लें.

5. डेटा को तेज़ी से लोड करना

इस लैब में हम जिन टेंसर प्रोसेसिंग यूनिट (टीपीयू) हार्डवेयर ऐक्सेलरेटर का इस्तेमाल करेंगे वे बहुत तेज़ हैं. इनको व्यस्त रखने के लिए, अक्सर डेटा को तेज़ी से प्रोसेस करना पड़ता है. Google Cloud Storage (GCS) में बहुत ज़्यादा थ्रूपुट होता है. हालांकि, सभी क्लाउड स्टोरेज सिस्टम की तरह, इसमें भी कनेक्शन शुरू करने पर कुछ नेटवर्क बैक ऐंड फ़ोर्थ का इस्तेमाल होता है. इसलिए, हमारे डेटा को हज़ारों अलग-अलग फ़ाइलों के तौर पर सेव करना सही नहीं है. हम उन्हें कम फ़ाइलों में बैच करने जा रहे हैं. साथ ही, tf.data.Dataset की मदद से, कई फ़ाइलों से एक साथ डेटा पढ़ने जा रहे हैं.

पढ़कर सुनाना

इमेज फ़ाइलों को लोड करने, उनके साइज़ को सामान्य साइज़ में बदलने, और फिर उन्हें 16 TFRecord फ़ाइलों में सेव करने वाला कोड, इस नोटबुक में मौजूद है. कृपया इसे जल्दी से पढ़ लें. इसे लागू करना ज़रूरी नहीं है, क्योंकि बाकी कोडलैब के लिए, TFRecord फ़ॉर्मैट में सही तरीके से डेटा उपलब्ध कराया जाएगा.

c3df49e90e5a654f.png Flower pictures to TFRecords.ipynb

GCS के थ्रूपुट को ऑप्टिमाइज़ करने के लिए, डेटा का सही लेआउट

TFRecord फ़ाइल फ़ॉर्मैट

Tensorflow, डेटा सेव करने के लिए protobuf पर आधारित TFRecord फ़ॉर्मैट का इस्तेमाल करता है. सीरियलाइज़ेशन के अन्य फ़ॉर्मैट भी काम करेंगे. हालांकि, TFRecord फ़ाइलों से सीधे तौर पर डेटासेट लोड करने के लिए, यह कोड लिखें:

filenames = tf.io.gfile.glob(FILENAME_PATTERN)
dataset = tf.data.TFRecordDataset(filenames)
dataset = dataset.map(...) # do the TFRecord decoding here - see below

बेहतर परफ़ॉर्मेंस के लिए, हमारा सुझाव है कि एक साथ कई TFRecord फ़ाइलों से डेटा पढ़ने के लिए, यहां दिए गए ज़्यादा जटिल कोड का इस्तेमाल करें. यह कोड, N फ़ाइलों से डेटा को एक साथ पढ़ेगा. साथ ही, डेटा को तेज़ी से पढ़ने के लिए, डेटा के क्रम को अनदेखा करेगा.

AUTOTUNE = tf.data.AUTOTUNE
ignore_order = tf.data.Options()
ignore_order.experimental_deterministic = False

filenames = tf.io.gfile.glob(FILENAME_PATTERN)
dataset = tf.data.TFRecordDataset(filenames, num_parallel_reads=AUTOTUNE)
dataset = dataset.with_options(ignore_order)
dataset = dataset.map(...) # do the TFRecord decoding here - see below

TFRecord से जुड़ी काम की बातों की सूची

TFRecords में तीन तरह का डेटा सेव किया जा सकता है: बाइट स्ट्रिंग (बाइट की सूची), 64 बिट पूर्णांक, और 32 बिट फ़्लोट. इन्हें हमेशा सूचियों के तौर पर सेव किया जाता है. एक डेटा एलिमेंट, साइज़ 1 की सूची होगा. TFRecords में डेटा सेव करने के लिए, यहां दिए गए हेल्पर फ़ंक्शन का इस्तेमाल किया जा सकता है.

writing byte strings

# warning, the input is a list of byte strings, which are themselves lists of bytes
def _bytestring_feature(list_of_bytestrings):
  return tf.train.Feature(bytes_list=tf.train.BytesList(value=list_of_bytestrings))

पूर्णांक लिखना

def _int_feature(list_of_ints): # int64
  return tf.train.Feature(int64_list=tf.train.Int64List(value=list_of_ints))

फ़्लोटिंग टेक्स्ट लिखना

def _float_feature(list_of_floats): # float32
  return tf.train.Feature(float_list=tf.train.FloatList(value=list_of_floats))

ऊपर दिए गए हेल्पर का इस्तेमाल करके, TFRecord लिखना

# input data in my_img_bytes, my_class, my_height, my_width, my_floats
with tf.python_io.TFRecordWriter(filename) as out_file:
  feature = {
    "image": _bytestring_feature([my_img_bytes]), # one image in the list
    "class": _int_feature([my_class]),            # one class in the list
    "size": _int_feature([my_height, my_width]),  # fixed length (2) list of ints
    "float_data": _float_feature(my_floats)       # variable length  list of floats
  }
  tf_record = tf.train.Example(features=tf.train.Features(feature=feature))
  out_file.write(tf_record.SerializeToString())

TFRecords से डेटा पढ़ने के लिए, आपको सबसे पहले सेव किए गए रिकॉर्ड का लेआउट तय करना होगा. डिक्लेरेशन में, किसी भी नाम वाले फ़ील्ड को निश्चित लंबाई वाली सूची या अलग-अलग लंबाई वाली सूची के तौर पर ऐक्सेस किया जा सकता है:

TFRecords से डेटा पढ़ना

def read_tfrecord(data):
  features = {
    # tf.string = byte string (not text string)
    "image": tf.io.FixedLenFeature([], tf.string), # shape [] means scalar, here, a single byte string
    "class": tf.io.FixedLenFeature([], tf.int64),  # shape [] means scalar, i.e. a single item
    "size": tf.io.FixedLenFeature([2], tf.int64),  # two integers
    "float_data": tf.io.VarLenFeature(tf.float32)  # a variable number of floats
  }

  # decode the TFRecord
  tf_record = tf.io.parse_single_example(data, features)

  # FixedLenFeature fields are now ready to use
  sz = tf_record['size']

  # Typical code for decoding compressed images
  image = tf.io.decode_jpeg(tf_record['image'], channels=3)

  # VarLenFeature fields require additional sparse.to_dense decoding
  float_data = tf.sparse.to_dense(tf_record['float_data'])

  return image, sz, float_data

# decoding a tf.data.TFRecordDataset
dataset = dataset.map(read_tfrecord)
# now a dataset of triplets (image, sz, float_data)

काम के कोड स्निपेट:

सिंगल डेटा एलिमेंट को पढ़ना

tf.io.FixedLenFeature([], tf.string)   # for one byte string
tf.io.FixedLenFeature([], tf.int64)    # for one int
tf.io.FixedLenFeature([], tf.float32)  # for one float

तय किए गए साइज़ की एलिमेंट की सूचियां पढ़ना

tf.io.FixedLenFeature([N], tf.string)   # list of N byte strings
tf.io.FixedLenFeature([N], tf.int64)    # list of N ints
tf.io.FixedLenFeature([N], tf.float32)  # list of N floats

डेटा आइटम की अलग-अलग संख्या को पढ़ना

tf.io.VarLenFeature(tf.string)   # list of byte strings
tf.io.VarLenFeature(tf.int64)    # list of ints
tf.io.VarLenFeature(tf.float32)  # list of floats

VarLenFeature, एक स्पार्स वेक्टर दिखाता है. साथ ही, TFRecord को डिकोड करने के बाद एक और चरण पूरा करना ज़रूरी होता है:

dense_data = tf.sparse.to_dense(tf_record['my_var_len_feature'])

TFRecords में वैकल्पिक फ़ील्ड भी हो सकते हैं. किसी फ़ील्ड को पढ़ते समय डिफ़ॉल्ट वैल्यू तय करने पर, फ़ील्ड मौजूद न होने पर गड़बड़ी के बजाय डिफ़ॉल्ट वैल्यू दिखती है.

tf.io.FixedLenFeature([], tf.int64, default_value=0) # this field is optional

हमने क्या-क्या बताया

  • 🤔 GCS से डेटा को तेज़ी से ऐक्सेस करने के लिए, डेटा फ़ाइलों को शार्ड करना
  • 😓 TFRecords लिखने का तरीका. (क्या आपको सिंटैक्स याद नहीं है? कोई बात नहीं, इस पेज को चीट शीट के तौर पर बुकमार्क करें)
  • 🤔 TFRecordDataset का इस्तेमाल करके, TFRecords से डेटासेट लोड करना

कृपया इस चेकलिस्ट को एक बार ध्यान से पढ़ लें.

6. [INFO] न्यूरल नेटवर्क क्लासिफ़ायर 101

कम शब्दों में

अगर आपको अगले पैराग्राफ़ में बोल्ड किए गए सभी शब्दों के बारे में पहले से पता है, तो अगले अभ्यास पर जाएं. अगर आपने डीप लर्निंग की शुरुआत अभी की है, तो आपका स्वागत है. कृपया आगे पढ़ें.

लेयर के सीक्वेंस के तौर पर बनाए गए मॉडल के लिए, Keras, Sequential API उपलब्ध कराता है. उदाहरण के लिए, तीन डेंस लेयर का इस्तेमाल करने वाले इमेज क्लासिफ़ायर को Keras में इस तरह लिखा जा सकता है:

model = tf.keras.Sequential([
    tf.keras.layers.Flatten(input_shape=[192, 192, 3]),
    tf.keras.layers.Dense(500, activation="relu"),
    tf.keras.layers.Dense(50, activation="relu"),
    tf.keras.layers.Dense(5, activation='softmax') # classifying into 5 classes
])

# this configures the training of the model. Keras calls it "compiling" the model.
model.compile(
  optimizer='adam',
  loss= 'categorical_crossentropy',
  metrics=['accuracy']) # % of correct answers

# train the model
model.fit(dataset, ... )

688858c21e3beff2.png

डेंस न्यूरल नेटवर्क

यह इमेज को क्लासिफ़ाई करने के लिए सबसे आसान न्यूरल नेटवर्क है. यह लेयर में व्यवस्थित किए गए "न्यूरॉन" से बना होता है. पहली लेयर, इनपुट डेटा को प्रोसेस करती है और इसके आउटपुट को अन्य लेयर में भेजती है. इसे "डेंस" इसलिए कहा जाता है, क्योंकि हर न्यूरॉन, पिछली लेयर के सभी न्यूरॉन से जुड़ा होता है.

c21bae6dade487bc.png

किसी इमेज को ऐसे नेटवर्क में फ़ीड करने के लिए, उसके सभी पिक्सल की आरजीबी वैल्यू को एक लंबे वेक्टर में बदला जाता है. इसके बाद, इसे इनपुट के तौर पर इस्तेमाल किया जाता है. यह इमेज को पहचानने की सबसे अच्छी तकनीक नहीं है. हालांकि, हम इसे बाद में बेहतर बनाएंगे.

न्यूरॉन, ऐक्टिवेशन, RELU

"न्यूरॉन" अपने सभी इनपुट का वेटेड सम कंप्यूट करता है. इसके बाद, इसमें "बायस" नाम की वैल्यू जोड़ता है और नतीजे को "ऐक्टिवेशन फ़ंक्शन" के तौर पर इस्तेमाल करता है. वज़न और बायस की जानकारी शुरुआत में नहीं होती है. इन्हें रैंडम तरीके से शुरू किया जाएगा. साथ ही, न्यूरल नेटवर्क को कई तरह के डेटा पर ट्रेनिंग देकर "सीखा" जाएगा.

644f4213a4ee70e5.png

सबसे लोकप्रिय ऐक्टिवेशन फ़ंक्शन को रेक्टिफ़ाइड लीनियर यूनिट के लिए RELU कहा जाता है. यह एक बहुत ही आसान फ़ंक्शन है. इसे ऊपर दिए गए ग्राफ़ में देखा जा सकता है.

सॉफ़्टमैक्स ऐक्टिवेशन

ऊपर दिया गया नेटवर्क, पांच न्यूरॉन वाली लेयर के साथ खत्म होता है. ऐसा इसलिए है, क्योंकि हम फूलों को पांच कैटगरी (गुलाब, ट्यूलिप, डैंडेलियन, डेज़ी, सूरजमुखी) में बांट रहे हैं. इंटरमीडिएट लेयर में मौजूद न्यूरॉन, क्लासिक RELU ऐक्टिवेशन फ़ंक्शन का इस्तेमाल करके चालू किए जाते हैं. हालांकि, आखिरी लेयर में हमें 0 और 1 के बीच की संख्याओं का हिसाब लगाना है. ये संख्याएं, इस बात की संभावना को दिखाती हैं कि यह फूल गुलाब, ट्यूलिप वगैरह है. इसके लिए, हम "सॉफ़्टमैक्स" नाम के ऐक्टिवेशन फ़ंक्शन का इस्तेमाल करेंगे.

किसी वेक्टर पर सॉफ़्टमैक्स लागू करने के लिए, हर एलिमेंट का एक्सपोनेंशियल लिया जाता है. इसके बाद, वेक्टर को सामान्य किया जाता है. आम तौर पर, L1 नॉर्म (ऐब्सलूट वैल्यू का योग) का इस्तेमाल किया जाता है, ताकि वैल्यू का योग 1 हो और उन्हें संभावनाओं के तौर पर समझा जा सके.

ef0d98c0952c262d.png d51252f75894479e.gif

क्रॉस-एंट्रॉपी लॉस

अब हमारा न्यूरल नेटवर्क, इनपुट इमेज से अनुमान लगाता है. हमें यह मेज़र करना होगा कि ये अनुमान कितने सही हैं. इसका मतलब है कि नेटवर्क से मिले जवाब और सही जवाबों के बीच का अंतर. सही जवाबों को अक्सर "लेबल" कहा जाता है. ध्यान रखें कि हमारे पास डेटासेट में मौजूद सभी इमेज के लिए सही लेबल हैं.

कोई भी दूरी काम करेगी, लेकिन क्लासिफ़िकेशन की समस्याओं के लिए, "क्रॉस-एंट्रॉपी दूरी" सबसे असरदार होती है. हम इसे गड़बड़ी या "लॉस" फ़ंक्शन कहेंगे:

7bdf8753d20617fb.png

ग्रेडिएंट डिसेंट

न्यूरल नेटवर्क को "ट्रेनिंग" देने का मतलब है कि ट्रेनिंग इमेज और लेबल का इस्तेमाल करके, वज़न और पूर्वाग्रहों को इस तरह से अडजस्ट किया जाए कि क्रॉस-एंट्रॉपी लॉस फ़ंक्शन को कम किया जा सके. यह सुविधा इस तरह से काम करती है.

क्रॉस-एंट्रॉपी, वेट, बायस, ट्रेनिंग इमेज के पिक्सल, और उसकी क्लास का फ़ंक्शन है.

अगर हम सभी वेट और सभी बायस के हिसाब से क्रॉस-एंट्रॉपी के पार्शियल डेरिवेटिव का हिसाब लगाते हैं, तो हमें "ग्रेडिएंट" मिलता है. इसका हिसाब किसी इमेज, लेबल, और वेट और बायस की मौजूदा वैल्यू के लिए किया जाता है. ध्यान रखें कि हमारे पास लाखों वज़न और बायस हो सकते हैं. इसलिए, ग्रेडिएंट की गिनती करना एक मुश्किल काम लगता है. अच्छी बात यह है कि TensorFlow हमारे लिए यह काम करता है. ग्रेडिएंट की गणितीय प्रॉपर्टी यह है कि यह "ऊपर" की ओर इशारा करता है. हमें उस दिशा में जाना है जहां क्रॉस-एंट्रॉपी कम हो. इसलिए, हम विपरीत दिशा में जाते हैं. हम ग्रेडिएंट के कुछ हिस्से से वज़न और पूर्वाग्रहों को अपडेट करते हैं. इसके बाद, हम ट्रेनिंग लूप में ट्रेनिंग इमेज और लेबल के अगले बैच का इस्तेमाल करके, यही प्रोसेस बार-बार दोहराते हैं. उम्मीद है कि यह एक ऐसी जगह पर जाकर खत्म होगा जहां क्रॉस-एंट्रॉपी कम से कम हो. हालांकि, इस बात की कोई गारंटी नहीं है कि यह कम से कम वैल्यू यूनीक है.

gradient descent2.png

मिनी-बैचिंग और मोमेंटम

सिर्फ़ एक उदाहरण इमेज पर ग्रेडिएंट का हिसाब लगाया जा सकता है. साथ ही, वज़न और पक्षपातों को तुरंत अपडेट किया जा सकता है. हालांकि, उदाहरण के लिए, 128 इमेज के बैच पर ऐसा करने से, एक ऐसा ग्रेडिएंट मिलता है जो अलग-अलग उदाहरण इमेज से जुड़ी पाबंदियों को बेहतर तरीके से दिखाता है. इसलिए, यह समाधान की ओर तेज़ी से बढ़ता है. मिनी-बैच का साइज़, अडजस्ट किया जा सकने वाला पैरामीटर होता है.

इस तकनीक को कभी-कभी "स्टोकास्टिक ग्रेडिएंट डिसेंट" भी कहा जाता है. इसका एक और फ़ायदा यह है कि बैच के साथ काम करने का मतलब है कि बड़ी मैट्रिक्स के साथ काम करना. इन्हें आम तौर पर जीपीयू और टीपीयू पर ऑप्टिमाइज़ करना आसान होता है.

हालांकि, कन्वर्जेंस अब भी थोड़ा मुश्किल हो सकता है. साथ ही, अगर ग्रेडिएंट वेक्टर सभी शून्य हैं, तो यह रुक भी सकता है. क्या इसका मतलब यह है कि हमें कम से कम एक समस्या मिली है? हमेशा नहीं. ग्रेडिएंट कॉम्पोनेंट की वैल्यू, कम से कम या ज़्यादा से ज़्यादा पर शून्य हो सकती है. लाखों एलिमेंट वाले ग्रेडिएंट वेक्टर में, अगर सभी एलिमेंट ज़ीरो हैं, तो इस बात की संभावना बहुत कम होती है कि हर ज़ीरो, कम से कम वैल्यू के बराबर हो और कोई भी ज़ीरो, ज़्यादा से ज़्यादा वैल्यू के बराबर न हो. कई डाइमेंशन वाले स्पेस में, सैडल पॉइंट काफ़ी सामान्य होते हैं और हम इन पर नहीं रुकना चाहते.

52e824fe4716c4a0.png

इलस्ट्रेशन: सैडल पॉइंट. ग्रेडिएंट 0 है, लेकिन यह सभी दिशाओं में कम से कम नहीं है. (इमेज एट्रिब्यूशन Wikimedia: By Nicoguaro - Own work, CC BY 3.0)

इसका समाधान यह है कि ऑप्टिमाइज़ेशन एल्गोरिदम में कुछ मोमेंटम जोड़ा जाए, ताकि वह बिना रुके सैडल पॉइंट को पार कर सके.

शब्दावली

बैच या मिनी-बैच: ट्रेनिंग हमेशा ट्रेनिंग डेटा और लेबल के बैच पर की जाती है. ऐसा करने से, एल्गोरिदम को कन्वर्ज होने में मदद मिलती है. "बैच" डाइमेंशन, आम तौर पर डेटा टेंसर का पहला डाइमेंशन होता है. उदाहरण के लिए, [100, 192, 192, 3] शेप वाले टेंसर में 192x192 पिक्सल की 100 इमेज होती हैं. हर पिक्सल की तीन वैल्यू (आरजीबी) होती हैं.

क्रॉस-एंट्रॉपी लॉस: यह एक खास लॉस फ़ंक्शन है. इसका इस्तेमाल अक्सर क्लासिफ़ायर में किया जाता है.

डेंस लेयर: न्यूरॉन की एक ऐसी लेयर जिसमें हर न्यूरॉन, पिछली लेयर के सभी न्यूरॉन से जुड़ा होता है.

विशेषताएं: न्यूरल नेटवर्क के इनपुट को कभी-कभी "विशेषताएं" कहा जाता है. डेटासेट के किन हिस्सों (या हिस्सों के कॉम्बिनेशन) को न्यूरल नेटवर्क में डाला जाए, ताकि अच्छी तरह से अनुमान लगाया जा सके, इस कला को "फ़ीचर इंजीनियरिंग" कहा जाता है.

लेबल: सुपरवाइज़्ड क्लासिफ़िकेशन की समस्या में "क्लास" या सही जवाबों को लेबल कहा जाता है

सीखने की दर: यह ग्रेडिएंट का वह हिस्सा होता है जिससे ट्रेनिंग लूप के हर इटरेशन में वज़न और बायस अपडेट किए जाते हैं.

लॉजेट: ऐक्टिवेशन फ़ंक्शन लागू होने से पहले, न्यूरॉन की लेयर के आउटपुट को "लॉजेट" कहा जाता है. यह शब्द, "लॉजिस्टिक फ़ंक्शन" से लिया गया है. इसे "सिग्मॉइड फ़ंक्शन" भी कहा जाता है. यह सबसे ज़्यादा इस्तेमाल किया जाने वाला ऐक्टिवेशन फ़ंक्शन था. "लॉजिस्टिक फ़ंक्शन से पहले न्यूरॉन आउटपुट" को छोटा करके "लॉजिट" कर दिया गया है.

loss: यह एक ऐसा फ़ंक्शन है जो न्यूरल नेटवर्क के आउटपुट की तुलना सही जवाबों से करता है

न्यूरॉन: यह अपने इनपुट का वेटेड सम कंप्यूट करता है. साथ ही, इसमें एक बायस जोड़ता है और नतीजे को ऐक्टिवेशन फ़ंक्शन के ज़रिए फ़ीड करता है.

वन-हॉट एन्कोडिंग: पांच में से तीसरी क्लास को पांच एलिमेंट वाले वेक्टर के तौर पर एन्कोड किया गया है. इसमें तीसरे एलिमेंट को छोड़कर बाकी सभी एलिमेंट शून्य हैं.

relu: रेक्टिफ़ाइड लीनियर यूनिट. यह न्यूरॉन के लिए एक लोकप्रिय ऐक्टिवेशन फ़ंक्शन है.

sigmoid: यह एक और ऐक्टिवेशन फ़ंक्शन है. यह पहले काफ़ी लोकप्रिय था और अब भी कुछ खास मामलों में काम आता है.

softmax: यह एक खास ऐक्टिवेशन फ़ंक्शन है, जो वेक्टर पर काम करता है. यह सबसे बड़े कॉम्पोनेंट और अन्य सभी कॉम्पोनेंट के बीच के अंतर को बढ़ाता है. साथ ही, वेक्टर को सामान्य बनाता है, ताकि उसका योग 1 हो. इससे वेक्टर को संभावनाओं के वेक्टर के तौर पर समझा जा सकता है. इसका इस्तेमाल क्लासिफ़ायर में आखिरी चरण के तौर पर किया जाता है.

टेंसर: "टेंसर" मैट्रिक्स की तरह होता है, लेकिन इसमें डाइमेंशन की संख्या कुछ भी हो सकती है. एक डाइमेंशन वाला टेंसर, वेक्टर होता है. दो डाइमेंशन वाला टेंसर, एक मैट्रिक्स होता है. इसके बाद, आपके पास 3, 4, 5 या उससे ज़्यादा डाइमेंशन वाले टेंसर हो सकते हैं.

7. ट्रांसफ़र लर्निंग

इमेज क्लासिफ़िकेशन की समस्या के लिए, डेंस लेयर शायद काफ़ी नहीं होंगी. हमें कनवोल्यूशनल लेयर और उन्हें व्यवस्थित करने के कई तरीकों के बारे में जानना होगा.

हालांकि, हम एक शॉर्टकट का भी इस्तेमाल कर सकते हैं! पूरी तरह से ट्रेन किए गए कॉन्वलूशनल न्यूरल नेटवर्क डाउनलोड किए जा सकते हैं. इसकी आखिरी लेयर, सॉफ़्टमैक्स क्लासिफ़िकेशन हेड को हटाया जा सकता है और उसकी जगह अपनी लेयर लगाई जा सकती है. ट्रेन किए गए सभी वेट और बायस पहले जैसे ही रहते हैं. आपको सिर्फ़ जोड़ी गई सॉफ़्टमैक्स लेयर को फिर से ट्रेन करना होता है. इस तकनीक को ट्रांसफ़र लर्निंग कहा जाता है. यह तब तक काम करती है, जब तक न्यूरल नेट को पहले से ट्रेन करने के लिए इस्तेमाल किया गया डेटासेट, आपके डेटासेट से "मिलता-जुलता" हो.

खुद करके सीखना

कृपया इस नोटबुक को खोलें, सेल (Shift-ENTER) को एक्ज़ीक्यूट करें, और जहां भी आपको "WORK REQUIRED" लेबल दिखे वहां दिए गए निर्देशों का पालन करें.

c3df49e90e5a654f.png Keras Flowers transfer learning (playground).ipynb

ज़्यादा जानकारी

ट्रांसफ़र लर्निंग की मदद से, आपको टॉप रिसर्चर्स की ओर से तैयार किए गए ऐडवांस कन्वलूशनल न्यूरल नेटवर्क आर्किटेक्चर और इमेज के बड़े डेटासेट पर प्री-ट्रेनिंग, दोनों का फ़ायदा मिलता है. इस मामले में, हम ImageNet पर ट्रेन किए गए नेटवर्क से ट्रांसफ़र लर्निंग करेंगे. ImageNet, इमेज का एक डेटाबेस है. इसमें कई पौधों और आउटडोर सीन की इमेज शामिल हैं. यह फूलों की इमेज से काफ़ी मिलती-जुलती है.

b8fc1efd2001f072.png

उदाहरण: पहले से ट्रेन किए गए कॉम्प्लेक्स कनवोल्यूशनल न्यूरल नेटवर्क का इस्तेमाल ब्लैक बॉक्स के तौर पर किया जा रहा है. इसमें सिर्फ़ क्लासिफ़िकेशन हेड को फिर से ट्रेन किया जा रहा है. इसे ट्रांसफ़र लर्निंग कहा जाता है. हम बाद में देखेंगे कि कनवोल्यूशनल लेयर की ये जटिल व्यवस्थाएं कैसे काम करती हैं. फ़िलहाल, यह किसी और की समस्या है.

Keras में ट्रांसफ़र लर्निंग

Keras में, tf.keras.applications.* कलेक्शन से पहले से ट्रेन किए गए मॉडल को इंस्टैंशिएट किया जा सकता है. उदाहरण के लिए, MobileNet V2 एक बहुत अच्छी कनवोल्यूशनल आर्किटेक्चर है. इसका साइज़ भी ठीक-ठाक है. include_top=False को चुनने पर, आपको पहले से ट्रेन किया गया मॉडल मिलता है. इसमें फ़ाइनल सॉफ़्टमैक्स लेयर नहीं होती है, ताकि आप अपनी लेयर जोड़ सकें:

pretrained_model = tf.keras.applications.MobileNetV2(input_shape=[*IMAGE_SIZE, 3], include_top=False)
pretrained_model.trainable = False

model = tf.keras.Sequential([
    pretrained_model,
    tf.keras.layers.Flatten(),
    tf.keras.layers.Dense(5, activation='softmax')
])

pretrained_model.trainable = False सेटिंग पर भी ध्यान दें. यह पहले से ट्रेन किए गए मॉडल के वेट और बायस को फ़्रीज़ कर देता है, ताकि सिर्फ़ आपकी सॉफ़्टमैक्स लेयर को ट्रेन किया जा सके. इसमें आम तौर पर कम वेट शामिल होते हैं. इसे जल्दी से और बहुत बड़े डेटासेट की ज़रूरत के बिना किया जा सकता है. हालांकि, अगर आपके पास काफ़ी डेटा है, तो ट्रांसफ़र लर्निंग, pretrained_model.trainable = True के साथ और भी बेहतर तरीके से काम कर सकती है. पहले से ट्रेन किए गए वेट, बेहतरीन शुरुआती वैल्यू देते हैं. साथ ही, ट्रेनिंग के दौरान इन्हें अब भी अडजस्ट किया जा सकता है, ताकि ये आपकी समस्या के हिसाब से बेहतर तरीके से काम कर सकें.

आखिर में, ध्यान दें कि आपकी डेंस सॉफ़्टमैक्स लेयर से पहले Flatten() लेयर डाली गई है. डेंस लेयर, डेटा के फ़्लैट वेक्टर पर काम करती हैं. हालांकि, हमें यह नहीं पता कि प्रीट्रेन किया गया मॉडल यही डेटा दिखाता है या नहीं. इसलिए, हमें फ़्लैटन करने की ज़रूरत है. अगले चैप्टर में, हम कनवोल्यूशनल आर्किटेक्चर के बारे में विस्तार से जानेंगे. साथ ही, हम कनवोल्यूशनल लेयर से मिले डेटा के फ़ॉर्मैट के बारे में भी बताएंगे.

इस तरीके से, आपको करीब 75% सटीक नतीजे मिलेंगे.

समाधान

यहां समाधान वाली नोटबुक दी गई है. अगर आपको कोई समस्या आ रही है, तो इसका इस्तेमाल किया जा सकता है.

c3df49e90e5a654f.png Keras Flowers transfer learning (solution).ipynb

हमने क्या-क्या बताया

  • 🤔 Keras में क्लासिफ़ायर कैसे लिखें
  • 🤓 को सॉफ़्टमैक्स लास्ट लेयर और क्रॉस-एंट्रॉपी लॉस के साथ कॉन्फ़िगर किया गया है
  • 😈 ट्रांसफ़र लर्निंग
  • 🤔 अपना पहला मॉडल ट्रेन करना
  • 🧐 ट्रेनिंग के दौरान, मॉडल की परफ़ॉर्मेंस और सटीक नतीजे देने की क्षमता

कृपया इस चेकलिस्ट को एक बार ध्यान से पढ़ लें.

8. [INFO] कॉन्वलूशनल न्यूरल नेटवर्क

कम शब्दों में

अगर आपको अगले पैराग्राफ़ में बोल्ड किए गए सभी शब्दों के बारे में पहले से पता है, तो अगले अभ्यास पर जाएं. अगर आपने हाल ही में कनवोल्यूशनल न्यूरल नेटवर्क का इस्तेमाल शुरू किया है, तो कृपया आगे पढ़ें.

convolutional.gif

इलस्ट्रेशन: किसी इमेज को दो फ़िल्टर की मदद से फ़िल्टर किया जा रहा है. हर फ़िल्टर में 4x4x3=48 लर्निंग वेट हैं.

Keras में एक सामान्य कॉन्वलूशनल न्यूरल नेटवर्क इस तरह दिखता है:

model = tf.keras.Sequential([
  # input: images of size 192x192x3 pixels (the three stands for RGB channels)
  tf.keras.layers.Conv2D(kernel_size=3, filters=24, padding='same', activation='relu', input_shape=[192, 192, 3]),
  tf.keras.layers.Conv2D(kernel_size=3, filters=24, padding='same', activation='relu'),
  tf.keras.layers.MaxPooling2D(pool_size=2),
  tf.keras.layers.Conv2D(kernel_size=3, filters=12, padding='same', activation='relu'),
  tf.keras.layers.MaxPooling2D(pool_size=2),
  tf.keras.layers.Conv2D(kernel_size=3, filters=6, padding='same', activation='relu'),
  tf.keras.layers.Flatten(),
  # classifying into 5 categories
  tf.keras.layers.Dense(5, activation='softmax')
])

model.compile(
  optimizer='adam',
  loss= 'categorical_crossentropy',
  metrics=['accuracy'])

688858c21e3beff2.png

कन्वलूशनल न्यूरल नेटवर्क के बारे में बुनियादी जानकारी

कनवोल्यूशनल नेटवर्क की लेयर में, एक "न्यूरॉन" सिर्फ़ इमेज के छोटे से हिस्से में, ठीक ऊपर मौजूद पिक्सल का वेटेड सम करता है. यह एक पूर्वाग्रह जोड़ता है और सम को ऐक्टिवेशन फ़ंक्शन के ज़रिए फ़ीड करता है. यह ठीक उसी तरह काम करता है जैसे किसी सामान्य डेंस लेयर में न्यूरॉन काम करता है. इसके बाद, इस ऑपरेशन को पूरी इमेज पर दोहराया जाता है. इसके लिए, एक ही वज़न का इस्तेमाल किया जाता है. याद रखें कि डेंस लेयर में, हर न्यूरॉन के अपने वेट होते हैं. यहां, वज़न का एक "पैच", इमेज पर दोनों दिशाओं में स्लाइड करता है ("कनवोल्यूशन"). आउटपुट में उतनी ही वैल्यू होती हैं जितने पिक्सल इमेज में होते हैं. हालांकि, किनारों पर कुछ पैडिंग ज़रूरी होती है. यह फ़िल्टर करने की प्रोसेस है. इसमें 4x4x3=48 वज़न वाले फ़िल्टर का इस्तेमाल किया जाता है.

हालांकि, 48 वैल्यू काफ़ी नहीं होंगी. ज़्यादा डिग्री ऑफ़ फ़्रीडम जोड़ने के लिए, हम वज़न के नए सेट के साथ उसी ऑपरेशन को दोहराते हैं. इससे फ़िल्टर के आउटपुट का नया सेट मिलता है. इसे इनपुट इमेज में मौजूद R,G,B चैनलों के हिसाब से, आउटपुट का "चैनल" कहा जा सकता है.

Screen Shot 2016-07-29 at 16.02.37.png

नए डाइमेंशन को जोड़कर, वज़न के दो (या इससे ज़्यादा) सेट को एक टेंसर के तौर पर जोड़ा जा सकता है. इससे हमें कनवोल्यूशनल लेयर के लिए, वेट टेंसर का सामान्य आकार मिलता है. इनपुट और आउटपुट चैनलों की संख्या पैरामीटर होती है. इसलिए, हम कनवोल्यूशनल लेयर को स्टैक और चेन करना शुरू कर सकते हैं.

d1b557707bcd1cb9.png

उदाहरण: कनवोल्यूशनल न्यूरल नेटवर्क, डेटा के "क्यूब" को डेटा के अन्य "क्यूब" में बदलता है.

स्ट्राइड कनवोल्यूशन, मैक्स पूलिंग

स्ट्राइड 2 या 3 के साथ कनवोल्यूशन करके, हम नतीजे के तौर पर मिले डेटा क्यूब को उसके हॉरिज़ॉन्टल डाइमेंशन में छोटा भी कर सकते हैं. ऐसा करने के दो सामान्य तरीके हैं:

  • स्ट्राइड कनवोल्यूशन: ऊपर की तरह स्लाइडिंग फ़िल्टर, लेकिन स्ट्राइड >1 के साथ
  • मैक्स पूलिंग: यह एक स्लाइडिंग विंडो होती है, जो MAX ऑपरेशन लागू करती है. आम तौर पर, यह 2x2 पैच पर लागू होती है और हर 2 पिक्सल पर दोहराई जाती है

2b2d4263bb8470b.gif

उदाहरण: कंप्यूटिंग विंडो को तीन पिक्सल तक स्लाइड करने पर, आउटपुट वैल्यू कम हो जाती हैं. स्ट्राइड कनवोल्यूशन या मैक्स पूलिंग (2x2 विंडो में ज़्यादा से ज़्यादा वैल्यू, जो 2 के स्ट्राइड से स्लाइड होती है) की मदद से, हॉरिज़ॉन्टल डाइमेंशन में डेटा क्यूब को छोटा किया जा सकता है.

Convolutional classifier

आखिर में, हम आखिरी डेटा क्यूब को फ़्लैट करके, क्लासिफ़िकेशन हेड जोड़ते हैं. इसके बाद, इसे डेंस और सॉफ़्टमैक्स-ऐक्टिवेटेड लेयर से पास किया जाता है. सामान्य तौर पर, कनवोल्यूशनल क्लासिफ़ायर ऐसा दिखता है:

4a61aaffb6cba3d1.png

इलस्ट्रेशन: कनवोल्यूशनल और सॉफ़्टमैक्स लेयर का इस्तेमाल करने वाला इमेज क्लासिफ़ायर. इसमें 3x3 और 1x1 फ़िल्टर का इस्तेमाल किया जाता है. maxpool लेयर, 2x2 डेटा पॉइंट के ग्रुप में से सबसे बड़ी वैल्यू लेती हैं. क्लासिफ़िकेशन हेड को, सॉफ़्टमैक्स ऐक्टिवेशन वाली डेंस लेयर के साथ लागू किया जाता है.

Keras में

ऊपर दिखाए गए कनवोल्यूशनल स्टैक को Keras में इस तरह लिखा जा सकता है:

model = tf.keras.Sequential([
  # input: images of size 192x192x3 pixels (the three stands for RGB channels)    
  tf.keras.layers.Conv2D(kernel_size=3, filters=32, padding='same', activation='relu', input_shape=[192, 192, 3]),
  tf.keras.layers.Conv2D(kernel_size=1, filters=32, padding='same', activation='relu'),
  tf.keras.layers.MaxPooling2D(pool_size=2),
  tf.keras.layers.Conv2D(kernel_size=3, filters=32, padding='same', activation='relu'),
  tf.keras.layers.Conv2D(kernel_size=1, filters=32, padding='same', activation='relu'),
  tf.keras.layers.MaxPooling2D(pool_size=2),
  tf.keras.layers.Conv2D(kernel_size=3, filters=32, padding='same', activation='relu'),
  tf.keras.layers.Conv2D(kernel_size=1, filters=32, padding='same', activation='relu'),
  tf.keras.layers.MaxPooling2D(pool_size=2),
  tf.keras.layers.Conv2D(kernel_size=3, filters=32, padding='same', activation='relu'),
  tf.keras.layers.Conv2D(kernel_size=1, filters=32, padding='same', activation='relu'),
  tf.keras.layers.MaxPooling2D(pool_size=2),
  tf.keras.layers.Conv2D(kernel_size=3, filters=16, padding='same', activation='relu'),
  tf.keras.layers.Conv2D(kernel_size=1, filters=8, padding='same', activation='relu'),
  tf.keras.layers.Flatten(),
  # classifying into 5 categories
  tf.keras.layers.Dense(5, activation='softmax')
])

model.compile(
  optimizer='adam',
  loss= 'categorical_crossentropy',
  metrics=['accuracy'])

9. आपका कस्टम कॉन्वनेट

खुद करके सीखना

आइए, हम स्क्रैच से एक कनवोल्यूशनल न्यूरल नेटवर्क बनाएं और उसे ट्रेन करें. टीपीयू का इस्तेमाल करने से, हमें बहुत तेज़ी से दोहराने की सुविधा मिलेगी. कृपया इस नोटबुक को खोलें, सेल (Shift-ENTER) को एक्ज़ीक्यूट करें, और जहां भी आपको "WORK REQUIRED" लेबल दिखे वहां दिए गए निर्देशों का पालन करें.

c3df49e90e5a654f.png Keras_Flowers_TPU (playground).ipynb

इसका मकसद, ट्रांसफ़र लर्निंग मॉडल की 75% सटीकता से बेहतर नतीजे पाना है. उस मॉडल को फ़ायदा मिला, क्योंकि उसे लाखों इमेज के डेटासेट पर पहले से ही ट्रेन किया गया था. वहीं, हमारे पास सिर्फ़ 3,670 इमेज हैं. क्या कम से कम इसे मैच किया जा सकता है?

ज़्यादा जानकारी

कितनी लेयर हैं और कितनी बड़ी हैं?

लेयर के साइज़ चुनना, विज्ञान से ज़्यादा कला है. आपको पैरामीटर (वज़न और पूर्वाग्रह) की संख्या को कम या ज़्यादा करने के बीच सही संतुलन बनाए रखना होगा. वज़न कम होने की वजह से, न्यूरल नेटवर्क फूलों की जटिल आकृतियों को नहीं दिखा सकता. बहुत ज़्यादा फ़िल्टर इस्तेमाल करने से, मॉडल "ओवरफ़िटिंग" की समस्या से जूझ सकता है. इसका मतलब है कि मॉडल सिर्फ़ ट्रेनिंग के लिए इस्तेमाल की गई इमेज के हिसाब से काम करेगा और नई इमेज के लिए सही नतीजे नहीं दे पाएगा. ज़्यादा पैरामीटर होने पर, मॉडल को ट्रेनिंग देने में भी समय लगेगा. Keras में, model.summary() फ़ंक्शन आपके मॉडल का स्ट्रक्चर और पैरामीटर की संख्या दिखाता है:

Layer (type)                 Output Shape              Param #   
=================================================================
conv2d (Conv2D)              (None, 192, 192, 16)      448       
_________________________________________________________________
conv2d_1 (Conv2D)            (None, 192, 192, 30)      4350      
_________________________________________________________________
max_pooling2d (MaxPooling2D) (None, 96, 96, 30)        0         
_________________________________________________________________
conv2d_2 (Conv2D)            (None, 96, 96, 60)        16260     
_________________________________________________________________
 ... 
_________________________________________________________________
global_average_pooling2d (Gl (None, 130)               0         
_________________________________________________________________
dense (Dense)                (None, 90)                11790     
_________________________________________________________________
dense_1 (Dense)              (None, 5)                 455       
=================================================================
Total params: 300,033
Trainable params: 300,033
Non-trainable params: 0
_________________________________________________________________

कुछ सुझाव:

  • एक से ज़्यादा लेयर होने की वजह से, "डीप" न्यूरल नेटवर्क असरदार होते हैं. फूलों की पहचान करने की इस आसान समस्या के लिए, 5 से 10 लेयर का इस्तेमाल किया जा सकता है.
  • छोटे फ़िल्टर इस्तेमाल करें. आम तौर पर, 3x3 फ़िल्टर हर जगह अच्छे होते हैं.
  • 1x1 फ़िल्टर का भी इस्तेमाल किया जा सकता है. ये सस्ते होते हैं. ये चैनल को "फ़िल्टर" नहीं करते हैं, बल्कि चैनलों के लीनियर कॉम्बिनेशन का हिसाब लगाते हैं. इनकी जगह असली फ़िल्टर का इस्तेमाल करें. ("1x1 कनवोल्यूशन" के बारे में ज़्यादा जानकारी अगले सेक्शन में दी गई है.)
  • इस तरह की क्लासिफ़िकेशन समस्या के लिए, मैक्स-पूलिंग लेयर (या स्ट्राइड >1 वाले कनवोल्यूशन) का इस्तेमाल करके, डेटा को बार-बार डाउनसैंपल करें. आपको इस बात से कोई फ़र्क़ नहीं पड़ता कि फूल कहां है. आपको सिर्फ़ यह जानना है कि वह गुलाब है या डेंडिलियन. इसलिए, x और y की जानकारी मिटाने से कोई फ़र्क़ नहीं पड़ता. साथ ही, छोटे-छोटे हिस्सों को फ़िल्टर करना सस्ता होता है.
  • नेटवर्क के आखिर में, फ़िल्टर की संख्या आम तौर पर क्लास की संख्या के बराबर हो जाती है. ऐसा क्यों होता है? इसके लिए, नीचे "ग्लोबल ऐवरेज पूलिंग" की तरकीब देखें. अगर आपको सैकड़ों क्लास में बांटना है, तो लगातार लेयर में फ़िल्टर की संख्या को धीरे-धीरे बढ़ाएं. पांच क्लास वाले फ़्लावर डेटासेट के लिए, सिर्फ़ पांच फ़िल्टर का इस्तेमाल करना काफ़ी नहीं होगा. ज़्यादातर लेयर में फ़िल्टर की संख्या एक जैसी रखी जा सकती है. उदाहरण के लिए, 32. हालांकि, आखिर में इसे कम किया जा सकता है.
  • फ़ाइनल डेंस लेयर(रों) को प्रोसेस करने में ज़्यादा समय लगता है. इसमें सभी कनवोल्यूशनल लेयर के कुल वज़न से ज़्यादा वज़न हो सकता है. उदाहरण के लिए, 24x24x10 डेटा पॉइंट वाले आखिरी डेटा क्यूब से बहुत अच्छा आउटपुट मिलने के बावजूद, 100 न्यूरॉन वाली डेंस लेयर की लागत 24x24x10x100=5,76, 000 वज़न होगी !!! सोच-समझकर काम करें या ग्लोबल एवरेज पूलिंग का इस्तेमाल करें (नीचे देखें).

ग्लोबल ऐवरेज पूलिंग

कन्वलूशनल न्यूरल नेटवर्क के आखिर में, ज़्यादा मेमोरी लेने वाली डेंस लेयर का इस्तेमाल करने के बजाय, आने वाले डेटा "क्यूब" को अपनी क्लास के हिसाब से कई हिस्सों में बांटा जा सकता है. इसके बाद, उनकी वैल्यू का औसत निकाला जा सकता है. साथ ही, इन वैल्यू को सॉफ़्टमैक्स ऐक्टिवेशन फ़ंक्शन के ज़रिए भेजा जा सकता है. क्लासिफ़िकेशन हेड बनाने के इस तरीके में, वज़न का इस्तेमाल नहीं किया जाता. Keras में, सिंटैक्स tf.keras.layers.GlobalAveragePooling2D(). है

93240029f59df7c2.png

समाधान

यहां समाधान वाली नोटबुक दी गई है. अगर आपको कोई समस्या आ रही है, तो इसका इस्तेमाल किया जा सकता है.

c3df49e90e5a654f.png Keras_Flowers_TPU (solution).ipynb

हमने क्या-क्या बताया

  • 🤔 कनवोल्यूशनल लेयर का इस्तेमाल किया गया
  • 🤓 मैक्स पूलिंग, स्ट्राइड, ग्लोबल एवरेज पूलिंग वगैरह के साथ एक्सपेरिमेंट किया गया...
  • 😀 टीपीयू पर, असल दुनिया के मॉडल को तेज़ी से दोहराया गया

कृपया इस चेकलिस्ट को एक बार ध्यान से पढ़ लें.

10. [जानकारी] मॉडर्न कनवोल्यूशनल आर्किटेक्चर

कम शब्दों में

7968830b57b708c0.png

इलस्ट्रेशन: एक कनवोल्यूशनल "मॉड्यूल". इस समय सबसे अच्छा क्या है ? मैक्स-पूल लेयर के बाद 1x1 कनवोल्यूशनल लेयर या लेयर का कोई अन्य कॉम्बिनेशन ? इन सभी को आज़माएं, नतीजों को एक साथ जोड़ें, और नेटवर्क को फ़ैसला लेने दें. दाईं ओर: ऐसे मॉड्यूल का इस्तेमाल करने वाला " इन्सेप्शन" कनवोल्यूशनल आर्किटेक्चर.

Keras में, ऐसे मॉडल बनाने के लिए "फ़ंक्शनल" मॉडल स्टाइल का इस्तेमाल करना होता है जिनमें डेटा फ़्लो को ब्रांच इन और आउट किया जा सकता है. उदाहरण के लिए:

l = tf.keras.layers # syntax shortcut

y = l.Conv2D(filters=32, kernel_size=3, padding='same',
             activation='relu', input_shape=[192, 192, 3])(x) # x=input image

# module start: branch out
y1 = l.Conv2D(filters=32, kernel_size=1, padding='same', activation='relu')(y)
y3 = l.Conv2D(filters=32, kernel_size=3, padding='same', activation='relu')(y)
y = l.concatenate([y1, y3]) # output now has 64 channels
# module end: concatenation

# many more layers ...

# Create the model by specifying the input and output tensors.
# Keras layers track their connections automatically so that's all that's needed.
z = l.Dense(5, activation='softmax')(y)
model = tf.keras.Model(x, z)

688858c21e3beff2.png

अन्य घटिया तरीके

छोटे 3x3 फ़िल्टर

40a7b15fb7dbe75c.png

इस इलस्ट्रेशन में, लगातार दो 3x3 फ़िल्टर का नतीजा दिखाया गया है. यह पता लगाने की कोशिश करें कि किन डेटा पॉइंट से नतीजा मिला है: ये दो लगातार 3x3 फ़िल्टर, 5x5 क्षेत्र के कुछ कॉम्बिनेशन का हिसाब लगाते हैं. यह ठीक वैसा कॉम्बिनेशन नहीं है जैसा कि 5x5 फ़िल्टर से कैलकुलेट किया जाता है. हालांकि, इसे आज़माया जा सकता है, क्योंकि लगातार दो 3x3 फ़िल्टर, एक 5x5 फ़िल्टर से ज़्यादा किफ़ायती होते हैं.

1x1 कनवोल्यूशन क्या है ?

fd7cac16f8ecb423.png

गणित के हिसाब से, "1x1" कनवोल्यूशन, किसी स्थिरांक से गुणा करने जैसा होता है. यह बहुत काम का कॉन्सेप्ट नहीं है. हालांकि, कनवोल्यूशनल न्यूरल नेटवर्क में, ध्यान रखें कि फ़िल्टर को सिर्फ़ 2D इमेज पर नहीं, बल्कि डेटा क्यूब पर लागू किया जाता है. इसलिए, "1x1" फ़िल्टर, डेटा के 1x1 कॉलम का वेटेड सम (उदाहरण देखें) कंप्यूट करता है. साथ ही, इसे डेटा पर स्लाइड करने पर, आपको इनपुट के चैनलों का लीनियर कॉम्बिनेशन मिलेगा. यह वाकई काम का है. अगर चैनलों को फ़िल्टर करने की अलग-अलग कार्रवाइयों के नतीजों के तौर पर देखा जाए, तो उदाहरण के लिए "नुकीले कान" के लिए एक फ़िल्टर, "मूंछें" के लिए दूसरा फ़िल्टर, और "पतली आंखें" के लिए तीसरा फ़िल्टर. इसके बाद, "1x1" कनवोल्यूशनल लेयर इन सुविधाओं के कई संभावित लीनियर कॉम्बिनेशन का हिसाब लगाएगी. यह "बिल्ली" की तलाश करते समय काम आ सकती है. इसके अलावा, 1x1 लेयर में कम वेट का इस्तेमाल किया जाता है.

11. Squeezenet

इन आइडिया को एक साथ इस्तेमाल करने का आसान तरीका, "Squeezenet" पेपर में दिखाया गया है. लेखकों ने एक बहुत ही सामान्य कनवोल्यूशनल मॉड्यूल डिज़ाइन का सुझाव दिया है. इसमें सिर्फ़ 1x1 और 3x3 कनवोल्यूशनल लेयर का इस्तेमाल किया गया है.

1730ac375379269b.png

इलस्ट्रेशन: "फ़ायर मॉड्यूल" पर आधारित SqueezeNet आर्किटेक्चर. ये एक के बाद एक 1x1 लेयर का इस्तेमाल करते हैं. ये लेयर, वर्टिकल डाइमेंशन में आने वाले डेटा को "स्क्वीज़" करती हैं. इसके बाद, दो पैरलल 1x1 और 3x3 कनवोल्यूशनल लेयर होती हैं, जो डेटा की डेप्थ को फिर से "बढ़ाती" हैं.

खुद करके सीखना

अपनी पिछली नोटबुक में काम जारी रखें और SqueezeNet से मिलता-जुलता कनवोल्यूशनल न्यूरल नेटवर्क बनाएं. आपको मॉडल कोड को Keras "फ़ंक्शनल स्टाइल" में बदलना होगा.

c3df49e90e5a654f.png Keras_Flowers_TPU (playground).ipynb

ज़्यादा जानकारी

इस अभ्यास के लिए, स्क्वीज़नेट मॉड्यूल के लिए हेल्पर फ़ंक्शन को परिभाषित करना फ़ायदेमंद होगा:

def fire(x, squeeze, expand):
  y = l.Conv2D(filters=squeeze, kernel_size=1, padding='same', activation='relu')(x)
  y1 = l.Conv2D(filters=expand//2, kernel_size=1, padding='same', activation='relu')(y)
  y3 = l.Conv2D(filters=expand//2, kernel_size=3, padding='same', activation='relu')(y)
  return tf.keras.layers.concatenate([y1, y3])

# this is to make it behave similarly to other Keras layers
def fire_module(squeeze, expand):
  return lambda x: fire(x, squeeze, expand)

# usage:
x = l.Input(shape=[192, 192, 3])
y = fire_module(squeeze=24, expand=48)(x) # typically, squeeze is less than expand
y = fire_module(squeeze=32, expand=64)(y)
...
model = tf.keras.Model(x, y)

इस बार हमारा लक्ष्य, 80% सटीकता हासिल करना है.

इन तरीकों को आज़माएँ

एक कनवोल्यूशनल लेयर से शुरू करें. इसके बाद, "fire_modules" का इस्तेमाल करें. साथ ही, MaxPooling2D(pool_size=2) लेयर का इस्तेमाल बारी-बारी से करें. नेटवर्क में, मैक्स पूलिंग लेयर की संख्या दो से चार के बीच रखी जा सकती है. साथ ही, मैक्स पूलिंग लेयर के बीच लगातार एक, दो या तीन फ़ायर मॉड्यूल का इस्तेमाल किया जा सकता है.

फ़ायर मॉड्यूल में, "squeeze" पैरामीटर की वैल्यू, "expand" पैरामीटर की वैल्यू से कम होनी चाहिए. ये पैरामीटर, फ़िल्टर की संख्याएं हैं. आम तौर पर, इनकी संख्या 8 से 196 तक हो सकती है. ऐसे आर्किटेक्चर का इस्तेमाल किया जा सकता है जिनमें नेटवर्क के ज़रिए फ़िल्टर की संख्या धीरे-धीरे बढ़ती है. इसके अलावा, ऐसे आर्किटेक्चर का भी इस्तेमाल किया जा सकता है जिनमें सभी फ़ायर मॉड्यूल में फ़िल्टर की संख्या एक जैसी होती है.

उदाहरण के लिए:

x = tf.keras.layers.Input(shape=[*IMAGE_SIZE, 3]) # input is 192x192 pixels RGB

y = tf.keras.layers.Conv2D(kernel_size=3, filters=32, padding='same', activation='relu')(x)
y = fire_module(24, 48)(y)
y = tf.keras.layers.MaxPooling2D(pool_size=2)(y)
y = fire_module(24, 48)(y)
y = tf.keras.layers.MaxPooling2D(pool_size=2)(y)
y = fire_module(24, 48)(y)
y = tf.keras.layers.GlobalAveragePooling2D()(y)
y = tf.keras.layers.Dense(5, activation='softmax')(y)

model = tf.keras.Model(x, y)

इस समय, आपको लग सकता है कि आपके एक्सपेरिमेंट ठीक से काम नहीं कर रहे हैं और 80% सटीकता का लक्ष्य हासिल करना मुश्किल है. अब कुछ और आसान तरकीबें आज़माएं.

बैच नॉर्मलाइज़ेशन

बैच नॉर्म, कन्वर्जेंस की समस्याओं को हल करने में मदद करेगा. अगली वर्कशॉप में, इस तकनीक के बारे में पूरी जानकारी दी जाएगी. फ़िलहाल, इसे ब्लैक बॉक्स "मैजिक" हेल्पर के तौर पर इस्तेमाल करें. इसके लिए, अपने नेटवर्क में हर कनवोल्यूशनल लेयर के बाद यह लाइन जोड़ें. इसमें fire_module फ़ंक्शन के अंदर की लेयर भी शामिल हैं:

y = tf.keras.layers.BatchNormalization(momentum=0.9)(y)
# please adapt the input and output "y"s to whatever is appropriate in your context

हमारे डेटासेट का साइज़ छोटा है. इसलिए, मोमेंटम पैरामीटर की डिफ़ॉल्ट वैल्यू 0.99 से घटाकर 0.9 करनी होगी. फ़िलहाल, इस जानकारी पर ध्यान न दें.

डेटा बढ़ाना

डेटा में कुछ आसान बदलाव करके, आपको कुछ और प्रतिशत पॉइंट मिलेंगे. जैसे, रंगत में बदलावों को बाएं से दाएं फ़्लिप करना:

4ed2958e09b487ca.pngad795b70334e0d6b.png

tf.data.Dataset API की मदद से, TensorFlow में ऐसा करना बहुत आसान है. अपने डेटा के लिए नया ट्रांसफ़ॉर्मेशन फ़ंक्शन तय करें:

def data_augment(image, label):
    image = tf.image.random_flip_left_right(image)
    image = tf.image.random_saturation(image, lower=0, upper=2)
    return image, label

इसके बाद, इसका इस्तेमाल अपने फ़ाइनल डेटा ट्रांसफ़ॉर्मेशन में करें (सेल "training and validation datasets", फ़ंक्शन "get_batched_dataset"):

dataset = dataset.repeat() # existing line
# insert this
if augment_data:
  dataset = dataset.map(data_augment, num_parallel_calls=AUTO)
dataset = dataset.shuffle(2048) # existing line

डेटा को बेहतर बनाने की सुविधा को चालू करना ज़रूरी नहीं है. साथ ही, यह पक्का करने के लिए ज़रूरी कोड जोड़ें कि सिर्फ़ ट्रेनिंग डेटासेट को बेहतर बनाया गया हो. पुष्टि करने वाले डेटासेट को बढ़ाने का कोई मतलब नहीं है.

अब 35 इपॉक में 80% सटीकता हासिल की जा सकती है.

समाधान

यहां समाधान वाली नोटबुक दी गई है. अगर आपको कोई समस्या आ रही है, तो इसका इस्तेमाल किया जा सकता है.

c3df49e90e5a654f.png Keras_Flowers_TPU_squeezenet.ipynb

हमने क्या-क्या बताया

  • 🤔 Keras के "फ़ंक्शनल स्टाइल" मॉडल
  • 🤓 Squeezenet आर्किटेक्चर
  • 🤓 tf.data.datset की मदद से डेटा बढ़ाना

कृपया इस चेकलिस्ट को एक बार ध्यान से पढ़ लें.

12. Xception को फ़ाइन-ट्यून किया गया

सेपरेबल कन्वलूशन

हाल ही में, कनवोल्यूशनल लेयर को लागू करने का एक अलग तरीका लोकप्रिय हो रहा है: डेप्थ-सेपरेबल कनवोल्यूशन. हमें पता है कि यह नाम थोड़ा मुश्किल है, लेकिन इसका कॉन्सेप्ट बहुत आसान है. इन्हें Tensorflow और Keras में tf.keras.layers.SeparableConv2D के तौर पर लागू किया जाता है.

सेपरेबल कनवोल्यूशन भी इमेज पर फ़िल्टर चलाता है. हालांकि, यह इनपुट इमेज के हर चैनल के लिए, वज़न के अलग-अलग सेट का इस्तेमाल करता है. इसके बाद, "1x1 कनवोल्यूशन" होता है. यह डॉट प्रॉडक्ट की एक सीरीज़ है. इससे फ़िल्टर किए गए चैनलों का वेटेड सम मिलता है. हर बार नए वेट के साथ, चैनलों के उतने वेटेज वाले रीकॉम्बिनेशन का हिसाब लगाया जाता है जितने ज़रूरी हैं.

615720b803bf8dda.gif

उदाहरण: सेपरेबल कनवोल्यूशन. पहला चरण: हर चैनल के लिए अलग फ़िल्टर के साथ कनवोल्यूशन. दूसरा चरण: चैनलों का लीनियर रिकॉम्बिनेशन. जब तक आउटपुट चैनलों की मनचाही संख्या नहीं पहुंच जाती, तब तक वज़न के नए सेट के साथ इसे दोहराया जाता है. पहले चरण को भी दोहराया जा सकता है. हर बार नए वेट के साथ, लेकिन ऐसा बहुत कम होता है.

सेपरेबल कनवोल्यूशन का इस्तेमाल, हाल ही के ज़्यादातर कनवोल्यूशनल नेटवर्क आर्किटेक्चर में किया जाता है. जैसे, MobileNetV2, Xception, EfficientNet. वैसे, आपने ट्रांसफ़र लर्निंग के लिए पहले MobileNetV2 का इस्तेमाल किया था.

ये सामान्य कनवोल्यूशन से सस्ते होते हैं और प्रैक्टिस में उतने ही असरदार पाए गए हैं. ऊपर दिए गए उदाहरण के लिए, यहां वज़न की गिनती दी गई है:

कन्वलूशनल लेयर: 4 x 4 x 3 x 5 = 240

सेपरेबल कनवोल्यूशनल लेयर: 4 x 4 x 3 + 3 x 5 = 48 + 15 = 63

हमारा सुझाव है कि पाठक, इस बात का पता लगाएं कि कनवोल्यूशनल लेयर के हर स्टाइल को एक ही तरीके से लागू करने के लिए, कितनी बार गुणा करने की ज़रूरत होती है. सेपरेबल कनवोल्यूशन, छोटे होते हैं और कंप्यूटेशनल तौर पर ज़्यादा असरदार होते हैं.

खुद करके सीखना

"ट्रांसफ़र लर्निंग" प्लेग्राउंड नोटबुक से फिर से शुरू करें. हालांकि, इस बार पहले से ट्रेन किए गए मॉडल के तौर पर Xception को चुनें. Xception में सिर्फ़ सेपरेबल कन्वलूशन का इस्तेमाल किया जाता है. सभी वज़न को ट्रेनिंग के लिए उपलब्ध कराएं. हम प्री-ट्रेन की गई लेयर का इस्तेमाल करने के बजाय, अपने डेटा पर प्री-ट्रेन किए गए वेट को फ़ाइन-ट्यून करेंगे.

c3df49e90e5a654f.png Keras Flowers transfer learning (playground).ipynb

लक्ष्य: 95% से ज़्यादा सटीक जवाब देना (हां, वाकई ऐसा हो सकता है!)

यह आखिरी एक्सरसाइज़ है. इसलिए, इसमें थोड़ा ज़्यादा कोड और डेटा साइंस से जुड़ा काम करना होगा.

फ़ाइन-ट्यूनिंग के बारे में ज़्यादा जानकारी

Xception, tf.keras.application.* में पहले से ट्रेन किए गए स्टैंडर्ड मॉडल में उपलब्ध है इस बार, सभी वज़न को ट्रेनिंग के लिए उपलब्ध रखना न भूलें.

pretrained_model = tf.keras.applications.Xception(input_shape=[*IMAGE_SIZE, 3],
                                                  include_top=False)
pretrained_model.trainable = True

मॉडल को फ़ाइन-ट्यून करते समय अच्छे नतीजे पाने के लिए, आपको लर्निंग रेट पर ध्यान देना होगा. साथ ही, रैंप-अप पीरियड के साथ लर्निंग रेट शेड्यूल का इस्तेमाल करना होगा. इस तरह:

9b1af213b2b36d47.png

स्टैंडर्ड सीखने की दर से शुरू करने पर, मॉडल के पहले से ट्रेन किए गए वेट में रुकावट आएगी. प्रोग्रेसिव स्टार्टिंग से, मॉडल को तब तक सुरक्षित रखा जाता है, जब तक वह आपके डेटा से जुड़ नहीं जाता. इसके बाद, वह उन्हें सही तरीके से बदल सकता है. रैंप के बाद, लर्निंग रेट को स्थिर रखा जा सकता है या उसे तेज़ी से कम किया जा सकता है.

Keras में, सीखने की दर को एक कॉलबैक के ज़रिए तय किया जाता है. इसमें हर युग के लिए सही सीखने की दर का हिसाब लगाया जा सकता है. Keras, हर युग के लिए ऑप्टिमाइज़र को सही सीखने की दर पास करेगा.

def lr_fn(epoch):
  lr = ...
  return lr

lr_callback = tf.keras.callbacks.LearningRateScheduler(lr_fn, verbose=True)

model.fit(..., callbacks=[lr_callback])

समाधान

यहां समाधान वाली नोटबुक दी गई है. अगर आपको कोई समस्या आ रही है, तो इसका इस्तेमाल किया जा सकता है.

c3df49e90e5a654f.png 07_Keras_Flowers_TPU_xception_fine_tuned_best.ipynb

हमने क्या-क्या बताया

  • 🤔 डेप्थ-सेपरेबल कनवोल्यूशन
  • 🤓 सीखने की दर के शेड्यूल
  • 😈 पहले से ट्रेन किए गए मॉडल को बेहतर बनाना.

कृपया इस चेकलिस्ट को एक बार ध्यान से पढ़ लें.

13. बधाई हो!

आपने अपना पहला मॉडर्न कॉन्वलूशनल न्यूरल नेटवर्क बनाया है. साथ ही, टीपीयू की मदद से, उसे कुछ ही मिनटों में 90% से ज़्यादा सटीक नतीजे देने के लिए ट्रेन किया है.

TPU का इस्तेमाल

TPU और GPU, Google Cloud के Vertex AI पर उपलब्ध हैं:

आखिर में, हमें आपके सुझाव/राय/शिकायत का इंतज़ार रहेगा. अगर आपको इस लैब में कोई गड़बड़ी दिखती है या आपको लगता है कि इसे बेहतर बनाया जाना चाहिए, तो कृपया हमें बताएं. GitHub की समस्याओं [ सुझाव/राय देने या शिकायत करने का लिंक] के ज़रिए सुझाव/राय दी जा सकती है या शिकायत की जा सकती है.

HR.png

Martin Görner ID small.jpg
लेखक: मार्टिन गर्नर
Twitter: @martin_gorner