TensorFlow.js: अपनी खुद की "Teachable Machine" बनाएं TensorFlow.js की मदद से ट्रांसफ़र लर्निंग का इस्तेमाल करना

1. शुरू करने से पहले

पिछले कुछ सालों में, TensorFlow.js मॉडल का इस्तेमाल बहुत ज़्यादा बढ़ा हुआ है. साथ ही, कई JavaScript डेवलपर अब सबसे नई टेक्नोलॉजी वाले मौजूदा मॉडल को इस्तेमाल करना चाहते हैं. साथ ही, उन्हें ऐसा कस्टम डेटा इस्तेमाल करना सिखा रहे हैं जो उनकी इंडस्ट्री में यूनीक है. जब कोई मौजूदा मॉडल (जिसे अक्सर बेस मॉडल कहा जाता है) लेकर, उसे एक जैसे, लेकिन अलग डोमेन पर इस्तेमाल करना, ट्रांसफ़र लर्निंग कहा जाता है.

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

यह कोडलैब आपको खाली कैनवस से वेब ऐप्लिकेशन बनाने का तरीका बताता है, ताकि Google की लोकप्रिय " पढ़ाई के लिए मशीन" वेबसाइट. इस वेबसाइट की मदद से, फ़ंक्शनल वेब ऐप्लिकेशन बनाया जा सकता है. इस ऐप्लिकेशन का इस्तेमाल करके, कोई भी उपयोगकर्ता अपने वेबकैम से उदाहरण के तौर पर दी गई कुछ इमेज का इस्तेमाल करके, अपनी पसंद के मुताबिक ऑब्जेक्ट की पहचान कर सकता है. वेबसाइट को जान-बूझकर कम से कम रखा जाता है, ताकि आप इस कोडलैब के मशीन लर्निंग पहलुओं पर फ़ोकस कर सकें. हालांकि, Teachable Machine वेबसाइट की तरह ही, UX को बेहतर बनाने के लिए आपके मौजूदा वेब डेवलपर अनुभव को लागू करने के कई विकल्प मौजूद हैं.

ज़रूरी शर्तें

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

  • इस लैब के लिए, TensorFlow.js, HTML5, सीएसएस, और JavaScript की सामान्य जानकारी का इस्तेमाल किया जाता है.

अगर आपने Tensorflow.js का इस्तेमाल पहले कभी नहीं किया है, तो पहले इस फ़्री ज़ीरो से हीरो कोर्स का इस्तेमाल करें. इसमें मशीन लर्निंग या TensorFlow.js शामिल नहीं है. साथ ही, आपको छोटे-छोटे चरणों में वह सारी जानकारी देता है जिसकी जानकारी आपको चाहिए.

आपको इनके बारे में जानकारी मिलेगी

  • TensorFlow.js क्या है और आपको अपने अगले वेब ऐप्लिकेशन में इसका इस्तेमाल क्यों करना चाहिए.
  • एचटीएमएल/सीएसएस /JS ऐसा आसान वेबपेज बनाने का तरीका जो Teachable Machine उपयोगकर्ता के अनुभव की नकल करता है.
  • ट्रांसफ़र लर्निंग में इस्तेमाल की जा सकने वाली इमेज सुविधाएं जनरेट करने के लिए, पहले से ट्रेन किए गए बेस मॉडल, खास तौर पर MobileNet को लोड करने के लिए, TensorFlow.js का इस्तेमाल करने का तरीका.
  • डेटा की उन अलग-अलग क्लास के लिए, उपयोगकर्ता के वेबकैम से डेटा इकट्ठा करने का तरीका जानें जिनकी आपको पहचान करनी है.
  • एक से ज़्यादा लेयर वाला पर्सेप्शन बनाने और उसे तय करने का तरीका. यह इमेज की सुविधाओं को लेकर, उनका इस्तेमाल करके नए ऑब्जेक्ट की कैटगरी तय करने के बारे में सीखता है.

चलो हैक हो जाते हैं...

आपको इन चीज़ों की ज़रूरत होगी

  • Glitch.com खाता होना चाहिए या आप किसी ऐसे वेब सर्विंग एनवायरमेंट का इस्तेमाल कर सकते हैं जिसमें आप आराम से बदलाव कर सकें और खुद को चला सकें.

2. TensorFlow.js क्या है?

54e81d02971f53e8.png

TensorFlow.js एक ओपन सोर्स मशीन लर्निंग लाइब्रेरी है जो JavaScript की किसी भी जगह पर काम कर सकती है. यह ऐप्लिकेशन, Python में लिखी गई TensorFlow लाइब्रेरी पर आधारित है. इसका मकसद, डेवलपर अनुभव को फिर से तैयार करना और JavaScript नेटवर्क के लिए एपीआई के सेट को फिर से तैयार करना है.

इसका इस्तेमाल कहां किया जा सकता है?

JavaScript की पोर्टेबिलिटी की वजह से, अब एक भाषा में लिखा जा सकता है और इन सभी प्लैटफ़ॉर्म पर मशीन लर्निंग का इस्तेमाल आसानी से किया जा सकता है:

  • वैनिला JavaScript का इस्तेमाल करके वेब ब्राउज़र में क्लाइंट साइड
  • Node.js का इस्तेमाल करके सर्वर साइड और यहां तक कि Raspberry Pi जैसे IoT डिवाइस भी
  • Electronicn का इस्तेमाल करके डेस्कटॉप ऐप्लिकेशन
  • React Native का इस्तेमाल करने वाले नेटिव मोबाइल ऐप्लिकेशन

TensorFlow.js इनमें से हर एक एनवायरमेंट में एक से ज़्यादा बैकएंड के साथ काम करता है. उदाहरण के लिए, यह हार्डवेयर पर आधारित असल एनवायरमेंट है जिन्हें यह सीपीयू या WebGL में एक्ज़ीक्यूट कर सकता है. एक "बैकएंड" का मतलब सर्वर साइड एनवायरमेंट नहीं है - उदाहरण के लिए, WebGL में एक्ज़ीक्यूट करने के लिए बैकएंड क्लाइंट साइड हो सकता है.) फ़िलहाल, TensorFlow.js इनके साथ काम करता है:

  • डिवाइस के ग्राफ़िक्स कार्ड पर WebGL एक्ज़ीक्यूशन (जीपीयू) - यह जीपीयू ऐक्सेलरेशन के साथ बड़े मॉडल (3 एमबी से ज़्यादा साइज़ वाले) को एक्ज़ीक्यूट करने का सबसे तेज़ तरीका है.
  • सीपीयू पर वेब असेंबली (डब्ल्यूएएसएम) का एक्ज़ीक्यूशन - इससे पुराने जनरेशन के मोबाइल फ़ोन समेत सभी डिवाइसों पर सीपीयू की परफ़ॉर्मेंस को बेहतर बनाने में मदद मिलती है. यह उन छोटे मॉडल (3 एमबी से कम के साइज़) के लिए बेहतर है जो ग्राफ़िक्स प्रोसेसर पर कॉन्टेंट अपलोड करने के ओवरहेड की वजह से, WebGL के मुकाबले WASM वाले सीपीयू पर तेज़ी से काम कर सकते हैं.
  • सीपीयू एक्ज़ीक्यूशन - फ़ॉलबैक के लिए कोई भी अन्य एनवायरमेंट उपलब्ध नहीं होना चाहिए. यह तीनों में से सबसे धीमा है, लेकिन आपकी मदद के लिए हमेशा मौजूद है.

ध्यान दें: अगर आपको पता है कि आपको किस डिवाइस पर बैकएंड को लागू करना है, तो इनमें से किसी एक बैकएंड को लागू करने का विकल्प चुनें. अगर आपको यह जानकारी नहीं देनी है, तो TensorFlow.js को यह तय करने की अनुमति दी जा सकती है.

क्लाइंट साइड सुपर पावर

क्लाइंट मशीन पर वेब ब्राउज़र में TensorFlow.js चलाने से कई फ़ायदे मिल सकते हैं, जिन पर गौर किया जा सकता है.

निजता

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

स्पीड

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

पहुंच और स्केल

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

लागत

किसी सर्वर का मतलब नहीं है. आपके एचटीएमएल, सीएसएस, JS, और मॉडल फ़ाइलों को होस्ट करने के लिए, आपको सिर्फ़ सीडीएन के लिए पेमेंट करना होगा. सीडीएन की कीमत, किसी सर्वर (जिसमें ग्राफ़िक कार्ड जुड़ा हो) को 24/7 चालू रखने की तुलना में काफ़ी कम है.

सर्वर साइड की सुविधाएं

TensorFlow.js के Node.js को इस्तेमाल करने से ये सुविधाएं चालू होती हैं.

CUDA की पूरी सहायता

ग्राफ़िक्स कार्ड से तेज़ी लाने के लिए, सर्वर साइड पर आपको NVIDIA CUDA ड्राइवर इंस्टॉल करने होंगे, ताकि TensorFlow, ग्राफ़िक्स कार्ड के साथ काम कर सके (WebGL का इस्तेमाल करने वाले ब्राउज़र के उलट - किसी इंस्टॉल की ज़रूरत नहीं होती). हालांकि, CUDA की पूरी क्षमता की मदद से, ग्राफ़िक्स कार्ड के निचले लेवल की क्षमताओं का पूरा फ़ायदा लिया जा सकता है. इससे ट्रेनिंग और अनुमान लगाने में कम समय लगता है. परफ़ॉर्मेंस और Python TensorFlow की परफ़ॉर्मेंस, दोनों एक जैसी C++ बैकएंड पर काम करती हैं.

मॉडल साइज़

रिसर्च पर आधारित आधुनिक मॉडल के लिए, हो सकता है कि आप बहुत बड़े मॉडल के साथ काम कर रहे हों, यानी जिनका साइज़ गीगाबाइट (जीबी) हो. प्रति ब्राउज़र टैब मेमोरी उपयोग की सीमाओं की वजह से इन मॉडल को वर्तमान में वेब ब्राउज़र में नहीं चलाया जा सकता. इन बड़े मॉडल को चलाने के लिए, Node.js को अपने सर्वर पर इस्तेमाल किया जा सकता है. इसके लिए, आपको हार्डवेयर की खास बातों का पालन करना होगा, ताकि इस तरह के मॉडल को बेहतर तरीके से चलाया जा सके.

आईओटी

Node.js की सुविधा Raspberry Pi जैसे मशहूर सिंगल बोर्ड कंप्यूटर पर काम करती है. इसका मतलब है कि ऐसे डिवाइसों पर भी TensorFlow.js मॉडल चलाए जा सकते हैं.

स्पीड

Node.js को JavaScript में लिखा जाता है. इसका मतलब है कि समय के साथ कंपाइलेशन काफ़ी काम का होता है. इसका मतलब है कि Node.js का इस्तेमाल करने पर आपको अक्सर परफ़ॉर्मेंस में सुधार दिख सकता है, क्योंकि इसे रनटाइम के दौरान ऑप्टिमाइज़ किया जाएगा. खास तौर पर, प्री-प्रोसेसिंग के दौरान ऐसा किया जा सकता है. इसका एक अच्छा उदाहरण इस केस स्टडी में देखा जा सकता है. इसमें दिखाया गया है कि हगिंग फ़ेस ने Node.js का इस्तेमाल करके, नैचुरल लैंग्वेज प्रोसेसिंग मॉडल की परफ़ॉर्मेंस को दोगुना कर दिया है.

अब आपको TensorFlow.js की बुनियादी बातों और इसके कुछ फ़ायदों के बारे में पता है. चलिए, अब इसकी मदद से काम की चीज़ें करना शुरू करते हैं!

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

ट्रांसफ़र लर्निंग क्या है?

ट्रांसफ़र लर्निंग में, पहले से सीखी गई जानकारी का इस्तेमाल करना शामिल होता है. इससे एक अलग, लेकिन मिलती-जुलती चीज़ सीखने में मदद मिलती है.

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

e28070392cd4afb9.png

आप दुनिया के किस हिस्से में हैं, इसके आधार पर हो सकता है कि आपने इस तरह का पेड़ पहले न देखा हो.

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

d9073a0d5df27222.png

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

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

ऐसा ही मोबाइलनेट जैसे ऐडवांस मॉडल की मदद से भी किया जा सकता है. यह एक बहुत ही लोकप्रिय रिसर्च मॉडल है जो 1, 000 अलग-अलग तरह के ऑब्जेक्ट पर इमेज की पहचान कर सकता है. कुत्तों से लेकर कार तक, इसे ImageNet नाम के एक बड़े डेटासेट की मदद से ट्रेनिंग दी गई है. इस डेटासेट में लाखों इमेज को लेबल किया गया है.

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

7d4e1e35c1a89715.gif

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

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

baf4e3d434576106.png

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

369a8a9041c6917d.png

मान लीजिए कि आप जिस नई चीज़ को पहचानने की कोशिश कर रहे हैं वह ऐसी आउटपुट सुविधाओं का भी इस्तेमाल कर सकती है जो पिछले मॉडल ने सीखी है, तो हो सकता है कि उन्हें किसी नए काम के लिए फिर से इस्तेमाल किया जा सकता हो.

ऊपर दिए गए डायग्राम में, इस काल्पनिक मॉडल को अंकों के आधार पर ट्रेनिंग दी गई है. इसलिए, हो सकता है कि अंकों के बारे में जो कुछ भी सीखा गया है उसे a, b, और c जैसे अक्षरों पर भी लागू किया जा सके.

इसलिए, अब नया क्लासिफ़िकेशन हेड जोड़ा जा सकता है, जो इसके बजाय a, b या c का अनुमान लगाने की कोशिश करता है, जैसा कि यहां दिखाया गया है:

db97e5e60ae73bbd.png

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

इस तरह के काम को ट्रांसफ़र लर्निंग कहा जाता है. Teachable Machine ऐप इसी काम को पूरा करती है.

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

हालांकि, मॉडल के सब-पार्ट कैसे इस्तेमाल किए जा सकते हैं? ज़्यादा जानकारी के लिए, अगले सेक्शन पर जाएं.

4. TensorFlow Hub - बेस मॉडल

इस्तेमाल करने के लिए, सही बेस मॉडल ढूंढें

MobileNet जैसे ज़्यादा ऐडवांस और लोकप्रिय रिसर्च मॉडल के लिए, TensorFlow हब पर जाएं. इसके बाद, TensorFlow.js के हिसाब से उन मॉडल के लिए फ़िल्टर करें जो MobileNet v3 आर्किटेक्चर का इस्तेमाल करते हैं. इससे आपको यहां दिखाए गए नतीजे मिलेंगे:

c5dc1420c6238c14.png

ध्यान दें कि इनमें से कुछ नतीजे "इमेज क्लासिफ़िकेशन" टाइप के हैं (हर मॉडल कार्ड के नतीजे के ऊपर बाईं ओर बताया गया है) और अन्य "इमेज फ़ीचर वेक्टर" टाइप की हैं.

ये चित्र फ़ीचर वेक्टर परिणाम मूल रूप से MobileNet के पहले से काटे गए वर्शन हैं जिनका उपयोग आप अंतिम वर्गीकरण के बजाय चित्र सुविधा सदिशों को प्राप्त करने के लिए कर सकते हैं.

इस तरह के मॉडल को अक्सर "आधार मॉडल" कहा जाता है, इसका इस्तेमाल, ट्रांसफ़र लर्निंग के लिए ठीक उसी तरह किया जा सकता है जैसा कि पिछले सेक्शन में दिखाया गया है. इसके लिए, आपको एक नया क्लासिफ़िकेशन हेड जोड़ना होगा और डेटा को अपने डेटा से ट्रेनिंग देनी होगी.

अगली बार, यह देखा जाना चाहिए कि कौनसा बेस मॉडल आपकी पसंद के आधार पर तैयार किया गया है. यह उस बेस मॉडल के लिए है जिसे TensorFlow.js फ़ॉर्मैट में रिलीज़ किया गया है. इनमें से किसी एक फ़ीचर वेक्टर MobileNet v3 मॉडल के लिए पेज खोलने पर, JS दस्तावेज़ देखा जा सकता है कि यह tf.loadGraphModel() का इस्तेमाल करने वाले दस्तावेज़ में दिए गए उदाहरण कोड स्निपेट पर आधारित ग्राफ़ मॉडल के तौर पर उपलब्ध है.

f97d903d2e46924b.png

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

ट्रांसफ़र लर्निंग के फ़ायदे

पूरे मॉडल आर्किटेक्चर को शुरुआत से ट्रेनिंग देने के बजाय, ट्रांसफ़र लर्निंग का इस्तेमाल करने के क्या फ़ायदे हैं?

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

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

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

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

ठीक है! ट्रांसफ़र लर्निंग क्या है, अब आपको पता है कि अब Teachable Machine का अपना वर्शन बनाने का समय आ गया है. आइए, शुरू करें!

5. कोड सेट अप करें

आपको इन चीज़ों की ज़रूरत होगी

  • एक आधुनिक वेब ब्राउज़र.
  • एचटीएमएल, सीएसएस, JavaScript, और Chrome DevTools के बारे में बुनियादी जानकारी (कंसोल आउटपुट देखना).

चलिए, कोडिंग सीखें

शुरू करने के लिए, बॉयलरप्लेट टेंप्लेट बनाए गए हैं. इन्हें Glitch.com या Codepen.io के लिए बनाया गया है. आप बस एक क्लिक करके, इस कोड लैब के लिए किसी भी टेंप्लेट को बेस स्टेट के तौर पर क्लोन कर सकते हैं.

Glitch पर जाकर, "इसे रीमिक्स करें" बटन पर क्लिक करके इसे फ़ोर्क करें और फ़ाइलों का ऐसा नया सेट बनाएं जिसमें बदलाव किया जा सके.

इसके अलावा, कोडपेन पर जाकर, " fork" का इस्तेमाल करें.

यह बहुत ही आसान ढांचा आपको नीचे दी गई फ़ाइलें उपलब्ध कराता है:

  • HTML पेज (index.html)
  • स्टाइलशीट (style.css)
  • हमारे JavaScript कोड (script.js) को लिखने के लिए फ़ाइल

आपकी सुविधा के लिए, TensorFlow.js लाइब्रेरी के लिए एचटीएमएल फ़ाइल में एक अतिरिक्त इंपोर्ट है. यह ऐसा दिखेगा:

index.html

<!-- Import TensorFlow.js library -->
<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs/dist/tf.min.js" type="text/javascript"></script>

इसके अलावा: अपने पसंदीदा वेबएडिटर या काम को स्थानीय तौर पर इस्तेमाल करें

अगर आपको कोड डाउनलोड करके, स्थानीय तौर पर या किसी दूसरे ऑनलाइन एडिटर पर काम करना है, तो ऊपर दी गई तीन फ़ाइलों को एक ही डायरेक्ट्री में बनाएं. इसके बाद, हमारे Glitch बॉयलरप्लेट के कोड को कॉपी करके, हर फ़ाइल में चिपकाएं.

6. ऐप्लिकेशन एचटीएमएल बॉयलरप्लेट

मैं कहां से शुरू करूं?

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

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

index.html खोलें और ऊपर दी गई सुविधाएं सेट अप करने के लिए मौजूदा कोड को नीचे दी गई जानकारी के साथ चिपकाएं:

index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>Transfer Learning - TensorFlow.js</title>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <!-- Import the webpage's stylesheet -->
    <link rel="stylesheet" href="/style.css">
  </head>  
  <body>
    <h1>Make your own "Teachable Machine" using Transfer Learning with MobileNet v3 in TensorFlow.js using saved graph model from TFHub.</h1>
    
    <p id="status">Awaiting TF.js load</p>
    
    <video id="webcam" autoplay muted></video>
    
    <button id="enableCam">Enable Webcam</button>
    <button class="dataCollector" data-1hot="0" data-name="Class 1">Gather Class 1 Data</button>
    <button class="dataCollector" data-1hot="1" data-name="Class 2">Gather Class 2 Data</button>
    <button id="train">Train &amp; Predict!</button>
    <button id="reset">Reset</button>

    <!-- Import TensorFlow.js library -->
    <script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@3.11.0/dist/tf.min.js" type="text/javascript"></script>

    <!-- Import the page's JavaScript to do some stuff -->
    <script type="module" src="/script.js"></script>
  </body>
</html>

इसका विश्लेषण करें

आइए, ऊपर दिए गए कुछ एचटीएमएल कोड को तोड़ते हैं, ताकि आपकी जोड़ी गई कुछ खास चीज़ों को हाइलाइट किया जा सके.

  • आपने पेज के टाइटल के लिए <h1> टैग के साथ-साथ 'स्टेटस' आईडी वाले <p> टैग को जोड़ा है यहां पर आपको जानकारी प्रिंट करनी होगी. ऐसा इसलिए, क्योंकि आउटपुट देखने के लिए सिस्टम के अलग-अलग हिस्सों का इस्तेमाल किया जाता है.
  • आपने 'वेबकैम' आईडी के साथ <video> एलिमेंट जोड़ा है. लाइव स्ट्रीम को बाद में रेंडर किया जा सकता है.
  • आपने 5 <button> एलिमेंट जोड़े हैं. पहला, ‘enableCam’ आईडी वाला से कैमरा चालू हो जाता है. अगले दो बटनों में 'dataCollector' की क्लास होती है, इसकी मदद से, उन ऑब्जेक्ट के लिए इमेज के उदाहरण इकट्ठा किए जा सकते हैं जिन्हें आपको पहचानना है. जिस कोड को बाद में लिखा जाएगा उसे इस तरह से डिज़ाइन किया जाएगा कि आप इन बटन को एक साथ जोड़ सकें. इसके बाद, वे अपने-आप काम करने लगेंगे.

ध्यान दें कि इन बटनों में उपयोगकर्ता की ओर से तय किया गया एक खास एट्रिब्यूट भी होता है, जिसे data-1hot कहते हैं. इसमें पहली क्लास के लिए पूर्णांक की वैल्यू 0 से शुरू होती है. इस संख्यात्मक इंडेक्स का इस्तेमाल किसी खास क्लास के डेटा को दिखाने के लिए किया जाएगा. इंडेक्स का इस्तेमाल, आउटपुट क्लास को स्ट्रिंग के बजाय संख्या के तौर पर सही तरीके से कोड में बदलने के लिए किया जाएगा. ऐसा इसलिए, क्योंकि एमएल मॉडल सिर्फ़ संख्याओं के साथ काम कर सकते हैं.

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

आखिर में, डेटा इकट्ठा होने के बाद ट्रेनिंग की प्रोसेस शुरू करने या ऐप्लिकेशन को रीसेट करने के लिए, आपके पास 'ट्रेन' और 'रीसेट करें' बटन होगा.

  • आपने दो <script> इंपोर्ट भी जोड़े हैं. एक TensorFlow.js के लिए और दूसरा script.js के लिए, जिसे आप जल्द ही तय करेंगे.

7. शैली जोड़ें

एलिमेंट की डिफ़ॉल्ट सेटिंग

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

style.css

body {
  font-family: helvetica, arial, sans-serif;
  margin: 2em;
}

h1 {
  font-style: italic;
  color: #FF6F00;
}


video {
  clear: both;
  display: block;
  margin: 10px;
  background: #000000;
  width: 640px;
  height: 480px;
}

button {
  padding: 10px;
  float: left;
  margin: 5px 3px 5px 10px;
}

.removed {
  display: none;
}

#status {
  font-size:150%;
}

बढ़िया! आपको यही मदद चाहिए थी. अगर आउटपुट की झलक देखी जा रही है, तो वह कुछ ऐसी दिखेगी:

81909685d7566dcb.png

8. JavaScript: मुख्य कॉन्सटेंट और लिसनर

मुख्य स्थिरांक तय करना

सबसे पहले, ऐसे कुछ कॉम्पोनेंट जोड़ें जिनका इस्तेमाल आपको पूरे ऐप्लिकेशन में करना है. सबसे पहले, script.js के कॉन्टेंट को इन कॉन्सटेंट से बदलें:

script.js

const STATUS = document.getElementById('status');
const VIDEO = document.getElementById('webcam');
const ENABLE_CAM_BUTTON = document.getElementById('enableCam');
const RESET_BUTTON = document.getElementById('reset');
const TRAIN_BUTTON = document.getElementById('train');
const MOBILE_NET_INPUT_WIDTH = 224;
const MOBILE_NET_INPUT_HEIGHT = 224;
const STOP_DATA_GATHER = -1;
const CLASS_NAMES = [];

आइए, इन बातों को समझते हैं:

  • STATUS में सिर्फ़ उस पैराग्राफ़ टैग का रेफ़रंस दिया जाता है जिसके लिए आपको स्टेटस अपडेट लिखे जाएंगे.
  • VIDEO में एचटीएमएल वीडियो एलिमेंट का रेफ़रंस होता है, जो वेबकैम फ़ीड को रेंडर करेगा.
  • ENABLE_CAM_BUTTON, RESET_BUTTON, और TRAIN_BUTTON, एचटीएमएल पेज से सभी मुख्य बटन के डीओएम रेफ़रंस हासिल करते हैं.
  • MOBILE_NET_INPUT_WIDTH और MOBILE_NET_INPUT_HEIGHT, MobileNet मॉडल की अनुमानित इनपुट चौड़ाई और ऊंचाई तय करते हैं. इसे फ़ाइल में सबसे ऊपर वाले कॉन्स्टेंट में सेव करके, अगर बाद में किसी दूसरे वर्शन का इस्तेमाल करने का फ़ैसला किया जाता है, तो वैल्यू को कई अलग-अलग जगहों पर बदलने के बजाय, एक बार अपडेट करना आसान हो जाता है.
  • STOP_DATA_GATHER को - 1 पर सेट किया गया है. इससे एक स्टेट वैल्यू सेव हो जाती है. इससे आपको पता चलता है कि उपयोगकर्ता ने वेबकैम फ़ीड से डेटा इकट्ठा करने के बटन पर क्लिक करना कब बंद किया. इस नंबर को ज़्यादा काम का नाम देने से, कोड बाद में पढ़ने लायक हो जाता है.
  • CLASS_NAMES, लुकअप का काम करता है और संभावित क्लास के सुझावों के लिए ऐसे नाम रखता है जिन्हें कोई भी व्यक्ति आसानी से पढ़ सके. इस कलेक्शन में बाद में जानकारी अपने-आप भर जाएगी.

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

मुख्य इवेंट लिसनर जोड़ना

सबसे पहले, मुख्य बटन में क्लिक इवेंट हैंडलर जोड़ें. जैसे:

script.js

ENABLE_CAM_BUTTON.addEventListener('click', enableCam);
TRAIN_BUTTON.addEventListener('click', trainAndPredict);
RESET_BUTTON.addEventListener('click', reset);


function enableCam() {
  // TODO: Fill this out later in the codelab!
}


function trainAndPredict() {
  // TODO: Fill this out later in the codelab!
}


function reset() {
  // TODO: Fill this out later in the codelab!
}

ENABLE_CAM_BUTTON - क्लिक करने पर enabledCam फ़ंक्शन को कॉल करता है.

TRAIN_BUTTON - क्लिक करने पर TrainerAnd को कॉल किया जाता है.

RESET_BUTTON - क्लिक करने पर कॉल रीसेट हो जाते हैं.

आखिर में इस सेक्शन में आपको वे सभी बटन मिल जाएंगे जिनमें 'dataCollector' क्लास है document.querySelectorAll() का इस्तेमाल करके. यह दस्तावेज़ से मिले एलिमेंट का ऐसा कलेक्शन दिखाता है जो मेल खाता है:

script.js

let dataCollectorButtons = document.querySelectorAll('button.dataCollector');
for (let i = 0; i < dataCollectorButtons.length; i++) {
  dataCollectorButtons[i].addEventListener('mousedown', gatherDataForClass);
  dataCollectorButtons[i].addEventListener('mouseup', gatherDataForClass);
  // Populate the human readable names for classes.
  CLASS_NAMES.push(dataCollectorButtons[i].getAttribute('data-name'));
}


function gatherDataForClass() {
  // TODO: Fill this out later in the codelab!
}

कोड के बारे में जानकारी:

इसके बाद, मिले बटन को फिर से इस्तेमाल करें और हर एक बटन में दो इवेंट लिसनर जोड़ें. एक ‘माउसडाउन' के लिए और एक ‘माउसअप' के लिए. इससे, बटन दबाए रहने तक सैंपल रिकॉर्ड किए जा सकते हैं. इससे डेटा इकट्ठा करने में मदद मिलती है.

दोनों इवेंट, gatherDataForClass फ़ंक्शन को कॉल करते हैं, जिसे आप बाद में तय करेंगे.

ऐसा होने पर, एचटीएमएल बटन एट्रिब्यूट के data-name एट्रिब्यूट से CLASS_NAMES कलेक्शन में, ऐसे क्लास के नाम डाले जा सकते हैं जिन्हें कोई भी व्यक्ति आसानी से पढ़ सकता है.

इसके बाद, उन मुख्य चीज़ों को स्टोर करने के लिए कुछ वैरिएबल जोड़ें जिनका बाद में इस्तेमाल किया जाएगा.

script.js

let mobilenet = undefined;
let gatherDataState = STOP_DATA_GATHER;
let videoPlaying = false;
let trainingDataInputs = [];
let trainingDataOutputs = [];
let examplesCount = [];
let predict = false;

आइए, उनके बारे में जानते हैं.

सबसे पहले, लोड किए गए मोबाइलनेट मॉडल को स्टोर करने के लिए, आपके पास mobilenet वैरिएबल होता है. शुरुआत में इसे 'तय नहीं' पर सेट करें.

इसके बाद, आपके पास gatherDataState नाम का एक वैरिएबल होगा. अगर कोई ‘dataCollector’ बटन दबाने पर, यह बटन उस बटन का 1 हॉट आईडी बन जाएगा, जैसा कि एचटीएमएल में बताया गया है. इससे आपको पता चलता है कि उस समय किस तरह का डेटा इकट्ठा किया जा रहा है. शुरुआत में, इसे STOP_DATA_GATHER पर सेट किया जाता है, ताकि बाद में लिखे जाने वाले डेटा को इकट्ठा करने वाले लूप में, कोई भी बटन न दबाए जाने पर कोई डेटा इकट्ठा न हो.

videoPlaying यह ट्रैक करता है कि वेबकैम स्ट्रीम लोड हो गई है और चल रही है या नहीं. यह स्ट्रीम, इस्तेमाल किए जाने के लिए उपलब्ध होती है या नहीं. शुरुआत में, यह false पर सेट रहता है, क्योंकि जब तक ENABLE_CAM_BUTTON. नहीं दबाया जाता, तब तक वेबकैम चालू नहीं होता

इसके बाद, दो सरणियां, trainingDataInputs और trainingDataOutputs तय करें. इनमें इकट्ठा किए गए ट्रेनिंग डेटा की वैल्यू को स्टोर किया जाता है. इसके लिए, आपको ‘dataCollector’ बटन पर क्लिक करना होता है MobileNet के बेस मॉडल से जनरेट की गई इनपुट सुविधाओं के लिए बटन और सैंपल के तौर पर ली गई आउटपुट क्लास के बटन.

इसके बाद, एक आखिरी अरे, examplesCount, तय किया जाता है, ताकि यह ट्रैक किया जा सके कि किसी क्लास को जोड़ने के बाद उसमें कितने उदाहरण शामिल किए गए हैं.

आखिर में, आपके पास predict नाम का एक वैरिएबल होता है, जो आपके अनुमान वाले लूप को कंट्रोल करता है. शुरुआत में इसे false पर सेट किया गया है. जब तक इसे बाद में true पर सेट नहीं किया जाता, तब तक कोई अनुमान नहीं लगाया जा सकता.

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

9. MobileNet के बेस मॉडल को लोड करें

सबसे पहले, loadMobileNetFeatureModel नाम का एक नया फ़ंक्शन तय करें, जैसा कि नीचे दिखाया गया है. यह एक एसिंक्रोनस फ़ंक्शन होना चाहिए, क्योंकि मॉडल को लोड करने की प्रोसेस एसिंक्रोनस होती है:

script.js

/**
 * Loads the MobileNet model and warms it up so ready for use.
 **/
async function loadMobileNetFeatureModel() {
  const URL = 
    'https://tfhub.dev/google/tfjs-model/imagenet/mobilenet_v3_small_100_224/feature_vector/5/default/1';
  
  mobilenet = await tf.loadGraphModel(URL, {fromTFHub: true});
  STATUS.innerText = 'MobileNet v3 loaded successfully!';
  
  // Warm up the model by passing zeros through it once.
  tf.tidy(function () {
    let answer = mobilenet.predict(tf.zeros([1, MOBILE_NET_INPUT_HEIGHT, MOBILE_NET_INPUT_WIDTH, 3]));
    console.log(answer.shape);
  });
}

// Call the function immediately to start loading.
loadMobileNetFeatureModel();

इस कोड में, उस URL को तय किया जाता है जहां TFHub दस्तावेज़ में लोड किया जाने वाला मॉडल मौजूद होता है.

इसके बाद, Google की इस वेबसाइट से मॉडल लोड करते समय, खास प्रॉपर्टी fromTFHub को true पर सेट करने का ध्यान रखते हुए, await tf.loadGraphModel() का इस्तेमाल करके मॉडल को लोड किया जा सकता है. यह सिर्फ़ TF Hub पर होस्ट किए गए मॉडल का इस्तेमाल करने के मामले में अलग है. यहां इस अतिरिक्त प्रॉपर्टी को सेट करना पड़ता है.

लोड होने के बाद, STATUS एलिमेंट के innerText को मैसेज पर सेट किया जा सकता है, ताकि आप देख सकें कि यह ठीक से लोड हुआ है या नहीं. साथ ही, आप डेटा इकट्ठा करने के लिए तैयार हैं.

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

tf.zeros() को tf.tidy() में रैप करके इस्तेमाल किया जा सकता है, ताकि यह पक्का किया जा सके कि टेंसर सही तरीके से नष्ट हों. इस बैच का साइज़ 1 है. साथ ही, शुरुआत में अपने कॉन्सटेंट की सही ऊंचाई और चौड़ाई भी सेट की जा सकती है. अंत में, आप कलर चैनल भी तय करते हैं, जो इस मामले में 3 है क्योंकि मॉडल को RGB इमेज की उम्मीद है.

इसके बाद, answer.shape() का इस्तेमाल करके लौटाए गए टेंसर के आकार को लॉग करें. इससे आपको इस मॉडल से बनने वाली इमेज की सुविधाओं के साइज़ को समझने में मदद मिलेगी.

इस फ़ंक्शन को परिभाषित करने के बाद, पेज लोड पर मॉडल डाउनलोड शुरू करने के लिए इसे तुरंत कॉल किया जा सकता है.

इस समय लाइव झलक देखने पर, आपको कुछ देर बाद स्थिति का टेक्स्ट "TF.js के लोड होने का इंतज़ार है" से बदल जाएगा "MobileNet v3 लोड हो गया!" जैसा कि नीचे दिखाया गया है. जारी रखने से पहले पक्का कर लें कि यह ठीक से काम कर रहा है.

a28b734e190afff.png

इस मॉडल की बनाई जाने वाली आउटपुट सुविधाओं का प्रिंट किया गया साइज़ देखने के लिए, कंसोल आउटपुट की जांच भी की जा सकती है. MobileNet मॉडल के ज़रिए शून्य चलाने के बाद, आपको [1, 1024] का आकार प्रिंट किया हुआ दिखेगा. पहला आइटम सिर्फ़ 1 का बैच साइज़ है और आपको दिखेगा कि वह असल में 1024 सुविधाएं दिखाता है. इन सुविधाओं का इस्तेमाल, नए ऑब्जेक्ट की कैटगरी तय करने में आपकी मदद करने के लिए किया जा सकता है.

10. नया मॉडल हेड तय करें

अब समय आ गया है कि आप अपने मॉडल हेड को तय करें, जो कि एक बहुत ही छोटी-सी लेयर वाली पर्सेप्शन है.

script.js

let model = tf.sequential();
model.add(tf.layers.dense({inputShape: [1024], units: 128, activation: 'relu'}));
model.add(tf.layers.dense({units: CLASS_NAMES.length, activation: 'softmax'}));

model.summary();

// Compile the model with the defined optimizer and specify a loss function to use.
model.compile({
  // Adam changes the learning rate over time which is useful.
  optimizer: 'adam',
  // Use the correct loss function. If 2 classes of data, must use binaryCrossentropy.
  // Else categoricalCrossentropy is used if more than 2 classes.
  loss: (CLASS_NAMES.length === 2) ? 'binaryCrossentropy': 'categoricalCrossentropy', 
  // As this is a classification problem you can record accuracy in the logs too!
  metrics: ['accuracy']  
});

आइए, इस कोड के बारे में जानें. आप एक tf.क्रमिक मॉडल परिभाषित करके शुरुआत करते हैं जिसमें आप मॉडल परतें जोड़ेंगे.

इसके बाद, इस मॉडल में इनपुट लेयर के तौर पर एक सघन लेयर जोड़ें. इसका इनपुट आकार 1024 है, क्योंकि MobileNet v3 की सुविधाओं से मिलने वाले आउटपुट इस साइज़ के हैं. आपने पिछले चरण में मॉडल पास करने के बाद इसके बारे में पता लगाया था. इस लेयर में 128 न्यूरॉन हैं, जो ReLU ऐक्टिवेशन फ़ंक्शन का इस्तेमाल करते हैं.

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

जोड़ने के लिए अगली लेयर, आउटपुट लेयर है. न्यूरॉन की संख्या, उन क्लास की संख्या के बराबर होनी चाहिए जिनका अनुमान लगाने की कोशिश की जा रही है. ऐसा करने के लिए, CLASS_NAMES.length का इस्तेमाल करके यह पता लगाया जा सकता है कि आपको कितनी क्लास की कैटगरी तय करनी हैं. यह यूज़र इंटरफ़ेस में मौजूद, डेटा इकट्ठा करने वाले बटन की संख्या के बराबर होती है. यह एक क्लासिफ़िकेशन की समस्या है, इसलिए इस आउटपुट लेयर पर softmax ऐक्टिवेशन का इस्तेमाल किया जा रहा है. इसका इस्तेमाल, रिग्रेशन के बजाय, क्लासिफ़िकेशन की समस्याओं को हल करने वाला मॉडल बनाने के लिए किया जाना चाहिए.

अब नए तय किए गए मॉडल की खास जानकारी को कंसोल पर प्रिंट करने के लिए, model.summary() प्रिंट करें.

आखिर में, मॉडल को कंपाइल करें, ताकि वह ट्रेनिंग के लिए तैयार रहे. यहां ऑप्टिमाइज़र adam पर सेट है. अगर CLASS_NAMES.length, 2 के बराबर है, तो नुकसान की वैल्यू binaryCrossentropy होगी. इसके अलावा, अगर तीन या उससे ज़्यादा क्लास की कैटगरी तय करनी है, तो categoricalCrossentropy का इस्तेमाल किया जाएगा. सटीक होने की मेट्रिक के लिए भी अनुरोध किया जाता है, ताकि डीबग करने के लिए, बाद में लॉग में उन पर नज़र रखी जा सके.

कंसोल में आपको कुछ ऐसा दिखेगा:

22eaf32286fea4bb.png

ध्यान दें कि इसमें ट्रेनिंग वाले 1,30,000 से ज़्यादा पैरामीटर हैं. हालांकि, यह सामान्य न्यूरॉन की एक सघन परत है, इसलिए यह बहुत तेज़ी से ट्रेनिंग देगा.

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

11. वेबकैम चालू करें

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

script.js

function hasGetUserMedia() {
  return !!(navigator.mediaDevices && navigator.mediaDevices.getUserMedia);
}

function enableCam() {
  if (hasGetUserMedia()) {
    // getUsermedia parameters.
    const constraints = {
      video: true,
      width: 640, 
      height: 480 
    };

    // Activate the webcam stream.
    navigator.mediaDevices.getUserMedia(constraints).then(function(stream) {
      VIDEO.srcObject = stream;
      VIDEO.addEventListener('loadeddata', function() {
        videoPlaying = true;
        ENABLE_CAM_BUTTON.classList.add('removed');
      });
    });
  } else {
    console.warn('getUserMedia() is not supported by your browser');
  }
}

सबसे पहले, hasGetUserMedia() नाम का एक फ़ंक्शन बनाएं. इससे यह पता लगाया जा सकेगा कि ब्राउज़र, मुख्य ब्राउज़र एपीआई प्रॉपर्टी की मौजूदगी की जांच करके getUserMedia() के साथ काम करता है या नहीं.

आपने अभी-अभी enableCam() फ़ंक्शन में जो hasGetUserMedia() फ़ंक्शन इस्तेमाल किया है उसका इस्तेमाल करके देखें कि वह काम करता है या नहीं. अगर ऐसा नहीं है, तो कंसोल में चेतावनी प्रिंट करें.

अगर यह फ़ाइल इसके साथ काम करती है, तो अपने getUserMedia() कॉल के लिए कुछ कंस्ट्रेंट तय करें. जैसे, आपको सिर्फ़ वीडियो स्ट्रीम चाहिए और वीडियो के width का साइज़ 640 पिक्सल और height का साइज़ 480 पिक्सल रखना है. क्यों? वैसे, इससे बड़ा कोई वीडियो नहीं होना चाहिए, क्योंकि MobileNet मॉडल में फ़ीड करने के लिए इसका साइज़ बदलकर 224 x 224 पिक्सल करना होगा. कम रिज़ॉल्यूशन का अनुरोध करके, कंप्यूटिंग के कुछ संसाधनों को सेव भी किया जा सकता है. ज़्यादातर कैमरे इस साइज़ के रिज़ॉल्यूशन पर काम करते हैं.

इसके बाद, ऊपर बताई गई constraints के साथ navigator.mediaDevices.getUserMedia() को कॉल करें. इसके बाद, stream के वापस आने तक इंतज़ार करें. stream के वापस आने के बाद, VIDEO एलिमेंट को उसकी srcObject वैल्यू के तौर पर सेट करके, stream को चलाया जा सकता है.

यह जानने के लिए कि stream कब लोड हो गया है और सही से चल रहा है, आपको VIDEO एलिमेंट में eventListener जोड़ना चाहिए.

स्ट्रीम लोड होने के बाद, videoPlaying को 'सही है' पर सेट किया जा सकता है. साथ ही, ENABLE_CAM_BUTTON को फिर से क्लिक किए जाने से रोकने के लिए, क्लास की क्लास "removed" पर सेट किया जा सकता है.

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

b378eb1affa9b883.png

ठीक है, अब dataCollector बटन क्लिक से निपटने के लिए फ़ंक्शन जोड़ने का समय आ गया है.

12. डेटा कलेक्शन बटन इवेंट हैंडलर

अब gatherDataForClass(). नाम के अपने खाली फ़ंक्शन को भरने का समय आ गया है. आपने कोडलैब की शुरुआत में dataCollector बटन के लिए, इसी को इवेंट हैंडलर फ़ंक्शन असाइन किया था.

script.js

/**
 * Handle Data Gather for button mouseup/mousedown.
 **/
function gatherDataForClass() {
  let classNumber = parseInt(this.getAttribute('data-1hot'));
  gatherDataState = (gatherDataState === STOP_DATA_GATHER) ? classNumber : STOP_DATA_GATHER;
  dataGatherLoop();
}

सबसे पहले, मौजूदा बटन पर data-1hot एट्रिब्यूट की जांच करें. इसके लिए, this.getAttribute() को एट्रिब्यूट के नाम का इस्तेमाल करें. इस मामले में, data-1hot एट्रिब्यूट को पैरामीटर के तौर पर इस्तेमाल करें. यह एक स्ट्रिंग है. इसके बाद, parseInt() का इस्तेमाल करके इसे पूर्णांक पर कास्ट किया जा सकता है और इस नतीजे को classNumber. नाम वाले वैरिएबल को असाइन किया जा सकता है

इसके बाद, gatherDataState वैरिएबल को उसी के हिसाब से सेट करें. अगर मौजूदा gatherDataState, STOP_DATA_GATHER (जिसे -1 पर सेट किया जाता है) के बराबर है, तो इसका मतलब है कि फ़िलहाल कोई डेटा इकट्ठा नहीं किया जा रहा है और यह mousedown इवेंट ट्रिगर हुआ था. gatherDataState को उस classNumber पर सेट करें जो आपको अभी मिला है.

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

आखिर में, dataGatherLoop(), को कॉल करें, जो असल में क्लास के डेटा की रिकॉर्डिंग करता है.

13. डेटा संग्रह

अब, dataGatherLoop() फ़ंक्शन तय करें. इस फ़ंक्शन की मदद से, वेबकैम वीडियो से इमेज का सैंपल लिया जाता है. साथ ही, उन्हें MobileNet मॉडल के ज़रिए पास किया जाता है और उस मॉडल (1024 फ़ीचर वेक्टर) के आउटपुट कैप्चर किए जाते हैं.

इसके बाद, यह उन्हें उस बटन के gatherDataState आईडी के साथ सेव कर देता है जो अभी दबाया जा रहा है, ताकि आपको पता चल सके कि यह डेटा किस क्लास को दिखाता है.

आइए, इसके बारे में जानते हैं:

script.js

function dataGatherLoop() {
  if (videoPlaying && gatherDataState !== STOP_DATA_GATHER) {
    let imageFeatures = tf.tidy(function() {
      let videoFrameAsTensor = tf.browser.fromPixels(VIDEO);
      let resizedTensorFrame = tf.image.resizeBilinear(videoFrameAsTensor, [MOBILE_NET_INPUT_HEIGHT, 
          MOBILE_NET_INPUT_WIDTH], true);
      let normalizedTensorFrame = resizedTensorFrame.div(255);
      return mobilenet.predict(normalizedTensorFrame.expandDims()).squeeze();
    });

    trainingDataInputs.push(imageFeatures);
    trainingDataOutputs.push(gatherDataState);
    
    // Intialize array index element if currently undefined.
    if (examplesCount[gatherDataState] === undefined) {
      examplesCount[gatherDataState] = 0;
    }
    examplesCount[gatherDataState]++;

    STATUS.innerText = '';
    for (let n = 0; n < CLASS_NAMES.length; n++) {
      STATUS.innerText += CLASS_NAMES[n] + ' data count: ' + examplesCount[n] + '. ';
    }
    window.requestAnimationFrame(dataGatherLoop);
  }
}

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

इसके बाद, आगे दिए गए कोड में बनाए गए टेंसर को हटाने के लिए, अपने कोड को tf.tidy() में रैप करें. इस tf.tidy() कोड को लागू करने का नतीजा, imageFeatures नाम के वैरिएबल में सेव किया जाता है.

अब आप tf.browser.fromPixels() का उपयोग करके VIDEO वेबकैम का फ़्रेम पा सकते हैं. इमेज डेटा वाले नतीजे के टेंसर को videoFrameAsTensor वैरिएबल में सेव किया जाता है.

इसके बाद, videoFrameAsTensor वैरिएबल का साइज़ बदलकर, MobileNet मॉडल के इनपुट के हिसाब से साइज़ बदलें. पहले पैरामीटर के रूप में उस टेंसर के साथ tf.image.resizeBilinear() कॉल का इस्तेमाल करें जिसे आपको नया आकार देना है. इसके बाद, पहले से बनाए गए कॉन्सटेंट से तय की गई नई ऊंचाई और चौड़ाई को तय करने वाले आकार का इस्तेमाल करें. आखिर में, तीसरा पैरामीटर पास करके, कोनों को सही पर सेट करें, ताकि साइज़ बदलते समय अलाइनमेंट से जुड़ी किसी भी समस्या से बचा जा सके. साइज़ बदलने का नतीजा, resizedTensorFrame नाम के वैरिएबल में सेव किया जाता है.

ध्यान दें कि इस प्रिमिटिव साइज़ से इमेज को बड़ा किया जाता है, क्योंकि आपकी वेबकैम इमेज का साइज़ 640 x 480 पिक्सल है. साथ ही, मॉडल के लिए 224 x 224 पिक्सल वाली स्क्वेयर इमेज होनी चाहिए.

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

इसके बाद, इमेज डेटा को नॉर्मलाइज़ करें. tf.browser.frompixels() का इस्तेमाल करते समय, इमेज का डेटा हमेशा 0 से 255 की रेंज में होता है. इसलिए, साइज़ बदलने वालेTensorFrame को 255 से भाग दिया जा सकता है, ताकि यह पक्का किया जा सके कि सभी वैल्यू 0 और 1 के बीच हैं. MobileNet मॉडल, इनपुट के तौर पर इसी की उम्मीद करता है.

आखिर में, कोड के tf.tidy() सेक्शन में, इस नॉर्मलाइज़ किए गए टेंसर को mobilenet.predict() कॉल करके लोड किए गए मॉडल में पुश करें, जिसमें expandDims() का इस्तेमाल करके normalizedTensorFrame के बड़े किए गए वर्शन को पास किया जा सकता है, ताकि यह 1 का बैच बन सके, क्योंकि मॉडल को प्रोसेसिंग के लिए इनपुट के बैच की ज़रूरत होती है.

एक बार नतीजा वापस आने पर, उस नतीजे पर तुरंत squeeze() को कॉल किया जा सकता है. ऐसा करके, उसे वापस 1D टेंसर पर स्क्वैश किया जा सकता है. इसके बाद, वापस आकर ऐसे imageFeatures वैरिएबल को असाइन किया जा सकता है जो tf.tidy() से नतीजा कैप्चर करता है.

अब आपके पास MobileNet मॉडल का imageFeatures है, इसलिए उन्हें पहले तय किए गए trainingDataInputs कलेक्शन में पुश करके रिकॉर्ड किया जा सकता है.

आपके पास यह रिकॉर्ड करने का विकल्प भी है कि यह इनपुट क्या है. इसके लिए, मौजूदा gatherDataState को trainingDataOutputs कलेक्शन में भी पुश करें.

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

इस समय, किसी क्लास के लिए दिए गए उदाहरणों की संख्या को भी बढ़ाया जा सकता है. ऐसा करने के लिए, सबसे पहले देखें कि examplesCount कलेक्शन में इंडेक्स पहले शुरू किया गया है या नहीं. अगर यह वैल्यू तय नहीं है, तो किसी क्लास के संख्या वाले आईडी का काउंटर शुरू करने के लिए, इसे 0 पर सेट करें. इसके बाद, मौजूदा gatherDataState के लिए, examplesCount को बढ़ाया जा सकता है.

अब वेब पेज पर STATUS एलिमेंट के टेक्स्ट को अपडेट करें, ताकि हर क्लास के कैप्चर होने की मौजूदा संख्या दिखाई जा सके. ऐसा करने के लिए, CLASS_NAMES कलेक्शन को लूप में चलाएं. इसके बाद, examplesCount में उसी इंडेक्स में मौजूद डेटा की संख्या के साथ उस नाम को प्रिंट करें जिसे कोई भी व्यक्ति आसानी से पढ़ सकता है.

आखिर में, इस फ़ंक्शन को बार-बार कॉल करने के लिए, पैरामीटर के तौर पर dataGatherLoop वाली window.requestAnimationFrame() को कॉल करें. यह बटन, mouseup की पहचान होने तक वीडियो के फ़्रेम का सैंपल देता रहेगा. साथ ही, gatherDataState को STOP_DATA_GATHER, पर सेट किया जाता है. इसके बाद, डेटा इकट्ठा करने की प्रोसेस खत्म हो जाती है.

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

541051644a45131f.gif

आपको अपडेट किया हुआ स्टेटस टेक्स्ट दिखेगा, क्योंकि इसमें सभी टेंसर मेमोरी में सेव होते हैं, जैसा कि ऊपर स्क्रीन कैप्चर में दिखाया गया है.

14. ट्रेनिंग दें और अनुमान लगाएं

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

script.js

async function trainAndPredict() {
  predict = false;
  tf.util.shuffleCombo(trainingDataInputs, trainingDataOutputs);
  let outputsAsTensor = tf.tensor1d(trainingDataOutputs, 'int32');
  let oneHotOutputs = tf.oneHot(outputsAsTensor, CLASS_NAMES.length);
  let inputsAsTensor = tf.stack(trainingDataInputs);
  
  let results = await model.fit(inputsAsTensor, oneHotOutputs, {shuffle: true, batchSize: 5, epochs: 10, 
      callbacks: {onEpochEnd: logProgress} });
  
  outputsAsTensor.dispose();
  oneHotOutputs.dispose();
  inputsAsTensor.dispose();
  predict = true;
  predictLoop();
}

function logProgress(epoch, logs) {
  console.log('Data for epoch ' + epoch, logs);
}

सबसे पहले, predict को false पर सेट करके पक्का करें कि आप किसी भी मौजूदा अनुमान को लागू होने से रोक रहे हैं.

इसके बाद, tf.util.shuffleCombo() का इस्तेमाल करके अपने इनपुट और आउटपुट अरे को शफ़ल करें, ताकि यह पक्का किया जा सके कि उनके क्रम की वजह से ट्रेनिंग में कोई समस्या न हो.

अपने आउटपुट अरे, trainingDataOutputs, को int32 टाइप के टेंसर1d टाइप में बदलें, ताकि यह एक हॉट एन्कोडिंग में इस्तेमाल किए जाने के लिए तैयार रहे. इसे outputsAsTensor नाम वाले वैरिएबल में सेव किया जाता है.

इस outputsAsTensor वैरिएबल के साथ, कोड में बदलने के लिए क्लास की ज़्यादा से ज़्यादा संख्या के साथ tf.oneHot() फ़ंक्शन का इस्तेमाल करें, जो सिर्फ़ CLASS_NAMES.length है. आपके एक हॉट कोड में बदले गए आउटपुट, अब oneHotOutputs नाम के नए टेंसर में सेव किए जाते हैं.

ध्यान दें कि मौजूदा समय में trainingDataInputs, रिकॉर्ड किए गए टेंसर का कलेक्शन है. ट्रेनिंग के लिए इनका इस्तेमाल करने के लिए, आपको टेंसर के कलेक्शन को सामान्य 2D टेंसर में बदलना होगा.

ऐसा करने के लिए, TensorFlow.js लाइब्रेरी में tf.stack() नाम का एक बेहतरीन फ़ंक्शन है,

यह टेंसर की कलेक्शन को लेता है और आउटपुट के तौर पर, हाई डाइमेंशन वाले टेंसर बनाने के लिए, उन्हें एक साथ स्टैक करता है. इस मामले में, टेंसर 2D दिखाया जाता है. यह 1 डाइमेंशन वाले इनपुट का एक बैच है, जिसकी लंबाई 1024 है. इसमें रिकॉर्ड की गई सुविधाएं मौजूद हैं. ट्रेनिंग के लिए इन इनपुट की ज़रूरत है.

इसके बाद, कस्टम मॉडल हेड को ट्रेनिंग देने के लिए await model.fit(). यहां oneHotOutputs के साथ अपना inputsAsTensor वैरिएबल पास किया जाता है, ताकि ट्रेनिंग डेटा को उदाहरण के तौर पर इनपुट और टारगेट आउटपुट के तौर पर इस्तेमाल किया जा सके. तीसरे पैरामीटर के कॉन्फ़िगरेशन ऑब्जेक्ट में, shuffle को true पर सेट करें, 5 का batchSize इस्तेमाल करें और epochs 10 पर सेट करें. इसके बाद, logProgress फ़ंक्शन के लिए onEpochEnd के लिए callback तय करें, जिसे आप जल्द ही तय करेंगे.

आखिर में, बनाए गए टेंसर को नष्ट किया जा सकता है, क्योंकि अब मॉडल तैयार हो गया है. इसके बाद, अनुमानों को फिर से लागू करने के लिए, predict को वापस true पर सेट किया जा सकता है. इसके बाद, लाइव वेबकैम इमेज का अनुमान लगाने के लिए, predictLoop() फ़ंक्शन को कॉल किया जा सकता है.

आप ट्रेनिंग की स्थिति लॉग करने के लिए, logProcess() फ़ंक्शन भी तय कर सकते हैं. इसका इस्तेमाल ऊपर model.fit() में किया जाता है. इससे ट्रेनिंग के हर राउंड के बाद, नतीजों को कंसोल के तौर पर प्रिंट किया जाता है.

आपका काम करीब-करीब पूरा हो गया है! अनुमान लगाने के लिए, predictLoop() फ़ंक्शन जोड़ें.

मुख्य अनुमान लूप

यहां आप मुख्य पूर्वानुमान लूप लागू करते हैं, जो वेबकैम से फ़्रेम का नमूना लेता है और ब्राउज़र में रीयल-टाइम परिणामों के साथ लगातार यह अनुमान लगाता है कि प्रत्येक फ़्रेम में क्या है.

आइए कोड की जांच करें:

script.js

function predictLoop() {
  if (predict) {
    tf.tidy(function() {
      let videoFrameAsTensor = tf.browser.fromPixels(VIDEO).div(255);
      let resizedTensorFrame = tf.image.resizeBilinear(videoFrameAsTensor,[MOBILE_NET_INPUT_HEIGHT, 
          MOBILE_NET_INPUT_WIDTH], true);

      let imageFeatures = mobilenet.predict(resizedTensorFrame.expandDims());
      let prediction = model.predict(imageFeatures).squeeze();
      let highestIndex = prediction.argMax().arraySync();
      let predictionArray = prediction.arraySync();

      STATUS.innerText = 'Prediction: ' + CLASS_NAMES[highestIndex] + ' with ' + Math.floor(predictionArray[highestIndex] * 100) + '% confidence';
    });

    window.requestAnimationFrame(predictLoop);
  }
}

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

इसके बाद, मौजूदा इमेज के लिए इमेज की सुविधाएं ठीक वैसे ही मिल सकती हैं जैसे आपने dataGatherLoop() फ़ंक्शन में की हैं. ज़रूरी है कि आप tf.browser.from pixels() का इस्तेमाल करके वेबकैम से फ़्रेम लें, उसे नॉर्मलाइज़ करें, उसका साइज़ बदलकर 224 x 224 पिक्सल करें, और फिर उस डेटा को MobileNet मॉडल से पास करें. इससे आपको इमेज की नई सुविधाएं मिलेंगी.

हालांकि, अब ट्रेन किए गए मॉडल के predict()फ़ंक्शन के ज़रिए मिले, imageFeatures को पास करके, अनुमान लगाने के लिए उस मॉडल का इस्तेमाल किया जा सकता है जिसे हाल ही में ट्रेनिंग दी गई है. इसके बाद, टेंसर को दबाकर फिर से 1 डाइमेंशन वाला बनाया जा सकता है. साथ ही, इसे prediction वैरिएबल को असाइन किया जा सकता है.

इस prediction की मदद से, argMax() का इस्तेमाल करके सबसे ज़्यादा वैल्यू वाले इंडेक्स को खोजा जा सकता है. इसके बाद, arraySync() का इस्तेमाल करके इस टेंसर को एक कलेक्शन में बदला जा सकता है, ताकि सबसे ज़्यादा वैल्यू वाले एलिमेंट की जगह का पता लगाया जा सके. यह वैल्यू, highestIndex नाम के वैरिएबल में सेव होती है.

इसी तरह, prediction के टेंसर पर सीधे arraySync() को कॉल करके, अनुमानित कॉन्फ़िडेंस स्कोर का अनुमान लगाया जा सकता है.

अब आपके पास prediction डेटा के साथ STATUS टेक्स्ट को अपडेट करने के लिए सारी ज़रूरी जानकारी मौजूद है. क्लास के लिए ऐसी स्ट्रिंग पाएं जिसे कोई भी व्यक्ति आसानी से पढ़ सके. इसके लिए, CLASS_NAMES कलेक्शन में highestIndex खोजें. इसके बाद, predictionArray से कॉन्फ़िडेंस वैल्यू हासिल करें. प्रतिशत के रूप में इसे और भी पढ़ने लायक बनाने के लिए, बस 100 से गुणा करके नतीजे को math.floor() करें.

आखिर में, predictionLoop() को दोबारा कॉल करने के लिए window.requestAnimationFrame() का इस्तेमाल करें. इससे आपको वीडियो स्ट्रीम पर रीयल-टाइम में कैटगरी तय करने की सुविधा मिलेगी. ऐसा तब तक जारी रहेगा, जब तक predict को false पर सेट नहीं किया जाता. ऐसा तब तक होता रहेगा, जब तक कि आप किसी नए मॉडल को नए डेटा के साथ ट्रेनिंग दें.

जो आपको पहेली के आखिरी हिस्से पर ले जाता है. 'रीसेट करें' बटन को लागू करना.

15. 'रीसेट करें' बटन को लागू करना

करीब-करीब पूरा हो गया है! पहेली का आखिरी हिस्सा है रीसेट बटन का इस्तेमाल करके, फिर से शुरू करना. आपके अभी खाली reset() फ़ंक्शन का कोड नीचे दिया गया है. आगे बढ़ें और इसे यहां दिए गए तरीके से अपडेट करें:

script.js

/**
 * Purge data and start over. Note this does not dispose of the loaded 
 * MobileNet model and MLP head tensors as you will need to reuse 
 * them to train a new model.
 **/
function reset() {
  predict = false;
  examplesCount.length = 0;
  for (let i = 0; i < trainingDataInputs.length; i++) {
    trainingDataInputs[i].dispose();
  }
  trainingDataInputs.length = 0;
  trainingDataOutputs.length = 0;
  STATUS.innerText = 'No data collected';
  
  console.log('Tensors in memory: ' + tf.memory().numTensors);
}

सबसे पहले, predict को false पर सेट करके, चल रहे किसी भी सुझाव के लूप को रोकें. इसके बाद, examplesCount कलेक्शन में मौजूद सारा कॉन्टेंट मिटाएं. इसके लिए, इसकी लंबाई 0 पर सेट करें. इसकी मदद से, किसी कलेक्शन में मौजूद सारा कॉन्टेंट आसानी से हटाया जा सकता है.

अब रिकॉर्ड किए गए सभी मौजूदा trainingDataInputs को देखें और पक्का करें कि इसमें मौजूद हर टेंसर का dispose() हो, ताकि मेमोरी फिर से खाली की जा सके. ऐसा इसलिए, क्योंकि JavaScript से कचरा इकट्ठा करने वाले टूल से टेन्सर को साफ़ नहीं किया जाता.

ऐसा करने के बाद, trainingDataInputs और trainingDataOutputs, दोनों कलेक्शन के लिए, अरे की लंबाई को सुरक्षित तरीके से 0 पर सेट किया जा सकता है, ताकि उन्हें भी हटाया जा सके.

आखिर में, STATUS टेक्स्ट को किसी ऐसी जानकारी पर सेट करें जो सही हो. साथ ही, मेमोरी में बचे टेंसर को सनिटी जांच के तौर पर प्रिंट करें.

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

16. इसे आज़माकर देखें

अब Teachable Machine के अपने वर्शन को आज़माने का समय आ गया है!

लाइव झलक पर जाएं, वेबकैम चालू करें, और अपने कमरे में मौजूद किसी ऑब्जेक्ट के लिए, क्लास 1 के कम से कम 30 सैंपल इकट्ठा करें. इसके बाद, दूसरी क्लास के किसी दूसरे ऑब्जेक्ट के लिए भी ऐसा ही करें. इसके बाद, 'ट्रेन' पर क्लिक करें और प्रोग्रेस देखने के लिए कंसोल लॉग देखें. यह ट्रेनिंग काफ़ी जल्दी हो जानी चाहिए:

bf1ac3cc5b15740.gif

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

17. बधाई हो

बधाई हो! आपने अभी-अभी ट्रांसफ़र लर्निंग का अपना पहला उदाहरण ब्राउज़र में उपलब्ध TensorFlow.js का इस्तेमाल करके पूरा किया है.

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

रीकैप

इस कोडलैब में आपने ये सीखा:

  1. ट्रांसफ़र लर्निंग क्या है और एक पूरे मॉडल को ट्रेनिंग देने पर इसके क्या फ़ायदे हैं.
  2. TensorFlow हब से फिर से इस्तेमाल किए जाने वाले मॉडल पाने का तरीका.
  3. ट्रांसफ़र लर्निंग के लिए सही वेब ऐप्लिकेशन कैसे सेट अप करें.
  4. इमेज की सुविधाएं जनरेट करने के लिए, बेस मॉडल को लोड करने और इस्तेमाल करने का तरीका.
  5. ऐसे नए अनुमान वाले हेड को ट्रेनिंग देने का तरीका जो वेबकैम की तस्वीरों से पसंद के मुताबिक बनाए गए ऑब्जेक्ट को पहचान सकता हो.
  6. रीयल टाइम में डेटा को कैटगरी में बांटने के लिए, नतीजों से जुड़े मॉडल का इस्तेमाल कैसे करें.

आगे क्या होगा?

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

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

साथ ही, अगर आपको मशीन ऐप्लिकेशन के मूल सिद्धांत के बारे में ज़्यादा जानकारी चाहिए, तो यह ट्यूटोरियल देखें.

आप जो भी बनाते हैं उसे हमारे साथ शेयर करें

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

अपने प्रोजेक्ट को TensorFlow ब्लॉग या आने वाले इवेंट में दिखाने के लिए, सोशल मीडिया पर #MadeWithTFJS हैशटैग का इस्तेमाल करके हमें टैग करना न भूलें. हम जानना चाहेंगे कि आप क्या बनाते हैं.

इन वेबसाइटों पर पैसे चुकाएं