1. शुरू करने से पहले
पिछले कुछ सालों में, TensorFlow.js मॉडल का इस्तेमाल तेज़ी से बढ़ा है. अब कई JavaScript डेवलपर, मौजूदा बेहतरीन मॉडल का इस्तेमाल करना चाहते हैं. साथ ही, उन्हें अपनी इंडस्ट्री के हिसाब से खास डेटा के साथ काम करने के लिए फिर से ट्रेन करना चाहते हैं. किसी मौजूदा मॉडल (इसे अक्सर बेस मॉडल कहा जाता है) को लेकर, उसे मिलते-जुलते लेकिन अलग डोमेन पर इस्तेमाल करने की प्रोसेस को ट्रांसफ़र लर्निंग कहा जाता है.
ट्रांसफ़र लर्निंग के कई फ़ायदे हैं. जैसे, यह पूरी तरह से नए मॉडल से बेहतर है. पहले से ट्रेन किए गए मॉडल से मिली जानकारी को फिर से इस्तेमाल किया जा सकता है. साथ ही, आपको उस नए आइटम के कम उदाहरणों की ज़रूरत होती है जिसे आपको क्लासिफ़ाई करना है. साथ ही, ट्रेनिंग अक्सर काफ़ी तेज़ी से होती है, क्योंकि पूरे नेटवर्क के बजाय सिर्फ़ मॉडल आर्किटेक्चर की आखिरी कुछ लेयर को फिर से ट्रेन करना होता है. इस वजह से, ट्रांसफ़र लर्निंग वेब ब्राउज़र एनवायरमेंट के लिए बहुत सही है. यहां संसाधनों में बदलाव हो सकता है. हालांकि, डेटा को आसानी से इकट्ठा करने के लिए, सेंसर को सीधे तौर पर ऐक्सेस किया जा सकता है.
इस कोडलैब में, आपको खाली कैनवस से वेब ऐप्लिकेशन बनाने का तरीका बताया गया है. इसमें Google की लोकप्रिय वेबसाइट " Teachable Machine" को फिर से बनाया गया है. यह वेबसाइट, एक ऐसा वेब ऐप्लिकेशन बनाने की सुविधा देती है जो काम करता है. इसका इस्तेमाल कोई भी व्यक्ति, वेबकैम से ली गई कुछ उदाहरण इमेज की मदद से, किसी कस्टम ऑब्जेक्ट की पहचान करने के लिए कर सकता है. वेबसाइट को जान-बूझकर कम से कम रखा गया है, ताकि आप इस कोडलैब के मशीन लर्निंग पहलुओं पर फ़ोकस कर सकें. हालांकि, Teachable Machine की ओरिजनल वेबसाइट की तरह ही, UX को बेहतर बनाने के लिए, वेब डेवलपर के तौर पर अपने मौजूदा अनुभव का इस्तेमाल किया जा सकता है.
ज़रूरी शर्तें
यह कोडलैब, वेब डेवलपर के लिए लिखा गया है. ये डेवलपर, TensorFlow.js के पहले से बने मॉडल और एपीआई के बुनियादी इस्तेमाल के बारे में कुछ हद तक जानते हैं. साथ ही, वे TensorFlow.js में ट्रांसफ़र लर्निंग का इस्तेमाल शुरू करना चाहते हैं.
- इस लैब के लिए, यह मान लिया गया है कि आपको TensorFlow.js, HTML5, सीएसएस, और JavaScript की बुनियादी जानकारी है.
अगर आपने TensorFlow.js का इस्तेमाल पहले कभी नहीं किया है, तो पहले यह मुफ़्त कोर्स करें. इसमें मशीन लर्निंग या TensorFlow.js के बारे में कोई भी जानकारी नहीं दी गई है. इसमें आपको छोटे-छोटे चरणों में, ज़रूरी सभी बातें सिखाई गई हैं.
आपको क्या सीखने को मिलेगा
- TensorFlow.js क्या है और आपको इसका इस्तेमाल अपने अगले वेब ऐप्लिकेशन में क्यों करना चाहिए.
- Teachable Machine के उपयोगकर्ता अनुभव को दोहराने वाला आसान एचटीएमएल/सीएसएस /जेएस वेबपेज बनाने का तरीका.
- पहले से ट्रेन किए गए बेस मॉडल, खास तौर पर MobileNet को लोड करने के लिए TensorFlow.js का इस्तेमाल कैसे करें, ताकि इमेज की ऐसी सुविधाएं जनरेट की जा सकें जिनका इस्तेमाल ट्रांसफ़र लर्निंग में किया जा सकता है.
- आपको पहचान करनी है, इसलिए उपयोगकर्ता के वेबकैम से डेटा की कई क्लास इकट्ठा करने का तरीका.
- इमेज की सुविधाओं का इस्तेमाल करने वाला मल्टी-लेयर परसेप्ट्रॉन बनाने और उसे तय करने का तरीका. साथ ही, इन सुविधाओं का इस्तेमाल करके नए ऑब्जेक्ट को क्लासिफ़ाई करने का तरीका.
चलिए, हैकिंग शुरू करते हैं...
आपको इन चीज़ों की ज़रूरत होगी
- हमारा सुझाव है कि आप Glitch.com खाते का इस्तेमाल करें. इसके अलावा, आपके पास वेब सर्वर के ऐसे एनवायरमेंट का इस्तेमाल करने का विकल्प भी है जिसे आप खुद आसानी से चला सकें और उसमें बदलाव कर सकें.
2. TensorFlow.js क्या है?

TensorFlow.js एक ओपन सोर्स मशीन लर्निंग लाइब्रेरी है. यह JavaScript की मदद से कहीं भी रन की जा सकती है. यह Python में लिखी गई ओरिजनल TensorFlow लाइब्रेरी पर आधारित है. इसका मकसद, डेवलपर के अनुभव को फिर से तैयार करना और JavaScript के इकोसिस्टम के लिए एपीआई का सेट तैयार करना है.
इसका इस्तेमाल कहां किया जा सकता है?
JavaScript को आसानी से एक प्लैटफ़ॉर्म से दूसरे प्लैटफ़ॉर्म पर ले जाया जा सकता है. इसलिए, अब एक ही भाषा में कोड लिखा जा सकता है. साथ ही, मशीन लर्निंग को इन सभी प्लैटफ़ॉर्म पर आसानी से लागू किया जा सकता है:
- वैनिला JavaScript का इस्तेमाल करके, वेब ब्राउज़र में क्लाइंट साइड
- Node.js का इस्तेमाल करके, सर्वर साइड और Raspberry Pi जैसे IoT डिवाइसों पर
- Electron का इस्तेमाल करने वाले डेस्कटॉप ऐप्लिकेशन
- React Native का इस्तेमाल करके बनाए गए नेटिव मोबाइल ऐप्लिकेशन
TensorFlow.js, इन सभी एनवायरमेंट में एक से ज़्यादा बैकएंड के साथ काम करता है. जैसे, सीपीयू या WebGL. इस संदर्भ में "बैकएंड" का मतलब सर्वर साइड एनवायरमेंट नहीं है. उदाहरण के लिए, WebGL में एक्ज़ीक्यूशन के लिए बैकएंड, क्लाइंट साइड हो सकता है. ऐसा इसलिए, ताकि यह पक्का किया जा सके कि यह सुविधा काम करती है और तेज़ी से काम करती रहे. फ़िलहाल, TensorFlow.js इन पर काम करता है:
- डिवाइस के ग्राफ़िक्स कार्ड (जीपीयू) पर WebGL एक्ज़ीक्यूशन - यह जीपीयू ऐक्सेलरेटर की मदद से, बड़े मॉडल (साइज़ में 3 एमबी से ज़्यादा) को एक्ज़ीक्यूट करने का सबसे तेज़ तरीका है.
- सीपीयू पर Web Assembly (WASM) को लागू करना - इससे सीपीयू की परफ़ॉर्मेंस को बेहतर बनाया जा सकता है. जैसे, पुरानी जनरेशन के मोबाइल फ़ोन पर. यह छोटे मॉडल (साइज़ में 3 एमबी से कम) के लिए ज़्यादा सही है. ऐसा इसलिए, क्योंकि ग्राफ़िक्स प्रोसेसर पर कॉन्टेंट अपलोड करने में लगने वाले समय की वजह से, WASM के साथ सीपीयू पर WebGL की तुलना में ज़्यादा तेज़ी से काम किया जा सकता है.
- सीपीयू एक्ज़ीक्यूशन - अगर कोई दूसरा एनवायरमेंट उपलब्ध नहीं है, तो फ़ॉलबैक होना चाहिए. यह तीनों में सबसे धीमी है, लेकिन यह हमेशा आपके लिए उपलब्ध रहती है.
ध्यान दें: अगर आपको पता है कि आपको किस डिवाइस पर कोड चलाना है, तो इनमें से किसी एक बैकएंड को फ़ोर्स किया जा सकता है. इसके अलावा, अगर आपने यह जानकारी नहीं दी है, तो TensorFlow.js को आपके लिए फ़ैसला लेने दें.
क्लाइंट साइड की बेहतरीन सुविधाएं
क्लाइंट मशीन पर वेब ब्राउज़र में TensorFlow.js चलाने से कई फ़ायदे मिल सकते हैं.
निजता
डेटा को तीसरे पक्ष के वेब सर्वर पर भेजे बिना, क्लाइंट मशीन पर डेटा को ट्रेन और क्लासिफ़ाई किया जा सकता है. ऐसा हो सकता है कि स्थानीय कानूनों का पालन करने के लिए, इस सुविधा का इस्तेमाल करना ज़रूरी हो. उदाहरण के लिए, जीडीपीआर. इसके अलावा, ऐसा तब भी हो सकता है, जब उपयोगकर्ता को किसी ऐसे डेटा को प्रोसेस करना हो जिसे वह अपने डिवाइस पर रखना चाहता है और तीसरे पक्ष को नहीं भेजना चाहता.
स्पीड
आपको किसी रिमोट सर्वर को डेटा नहीं भेजना होता है. इसलिए, अनुमान लगाने (डेटा को कैटगरी में बांटने की प्रोसेस) की प्रोसेस तेज़ी से हो सकती है. इससे भी अच्छी बात यह है कि अगर उपयोगकर्ता आपको ऐक्सेस देता है, तो आपके पास डिवाइस के सेंसर का सीधा ऐक्सेस होता है. जैसे, कैमरा, माइक्रोफ़ोन, जीपीएस, एक्सलरोमीटर वगैरह.
पहुंच और बड़े पैमाने पर इंटिग्रेशन
आपके भेजे गए लिंक पर दुनिया भर में कोई भी व्यक्ति एक क्लिक में पहुंच सकता है. साथ ही, वह अपने ब्राउज़र में वेब पेज खोलकर, आपके बनाए गए कॉन्टेंट का इस्तेमाल कर सकता है. मशीन लर्निंग सिस्टम का इस्तेमाल करने के लिए, CUDA ड्राइवर और अन्य सुविधाओं के साथ सर्वर साइड Linux को सेटअप करने की ज़रूरत नहीं है.
लागत
सर्वर न होने का मतलब है कि आपको सिर्फ़ सीडीएन के लिए पेमेंट करना होगा. इससे एचटीएमएल, सीएसएस, JS, और मॉडल फ़ाइलों को होस्ट किया जा सकेगा. किसी सर्वर को 24 घंटे चालू रखने (इसमें ग्राफ़िक्स कार्ड भी शामिल हो सकता है) की लागत के मुकाबले, सीडीएन की लागत काफ़ी कम होती है.
सर्वर साइड की सुविधाएं
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 का इस्तेमाल करने पर, आपको अक्सर परफ़ॉर्मेंस में सुधार दिखेगा. ऐसा इसलिए, क्योंकि इसे रनटाइम पर ऑप्टिमाइज़ किया जाएगा. खास तौर पर, किसी भी तरह की प्रीप्रोसेसिंग के लिए. इसका एक बेहतरीन उदाहरण इस केस स्टडी में देखा जा सकता है. इसमें दिखाया गया है कि Hugging Face ने Node.js का इस्तेमाल करके, अपने नैचुरल लैंग्वेज प्रोसेसिंग मॉडल की परफ़ॉर्मेंस को दो गुना कैसे किया.
अब आपको TensorFlow.js के बारे में बुनियादी जानकारी मिल गई है. साथ ही, यह भी पता चल गया है कि इसे कहां इस्तेमाल किया जा सकता है और इसके क्या फ़ायदे हैं. तो चलिए, अब इसका इस्तेमाल शुरू करते हैं!
3. ट्रांसफ़र लर्निंग
ट्रांसफ़र लर्निंग क्या है?
ट्रांसफ़र लर्निंग में, पहले से सीखी गई जानकारी का इस्तेमाल करके, किसी दूसरी लेकिन मिलती-जुलती चीज़ को सीखने में मदद मिलती है.
हम इंसान ऐसा हमेशा करते हैं. आपके दिमाग़ में ज़िंदगी भर के अनुभव मौजूद होते हैं. इनका इस्तेमाल करके, ऐसी नई चीज़ों को पहचाना जा सकता है जिन्हें आपने पहले कभी नहीं देखा. उदाहरण के लिए, इस विलो ट्री को देखें:

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

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

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

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

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

यहां निचली लेयर फ़्रीज़ हो जाती हैं और उन्हें ट्रेन नहीं किया जाता. सिर्फ़ नई क्लासिफ़िकेशन हेड खुद को अपडेट करेगी, ताकि वह बाईं ओर मौजूद पहले से ट्रेन किए गए मॉडल से मिली सुविधाओं के बारे में जान सके.
इस प्रोसेस को ट्रांसफ़र लर्निंग कहा जाता है. Teachable Machine, पर्दे के पीछे यही काम करता है.
यह भी देखा जा सकता है कि नेटवर्क के आखिर में सिर्फ़ मल्टी-लेयर परसेप्ट्रॉन को ट्रेन करने से, यह नेटवर्क बहुत तेज़ी से ट्रेन होता है. ऐसा तब होता है, जब आपको पूरे नेटवर्क को शुरू से ट्रेन करना होता है.
लेकिन, किसी मॉडल के उप-भागों को कैसे ऐक्सेस किया जा सकता है? इसके बारे में जानने के लिए, अगले सेक्शन पर जाएं.
4. TensorFlow Hub - बेस मॉडल
इस्तेमाल करने के लिए सही बेस मॉडल ढूंढना
MobileNet जैसे ज़्यादा बेहतर और लोकप्रिय रिसर्च मॉडल के लिए, TensorFlow हब पर जाएं. इसके बाद, TensorFlow.js के लिए सही मॉडल फ़िल्टर करें. ये मॉडल, MobileNet v3 आर्किटेक्चर का इस्तेमाल करते हैं. इससे आपको यहां दिखाए गए जैसे नतीजे मिलेंगे:

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

यह भी ध्यान दें कि अगर आपको ग्राफ़ फ़ॉर्मैट के बजाय लेयर फ़ॉर्मैट में कोई मॉडल मिलता है, तो आपके पास यह चुनने का विकल्प होता है कि ट्रेनिंग के लिए किन लेयर को फ़्रीज़ करना है और किन लेयर को अनफ़्रीज़ करना है. यह किसी नए टास्क के लिए मॉडल बनाते समय बहुत मददगार हो सकता है. इसे अक्सर "ट्रांसफ़र मॉडल" कहा जाता है. हालांकि, फ़िलहाल इस ट्यूटोरियल के लिए, डिफ़ॉल्ट ग्राफ़ मॉडल टाइप का इस्तेमाल किया जाएगा. ज़्यादातर TF Hub मॉडल इसी टाइप के होते हैं. Layers मॉडल के साथ काम करने के बारे में ज़्यादा जानने के लिए, ज़्यादा से ज़्यादा TensorFlow.js कोर्स देखें.
ट्रांसफ़र लर्निंग के फ़ायदे
पूरे मॉडल आर्किटेक्चर को शुरू से ट्रेन करने के बजाय, ट्रांसफ़र लर्निंग का इस्तेमाल करने के क्या फ़ायदे हैं?
सबसे पहले, ट्रेनिंग में लगने वाला समय. ट्रांसफ़र लर्निंग का इस्तेमाल करने का यह एक मुख्य फ़ायदा है, क्योंकि आपके पास पहले से ही एक ऐसा मॉडल होता है जिसे ट्रेन किया जा चुका होता है और आपको उसी मॉडल को बेहतर बनाना होता है.
दूसरी बात, पहले से हुई ट्रेनिंग की वजह से, आपको उस नई चीज़ के बहुत कम उदाहरण दिखाने पड़ सकते हैं जिसे आपको क्लासिफ़ाई करना है.
अगर आपके पास किसी चीज़ के उदाहरण डेटा को इकट्ठा करने के लिए सीमित समय और संसाधन हैं, तो यह सुविधा आपके लिए बहुत काम की है. साथ ही, अगर आपको ज़्यादा ट्रेनिंग डेटा इकट्ठा करने से पहले, जल्दी से एक प्रोटोटाइप बनाना है, तो यह सुविधा आपके लिए बहुत काम की है. इससे प्रोटोटाइप को ज़्यादा बेहतर बनाया जा सकता है.
कम डेटा की ज़रूरत और छोटे नेटवर्क को तेज़ी से ट्रेन करने की वजह से, ट्रांसफ़र लर्निंग में कम संसाधनों की ज़रूरत होती है. इसलिए, यह ब्राउज़र के लिए बहुत सही है. साथ ही, मॉडल को पूरी तरह से ट्रेन करने में घंटों, दिनों या हफ़्तों के बजाय, आधुनिक मशीन पर सिर्फ़ कुछ सेकंड लगते हैं.
ठीक है! अब आपको ट्रांसफ़र लर्निंग के बारे में पता चल गया है. इसलिए, अब समय है कि आप Teachable Machine का अपना वर्शन बनाएं. आइए, शुरू करें!
5. कोडिंग के लिए सेट अप करना
आपको इन चीज़ों की ज़रूरत होगी
- मॉडर्न वेब ब्राउज़र.
- एचटीएमएल, सीएसएस, JavaScript, और Chrome DevTools की बुनियादी जानकारी (कंसोल आउटपुट देखना).
चलिए कोडिंग शुरू करते हैं
Glitch.com या Codepen.io के लिए, बॉयलरप्लेट टेंप्लेट बनाए गए हैं. इस कोड लैब के लिए, सिर्फ़ एक क्लिक में किसी भी टेंप्लेट को अपनी बुनियादी स्थिति के तौर पर क्लोन किया जा सकता है.
Glitch पर, "remix this" बटन पर क्लिक करके इसे फ़ोर्क करें. इसके बाद, फ़ाइलों का एक नया सेट बनाएं, जिसे बदला जा सकता है.
इसके अलावा, Codepen पर स्क्रीन के सबसे नीचे दाएं कोने में मौजूद, " fork" पर क्लिक करें.
इस बहुत ही आसान स्ट्रक्चर में, आपको ये फ़ाइलें मिलती हैं:
- एचटीएमएल पेज (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 & 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>टैग और ‘status' आईडी वाला<p>टैग जोड़ा है. आपको इसी टैग में जानकारी प्रिंट करनी है, क्योंकि आउटपुट देखने के लिए सिस्टम के अलग-अलग हिस्सों का इस्तेमाल किया जाता है. - आपने ‘webcam’ आईडी वाला
<video>एलिमेंट जोड़ा है. इसमें बाद में वेबकैम स्ट्रीम रेंडर की जाएगी. - आपने पांच
<button>एलिमेंट जोड़े हैं. पहले विकल्प का आईडी ‘enableCam' है. इससे कैमरा चालू होता है. अगले दो बटन में ‘dataCollector’ क्लास है. इससे उन ऑब्जेक्ट के लिए उदाहरण इमेज इकट्ठा की जा सकती हैं जिन्हें पहचानना है. बाद में लिखा गया कोड इस तरह से डिज़ाइन किया जाएगा कि आप इनमें से कोई भी बटन जोड़ सकें. साथ ही, वे अपने-आप काम करेंगे.
ध्यान दें कि इन बटन में, उपयोगकर्ता के तय किए गए एट्रिब्यूट भी होते हैं. इन्हें data-1hot कहा जाता है. इनकी पूर्णांक वैल्यू, पहली क्लास के लिए 0 से शुरू होती है. यह वह संख्यात्मक इंडेक्स है जिसका इस्तेमाल, किसी क्लास के डेटा को दिखाने के लिए किया जाएगा. इस इंडेक्स का इस्तेमाल, आउटपुट क्लास को सही तरीके से एन्कोड करने के लिए किया जाएगा. इसके लिए, स्ट्रिंग के बजाय संख्या का इस्तेमाल किया जाएगा. ऐसा इसलिए, क्योंकि एमएल मॉडल सिर्फ़ संख्याओं के साथ काम कर सकते हैं.
इसमें data-name एट्रिब्यूट भी होता है. इसमें वह नाम होता है जिसे आपको इस क्लास के लिए इस्तेमाल करना है. इससे उपयोगकर्ता को 1 हॉट एन्कोडिंग से मिली संख्यात्मक इंडेक्स वैल्यू के बजाय, ज़्यादा काम का नाम दिया जा सकता है.
आखिर में, आपके पास ट्रेन और रीसेट बटन होता है. डेटा इकट्ठा हो जाने के बाद, ट्रेनिंग की प्रोसेस शुरू करने के लिए ट्रेन बटन पर क्लिक करें. वहीं, ऐप्लिकेशन को रीसेट करने के लिए रीसेट बटन पर क्लिक करें.
- आपने दो
<script>इंपोर्ट भी जोड़े हैं. एक TensorFlow.js के लिए और दूसरा script.js के लिए. script.js को आपको जल्द ही तय करना होगा.
7. शैली जोड़ें
एलिमेंट की डिफ़ॉल्ट सेटिंग
अभी जोड़े गए एचटीएमएल एलिमेंट के लिए स्टाइल जोड़ें, ताकि वे सही तरीके से रेंडर हो सकें. यहां कुछ ऐसी स्टाइल दी गई हैं जिन्हें पोज़िशन और साइज़ के एलिमेंट में सही तरीके से जोड़ा जाता है. कोई खास बात नहीं है. उपयोगकर्ता अनुभव को और बेहतर बनाने के लिए, इसमें बाद में और भी चीज़ें जोड़ी जा सकती हैं. जैसे, आपने Teachable Machine वाले वीडियो में देखा था.
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%;
}
बढ़िया! आपको बस इतना ही करना है. अगर अभी आउटपुट की झलक देखी जाती है, तो यह कुछ इस तरह दिखनी चाहिए:

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 - इस पर क्लिक करने से, enableCam फ़ंक्शन कॉल होता है.
TRAIN_BUTTON - इस पर क्लिक करने से, trainAndPredict फ़ंक्शन कॉल होता है.
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!
}
कोड के बारे में जानकारी:
इसके बाद, मिले हुए बटन पर लूप चलाया जाता है और हर बटन से दो इवेंट लिसनर जोड़े जाते हैं. एक ‘mousedown' के लिए और एक ‘mouseup' के लिए. इससे बटन को दबाए रखने तक सैंपल रिकॉर्ड किए जा सकते हैं. यह डेटा इकट्ठा करने के लिए काम का होता है.
दोनों इवेंट, gatherDataForClass फ़ंक्शन को कॉल करते हैं. इसे आपको बाद में तय करना होगा.
इस समय, आपको मिले क्लास के ऐसे नाम भी CLASS_NAMES ऐरे में पुश किए जा सकते हैं जिन्हें आसानी से पढ़ा जा सकता है. ये नाम, एचटीएमएल बटन एट्रिब्यूट data-name से मिलते हैं.
इसके बाद, कुछ वैरिएबल जोड़ें. इनमें ऐसी अहम जानकारी सेव की जाएगी जिसका इस्तेमाल बाद में किया जाएगा.
script.js
let mobilenet = undefined;
let gatherDataState = STOP_DATA_GATHER;
let videoPlaying = false;
let trainingDataInputs = [];
let trainingDataOutputs = [];
let examplesCount = [];
let predict = false;
आइए, इनके बारे में जानते हैं.
सबसे पहले, आपके पास लोड किए गए mobilenet मॉडल को सेव करने के लिए mobilenet वैरिएबल है. शुरुआत में इसे undefined पर सेट करें.
इसके बाद, आपके पास gatherDataState नाम का एक वैरिएबल है. अगर ‘dataCollector' बटन दबाया जाता है, तो यह बटन के पहले हॉट आईडी में बदल जाता है. इसे एचटीएमएल में तय किया जाता है, ताकि आपको पता चल सके कि उस समय किस तरह का डेटा इकट्ठा किया जा रहा है. शुरुआत में, इसे STOP_DATA_GATHER पर सेट किया जाता है, ताकि बाद में लिखा गया डेटा इकट्ठा करने वाला लूप, कोई भी डेटा इकट्ठा न करे. ऐसा तब होता है, जब कोई बटन नहीं दबाया जा रहा हो.
videoPlaying इस कुकी से यह ट्रैक किया जाता है कि वेबकैम स्ट्रीम लोड हो गई है और चल रही है या नहीं. साथ ही, यह भी ट्रैक किया जाता है कि इसका इस्तेमाल किया जा सकता है या नहीं. शुरुआत में, इसे false पर सेट किया जाता है, क्योंकि जब तक ENABLE_CAM_BUTTON. को नहीं दबाया जाता, तब तक वेबकैम चालू नहीं होता
इसके बाद, दो ऐरे, trainingDataInputs और trainingDataOutputs तय करें. ये कुकी, इकट्ठा किए गए ट्रेनिंग डेटा की वैल्यू सेव करती हैं. ऐसा तब होता है, जब MobileNet के बेस मॉडल से जनरेट की गई इनपुट सुविधाओं और आउटपुट क्लास के लिए, ‘dataCollector' बटन पर क्लिक किया जाता है.
इसके बाद, एक फ़ाइनल ऐरे examplesCount, को तय किया जाता है, ताकि यह ट्रैक किया जा सके कि उदाहरण जोड़ने के बाद, हर क्लास के लिए कितने उदाहरण शामिल किए गए हैं.
आखिर में, आपके पास predict नाम का एक वैरिएबल होता है, जो आपके अनुमान लगाने वाले लूप को कंट्रोल करता है. शुरुआत में, यह false पर सेट होता है. जब तक इसे true पर सेट नहीं किया जाता, तब तक कोई अनुमान नहीं लगाया जा सकता.
अब जब सभी मुख्य वैरिएबल तय कर लिए गए हैं, तो आइए हम पहले से काटे गए MobileNet 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 के दस्तावेज़ से लोड किए जाने वाले मॉडल की जगह की जानकारी होती है.
इसके बाद, await tf.loadGraphModel() का इस्तेमाल करके मॉडल लोड किया जा सकता है. हालांकि, आपको यह ध्यान रखना होगा कि इस Google वेबसाइट से मॉडल लोड करते समय, खास प्रॉपर्टी fromTFHub को true पर सेट किया गया हो. यह सिर्फ़ TF Hub पर होस्ट किए गए मॉडल का इस्तेमाल करने के लिए एक खास मामला है. इसमें इस अतिरिक्त प्रॉपर्टी को सेट करना ज़रूरी है.
लोडिंग पूरी होने के बाद, STATUS एलिमेंट के innerText को मैसेज के साथ सेट किया जा सकता है. इससे आपको यह पता चल पाएगा कि यह सही तरीके से लोड हो गया है और अब डेटा इकट्ठा किया जा सकता है.
अब सिर्फ़ मॉडल को वार्म अप करना बाकी है. इस तरह के बड़े मॉडल का पहली बार इस्तेमाल करने पर, सभी चीज़ें सेट अप होने में थोड़ा समय लग सकता है. इसलिए, मॉडल में शून्य पास करने से, आने वाले समय में किसी भी तरह की रुकावट से बचने में मदद मिलती है. ऐसा तब होता है, जब समय ज़्यादा अहम हो सकता है.
टेंसर को सही तरीके से डिस्पोज़ करने के लिए, tf.zeros() को tf.tidy() में रैप किया जा सकता है. इससे यह पक्का किया जा सकता है कि बैच का साइज़ 1 हो और ऊंचाई और चौड़ाई वही हो जो आपने शुरुआत में कॉन्स्टेंट में तय की थी. आखिर में, आपको कलर चैनल भी तय करने होते हैं. इस मामले में, यह 3 है, क्योंकि मॉडल को आरजीबी इमेज की ज़रूरत होती है.
इसके बाद, answer.shape() का इस्तेमाल करके, वापस लाए गए टेंसर के नतीजे वाले शेप को लॉग करें. इससे आपको यह समझने में मदद मिलेगी कि यह मॉडल, इमेज की कितनी सुविधाओं को जनरेट करता है.
इस फ़ंक्शन को तय करने के बाद, इसे तुरंत कॉल किया जा सकता है. इससे पेज लोड होने पर मॉडल डाउनलोड होना शुरू हो जाएगा.
अगर आपको अभी लाइव झलक देखनी है, तो कुछ समय बाद आपको स्टेटस टेक्स्ट में बदलाव दिखेगा. यह "Awaiting TF.js load" से बदलकर "MobileNet v3 loaded successfully!" हो जाएगा. यह बदलाव नीचे दिखाया गया है. जारी रखने से पहले पक्का करें कि यह काम करता हो.

कंसोल आउटपुट की जांच करके, इस मॉडल से जनरेट होने वाली आउटपुट सुविधाओं का प्रिंट किया गया साइज़ भी देखा जा सकता है. MobileNet मॉडल में शून्य डालने के बाद, आपको [1, 1024] का आकार दिखेगा. पहला आइटम, सिर्फ़ एक बैच साइज़ है. इसमें 1,024 सुविधाएं मिलती हैं. इनका इस्तेमाल, नए ऑब्जेक्ट को कैटगरी में बांटने के लिए किया जा सकता है.
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.sequential मॉडल तय करना होगा. इसके बाद, इसमें मॉडल लेयर जोड़ी जाएंगी.
इसके बाद, इस मॉडल में इनपुट लेयर के तौर पर डेंस लेयर जोड़ें. इसका इनपुट शेप 1024 है, क्योंकि MobileNet v3 की सुविधाओं से मिलने वाले आउटपुट इसी साइज़ के होते हैं. आपने पिछले चरण में, मॉडल के ज़रिए पास किए गए लोगों के बारे में यह जानकारी देखी. इस लेयर में 128 न्यूरॉन हैं, जो ReLU ऐक्टिवेशन फ़ंक्शन का इस्तेमाल करते हैं.
अगर आपको ऐक्टिवेशन फ़ंक्शन और मॉडल लेयर के बारे में नहीं पता है, तो इस वर्कशॉप की शुरुआत में दिए गए कोर्स को पूरा करें. इससे आपको यह समझने में मदद मिलेगी कि ये प्रॉपर्टी बैकग्राउंड में क्या काम करती हैं.
इसके बाद, आउटपुट लेयर जोड़ें. न्यूरॉन की संख्या, उन क्लास की संख्या के बराबर होनी चाहिए जिनके बारे में अनुमान लगाना है. इसके लिए, CLASS_NAMES.length का इस्तेमाल करके यह पता लगाया जा सकता है कि आपको कितनी क्लासिफ़िकेशन करनी हैं. यह संख्या, यूज़र इंटरफ़ेस में मौजूद डेटा इकट्ठा करने वाले बटन की संख्या के बराबर होती है. यह एक क्लासिफ़िकेशन की समस्या है. इसलिए, इस आउटपुट लेयर पर softmax ऐक्टिवेशन का इस्तेमाल किया जाता है. इसका इस्तेमाल तब किया जाना चाहिए, जब रिग्रेशन के बजाय क्लासिफ़िकेशन की समस्याओं को हल करने के लिए मॉडल बनाया जा रहा हो.
अब कंसोल पर नए मॉडल का खास जानकारी प्रिंट करने के लिए, model.summary() प्रिंट करें.
आखिर में, मॉडल को कंपाइल करें, ताकि उसे ट्रेनिंग दी जा सके. यहां ऑप्टिमाइज़र को adam पर सेट किया गया है. अगर CLASS_NAMES.length, 2 के बराबर है, तो नुकसान binaryCrossentropy होगा. अगर क्लासिफ़ाई करने के लिए तीन या उससे ज़्यादा क्लास हैं, तो यह categoricalCrossentropy का इस्तेमाल करेगा. सटीकता से जुड़ी मेट्रिक का अनुरोध भी किया जाता है, ताकि उन्हें बाद में लॉग में मॉनिटर किया जा सके. इससे डीबग करने में मदद मिलती है.
आपको कंसोल में कुछ ऐसा दिखेगा:

ध्यान दें कि इसमें ट्रेनिंग के लिए 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 मॉडल में फ़ीड करने के लिए, इसे 224x224 पिक्सल के साइज़ में बदलना होगा. कम रिज़ॉल्यूशन का अनुरोध करके, कुछ कंप्यूटिंग संसाधनों को भी बचाया जा सकता है. ज़्यादातर कैमरे, इस साइज़ के रिज़ॉल्यूशन के साथ काम करते हैं.
इसके बाद, ऊपर दी गई जानकारी के साथ navigator.mediaDevices.getUserMedia() को कॉल करें. इसके बाद, stream के वापस आने का इंतज़ार करें.constraints stream वापस मिलने के बाद, VIDEO एलिमेंट को stream की srcObject वैल्यू के तौर पर सेट करके, stream चलाया जा सकता है.
आपको VIDEO एलिमेंट पर एक eventListener भी जोड़ना चाहिए, ताकि यह पता चल सके कि stream लोड हो गया है और सही तरीके से चल रहा है.
स्ट्रीम लोड होने के बाद, videoPlaying को सही पर सेट किया जा सकता है. साथ ही, ENABLE_CAM_BUTTON को हटाया जा सकता है, ताकि कोई व्यक्ति उस पर फिर से क्लिक न कर पाए. इसके लिए, ENABLE_CAM_BUTTON की क्लास को "removed" पर सेट करें.
अब अपना कोड चलाएं. इसके बाद, 'कैमरा चालू करें' बटन पर क्लिक करें और वेबकैम का ऐक्सेस दें. अगर पहली बार यह सुविधा इस्तेमाल की जा रही है, तो आपको पेज पर वीडियो एलिमेंट में रेंडर किया गया दिखेगा. यह इस तरह दिखेगा:

ठीक है, अब 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 एट्रिब्यूट की वैल्यू देखें. इसके लिए, एट्रिब्यूट के नाम के साथ data-1hot को कॉल करें. इस मामले में, data-1hot को पैरामीटर के तौर पर इस्तेमाल करें.this.getAttribute() यह एक स्ट्रिंग है. इसलिए, इसे पूर्णांक में बदलने के लिए 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 नाम के वैरिएबल में सेव किया जाता है.
इसके बाद, MobileNet मॉडल के इनपुट के लिए, videoFrameAsTensor वैरिएबल का साइज़ बदलकर सही शेप में करें. tf.image.resizeBilinear() कॉल का इस्तेमाल करें. इसमें, पहले पैरामीटर के तौर पर उस टेंसर को डालें जिसका आकार बदलना है. इसके बाद, उस आकार को डालें जो नई ऊंचाई और चौड़ाई तय करता है. यह आकार, उन स्थिरांकों के हिसाब से तय किया जाता है जिन्हें आपने पहले बनाया था. आखिर में, तीसरे पैरामीटर को पास करके, अलाइन कॉर्नर को सही पर सेट करें, ताकि साइज़ बदलते समय अलाइनमेंट से जुड़ी कोई समस्या न हो. इमेज के साइज़ में बदलाव करने के बाद, उसे resizedTensorFrame नाम के वैरिएबल में सेव किया जाता है.
ध्यान दें कि इस प्रिमिटिव से इमेज का साइज़ बदलने पर, इमेज स्ट्रेच हो जाती है. ऐसा इसलिए होता है, क्योंकि आपके वेबकैम की इमेज का साइज़ 640 x 480 पिक्सल है. वहीं, मॉडल को 224 x 224 पिक्सल की स्क्वेयर इमेज की ज़रूरत होती है.
इस डेमो के लिए, यह ठीक से काम करना चाहिए. हालांकि, इस कोडलैब को पूरा करने के बाद, आपको इस इमेज को क्रॉप करके स्क्वेयर बनाना चाहिए. इससे आपको बाद में बनाए जाने वाले किसी भी प्रोडक्शन सिस्टम के लिए, बेहतर नतीजे मिलेंगे.
इसके बाद, इमेज डेटा को नॉर्मलाइज़ करें. tf.browser.frompixels() का इस्तेमाल करते समय, इमेज का डेटा हमेशा 0 से 255 के बीच होता है. इसलिए, resizedTensorFrame को 255 से भाग देकर यह पक्का किया जा सकता है कि सभी वैल्यू 0 से 1 के बीच हों. MobileNet मॉडल को इनपुट के तौर पर यही वैल्यू चाहिए होती हैं.
आखिर में, कोड के tf.tidy() सेक्शन में, इस सामान्य किए गए टेंसर को लोड किए गए मॉडल के ज़रिए पुश करें. इसके लिए, mobilenet.predict() को कॉल करें. इसमें normalizedTensorFrame के बड़े किए गए वर्शन को expandDims() का इस्तेमाल करके पास करें, ताकि यह 1 का बैच हो. ऐसा इसलिए, क्योंकि मॉडल को प्रोसेस करने के लिए इनपुट के बैच की ज़रूरत होती है.
नतीजा मिलने के बाद, उस नतीजे पर तुरंत squeeze() को कॉल करके, उसे वापस 1D टेंसर में बदला जा सकता है. इसके बाद, उसे वापस करके imageFeatures वैरिएबल को असाइन किया जा सकता है. यह वैरिएबल, tf.tidy() से मिले नतीजे को कैप्चर करता है.
अब आपके पास MobileNet मॉडल से imageFeatures है. इसलिए, उन्हें trainingDataInputs ऐरे में पुश करके रिकॉर्ड किया जा सकता है. यह ऐरे आपने पहले तय किया था.
इस इनपुट के बारे में जानकारी भी रिकॉर्ड की जा सकती है. इसके लिए, मौजूदा gatherDataState को trainingDataOutputs ऐरे में पुश करें.
ध्यान दें कि gatherDataState वैरिएबल को मौजूदा क्लास के उस संख्यात्मक आईडी पर सेट किया गया होगा जिसके लिए डेटा रिकॉर्ड किया जा रहा है. ऐसा तब हुआ होगा, जब पहले से तय किए गए gatherDataForClass() फ़ंक्शन में बटन पर क्लिक किया गया था.
इस चरण में, किसी क्लास के लिए उदाहरणों की संख्या भी बढ़ाई जा सकती है. इसके लिए, सबसे पहले यह देखें कि examplesCount ऐरे में इंडेक्स पहले से शुरू किया गया है या नहीं. अगर यह तय नहीं किया गया है, तो इसे 0 पर सेट करें, ताकि किसी क्लास के संख्यात्मक आईडी के लिए काउंटर को शुरू किया जा सके. इसके बाद, मौजूदा gatherDataState के लिए examplesCount को बढ़ाया जा सकता है.
अब वेब पेज पर STATUS एलिमेंट के टेक्स्ट को अपडेट करें, ताकि हर क्लास के लिए मौजूदा संख्याएं दिखें. इसके लिए, CLASS_NAMES ऐरे में लूप करें और examplesCount में उसी इंडेक्स पर मौजूद डेटा की संख्या के साथ, आसानी से समझा जा सकने वाला नाम प्रिंट करें.
आखिर में, इस फ़ंक्शन को फिर से कॉल करने के लिए, window.requestAnimationFrame() को dataGatherLoop पैरामीटर के तौर पर पास करके कॉल करें. यह वीडियो से फ़्रेम के सैंपल तब तक लेता रहेगा, जब तक बटन के mouseup का पता नहीं चल जाता. इसके बाद, gatherDataState को STOP_DATA_GATHER, पर सेट कर दिया जाएगा. इसके बाद, डेटा इकट्ठा करने का लूप खत्म हो जाएगा.
अब कोड चलाने पर, आपको 'कैमरा चालू करें' बटन पर क्लिक करने का विकल्प मिलेगा. इसके बाद, वेबकैम के लोड होने का इंतज़ार करें. इसके बाद, डेटा की हर क्लास के उदाहरण इकट्ठा करने के लिए, डेटा इकट्ठा करने वाले हर बटन पर क्लिक करके उसे दबाए रखें. यहां आपको दिखेगा कि मैं अपने मोबाइल फ़ोन और हाथ के लिए डेटा इकट्ठा कर रहा हूं.

आपको स्टेटस टेक्स्ट अपडेट होता हुआ दिखेगा, क्योंकि यह सभी टेंसर को मेमोरी में सेव करता है. जैसा कि ऊपर दिए गए स्क्रीन कैप्चर में दिखाया गया है.
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 टाइप के tensor1d में बदलें, ताकि इसे वन हॉट एन्कोडिंग में इस्तेमाल किया जा सके. इसे outputsAsTensor नाम के वैरिएबल में सेव किया जाता है.
इस outputsAsTensor वैरिएबल के साथ tf.oneHot() फ़ंक्शन का इस्तेमाल करें. साथ ही, एन्कोड करने के लिए क्लास की ज़्यादा से ज़्यादा संख्या का इस्तेमाल करें, जो कि सिर्फ़ CLASS_NAMES.length है. आपके वन हॉट एन्कोडेड आउटपुट, अब oneHotOutputs नाम के नए टेंसर में सेव किए जाते हैं.
ध्यान दें कि फ़िलहाल trainingDataInputs, रिकॉर्ड किए गए टेंसर का एक कलेक्शन है. ट्रेनिंग के लिए इनका इस्तेमाल करने के लिए, आपको टेंसर के ऐरे को सामान्य 2D टेंसर में बदलना होगा.
इसके लिए, TensorFlow.js लाइब्रेरी में एक बेहतरीन फ़ंक्शन मौजूद है, जिसे tf.stack() कहा जाता है.
यह फ़ंक्शन, टेंसर के ऐरे को इनपुट के तौर पर लेता है और उन्हें एक साथ स्टैक करता है. इसके बाद, आउटपुट के तौर पर ज़्यादा डाइमेंशन वाला टेंसर जनरेट करता है. इस मामले में, 2D टेंसर दिखाया जाता है. यह एक डाइमेंशन वाले इनपुट का बैच होता है. इसमें रिकॉर्ड की गई सुविधाओं के साथ-साथ, 1024 की लंबाई वाले इनपुट भी शामिल होते हैं. ट्रेनिंग के लिए आपको इसकी ज़रूरत होती है.
इसके बाद, कस्टम मॉडल हेड को ट्रेन करने के लिए await model.fit(). यहां आपको अपने inputsAsTensor वैरिएबल को oneHotOutputs के साथ पास करना होगा. इससे उदाहरण के इनपुट और टारगेट आउटपुट के लिए इस्तेमाल किए जाने वाले ट्रेनिंग डेटा को दिखाया जा सकेगा. तीसरे पैरामीटर के कॉन्फ़िगरेशन ऑब्जेक्ट में, 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 को पास करें. इसके बाद, नतीजे के तौर पर मिले टेंसर को स्क्वीज़ करके, उसे फिर से एक डाइमेंशन वाला बनाया जा सकता है. साथ ही, उसे prediction नाम के वैरिएबल को असाइन किया जा सकता है.
इस prediction की मदद से, argMax() का इस्तेमाल करके उस इंडेक्स का पता लगाया जा सकता है जिसकी वैल्यू सबसे ज़्यादा है. इसके बाद, इस नतीजे वाले टेंसर को arraySync() का इस्तेमाल करके ऐरे में बदला जा सकता है. इससे JavaScript में मौजूद डेटा का पता लगाया जा सकता है, ताकि सबसे ज़्यादा वैल्यू वाले एलिमेंट की पोज़िशन का पता लगाया जा सके. यह वैल्यू, highestIndex नाम के वैरिएबल में सेव की जाती है.
इसी तरह, arraySync() पर सीधे prediction को कॉल करके, अनुमान के भरोसेमंद होने के स्कोर भी पाए जा सकते हैं.
अब आपके पास prediction डेटा की मदद से, STATUS टेक्स्ट को अपडेट करने के लिए ज़रूरी सभी चीज़ें हैं. क्लास के लिए, आसानी से पढ़ी जा सकने वाली स्ट्रिंग पाने के लिए, CLASS_NAMES ऐरे में highestIndex को खोजें. इसके बाद, predictionArray से कॉन्फ़िडेंस वैल्यू पाएं. इसे प्रतिशत के तौर पर ज़्यादा आसानी से पढ़ने के लिए, इसे 100 से गुणा करें और नतीजे में math.floor() जोड़ें.
आखिर में, जब आप तैयार हों, तब window.requestAnimationFrame() का इस्तेमाल करके predictionLoop() को फिर से कॉल करें, ताकि आपको वीडियो स्ट्रीम पर रीयल टाइम में क्लासिफ़िकेशन मिल सके. अगर नए डेटा के साथ किसी नए मॉडल को ट्रेन करने का विकल्प चुना जाता है, तो यह प्रोसेस तब तक जारी रहती है, जब तक 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 सैंपल इकट्ठा करें. इसके बाद, किसी दूसरे ऑब्जेक्ट के लिए क्लास 2 के सैंपल इकट्ठा करें. 'ट्रेन करें' पर क्लिक करें. इसके बाद, कंसोल लॉग देखें, ताकि आपको पता चल सके कि ट्रेनिंग कितनी पूरी हुई है. इसे बहुत तेज़ी से ट्रेन किया जाना चाहिए:

ट्रेनिंग पूरी होने के बाद, कैमरे को ऑब्जेक्ट दिखाएं. इससे आपको लाइव अनुमान मिलेंगे. ये अनुमान, वेब पेज पर सबसे ऊपर मौजूद स्टेटस टेक्स्ट एरिया में प्रिंट किए जाएंगे. अगर आपको समस्या आ रही है, तो मेरे पूरे कोड की जांच करें. इससे आपको पता चलेगा कि आपने कोई कोड कॉपी करना तो नहीं छोड़ दिया है.
17. बधाई हो
बधाई हो! आपने ब्राउज़र में TensorFlow.js का इस्तेमाल करके, ट्रांसफ़र लर्निंग का पहला उदाहरण पूरा कर लिया है.
इसे आज़माएं और अलग-अलग ऑब्जेक्ट पर टेस्ट करें. आपको दिख सकता है कि कुछ ऑब्जेक्ट को पहचानना, दूसरों के मुकाबले ज़्यादा मुश्किल होता है. ऐसा तब होता है, जब वे किसी और ऑब्जेक्ट से मिलते-जुलते हों. इन दोनों के बीच अंतर करने के लिए, आपको ज़्यादा क्लास या ट्रेनिंग डेटा जोड़ना पड़ सकता है.
रीकैप
इस कोडलैब में, आपने इनके बारे में जाना:
- ट्रांसफ़र लर्निंग क्या है और पूरे मॉडल को ट्रेन करने के मुकाबले इसके क्या फ़ायदे हैं.
- TensorFlow Hub से, दोबारा इस्तेमाल किए जा सकने वाले मॉडल पाने का तरीका.
- ट्रांसफ़र लर्निंग के लिए सही वेब ऐप्लिकेशन सेट अप करने का तरीका.
- इमेज की सुविधाएं जनरेट करने के लिए, बेस मॉडल को लोड और इस्तेमाल करने का तरीका.
- एक नई अनुमान लगाने वाली हेड को कैसे ट्रेन करें, ताकि वह वेबकैम की इमेज से कस्टम ऑब्जेक्ट की पहचान कर सके.
- रीयल टाइम में डेटा को कैटगरी में बांटने के लिए, जनरेट किए गए मॉडल का इस्तेमाल कैसे करें.
आगे क्या करना है?
अब आपके पास काम करने के लिए एक बुनियादी ढांचा है. ऐसे में, मशीन लर्निंग मॉडल के इस बॉयलरप्लेट को असल दुनिया में इस्तेमाल करने के लिए, आपके पास कौन-कौनसे क्रिएटिव आइडिया हैं? ऐसा हो सकता है कि आप जिस इंडस्ट्री में काम करते हैं उसमें कोई बड़ा बदलाव करके, अपनी कंपनी के लोगों की मदद करें. इससे वे मॉडल को ट्रेनिंग देकर, रोज़मर्रा के काम में ज़रूरी चीज़ों को क्लासिफ़ाई कर पाएंगे? इसका इस्तेमाल कई तरह से किया जा सकता है.
ज़्यादा जानने के लिए, यह पूरा कोर्स मुफ़्त में करें. इसमें बताया गया है कि इस कोडलैब में मौजूद दोनों मॉडल को एक ही मॉडल में कैसे जोड़ा जाए, ताकि वे ज़्यादा असरदार तरीके से काम कर सकें.
अगर आपको Teachable Machine के ओरिजनल ऐप्लिकेशन के पीछे के सिद्धांत के बारे में ज़्यादा जानना है, तो यह ट्यूटोरियल देखें.
हमारे साथ अपनी बनाई गई चीज़ें शेयर करना
आज आपने जो भी बनाया है उसे अन्य क्रिएटिव कामों के लिए भी आसानी से इस्तेमाल किया जा सकता है. हमारा सुझाव है कि आप कुछ नया और अलग सोचें और हैकिंग जारी रखें.
हमें सोशल मीडिया पर टैग करना न भूलें. इसके लिए, #MadeWithTFJS हैशटैग का इस्तेमाल करें. इससे आपके प्रोजेक्ट को हमारे TensorFlow ब्लॉग या आने वाले इवेंट में शामिल किया जा सकता है. हमें यह देखने में खुशी होगी कि आपने क्या बनाया है.
एक्सप्लोर करने के लिए वेबसाइटें
- TensorFlow.js की आधिकारिक वेबसाइट
- TensorFlow.js के पहले से बने मॉडल
- TensorFlow.js API
- TensorFlow.js Show & Tell — इससे आपको प्रेरणा मिलेगी और यह पता चलेगा कि दूसरों ने क्या बनाया है.