1. আপনি শুরু করার আগে
TensorFlow.js মডেলের ব্যবহার গত কয়েক বছরে দ্রুতগতিতে বেড়েছে এবং অনেক জাভাস্ক্রিপ্ট ডেভেলপার এখন বিদ্যমান অত্যাধুনিক মডেলগুলি নিতে এবং তাদের শিল্পের জন্য অনন্য কাস্টম ডেটার সাথে কাজ করার জন্য তাদের পুনরায় প্রশিক্ষণ দিতে চাইছে। একটি বিদ্যমান মডেল নেওয়ার কাজ (প্রায়শই একটি বেস মডেল হিসাবে উল্লেখ করা হয়), এবং এটিকে একই রকম কিন্তু ভিন্ন ডোমেনে ব্যবহার করাকে ট্রান্সফার লার্নিং বলা হয়।
সম্পূর্ণ ফাঁকা মডেল থেকে শুরু করে স্থানান্তর শিক্ষার অনেক সুবিধা রয়েছে। আপনি একটি পূর্বের প্রশিক্ষিত মডেল থেকে ইতিমধ্যে শেখা জ্ঞান পুনরায় ব্যবহার করতে পারেন, এবং আপনি যে নতুন আইটেমটি শ্রেণীবদ্ধ করতে চান তার কম উদাহরণ প্রয়োজন। এছাড়াও, পুরো নেটওয়ার্কের পরিবর্তে শুধুমাত্র মডেল আর্কিটেকচারের শেষ কয়েকটি স্তরকে পুনরায় প্রশিক্ষণ দেওয়ার কারণে প্রশিক্ষণ প্রায়শই উল্লেখযোগ্যভাবে দ্রুত হয়। এই কারণে, ট্রান্সফার লার্নিং ওয়েব ব্রাউজার পরিবেশের জন্য খুব উপযুক্ত যেখানে এক্সিকিউশন ডিভাইসের উপর ভিত্তি করে সংস্থানগুলি পরিবর্তিত হতে পারে, কিন্তু সহজ ডেটা অধিগ্রহণের জন্য সেন্সরগুলিতে সরাসরি অ্যাক্সেসও রয়েছে।
এই কোডল্যাবটি আপনাকে দেখায় কিভাবে একটি ফাঁকা ক্যানভাস থেকে একটি ওয়েব অ্যাপ তৈরি করতে হয়, গুগলের জনপ্রিয় " শিক্ষাযোগ্য মেশিন " ওয়েবসাইটটি পুনরায় তৈরি করে৷ ওয়েবসাইটটি আপনাকে একটি কার্যকরী ওয়েব অ্যাপ তৈরি করতে দেয় যা যেকোনো ব্যবহারকারী তাদের ওয়েবক্যাম থেকে কয়েকটি উদাহরণের চিত্র সহ একটি কাস্টম অবজেক্ট চিনতে ব্যবহার করতে পারে। ওয়েবসাইটটি উদ্দেশ্যমূলকভাবে ন্যূনতম রাখা হয়েছে যাতে আপনি এই কোডল্যাবের মেশিন লার্নিং দিকগুলিতে ফোকাস করতে পারেন। মূল Teachable Machine ওয়েবসাইটের মতো, তবে, UX উন্নত করতে আপনার বিদ্যমান ওয়েব ডেভেলপার অভিজ্ঞতা প্রয়োগ করার প্রচুর সুযোগ রয়েছে।
পূর্বশর্ত
এই কোডল্যাবটি ওয়েব ডেভেলপারদের জন্য লেখা হয়েছে যারা TensorFlow.js প্রি-মেড মডেল এবং বেসিক API ব্যবহারের সাথে কিছুটা পরিচিত এবং যারা TensorFlow.js-এ ট্রান্সফার লার্নিং শুরু করতে চান।
- TensorFlow.js, HTML5, CSS, এবং JavaScript-এর সাথে প্রাথমিক পরিচিতি এই ল্যাবের জন্য ধরে নেওয়া হয়।
আপনি যদি Tensorflow.js-এ নতুন হয়ে থাকেন, তাহলে প্রথমে এই বিনামূল্যের জিরো টু হিরো কোর্সটি নেওয়ার কথা বিবেচনা করুন , যা মেশিন লার্নিং বা TensorFlow.js-এর সাথে কোনো ব্যাকগ্রাউন্ড অনুমান করে না এবং ছোট ধাপে আপনার যা জানা দরকার তা শেখায়।
আপনি কি শিখবেন
- TensorFlow.js কি এবং কেন আপনার পরবর্তী ওয়েব অ্যাপে এটি ব্যবহার করা উচিত।
- কীভাবে একটি সরলীকৃত HTML/CSS/JS ওয়েবপেজ তৈরি করবেন যা শিক্ষনীয় মেশিন ব্যবহারকারীর অভিজ্ঞতার প্রতিলিপি করে।
- কিভাবে TensorFlow.js ব্যবহার করবেন একটি প্রাক-প্রশিক্ষিত বেস মডেল লোড করতে, বিশেষ করে MobileNet, ইমেজ ফিচার তৈরি করতে যা ট্রান্সফার লার্নিংয়ে ব্যবহার করা যেতে পারে।
- আপনি চিনতে চান এমন একাধিক শ্রেণীর ডেটার জন্য ব্যবহারকারীর ওয়েবক্যাম থেকে কীভাবে ডেটা সংগ্রহ করবেন।
- কীভাবে একটি মাল্টি-লেয়ার পারসেপ্ট্রন তৈরি এবং সংজ্ঞায়িত করা যায় যা চিত্রের বৈশিষ্ট্যগুলি নেয় এবং সেগুলি ব্যবহার করে নতুন বস্তুকে শ্রেণিবদ্ধ করতে শেখে।
আসুন হ্যাকিং করা যাক...
আপনি কি প্রয়োজন হবে
- একটি Glitch.com অ্যাকাউন্ট অনুসরণ করার জন্য অগ্রাধিকার দেওয়া হয়, অথবা আপনি এমন একটি ওয়েব পরিবেশন পরিবেশ ব্যবহার করতে পারেন যা আপনি সম্পাদনা করতে এবং নিজে চালাতে পারেন৷
2. TensorFlow.js কি?
TensorFlow.js হল একটি ওপেন সোর্স মেশিন লার্নিং লাইব্রেরি যা জাভাস্ক্রিপ্ট যে কোন জায়গায় চালাতে পারে। এটি পাইথনে লেখা মূল TensorFlow লাইব্রেরির উপর ভিত্তি করে তৈরি করা হয়েছে এবং জাভাস্ক্রিপ্ট ইকোসিস্টেমের জন্য এই ডেভেলপার অভিজ্ঞতা এবং API-এর সেট পুনরায় তৈরি করা।
এটা কোথায় ব্যবহার করা যেতে পারে?
জাভাস্ক্রিপ্টের বহনযোগ্যতার কারণে, আপনি এখন 1টি ভাষায় লিখতে পারেন এবং নিচের সমস্ত প্ল্যাটফর্মে সহজেই মেশিন লার্নিং করতে পারেন:
- ভ্যানিলা জাভাস্ক্রিপ্ট ব্যবহার করে ওয়েব ব্রাউজারে ক্লায়েন্ট সাইড
- সার্ভার সাইড এবং এমনকি IoT ডিভাইস যেমন Raspberry Pi Node.js ব্যবহার করে
- ইলেক্ট্রন ব্যবহার করে ডেস্কটপ অ্যাপ
- React Native ব্যবহার করে নেটিভ মোবাইল অ্যাপ
TensorFlow.js এই প্রতিটি পরিবেশের মধ্যে একাধিক ব্যাকএন্ডকেও সমর্থন করে (প্রকৃত হার্ডওয়্যার ভিত্তিক পরিবেশ যা এটি কার্যকর করতে পারে যেমন CPU বা WebGL এর মধ্যে। এই প্রসঙ্গে একটি "ব্যাকএন্ড" মানে সার্ভার সাইড এনভায়রনমেন্ট নয় - এক্সিকিউশনের জন্য ব্যাকএন্ড WebGL-এ ক্লায়েন্ট সাইড হতে পারে উদাহরণস্বরূপ) সামঞ্জস্য নিশ্চিত করতে এবং জিনিসগুলি দ্রুত চলমান রাখতে। বর্তমানে TensorFlow.js সমর্থন করে:
- ডিভাইসের গ্রাফিক্স কার্ডে (GPU) WebGL এক্সিকিউশন - GPU ত্বরণ সহ বড় মডেল (3MB এর বেশি) চালানোর এটি দ্রুততম উপায়।
- CPU-তে ওয়েব অ্যাসেম্বলি (WASM) এক্সিকিউশন - উদাহরণস্বরূপ পুরানো প্রজন্মের মোবাইল ফোন সহ ডিভাইস জুড়ে CPU কর্মক্ষমতা উন্নত করতে। গ্রাফিক্স প্রসেসরে বিষয়বস্তু আপলোড করার ওভারহেডের কারণে ওয়েবজিএল-এর তুলনায় WASM-এর সাথে CPU-তে আসলে WASM-এর সাথে দ্রুত কার্যকর করতে পারে এমন ছোট মডেলগুলির জন্য এটি আরও উপযুক্ত।
- সিপিইউ এক্সিকিউশন - ফলব্যাক অন্য কোনো পরিবেশে পাওয়া উচিত নয়। এটি তিনটির মধ্যে সবচেয়ে ধীর তবে সর্বদা আপনার জন্য রয়েছে।
দ্রষ্টব্য: আপনি এই ব্যাকএন্ডগুলির মধ্যে একটিকে জোর করে বেছে নিতে পারেন যদি আপনি জানেন যে আপনি কোন ডিভাইসে কাজ করবেন, অথবা আপনি যদি এটি নির্দিষ্ট না করেন তবে আপনি কেবল TensorFlow.js কে আপনার জন্য সিদ্ধান্ত নিতে দিতে পারেন।
ক্লায়েন্ট সাইড সুপার পাওয়ার
ক্লায়েন্ট মেশিনে ওয়েব ব্রাউজারে TensorFlow.js চালানোর ফলে বেশ কিছু সুবিধা হতে পারে যা বিবেচনা করার মতো।
গোপনীয়তা
আপনি 3য় পক্ষের ওয়েব সার্ভারে কখনও ডেটা না পাঠিয়ে ক্লায়েন্ট মেশিনে ডেটা প্রশিক্ষণ এবং শ্রেণিবদ্ধ করতে পারেন। এমন কিছু সময় থাকতে পারে যেখানে স্থানীয় আইন মেনে চলার জন্য এটির প্রয়োজন হতে পারে, যেমন GDPR, অথবা কোনো ডেটা প্রক্রিয়া করার সময় যা ব্যবহারকারী তাদের মেশিনে রাখতে চান এবং তৃতীয় পক্ষের কাছে পাঠানো হয়নি।
গতি
যেহেতু আপনাকে দূরবর্তী সার্ভারে ডেটা পাঠাতে হবে না, অনুমান (ডেটা শ্রেণীবদ্ধ করার কাজ) দ্রুত হতে পারে। আরও ভাল, আপনার ডিভাইসের সেন্সর যেমন ক্যামেরা, মাইক্রোফোন, জিপিএস, অ্যাক্সিলোমিটার এবং আরও অনেক কিছুতে আপনার সরাসরি অ্যাক্সেস আছে ব্যবহারকারী আপনাকে অ্যাক্সেস দেওয়ার অনুমতি দেয়।
পৌঁছান এবং স্কেল করুন
এক ক্লিকে বিশ্বের যে কেউ আপনার পাঠানো একটি লিঙ্কে ক্লিক করতে পারে, তাদের ব্রাউজারে ওয়েব পৃষ্ঠা খুলতে পারে এবং আপনি যা তৈরি করেছেন তা ব্যবহার করতে পারেন। মেশিন লার্নিং সিস্টেম ব্যবহার করার জন্য CUDA ড্রাইভার সহ একটি জটিল সার্ভার সাইড লিনাক্স সেটআপের প্রয়োজন নেই এবং আরও অনেক কিছু।
খরচ
কোনো সার্ভার মানেই আপনার HTML, CSS, JS, এবং মডেল ফাইলগুলি হোস্ট করার জন্য একটি CDN এর জন্য আপনাকে অর্থপ্রদান করতে হবে। একটি CDN-এর খরচ একটি সার্ভার (সম্ভাব্যভাবে একটি গ্রাফিক্স কার্ড সংযুক্ত) 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 জাভাস্ক্রিপ্টে লেখা হয় যার মানে এটি শুধুমাত্র সময় সংকলন থেকে উপকৃত হয়। এর মানে হল যে আপনি প্রায়শই Node.js ব্যবহার করার সময় পারফরম্যান্স লাভ দেখতে পারেন কারণ এটি রানটাইমে অপ্টিমাইজ করা হবে, বিশেষ করে আপনি যে কোনো প্রিপ্রসেসিং করছেন। এর একটি দুর্দান্ত উদাহরণ এই কেস স্টাডিতে দেখা যায় যা দেখায় যে কীভাবে Hugging Face তাদের প্রাকৃতিক ভাষা প্রক্রিয়াকরণ মডেলের জন্য 2x পারফরম্যান্স বুস্ট পেতে Node.js ব্যবহার করেছে৷
এখন আপনি TensorFlow.js এর মূল বিষয়গুলি বুঝতে পেরেছেন, যেখানে এটি চলতে পারে এবং কিছু সুবিধা, আসুন এটির সাথে দরকারী জিনিসগুলি করা শুরু করি!
3. ট্রান্সফার লার্নিং
ট্রান্সফার লার্নিং আসলে কি?
ট্রান্সফার লার্নিং একটি ভিন্ন কিন্তু একই জিনিস শিখতে সাহায্য করার জন্য ইতিমধ্যেই শেখা হয়েছে এমন জ্ঞান নেওয়া জড়িত।
আমরা মানুষ সব সময় এই কাজ. আপনার মস্তিষ্কে আজীবন অভিজ্ঞতা রয়েছে যা আপনি নতুন জিনিসগুলিকে চিনতে সাহায্য করতে ব্যবহার করতে পারেন যা আপনি আগে কখনও দেখেননি। উদাহরণস্বরূপ এই উইলো গাছটি নিন:
আপনি বিশ্বের কোথায় আছেন তার উপর নির্ভর করে এমন সম্ভাবনা রয়েছে যে আপনি এই ধরণের গাছ আগে দেখেননি।
তবুও যদি আমি আপনাকে নীচের নতুন ছবিতে কোনও উইলো গাছ আছে কিনা তা আমাকে বলতে বলি, আপনি সম্ভবত সেগুলিকে খুব দ্রুত খুঁজে পেতে পারেন, যদিও সেগুলি একটি ভিন্ন কোণে, এবং আমি আপনাকে দেখানো আসলটির থেকে কিছুটা আলাদা৷
আপনার মস্তিষ্কে ইতিমধ্যেই একগুচ্ছ নিউরন রয়েছে যেগুলি গাছের মতো বস্তুগুলিকে কীভাবে শনাক্ত করতে হয় তা জানে এবং অন্যান্য নিউরনগুলি যা দীর্ঘ সরল রেখা খুঁজে পেতে ভাল। আপনি একটি উইলো গাছকে দ্রুত শ্রেণীবদ্ধ করতে সেই জ্ঞানটি পুনরায় ব্যবহার করতে পারেন, যা একটি গাছের মতো বস্তু যার অনেকগুলি লম্বা সোজা উল্লম্ব শাখা রয়েছে।
একইভাবে, যদি আপনার কাছে একটি মেশিন লার্নিং মডেল থাকে যা ইতিমধ্যেই একটি ডোমেনে প্রশিক্ষিত হয়, যেমন ছবি শনাক্ত করা, আপনি একটি ভিন্ন কিন্তু সম্পর্কিত কাজ সম্পাদন করতে এটি পুনরায় ব্যবহার করতে পারেন।
আপনি MobileNet এর মত একটি উন্নত মডেলের সাথে একই কাজ করতে পারেন, যা একটি খুব জনপ্রিয় গবেষণা মডেল যা 1000টি বিভিন্ন ধরনের অবজেক্টে ইমেজ রিকগনিশন করতে পারে। কুকুর থেকে গাড়ি পর্যন্ত, এটিকে ইমেজনেট নামে পরিচিত একটি বিশাল ডেটাসেটে প্রশিক্ষণ দেওয়া হয়েছিল যাতে লক্ষ লক্ষ লেবেলযুক্ত চিত্র রয়েছে।
এই অ্যানিমেশনে, আপনি এই MobileNet V1 মডেলের বিশাল সংখ্যক স্তর দেখতে পারেন:
এর প্রশিক্ষণের সময়, এই মডেলটি শিখেছে কীভাবে সাধারণ বৈশিষ্ট্যগুলি বের করতে হয় যা এই 1000টি বস্তুর জন্য গুরুত্বপূর্ণ, এবং এই ধরনের বস্তুগুলি সনাক্ত করতে এটি ব্যবহার করে এমন অনেক নিম্ন স্তরের বৈশিষ্ট্যগুলি এমন নতুন বস্তু সনাক্ত করতে কার্যকর হতে পারে যা এটি আগে কখনও দেখেনি। সর্বোপরি, সবকিছুই শেষ পর্যন্ত শুধু লাইন, টেক্সচার এবং আকারের সংমিশ্রণ।
আসুন একটি প্রথাগত কনভোলিউশনাল নিউরাল নেটওয়ার্ক (সিএনএন) আর্কিটেকচার (মোবাইলনেটের অনুরূপ) দেখে নেওয়া যাক এবং দেখুন কিভাবে ট্রান্সফার লার্নিং এই প্রশিক্ষিত নেটওয়ার্ককে নতুন কিছু শিখতে সাহায্য করতে পারে। নীচের চিত্রটি একটি সিএনএন-এর আদর্শ মডেল আর্কিটেকচার দেখায় যা এই ক্ষেত্রে 0 থেকে 9 পর্যন্ত হাতে লেখা অঙ্কগুলি চিনতে প্রশিক্ষিত ছিল:
যদি আপনি একটি বিদ্যমান প্রশিক্ষিত মডেলের প্রাক-প্রশিক্ষিত নিম্ন স্তরের স্তরগুলিকে বাম দিকে দেখানো এইভাবে আলাদা করতে পারেন, ডানদিকে প্রদর্শিত মডেলের শেষের কাছাকাছি শ্রেণিবিন্যাসের স্তরগুলি থেকে (কখনও কখনও মডেলের শ্রেণিবিন্যাস প্রধান হিসাবে উল্লেখ করা হয়), আপনি প্রশিক্ষিত মূল ডেটার উপর ভিত্তি করে যে কোনও প্রদত্ত চিত্রের জন্য আউটপুট বৈশিষ্ট্যগুলি তৈরি করতে নিম্ন স্তরের স্তরগুলি ব্যবহার করতে পারেন। এখানে শ্রেণীবিন্যাস প্রধান সরানো একই নেটওয়ার্ক আছে:
আপনি যে নতুন জিনিসটি চিনতে চাচ্ছেন তা ধরে নিলে পূর্বের মডেলটি শিখেছে এমন আউটপুট বৈশিষ্ট্যগুলিও ব্যবহার করতে পারে, তাহলে একটি নতুন উদ্দেশ্যে সেগুলি পুনরায় ব্যবহার করার একটি ভাল সুযোগ রয়েছে।
উপরের চিত্রে, এই অনুমানমূলক মডেলটি অঙ্কের উপর প্রশিক্ষিত ছিল, তাই হয়তো অঙ্ক সম্পর্কে যা শিখেছি তা a, b, এবং c এর মতো অক্ষরগুলিতেও প্রয়োগ করা যেতে পারে।
সুতরাং এখন আপনি একটি নতুন শ্রেণিবিন্যাস হেড যোগ করতে পারেন যা a, b, বা c এর পরিবর্তে ভবিষ্যদ্বাণী করার চেষ্টা করে, যেমন দেখানো হয়েছে:
এখানে নিম্ন স্তরের স্তরগুলি হিমায়িত এবং প্রশিক্ষিত নয়, শুধুমাত্র নতুন শ্রেণীবিভাগ প্রধান বাম দিকে প্রাক-প্রশিক্ষিত চপ আপ মডেল থেকে প্রদত্ত বৈশিষ্ট্যগুলি থেকে শিখতে নিজেকে আপডেট করবে।
এটি করার কাজটিকে ট্রান্সফার লার্নিং বলা হয় এবং পর্দার আড়ালে শিক্ষনীয় মেশিন এটিই করে।
আপনি আরও দেখতে পারেন যে শুধুমাত্র নেটওয়ার্কের একেবারে শেষে মাল্টি-লেয়ার পারসেপ্ট্রনকে প্রশিক্ষিত করার মাধ্যমে, এটি আপনাকে স্ক্র্যাচ থেকে পুরো নেটওয়ার্ককে প্রশিক্ষণ দেওয়ার চেয়ে অনেক দ্রুত প্রশিক্ষণ দেয়।
কিন্তু আপনি কিভাবে একটি মডেলের উপ-অংশগুলিতে আপনার হাত পেতে পারেন? খুঁজে বের করতে পরবর্তী বিভাগে যান।
4. টেনসরফ্লো হাব - বেস মডেল
ব্যবহার করার জন্য একটি উপযুক্ত বেস মডেল খুঁজুন
MobileNet-এর মতো আরও উন্নত এবং জনপ্রিয় গবেষণা মডেলের জন্য, আপনি TensorFlow হাবে যেতে পারেন, এবং তারপরে TensorFlow.js-এর জন্য উপযুক্ত মডেলগুলির জন্য ফিল্টার করতে পারেন যেগুলি এখানে দেখানোর মতো ফলাফল পেতে MobileNet v3 আর্কিটেকচার ব্যবহার করে :
মনে রাখবেন যে এই ফলাফলগুলির মধ্যে কিছু "ইমেজ শ্রেণীবিভাগ" (প্রতিটি মডেল কার্ডের ফলাফলের উপরের বাম দিকে বিশদ বিবরণ) টাইপের এবং অন্যগুলি "চিত্র বৈশিষ্ট্য ভেক্টর" টাইপের।
এই ইমেজ ফিচার ভেক্টর ফলাফলগুলি মূলত MobileNet-এর প্রাক-কাপ করা সংস্করণ যা আপনি চূড়ান্ত শ্রেণীবিভাগের পরিবর্তে চিত্র বৈশিষ্ট্য ভেক্টর পেতে ব্যবহার করতে পারেন।
এই ধরনের মডেলগুলিকে প্রায়শই "বেস মডেল" বলা হয়, যেটি আপনি একটি নতুন শ্রেণীবিভাগ প্রধান যোগ করে এবং আপনার নিজস্ব ডেটা দিয়ে প্রশিক্ষণের মাধ্যমে পূর্ববর্তী বিভাগে দেখানো একই পদ্ধতিতে স্থানান্তর শিক্ষা সম্পাদন করতে ব্যবহার করতে পারেন।
পরের জিনিসটি পরীক্ষা করার জন্য আগ্রহের একটি প্রদত্ত বেস মডেলের জন্য TensorFlow.js ফর্ম্যাটে মডেলটি প্রকাশ করা হয়েছে৷ আপনি যদি এই বৈশিষ্ট্য ভেক্টর MobileNet v3 মডেলগুলির একটির জন্য পৃষ্ঠাটি খোলেন তবে আপনি JS ডকুমেন্টেশন থেকে দেখতে পাবেন যে এটি ডকুমেন্টেশনের উদাহরণ কোড স্নিপেটের উপর ভিত্তি করে একটি গ্রাফ মডেল আকারে যা tf.loadGraphModel()
ব্যবহার করে।
এটিও লক্ষ করা উচিত যে আপনি যদি গ্রাফ বিন্যাসের পরিবর্তে স্তর বিন্যাসে একটি মডেল খুঁজে পান তবে আপনি প্রশিক্ষণের জন্য কোন স্তরগুলিকে হিমায়িত করতে হবে এবং কোনটি আনফ্রিজ করতে হবে তা চয়ন করতে পারেন৷ একটি নতুন কাজের জন্য একটি মডেল তৈরি করার সময় এটি খুব শক্তিশালী হতে পারে, যা প্রায়ই "স্থানান্তর মডেল" হিসাবে উল্লেখ করা হয়। আপাতত, যাইহোক, আপনি এই টিউটোরিয়ালের জন্য ডিফল্ট গ্রাফ মডেল টাইপ ব্যবহার করবেন, যেটি বেশিরভাগ TF হাব মডেল হিসাবে স্থাপন করা হয়। লেয়ার মডেলগুলির সাথে কাজ করার বিষয়ে আরও জানতে, জিরো থেকে হিরো TensorFlow.js কোর্সটি দেখুন।
স্থানান্তর শিক্ষার সুবিধা
স্ক্র্যাচ থেকে পুরো মডেল আর্কিটেকচার প্রশিক্ষণের পরিবর্তে ট্রান্সফার লার্নিং ব্যবহার করার সুবিধা কী?
প্রথমত, প্রশিক্ষণের সময় হল একটি ট্রান্সফার শেখার পদ্ধতি ব্যবহার করার একটি মূল সুবিধা কারণ আপনার কাছে ইতিমধ্যেই তৈরি করার জন্য একটি প্রশিক্ষিত বেস মডেল রয়েছে।
দ্বিতীয়ত, আপনি যে নতুন জিনিসের শ্রেণীবিভাগ করার চেষ্টা করছেন তার অনেক কম উদাহরণ দেখিয়ে আপনি দূরে যেতে পারেন যা ইতিমধ্যেই সংঘটিত প্রশিক্ষণের কারণে।
আপনি যে জিনিসটি শ্রেণীবদ্ধ করতে চান তার উদাহরণ ডেটা সংগ্রহ করার জন্য আপনার কাছে সীমিত সময় এবং সংস্থান থাকলে এটি সত্যিই দুর্দান্ত, এবং এটিকে আরও শক্তিশালী করতে আরও প্রশিক্ষণের ডেটা সংগ্রহ করার আগে দ্রুত একটি প্রোটোটাইপ তৈরি করতে হবে।
কম ডেটার প্রয়োজনীয়তা এবং একটি ছোট নেটওয়ার্ককে প্রশিক্ষণের গতির প্রেক্ষিতে, স্থানান্তর শেখার কম সম্পদ নিবিড়। এটি ব্রাউজার পরিবেশের জন্য খুব উপযুক্ত করে তোলে, সম্পূর্ণ মডেল প্রশিক্ষণের জন্য ঘন্টা, দিন বা সপ্তাহের পরিবর্তে একটি আধুনিক মেশিনে মাত্র দশ সেকেন্ড সময় নেয়।
ঠিক আছে! এখন আপনি ট্রান্সফার লার্নিং এর সারমর্মটি জানেন, এটি আপনার নিজস্ব শিক্ষণযোগ্য মেশিনের সংস্করণ তৈরি করার সময়। চলুন শুরু করা যাক!
5. কোড সেট আপ করুন
আপনি কি প্রয়োজন হবে
- একটি আধুনিক ওয়েব ব্রাউজার।
- HTML, CSS, JavaScript এবং Chrome DevTools এর প্রাথমিক জ্ঞান (কনসোল আউটপুট দেখা)।
কোডিং করা যাক
থেকে শুরু করার জন্য বয়লারপ্লেট টেমপ্লেটগুলি Glitch.com বা Codepen.io- এর জন্য তৈরি করা হয়েছে। আপনি এই কোড ল্যাবের জন্য আপনার বেস স্টেট হিসাবে যেকোন একটি টেমপ্লেটকে ক্লোন করতে পারেন, শুধুমাত্র একটি ক্লিকে।
Glitch-এ, এটিকে কাঁটাচামচ করতে " রিমিক্স এই" বোতামটি ক্লিক করুন এবং আপনি সম্পাদনা করতে পারেন এমন ফাইলগুলির একটি নতুন সেট তৈরি করুন৷
বিকল্পভাবে, কোডপেনে, স্ক্রিনের নীচের নীচে ডানদিকে " ফর্ক" ক্লিক করুন।
এই খুব সাধারণ কঙ্কাল আপনাকে নিম্নলিখিত ফাইলগুলি সরবরাহ করে:
- HTML পৃষ্ঠা (index.html)
- স্টাইলশীট (style.css)
- আমাদের জাভাস্ক্রিপ্ট কোড লেখার জন্য ফাইল (script.js)
আপনার সুবিধার জন্য, TensorFlow.js লাইব্রেরির জন্য HTML ফাইলে একটি যোগ করা হয়েছে। এটি এই মত দেখায়:
index.html
<!-- Import TensorFlow.js library -->
<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs/dist/tf.min.js" type="text/javascript"></script>
বিকল্প: আপনার পছন্দের ওয়েবডিটর ব্যবহার করুন বা স্থানীয়ভাবে কাজ করুন
আপনি যদি কোডটি ডাউনলোড করতে চান এবং স্থানীয়ভাবে কাজ করতে চান, বা অন্য কোনও অনলাইন সম্পাদকে, শুধুমাত্র একই ডিরেক্টরিতে উপরে নাম দেওয়া 3টি ফাইল তৈরি করুন এবং আমাদের গ্লিচ বয়লারপ্লেট থেকে কোডটি কপি করে প্রতিটিতে পেস্ট করুন৷
6. অ্যাপ এইচটিএমএল বয়লারপ্লেট
কোথায় শুরু করব?
সমস্ত প্রোটোটাইপের জন্য কিছু মৌলিক HTML ভারা প্রয়োজন যাতে আপনি আপনার ফলাফলগুলি রেন্ডার করতে পারেন৷ এটা এখন সেট আপ. আপনি যোগ করতে যাচ্ছেন:
- পৃষ্ঠার জন্য একটি শিরোনাম।
- কিছু বর্ণনামূলক লেখা।
- একটি স্ট্যাটাস অনুচ্ছেদ।
- ওয়েবক্যাম ফিড একবার প্রস্তুত হওয়ার জন্য একটি ভিডিও।
- ক্যামেরা চালু করতে, ডেটা সংগ্রহ করতে বা অভিজ্ঞতা পুনরায় সেট করতে বেশ কয়েকটি বোতাম।
- 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>
ভেঙ্গে ফেলো
আপনার যোগ করা কিছু মূল জিনিস হাইলাইট করতে উপরের কিছু HTML কোড ভেঙে দেওয়া যাক।
- আপনি পৃষ্ঠার শিরোনামের জন্য একটি
<h1>
ট্যাগ যোগ করেছেন একটি<p>
ট্যাগের সাথে একটি 'স্থিতি' আইডি সহ, যেখানে আপনি তথ্য মুদ্রণ করবেন, কারণ আপনি আউটপুট দেখার জন্য সিস্টেমের বিভিন্ন অংশ ব্যবহার করেন। - আপনি 'ওয়েবক্যাম'-এর একটি আইডি সহ একটি
<video>
উপাদান যোগ করেছেন, যেখানে আপনি পরে আপনার ওয়েবক্যাম স্ট্রিম রেন্ডার করবেন। - আপনি 5টি
<button>
উপাদান যোগ করেছেন। প্রথমটি, 'enableCam'-এর আইডি দিয়ে, ক্যামেরাকে সক্ষম করে। পরবর্তী দুটি বোতামে 'ডেটাকলেক্টর'-এর একটি শ্রেণী রয়েছে, যা আপনাকে যে বস্তুগুলিকে চিনতে চান তার উদাহরণ চিত্র সংগ্রহ করতে দেয়। আপনি পরে যে কোডটি লিখবেন তা এমনভাবে ডিজাইন করা হবে যাতে আপনি এই বোতামগুলির যেকোনো সংখ্যা যোগ করতে পারেন এবং সেগুলি স্বয়ংক্রিয়ভাবে কাজ করবে।
উল্লেখ্য যে এই বোতামগুলিতে ডেটা-1 হট নামে একটি বিশেষ ব্যবহারকারী-সংজ্ঞায়িত বৈশিষ্ট্যও রয়েছে, যার প্রথম শ্রেণীর জন্য 0 থেকে পূর্ণসংখ্যার মান শুরু হয়। এটি এমন একটি সংখ্যাসূচক সূচক যা আপনি একটি নির্দিষ্ট শ্রেণীর ডেটা উপস্থাপন করতে ব্যবহার করবেন। সূচীটি আউটপুট ক্লাসগুলিকে স্ট্রিংয়ের পরিবর্তে একটি সংখ্যাসূচক উপস্থাপনা সহ সঠিকভাবে এনকোড করতে ব্যবহার করা হবে, কারণ ML মডেলগুলি শুধুমাত্র সংখ্যার সাথে কাজ করতে পারে।
এছাড়াও একটি ডেটা-নাম বৈশিষ্ট্য রয়েছে যাতে আপনি এই শ্রেণীর জন্য ব্যবহার করতে চান এমন মানব পাঠযোগ্য নাম রয়েছে, যা আপনাকে 1 হট এনকোডিং থেকে একটি সংখ্যাসূচক সূচক মানের পরিবর্তে ব্যবহারকারীকে আরও অর্থপূর্ণ নাম প্রদান করতে দেয়৷
অবশেষে, আপনার কাছে একটি ট্রেন এবং রিসেট বোতাম রয়েছে যা একবার ডেটা সংগ্রহ করার পরে প্রশিক্ষণ প্রক্রিয়া শুরু করতে বা যথাক্রমে অ্যাপটি পুনরায় সেট করতে।
- আপনি 2টি
<script>
আমদানিও যোগ করেছেন। একটি TensorFlow.js এর জন্য এবং অন্যটি script.js এর জন্য যা আপনি শীঘ্রই সংজ্ঞায়িত করবেন৷
7. শৈলী যোগ করুন
এলিমেন্ট ডিফল্ট
সঠিকভাবে রেন্ডার নিশ্চিত করতে আপনি এইমাত্র যোগ করেছেন এমন HTML উপাদানগুলির জন্য শৈলী যোগ করুন। এখানে কিছু শৈলী রয়েছে যা সঠিকভাবে অবস্থান এবং আকারের উপাদানগুলিতে যোগ করা হয়েছে। খুব বিশেষ কিছু না. আপনি অবশ্যই আরও ভাল ইউএক্স তৈরি করতে পরে এটিতে যোগ করতে পারেন, যেমন আপনি শিক্ষণীয় মেশিন ভিডিওতে দেখেছেন।
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. জাভাস্ক্রিপ্ট: কী ধ্রুবক এবং শ্রোতা
কী ধ্রুবক সংজ্ঞায়িত করুন
প্রথমে, কিছু মূল ধ্রুবক যোগ করুন যা আপনি পুরো অ্যাপ জুড়ে ব্যবহার করবেন। এই ধ্রুবকগুলির সাথে 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
HTML ভিডিও উপাদানের একটি রেফারেন্স রয়েছে যা ওয়েবক্যাম ফিড রেন্ডার করবে। -
ENABLE_CAM_BUTTON
,RESET_BUTTON
, এবংTRAIN_BUTTON
HTML পৃষ্ঠা থেকে সমস্ত কী বোতামের DOM রেফারেন্স দখল করে৷ -
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
- ক্লিক করলে ট্রেন এবং প্রেডিক্টে কল করে।
RESET_BUTTON
- ক্লিক করলে কল রিসেট হয়।
অবশেষে এই বিভাগে আপনি document.querySelectorAll()
ব্যবহার করে 'dataCollector'-এর ক্লাস আছে এমন সমস্ত বোতাম খুঁজে পেতে পারেন। এটি নথি থেকে পাওয়া উপাদানগুলির একটি অ্যারে প্রদান করে যা মেলে:
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!
}
কোড ব্যাখ্যা:
তারপরে আপনি পাওয়া বোতামগুলির মাধ্যমে পুনরাবৃত্তি করুন এবং প্রতিটির সাথে 2 জন ইভেন্ট শ্রোতাকে সংযুক্ত করুন৷ একটি 'মাউসডাউন' এর জন্য এবং একটি 'মাউসআপ' এর জন্য। এটি আপনাকে যতক্ষণ বোতাম টিপছে ততক্ষণ নমুনা রেকর্ড করতে দেয়, যা ডেটা সংগ্রহের জন্য দরকারী।
উভয় ইভেন্টই একটি gatherDataForClass
ফাংশন বলে যা আপনি পরে সংজ্ঞায়িত করবেন।
এই মুহুর্তে, আপনি HTML বোতাম অ্যাট্রিবিউট ডেটা-নাম থেকে 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 হট আইডি হবে, যেমনটি HTML-এ সংজ্ঞায়িত করা হয়েছে, যাতে আপনি জানতে পারেন যে আপনি সেই মুহূর্তে কোন শ্রেণীর ডেটা সংগ্রহ করছেন। প্রাথমিকভাবে, এটি STOP_DATA_GATHER
এ সেট করা হয়েছে যাতে আপনি পরে যে ডেটা সংগ্রহের লুপটি লিখবেন সেটি কোনো বোতাম টিপলে কোনো ডেটা সংগ্রহ করবে না।
videoPlaying
ওয়েবক্যাম স্ট্রীম সফলভাবে লোড হয়েছে এবং চালানো হয়েছে এবং ব্যবহারের জন্য উপলব্ধ কিনা তা ট্র্যাক রাখে। প্রাথমিকভাবে, এটি false
হিসাবে সেট করা হয়েছে কারণ আপনি ENABLE_CAM_BUTTON.
এর পরে, 2টি অ্যারে, 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()
ব্যবহার করে মডেলটি লোড করতে পারেন, fromTFHub
বিশেষ বৈশিষ্ট্যটিকে true
সেট করার কথা মনে রেখে আপনি এই Google ওয়েবসাইট থেকে একটি মডেল লোড করছেন৷ এটি শুধুমাত্র TF হাবে হোস্ট করা মডেল ব্যবহার করার জন্য একটি বিশেষ ক্ষেত্রে যেখানে এই অতিরিক্ত সম্পত্তি সেট করতে হবে।
একবার লোডিং সম্পূর্ণ হলে আপনি একটি বার্তা সহ STATUS
উপাদানের innerText
সেট করতে পারেন যাতে আপনি দৃশ্যত দেখতে পারেন এটি সঠিকভাবে লোড হয়েছে এবং আপনি ডেটা সংগ্রহ শুরু করতে প্রস্তুত৷
এখন শুধু মডেলটিকে ওয়ার্ম আপ করা বাকি। এই ধরনের বড় মডেলগুলির সাথে, আপনি প্রথমবার মডেলটি ব্যবহার করার সময়, সবকিছু সেট আপ করতে একটু সময় নিতে পারে৷ তাই এটি মডেলের মধ্য দিয়ে শূন্য অতিক্রম করতে সাহায্য করে যাতে ভবিষ্যতে কোনো অপেক্ষা না করা যায় যেখানে সময় আরও জটিল হতে পারে।
আপনি tf.zeros()
ব্যবহার করতে পারেন tf.tidy()
এ মোড়ানো নিশ্চিত করতে টেনসর সঠিকভাবে নিষ্পত্তি করা হয়েছে, ব্যাচের আকার 1 এবং সঠিক উচ্চতা এবং প্রস্থ যা আপনি শুরুতে আপনার ধ্রুবকগুলিতে সংজ্ঞায়িত করেছেন। অবশেষে, আপনি রঙের চ্যানেলগুলিও নির্দিষ্ট করুন, যেটি এই ক্ষেত্রে 3 যেমন মডেলটি আরজিবি ছবি আশা করে।
এর পরে, এই মডেলটি তৈরি করা ছবির বৈশিষ্ট্যগুলির আকার বুঝতে সাহায্য করার জন্য answer.shape()
ব্যবহার করে ফেরত টেনসরের ফলের আকৃতি লগ করুন।
এই ফাংশনটি সংজ্ঞায়িত করার পরে, আপনি পৃষ্ঠা লোডে মডেল ডাউনলোড শুরু করতে অবিলম্বে এটিকে কল করতে পারেন।
আপনি যদি এখনই আপনার লাইভ প্রিভিউ দেখেন, তাহলে কিছুক্ষণ পর আপনি দেখতে পাবেন স্ট্যাটাস টেক্সট পরিবর্তন হয়ে "TF.js লোডের অপেক্ষায়" থেকে "MobileNet v3 সফলভাবে লোড হয়েছে!" নীচে দেখানো হিসাবে. চালিয়ে যাওয়ার আগে এটি কাজ করে তা নিশ্চিত করুন।
এই মডেলটি যে আউটপুট বৈশিষ্ট্যগুলি তৈরি করে তার মুদ্রিত আকার দেখতে আপনি কনসোল আউটপুটটিও পরীক্ষা করতে পারেন। 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.sequential মডেল সংজ্ঞায়িত করে শুরু করুন যেখানে আপনি মডেল স্তর যুক্ত করবেন।
এর পরে, এই মডেলটিতে ইনপুট স্তর হিসাবে একটি ঘন স্তর যুক্ত করুন। মোবাইলনেট v3 বৈশিষ্ট্যগুলি থেকে আউটপুটগুলি এই আকারের হওয়ায় এটির একটি ইনপুট আকার 1024
রয়েছে৷ আপনি মডেলের মধ্য দিয়ে অতিক্রম করার পর আগের ধাপে এটি আবিষ্কার করেছেন। এই স্তরটিতে 128টি নিউরন রয়েছে যা ReLU অ্যাক্টিভেশন ফাংশন ব্যবহার করে।
আপনি যদি অ্যাক্টিভেশন ফাংশন এবং মডেল স্তরগুলিতে নতুন হন, তাহলে এই বৈশিষ্ট্যগুলি পর্দার আড়ালে কী করে তা বোঝার জন্য এই কর্মশালার শুরুতে বিস্তারিত কোর্সটি নেওয়ার কথা বিবেচনা করুন ৷
পরবর্তী স্তরটি যোগ করার জন্য আউটপুট স্তর। আপনি ভবিষ্যদ্বাণী করার চেষ্টা করছেন এমন ক্লাসের সংখ্যার সমান হওয়া উচিত নিউরনের সংখ্যা। এটি করার জন্য আপনি CLASS_NAMES.length
ব্যবহার করতে পারেন যে আপনি কতগুলি ক্লাস শ্রেণীবদ্ধ করার পরিকল্পনা করছেন, যা ব্যবহারকারী ইন্টারফেসে পাওয়া ডেটা সংগ্রহ বোতামের সংখ্যার সমান। যেহেতু এটি একটি শ্রেণিবিন্যাসের সমস্যা, আপনি এই আউটপুট স্তরে softmax
অ্যাক্টিভেশন ব্যবহার করেন, যা রিগ্রেশনের পরিবর্তে শ্রেণিবিন্যাসের সমস্যা সমাধানের জন্য একটি মডেল তৈরি করার চেষ্টা করার সময় ব্যবহার করা আবশ্যক।
কনসোলে নতুন সংজ্ঞায়িত মডেলের ওভারভিউ প্রিন্ট করতে এখন একটি model.summary()
প্রিন্ট করুন।
অবশেষে, মডেলটি কম্পাইল করুন যাতে এটি প্রশিক্ষণের জন্য প্রস্তুত হয়। এখানে অপ্টিমাইজারটি adam
এ সেট করা হয়েছে, এবং CLASS_NAMES.length
2
এর সমান হলে ক্ষতি হয় binaryCrossentropy
হবে, অথবা শ্রেণীবদ্ধ করার জন্য 3 বা তার বেশি শ্রেণী থাকলে এটি categoricalCrossentropy
ব্যবহার করবে। নির্ভুলতা মেট্রিকগুলিও অনুরোধ করা হয়েছে যাতে ডিবাগিংয়ের উদ্দেশ্যে সেগুলি পরে লগগুলিতে নিরীক্ষণ করা যায়৷
কনসোলে আপনি এই মত কিছু দেখতে হবে:
উল্লেখ্য যে এটিতে 130 হাজারের বেশি প্রশিক্ষণযোগ্য পরামিতি রয়েছে। তবে এটি নিয়মিত নিউরনের একটি সাধারণ ঘন স্তর হওয়ায় এটি বেশ দ্রুত প্রশিক্ষণ দেবে।
প্রোজেক্টটি সম্পূর্ণ হওয়ার পরে করার জন্য একটি কার্যকলাপ হিসাবে, আপনি প্রথম স্তরে নিউরনের সংখ্যা পরিবর্তন করার চেষ্টা করতে পারেন যাতে আপনি এখনও শালীন কর্মক্ষমতা পেয়ে এটি কতটা কম করতে পারেন। প্রায়শই মেশিন লার্নিংয়ের সাথে কিছু স্তরের ট্রায়াল এবং ত্রুটি থাকে যা আপনাকে সম্পদের ব্যবহার এবং গতির মধ্যে সর্বোত্তম ট্রেড অফ দেওয়ার জন্য সর্বোত্তম প্যারামিটার মানগুলি খুঁজে পায়।
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()
সমর্থন করে কিনা তা যাচাই করার জন্য মূল ব্রাউজার API-এর বৈশিষ্ট্যগুলির অস্তিত্ব পরীক্ষা করে।
enableCam()
ফাংশনে hasGetUserMedia()
ফাংশনটি ব্যবহার করুন যা আপনি উপরে সংজ্ঞায়িত করেছেন এটি সমর্থিত কিনা তা পরীক্ষা করতে। যদি এটি না হয়, কনসোলে একটি সতর্কতা মুদ্রণ করুন।
যদি এটি এটি সমর্থন করে, তাহলে আপনার getUserMedia()
কলের জন্য কিছু সীমাবদ্ধতা নির্ধারণ করুন, যেমন আপনি শুধুমাত্র ভিডিও স্ট্রিম চান, এবং আপনি ভিডিওর width
640
পিক্সেল আকারে এবং height
480
পিক্সেল হতে পছন্দ করেন৷ কেন? ঠিক আছে, এর থেকে বড় একটি ভিডিও পাওয়ার খুব বেশি বিন্দু নেই কারণ এটিকে মোবাইলনেট মডেলে খাওয়ানোর জন্য 224 বাই 224 পিক্সেলের আকার পরিবর্তন করতে হবে। আপনি একটি ছোট রেজোলিউশনের অনুরোধ করে কিছু কম্পিউটিং সংস্থানও সংরক্ষণ করতে পারেন। বেশিরভাগ ক্যামেরা এই আকারের রেজোলিউশন সমর্থন করে।
এরপরে, উপরে বিস্তারিত constraints
সহ navigator.mediaDevices.getUserMedia()
কে কল করুন এবং তারপরে stream
ফিরে আসার জন্য অপেক্ষা করুন। একবার stream
ফেরত দিলে আপনি আপনার VIDEO
উপাদানটিকে এটির srcObject
মান হিসাবে সেট করে stream
চালানোর জন্য পেতে পারেন।
stream
কখন লোড হয়েছে এবং সফলভাবে বাজছে তা জানতে আপনার VIDEO
উপাদানটিতে একটি ইভেন্ট লিসেনার যোগ করা উচিত।
একবার স্টিম লোড হয়ে গেলে, আপনি videoPlaying
সত্যে সেট করতে পারেন এবং 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
অ্যাট্রিবিউট চেক করুন attribute-এর নামের সাথে this.getAttribute()
কল করে, এই ক্ষেত্রে data-1hot
প্যারামিটার হিসেবে। যেহেতু এটি একটি স্ট্রিং, আপনি parseInt()
ব্যবহার করে এটিকে একটি পূর্ণসংখ্যাতে কাস্ট করতে পারেন এবং এই ফলাফলটি classNumber.
এরপরে, সেই অনুযায়ী gatherDataState
ভেরিয়েবল সেট করুন। যদি বর্তমান gatherDataState
STOP_DATA_GATHER
এর সমান হয় (যা আপনি -1 সেট করেছেন), তাহলে তার মানে আপনি বর্তমানে কোনো ডেটা সংগ্রহ করছেন না এবং এটি একটি mousedown
ইভেন্ট যা ফায়ার করেছে। আপনি এইমাত্র পাওয়া classNumber
হিসাবে gatherDataState
সেট করুন।
অন্যথায়, এর মানে হল যে আপনি বর্তমানে ডেটা সংগ্রহ করছেন এবং যে ইভেন্টটি গুলি করা হয়েছে সেটি একটি mouseup
ইভেন্ট ছিল এবং আপনি এখন সেই ক্লাসের জন্য ডেটা সংগ্রহ করা বন্ধ করতে চান৷ আপনি খুব শীঘ্রই সংজ্ঞায়িত করবেন এমন ডেটা সংগ্রহের লুপটি শেষ করতে কেবল এটি STOP_DATA_GATHER
স্টেটে আবার সেট করুন।
অবশেষে, dataGatherLoop(),
যা আসলে শ্রেণীর ডেটা রেকর্ডিং সম্পাদন করে।
13. ডেটা সংগ্রহ
এখন, dataGatherLoop()
ফাংশনটি সংজ্ঞায়িত করুন। এই ফাংশনটি ওয়েবক্যাম ভিডিও থেকে চিত্রগুলি নমুনা দেওয়ার জন্য, মোবাইলনেট মডেলের মাধ্যমে পাস করার জন্য এবং সেই মডেলের আউটপুটগুলি (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
ভেরিয়েবলের আকার পরিবর্তন করুন। আপনি প্রথম প্যারামিটার হিসাবে পুনরায় আকার দিতে চান এমন টেনসারের সাথে একটি tf.image.resizeBilinear()
কল করুন এবং তারপরে এমন একটি আকার যা আপনি ইতিমধ্যে তৈরি করা ধ্রুবকগুলির দ্বারা সংজ্ঞায়িত হিসাবে নতুন উচ্চতা এবং প্রস্থকে সংজ্ঞায়িত করে। অবশেষে, পুনরায় আকার দেওয়ার সময় কোনও প্রান্তিককরণ সমস্যা এড়াতে তৃতীয় প্যারামিটারটি পাস করে প্রান্তিক কোণগুলি সত্যে সেট করুন। এই আকার পরিবর্তনটির ফলাফলটি resizedTensorFrame
নামে একটি ভেরিয়েবলে সংরক্ষণ করা হয়।
নোট করুন যে এই আদিম আকার পরিবর্তনটি চিত্রটি প্রসারিত করে, কারণ আপনার ওয়েবক্যাম চিত্রটি আকারে 480 বাই 480 পিক্সেল এবং মডেলটির 224 দ্বারা 224 পিক্সেল দ্বারা বর্গাকার চিত্রের প্রয়োজন।
এই ডেমোটির উদ্দেশ্যে এটি ঠিকঠাক কাজ করা উচিত। যাইহোক, একবার আপনি এই কোডল্যাবটি সম্পূর্ণ করার পরে, আপনি পরে তৈরি করতে পারেন এমন কোনও উত্পাদন সিস্টেমের জন্য আরও ভাল ফলাফলের জন্য আপনি এই চিত্র থেকে একটি স্কোয়ার চেষ্টা করতে এবং ক্রপ করতে চাইতে পারেন।
এরপরে, চিত্রের ডেটা স্বাভাবিক করুন। tf.browser.frompixels()
ব্যবহার করার সময় চিত্রের ডেটা সর্বদা 0 থেকে 255 এর মধ্যে থাকে, যাতে আপনি কেবল 255 দ্বারা রেজাইজডটেনসরফ্রেমকে বিভক্ত করতে পারেন যাতে সমস্ত মান 0 এবং 1 এর মধ্যে থাকে তা নিশ্চিত করতে, যা মোবাইলনেট মডেল ইনপুট হিসাবে প্রত্যাশা করে।
অবশেষে, কোডের tf.tidy()
বিভাগে, লোডড মডেলের মাধ্যমে mobilenet.predict()
কল করে এই স্বাভাবিক টেনসরকে চাপ দিন, যেখানে আপনি expandDims()
ব্যবহার করে normalizedTensorFrame
প্রসারিত সংস্করণটি পাস করেন যাতে এটি একটি ব্যাচ হয় 1 এর, যেমন মডেল প্রসেসিংয়ের জন্য ইনপুটগুলির একটি ব্যাচ আশা করে।
ফলাফলটি ফিরে আসার পরে, আপনি তত্ক্ষণাত্ squeeze()
কল করতে পারেন সেই ফিরে আসা ফলাফলটি স্কোয়াশ করার জন্য এটি একটি 1 ডি টেনসারে ফিরে যেতে পারেন, যা আপনি ফিরে এসে imageFeatures
ভেরিয়েবলের জন্য বরাদ্দ করে যা tf.tidy()
থেকে ফলাফলটি ক্যাপচার করে।
মোবাইলনেট মডেল থেকে এখন আপনার কাছে 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);
}
প্রথমে, নিশ্চিত করুন যে আপনি কোনও বর্তমান ভবিষ্যদ্বাণীগুলি false
predict
সেট করে সংঘটিত হওয়া থেকে বিরত রেখেছেন।
এরপরে, অর্ডারটি প্রশিক্ষণের ক্ষেত্রে সমস্যা সৃষ্টি করে না তা নিশ্চিত করার জন্য tf.util.shuffleCombo()
ব্যবহার করে আপনার ইনপুট এবং আউটপুট অ্যারেগুলি পরিবর্তন করুন।
আপনার আউটপুট অ্যারে, trainingDataOutputs,
টাইপ ইনট 32 এর একটি টেনসর 1 ডি হিসাবে রূপান্তর করুন যাতে এটি একটি গরম এনকোডিংয়ে ব্যবহার করার জন্য প্রস্তুত। এটি outputsAsTensor
নামে একটি ভেরিয়েবলে সংরক্ষণ করা হয়।
এনকোড করার জন্য সর্বোচ্চ সংখ্যক শ্রেণীর সাথে এই outputsAsTensor
ভেরিয়েবলের সাথে tf.oneHot()
ফাংশনটি ব্যবহার করুন, যা কেবল CLASS_NAMES.length
। আপনার একটি হট এনকোডেড আউটপুটগুলি এখন oneHotOutputs
নামে একটি নতুন টেনসারে সংরক্ষণ করা হয়েছে।
নোট করুন যে বর্তমানে trainingDataInputs
রেকর্ড করা টেনারগুলির একটি অ্যারে। প্রশিক্ষণের জন্য এগুলি ব্যবহার করার জন্য আপনাকে নিয়মিত 2 ডি টেনসর হওয়ার জন্য টেনারগুলির অ্যারে রূপান্তর করতে হবে।
এটি করার জন্য tensorflow.js লাইব্রেরির মধ্যে tf.stack()
নামে একটি দুর্দান্ত ফাংশন রয়েছে
যা টেনসরগুলির একটি অ্যারে নেয় এবং আউটপুট হিসাবে উচ্চতর মাত্রিক টেনসর উত্পাদন করতে তাদের একসাথে স্ট্যাক করে। এক্ষেত্রে একটি টেনসর 2 ডি ফিরে আসে, এটি 1 টি মাত্রিক ইনপুটগুলির একটি ব্যাচ যা প্রতিটি 1024 দৈর্ঘ্যে রেকর্ড করা বৈশিষ্ট্যযুক্ত দৈর্ঘ্যে থাকে, যা আপনার প্রশিক্ষণের জন্য প্রয়োজন।
এরপরে, কাস্টম মডেল হেডকে প্রশিক্ষণ দেওয়ার জন্য await model.fit()
। উদাহরণস্বরূপ ইনপুট এবং টার্গেট আউটপুটগুলি যথাক্রমে ব্যবহার করার জন্য প্রশিক্ষণের ডেটা উপস্থাপন করতে এখানে আপনি আপনার inputsAsTensor
ভেরিয়েবলটি oneHotOutputs
সাথে পাস করুন। তৃতীয় প্যারামিটারের জন্য কনফিগারেশন অবজেক্টে, true
shuffle
সেট করুন, 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 দ্বারা 224 দ্বারা আকার পরিবর্তন করুন এবং তারপরে ফলস্বরূপ চিত্রের বৈশিষ্ট্যগুলি পেতে মোবাইলনেট মডেলের মাধ্যমে সেই ডেটা পাস করুন।
তবে এখন, আপনি প্রশিক্ষিত মডেলের predict()
ফাংশনটির মাধ্যমে সবেমাত্র পাওয়া ফলাফলের imageFeatures
পাস করে আপনার নতুন প্রশিক্ষিত মডেল হেড ব্যবহার করতে পারেন। তারপরে আপনি আবার 1 টি মাত্রিক তৈরি করতে ফলাফলের টেনসরটি চেপে ধরতে পারেন এবং এটি prediction
নামে একটি পরিবর্তনশীলকে বরাদ্দ করতে পারেন।
এই prediction
সাহায্যে আপনি সূচকটি খুঁজে পেতে পারেন যা argMax()
ব্যবহার করে সর্বোচ্চ মান রয়েছে এবং তারপরে সর্বাধিক মূল্যবান উপাদানের অবস্থানটি আবিষ্কার করতে জাভাস্ক্রিপ্টে অন্তর্নিহিত ডেটা পেতে arraySync()
ব্যবহার করে এই ফলস্বরূপ টেনসরকে একটি অ্যারে রূপান্তর করুন। এই মানটি highestIndex
নামে ভেরিয়েবলে সংরক্ষণ করা হয়।
আপনি সরাসরি prediction
টেনসারে arraySync()
কে কল করে একইভাবে প্রকৃত পূর্বাভাসের আত্মবিশ্বাসের স্কোরগুলিও পেতে পারেন।
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);
}
প্রথমে, false
predict
সেট করে কোনও চলমান পূর্বাভাস লুপগুলি বন্ধ করুন। এরপরে, এর দৈর্ঘ্য 0 এ সেট করে examplesCount
অ্যারেতে সমস্ত সামগ্রী মুছুন, যা একটি অ্যারে থেকে সমস্ত সামগ্রী সাফ করার একটি সহজ উপায়।
এখন সমস্ত বর্তমান রেকর্ডড trainingDataInputs
মধ্য দিয়ে যান এবং আবার মেমরি মুক্ত করার জন্য এর মধ্যে থাকা প্রতিটি টেনসারের মধ্যে আপনি dispose()
নিশ্চিত করুন, কারণ জাভাস্ক্রিপ্ট আবর্জনা সংগ্রাহক দ্বারা টেনারগুলি পরিষ্কার করা হয়নি।
এটি হয়ে গেলে আপনি এখন নিরাপদে অ্যারের দৈর্ঘ্য 0 এ trainingDataInputs
এবং trainingDataOutputs
অ্যারে উভয়কেও সাফ করার জন্য সেট করতে পারেন।
অবশেষে STATUS
পাঠ্যটি বুদ্ধিমান কিছুতে সেট করুন এবং স্যানিটি চেক হিসাবে স্মৃতিতে বাম টেনারগুলি মুদ্রণ করুন।
নোট করুন যে মোবাইলনেট মডেল এবং আপনি যে মাল্টি-লেয়ার পার্সেপট্রন সংজ্ঞায়িত করেছেন তা উভয়ই নিষ্পত্তি করা হয়নি বলে স্মৃতিতে এখনও কয়েক শতাধিক টেনার থাকবে। আপনি যদি এই পুনরায় সেট করার পরে আবার প্রশিক্ষণের সিদ্ধান্ত নেন তবে আপনাকে নতুন প্রশিক্ষণ ডেটা দিয়ে তাদের পুনরায় ব্যবহার করতে হবে।
16. আসুন এটি চেষ্টা করে দেখুন
আপনার শিক্ষণযোগ্য মেশিনের নিজস্ব সংস্করণটি পরীক্ষা করার সময় এসেছে!
লাইভ পূর্বরূপের দিকে যান, ওয়েবক্যাম সক্ষম করুন, আপনার ঘরের কিছু অবজেক্টের জন্য 1 ম শ্রেণির জন্য কমপক্ষে 30 টি নমুনা সংগ্রহ করুন এবং তারপরে কোনও আলাদা অবজেক্টের জন্য 2 ক্লাস 2 এর জন্য একই কাজ করুন, ট্রেনে ক্লিক করুন এবং অগ্রগতি দেখতে কনসোল লগটি পরীক্ষা করুন। এটি বেশ দ্রুত প্রশিক্ষণ দেওয়া উচিত:
একবার প্রশিক্ষিত হয়ে গেলে, লাইভ ভবিষ্যদ্বাণীগুলি পেতে ক্যামেরায় অবজেক্টগুলি দেখান যা শীর্ষের কাছাকাছি ওয়েব পৃষ্ঠায় স্ট্যাটাস পাঠ্য অঞ্চলে মুদ্রিত হবে। যদি আপনার সমস্যা হয় তবে আপনি কোনও কিছুর অনুলিপি মিস করেছেন কিনা তা দেখতে আমার সমাপ্ত ওয়ার্কিং কোডটি পরীক্ষা করুন ।
17. অভিনন্দন
অভিনন্দন! আপনি ব্রাউজারে লাইভ টেনসরফ্লো.জেএস ব্যবহার করে আপনার প্রথম স্থানান্তর শেখার উদাহরণটি সম্পন্ন করেছেন।
এটি চেষ্টা করে দেখুন, এটি বিভিন্ন অবজেক্টে পরীক্ষা করুন, আপনি লক্ষ্য করতে পারেন যে কিছু জিনিস অন্যের চেয়ে স্বীকৃতি দেওয়া আরও কঠিন, বিশেষত যদি সেগুলি অন্য কোনও কিছুর সাথে মিল থাকে। এগুলি আলাদা করে বলতে সক্ষম হতে আপনার আরও ক্লাস বা প্রশিক্ষণের ডেটা যুক্ত করতে হবে।
রিক্যাপ
এই কোডল্যাবটিতে আপনি শিখেছেন:
- কী স্থানান্তর শেখার, এবং একটি সম্পূর্ণ মডেল প্রশিক্ষণের ক্ষেত্রে এর সুবিধাগুলি।
- টেনসরফ্লো হাব থেকে পুনরায় ব্যবহারের জন্য কীভাবে মডেল পাবেন।
- স্থানান্তর শেখার জন্য উপযুক্ত একটি ওয়েব অ্যাপ্লিকেশন কীভাবে সেট আপ করবেন।
- চিত্রের বৈশিষ্ট্যগুলি তৈরি করতে কীভাবে একটি বেস মডেল লোড এবং ব্যবহার করবেন।
- কীভাবে একটি নতুন ভবিষ্যদ্বাণী হেডকে প্রশিক্ষণ দেওয়া যায় যা ওয়েবক্যামের চিত্র থেকে কাস্টম অবজেক্টগুলি সনাক্ত করতে পারে।
- রিয়েল টাইমে ডেটা শ্রেণিবদ্ধ করতে কীভাবে ফলাফল মডেলগুলি ব্যবহার করবেন।
এরপর কি?
এখন আপনার কাছ থেকে শুরু করার জন্য একটি কার্যনির্বাহী বেস রয়েছে, আপনি কী কাজ করছেন এমন একটি বাস্তব বিশ্বের ব্যবহারের ক্ষেত্রে এই মেশিন লার্নিং মডেল বয়লারপ্লেটটি প্রসারিত করতে আপনি কোন সৃজনশীল ধারণাগুলি নিয়ে আসতে পারেন? আপনি বর্তমানে আপনার কোম্পানির ট্রেন মডেলগুলিতে তাদের প্রতিদিনের কাজের ক্ষেত্রে গুরুত্বপূর্ণ বিষয়গুলিকে শ্রেণিবদ্ধ করতে সহায়তা করার জন্য যে শিল্পে কাজ করছেন তা আপনি বিপ্লব করতে পারেন? সম্ভাবনা অন্তহীন.
আরও এগিয়ে যাওয়ার জন্য, এই সম্পূর্ণ কোর্সটি নিখরচায় নেওয়ার বিষয়টি বিবেচনা করুন , যা আপনাকে দেখায় যে কীভাবে আপনার বর্তমানে এই কোডেল্যাবটিতে থাকা 2 টি মডেল দক্ষতার জন্য 1 একক মডেল হিসাবে একত্রিত করবেন।
এছাড়াও আপনি যদি মূল টিচেবল মেশিন অ্যাপ্লিকেশনটির পিছনে তত্ত্বের চারপাশে আরও কৌতূহলী হন তবে এই টিউটোরিয়ালটি দেখুন।
আপনি আমাদের সাথে যা করেন তা ভাগ করুন
অন্যান্য সৃজনশীল ব্যবহারের ক্ষেত্রেও আপনি আজ যা তৈরি করেছেন তা সহজেই প্রসারিত করতে পারেন এবং আমরা আপনাকে বাক্সের বাইরে ভাবতে এবং হ্যাকিং চালিয়ে যেতে উত্সাহিত করি।
আপনার প্রকল্পের জন্য আমাদের টেনসরফ্লো ব্লগ বা এমনকি ভবিষ্যতের ইভেন্টগুলিতে বৈশিষ্ট্যযুক্ত হওয়ার জন্য আপনার প্রকল্পের সুযোগের জন্য #MADEWITHTFJS হ্যাশট্যাগ ব্যবহার করে আমাদের সোশ্যাল মিডিয়ায় ট্যাগ করতে ভুলবেন না। আমরা আপনি কী করেন তা দেখতে আমরা পছন্দ করব।
ওয়েবসাইট চেক আউট
- টেনসরফ্লো.জেএস অফিসিয়াল ওয়েবসাইট
- টেনসরফ্লো.জেএস প্রাক-তৈরি মডেল
- টেনসরফ্লো.জেএস এপিআই
- টেনসরফ্লো.জেএস দেখান এবং বলুন - অনুপ্রাণিত হন এবং অন্যরা কী তৈরি করেছে তা দেখুন।
1. আপনি শুরু করার আগে
টেনসরফ্লো.জেএস মডেল ব্যবহার গত কয়েক বছর ধরে তাত্পর্যপূর্ণভাবে বৃদ্ধি পেয়েছে এবং অনেক জাভাস্ক্রিপ্ট বিকাশকারী এখন বিদ্যমান অত্যাধুনিক মডেলগুলি গ্রহণ করতে এবং তাদের শিল্পের জন্য অনন্য কাস্টম ডেটা নিয়ে কাজ করার জন্য তাদের পুনরায় প্রশিক্ষণ দিতে চাইছেন। একটি বিদ্যমান মডেল গ্রহণের কাজটি (প্রায়শই একটি বেস মডেল হিসাবে পরিচিত) এবং এটি অনুরূপ তবে বিভিন্ন ডোমেনে ব্যবহার করা স্থানান্তর শেখার হিসাবে পরিচিত।
সম্পূর্ণ ফাঁকা মডেল থেকে শুরু করে স্থানান্তর শিক্ষার অনেক সুবিধা রয়েছে। আপনি পূর্বের প্রশিক্ষিত মডেল থেকে ইতিমধ্যে শিখে নেওয়া জ্ঞান পুনরায় ব্যবহার করতে পারেন এবং আপনি যে নতুন আইটেমটি শ্রেণিবদ্ধ করতে চান তার কম উদাহরণ প্রয়োজন। এছাড়াও, পুরো নেটওয়ার্কের পরিবর্তে মডেল আর্কিটেকচারের চূড়ান্ত কয়েকটি স্তরগুলি পুনরায় প্রশিক্ষণ দেওয়ার কারণে প্রশিক্ষণ প্রায়শই উল্লেখযোগ্যভাবে দ্রুত হয়। এই কারণে, ট্রান্সফার লার্নিং ওয়েব ব্রাউজার পরিবেশের জন্য খুব উপযুক্ত যেখানে সম্পদ সম্পাদনের ডিভাইসের ভিত্তিতে সংস্থানগুলি পরিবর্তিত হতে পারে, তবে সহজ ডেটা অধিগ্রহণের জন্য সেন্সরগুলিতে সরাসরি অ্যাক্সেস রয়েছে।
এই কোডল্যাব আপনাকে গুগলের জনপ্রিয় " টিচেবল মেশিন " ওয়েবসাইটটি পুনরুদ্ধার করে কীভাবে একটি ফাঁকা ক্যানভাস থেকে একটি ওয়েব অ্যাপ্লিকেশন তৈরি করবেন তা দেখায়। ওয়েবসাইটটি আপনাকে একটি কার্যকরী ওয়েব অ্যাপ্লিকেশন তৈরি করতে দেয় যা কোনও ব্যবহারকারী তাদের ওয়েবক্যামের কয়েকটি উদাহরণ চিত্র সহ একটি কাস্টম অবজেক্টকে সনাক্ত করতে ব্যবহার করতে পারে। ওয়েবসাইটটি উদ্দেশ্যমূলকভাবে ন্যূনতম রাখা হয়েছে যাতে আপনি এই কোডল্যাবের মেশিন লার্নিং দিকগুলিতে ফোকাস করতে পারেন। মূল টিচেবল মেশিন ওয়েবসাইটের মতো, তবে, ইউএক্স উন্নত করতে আপনার বিদ্যমান ওয়েব বিকাশকারী অভিজ্ঞতা প্রয়োগ করার প্রচুর সুযোগ রয়েছে।
পূর্বশর্ত
এই কোডল্যাবটি ওয়েব বিকাশকারীদের জন্য লেখা হয়েছে যারা টেনসরফ্লো.জেএস প্রাক-তৈরি মডেল এবং বেসিক এপিআই ব্যবহারের সাথে কিছুটা পরিচিত এবং যারা ট্রান্সফার লার্নিং ইনটেনসরফ্লো.জেএস দিয়ে শুরু করতে চান।
- টেনসরফ্লো.জেএস, এইচটিএমএল 5, সিএসএস এবং জাভাস্ক্রিপ্টের সাথে প্রাথমিক পরিচিতি এই ল্যাবটির জন্য ধরে নেওয়া হয়েছে।
আপনি যদি টেনসরফ্লো.জেএসে নতুন হন তবে প্রথমে এই নিখরচায় শূন্যকে হিরো কোর্সে নিয়ে যাওয়া বিবেচনা করুন , যা মেশিন লার্নিং বা টেনসরফ্লো.জেএসের সাথে কোনও পটভূমি ধরে না এবং আপনাকে ছোট পদক্ষেপে আপনার যা জানা দরকার তা শিখিয়ে দেয়।
আপনি কি শিখবেন
- টেনসরফ্লো.জেএস কী এবং কেন আপনার এটি আপনার পরবর্তী ওয়েব অ্যাপে ব্যবহার করা উচিত।
- কীভাবে একটি সরলীকৃত এইচটিএমএল /সিএসএস /জেএস ওয়েবপৃষ্ঠা তৈরি করবেন যা শিক্ষণযোগ্য মেশিন ব্যবহারকারীর অভিজ্ঞতার প্রতিলিপি করে।
- ট্রান্সফার লার্নিংয়ে ব্যবহার করা যেতে পারে এমন চিত্র বৈশিষ্ট্য তৈরি করতে প্রাক-প্রশিক্ষিত বেস মডেল, বিশেষত মোবাইলনেট লোড করতে কীভাবে টেনসরফ্লো.জেএস ব্যবহার করবেন।
- আপনি কীভাবে একাধিক শ্রেণির ডেটা সনাক্ত করতে চান তার জন্য কোনও ব্যবহারকারীর ওয়েবক্যাম থেকে ডেটা কীভাবে সংগ্রহ করবেন।
- কীভাবে একটি মাল্টি-লেয়ার পার্সেপট্রন তৈরি এবং সংজ্ঞায়িত করবেন যা চিত্রের বৈশিষ্ট্যগুলি গ্রহণ করে এবং সেগুলি ব্যবহার করে নতুন অবজেক্টগুলিকে শ্রেণিবদ্ধ করতে শিখেছে।
হ্যাকিং করা যাক ...
আপনি কি প্রয়োজন হবে
- একটি গ্লিচ ডটকম অ্যাকাউন্টটি অনুসরণ করা পছন্দ করা হয়, বা আপনি কোনও ওয়েব পরিবেশন পরিবেশ ব্যবহার করতে পারেন যা আপনি স্বাচ্ছন্দ্য বোধ করেন এবং নিজেকে চালাতে স্বাচ্ছন্দ্য বোধ করেন।
২. টেনসরফ্লো.জেএস কী?
টেনসরফ্লো.জেএস একটি ওপেন সোর্স মেশিন লার্নিং লাইব্রেরি যা জাভাস্ক্রিপ্ট যে কোনও জায়গায় চালাতে পারে। এটি পাইথনে রচিত মূল টেনসরফ্লো লাইব্রেরির উপর ভিত্তি করে এবং জাভাস্ক্রিপ্ট ইকোসিস্টেমের জন্য এই বিকাশকারী অভিজ্ঞতা এবং এপিআইগুলির সেট পুনরায় তৈরি করার লক্ষ্য।
এটা কোথায় ব্যবহার করা যেতে পারে?
জাভাস্ক্রিপ্টের বহনযোগ্যতা দেওয়া, আপনি এখন 1 টি ভাষায় লিখতে পারেন এবং নিম্নলিখিত সমস্ত প্ল্যাটফর্মগুলিতে সহজেই মেশিন লার্নিং করতে পারেন:
- ভ্যানিলা জাভাস্ক্রিপ্ট ব্যবহার করে ওয়েব ব্রাউজারে ক্লায়েন্ট সাইড
- সার্ভার সাইড এবং এমনকি রাস্পবেরি পাই এর মতো আইওটি ডিভাইসগুলি নোড.জেএস ব্যবহার করে
- ইলেক্ট্রন ব্যবহার করে ডেস্কটপ অ্যাপ্লিকেশন
- রিঅ্যাক্ট নেটিভ ব্যবহার করে নেটিভ মোবাইল অ্যাপ্লিকেশনগুলি
Tensorflow.js এছাড়াও এই পরিবেশগুলির মধ্যে একাধিক ব্যাকেন্ডকে সমর্থন করে (প্রকৃত হার্ডওয়্যার ভিত্তিক পরিবেশ এটি যেমন সিপিইউ বা ওয়েবজিএল এর মধ্যে কার্যকর করতে পারে example সামঞ্জস্যতা নিশ্চিত করতে এবং জিনিসগুলিকে দ্রুত চালিয়ে রাখতে উদাহরণস্বরূপ ওয়েবজিএল -তে ক্লায়েন্টের দিক হতে পারে)। বর্তমানে টেনসরফ্লো.জেএস সমর্থন করে:
- ডিভাইসের গ্রাফিক্স কার্ডে (জিপিইউ) ওয়েবজিএল এক্সিকিউশন - জিপিইউ ত্বরণ সহ বৃহত্তর মডেলগুলি (আকারে 3 এমবি এর বেশি) কার্যকর করার এটি দ্রুততম উপায়।
- সিপিইউতে ওয়েব অ্যাসেম্বলি (ডাব্লুএএসএম) এক্সিকিউশন - উদাহরণস্বরূপ পুরানো প্রজন্মের মোবাইল ফোন সহ ডিভাইসগুলিতে সিপিইউ পারফরম্যান্স উন্নত করতে। এটি ছোট মডেলগুলির সাথে আরও উপযুক্ত (আকারে 3MB এর চেয়ে কম) যা গ্রাফিক্স প্রসেসরে সামগ্রী আপলোড করার কারণে ওয়েবজিএল এর চেয়ে সিপিইউতে দ্রুত কার্যকর করতে পারে।
- সিপিইউ এক্সিকিউশন - ফ্যালব্যাকের অন্য কোনও পরিবেশের উপলব্ধ থাকা উচিত নয়। এটি তিনটির মধ্যে ধীরতম তবে সর্বদা আপনার জন্য থাকে।
দ্রষ্টব্য: আপনি কোন ডিভাইসটি কার্যকর করবেন তা যদি আপনি জানেন তবে আপনি এই ব্যাকেন্ডগুলির মধ্যে একটিকে জোর করে বেছে নিতে পারেন, বা আপনি যদি এটি নির্দিষ্ট না করেন তবে আপনি কেবল টেনসরফ্লো.জেএস আপনার জন্য সিদ্ধান্ত নিতে পারেন।
ক্লায়েন্ট সাইড সুপার পাওয়ারস
ক্লায়েন্ট মেশিনে ওয়েব ব্রাউজারে টেনসরফ্লো.জেএস চালানো বেশ কয়েকটি সুবিধার দিকে নিয়ে যেতে পারে যা বিবেচনা করার মতো।
গোপনীয়তা
আপনি উভয়ই তৃতীয় পক্ষের ওয়েব সার্ভারে ডেটা প্রেরণ না করে ক্লায়েন্ট মেশিনে ডেটা প্রশিক্ষণ এবং শ্রেণিবদ্ধ করতে পারেন। এমন অনেক সময় থাকতে পারে যেখানে উদাহরণস্বরূপ জিডিপিআর যেমন স্থানীয় আইন মেনে চলার প্রয়োজন হতে পারে বা ব্যবহারকারীরা তাদের মেশিনে রাখতে চাইতে পারে এমন কোনও ডেটা প্রক্রিয়াকরণের সময় এবং তৃতীয় পক্ষের কাছে প্রেরণ না করে।
গতি
যেহেতু আপনাকে কোনও রিমোট সার্ভারে ডেটা প্রেরণ করতে হবে না, অনুমান (ডেটা শ্রেণিবদ্ধকরণের আইন) দ্রুত হতে পারে। আরও ভাল, আপনার কাছে ডিভাইসের সেন্সরগুলিতে সরাসরি অ্যাক্সেস রয়েছে যেমন ক্যামেরা, মাইক্রোফোন, জিপিএস, অ্যাক্সিলোমিটার এবং আরও অনেক কিছু ব্যবহারকারী আপনাকে অ্যাক্সেস মঞ্জুর করা উচিত।
পৌঁছনো এবং স্কেল
বিশ্বের যে কোনও ক্লিক দিয়ে বিশ্বের যে কোনও লিঙ্ক আপনি তাদের প্রেরণ করেছেন, তাদের ব্রাউজারে ওয়েব পৃষ্ঠাটি খুলতে এবং আপনি যা তৈরি করেছেন তা ব্যবহার করতে পারেন। সিউডিএ ড্রাইভারদের সাথে জটিল সার্ভার সাইড লিনাক্স সেটআপের প্রয়োজন নেই এবং আরও অনেক কিছু কেবল মেশিন লার্নিং সিস্টেমটি ব্যবহার করার জন্য।
খরচ
কোনও সার্ভার মানে আপনার এইচটিএমএল, সিএসএস, জেএস এবং মডেল ফাইলগুলি হোস্ট করার জন্য একটি সিডিএন হ'ল কেবলমাত্র আপনাকে অর্থ প্রদান করতে হবে। সিডিএন এর ব্যয় 24/7 চলমান একটি সার্ভার (সম্ভাব্যভাবে একটি গ্রাফিক্স কার্ড সংযুক্ত) রাখার চেয়ে অনেক সস্তা।
সার্ভার সাইড বৈশিষ্ট্য
টেনসরফ্লো.জেএস এর নোড.জেএস বাস্তবায়নকে উপকারে নিম্নলিখিত বৈশিষ্ট্যগুলি সক্ষম করে।
সম্পূর্ণ চুদা সমর্থন
সার্ভারের পাশে, গ্রাফিক্স কার্ডের ত্বরণের জন্য, আপনাকে অবশ্যই গ্রাফিক্স কার্ডের সাথে কাজ করতে টেনসরফ্লো সক্ষম করতে এনভিডিয়া চুদা ড্রাইভারগুলি ইনস্টল করতে হবে (ব্রাউজারের বিপরীতে যা ওয়েবজিএল ব্যবহার করে - কোনও ইনস্টল প্রয়োজন নেই)। তবে সম্পূর্ণ সিইউডিএ সমর্থন দিয়ে আপনি গ্রাফিক্স কার্ডের নিম্ন স্তরের ক্ষমতাগুলি পুরোপুরি উপার্জন করতে পারেন, যা দ্রুত প্রশিক্ষণ এবং অনুমানের সময়গুলির দিকে পরিচালিত করে। পারফরম্যান্স পাইথন টেনসরফ্লো বাস্তবায়নের সাথে সমতা অর্জন করছে কারণ তারা উভয়ই একই সি ++ ব্যাকএন্ড ভাগ করে নেয়।
মডেলের আকার
গবেষণা থেকে প্রান্ত মডেলগুলি কাটার জন্য, আপনি খুব বড় মডেলগুলির সাথে কাজ করছেন, সম্ভবত গিগাবাইটগুলি আকারে। ব্রাউজার ট্যাব প্রতি মেমরি ব্যবহারের সীমাবদ্ধতার কারণে এই মডেলগুলি বর্তমানে ওয়েব ব্রাউজারে চালানো যাবে না। এই বৃহত্তর মডেলগুলি চালানোর জন্য আপনি আপনার নিজের সার্ভারে নোড.জেএস ব্যবহার করতে পারেন হার্ডওয়্যার স্পেসিফিকেশনগুলির সাথে আপনাকে এমন একটি মডেল দক্ষতার সাথে চালানোর জন্য প্রয়োজন।
আইওটি
নোড.জেএস রাস্পবেরি পাই এর মতো জনপ্রিয় একক বোর্ড কম্পিউটারগুলিতে সমর্থিত, যার ফলস্বরূপ আপনি এই জাতীয় ডিভাইসে টেনসরফ্লো.জেএস মডেলগুলিও কার্যকর করতে পারেন।
গতি
নোড.জেএস জাভাস্ক্রিপ্টে লেখা হয়েছে যার অর্থ এটি কেবল সময়ের সংকলন থেকে উপকৃত হয়। এর অর্থ হ'ল নোড.জেএস ব্যবহার করার সময় আপনি প্রায়শই পারফরম্যান্স লাভ দেখতে পাবেন কারণ এটি রানটাইমে অনুকূলিত হবে, বিশেষত আপনি যে কোনও প্রিপ্রোসেসিংয়ের জন্য করছেন। এর একটি দুর্দান্ত উদাহরণ এই কেস স্টাডিতে দেখা যায় যা দেখায় যে কীভাবে আলিঙ্গন মুখ নোড.জেএস ব্যবহার করেছে তাদের প্রাকৃতিক ভাষা প্রক্রিয়াকরণ মডেলের জন্য 2x পারফরম্যান্স উত্সাহ পেতে।
এখন আপনি টেনসরফ্লো.জেএস এর মূল বিষয়গুলি বুঝতে পেরেছেন, যেখানে এটি চালাতে পারে এবং কিছু সুবিধাগুলি, আসুন এটির সাথে দরকারী জিনিসগুলি করা শুরু করি!
3. স্থানান্তর শিখুন
ট্রান্সফার লার্নিং ঠিক কী?
স্থানান্তর শেখার মধ্যে এমন জ্ঞান নেওয়া জড়িত যা ইতিমধ্যে একটি আলাদা তবে অনুরূপ জিনিস শিখতে শিখেছে।
আমরা মানুষ সর্বদা এটি করি। আপনার মস্তিষ্কে আপনার আজীবন অভিজ্ঞতা রয়েছে যা আপনি আগে কখনও দেখেন নি এমন নতুন জিনিসগুলি সনাক্ত করতে সহায়তা করতে পারেন। উদাহরণস্বরূপ এই উইলো গাছটি নিন:
আপনি পৃথিবীতে কোথায় আছেন তার উপর নির্ভর করে এমন একটি সুযোগ রয়েছে যা আপনি আগে এই ধরণের গাছটি দেখেন নি।
তবুও যদি আমি আপনাকে বলতে বলি যে নীচের নতুন চিত্রটিতে কোনও উইলো গাছ রয়েছে কিনা তবে আপনি সম্ভবত এগুলি খুব দ্রুত স্পট করতে পারেন, যদিও সেগুলি অন্য কোনও কোণে রয়েছে এবং আমি আপনাকে দেখিয়েছি এমন মূলটির চেয়ে কিছুটা আলাদা।
আপনার মস্তিষ্কে ইতিমধ্যে একগুচ্ছ নিউরন রয়েছে যা গাছের মতো বস্তুগুলি কীভাবে সনাক্ত করতে পারে এবং অন্যান্য নিউরনগুলি দীর্ঘ সোজা রেখাগুলি খুঁজে পেতে ভাল। আপনি সেই জ্ঞানটিকে দ্রুত একটি উইলো গাছকে শ্রেণিবদ্ধ করার জন্য পুনরায় ব্যবহার করতে পারেন, এটি গাছের মতো বস্তু যা প্রচুর দীর্ঘ সোজা উল্লম্ব শাখা রয়েছে।
একইভাবে, যদি আপনার কাছে কোনও মেশিন লার্নিং মডেল থাকে যা ইতিমধ্যে কোনও ডোমেনে প্রশিক্ষণপ্রাপ্ত, যেমন চিত্রগুলি স্বীকৃতি দেওয়ার মতো, আপনি এটি একটি আলাদা তবে সম্পর্কিত কাজ সম্পাদন করতে পুনরায় ব্যবহার করতে পারেন।
আপনি মোবাইলনেটের মতো উন্নত মডেলের সাথে একই কাজ করতে পারেন, এটি একটি খুব জনপ্রিয় গবেষণা মডেল যা 1000 বিভিন্ন অবজেক্টের ধরণের চিত্রের স্বীকৃতি সম্পাদন করতে পারে। কুকুর থেকে গাড়ি পর্যন্ত, এটি একটি বিশাল ডেটাসেটে প্রশিক্ষিত হয়েছিল যা ইমেজেনেট নামে পরিচিত যা লক্ষ লক্ষ লেবেলযুক্ত চিত্র রয়েছে।
এই অ্যানিমেশনটিতে, আপনি এই মোবাইলনেট ভি 1 মডেলটিতে এটির বিশাল সংখ্যক স্তর দেখতে পাচ্ছেন:
এর প্রশিক্ষণের সময়, এই মডেলটি শিখেছে যে কীভাবে সাধারণ বৈশিষ্ট্যগুলি এই 1000 টি অবজেক্টের জন্য গুরুত্বপূর্ণ, এবং এই জাতীয় অবজেক্টগুলি সনাক্ত করতে যে নিম্ন স্তরের বৈশিষ্ট্যগুলি ব্যবহার করে তার অনেকগুলি এটি আগে কখনও দেখেনি এমন নতুন অবজেক্টগুলি সনাক্ত করতে কার্যকর হতে পারে। সর্বোপরি, সবকিছু শেষ পর্যন্ত কেবল লাইন, টেক্সচার এবং আকারের সংমিশ্রণ।
আসুন আমরা একটি traditional তিহ্যবাহী কনভোলিউশনাল নিউরাল নেটওয়ার্ক (সিএনএন) আর্কিটেকচার (মোবাইলনেটের অনুরূপ) এ একবার দেখে নিই এবং দেখুন কীভাবে স্থানান্তর শেখা এই প্রশিক্ষিত নেটওয়ার্ককে নতুন কিছু শিখতে কীভাবে উপার্জন করতে পারে। নীচের চিত্রটি একটি সিএনএন -এর সাধারণ মডেল আর্কিটেকচার দেখায় যা এই ক্ষেত্রে 0 থেকে 9 পর্যন্ত হস্তাক্ষরযুক্ত অঙ্কগুলি সনাক্ত করতে প্রশিক্ষণ দেওয়া হয়েছিল:
ডানদিকে প্রদর্শিত মডেলের শেষের নিকটবর্তী শ্রেণিবিন্যাস স্তরগুলি থেকে আপনি যদি বামদিকে প্রদর্শিত বিদ্যমান প্রশিক্ষিত মডেলের প্রাক-প্রশিক্ষিত নিম্ন স্তরের স্তরগুলি পৃথক করতে পারেন তবে (কখনও কখনও মডেলের শ্রেণিবিন্যাস প্রধান হিসাবে পরিচিত), আপনি প্রশিক্ষিত মূল ডেটার উপর ভিত্তি করে প্রদত্ত যে কোনও চিত্রের জন্য আউটপুট বৈশিষ্ট্যগুলি উত্পাদন করতে আপনি নিম্ন স্তরের স্তরগুলি ব্যবহার করতে পারেন। শ্রেণিবিন্যাসের মাথাটি সরানো সহ এখানে একই নেটওয়ার্ক রয়েছে:
আপনি যে নতুন জিনিসটি স্বীকৃতি দেওয়ার চেষ্টা করছেন তা ধরে নেওয়া পূর্ববর্তী মডেলটি শিখেছে এমন আউটপুট বৈশিষ্ট্যগুলিও ব্যবহার করতে পারে, তারপরে তাদের নতুন উদ্দেশ্যে পুনরায় ব্যবহার করা যেতে পারে এমন একটি ভাল সুযোগ রয়েছে।
উপরের চিত্রটিতে, এই অনুমানমূলক মডেলটি অঙ্কগুলিতে প্রশিক্ষিত ছিল, সুতরাং অঙ্কগুলি সম্পর্কে যা শিখেছিল তা এ, বি এবং সি এর মতো বর্ণগুলিতেও প্রয়োগ করা যেতে পারে।
সুতরাং এখন আপনি একটি নতুন শ্রেণিবিন্যাসের মাথা যুক্ত করতে পারেন যা পরিবর্তে এ, বি, বা সি এর পূর্বাভাস দেওয়ার চেষ্টা করে, যেমন দেখানো হয়েছে:
এখানে নিম্ন স্তরের স্তরগুলি হিমশীতল এবং প্রশিক্ষিত নয়, কেবল নতুন শ্রেণিবিন্যাসের প্রধান বাম দিকে প্রাক-প্রশিক্ষিত কাটা আপ মডেল থেকে প্রদত্ত বৈশিষ্ট্যগুলি থেকে শিখতে নিজেকে আপডেট করবে।
এটি করার কাজটি ট্রান্সফার লার্নিং হিসাবে পরিচিত এবং টিচেবল মেশিনটি পর্দার আড়ালে যা করে।
আপনি এটিও দেখতে পাচ্ছেন যে নেটওয়ার্কের একেবারে শেষে কেবল মাল্টি-লেয়ার পার্সেপট্রনকে প্রশিক্ষণ দেওয়ার মাধ্যমে, আপনাকে পুরো নেটওয়ার্কটি স্ক্র্যাচ থেকে প্রশিক্ষণ দিতে হবে তার চেয়ে অনেক দ্রুত ট্রেন করে।
তবে আপনি কীভাবে কোনও মডেলের উপ-অংশগুলিতে আপনার হাত পেতে পারেন? খুঁজে বের করতে পরবর্তী বিভাগে যান।
4. টেনসরফ্লো হাব - বেস মডেল
ব্যবহারের জন্য একটি উপযুক্ত বেস মডেল সন্ধান করুন
মোবাইলনেটের মতো আরও উন্নত এবং জনপ্রিয় গবেষণা মডেলগুলির জন্য, আপনি টেনসরফ্লো হাবে যেতে পারেন এবং তারপরে টেনসরফ্লো.জেএসের জন্য উপযুক্ত মডেলগুলির জন্য ফিল্টার করতে পারেন যা এখানে প্রদর্শিতগুলির মতো ফলাফলগুলি খুঁজে পেতে মোবাইলনেট ভি 3 আর্কিটেকচার ব্যবহার করে :
নোট করুন যে এর মধ্যে কয়েকটি ফলাফল "চিত্র শ্রেণিবদ্ধকরণ" টাইপের (প্রতিটি মডেল কার্ডের ফলাফলের শীর্ষে বিশদ) এবং অন্যরা "চিত্র বৈশিষ্ট্য ভেক্টর" টাইপের।
এই চিত্র বৈশিষ্ট্য ভেক্টর ফলাফলগুলি মূলত মোবাইলনেটের প্রাক-চপড আপ সংস্করণগুলি যা আপনি চূড়ান্ত শ্রেণিবিন্যাসের পরিবর্তে চিত্র বৈশিষ্ট্য ভেক্টরগুলি পেতে ব্যবহার করতে পারেন।
এর মতো মডেলগুলিকে প্রায়শই "বেস মডেলস" বলা হয় যা আপনি তারপরে নতুন শ্রেণিবিন্যাসের মাথা যুক্ত করে এবং এটি আপনার নিজের ডেটা দিয়ে প্রশিক্ষণ দিয়ে পূর্ববর্তী বিভাগে যেমন দেখানো হয়েছে তেমন একই পদ্ধতিতে স্থানান্তর শেখার জন্য ব্যবহার করতে পারেন।
পরবর্তী জিনিসটি হ'ল টেনসরফ্লো.জেএস ফর্ম্যাটটি মডেল হিসাবে প্রকাশিত হয় তার আগ্রহের একটি প্রদত্ত বেস মডেলের জন্য। আপনি যদি এই বৈশিষ্ট্য ভেক্টর মোবাইলনেট ভি 3 মডেলগুলির একটির জন্য পৃষ্ঠাটি খোলেন তবে আপনি জেএস ডকুমেন্টেশন থেকে দেখতে পাচ্ছেন যে এটি ডকুমেন্টেশনের উদাহরণ কোড স্নিপেটের উপর ভিত্তি করে একটি গ্রাফ মডেলের আকারে যা tf.loadGraphModel()
ব্যবহার করে।
এটিও লক্ষ করা উচিত যে আপনি যদি গ্রাফ ফর্ম্যাটের পরিবর্তে স্তর বিন্যাসে কোনও মডেল খুঁজে পান তবে আপনি কোন স্তরগুলি হিমায়িত করতে পারেন এবং কোন প্রশিক্ষণের জন্য আনফিজ করতে হবে তা চয়ন করতে পারেন। কোনও নতুন কাজের জন্য একটি মডেল তৈরি করার সময় এটি খুব শক্তিশালী হতে পারে, যা প্রায়শই "স্থানান্তর মডেল" হিসাবে পরিচিত। আপাতত, তবে আপনি এই টিউটোরিয়ালটির জন্য ডিফল্ট গ্রাফ মডেল প্রকারটি ব্যবহার করবেন, যা বেশিরভাগ টিএফ হাব মডেল হিসাবে মোতায়েন করা হয়। স্তরগুলির মডেলগুলির সাথে কাজ করার বিষয়ে আরও জানতে, হিরো টেনসরফ্লো.জেএস কোর্সে শূন্যটি দেখুন।
স্থানান্তর শিক্ষার সুবিধা
স্ক্র্যাচ থেকে পুরো মডেল আর্কিটেকচারকে প্রশিক্ষণের পরিবর্তে ট্রান্সফার লার্নিং ব্যবহারের সুবিধাগুলি কী?
প্রথমত, প্রশিক্ষণের সময়টি স্থানান্তর শেখার পদ্ধতির ব্যবহার করার জন্য একটি মূল সুবিধা কারণ আপনার ইতিমধ্যে তৈরি করার জন্য একটি প্রশিক্ষিত বেস মডেল রয়েছে।
দ্বিতীয়ত, আপনি ইতিমধ্যে সংঘটিত প্রশিক্ষণের কারণে আপনি যে নতুন জিনিসটি শ্রেণিবদ্ধ করার চেষ্টা করছেন তার অনেক কম উদাহরণ দেখিয়ে আপনি পালিয়ে যেতে পারেন।
আপনি যদি শ্রেণিবদ্ধ করতে চান তার উদাহরণ ডেটা সংগ্রহ করার জন্য আপনার সীমিত সময় এবং সংস্থানগুলি থাকলে এটি সত্যিই দুর্দান্ত এবং এটি আরও দৃ ust ় করার জন্য আরও প্রশিক্ষণের ডেটা সংগ্রহ করার আগে দ্রুত একটি প্রোটোটাইপ তৈরি করা দরকার।
কম ডেটার প্রয়োজন এবং একটি ছোট নেটওয়ার্ক প্রশিক্ষণের গতি প্রয়োজন, স্থানান্তর শেখার কম সংস্থান নিবিড়। এটি এটি ব্রাউজারের পরিবেশের জন্য খুব উপযুক্ত করে তোলে, পুরো মডেল প্রশিক্ষণের জন্য ঘন্টা, দিন বা সপ্তাহের পরিবর্তে আধুনিক মেশিনে মাত্র কয়েক সেকেন্ড সময় নেয়।
ঠিক আছে! স্থানান্তর শেখার কী তা এখন আপনি জানেন, এটি আপনার শিক্ষণযোগ্য মেশিনের নিজস্ব সংস্করণ তৈরি করার সময় এসেছে। চলুন শুরু করা যাক!
5. কোড সেট আপ করুন
আপনি কি প্রয়োজন হবে
- একটি আধুনিক ওয়েব ব্রাউজার।
- এইচটিএমএল, সিএসএস, জাভাস্ক্রিপ্ট এবং ক্রোম ডিভটুলস (কনসোল আউটপুটটি দেখছে) এর প্রাথমিক জ্ঞান।
কোডিং করা যাক
শুরু করতে বয়লারপ্লেট টেম্পলেটগুলি গ্লিচ ডটকম বা কোডপেন.আইওর জন্য তৈরি করা হয়েছে। আপনি কেবল একটি ক্লিকে এই কোড ল্যাবের জন্য আপনার বেস স্টেট হিসাবে টেম্পলেটকে কেবল ক্লোন করতে পারেন।
গ্লিচ এ, এটি কাঁটাচামচ করতে " এই রিমিক্স এই" বোতামটি ক্লিক করুন এবং আপনি সম্পাদনা করতে পারেন এমন ফাইলগুলির একটি নতুন সেট তৈরি করুন।
বিকল্পভাবে, কোডপেনে, স্ক্রিনের নীচের নীচে ডানদিকে " কাঁটাচামচ" ক্লিক করুন।
এই খুব সাধারণ কঙ্কাল আপনাকে নিম্নলিখিত ফাইলগুলি সরবরাহ করে:
- এইচটিএমএল পৃষ্ঠা (সূচক। এইচটিএমএল)
- স্টাইলশীট (style.css)
- আমাদের জাভাস্ক্রিপ্ট কোড লিখতে ফাইল (স্ক্রিপ্ট.জেএস)
আপনার সুবিধার জন্য, টেনসরফ্লো.জেএস লাইব্রেরির জন্য এইচটিএমএল ফাইলে একটি অতিরিক্ত আমদানি রয়েছে। এটি এই মত দেখায়:
index.html
<!-- Import TensorFlow.js library -->
<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs/dist/tf.min.js" type="text/javascript"></script>
বিকল্প: আপনার পছন্দসই ওয়েবডিটার ব্যবহার করুন বা স্থানীয়ভাবে কাজ করুন
আপনি যদি কোডটি ডাউনলোড করতে এবং স্থানীয়ভাবে কাজ করতে চান, বা অন্য কোনও অনলাইন সম্পাদকটিতে কাজ করতে চান তবে কেবল একই ডিরেক্টরিতে উপরে বর্ণিত 3 টি ফাইল তৈরি করুন এবং আমাদের গ্লিচ বয়লারপ্লেট থেকে কোডটি অনুলিপি করুন এবং সেগুলির প্রত্যেকটিতে পেস্ট করুন।
6. অ্যাপ্লিকেশন এইচটিএমএল বয়লারপ্লেট
কোথায় শুরু করব?
সমস্ত প্রোটোটাইপগুলির জন্য কিছু বেসিক এইচটিএমএল স্ক্যাফোল্ডিং প্রয়োজন যা আপনি আপনার অনুসন্ধানগুলি রেন্ডার করতে পারেন। এখনই সেট আপ করুন। আপনি যোগ করতে যাচ্ছেন:
- পৃষ্ঠার জন্য একটি শিরোনাম।
- কিছু বর্ণনামূলক পাঠ্য।
- একটি স্থিতি অনুচ্ছেদ।
- ওয়েবক্যাম ফিডটি একবার প্রস্তুত করার জন্য একটি ভিডিও।
- ক্যামেরা শুরু করতে, ডেটা সংগ্রহ করতে বা অভিজ্ঞতাটি পুনরায় সেট করার জন্য বেশ কয়েকটি বোতাম।
- টেনসরফ্লো.জেএস এবং জেএস ফাইলগুলির জন্য আমদানি আপনি পরে কোড করবেন।
উপরের বৈশিষ্ট্যগুলি সেট আপ করতে নিম্নলিখিত কোডের উপরে 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>
ভেঙ্গে ফেলো
আপনি যুক্ত কিছু মূল বিষয় হাইলাইট করতে উপরের কিছু এইচটিএমএল কোডটি ভেঙে ফেলি।
- আপনি 'স্ট্যাটাস' এর আইডি সহ একটি
<p>
ট্যাগ সহ পৃষ্ঠা শিরোনামের জন্য একটি<h1>
ট্যাগ যুক্ত করেছেন, যেখানে আপনি আউটপুটগুলি দেখতে সিস্টেমের বিভিন্ন অংশ ব্যবহার করেন বলে আপনি তথ্য মুদ্রণ করবেন। - আপনি 'ওয়েবক্যাম' এর একটি আইডি সহ একটি
<video>
উপাদান যুক্ত করেছেন, যাতে আপনি পরে আপনার ওয়েবক্যাম স্ট্রিমটি রেন্ডার করবেন। - আপনি 5
<button>
উপাদান যুক্ত করেছেন। প্রথমটি, 'ইঙ্ক্যালক্যাম' এর আইডি সহ ক্যামেরাটি সক্ষম করে। পরবর্তী দুটি বোতামে 'ডেটাকোলেক্টর' এর একটি শ্রেণি রয়েছে, যা আপনাকে যে অবজেক্টগুলি সনাক্ত করতে চান তার জন্য আপনাকে উদাহরণ চিত্র সংগ্রহ করতে দেয়। আপনি পরে লিখেছেন কোডটি এমনভাবে ডিজাইন করা হবে যাতে আপনি এই বোতামগুলির যে কোনও সংখ্যক যুক্ত করতে পারেন এবং সেগুলি স্বয়ংক্রিয়ভাবে উদ্দেশ্য হিসাবে কাজ করবে।
নোট করুন যে এই বোতামগুলিতে ডেটা -1 হট নামে একটি বিশেষ ব্যবহারকারী-সংজ্ঞায়িত বৈশিষ্ট্যও রয়েছে, প্রথম শ্রেণীর জন্য 0 থেকে শুরু হওয়া একটি পূর্ণসংখ্যার মান সহ। এটি একটি নির্দিষ্ট শ্রেণীর ডেটা উপস্থাপন করতে আপনি ব্যবহার করবেন এমন সংখ্যাসূচক সূচক। সূচকটি স্ট্রিংয়ের পরিবর্তে সংখ্যাসূচক উপস্থাপনা সহ সঠিকভাবে আউটপুট ক্লাসগুলি এনকোড করতে ব্যবহৃত হবে, কারণ এমএল মডেলগুলি কেবল সংখ্যার সাথে কাজ করতে পারে।
এছাড়াও একটি ডেটা-নাম বৈশিষ্ট্য রয়েছে যা এই শ্রেণীর জন্য আপনি ব্যবহার করতে চান এমন মানব পঠনযোগ্য নাম রয়েছে, যা আপনাকে 1 টি হট এনকোডিং থেকে সংখ্যার সূচক মানের পরিবর্তে ব্যবহারকারীর আরও অর্থবহ নাম সরবরাহ করতে দেয়।
Finally, you have a train and reset button to kick off the training process once data has been collected, or to reset the app respectively.
- You also added 2
<script>
imports. One for TensorFlow.js, and the other for script.js that you will define shortly.
7. Add style
Element defaults
Add styles for the HTML elements you just added to ensure they render correctly. Here are some styles that are added to position and size elements correctly. খুব বিশেষ কিছু না. You could certainly add to this later to make an even better UX, like you saw in the teachable machine video.
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%;
}
দারুণ! যে সব আপনার প্রয়োজন. If you preview the output right now, it should look something like this:
8. JavaScript: Key constants and listeners
Define key constants
First, add some key constants you'll use throughout the app. Start by replacing the contents of script.js
with these constants:
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 = [];
Let's break down what these are for:
-
STATUS
simply holds a reference to the paragraph tag you will write status updates to. -
VIDEO
holds a reference to the HTML video element that will render the webcam feed. -
ENABLE_CAM_BUTTON
,RESET_BUTTON
, andTRAIN_BUTTON
grab DOM references to all the key buttons from the HTML page. -
MOBILE_NET_INPUT_WIDTH
andMOBILE_NET_INPUT_HEIGHT
define the expected input width and height of the MobileNet model respectively. By storing this in a constant near the top of the file like this, if you decide to use a different version later, it makes it easier to update the values once instead of having to replace it in many different places. -
STOP_DATA_GATHER
is set to - 1. This stores a state value so you know when the user has stopped clicking a button to gather data from the webcam feed. By giving this number a more meaningful name, it makes the code more readable later. -
CLASS_NAMES
acts as a lookup and holds the human readable names for the possible class predictions. This array will be populated later.
OK, now that you have references to key elements, it is time to associate some event listeners to them.
Add key event listeners
Start by adding click event handlers to key buttons as shown:
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
- calls the enableCam function when clicked.
TRAIN_BUTTON
- calls trainAndPredict when clicked.
RESET_BUTTON
- calls reset when clicked.
Finally in this section you can find all buttons that have a class of 'dataCollector' using document.querySelectorAll()
. This returns an array of elements found from the document that match:
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!
}
কোড ব্যাখ্যা:
You then iterate through the found buttons and associate 2 event listeners to each. One for 'mousedown', and one for 'mouseup'. This lets you keep recording samples as long as the button is pressed, which is useful for data collection.
Both events call a gatherDataForClass
function that you will define later.
At this point, you can also push the found human readable class names from the HTML button attribute data-name to the CLASS_NAMES
array.
Next, add some variables to store key things that will be used later.
script.js
let mobilenet = undefined;
let gatherDataState = STOP_DATA_GATHER;
let videoPlaying = false;
let trainingDataInputs = [];
let trainingDataOutputs = [];
let examplesCount = [];
let predict = false;
Let's walk through those.
First, you have a variable mobilenet
to store the loaded mobilenet model. Initially set this to undefined.
Next, you have a variable called gatherDataState
. If a 'dataCollector' button is pressed, this changes to be the 1 hot ID of that button instead, as defined in the HTML, so you know what class of data you are collecting at that moment. Initially, this is set to STOP_DATA_GATHER
so that the data gather loop you write later will not gather any data when no buttons are being pressed.
videoPlaying
keeps track of whether the webcam stream is successfully loaded and playing and is available to use. Initially, this is set to false
as the webcam is not on until you press the ENABLE_CAM_BUTTON.
Next, define 2 arrays, trainingDataInputs
and trainingDataOutputs
. These store the gathered training data values, as you click the 'dataCollector' buttons for the input features generated by MobileNet base model, and the output class sampled respectively.
One final array, examplesCount,
is then defined to keep track of how many examples are contained for each class once you start adding them.
Finally, you have a variable called predict
that controls your prediction loop. This is set to false
initially. No predictions can take place until this is set to true
later.
Now that all the key variables have been defined, let's go and load the pre-chopped up MobileNet v3 base model that provides image feature vectors instead of classifications.
9. Load the MobileNet base model
First, define a new function called loadMobileNetFeatureModel
as shown below. This must be an async function as the act of loading a model is asynchronous:
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();
In this code you define the URL
where the model to load is located from the TFHub documentation.
You can then load the model using await tf.loadGraphModel()
, remembering to set the special property fromTFHub
to true
as you are loading a model from this Google website. This is a special case only for using models hosted on TF Hub where this extra property has to be set.
Once loading is complete you can set the STATUS
element's innerText
with a message so you can visually see it has loaded correctly and you are ready to start gathering data.
The only thing left to do now is to warm up the model. With larger models like this, the first time you use the model, it can take a moment to set everything up. Therefore it helps to pass zeros through the model to avoid any waiting in the future where timing may be more critical.
You can use tf.zeros()
wrapped in a tf.tidy()
to ensure tensors are disposed of correctly, with a batch size of 1, and the correct height and width that you defined in your constants at the start. Finally, you also specify the color channels, which in this case is 3 as the model expects RGB images.
Next, log the resulting shape of the tensor returned using answer.shape()
to help you understand the size of the image features this model produces.
After defining this function, you can then call it immediately to initiate the model download on the page load.
If you view your live preview right now, after a few moments you will see the status text change from "Awaiting TF.js load" to become "MobileNet v3 loaded successfully!" নীচে দেখানো হিসাবে. Ensure this works before continuing.
You can also check the console output to see the printed size of the output features that this model produces. After running zeros through the MobileNet model, you'll see a shape of [1, 1024]
printed. The first item is just the batch size of 1, and you can see it actually returns 1024 features that can then be used to help you classify new objects.
10. Define the new model head
Now it's time to define your model head, which is essentially a very minimal multi-layer perceptron.
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']
});
এর এই কোড মাধ্যমে পদচারণা করা যাক. You start by defining a tf.sequential model to which you will add model layers to.
Next, add a dense layer as the input layer to this model. This has an input shape of 1024
as the outputs from the MobileNet v3 features are of this size. You discovered this in the previous step after passing ones through the model. This layer has 128 neurons that use the ReLU activation function.
If you are new to activation functions and model layers, consider taking the course detailed at the start of this workshop to understand what these properties do behind the scenes.
The next layer to add is the output layer. The number of neurons should equal the number of classes you are trying to predict. To do that you can use CLASS_NAMES.length
to find how many classes you are planning to classify, which is equal to the number of data gather buttons found in the user interface. As this is a classification problem, you use the softmax
activation on this output layer, which must be used when trying to create a model to solve classification problems instead of regression.
Now print a model.summary()
to print the overview of the newly defined model to the console.
Finally, compile the model so it is ready to be trained. Here the optimizer is set to adam
, and the loss will either be binaryCrossentropy
if CLASS_NAMES.length
is equal to 2
, or it will use categoricalCrossentropy
if there are 3 or more classes to classify. Accuracy metrics are also requested so they can be monitored in the logs later for debugging purposes.
In the console you should see something like this:
Note that this has over 130 thousand trainable parameters. But as this is a simple dense layer of regular neurons it will train pretty fast.
As an activity to do once the project is complete, you could try changing the number of neurons in the first layer to see how low you can make it while still getting decent performance. Often with machine learning there is some level of trial and error to find optimal parameter values to give you the best trade off between resource usage and speed.
11. Enable the webcam
It's now time to flesh out the enableCam()
function you defined earlier. Add a new function named hasGetUserMedia()
as shown below and then replace the contents of the previously defined enableCam()
function with the corresponding code below.
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');
}
}
First, create a function named hasGetUserMedia()
to check if the browser supports getUserMedia()
by checking for the existence of key browser APIs properties.
In the enableCam()
function use the hasGetUserMedia()
function you just defined above to check if it is supported. If it isn't, print a warning to the console.
If it supports it, define some constraints for your getUserMedia()
call, such as you want the video stream only, and that you prefer the width
of the video to be 640
pixels in size, and the height
to be 480
pixels. কেন? Well, there is not much point getting a video larger than this as it would need to be resized to 224 by 224 pixels to be fed into the MobileNet model. You may as well save some computing resources by requesting a smaller resolution. Most cameras support a resolution of this size.
Next, call navigator.mediaDevices.getUserMedia()
with the constraints
detailed above, and then wait for the stream
to be returned. Once the stream
is returned you can get your VIDEO
element to play the stream
by setting it as its srcObject
value.
You should also add an eventListener on the VIDEO
element to know when the stream
has loaded and is playing successfully.
Once the steam loads, you can set videoPlaying
to true and remove the ENABLE_CAM_BUTTON
to prevent it from being clicked again by setting its class to " removed
".
Now run your code, click the enable camera button, and allow access to the webcam. If it is your first time doing this, you should see yourself rendered to the video element on the page as shown:
Ok, now it is time to add a function to deal with the dataCollector
button clicks.
12. Data collection button event handler
Now it's time to fill out your currently empty function called gatherDataForClass().
This is what you assigned as your event handler function for dataCollector
buttons at the start of the codelab.
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();
}
First, check the data-1hot
attribute on the currently clicked button by calling this.getAttribute()
with the attribute's name, in this case data-1hot
as the parameter. As this is a string, you can then use parseInt()
to cast it to an integer and assign this result to a variable named classNumber.
Next, set the gatherDataState
variable accordingly. If the current gatherDataState
is equal to STOP_DATA_GATHER
(which you set to be -1), then that means you are not currently gathering any data and it was a mousedown
event that fired. Set the gatherDataState
to be the classNumber
you just found.
Otherwise, it means that you are currently gathering data and the event that fired was a mouseup
event, and you now want to stop gathering data for that class. Just set it back to the STOP_DATA_GATHER
state to end the data gathering loop you will define shortly.
Finally, kick off the call to dataGatherLoop(),
which actually performs the recording of class data.
13. Data collection
Now, define the dataGatherLoop()
function. This function is responsible for sampling images from the webcam video, passing them through the MobileNet model, and capturing the outputs of that model (the 1024 feature vectors).
It then stores them along with the gatherDataState
ID of the button that is currently being pressed so you know what class this data represents.
এর মধ্য দিয়ে চলুন:
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);
}
}
You are only going to continue this function's execution if videoPlaying
is true, meaning that the webcam is active, and gatherDataState
is not equal to STOP_DATA_GATHER
and a button for class data gathering is currently being pressed.
Next, wrap your code in a tf.tidy()
to dispose of any created tensors in the code that follows. The result of this tf.tidy()
code execution is stored in a variable called imageFeatures
.
You can now grab a frame of the webcam VIDEO
using tf.browser.fromPixels()
. The resulting tensor containing the image data is stored in a variable called videoFrameAsTensor
.
Next, resize the videoFrameAsTensor
variable to be of the correct shape for the MobileNet model's input. Use a tf.image.resizeBilinear()
call with the tensor you want to reshape as the first parameter, and then a shape that defines the new height and width as defined by the constants you already created earlier. Finally, set align corners to true by passing the third parameter to avoid any alignment issues when resizing. The result of this resize is stored in a variable called resizedTensorFrame
.
Note that this primitive resize stretches the image, as your webcam image is 640 by 480 pixels in size, and the model needs a square image of 224 by 224 pixels.
For the purposes of this demo this should work fine. However, once you complete this codelab, you may want to try and crop a square from this image instead for even better results for any production system you may create later.
Next, normalize the image data. Image data is always in the range of 0 to 255 when using tf.browser.frompixels()
, so you can simply divide resizedTensorFrame by 255 to ensure all values are between 0 and 1 instead, which is what the MobileNet model expects as inputs.
Finally, in the tf.tidy()
section of the code, push this normalized tensor through the loaded model by calling mobilenet.predict()
, to which you pass the expanded version of the normalizedTensorFrame
using expandDims()
so that it is a batch of 1, as the model expects a batch of inputs for processing.
Once the result comes back, you can then immediately call squeeze()
on that returned result to squash it back down to a 1D tensor, which you then return and assign to the imageFeatures
variable that captures the result from tf.tidy()
.
Now that you have the imageFeatures
from the MobileNet model, you can record those by pushing them onto the trainingDataInputs
array that you defined previously.
You can also record what this input represents by pushing the current gatherDataState
to the trainingDataOutputs
array too.
Note that the gatherDataState
variable would have been set to the current class's numerical ID you are recording data for when the button was clicked in the previously defined gatherDataForClass()
function.
At this point you can also increment the number of examples you have for a given class. To do this, first check if the index within the examplesCount
array has been initialized before or not. If it is undefined, set it to 0 to initialize the counter for a given class's numerical ID, and then you can increment the examplesCount
for the current gatherDataState
.
Now update the STATUS
element's text on the web page to show the current counts for each class as they're captured. To do this, loop through the CLASS_NAMES
array, and print the human readable name combined with the data count at the same index in examplesCount
.
Finally, call window.requestAnimationFrame()
with dataGatherLoop
passed as a parameter, to recursively call this function again. This will continue to sample frames from the video until the button's mouseup
is detected, and gatherDataState
is set to STOP_DATA_GATHER,
at which point the data gather loop will end.
If you run your code now, you should be able to click the enable camera button, await the webcam to load, and then click and hold each of the data gather buttons to gather examples for each class of data. Here you see me gather data for my mobile phone and my hand respectively.
You should see the status text updated as it stores all the tensors in memory as shown in the screen capture above.
14. Train and predict
The next step is to implement code for your currently empty trainAndPredict()
function, which is where the transfer learning takes place. Let's take a look at the code:
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);
}
First, ensure you stop any current predictions from taking place by setting predict
to false
.
Next, shuffle your input and output arrays using tf.util.shuffleCombo()
to ensure the order does not cause issues in training.
Convert your output array, trainingDataOutputs,
to be a tensor1d of type int32 so it is ready to be used in a one hot encoding . This is stored in a variable named outputsAsTensor
.
Use the tf.oneHot()
function with this outputsAsTensor
variable along with the max number of classes to encode, which is just the CLASS_NAMES.length
. Your one hot encoded outputs are now stored in a new tensor called oneHotOutputs
.
Note that currently trainingDataInputs
is an array of recorded tensors. In order to use these for training you will need to convert the array of tensors to become a regular 2D tensor.
To do that there is a great function within the TensorFlow.js library called tf.stack()
,
which takes an array of tensors and stacks them together to produce a higher dimensional tensor as an output. In this case a tensor 2D is returned, that's a batch of 1 dimensional inputs that are each 1024 in length containing the features recorded, which is what you need for training.
Next, await model.fit()
to train the custom model head. Here you pass your inputsAsTensor
variable along with the oneHotOutputs
to represent the training data to use for example inputs and target outputs respectively. In the configuration object for the 3rd parameter, set shuffle
to true
, use batchSize
of 5
, with epochs
set to 10
, and then specify a callback
for onEpochEnd
to the logProgress
function that you will define shortly.
Finally, you can dispose of the created tensors as the model is now trained. You can then set predict
back to true
to allow predictions to take place again, and then call the predictLoop()
function to start predicting live webcam images.
You can also define the logProcess()
function to log the state of training, which is used in model.fit()
above and that prints results to console after each round of training.
আপনি প্রায় সেখানে! Time to add the predictLoop()
function to make predictions.
Core prediction loop
Here you implement the main prediction loop that samples frames from a webcam and continuously predicts what is in each frame with real time results in the browser.
Let's check the code:
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);
}
}
First, check that predict
is true, so that predictions are only made after a model is trained and is available to use.
Next, you can get the image features for the current image just like you did in the dataGatherLoop()
function. Essentially, you grab a frame from the webcam using tf.browser.from pixels()
, normalise it, resize it to be 224 by 224 pixels in size, and then pass that data through the MobileNet model to get the resulting image features.
Now, however, you can use your newly trained model head to actually perform a prediction by passing the resulting imageFeatures
just found through the trained model's predict()
function. You can then squeeze the resulting tensor to make it 1 dimensional again and assign it to a variable called prediction
.
With this prediction
you can find the index that has the highest value using argMax()
, and then convert this resulting tensor to an array using arraySync()
to get at the underlying data in JavaScript to discover the position of the highest valued element. This value is stored in the variable called highestIndex
.
You can also get the actual prediction confidence scores in the same way by calling arraySync()
on the prediction
tensor directly.
You now have everything you need to update the STATUS
text with the prediction
data. To get the human readable string for the class you can just look up the highestIndex
in the CLASS_NAMES
array, and then grab the confidence value from the predictionArray
. To make it more readable as a percentage, just multiply by 100 and math.floor()
the result.
Finally, you can use window.requestAnimationFrame()
to call predictionLoop()
all over again once ready, to get real time classification on your video stream. This continues until predict
is set to false
if you choose to train a new model with new data.
Which brings you to the final piece of the puzzle. Implementing the reset button.
15. Implement the reset button
Almost complete! The final piece of the puzzle is to implement a reset button to start over. The code for your currently empty reset()
function is below. Go ahead and update it as follows:
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);
}
First, stop any running prediction loops by setting predict
to false
. Next, delete all contents in the examplesCount
array by setting its length to 0, which is a handy way to clear all contents from an array.
Now go through all the current recorded trainingDataInputs
and ensure you dispose()
of each tensor contained within it to free up memory again, as Tensors are not cleaned up by the JavaScript garbage collector.
Once that is done you can now safely set the array length to 0 on both the trainingDataInputs
and trainingDataOutputs
arrays to clear those too.
Finally set the STATUS
text to something sensible, and print out the tensors left in memory as a sanity check.
Note that there will be a few hundred tensors still in memory as both the MobileNet model and the multi-layer perceptron you defined are not disposed of. You will need to reuse them with new training data if you decide to train again after this reset.
16. Let's try it out
It's time to test out your very own version of Teachable Machine!
Head to the live preview, enable the webcam, gather at least 30 samples for class 1 for some object in your room, and then do the same for class 2 for a different object, click train, and check the console log to see progress. It should train pretty fast:
Once trained, show the objects to the camera to get live predictions that will be printed to the status text area on the web page near the top. If you are having trouble, check my completed working code to see if you missed copying over anything.
17. অভিনন্দন
অভিনন্দন! You have just completed your very first transfer learning example using TensorFlow.js live in the browser.
Try it out, test it on a variety of objects, you may notice some things are harder to recognize than others, especially if they are similar to something else. You may need to add more classes or training data to be able to tell them apart.
রিক্যাপ
In this codelab you learned:
- What transfer learning is, and its advantages over training a full model.
- How to get models for re-use from TensorFlow Hub.
- How to set up a web app suitable for transfer learning.
- How to load and use a base model to generate image features.
- How to train a new prediction head that can recognize custom objects from webcam imagery.
- How to use the resulting models to classify data in real time.
এরপর কি?
Now that you have a working base to start from, what creative ideas can you come up with to extend this machine learning model boilerplate for a real world use case you may be working on? Maybe you could revolutionize the industry that you currently work in to help folk at your company train models to classify things that are important in their day-to-day work? সম্ভাবনা অন্তহীন.
To go further, consider taking this full course for free , which shows you how to combine the 2 models you currently have in this codelab into 1 single model for efficiency.
Also if you are curious more around the theory behind the original teachable machine application check out this tutorial .
Share what you make with us
You can easily extend what you made today for other creative use cases too and we encourage you to think outside the box and keep hacking.
Remember to tag us on social media using the #MadeWithTFJS hashtag for a chance for your project to be featured on our TensorFlow blog or even future events . We would love to see what you make.
Websites to check out
- TensorFlow.js official website
- TensorFlow.js pre-made models
- TensorFlow.js API
- TensorFlow.js Show & Tell — get inspired and see what others have made.