Feed-forward ANN - 2
(Artificial Neuron থেকে Fully Connected Network)
আজকের পোস্টের সঙ্গে যে notebookটা আছে, তার কিছু অংশের অনুপ্রেরণা Sebastian Bodenstein এর October 2015 এর talk আর Tuseeta Banerjeeর নিউরাল নেটওয়ার্ক নিয়ে notebook।
আগের পোস্টে আমরা শিখেছি, কি করে একটা Artificial Neuron (AN) বানানো যায়। আমরা ভাবতেই পারি, যে AN এর তিনটে অংশ: Inputs, Output, আর Activation Function (AF)। Input যদিও অনেকরকম হতে পারে, কিন্তু আমরা এখনো অবধি যেকোন vector \( \{x_1, x_2, x_3, \ldots\} \) কে input হিসেবে ব্যবহার করতে শিখেছি। এরপর ভাবতে পারি, AN এর output হলো: \( \vec{w}\cdot\vec{x} + b \)। AF এর কাজ হলো এর ওপর একটা function চাপিয়ে দেওয়া, যাতে output টা বদলে গিয়ে হয়: \( f_0\left( \vec{w}\cdot\vec{x} + b \right) \)।
AF কে আপাতত যদি সরিয়ে রাখি, তাহলে আমাদের AN কে নির্দেশ করার জন্যে শুধু \( \vec{w} \) আর \( b \)-ই যথেষ্ট, তাই না? বেশ। আমরা এর আগে অল্প কথায় জেনেছি, যে একা এই ব্যাটার পক্ষে একটা XOR gate-ও বানানো সম্ভব নয়। বেশ, তবে একে একটু শক্তিশালী করতে এদের কয়েকটাকে আমরা একসাথে জুড়ে দিতে পারি। এরা সবাই একই input নেবে, কিন্তু এদের প্রত্যেকের \( \vec{w} \) আর \( b \) হবে আলাদা। ফলে, প্রত্যেকের output আলাদা হবে। এদের একসঙ্গে আমরা একটা Layer বলবো। আরেকটু নির্দিষ্ট করে বললে একে একটা Linear Layer বলবো। এই গোটা জিনিসটা তবে উপরের ছবির মতো দেখতে হবে।
এই layerটাকে আমরা একটা function হিসেবে ভাবতে পারি। প্রতিটা AN এর \( \vec{w} \) আর \( b \) যেহেতু আলাদা, তাই এখন, গোটা layerএর জন্যে আমরা একটা weight matrix \( W \) পাবো, যার row গুলো হবে একেকটা AN এর \( \vec{w} \)। অর্থাৎ, \( W_{ij} \) হবে \( i \)-তম AN এর weight vector এর \( j \)-তম element। তেমনি, layerএর একটা bias vector \( \vec{B} \) থাকবে, যেখানে \( B_i \) হবে \( i \)-তম AN এর bias। উপরের ছবির layer এর তবে একখান \( (5 \times 3)~W \) আছে। তাহলে আমাদের layerএর functionটা দাঁড়ালো: \( \vec{x} \rightarrow W~\vec{x} +\vec{B} \)। এই functionটা আমরা Mathematicaয় কি করে তৈরি করতে পারি? এইভাবে:
linear[data_, weight_, bias_] := Dot[weight, data] + bias
কিন্তু এই layerটা তো ঠিক AN এর layer নয়, তার জন্যে প্রতিটা output এর ওপর AF লাগাতে হবে। আমাদের Linear Layer এর প্রতিটা output, প্রতিটি input এর সঙ্গে যুক্ত, মানে, প্রতিটি input এর ওপর নির্ভর করে। তাই একে অনেকসময়েই Fully Connected Layerও বলা হয়। আমরা একটু অন্যরকম একটা layerএর কথাও ভাবতে পারি, যার কাজ হলো অন্য layerএর সব outputএর ওপর একই function চাপানো। এটাই আমাদের AFএর layer হবে তাহলে। কোন layerএর প্রতিটি elementএর ওপর একই function চাপায় বলে, একে আমরা Elementwise Layer বলবো। Mathematicaয় এই layer বানানোর কাজটা খুব সহজ করে দেওয়া আছে। নীচের উদাহরণে দেখো, আমরা একটা linear layer (unilayer) বানিয়েছি, যার মধ্যে 2 খানা neuron আছে, আর যার input (data) হলো একটা 3-dimensional vector, মানে ওতে তিনখানা element আছে:
In[1]:= data = {2, 10, 3};
In[2]:= unilayer = LinearLayer[2, "Input" -> 3]
Out[2]:=
বানিয়ে তো ফেললাম, কিন্তু এই layer এর \( W \) আর \( B \) তো আমরা Mathematicaকে সাপ্লাই করিনি। দেখো, সেই জন্যেই উপরের উদাহরণে ওগুলো লাল হয়ে আছে। Mathematica একটা linear layer এর খাঁচা তৈরি করেছে, কিন্তু খাঁচাটা ফাঁকা। আপাতত আমরা দেখতে চাই, কিছু random value দিয়ে যদি \( W \) কে ভরে দেওয়া যায়, তবে এটাকে dataর ওপর চাপানো যাবে। সে জন্যে function হলো NetInitialize। এর কাজ, যে সমস্ত layer এর ভেতর training এর উপযুক্ত parameter থাকে, তাদের কিছু initial value বসিয়ে দেওয়া, যাতে সেই layerকে নিয়ে কিছু পরীক্ষা-নিরীক্ষা করা যায় (মনে রেখো, এই weight আর bias গুলোকেই কিন্তু আমরা training এর মাধ্যমে বদলাবো)। Default ফর্মে NetInitialize bias গুলোকে 0 বসায়। বেশ, তবে unilayerকে initialize করে layer বানানো যাক, আর সেই layerকে চাপানো যাক dataর ঘাড়ে:
In[3]:= layer = NetInitialize@unilayer
In[4]:= layer[data]
Out[3]:=
Out[4]:= {1.61596, -1.9618}
দু’টো ব্যাপার খেয়াল করো, প্রথমত, layerএর ভেতরে এখন আর লাল কোন লেখা নেই, দ্বিতীয়ত, layerএর ভেতরে 2 টো Neuron আছে, তার প্রতিটার জন্যে একটা করে output পেয়েছি বলে, layer[data]র output একটা 2-dimensional vector। কি কি \( W \) আর \( B \) ব্যবহার করেছে NetInitialize? জানতে NetExtract ব্যবহার করতে হবে:
In[5]:= Normal@NetExtract[layer, "Weights"] // MatrixForm
In[6]:= Normal@NetExtract[layer, "Biases"]
Out[5]:=
Out[6]:= {0., 0.}
এবার এগুলো ব্যবহার করে যদি আমরা আমাদের বানানো affine transformation function linear কে dataর ওপর বসাই, তবে একদম এক output পাওয়া উচিত। ঠিক তা-ই পাবো:
In[7]:= Normal@linear[data,NetExtract[layer,"Weights"],NetExtract[layer, "Biases"]]
Out[7]:= {1.61596, -1.9618}
আমরা linear layer তৈরি করতে শিখে গেছি। যদি তোমার কাছে একটু পুরনো Mathematica থাকে, তবে DotPlusLayer দিয়ে খোঁজো, নামটা আগে আলাদা ছিলো। একইরকম ভাবে আমরা বানাতে পারি, ElementwiseLayer (সব উদাহরণ পোস্টের সঙ্গের notebookএ আছে)। এই দু’টো layer কে তাহলে পর পর বসিয়ে দিলেই একটা পুরো Artificial Neural Layer তৈরি হয়ে যাবে! কিন্তু, পরপর বসানো মানে? এগুলো তো ঠিক function নয়, একধরনের খাঁচা, যার মধ্যে নানারকম parameter বসানোর সুযোগ আছে। এই পরপর বসানোর কাজটা করে NetChain। উদাহরণ:
In[1]:= net = NetChain[{LinearLayer[5], ElementwiseLayer[LogisticSigmoid], LinearLayer[1]}, "Input" -> "Scalar", "Output" -> "Scalar"];
In[2]:= inet = NetInitialize[net, Method -> {"Random", "Biases" -> 2}];
In[3]:= Plot[inet[x], {x, -5, 5}]
Out[3]:=
উপরের উদাহরণে আমরা তিনখানা layer ব্যবহার করেছি, আর তাদের দু’পাশে আছে input আর output। এর ফলে যে নেটওয়ার্কটা তৈরি হয়েছে, তার চেহারা এই রকম:
ব্যস্, আর কি, বানিয়ে ফেলেছি একটা Artificial Neural Network (ANN)। আগের পোস্টের শুরুতে যে ছবিটা ছিল, সেটাও একটা ANN। তাহলে বোঝা গেল, একটা নেটওয়ার্ক বানাতে আমাদের লাগবে পরপর বেশ কিছু layer। Input আর output layer বাদ দিলে ভেতরে যত layer থাকবে, তাদের আমরা বলবো Hidden Layer। প্রতিটা layerএ কতগুলো করে neuron রাখবো, আর ঠিক কতগুলো hidden layer জুড়ে নেটওয়ার্ক বানাবো, এর পুরোটাই আমাদের হাতে। কিন্তু সে সম্পর্কে বিস্তারিত আমরা পরে শিখবো।
আমাদের আগের দিনের নিয়মে যদি ভাবি, তবে একেকটা linear layer আর activation (elementwise) layer মিলে একটা ‘neural’ layer তৈরি হয়। Perceptronএর সঙ্গে এর বেশ মিল থাকায়, এইরকম layer জুড়ে তৈরি নেটওয়ার্ককে অনেকসময় Multilayer Perceptron (MLP)ও বলে। কিন্তু আমরা জানি, এরা perceptron নয়। তাই এই নামটা এড়িয়ে যাওয়াই ভাল। আরও একটা ব্যাপার দেখো, এখানে সবসময় আগের layer এর output পরের layerএর input হিসেবে ব্যবহার করা হচ্ছে, কখনোই উলটোটা নয়, অর্থাৎ, কোন একটা layerএর output কে কখনোই feedback হিসেবে আগের কোন networkএ ব্যবহার করা হচ্ছে না। কিন্তু সেরকম নেটওয়ার্কও আছে। সে সবের থেকে আলাদা করতে আমাদের জানা এই ধরনের networkকে Feed-forward network বলে। আশা করি, এবার পোস্টের নাম-মাহাত্ম্য বোঝা গেছে।
ভাল কথা, দোকান খুলে ফেলেছি, কিন্তু কি বিক্রি করবো? খদ্দেরই বা কোথায়? একটা ANN দিয়ে কোন সমস্যা সমাধান করতে গেলে আমাদের কয়েকটা জিনিস ঠিক করে তবেই মাঠে নামতে হবে:
কি?: আমরা ঠিক কি কি কাজ করতে পারি এই যন্তরটা দিয়ে? বোঝাই যাচ্ছে, অনে—ক কিছু, কিন্তু আপাতত (যেহেতু আমাদের লক্ষ্য হাতেকলমে একটা কাজ করে ব্যাপারটা সম্পর্কে একটা ধারণা পাওয়া), আমরা শুধু এক ধরনের কাজের কথা ভাববো: classification। অর্থাৎ, যদি আমাদের কাছে যদি কিছু জিনিস থাকে (সে numeric data, ছবি, লেখা – যা ইচ্ছে), আর যদি তাদের কিছু class-এ ভাগ করে ফেলা সম্ভব হয়, তবে জিনিসটা মেশিনকে দিলে সে সেই classificationটা কতটা ভাল করতে পারে, তা দেখা।
কিভাবে?: এই দুরূহ কাজটা করতে আমরা দু’ভাবে এগোতে পারি – 1) কিছুই না বলে মেশিনকে data ধরিয়ে দিয়ে জিজ্ঞেস করতে পারি – এদের মধ্যে থেকে কি কিছু classification করা সম্ভব? অথবা, 2) যদি আমাদের কাছে বেশ কিছু উদাহরণ থাকে, যেখানে বেশ কিছু dataকে ইতিমধ্যেই classify করে রাখা আছে, তবে আমরা পরপর মেশিনকে সেই data আর তার class দেখিয়ে ‘train’ করতে পারি, যাতে এরপর নতুন data পেলে সে নিজেই লব্ধ জ্ঞানের সাহায্যে তাকে সঠিক class এ বসিয়ে দিতে পারে। দ্বিতীয় রাস্তায় প্রথমেই training এর সময় যে তদারকির দরকার, তার কারণে একে বলে supervised learning। আমরা প্রথমে এটাই করতে শিখবো, নিজেদের বানানো একটা ANN দিয়ে। ANN আমরা অল্পস্বল্প বানাতে জানলেও, কি করে তা কাজ করে, এখনো জানিনা, অতএব সেটা আপাতত একটু হলেও জানতে হবে।
কাকে?: Training করতে হলে, আমাদের দরকার – data। যে সে data হলে হবে না। চাই এমন data, যার প্রতিটি উদাহরণকে সঠিকভাবে তার ‘class’ দিয়ে চিহ্নিত (label) করা আছে। একে আমরা বলবো ‘training data’। কপাল ভালো থাকলে, আমাদের কাছে এমন কিছু dataও থাকতে পারে, যা আমরা মেশিনকে না দেখিয়ে সরিয়ে রাখতে পারি, আর training এর পর মেশিনকে সেই data দেখিয়ে জিজ্ঞেস করতে পারি, তার class কি (অবশ্যই উত্তর না দেখিয়ে)। তারপর মেশিনের দেওয়া উত্তর মিলিয়ে দেখতে পারি, সে পাশ করেছে কি না। এই দ্বিতীয় ধরনের dataকে আমরা বলবো ‘test data’।
কেমন?: শুধু পরীক্ষা পাশ করলে তো হবেনা, মেশিন classification এ কত ভাল নম্বর পেলো, তা-ও দেখতে হবে। তার জন্যে জানতে হবে, classification ব্যাপারটার হাল-হকিকৎ, আর কতভাবে তার গুণগত মান ঠিক করা যায়।
পোস্টটা এখানেই শেষ করা যাক। পরের পোস্টগুলোয় দেখা যাক, আমরা এই প্রশ্নগুলোর উত্তর খুঁজে একটা networkকে train করাতে পারি কিনা…
আগের পোস্টে আমরা শিখেছি, কি করে একটা Artificial Neuron (AN) বানানো যায়। আমরা ভাবতেই পারি, যে AN এর তিনটে অংশ: Inputs, Output, আর Activation Function (AF)। Input যদিও অনেকরকম হতে পারে, কিন্তু আমরা এখনো অবধি যেকোন vector \( \{x_1, x_2, x_3, \ldots\} \) কে input হিসেবে ব্যবহার করতে শিখেছি। এরপর ভাবতে পারি, AN এর output হলো: \( \vec{w}\cdot\vec{x} + b \)। AF এর কাজ হলো এর ওপর একটা function চাপিয়ে দেওয়া, যাতে output টা বদলে গিয়ে হয়: \( f_0\left( \vec{w}\cdot\vec{x} + b \right) \)।
AF কে আপাতত যদি সরিয়ে রাখি, তাহলে আমাদের AN কে নির্দেশ করার জন্যে শুধু \( \vec{w} \) আর \( b \)-ই যথেষ্ট, তাই না? বেশ। আমরা এর আগে অল্প কথায় জেনেছি, যে একা এই ব্যাটার পক্ষে একটা XOR gate-ও বানানো সম্ভব নয়। বেশ, তবে একে একটু শক্তিশালী করতে এদের কয়েকটাকে আমরা একসাথে জুড়ে দিতে পারি। এরা সবাই একই input নেবে, কিন্তু এদের প্রত্যেকের \( \vec{w} \) আর \( b \) হবে আলাদা। ফলে, প্রত্যেকের output আলাদা হবে। এদের একসঙ্গে আমরা একটা Layer বলবো। আরেকটু নির্দিষ্ট করে বললে একে একটা Linear Layer বলবো। এই গোটা জিনিসটা তবে উপরের ছবির মতো দেখতে হবে।
এই layerটাকে আমরা একটা function হিসেবে ভাবতে পারি। প্রতিটা AN এর \( \vec{w} \) আর \( b \) যেহেতু আলাদা, তাই এখন, গোটা layerএর জন্যে আমরা একটা weight matrix \( W \) পাবো, যার row গুলো হবে একেকটা AN এর \( \vec{w} \)। অর্থাৎ, \( W_{ij} \) হবে \( i \)-তম AN এর weight vector এর \( j \)-তম element। তেমনি, layerএর একটা bias vector \( \vec{B} \) থাকবে, যেখানে \( B_i \) হবে \( i \)-তম AN এর bias। উপরের ছবির layer এর তবে একখান \( (5 \times 3)~W \) আছে। তাহলে আমাদের layerএর functionটা দাঁড়ালো: \( \vec{x} \rightarrow W~\vec{x} +\vec{B} \)। এই functionটা আমরা Mathematicaয় কি করে তৈরি করতে পারি? এইভাবে:
linear[data_, weight_, bias_] := Dot[weight, data] + bias
অন্য কথা:
Linear Layer যেটা করে, তাকে বলে Affine Transformation। কোন সোজা লাইনের ওপর এই ধরনের transform প্রয়োগ করলে, transformation এর পরেও লাইনের ওপর থাকা সমস্ত পয়েন্টের transformed পয়েন্টও একই লাইনের ওপর থাকে, আর সমস্ত আপেক্ষিক দূরত্বও সমান থাকে। যেমন, লাইনের ঠিক মাঝখানের পয়েন্ট, transformএর পরেও, লাইনের মধ্যবিন্দুই থাকবে। চলতি কথায় অনেকসময় affine transformation কে ‘Linear Transformation’ও বলা হয়। সঙ্গের ছবিতে, একটা বৃত্তকে বারবার affine transformation করে অন্য ছবিগুলো বানিয়ে জুড়ে দেওয়া হয়েছে। বোঝার সুবিধের জন্যে প্রতি transform এ রঙের গাঢ়ত্ব আর পরিধির প্রস্থ একটু করে কমিয়ে দেওয়া হয়েছে।
Linear Layer যেটা করে, তাকে বলে Affine Transformation। কোন সোজা লাইনের ওপর এই ধরনের transform প্রয়োগ করলে, transformation এর পরেও লাইনের ওপর থাকা সমস্ত পয়েন্টের transformed পয়েন্টও একই লাইনের ওপর থাকে, আর সমস্ত আপেক্ষিক দূরত্বও সমান থাকে। যেমন, লাইনের ঠিক মাঝখানের পয়েন্ট, transformএর পরেও, লাইনের মধ্যবিন্দুই থাকবে। চলতি কথায় অনেকসময় affine transformation কে ‘Linear Transformation’ও বলা হয়। সঙ্গের ছবিতে, একটা বৃত্তকে বারবার affine transformation করে অন্য ছবিগুলো বানিয়ে জুড়ে দেওয়া হয়েছে। বোঝার সুবিধের জন্যে প্রতি transform এ রঙের গাঢ়ত্ব আর পরিধির প্রস্থ একটু করে কমিয়ে দেওয়া হয়েছে।
কিন্তু এই layerটা তো ঠিক AN এর layer নয়, তার জন্যে প্রতিটা output এর ওপর AF লাগাতে হবে। আমাদের Linear Layer এর প্রতিটা output, প্রতিটি input এর সঙ্গে যুক্ত, মানে, প্রতিটি input এর ওপর নির্ভর করে। তাই একে অনেকসময়েই Fully Connected Layerও বলা হয়। আমরা একটু অন্যরকম একটা layerএর কথাও ভাবতে পারি, যার কাজ হলো অন্য layerএর সব outputএর ওপর একই function চাপানো। এটাই আমাদের AFএর layer হবে তাহলে। কোন layerএর প্রতিটি elementএর ওপর একই function চাপায় বলে, একে আমরা Elementwise Layer বলবো। Mathematicaয় এই layer বানানোর কাজটা খুব সহজ করে দেওয়া আছে। নীচের উদাহরণে দেখো, আমরা একটা linear layer (unilayer) বানিয়েছি, যার মধ্যে 2 খানা neuron আছে, আর যার input (data) হলো একটা 3-dimensional vector, মানে ওতে তিনখানা element আছে:
In[1]:= data = {2, 10, 3};
In[2]:= unilayer = LinearLayer[2, "Input" -> 3]
Out[2]:=
বানিয়ে তো ফেললাম, কিন্তু এই layer এর \( W \) আর \( B \) তো আমরা Mathematicaকে সাপ্লাই করিনি। দেখো, সেই জন্যেই উপরের উদাহরণে ওগুলো লাল হয়ে আছে। Mathematica একটা linear layer এর খাঁচা তৈরি করেছে, কিন্তু খাঁচাটা ফাঁকা। আপাতত আমরা দেখতে চাই, কিছু random value দিয়ে যদি \( W \) কে ভরে দেওয়া যায়, তবে এটাকে dataর ওপর চাপানো যাবে। সে জন্যে function হলো NetInitialize। এর কাজ, যে সমস্ত layer এর ভেতর training এর উপযুক্ত parameter থাকে, তাদের কিছু initial value বসিয়ে দেওয়া, যাতে সেই layerকে নিয়ে কিছু পরীক্ষা-নিরীক্ষা করা যায় (মনে রেখো, এই weight আর bias গুলোকেই কিন্তু আমরা training এর মাধ্যমে বদলাবো)। Default ফর্মে NetInitialize bias গুলোকে 0 বসায়। বেশ, তবে unilayerকে initialize করে layer বানানো যাক, আর সেই layerকে চাপানো যাক dataর ঘাড়ে:
In[3]:= layer = NetInitialize@unilayer
In[4]:= layer[data]
Out[3]:=
Out[4]:= {1.61596, -1.9618}
দু’টো ব্যাপার খেয়াল করো, প্রথমত, layerএর ভেতরে এখন আর লাল কোন লেখা নেই, দ্বিতীয়ত, layerএর ভেতরে 2 টো Neuron আছে, তার প্রতিটার জন্যে একটা করে output পেয়েছি বলে, layer[data]র output একটা 2-dimensional vector। কি কি \( W \) আর \( B \) ব্যবহার করেছে NetInitialize? জানতে NetExtract ব্যবহার করতে হবে:
In[5]:= Normal@NetExtract[layer, "Weights"] // MatrixForm
In[6]:= Normal@NetExtract[layer, "Biases"]
Out[5]:=
Out[6]:= {0., 0.}
এবার এগুলো ব্যবহার করে যদি আমরা আমাদের বানানো affine transformation function linear কে dataর ওপর বসাই, তবে একদম এক output পাওয়া উচিত। ঠিক তা-ই পাবো:
In[7]:= Normal@linear[data,NetExtract[layer,"Weights"],NetExtract[layer, "Biases"]]
Out[7]:= {1.61596, -1.9618}
আমরা linear layer তৈরি করতে শিখে গেছি। যদি তোমার কাছে একটু পুরনো Mathematica থাকে, তবে DotPlusLayer দিয়ে খোঁজো, নামটা আগে আলাদা ছিলো। একইরকম ভাবে আমরা বানাতে পারি, ElementwiseLayer (সব উদাহরণ পোস্টের সঙ্গের notebookএ আছে)। এই দু’টো layer কে তাহলে পর পর বসিয়ে দিলেই একটা পুরো Artificial Neural Layer তৈরি হয়ে যাবে! কিন্তু, পরপর বসানো মানে? এগুলো তো ঠিক function নয়, একধরনের খাঁচা, যার মধ্যে নানারকম parameter বসানোর সুযোগ আছে। এই পরপর বসানোর কাজটা করে NetChain। উদাহরণ:
In[1]:= net = NetChain[{LinearLayer[5], ElementwiseLayer[LogisticSigmoid], LinearLayer[1]}, "Input" -> "Scalar", "Output" -> "Scalar"];
In[2]:= inet = NetInitialize[net, Method -> {"Random", "Biases" -> 2}];
In[3]:= Plot[inet[x], {x, -5, 5}]
Out[3]:=
উপরের উদাহরণে আমরা তিনখানা layer ব্যবহার করেছি, আর তাদের দু’পাশে আছে input আর output। এর ফলে যে নেটওয়ার্কটা তৈরি হয়েছে, তার চেহারা এই রকম:
ব্যস্, আর কি, বানিয়ে ফেলেছি একটা Artificial Neural Network (ANN)। আগের পোস্টের শুরুতে যে ছবিটা ছিল, সেটাও একটা ANN। তাহলে বোঝা গেল, একটা নেটওয়ার্ক বানাতে আমাদের লাগবে পরপর বেশ কিছু layer। Input আর output layer বাদ দিলে ভেতরে যত layer থাকবে, তাদের আমরা বলবো Hidden Layer। প্রতিটা layerএ কতগুলো করে neuron রাখবো, আর ঠিক কতগুলো hidden layer জুড়ে নেটওয়ার্ক বানাবো, এর পুরোটাই আমাদের হাতে। কিন্তু সে সম্পর্কে বিস্তারিত আমরা পরে শিখবো।
আমাদের আগের দিনের নিয়মে যদি ভাবি, তবে একেকটা linear layer আর activation (elementwise) layer মিলে একটা ‘neural’ layer তৈরি হয়। Perceptronএর সঙ্গে এর বেশ মিল থাকায়, এইরকম layer জুড়ে তৈরি নেটওয়ার্ককে অনেকসময় Multilayer Perceptron (MLP)ও বলে। কিন্তু আমরা জানি, এরা perceptron নয়। তাই এই নামটা এড়িয়ে যাওয়াই ভাল। আরও একটা ব্যাপার দেখো, এখানে সবসময় আগের layer এর output পরের layerএর input হিসেবে ব্যবহার করা হচ্ছে, কখনোই উলটোটা নয়, অর্থাৎ, কোন একটা layerএর output কে কখনোই feedback হিসেবে আগের কোন networkএ ব্যবহার করা হচ্ছে না। কিন্তু সেরকম নেটওয়ার্কও আছে। সে সবের থেকে আলাদা করতে আমাদের জানা এই ধরনের networkকে Feed-forward network বলে। আশা করি, এবার পোস্টের নাম-মাহাত্ম্য বোঝা গেছে।
ভাল কথা, দোকান খুলে ফেলেছি, কিন্তু কি বিক্রি করবো? খদ্দেরই বা কোথায়? একটা ANN দিয়ে কোন সমস্যা সমাধান করতে গেলে আমাদের কয়েকটা জিনিস ঠিক করে তবেই মাঠে নামতে হবে:
কি?: আমরা ঠিক কি কি কাজ করতে পারি এই যন্তরটা দিয়ে? বোঝাই যাচ্ছে, অনে—ক কিছু, কিন্তু আপাতত (যেহেতু আমাদের লক্ষ্য হাতেকলমে একটা কাজ করে ব্যাপারটা সম্পর্কে একটা ধারণা পাওয়া), আমরা শুধু এক ধরনের কাজের কথা ভাববো: classification। অর্থাৎ, যদি আমাদের কাছে যদি কিছু জিনিস থাকে (সে numeric data, ছবি, লেখা – যা ইচ্ছে), আর যদি তাদের কিছু class-এ ভাগ করে ফেলা সম্ভব হয়, তবে জিনিসটা মেশিনকে দিলে সে সেই classificationটা কতটা ভাল করতে পারে, তা দেখা।
কিভাবে?: এই দুরূহ কাজটা করতে আমরা দু’ভাবে এগোতে পারি – 1) কিছুই না বলে মেশিনকে data ধরিয়ে দিয়ে জিজ্ঞেস করতে পারি – এদের মধ্যে থেকে কি কিছু classification করা সম্ভব? অথবা, 2) যদি আমাদের কাছে বেশ কিছু উদাহরণ থাকে, যেখানে বেশ কিছু dataকে ইতিমধ্যেই classify করে রাখা আছে, তবে আমরা পরপর মেশিনকে সেই data আর তার class দেখিয়ে ‘train’ করতে পারি, যাতে এরপর নতুন data পেলে সে নিজেই লব্ধ জ্ঞানের সাহায্যে তাকে সঠিক class এ বসিয়ে দিতে পারে। দ্বিতীয় রাস্তায় প্রথমেই training এর সময় যে তদারকির দরকার, তার কারণে একে বলে supervised learning। আমরা প্রথমে এটাই করতে শিখবো, নিজেদের বানানো একটা ANN দিয়ে। ANN আমরা অল্পস্বল্প বানাতে জানলেও, কি করে তা কাজ করে, এখনো জানিনা, অতএব সেটা আপাতত একটু হলেও জানতে হবে।
কাকে?: Training করতে হলে, আমাদের দরকার – data। যে সে data হলে হবে না। চাই এমন data, যার প্রতিটি উদাহরণকে সঠিকভাবে তার ‘class’ দিয়ে চিহ্নিত (label) করা আছে। একে আমরা বলবো ‘training data’। কপাল ভালো থাকলে, আমাদের কাছে এমন কিছু dataও থাকতে পারে, যা আমরা মেশিনকে না দেখিয়ে সরিয়ে রাখতে পারি, আর training এর পর মেশিনকে সেই data দেখিয়ে জিজ্ঞেস করতে পারি, তার class কি (অবশ্যই উত্তর না দেখিয়ে)। তারপর মেশিনের দেওয়া উত্তর মিলিয়ে দেখতে পারি, সে পাশ করেছে কি না। এই দ্বিতীয় ধরনের dataকে আমরা বলবো ‘test data’।
কেমন?: শুধু পরীক্ষা পাশ করলে তো হবেনা, মেশিন classification এ কত ভাল নম্বর পেলো, তা-ও দেখতে হবে। তার জন্যে জানতে হবে, classification ব্যাপারটার হাল-হকিকৎ, আর কতভাবে তার গুণগত মান ঠিক করা যায়।
পোস্টটা এখানেই শেষ করা যাক। পরের পোস্টগুলোয় দেখা যাক, আমরা এই প্রশ্নগুলোর উত্তর খুঁজে একটা networkকে train করাতে পারি কিনা…
No comments