ব্যাসিক পরিচিতি
Last updated
Last updated
চলুন আমরা একটা জগতের কথা চিন্তা করি যে জগতে একটা কম্পিউটার আছে যার ডিসপ্লে মাত্র 2x2পিক্সেল সাইজের। আর ওই জগতে সব মিলে ২টা ক্যারেক্টার বা বর্ণ আছে যেগুলো হচ্ছে,এবং /অর্থাৎ ওখানকার কিবোর্ড দিয়ে একটা ফরওয়ার্ড স্ল্যাস অথবা একটা ব্যাক স্ল্যাস লেখা যায় :Pঅনেকটা নিচের মত -</p>
এখন আমরা এই কম্পিউটারের জন্য একটা ইমেজ ক্লাসিফায়ার সফটওয়্যার বানাতে চাই যাতে করে যখন আমরা কম্পিউটারকে নিচের ইমেজটি ইনপুট দেবো তখন সে যাতে সেটা চিনে বলতে পারে যে এটা একটা \. (ব্যাক স্ল্যাস)
এবং একই ভাবে ফরওয়ার্ড স্ল্যাসটাকেও চিনতে পারে।
কিন্তু আমরা সবাই জানি যে কম্পিউটারের কাছে সব কিছুই আসলে নাম্বার। কম্পিউটার তো আর সরাসরি ফটো চেনে না, খুব বেশি হলে একটা ফটোর ম্যাথেমেটিক্যাল রিপ্রেজেন্টেশন চেনে। তাই, ধরে নিচ্ছি যে সেই কম্পিউটারের গ্রাফিক্স প্রোগ্রামটি মনিটরে কোন অ্যাক্টিভ পিক্সেল বা রং (এক্ষেত্রে ধরি লাল রঙের মান 1) দেখানোর জন্য 1 ব্যবহার করে এবং রং এর অনুপস্থিতি (ধরি গ্রে কালার এর মান -1) প্রকাশের জন্য -1 ব্যবহার করে।এতে করে প্রত্যেকটি বর্ণের গ্রাফিক্যাল রিপ্রেজেন্টেশন নিচের মত ধরে নেয়া যেতে পারে।
কিন্তু গ্রাফিক্যাল রিপ্রেজেন্টেশন বা ম্যাথেম্যাটিক্যাল রিপ্রেজেন্টেশন যাই হোক কম্পিউটার এই ম্যাট্রিক্সের মত দেখতে ডাটা ফরম্যাটকে লম্বা একটা অ্যারের মত করেই ধরে, হিসাব নিকাশ করার জন্য। অর্থাৎ নিচের মত,
পাইছি এবার। খেয়াল করুন এই দুটা আলাদা ইমেজের জন্য যে ফাইনাল ডাটা স্ট্রাকচার দাঁড়ালো সেগুলোকে কিন্তু আমরা আমাদের সেই প্রথম দিকের ইনপুট কম্বিনেশন সমস্যার সাথেই তুলনা করতে পারি। অর্থাৎ 1 -1 -1 1 কম্বিনেশনের আউটপুট ধরি 1 (ধরি 1 মানে ব্যাক স্ল্যাস) আর -1 1 1 -1 কম্বিনেশনের আউটপুট ধরি 0 (ধরি 0 মানে ফরওয়ার্ড স্ল্যাস)।
তাহলে যদি আমরা এই ইনপুট কম্বিনেশন গুলোতে সঠিক ভাবে কিছু ওয়েট সেট করতে পারি এবং দুইটা আলাদা ইনপুট কম্বিনেশনের জন্য দুটো আলাদা রেজাল্ট আসে (একটা শূন্যের কাছা কাছি আরেকটা এক এর কাছাকাছি। তাহলেই কিন্তু আমাদের ইমেজ ক্লাসিফায়ার তৈরি হয়ে গেলো। ওই ক্লাসিফায়ারে যতবারই [1 -1 -1 1] তথা ব্যাক স্ল্যাসের ইমেজের একটি ডাটা ম্যাট্রিক্স দেয়া হবে ততবার সে ওই ইনপুট গুলোর সাথে ওয়েট এর গুন যোগ করে আউটপুট দিবে ১ এর কাছাকাছি একটা মান আর আমরা জানি ১ মানে ব্যাক স্ল্যাস। তাই চিনে যাবো এই ইমেজ একটা ব্যাক স্ল্যাস। তো, চলুন এই সিম্পল ক্লাসিফায়ারের জন্য কিছু অপ্টিমাইজড ওয়েট বের করি।
প্রথমেই সব ওয়েট মনে করি 1. তাহলে [1 -1 -1 1] এর জন্য -
(1*1) + (-1*1) + (-1*1) + (1*1) = 1 - 1 - 1 + 1 = 0
আর [-1 1 1 -1] এর জন্য -
(-1*1)+(1*1)+(1*1)*(-1*1) = -1 + 1 + 1 - 1 = 0
লাভ হল না, দুইটার ক্ষেত্রেই শূন্য আসছে অর্থার ক্লাসিফাই করার মত সলিড Rule এটা হয় নি বা বলা যায় ওয়েট গুলো সঠিক হয় নি। ওয়েট গুলো একটু অ্যাডজাস্ট করে নিচের মত ট্রাই করি। অর্থাৎ প্রথম এইজের ওয়েট ধরি 1, দ্বিতীয় এইজের ওয়েট ধরি -1, তৃতীয় এইজের ওয়েট ধরি -1 এবং চতুর্থ এইজের ওয়েট ধরি 1. (যেহেতু চারটা Edge ধরে ৪টা ইনপুট আসছে একটা নিউরনের দিকে)
তাহলে [1 -1 -1 1] এর জন্য -
(1*1) + (-1*-1) + (-1*-1) + (1*1) = 1 + 1 + 1 + 1 = 4 Sigmoid করে 0.98
আর [-1 1 1 -1] এর জন্য -
(-1*1)+(1*-1)+(1*-1)*(-1*1) = -1 - 1 - 1 - 1 = -4 Sigmoid করে 0.01
অর্থাৎ আমরা মোটামুটি সঠিক ওয়েট এর খোঁজ পেয়েছি যেগুলো একটি ব্যাসিক নিউরাল নেটওয়ার্কে ব্যবহার করলে দুটা আলাদা ইনপুট কম্বিনেশনের জন্য দুটো আলাদা আউটপুট আসে এবং তার সাহায্যে আমরা দুটো ইমেজকে ক্লাসিফাই বা আলাদা করে চিনতে পারি :D একটু পরীক্ষা করেও দেখতে পারেন যে আসলেই সঠিক ওয়েটের খোঁজ পাওয়া গেছে কিনা। যেমন - নিচের দুটো ইমেজের কথা চিন্তা করুন,
দেখে মনে হচ্ছে উপরের ইমেজটি একটি ব্যাক স্ল্যাস কিন্তু উপড়ে একটু কালি বেশি পরে গেছে। আর নিচেরটা একটা ফরওয়ার্ড স্ল্যাস কিন্তু উপড়ে পুরোটা আকা শেষ হয়নি। এটা আমরা ধারনা করতে পারছি। কিন্তু চলুন পরীক্ষা করে দেখি আমাদের একটু আগের ব্যাসিক ইমেজ ক্লাসিফায়ার নিউরাল নেটওয়ার্ক এটা ধরতে পারে কিনা।
তাহলে প্রথম ইমেজ অর্থাৎ [1 1 -1 1] এর জন্য -
(1*1) + (1*-1) + (-1*-1) + (1*1) = 1 - 1 + 1 + 1 = 2 Sigmoid করে 0.88 (1 এর কাছাকাছি অর্থাৎ ব্যাক স্ল্যাস)
আর [-1 -1 1 -1] এর জন্য -
(-1*1)+(-1*-1)+(1*-1)*(-1*1) = -1 + 1 - 1 - 1 = -2 Sigmoid করে 0.11 (0 এর কাছাকাছি অর্থাৎ ফরওয়ার্ড ল্যাস)
গ্রেট, এরকম ভাঙ্গা হাতের লেখাকেও আমাদের ক্লাসিফায়ার ঠিকি ধরতে পারছে :) কিন্তু ভুলে গেলে চলবে না, এই যে, হুট করে সব ওয়েট [1 1 1 1] এর কথা চিন্তা করে তারপর অপ্টিমাইজড ওয়েট [1 -1 -1 1] -এ আসতে পারা, এখানে কিন্তু সেই এরর, অ্যাডজাস্ট, লার্নিং লুপেরই কাজ করতে হবে। এসব আগেই আলোচনা হয়ে গেছে :) আমরা বোঝার জন্য এক লাফেই অপ্টাইজ ওয়েট নিয়ে পরীক্ষা করেছি।
এবার চলুন একটু জটিল আরেকটা জগতের কথা চিন্তা করি যে জগতে একটা কম্পিউটার আছে যার ডিসপ্লে 3x3 পিক্সেল সাইজের। আর ওই জগতে সব মিলে ৪টা ক্যারেক্টার বা বর্ণ আছে যেগুলো হচ্ছে - \ / X O অর্থাৎ ওখানকার কিবোর্ড দিয়ে একটা ফরওয়ার্ড স্ল্যাস, একটা ব্যাক স্ল্যাস, একটা এক্স, আরেকটা ও লেখা যায় :P অনেকটা নিচের মত -
এখন মনে করুন যে ওই ৪টি বর্ণের কোন একটিকে কম্পিউটারে টাইপ করলে এর মনিটরে নিচের মত করে সেই ক্যারেক্টারটি রেন্ডার হয় -
এখন প্রশ্ন হচ্ছে কিভাবে আমরা তুলনামূলক জটিল একটি ক্লাসিফায়ার বানাতে পারি যার মাধ্যমে আমরা এই ক্যারেক্টার গুলোকে শুধুমাত্র তাদের ডাটা দেখে আলাদা করে চিনতে পারি? এখানে কিন্তু সেই ব্যাসিক ক্লাসিফায়ার কাজ করবে না। কেন করবে না সেটা এই পোস্টের দ্বিতীয় উদাহরণ পড়লেও আন্দাজ পাওয়া যাবে। এমনকি খুব সময় দিয়ে ওয়েট অ্যাডজাস্ট করে করেও এর জন্য পারফেক্ট কোন ওয়েট ম্যাট্রিক্স পাওয়া যাবে না যাতে করে ক্লাসিফায়ারটি খুব অ্যাকিউরেট হয়। কারন - বাস্তবে একটা বর্ণ একটা ইমেজের একদম মাঝেখানেই যে থাকবে তা নয়। বর্ণ একটাই যদি ধরি X. সেটা এক একটা ইমেজে এক এক ভাবে থাকতে পারে। যেমন - কোন ফটোতে একটু ডানে চাপিয়ে, কোনটাতে একটু বাপে চেপে অথবা কোথাও একটু ছোট (কম পিক্সেল ডাইমেনশন নিয়ে), অথবা কোথাও বড় আকারে থাকতে পারে। তাই পিক্সেল গুলোর সাথে যতই পারেফেক্ট ওয়েট জুড়ে দেয়া হোক না কেন, অবস্থা বিশেষে ক্লাসিফায়ার চিনতে পারবে না যে সেই ফটোতে নির্দিষ্ট একটা বর্ণ আছে।
তো উপায় যেটা সেটা হচ্ছে, একটা X দেখতে কেমন এবং তার বিভিন্ন অংশ গুলো কেমন সেগুলোকে প্রথমে চিনে তারপর অংশ ভিত্তিক কম্বিনেশন খুঁজতে হবে সেই বড় ইমেজটাতে (যেটায় X লুকায় আছে)। পিক্সেল ভিত্তিক খোঁজে আর কাজ হবে না। এতে করে X বর্ণটা ইমেজের যেখানেই থাকুক আর যেভাবেই থাকুক না কেন, তার অংশ বিশেষগুলো কিন্তু যেখানে থাকবে একভাবে থাকবে। অর্থাৎ X এর হাত গুলো কিন্তু ছিন্ন বিচ্ছিন্ন হয়ে থাকবে না। যেখানেই থাকুক না কেন হাত গুলো জয়েন্ট আকারেই থাকবে। তেমনি O যেখানেই যেভাবে থাকুক, মাঝখানে একটা ফাকা জায়গা থাকবে এটা স্বাভাবিক।
আচ্ছা, এবার আমরা একটু 2x2 পিক্সেলের জগত থেকে হেল্প নেবো। সেখানে আমাদের ব্যাক এবং ফরওয়ার্ড স্ল্যাস আছে। খেয়াল করুন, সেগুলাই কিন্তু X এর হাত গুলোর মতই। অর্থাৎ একভাবে খেয়াল করলে বলা যায় যে - তিন পিক্সেল ওয়ালা জগতের X, O, \, / গুলো বস্তুত দুই পিক্সেল ওয়ালা জগতের \ এবং / এর সমন্বয়েই তৈরি। নিচের ফিগারটা একটু খেয়াল করি,
উপরের ডায়ারগ্রামটাই কিন্তু একটা কনভলিউশনাল নিউরাল নেটওয়ার্কের ব্লক ডায়াগ্রাম। (ভয়ের কিছু নাই বিস্তারিত এড়িয়ে যাওয়া হবে না)। দুটি স্টেজে একটা কনভলিউশনাল নিউরাল নেটওয়ার্কের কাজকে বর্ণনা করা যায়। প্রথম স্টেজে অর্থাৎ বামের দিকে একটি বড় ইমেজ থেকে Convolution এবং Pooling টেকনিকের মাধ্যমে ছোট কিন্তু অর্থবহ ইমেজ বের করে আনা হয়। Convolution এর জন্য ছোট ইমেজ ব্যবহার করা হয় যেটাকে ফিল্টার বলা হয়। যেমন X ওয়ালা বড় একটা ইমেজের উপর আমরা \ এর ইমেজ এবং / এর ইমেজ নিয়ে Convolution করতে পারি কারণ পুরো X এর মধ্যে বস্তুত এগুলোরই অবস্থান। আর তাই X এর হাত গুলোকে চিনে নেয়ার জন্য আমরা শুধু (কাটা) হাতের ফটোকে ফিল্টার হিসেবে ব্যবহার করতে পারি।
এরপর সেই ছোট আকারের ইমেজ গুলোকে নিয়ে পরের স্টেজে নিউরাল নেটওয়ার্ক এর কাজ করা হয়। এই স্টেজে নিউরাল নেটওয়ার্কের লজিক, ওয়েট ইত্যাদি ফিক্স করে, এর আগের স্টেজের ইমেজ অর্থাৎ Pooled ইমেজের উপর কাজ করা হয় এবং পিক্সেল কম্বিনেশন যাচাই করে পার্থক্য বা চেনার কাজ করা হয়। এই দ্বিতীয় স্টেজটাকে বলে Fully Connected Layer আর প্রথম স্টেজকে বলে Convolution Layer (এই স্টেজে পুলিং বা অন্যান্য আরও কিছু ফাংশনের ব্যবহার থাকতে পারে)।
একটু বিস্তারিতভাবে এবার এই কাজ গুলো করে দেখি। নিচের ফিগারটি খেয়াল করুন,
এখানে বাম পাশে একটা X ওয়ালা ইমেজ আছে। তার ডানে আমরা দুটো ফিল্টার নিয়েছি। একটা ফিল্টার আসলে ব্যাক স্ল্যাস চেনার ফিল্টার। এই ফিল্টার দিয়ে বড় ইমেজের উপর ঘুরে বেড়ালে (Convolution করলে) যেখানেই হাই ভ্যালু পাবে সেখানেই একটা ব্যাক স্ল্যাস পাওয়া গেছে বলে ধরে নেয়া যাবে। আগের মত চিন্তা করলে এটা ব্যাক স্ল্যাস চেনার সেই ওয়েট ম্যাট্রিক্স। শুধু +1 আর -1 কে + এবং - এ চিহ্নিত করা হয়েছে (অর্থাৎ [1 -1 -1 1] => [+ - - +]. আরেকটা ফিল্টার হচ্ছে ফরওয়ার্ড স্ল্যাস চেনার ফিল্টার। এই ফিল্টারকে বড় ইমেজের উপড়ে ঘুরিয়ে নিয়ে বেড়ালে যখনই হাই ভ্যালু পাবে তখন সেখানে একটা ফরওয়ার্ড স্ল্যাস আছে বলে জানা যাবে।