Feed-forward ANN - 1
(Perceptron থেকে Neuron)
আজকের পোস্ট শুরু করার আগে একটা ছোট্ট সতর্কবাণী: যখনই ইচ্ছে হবে neural networkএর কার্যপ্রণালীর সঙ্গে আমাদের মস্তিষ্কের তুলনা টানার, সাবধান। যেকোন সময় আমাদের উদাহরণগুলোকে তুমি চিন্তার একটা model হিসেবে ভাবতে পারো, কিন্তু ব্যস্, ওইপর্যন্তই। ওটা modelমাত্র, তাই ভুল হওয়ার সম্ভাবনা চোদ্দ-আনা। modelটা যদি তোমায় বুঝতে সাহায্য করে, বেশ, কিন্তু ভুল করেও ওদের সঙ্গে আমাদের অসম্ভব জটিল আর লক্ষ লক্ষ বছরের বিবর্তনের ফলাফল খুলিটাকে গুলিয়ে ফেলোনা।
আজকের লেখা মূলত Michael Nielsen এর বইয়ের প্রথম চ্যাপ্টারের ওপর নির্ভর করবে। নীচে কিছু animation দেখতে পাবে, যার ওপর ক্লিক করলে একটা interactive web-page খুলবে। সেখানে গিয়ে তোমার যত খুশি খেলতে পারো। যদি সেই উদাহরণ গুলো না চলে (সে server ঢিমে হওয়ার জন্যেই হোক, বা তোমার net-connection ধীর হওয়ার জন্যে), ভয়ের কারণ নেই: আজকের পোস্টে যত interactive উদাহরণ আর যে যে ধরনের function ব্যবহার করা হয়েছে, তার code, পোস্টের একদম নীচের ‘নোটবুক ডাউনলোড’ লিঙ্ক থেকে download করা notebookএ পাওয়া যাবে। নিজের কম্পিউটারে চালিয়ে দেখো।
আমরা কি করে কোন সিদ্ধান্ত নিই? বিশেষ করে যখন অনেকগুলো ঘটনার ওপর সেই সিদ্ধান্তটা নির্ভর করে? একটা উদাহরণ নিয়ে ভাবা যাক: ধরো, তুমি শহর থেকে দূরে হোস্টেলে থাকো, আর weekendএ শহরে গিয়ে অনেকদিন সামান্য পানাহার করা হয়নি। এদিকে সকাল থেকেই আকাশ মেঘলা, আর তোমার বন্ধুরাও তাই দেখে যেতে গড়িমসি করছে। মাসের শেষ, হাতে বেশি টাকাও নেই। যাওয়া কি উচিত? তোমার কথা জানিনা, আমি এ অবস্থায় পরপর কিছু কথা ভেবে তারপর সিদ্ধান্ত নিতাম। একা গিয়ে কোথাও মজা নেই। তাই বন্ধুরা না গেলে এককথায় যাবো না (ওদের ওপর অভিমান করাটা যদিও এক্ষেত্রে জন্মগত অধিকার)। বৃষ্টি পড়লে ফেরাটা মাটি হবে, যানবাহন পেতে বেজায় মুশকিল, অতএব যাওয়ার মানে নেই। টাকা? সে, যদি বন্ধুরা যায়, ব্যবস্থা হয়ে যাবে। মাসের শেষ, নাহয় পরের মাসের শুরুতেই শোধ দিয়ে দেওয়া যাবে’খন। এই অবস্থায়, দেখো দেখি, নিচের ছবি থেকে আমার সিদ্ধান্তগুলো পরিষ্কার হচ্ছে কিনা? ইচ্ছেমতো এক একবার ‘Friends’, ‘Money’ আর ‘Rain’ – এই optionগুলোর নানা combination টিক দিয়ে দেখো তো, আমার মনের অবস্থার একটা মোটামুটি ধারণা পাওয়া যায় কিনা?
আজকের লেখা মূলত Michael Nielsen এর বইয়ের প্রথম চ্যাপ্টারের ওপর নির্ভর করবে। নীচে কিছু animation দেখতে পাবে, যার ওপর ক্লিক করলে একটা interactive web-page খুলবে। সেখানে গিয়ে তোমার যত খুশি খেলতে পারো। যদি সেই উদাহরণ গুলো না চলে (সে server ঢিমে হওয়ার জন্যেই হোক, বা তোমার net-connection ধীর হওয়ার জন্যে), ভয়ের কারণ নেই: আজকের পোস্টে যত interactive উদাহরণ আর যে যে ধরনের function ব্যবহার করা হয়েছে, তার code, পোস্টের একদম নীচের ‘নোটবুক ডাউনলোড’ লিঙ্ক থেকে download করা notebookএ পাওয়া যাবে। নিজের কম্পিউটারে চালিয়ে দেখো।
আমরা কি করে কোন সিদ্ধান্ত নিই? বিশেষ করে যখন অনেকগুলো ঘটনার ওপর সেই সিদ্ধান্তটা নির্ভর করে? একটা উদাহরণ নিয়ে ভাবা যাক: ধরো, তুমি শহর থেকে দূরে হোস্টেলে থাকো, আর weekendএ শহরে গিয়ে অনেকদিন সামান্য পানাহার করা হয়নি। এদিকে সকাল থেকেই আকাশ মেঘলা, আর তোমার বন্ধুরাও তাই দেখে যেতে গড়িমসি করছে। মাসের শেষ, হাতে বেশি টাকাও নেই। যাওয়া কি উচিত? তোমার কথা জানিনা, আমি এ অবস্থায় পরপর কিছু কথা ভেবে তারপর সিদ্ধান্ত নিতাম। একা গিয়ে কোথাও মজা নেই। তাই বন্ধুরা না গেলে এককথায় যাবো না (ওদের ওপর অভিমান করাটা যদিও এক্ষেত্রে জন্মগত অধিকার)। বৃষ্টি পড়লে ফেরাটা মাটি হবে, যানবাহন পেতে বেজায় মুশকিল, অতএব যাওয়ার মানে নেই। টাকা? সে, যদি বন্ধুরা যায়, ব্যবস্থা হয়ে যাবে। মাসের শেষ, নাহয় পরের মাসের শুরুতেই শোধ দিয়ে দেওয়া যাবে’খন। এই অবস্থায়, দেখো দেখি, নিচের ছবি থেকে আমার সিদ্ধান্তগুলো পরিষ্কার হচ্ছে কিনা? ইচ্ছেমতো এক একবার ‘Friends’, ‘Money’ আর ‘Rain’ – এই optionগুলোর নানা combination টিক দিয়ে দেখো তো, আমার মনের অবস্থার একটা মোটামুটি ধারণা পাওয়া যায় কিনা?
ওই যে গোল্লাটা, ওটা এমন একটা function বোঝাচ্ছে, যেটা তিনরকমের আলাদা binary input থেকে একটাই binary output তৈরি করছে। Binary, কারণ প্রশ্ন বা উত্তর মাত্র দু’রকমের হতে পারে এক্ষেত্রে – হয় আমি যাবো, নয়, যাবো না; বৃষ্টি হয় হবে, নয় হবে না। ব্যস্। তৈরি হয়ে গেলো একটা Perceptron। আগের পোস্টে জেনেছিলাম না, 1960 এর কাছাকাছি Perceptron বলে একধরনের জিনিস তৈরি হয়েছিলো, যারা আজকের artificial neuronদের পূর্বসূরী? উপরের ওই গোল্লাটা তা-ই।
অন্য কথা:
1960 সালের মাঝামাঝি computer science এর নানা conference এ কাঁচা পিএইচডি পড়ুয়ারা হাঁ করে দেখতো এক অদ্ভুত দৃশ্য। একই স্কুলের দুই ছাত্র, একজন আরেকজনের থেকে এক ক্লাস সিনিয়র, প্রবল তর্কে লিপ্ত। একজনের বক্তব্য, তাঁর তৈরি করা কম্পিউটার মডেলের পক্ষে একসময় ছবি দেখা বোঝা সম্ভব হবে ছবিটা কিসের। অন্যজন একই উৎসাহে প্রমাণ করার চেষ্টা করতেন, যে কেন এই মডেলের পক্ষে তেমন কিছুই করা সম্ভব না। কারুর কথাই ফেলনা নয়। 1958এ প্রথম জনের তৈরি কম্পিউটার নিয়ে New York Times খবরের শিরোনাম ছিল: “NEW NAVY DEVICE LEARNS BY DOING: Psychologist Shows Embryo of Computer Designed to Read and Grow Wiser”, New Yorker লিখেছিল: “Indeed, it strikes us as the first serious rival to the human brain ever devised.”
অন্যদিকে, দ্বিতীয় জন 1969 সালে প্রথমজনের সেই আবিষ্কার নিয়ে বই লিখে প্রমাণ করেছিলেন, যে তৎকালীন অবস্থায় মেশিনটির পক্ষে নিদেন একখানা XOR Gate ও বানানো সম্ভব নয়, universal classifier হওয়া তো দূর অস্ত। প্রথমজনের নাম Frank Rosenblatt, আর তাঁর বানানো মেশিনের নাম Perceptron। দ্বিতীয়জন Marvin Minsky (ভদ্রলোকের নাম এই নিয়ে তৃতীয়বার উচ্চারিত হলো এই ব্লগে, নেহাত ফেলনা লোক নন; প্রসঙ্গতঃ, উল্লিখিত বইটার নামও “Perceptrons”। বইটার প্রকাশের পরেই নিশ্চিতভাবে সমসাময়িক AI researchএর মৃত্যুঘন্টা বেজেছিলো।)। জগৎ প্রথমজনের প্রতি বিশেষ প্রসন্ন ছিলো না। Rosenblatt এর শেষ জীবন কেটেছিলো এক ইঁদুরের মগজ অন্য ইঁদুরের করোটিতে চালান করে। অন্যদিকে, বইটার প্রকাশের পরের বছর Minsky পান A.M. Turing Award – computing এর সেরা পুরষ্কার।
গলতি Rosenblatt এর ধারণায় ছিলো না, ছিলো Perceptronএর single layer ব্যবহারে, আর Minsky ও মোটেই দাবী করেননি যে multi-layer Perceptronএর পক্ষেও কিছু করা সম্ভব না। কিন্তু জনমানসে যে ধারণা একবার তৈরি হয়, তাকে ভাঙে কে? যাই হোক, ইতিহাসের খেলা বেজায় গোলমেলে; আজ যে তুমি এই ব্লগে এসে Perceptron নিয়ে পড়ছো, এতেই Rosenblatt এর ভূতের আনন্দে আইসক্রিম খেতে যাওয়া উচিত। এই দু’জনের লড়াই নিয়ে নানা রকম লেখার একটা collection তৈরি করে রাখা আছে এখানে।
Source |
অন্যদিকে, দ্বিতীয় জন 1969 সালে প্রথমজনের সেই আবিষ্কার নিয়ে বই লিখে প্রমাণ করেছিলেন, যে তৎকালীন অবস্থায় মেশিনটির পক্ষে নিদেন একখানা XOR Gate ও বানানো সম্ভব নয়, universal classifier হওয়া তো দূর অস্ত। প্রথমজনের নাম Frank Rosenblatt, আর তাঁর বানানো মেশিনের নাম Perceptron। দ্বিতীয়জন Marvin Minsky (ভদ্রলোকের নাম এই নিয়ে তৃতীয়বার উচ্চারিত হলো এই ব্লগে, নেহাত ফেলনা লোক নন; প্রসঙ্গতঃ, উল্লিখিত বইটার নামও “Perceptrons”। বইটার প্রকাশের পরেই নিশ্চিতভাবে সমসাময়িক AI researchএর মৃত্যুঘন্টা বেজেছিলো।)। জগৎ প্রথমজনের প্রতি বিশেষ প্রসন্ন ছিলো না। Rosenblatt এর শেষ জীবন কেটেছিলো এক ইঁদুরের মগজ অন্য ইঁদুরের করোটিতে চালান করে। অন্যদিকে, বইটার প্রকাশের পরের বছর Minsky পান A.M. Turing Award – computing এর সেরা পুরষ্কার।
গলতি Rosenblatt এর ধারণায় ছিলো না, ছিলো Perceptronএর single layer ব্যবহারে, আর Minsky ও মোটেই দাবী করেননি যে multi-layer Perceptronএর পক্ষেও কিছু করা সম্ভব না। কিন্তু জনমানসে যে ধারণা একবার তৈরি হয়, তাকে ভাঙে কে? যাই হোক, ইতিহাসের খেলা বেজায় গোলমেলে; আজ যে তুমি এই ব্লগে এসে Perceptron নিয়ে পড়ছো, এতেই Rosenblatt এর ভূতের আনন্দে আইসক্রিম খেতে যাওয়া উচিত। এই দু’জনের লড়াই নিয়ে নানা রকম লেখার একটা collection তৈরি করে রাখা আছে এখানে।
কি করে কাজ করে এই Perceptron? ওই তিনধরনের inputকে ধরা যাক বললাম \( x_1,~x_2,~x_3 \)। সমস্যা অনুযায়ী input এর চেয়ে বেশি বা কম হতেই পারে। এবার, কোনভাবে এই inputগুলোর গুরুত্বটা numerically প্রকাশ করতে হবে। Rosenblatt করলেন কি, প্রতি inputএর জন্যে একখানা করে সংখ্যা বসালেন, যাদের বলা হলো সেই inputএর weight। উপরের উদাহরণে দেখো, প্রতিটা inputএর জন্যে একখানা করে slider দেওয়া আছে, যাদের নড়ালে-চড়ালে output কখনো কখনো বদলে যায় (‘Weights & Bias’ লেখাটায় ক্লিক করলে ওগুলো দেখা যাবে)। এগুলো, সঙ্গের inputএর weight। উপরের উদাহরণে ওগুলো 1 থেকে 5 অবধি হতে পারে। যে inputএর weight যত বেশি, সিদ্ধান্ত নেওয়ার সময় তার গুরুত্ব ততটাই। এখন, আমাদের input যেহেতু binary, তাই 0 বা 1 হতে পারে। যেমন, ‘Friends?’ এর উত্তর 1 মানে বন্ধুরা সঙ্গে যাবে, 0 মানে যাবে না (‘Rain?’ এর উত্তর হ্যাঁ মানে কিন্তু input 0, কারণ বৃষ্টি হলে বেরবো না)। ‘Show Numbers’ checkboxটায় ক্লিক করে দেখো, নানা combination এর জন্যে outputও নানা রকমের।
Rosenblatt এর রেসিপি মেনে, আমরা inputগুলোর weighted sum বানিয়েছি। অর্থাৎ, weightগুলো যদি \( w_1,~w_2,~w_3 \) হয়, তবে আমরা বানিয়েছি \( \sum_j w_j x_j \), মানে, আমাদের উদাহরণে, \( w_1 x_1 + w_2 x_2 + w_3 x_3 \)। আমার নিজের উদাহরণে কি কি weight ব্যবহার করছি, সেটা প্রতি slider এর ডানদিকের ‘+’ বাটনে ক্লিক করলেই দেখতে পাবে। এবার, আমার লক্ষ্য, outputকেও binary বানানো। আমার নেওয়া weight এর combination টার জন্যে আমি দেখেছি, বিভিন্ন inputএর বিভিন্ন combination এ আমার \( \sum_j w_j x_j \) 5 এর আশেপাশে ঘোরাফেরা করে। এই 5 কে যদি আমরা একটা threshold বলে চিহ্নিত করি, তবে এর চেয়ে কম বা বেশিকে 0 বা 1 বলাই যায়। বেশ, ‘জয়ত্তারা!’ বলে ঘোষণা করা যাক, যে আমাদের output হবে এই রকম:
\[ \text{output} = \begin{cases} 0 & \sum_j w_j x_j \leq \text{threshold} \\ 1 & \sum_j w_j x_j > \text{threshold} \\ \end{cases} \]
অথবা,
\[ \text{output} = \begin{cases} 0 & \sum_j w_j x_j + \text{bias} \leq 0 \\ 1 & \sum_j w_j x_j + \text{bias} > 0 \\ \end{cases} \]
যেখানে \( \text{bias} = - \text{threshold} \)। যদি weight আর input গুলোকে vector হিসেবে ভাবি, তবে \( \sum_j w_j x_j \) বারবার না লিখে \( \vec{w} \cdot \vec{x} \) লেখাই যায়। তবে আমাদের Perceptron হয়ে দাঁড়ালো,
\[ \text{output} = \begin{cases} 0 & \vec{w} \cdot \vec{x} + b \leq 0 \\ 1 & \vec{w} \cdot \vec{x} + b > 0 \\ \end{cases} \]
পরিষ্কার বোঝা যাচ্ছে, আমাদের Perceptronএর output, আসলে একটা step function। Mathematicaয় এটা লেখা হয় HeavisideTheta[z] দিয়ে। ব্যস্। এতক্ষণ যে sliderটার কথা বেমালুম চেপে রেখেছিলাম, এইবার তাকে দরকার। ‘Bias’ এর sliderটা নিয়ে খেলাধুলো করলে পরিষ্কার দেখতে পাবে, \( \vec{w} \) আর \( b \) এর নানা combination দিয়ে শুধু যে কোন একজনের সিদ্ধান্ত নেওয়ার modelই নয়, এই সমস্যায় থাকা যে কোন লোকের সিদ্ধান্তে পৌঁছনো সম্ভব। আমার উদাহরণে বন্ধুরা থাকলেই output \( > 0 \) হবে। চেষ্টা করে দেখো তো, এমন কোন \( \vec{w} \) আর \( b \) এর কম্বিনেশন পাও কিনা, যার ফলে শুধু ‘Money’ 1 হলেই output \( > 0 \) হবে, কিন্তু ‘Rain?’ উত্তর ‘Yes’ হলে output \( \leq 0 \) হবে সবসময়?
দু’একটা জিনিস ঝালিয়ে নিয়ে এগোনো যাক। আমরা দেখেছি, Perceptronএর ক্ষেত্রে weights আর bias অল্প বদলালেই output বদলে যেতে পারে। \( \vec{w} \) আর \( b \) এর value সামান্য বদলে দিলে (ধরো এই বদলের পরিমাণ \( \Delta \vec{w} \) আর \( \Delta b \)) যদি উত্তর দুম করে পুরো outputটাকে উলটে দেয় (মানে ধরো 0 র জায়গায় 1), তবে সেটা বাকি networkকে প্রভাবিত করবে, আর সেটা learningএর পক্ষে খুব খারাপ ব্যাপার। একটা network learning তখনই সম্ভব, যদি weights আর bias এর \( \Delta \vec{w} \) আর \( \Delta b \) পরিবর্তনের ফলে outputএরও \( \Delta \)output পরিবর্তন হয়। তা যদি সত্যি হয়, তবে Perceptronদের learning যে কি করে সম্ভব, এটা বোঝা কঠিন হয়ে দাঁড়াচ্ছে।
Perceptronএর গুরুত্ব আর খামতি (আর তার সমাধানের ইতিহাস, পদ্ধতি, আর অঙ্ক) নিয়ে একটা গোটা পোস্ট লিখে ফেলা যায়। পরে সময় হ’লে ভাবা যাবে, কিন্তু আজ আমরা আরেকটু এগিয়ে জানবো Artificial Neuron (AN) দের কথা। AN রা একেবারেই Perceptron এর মতো, একই রকম \( \vec{w} \) আর \( b \) নিয়ে তৈরি, শুধু একটাই পার্থক্য: input, 0 আর 1 এর বদলে যে কোন real number হতে পারে। তাহলে output? সেটা হবে \( f_a\left( \vec{w} \cdot \vec{x} + b \right) \), এখানে \( f_a \) হলো Activation Function (AF)। এর কাজ কি? সেটা বোঝার জন্যে একটা বিশেষ AF এর উদাহরণ নিয়ে দেখা যাক। ধরা যাক, \( f_a = \sigma \), যেখানে \( \sigma \) হলো একটা Sigmoid Function:
\[ \sigma(z) = \frac{ 1 }{ 1+ e^{-z} } \]
Mathematicaয় এই function টা লেখা হয় LogisticSigmoid[z] দিয়ে। এই ধরনের AN কে আমরা বলবো Sigmoid Neuron (SN)। কেন এইধরনের AF এর ব্যবহার? এর কারণ বোঝার জন্যে \( \sigma \)র সঙ্গে একটা step function এর পার্থক্য আর মিলটা বুঝতে হবে। সঙ্গের ছবিটা দেখলে আশা করি বোঝা যাচ্ছে, \( \sigma(z) \) যেন একটা নরম প্রকৃতির step function, যার ফলে, \( z = \vec{w} \cdot \vec{x} + b \) এর বেশ বড়ো অথবা ছোট valueর জন্যে \( e^{-(+)|z|} \approx 0~(\infty) \), আর তার ফলে, \( \sigma(z) \approx 1~(0) \Rightarrow \theta(z) \)। তার মানে, \( |z| \)এর একটা মোটামুটি বড় valueর জন্যে SN আর Perceptron এর মধ্যে বিশেষ কোন ফারাক নেই। যা কিছু পার্থক্য, তা হলো ওই মাঝের ছোট \( |z| \)এর জন্যে। SN এর এই নরম স্বভাবের কারণে weight আর bias এর ছোট্ট বদল (\( \Delta w_j \) আর \( \Delta b \)) হলে outputএর ও একটা ছোট্ট বদল (\( \Delta \)output) হবে। Calculus আমাদের এক্ষেত্রে জানায়,
\[ \Delta\text{output} \approx \sum_j \frac{\partial\text{output}}{\partial w_j} \Delta w_j + \frac{\partial\text{output}}{\partial b} \Delta b \,, \]
যেখানে \( \partial\text{output} / \partial x \) হলো \( x \) এর সাপেক্ষে outputএর partial derivative। কিন্তু এসবের ফলে, output তো আর binary থাকলো না, 0 থেকে 1 এর মধ্যে একটা real number হয়ে গেলো। এটা অনেকক্ষেত্রে সুবিধেজনক হলেও, যখন আমাদের একটা binary output দরকার, তখন আমরা কি করবো? সেক্ষেত্রে একটা সহজ উপায় হলো, 0 থেকে 1 এর মধ্যে আবার একটা threshold ঠিক করা (সাধারণত 0.5 ধরা হয়), যার থেকে বেশি হলে outputকে আমরা 1 ধরবো, কম হলে 0। নীচের উদাহরণে খেলাধুলো করে দেখো, আমাদের আগের perceptronটাকে SN বানালে ঠিক কি রকম পরিবর্তন হয়।
আজকের পোস্টে যত interactive উদাহরণ আর যে যে ধরনের function ব্যবহার করা হয়েছে, তার code, নীচের লিঙ্ক থেকে download করা notebookএ পাওয়া যাবে। নেড়ে-ঘেঁটে দেখো, যদি বুঝতে অসুবিধে হয়, উপরের ‘যোগাযোগ (Contact)’ পাতায় লেখো, সময়-সুযোগ পেলে অবশ্যই উত্তর দেওয়ার চেষ্টা করবো। আজ এই পর্যন্তই থাক, পরের দিন আমরা জানবো, কি করে এই Artificial Neuron দের দিয়ে একটা network বানিয়ে তারপর তাদের train করা যায়।
No comments