TensorFlow.js: আপনার নিজের "শিক্ষাযোগ্য মেশিন" TensorFlow.js এর সাথে ট্রান্সফার লার্নিং ব্যবহার করে

১. শুরু করার আগে

গত কয়েক বছরে TensorFlow.js মডেলের ব্যবহার দ্রুতগতিতে বৃদ্ধি পেয়েছে এবং অনেক জাভাস্ক্রিপ্ট ডেভেলপার এখন বিদ্যমান অত্যাধুনিক মডেলগুলিকে গ্রহণ করতে এবং তাদের শিল্পের জন্য অনন্য কাস্টম ডেটার সাথে কাজ করার জন্য পুনরায় প্রশিক্ষণ দেওয়ার চেষ্টা করছেন। একটি বিদ্যমান মডেল (প্রায়শই বেস মডেল হিসাবে উল্লেখ করা হয়) গ্রহণ করা এবং এটি একটি অনুরূপ কিন্তু ভিন্ন ডোমেইনে ব্যবহার করাকে ট্রান্সফার লার্নিং বলা হয়।

সম্পূর্ণ ফাঁকা মডেল থেকে শুরু করার তুলনায় ট্রান্সফার লার্নিং-এর অনেক সুবিধা রয়েছে। আপনি পূর্বে প্রশিক্ষিত মডেল থেকে ইতিমধ্যেই শেখা জ্ঞান পুনঃব্যবহার করতে পারেন এবং আপনি যে নতুন আইটেমটি শ্রেণীবদ্ধ করতে চান তার কম উদাহরণের প্রয়োজন হয়। এছাড়াও, প্রশিক্ষণ প্রায়শই উল্লেখযোগ্যভাবে দ্রুত হয় কারণ পুরো নেটওয়ার্কের পরিবর্তে মডেল আর্কিটেকচারের শেষ কয়েকটি স্তর পুনরায় প্রশিক্ষণ দিতে হয়। এই কারণে, ট্রান্সফার লার্নিং ওয়েব ব্রাউজার পরিবেশের জন্য খুব উপযুক্ত যেখানে এক্সিকিউশনের ডিভাইসের উপর ভিত্তি করে সংস্থানগুলি পরিবর্তিত হতে পারে, তবে সহজে ডেটা অর্জনের জন্য সেন্সরগুলিতে সরাসরি অ্যাক্সেসও রয়েছে।

এই কোডল্যাবটি আপনাকে দেখায় কিভাবে একটি ফাঁকা ক্যানভাস থেকে একটি ওয়েব অ্যাপ তৈরি করতে হয়, যা Google এর জনপ্রিয় " Teachable Machine " ওয়েবসাইটটি পুনরায় তৈরি করে। ওয়েবসাইটটি আপনাকে একটি কার্যকরী ওয়েব অ্যাপ তৈরি করতে দেয় যা যেকোনো ব্যবহারকারী তাদের ওয়েবক্যাম থেকে কয়েকটি উদাহরণ চিত্রের সাহায্যে একটি কাস্টম অবজেক্ট সনাক্ত করতে ব্যবহার করতে পারে। ওয়েবসাইটটি উদ্দেশ্যমূলকভাবে ন্যূনতম রাখা হয়েছে যাতে আপনি এই কোডল্যাবের মেশিন লার্নিং দিকগুলিতে মনোনিবেশ করতে পারেন। তবে, মূল 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 অ্যাকাউন্ট অনুসরণ করা পছন্দনীয়, অথবা আপনি এমন একটি ওয়েব পরিবেশন পরিবেশ ব্যবহার করতে পারেন যেখানে আপনি নিজে সম্পাদনা এবং পরিচালনা করতে স্বাচ্ছন্দ্য বোধ করেন।

২. TensorFlow.js কি?

54e81d02971f53e8.png সম্পর্কে

TensorFlow.js হল একটি ওপেন সোর্স মেশিন লার্নিং লাইব্রেরি যা জাভাস্ক্রিপ্টের যেকোনো জায়াস্ক্রিপ্ট ব্যবহার করতে পারে। এটি পাইথনে লেখা মূল TensorFlow লাইব্রেরির উপর ভিত্তি করে তৈরি এবং জাভাস্ক্রিপ্ট ইকোসিস্টেমের জন্য এই ডেভেলপার অভিজ্ঞতা এবং API-এর সেট পুনরায় তৈরি করার লক্ষ্যে কাজ করে।

এটা কোথায় ব্যবহার করা যেতে পারে?

জাভাস্ক্রিপ্টের পোর্টেবিলিটির কারণে, আপনি এখন একটি ভাষায় লিখতে পারেন এবং নিম্নলিখিত সমস্ত প্ল্যাটফর্মে সহজেই মেশিন লার্নিং সম্পাদন করতে পারেন:

  • ভ্যানিলা জাভাস্ক্রিপ্ট ব্যবহার করে ওয়েব ব্রাউজারে ক্লায়েন্ট সাইড
  • সার্ভার সাইড এবং এমনকি রাস্পবেরি পাই এর মতো IoT ডিভাইসগুলি Node.js ব্যবহার করে
  • ইলেক্ট্রন ব্যবহার করে ডেস্কটপ অ্যাপ
  • রিঅ্যাক্ট নেটিভ ব্যবহার করে নেটিভ মোবাইল অ্যাপস

TensorFlow.js এই পরিবেশগুলির প্রতিটির মধ্যে একাধিক ব্যাকএন্ড সমর্থন করে (যেমন CPU বা WebGL এর মতো প্রকৃত হার্ডওয়্যার ভিত্তিক পরিবেশ। এই প্রসঙ্গে "ব্যাকএন্ড" মানে সার্ভার সাইড পরিবেশ নয় - উদাহরণস্বরূপ WebGL-এ এক্সিকিউশনের জন্য ব্যাকএন্ড ক্লায়েন্ট সাইড হতে পারে) যাতে সামঞ্জস্যতা নিশ্চিত করা যায় এবং জিনিসগুলি দ্রুত চলমান থাকে। বর্তমানে TensorFlow.js সমর্থন করে:

  • ডিভাইসের গ্রাফিক্স কার্ডে (GPU)-তে WebGL এক্সিকিউশন - এটি GPU অ্যাক্সিলারেশন সহ বৃহত্তর মডেলগুলি (3MB-এর বেশি আকারের) এক্সিকিউশন করার দ্রুততম উপায়।
  • CPU-তে ওয়েব অ্যাসেম্বলি (WASM) কার্যকর করা - উদাহরণস্বরূপ, পুরোনো প্রজন্মের মোবাইল ফোন সহ সমস্ত ডিভাইসে CPU কর্মক্ষমতা উন্নত করার জন্য। এটি ছোট মডেলগুলির (3MB এর কম আকারের) জন্য আরও উপযুক্ত, যা আসলে WebGL-এর তুলনায় WASM-এর মাধ্যমে CPU-তে দ্রুত কার্যকর হতে পারে কারণ গ্রাফিক্স প্রসেসরে সামগ্রী আপলোড করার জন্য অতিরিক্ত খরচ হয়।
  • CPU এক্সিকিউশন - অন্য কোনও পরিবেশ উপলব্ধ না থাকলে ফলব্যাক। এটি তিনটির মধ্যে সবচেয়ে ধীর কিন্তু সর্বদা আপনার জন্য রয়েছে।

দ্রষ্টব্য: আপনি যদি জানেন যে আপনি কোন ডিভাইসে কাজ করবেন, তাহলে আপনি এই ব্যাকএন্ডগুলির মধ্যে একটিকে জোর করে ব্যবহার করতে পারেন, অথবা যদি আপনি এটি নির্দিষ্ট না করেন তবে TensorFlow.js কে আপনার জন্য সিদ্ধান্ত নিতে দিতে পারেন।

ক্লায়েন্ট সাইড সুপার পাওয়ার

ক্লায়েন্ট মেশিনে ওয়েব ব্রাউজারে TensorFlow.js চালানোর ফলে বেশ কিছু সুবিধা পাওয়া যেতে পারে যা বিবেচনা করার মতো।

গোপনীয়তা

আপনি তৃতীয় পক্ষের ওয়েব সার্ভারে ডেটা না পাঠিয়ে ক্লায়েন্ট মেশিনে ডেটা প্রশিক্ষণ এবং শ্রেণীবদ্ধ করতে পারেন। এমন সময় আসতে পারে যখন স্থানীয় আইন মেনে চলার প্রয়োজন হতে পারে, যেমন 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 রাস্পবেরি পাই এর মতো জনপ্রিয় সিঙ্গেল বোর্ড কম্পিউটারগুলিতে সমর্থিত, যার অর্থ আপনি এই জাতীয় ডিভাইসগুলিতেও TensorFlow.js মডেলগুলি কার্যকর করতে পারেন।

গতি

Node.js জাভাস্ক্রিপ্টে লেখা, যার অর্থ এটি ঠিক সময়ে সংকলন করলে উপকৃত হয়। এর অর্থ হল Node.js ব্যবহার করার সময় আপনি প্রায়শই কর্মক্ষমতা বৃদ্ধি দেখতে পাবেন কারণ এটি রানটাইমে অপ্টিমাইজ করা হবে, বিশেষ করে আপনার করা যেকোনো প্রিপ্রসেসিংয়ের ক্ষেত্রে। এর একটি দুর্দান্ত উদাহরণ এই কেস স্টাডিতে দেখা যাবে যেখানে দেখানো হয়েছে যে Hugging Face কীভাবে Node.js ব্যবহার করে তাদের প্রাকৃতিক ভাষা প্রক্রিয়াকরণ মডেলের জন্য 2x কর্মক্ষমতা বৃদ্ধি করেছে।

এখন আপনি TensorFlow.js এর মূল বিষয়গুলি, এটি কোথায় চালানো যেতে পারে এবং কিছু সুবিধা সম্পর্কে বুঝতে পেরেছেন, আসুন এটি দিয়ে দরকারী জিনিসগুলি করা শুরু করি!

৩. স্থানান্তর শিক্ষা

ট্রান্সফার লার্নিং আসলে কী?

ট্রান্সফার লার্নিং বলতে বোঝায় এমন জ্ঞান নেওয়া যা ইতিমধ্যেই শেখা হয়েছে, যাতে ভিন্ন কিন্তু একই রকম জিনিস শেখা যায়।

আমরা মানুষরা সবসময় এটা করি। তোমার মস্তিষ্কে জীবনের অনেক অভিজ্ঞতা আছে যা তুমি এমন নতুন জিনিস চিনতে সাহায্য করতে পারো যা তুমি আগে কখনও দেখেনি। উদাহরণস্বরূপ এই উইলো গাছের কথাই ধরো:

e28070392cd4afb9.png সম্পর্কে

আপনি বিশ্বের কোন প্রান্তে আছেন তার উপর নির্ভর করে, এই ধরণের গাছ আগে নাও দেখে থাকতে পারেন।

তবুও যদি আমি আপনাকে জিজ্ঞাসা করি যে নীচের নতুন ছবিতে কোনও উইলো গাছ আছে কিনা, তাহলে আপনি সম্ভবত সেগুলি খুব দ্রুত দেখতে পাবেন, যদিও সেগুলি ভিন্ন কোণে রয়েছে এবং আমি আপনাকে যে আসলটি দেখিয়েছি তার থেকে কিছুটা আলাদা।

d9073a0d5df27222.png সম্পর্কে

তোমার মস্তিষ্কে ইতিমধ্যেই একগুচ্ছ নিউরন আছে যারা গাছের মতো বস্তু শনাক্ত করতে জানে, এবং অন্যান্য নিউরন যারা লম্বা সরলরেখা খুঁজে বের করতে ভালো। তুমি সেই জ্ঞান পুনঃব্যবহার করে দ্রুত একটি উইলো গাছকে শ্রেণীবদ্ধ করতে পারো, যা একটি গাছের মতো বস্তু যার অনেক লম্বা, সোজা উল্লম্ব শাখা রয়েছে।

একইভাবে, যদি আপনার কাছে এমন একটি মেশিন লার্নিং মডেল থাকে যা ইতিমধ্যেই কোনও ডোমেনে প্রশিক্ষিত, যেমন ছবি সনাক্তকরণ, তাহলে আপনি এটিকে একটি ভিন্ন কিন্তু সম্পর্কিত কাজ সম্পাদনের জন্য পুনরায় ব্যবহার করতে পারেন।

আপনি মোবাইলনেটের মতো একটি উন্নত মডেলের সাথেও একই কাজ করতে পারেন, যা একটি অত্যন্ত জনপ্রিয় গবেষণা মডেল যা ১০০০টি ভিন্ন ধরণের বস্তুর উপর চিত্র স্বীকৃতি সম্পাদন করতে পারে। কুকুর থেকে শুরু করে গাড়ি পর্যন্ত, এটি ইমেজনেট নামে পরিচিত একটি বিশাল ডেটাসেটের উপর প্রশিক্ষিত ছিল যার লক্ষ লক্ষ লেবেলযুক্ত চিত্র রয়েছে।

এই অ্যানিমেশনে, আপনি এই মোবাইলনেট ভি১ মডেলে এর বিশাল সংখ্যক স্তর দেখতে পাবেন:

অনুসরণ

প্রশিক্ষণের সময়, এই মডেলটি শিখেছে কিভাবে ঐ ১০০০টি বস্তুর জন্য গুরুত্বপূর্ণ সাধারণ বৈশিষ্ট্যগুলি বের করতে হয়, এবং এই ধরনের বস্তু সনাক্ত করার জন্য এটি যে নিম্ন স্তরের বৈশিষ্ট্যগুলি ব্যবহার করে তা নতুন বস্তু সনাক্ত করতেও কার্যকর হতে পারে যা এটি আগে কখনও দেখেনি। সর্বোপরি, সবকিছুই শেষ পর্যন্ত কেবল রেখা, টেক্সচার এবং আকারের সংমিশ্রণ।

চলুন, একটি ঐতিহ্যবাহী কনভোলিউশনাল নিউরাল নেটওয়ার্ক (CNN) আর্কিটেকচার (মোবাইলনেটের অনুরূপ) দেখে নেওয়া যাক এবং দেখি কিভাবে ট্রান্সফার লার্নিং এই প্রশিক্ষিত নেটওয়ার্ককে নতুন কিছু শেখার জন্য কাজে লাগাতে পারে। নীচের ছবিটি একটি CNN এর সাধারণ মডেল আর্কিটেকচার দেখায় যা এই ক্ষেত্রে 0 থেকে 9 পর্যন্ত হাতে লেখা সংখ্যা সনাক্ত করার জন্য প্রশিক্ষিত ছিল:

baf4e3d434576106.png

যদি আপনি বাম দিকে দেখানো মডেলের পূর্ব-প্রশিক্ষিত নিম্ন স্তরের স্তরগুলিকে ডানদিকে দেখানো মডেলের শেষের কাছাকাছি শ্রেণীবিভাগ স্তরগুলি (কখনও কখনও মডেলের শ্রেণীবিভাগ প্রধান হিসাবে উল্লেখ করা হয়) থেকে আলাদা করতে পারেন, তাহলে আপনি যে মূল তথ্যের উপর প্রশিক্ষণ দেওয়া হয়েছিল তার উপর ভিত্তি করে যে কোনও চিত্রের জন্য আউটপুট বৈশিষ্ট্য তৈরি করতে নিম্ন স্তরের স্তরগুলি ব্যবহার করতে পারেন। এখানে একই নেটওয়ার্ক রয়েছে যেখানে শ্রেণীবিভাগ প্রধানটি সরানো হয়েছে:

369a8a9041c6917d.png সম্পর্কে

ধরে নিচ্ছি যে আপনি যে নতুন জিনিসটি চিনতে চাইছেন তা পূর্ববর্তী মডেলের শেখা আউটপুট বৈশিষ্ট্যগুলিও ব্যবহার করতে পারে, তাহলে নতুন উদ্দেশ্যে সেগুলি পুনরায় ব্যবহার করার সম্ভাবনা বেশি।

উপরের চিত্রটিতে, এই কাল্পনিক মডেলটি অঙ্কের উপর প্রশিক্ষিত ছিল, তাই সম্ভবত অঙ্ক সম্পর্কে যা শেখা হয়েছে তা a, b, এবং c এর মতো অক্ষরগুলিতেও প্রয়োগ করা যেতে পারে।

তাহলে এখন আপনি একটি নতুন শ্রেণীবিভাগের শিরোনাম যোগ করতে পারেন যা a, b, অথবা c ভবিষ্যদ্বাণী করার চেষ্টা করে, যেমন দেখানো হয়েছে:

db97e5e60ae73bbd.png সম্পর্কে

এখানে নিম্ন স্তরের স্তরগুলি হিমায়িত এবং প্রশিক্ষিত নয়, শুধুমাত্র নতুন শ্রেণিবিন্যাস প্রধান বাম দিকের প্রাক-প্রশিক্ষিত চপ আপ মডেল থেকে প্রদত্ত বৈশিষ্ট্যগুলি থেকে শেখার জন্য নিজেকে আপডেট করবে।

এটি করার কাজটি ট্রান্সফার লার্নিং নামে পরিচিত এবং টিচেবল মেশিন পর্দার আড়ালে যা করে।

আপনি আরও দেখতে পাচ্ছেন যে নেটওয়ার্কের একেবারে শেষে মাল্টি-লেয়ার পারসেপ্ট্রনকে প্রশিক্ষণ দেওয়ার মাধ্যমে, এটি পুরো নেটওয়ার্কটিকে শুরু থেকে প্রশিক্ষণ দেওয়ার চেয়ে অনেক দ্রুত প্রশিক্ষণ দেয়।

কিন্তু কিভাবে আপনি একটি মডেলের উপ-অংশগুলি হাতে পাবেন? তা জানতে পরবর্তী বিভাগে যান।

৪. টেনসরফ্লো হাব - বেস মডেল

ব্যবহারের জন্য উপযুক্ত একটি বেস মডেল খুঁজুন

MobileNet এর মতো আরও উন্নত এবং জনপ্রিয় গবেষণা মডেলের জন্য, আপনি TensorFlow hub এ যেতে পারেন, এবং তারপর TensorFlow.js এর জন্য উপযুক্ত মডেলগুলি ফিল্টার করুন যা MobileNet v3 আর্কিটেকচার ব্যবহার করে এখানে দেখানো ফলাফলগুলির মতো ফলাফল খুঁজে পেতে পারে:

c5dc1420c6238c14.png সম্পর্কে

মনে রাখবেন যে এই ফলাফলগুলির মধ্যে কিছু "চিত্র শ্রেণীবিভাগ" ধরণের (প্রতিটি মডেল কার্ড ফলাফলের উপরের বাম দিকে বিস্তারিত), এবং অন্যগুলি "চিত্র বৈশিষ্ট্য ভেক্টর" ধরণের।

এই ইমেজ ফিচার ভেক্টর ফলাফলগুলি মূলত মোবাইলনেটের আগে থেকে কাটা সংস্করণ যা আপনি চূড়ান্ত শ্রেণীবিভাগের পরিবর্তে ইমেজ ফিচার ভেক্টর পেতে ব্যবহার করতে পারেন।

এই ধরণের মডেলগুলিকে প্রায়শই "বেস মডেল" বলা হয়, যা আপনি পূর্ববর্তী বিভাগে দেখানো পদ্ধতিতে স্থানান্তর শেখার জন্য একটি নতুন শ্রেণিবিন্যাস প্রধান যুক্ত করে এবং আপনার নিজস্ব ডেটা দিয়ে এটি প্রশিক্ষণ দিয়ে ব্যবহার করতে পারেন।

পরবর্তী জিনিসটি হল TensorFlow.js ফর্ম্যাটে মডেলটি কীভাবে প্রকাশিত হয়েছে তা আগ্রহের একটি নির্দিষ্ট বেস মডেলের জন্য পরীক্ষা করা। যদি আপনি এই বৈশিষ্ট্য ভেক্টর MobileNet v3 মডেলগুলির একটির জন্য পৃষ্ঠাটি খোলেন তবে আপনি JS ডকুমেন্টেশন থেকে দেখতে পাবেন যে এটি ডকুমেন্টেশনের উদাহরণ কোড স্নিপেটের উপর ভিত্তি করে একটি গ্রাফ মডেলের আকারে রয়েছে যা tf.loadGraphModel() ব্যবহার করে।

f97d903d2e46924b.png

এটাও মনে রাখা উচিত যে যদি আপনি গ্রাফ ফর্ম্যাটের পরিবর্তে লেয়ার ফর্ম্যাটে একটি মডেল খুঁজে পান, তাহলে আপনি প্রশিক্ষণের জন্য কোন লেয়ারগুলি ফ্রিজ করবেন এবং কোনটি আনফ্রিজ করবেন তা বেছে নিতে পারেন। একটি নতুন কাজের জন্য একটি মডেল তৈরি করার সময় এটি খুব শক্তিশালী হতে পারে, যা প্রায়শই "ট্রান্সফার মডেল" হিসাবে উল্লেখ করা হয়। তবে আপাতত, আপনি এই টিউটোরিয়ালের জন্য ডিফল্ট গ্রাফ মডেল টাইপ ব্যবহার করবেন, যা বেশিরভাগ TF হাব মডেল হিসাবে স্থাপন করা হয়। লেয়ার মডেলগুলির সাথে কাজ করার বিষয়ে আরও জানতে, জিরো থেকে হিরো TensorFlow.js কোর্সটি দেখুন।

ট্রান্সফার লার্নিংয়ের সুবিধা

সম্পূর্ণ মডেল আর্কিটেকচারকে শুরু থেকে প্রশিক্ষণ দেওয়ার পরিবর্তে ট্রান্সফার লার্নিং ব্যবহারের সুবিধা কী কী?

প্রথমত, প্রশিক্ষণের সময় হল ট্রান্সফার লার্নিং পদ্ধতি ব্যবহারের একটি গুরুত্বপূর্ণ সুবিধা কারণ আপনার ইতিমধ্যেই একটি প্রশিক্ষিত বেস মডেল তৈরি করার আছে।

দ্বিতীয়ত, ইতিমধ্যেই যে প্রশিক্ষণ সম্পন্ন হয়েছে তার কারণে আপনি যে নতুন জিনিসটিকে শ্রেণীবদ্ধ করার চেষ্টা করছেন তার অনেক কম উদাহরণ দেখিয়ে আপনি রেহাই পেতে পারেন।

আপনি যে জিনিসটিকে শ্রেণীবদ্ধ করতে চান তার উদাহরণ তথ্য সংগ্রহ করার জন্য যদি আপনার কাছে সীমিত সময় এবং সম্পদ থাকে এবং এটিকে আরও শক্তিশালী করার জন্য আরও প্রশিক্ষণ তথ্য সংগ্রহ করার আগে দ্রুত একটি প্রোটোটাইপ তৈরি করতে হয় তবে এটি সত্যিই দুর্দান্ত।

কম ডেটার প্রয়োজন এবং ছোট নেটওয়ার্ক প্রশিক্ষণের গতির কারণে, ট্রান্সফার লার্নিং কম রিসোর্স-নিবিড়। এটি ব্রাউজার পরিবেশের জন্য এটিকে খুবই উপযুক্ত করে তোলে, সম্পূর্ণ মডেল প্রশিক্ষণের জন্য ঘন্টা, দিন বা সপ্তাহের পরিবর্তে একটি আধুনিক মেশিনে মাত্র দশ সেকেন্ড সময় লাগে।

ঠিক আছে! এখন আপনি ট্রান্সফার লার্নিং কী তার সারমর্ম জানেন, এখন টিচেবল মেশিনের নিজস্ব সংস্করণ তৈরি করার সময়। চলুন শুরু করা যাক!

৫. কোডিংয়ের জন্য প্রস্তুত হোন

তোমার যা লাগবে

  • একটি আধুনিক ওয়েব ব্রাউজার।
  • HTML, CSS, JavaScript, এবং Chrome DevTools (কনসোল আউটপুট দেখা) সম্পর্কে প্রাথমিক জ্ঞান।

চলো কোডিং শুরু করি

Glitch.com অথবা Codepen.io এর জন্য শুরু করার জন্য Boilerplate টেমপ্লেট তৈরি করা হয়েছে। আপনি কেবল এক ক্লিকে এই কোড ল্যাবের জন্য আপনার বেস স্টেট হিসাবে যেকোনো টেমপ্লেট ক্লোন করতে পারেন।

গ্লিচে, " রিমিক্স দিস" বোতামে ক্লিক করে এটিকে ফোর্ক করুন এবং সম্পাদনা করার জন্য নতুন ফাইল তৈরি করুন।

অথবা, কোডপেনে, স্ক্রিনের নীচের ডানদিকে " ফর্ক" এ ক্লিক করুন।

এই খুব সহজ কঙ্কালটি আপনাকে নিম্নলিখিত ফাইলগুলি সরবরাহ করে:

  • 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টি ফাইল তৈরি করুন এবং আমাদের গ্লিচ বয়লারপ্লেট থেকে কোডটি কপি করে প্রতিটিতে পেস্ট করুন।

৬. অ্যাপ HTML বয়লারপ্লেট

আমি কোথা থেকে শুরু করব?

সকল প্রোটোটাইপের জন্য কিছু মৌলিক 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 &amp; Predict!</button>
    <button id="reset">Reset</button>

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

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

ভেঙে ফেলো।

আপনার যোগ করা কিছু গুরুত্বপূর্ণ বিষয় তুলে ধরার জন্য উপরের HTML কোডগুলো ভেঙে ফেলা যাক।

  • আপনি পৃষ্ঠার শিরোনামের জন্য একটি <h1> ট্যাগ এবং 'status' আইডি সহ একটি <p> ট্যাগ যোগ করেছেন, যেখানে আপনি আউটপুট দেখার জন্য সিস্টেমের বিভিন্ন অংশ ব্যবহার করার সময় তথ্য মুদ্রণ করবেন।
  • আপনি 'ওয়েবক্যাম' আইডি সহ একটি <video> উপাদান যোগ করেছেন, যেখানে আপনি পরে আপনার ওয়েবক্যাম স্ট্রিম রেন্ডার করবেন।
  • আপনি ৫টি <button> উপাদান যোগ করেছেন। প্রথমটি, 'enableCam' এর ID সহ, ক্যামেরা সক্ষম করে। পরবর্তী দুটি বোতামে 'dataCollector' এর একটি ক্লাস রয়েছে, যা আপনাকে আপনার পছন্দের বস্তুগুলির জন্য উদাহরণ চিত্র সংগ্রহ করতে দেয়। আপনি পরে যে কোডটি লিখবেন তা এমনভাবে ডিজাইন করা হবে যাতে আপনি এই বোতামগুলির যেকোনো সংখ্যক যোগ করতে পারেন এবং সেগুলি স্বয়ংক্রিয়ভাবে ইচ্ছামত কাজ করবে।

মনে রাখবেন যে এই বোতামগুলিতে data-1hot নামে একটি বিশেষ ব্যবহারকারী-সংজ্ঞায়িত বৈশিষ্ট্যও রয়েছে, যার প্রথম শ্রেণীর জন্য একটি পূর্ণসংখ্যার মান 0 থেকে শুরু হয়। এটি হল সংখ্যাসূচক সূচক যা আপনি একটি নির্দিষ্ট শ্রেণীর ডেটা উপস্থাপন করতে ব্যবহার করবেন। সূচকটি স্ট্রিংয়ের পরিবর্তে সংখ্যাসূচক উপস্থাপনা দিয়ে আউটপুট ক্লাসগুলিকে সঠিকভাবে এনকোড করতে ব্যবহৃত হবে, কারণ ML মডেলগুলি কেবল সংখ্যার সাথে কাজ করতে পারে।

এই ক্লাসের জন্য আপনি যে মানব পাঠযোগ্য নামটি ব্যবহার করতে চান তার একটি data-name বৈশিষ্ট্যও রয়েছে, যা আপনাকে 1 হট এনকোডিং থেকে একটি সংখ্যাসূচক সূচক মানের পরিবর্তে ব্যবহারকারীকে আরও অর্থপূর্ণ নাম প্রদান করতে দেয়।

অবশেষে, তথ্য সংগ্রহের পর প্রশিক্ষণ প্রক্রিয়া শুরু করার জন্য অথবা অ্যাপটি রিসেট করার জন্য আপনার কাছে একটি ট্রেন এবং রিসেট বোতাম রয়েছে।

  • আপনি ২টি <script> আমদানিও যোগ করেছেন। একটি TensorFlow.js এর জন্য, এবং অন্যটি script.js এর জন্য যা আপনি শীঘ্রই সংজ্ঞায়িত করবেন।

৭. স্টাইল যোগ করুন

এলিমেন্ট ডিফল্ট

আপনার যোগ করা HTML উপাদানগুলির জন্য স্টাইল যোগ করুন যাতে সেগুলি সঠিকভাবে রেন্ডার হয়। এখানে কিছু স্টাইল দেওয়া হল যেগুলি পজিশন এবং সাইজ এলিমেন্টগুলিতে সঠিকভাবে যোগ করা হয়েছে। বিশেষ কিছু নয়। আরও ভালো UX তৈরি করতে আপনি অবশ্যই পরে এটি যোগ করতে পারেন, যেমনটি আপনি শিক্ষণযোগ্য মেশিন ভিডিওতে দেখেছেন।

স্টাইল.সিএসএস

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

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


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

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

.removed {
  display: none;
}

#status {
  font-size:150%;
}

দারুন! আপনার যা দরকার তা হল। আপনি যদি এখনই আউটপুটটির প্রিভিউ দেখেন, তাহলে এটি এরকম দেখাবে:

81909685d7566dcb.png সম্পর্কে

৮. জাভাস্ক্রিপ্ট: মূল ধ্রুবক এবং শ্রোতা

কী ধ্রুবক সংজ্ঞায়িত করুন

প্রথমে, অ্যাপ জুড়ে ব্যবহার করা কিছু কী ধ্রুবক যোগ করুন। 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 একটি লুকআপ হিসেবে কাজ করে এবং সম্ভাব্য ক্লাস ভবিষ্যদ্বাণীর জন্য মানুষের পঠনযোগ্য নাম ধারণ করে। এই অ্যারেটি পরে পূরণ করা হবে।

ঠিক আছে, এখন যেহেতু আপনার কাছে মূল উপাদানগুলির উল্লেখ আছে, এখন সময় এসেছে কিছু ইভেন্ট শ্রোতাদের তাদের সাথে যুক্ত করার।

গুরুত্বপূর্ণ ইভেন্ট শ্রোতাদের যোগ করুন

দেখানো পদ্ধতিতে কী বোতামগুলিতে ক্লিক ইভেন্ট হ্যান্ডলার যোগ করে শুরু করুন:

স্ক্রিপ্ট.জেএস

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


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


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


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

ENABLE_CAM_BUTTON - ক্লিক করলে enableCam ফাংশনটি কল করে।

TRAIN_BUTTON - ক্লিক করলে trainAndPredict কল করে।

RESET_BUTTON - ক্লিক করলে কল রিসেট হয়।

অবশেষে এই বিভাগে আপনি document.querySelectorAll() ব্যবহার করে 'dataCollector' এর একটি ক্লাস আছে এমন সমস্ত বোতাম খুঁজে পেতে পারেন। এটি ডকুমেন্ট থেকে পাওয়া উপাদানগুলির একটি অ্যারে ফেরত দেয় যা মিলছে:

স্ক্রিপ্ট.জেএস

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 অ্যারেতে পুশ করতে পারেন।

এরপর, কিছু ভেরিয়েবল যোগ করুন যাতে পরবর্তীতে ব্যবহৃত গুরুত্বপূর্ণ জিনিসগুলি সংরক্ষণ করা যায়।

স্ক্রিপ্ট.জেএস

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

চলো এগুলো দেখে নেই।

প্রথমে, লোড করা মোবাইলনেট মডেলটি সংরক্ষণ করার জন্য আপনার কাছে একটি ভেরিয়েবল mobilenet আছে। প্রথমে এটিকে undefined এ সেট করুন।

এরপর, আপনার কাছে gatherDataState নামক একটি ভেরিয়েবল আছে। যদি একটি 'dataCollector' বোতাম টিপানো হয়, তাহলে এটি HTML-এ সংজ্ঞায়িত হিসাবে, সেই বোতামের ১ম হট আইডিতে পরিবর্তিত হবে, যাতে আপনি জানতে পারেন যে আপনি সেই মুহূর্তে কোন শ্রেণীর ডেটা সংগ্রহ করছেন। প্রাথমিকভাবে, এটি STOP_DATA_GATHER এ সেট করা হয়েছে যাতে পরে আপনি যে ডেটা সংগ্রহ লুপটি লিখবেন তা কোনও বোতাম টিপলে কোনও ডেটা সংগ্রহ করবে না।

videoPlaying ওয়েবক্যাম স্ট্রিমটি সফলভাবে লোড এবং প্লে হচ্ছে কিনা এবং ব্যবহারের জন্য উপলব্ধ কিনা তা ট্র্যাক করে। প্রাথমিকভাবে, এটি false সেট করা হয় কারণ আপনি ENABLE_CAM_BUTTON.

এরপর, 2টি অ্যারে সংজ্ঞায়িত করুন, trainingDataInputs এবং trainingDataOutputs । এগুলি সংগৃহীত প্রশিক্ষণ ডেটা মান সংরক্ষণ করে, যখন আপনি MobileNet বেস মডেল দ্বারা তৈরি ইনপুট বৈশিষ্ট্যগুলির জন্য 'dataCollector' বোতামে ক্লিক করেন এবং যথাক্রমে নমুনাকৃত আউটপুট ক্লাস।

একটি চূড়ান্ত অ্যারে, examplesCount, সংজ্ঞায়িত করা হয় যাতে আপনি একবার প্রতিটি ক্লাসের জন্য কতগুলি উদাহরণ যুক্ত করা শুরু করেন তা ট্র্যাক করা যায়।

অবশেষে, আপনার কাছে predict নামক একটি ভেরিয়েবল আছে যা আপনার predict লুপ নিয়ন্ত্রণ করে। এটি প্রাথমিকভাবে false তে সেট করা আছে। পরবর্তীতে এটি true তে সেট না করা পর্যন্ত কোনও ভবিষ্যদ্বাণী করা যাবে না।

এখন যেহেতু সমস্ত কী ভেরিয়েবল সংজ্ঞায়িত করা হয়েছে, চলুন এবং আগে থেকে কাটা MobileNet v3 বেস মডেলটি লোড করি যা শ্রেণীবিভাগের পরিবর্তে চিত্র বৈশিষ্ট্য ভেক্টর প্রদান করে।

৯. মোবাইলনেট বেস মডেলটি লোড করুন

প্রথমে, নীচে দেখানো loadMobileNetFeatureModel নামক একটি নতুন ফাংশন সংজ্ঞায়িত করুন। এটি অবশ্যই একটি অ্যাসিঙ্ক ফাংশন হতে হবে কারণ একটি মডেল লোড করার কাজটি অ্যাসিঙ্ক্রোনাস:

স্ক্রিপ্ট.জেএস

/**
 * 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();

এই কোডে আপনি TFHub ডকুমেন্টেশন থেকে লোড করা মডেলটি কোথায় অবস্থিত তা URL সংজ্ঞায়িত করবেন।

এরপর আপনি await tf.loadGraphModel() ব্যবহার করে মডেলটি লোড করতে পারেন, এই Google ওয়েবসাইট থেকে মডেল লোড করার সময় fromTFHub true তে সেট করতে ভুলবেন না। এটি শুধুমাত্র TF Hub-এ হোস্ট করা মডেল ব্যবহারের জন্য একটি বিশেষ কেস যেখানে এই অতিরিক্ত বৈশিষ্ট্যটি সেট করতে হবে।

লোডিং সম্পূর্ণ হলে আপনি STATUS এলিমেন্টের innerText একটি বার্তা দিয়ে সেট করতে পারেন যাতে আপনি দৃশ্যত দেখতে পারেন যে এটি সঠিকভাবে লোড হয়েছে এবং আপনি ডেটা সংগ্রহ শুরু করতে প্রস্তুত।

এখন শুধু মডেলটি গরম করা বাকি। এই ধরণের বড় মডেলের ক্ষেত্রে, প্রথমবার মডেলটি ব্যবহার করার সময় সবকিছু সেট আপ করতে কিছুটা সময় লাগতে পারে। তাই এটি মডেলের মধ্য দিয়ে শূন্য পাস করতে সাহায্য করে যাতে ভবিষ্যতে সময় আরও গুরুত্বপূর্ণ হতে পারে এমন কোনও অপেক্ষা এড়ানো যায়।

আপনি tf.zeros() ব্যবহার করে tf.tidy() দিয়ে মোড়ানো tf.zeros() ব্যবহার করতে পারেন যাতে নিশ্চিত করা যায় যে টেনসরগুলি সঠিকভাবে নিষ্পত্তি করা হচ্ছে, যার ব্যাচ সাইজ ১ এবং শুরুতে আপনার ধ্রুবকগুলিতে সংজ্ঞায়িত সঠিক উচ্চতা এবং প্রস্থ। অবশেষে, আপনি রঙের চ্যানেলগুলিও নির্দিষ্ট করতে পারেন, যা এই ক্ষেত্রে 3, কারণ মডেলটি RGB চিত্রগুলি আশা করে।

এরপর, answer.shape() ব্যবহার করে ফিরে আসা টেনসরের আকৃতি লগ করুন যাতে আপনি এই মডেলটি তৈরি করে এমন চিত্রের বৈশিষ্ট্যগুলির আকার বুঝতে পারেন।

এই ফাংশনটি সংজ্ঞায়িত করার পরে, আপনি পৃষ্ঠা লোডে মডেল ডাউনলোড শুরু করার জন্য অবিলম্বে এটিকে কল করতে পারেন।

যদি আপনি এখনই আপনার লাইভ প্রিভিউ দেখেন, তাহলে কিছুক্ষণ পরে আপনি দেখতে পাবেন যে স্ট্যাটাস টেক্সট "TF.js লোডের অপেক্ষায়" থেকে "MobileNet v3 সফলভাবে লোড হয়েছে!" হয়ে গেছে, যেমনটি নীচে দেখানো হয়েছে। চালিয়ে যাওয়ার আগে নিশ্চিত করুন যে এটি কাজ করছে।

a28b734e190afff.png সম্পর্কে

এই মডেলটি যে আউটপুট বৈশিষ্ট্যগুলি তৈরি করে তার মুদ্রিত আকার দেখতে আপনি কনসোল আউটপুটটিও পরীক্ষা করতে পারেন। মোবাইলনেট মডেলের মাধ্যমে শূন্যগুলি চালানোর পরে, আপনি [1, 1024] আকারের একটি মুদ্রিত আকার দেখতে পাবেন। প্রথম আইটেমটি কেবল 1 এর ব্যাচ আকার, এবং আপনি দেখতে পাবেন এটি আসলে 1024 বৈশিষ্ট্যগুলি প্রদান করে যা আপনাকে নতুন বস্তুগুলিকে শ্রেণীবদ্ধ করতে সাহায্য করতে ব্যবহার করা যেতে পারে।

১০. নতুন মডেলের প্রধান সংজ্ঞায়িত করুন

এখন আপনার মডেল হেডকে সংজ্ঞায়িত করার সময়, যা মূলত একটি খুব ন্যূনতম মাল্টি-লেয়ার পারসেপ্ট্রন।

স্ক্রিপ্ট.জেএস

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

model.summary();

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

এই কোডটি দেখে নেওয়া যাক। আপনি একটি tf.sequential মডেল সংজ্ঞায়িত করে শুরু করুন যেখানে আপনি মডেল স্তরগুলি যুক্ত করবেন।

এরপর, এই মডেলে ইনপুট লেয়ার হিসেবে একটি ঘন স্তর যুক্ত করুন। এর ইনপুট আকৃতি 1024 কারণ MobileNet v3 বৈশিষ্ট্য থেকে আউটপুটগুলি এই আকারের। মডেলের মধ্য দিয়ে কিছু পাস করার পরে আপনি পূর্ববর্তী ধাপে এটি আবিষ্কার করেছেন। এই স্তরে ১২৮টি নিউরন রয়েছে যা ReLU অ্যাক্টিভেশন ফাংশন ব্যবহার করে।

আপনি যদি অ্যাক্টিভেশন ফাংশন এবং মডেল লেয়ারগুলিতে নতুন হন, তাহলে এই বৈশিষ্ট্যগুলি পর্দার আড়ালে কী কাজ করে তা বোঝার জন্য এই কর্মশালার শুরুতে বিস্তারিত কোর্সটি নেওয়ার কথা বিবেচনা করুন

পরবর্তী স্তরটি হল আউটপুট স্তর। নিউরনের সংখ্যা আপনার পূর্বাভাসের সাথে সামঞ্জস্যপূর্ণ হওয়া উচিত। এটি করার জন্য আপনি CLASS_NAMES.length ব্যবহার করে কতগুলি ক্লাস শ্রেণীবদ্ধ করার পরিকল্পনা করছেন তা খুঁজে বের করতে পারেন, যা ব্যবহারকারী ইন্টারফেসে পাওয়া ডেটা সংগ্রহ বোতামের সংখ্যার সমান। যেহেতু এটি একটি শ্রেণীবদ্ধকরণ সমস্যা, তাই আপনি এই আউটপুট স্তরে softmax অ্যাক্টিভেশন ব্যবহার করেন, যা রিগ্রেশনের পরিবর্তে শ্রেণীবদ্ধকরণ সমস্যা সমাধানের জন্য একটি মডেল তৈরি করার চেষ্টা করার সময় ব্যবহার করা আবশ্যক।

এখন কনসোলে নতুন সংজ্ঞায়িত মডেলের ওভারভিউ প্রিন্ট করতে একটি model.summary() প্রিন্ট করুন।

অবশেষে, মডেলটি কম্পাইল করুন যাতে এটি প্রশিক্ষণের জন্য প্রস্তুত হয়। এখানে অপ্টিমাইজারটি adam এ সেট করা আছে, এবং CLASS_NAMES.length 2 এর সমান হলে ক্ষতি হবে binaryCrossentropy , অথবা শ্রেণীবদ্ধ করার জন্য 3 বা তার বেশি ক্লাস থাকলে এটি categoricalCrossentropy ব্যবহার করবে। সঠিকতা মেট্রিক্সও অনুরোধ করা হয়েছে যাতে ডিবাগিংয়ের উদ্দেশ্যে পরে লগে সেগুলি পর্যবেক্ষণ করা যায়।

কনসোলে আপনার এরকম কিছু দেখা উচিত:

অনুসরণ

মনে রাখবেন যে এতে ১৩০ হাজারেরও বেশি প্রশিক্ষণযোগ্য পরামিতি রয়েছে। কিন্তু যেহেতু এটি নিয়মিত নিউরনের একটি সরল ঘন স্তর, তাই এটি বেশ দ্রুত প্রশিক্ষণ পাবে।

প্রকল্পটি সম্পূর্ণ হওয়ার পরে করার জন্য একটি কার্যকলাপ হিসাবে, আপনি প্রথম স্তরে নিউরনের সংখ্যা পরিবর্তন করার চেষ্টা করতে পারেন যাতে আপনি কতটা কম পারফর্মেন্স পেতে পারেন এবং তারপরও ভালো পারফর্মেন্স পেতে পারেন। প্রায়শই মেশিন লার্নিংয়ে কিছু স্তরের ট্রায়াল এবং এরর থাকে যাতে রিসোর্স ব্যবহার এবং গতির মধ্যে সর্বোত্তম লেনদেন করা যায়।

১১. ওয়েবক্যাম চালু করুন

এখন আপনার পূর্বে সংজ্ঞায়িত enableCam() ফাংশনটি তৈরি করার সময় এসেছে। নিচে দেখানো হয়েছে, hasGetUserMedia() নামে একটি নতুন ফাংশন যোগ করুন এবং তারপর পূর্বে সংজ্ঞায়িত enableCam() ফাংশনের বিষয়বস্তু নীচের সংশ্লিষ্ট কোড দিয়ে প্রতিস্থাপন করুন।

স্ক্রিপ্ট.জেএস

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 এলিমেন্টে একটি eventListener যোগ করা উচিত।

স্টিম লোড হয়ে গেলে, আপনি videoPlaying true তে সেট করতে পারেন এবং ENABLE_CAM_BUTTON কে সরিয়ে ফেলতে পারেন যাতে এটি আবার ক্লিক না হয় এবং এর ক্লাস " removed " তে সেট করে এটি আবার ক্লিক না হয়।

এখন আপনার কোডটি চালান, সক্ষম ক্যামেরা বোতামে ক্লিক করুন এবং ওয়েবক্যামে অ্যাক্সেসের অনুমতি দিন। যদি আপনি এটি প্রথমবার করেন, তাহলে আপনি নিজেকে পৃষ্ঠায় ভিডিও উপাদানে রেন্ডার করা দেখতে পাবেন যেমনটি দেখানো হয়েছে:

b378eb1affa9b883.png সম্পর্কে

ঠিক আছে, এখন dataCollector বোতামের ক্লিক মোকাবেলা করার জন্য একটি ফাংশন যোগ করার সময়।

১২. ডেটা সংগ্রহ বোতাম ইভেন্ট হ্যান্ডলার

এখন আপনার খালি ফাংশনটি পূরণ করার সময় এসেছে gatherDataForClass(). কোডল্যাবের শুরুতে dataCollector বোতামগুলির জন্য ইভেন্ট হ্যান্ডলার ফাংশন হিসেবে আপনি এটিই নির্ধারণ করেছিলেন।

স্ক্রিপ্ট.জেএস

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

প্রথমে, বর্তমানে ক্লিক করা বোতামে data-1hot অ্যাট্রিবিউটটি পরীক্ষা করুন, এই অ্যাট্রিবিউটের নাম দিয়ে this.getAttribute() কল করুন, এই ক্ষেত্রে data-1hot প্যারামিটার হিসেবে। যেহেতু এটি একটি স্ট্রিং, তাই আপনি parseInt() ব্যবহার করে এটিকে একটি পূর্ণসংখ্যায় কাস্ট করতে পারেন এবং এই ফলাফলটি classNumber.

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.

Let's walk through it:

স্ক্রিপ্ট.জেএস

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.

541051644a45131f.gif

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:

স্ক্রিপ্ট.জেএস

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.

You're almost there! 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:

স্ক্রিপ্ট.জেএস

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:

স্ক্রিপ্ট.জেএস

/**
 * 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:

bf1ac3cc5b15740.gif

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.

১৭. অভিনন্দন

Congratulations! 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:

  1. What transfer learning is, and its advantages over training a full model.
  2. How to get models for re-use from TensorFlow Hub.
  3. How to set up a web app suitable for transfer learning.
  4. How to load and use a base model to generate image features.
  5. How to train a new prediction head that can recognize custom objects from webcam imagery.
  6. 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? The possibilities are endless.

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