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

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

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

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

ca8cc21f6838eccc.png

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

  • कस्टम मॉडल को तेज़ी से बनाने के लिए, Keras और टेंसर प्रोसेसिंग यूनिट (टीपीयू) का इस्तेमाल करना.
  • ट्रेनिंग डेटा को असरदार तरीके से लोड करने के लिए, 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 notebook की एक खास सुविधा है. इनके अंदर मौजूद कोड देखने के लिए, इन पर दो बार क्लिक किया जा सकता है. हालांकि, यह आम तौर पर ज़्यादा दिलचस्प नहीं होता. आम तौर पर, ये सहायता या विज़ुअलाइज़ेशन फ़ंक्शन होते हैं. हालांकि, आपको इन सेल को अब भी चलाना होगा, ताकि फ़ंक्शन को अंदर ही अंदर तय किया जा सके.

पुष्टि करना

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 बोर्ड होता है. इस बोर्ड पर चार ड्यूअल-कोर 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 एनवायरमेंट वैरिएबल सेट करें. इसके अलावा, 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 एपीआई का इस्तेमाल किया जाता है. सबसे पहले, हम एपीआई के बारे में जान लेते हैं.

खुद करके

कृपया इस नोटबुक को खोलें, सेल (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 में डेटा सेव करने के लिए, यहां दिए गए हेल्पर फ़ंक्शन का इस्तेमाल किया जा सकता है.

बाइट स्ट्रिंग लिखना

# 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

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

न्यूरॉन, ऐक्टिवेशन, आरईएलयू

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

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 इमेज होती हैं. हर पिक्सल के लिए तीन वैल्यू (RGB) होती हैं.

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

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

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

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

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

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

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

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

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

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. [जानकारी] कनवोल्यूशनल न्यूरल नेटवर्क

कम शब्दों में

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

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 कनवोल्यूशनल लेयर या लेयर का कोई अन्य कॉम्बिनेशन ? इन सभी को आज़माएं, नतीजों को एक साथ जोड़ें, और नेटवर्क को फ़ैसला लेने दें. दाईं ओर: ऐसे मॉड्यूल का इस्तेमाल करने वाला " inception" कनवोल्यूशनल आर्किटेक्चर.

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

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

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

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

c3df49e90e5a654f.png Keras_Flowers_TPU (playground).ipynb

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

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

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% सटीकता हासिल करना है.

ये काम करके देखें

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

फ़ायर मॉड्यूल में, "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.png

ad795b70334e0d6b.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