Chapter 10 of 18
The downhill walk that turns loss into learning
আগের চ্যাপ্টার প্রতিষ্ঠা করেছিল যে একটা loss function মডেলের প্রেডিকশনকে একটা মাত্র সংখ্যায় পরিণত করে যা এটা কতটা ভুল ছিল তা মাপে। ট্রেনিং মানে সেই সংখ্যাটা ছোট করতে weight অ্যাডজাস্ট করা — কিন্তু প্রতিটা weight কীভাবে বদলাবে? বাড়াবেন? কমাবেন? কতটা? একটা gradient হলো গাণিতিক টুল যা ঠিক এই প্রশ্নের উত্তর দেয়।
একটা gradient একটা নির্দিষ্ট বিন্দুতে একটা ফাংশন সম্পর্কে দুইটা জিনিস বলে: কোন দিকে গেলে ফাংশনটা সবচেয়ে দ্রুত বাড়ে, আর সেই বৃদ্ধিটা কতটা খাড়া। একটা মাত্র ভেরিয়েবলের ফাংশনের জন্য, gradient হলো ক্যালকুলাসের সেই পরিচিত derivative — সেই বিন্দুতে ফাংশনের কার্ভের ঢাল।
এই এক্সপ্রেশনটা পড়া হয় "loss -এর পরিবর্তনের হার weight -এর সাপেক্ষে।" যদি পজিটিভ হয়, সামান্য বাড়ালে loss বাড়বে — খারাপ খবর, কারণ লক্ষ্য loss কমানো। যদি নেগেটিভ হয়, বাড়ালে loss কমবে — ঠিক যা ট্রেনিং চায়।
আসল নিউরাল নেটওয়ার্কে অনেক weight আর bias থাকে, শুধু একটা না, তাই gradient সাধারণীকরণ হয়ে একটা ভেক্টর-এ পরিণত হয় — পার্শিয়াল ডেরিভেটিভের একটা লিস্ট, মডেলের প্রতিটা প্যারামিটারের জন্য একটা করে:
এই ভেক্টরের প্রতিটা এন্ট্রি একটা নির্দিষ্ট weight-এর জন্য একই প্রশ্নের উত্তর দেয়: "যদি শুধু এই weight-টা সামান্য উপরে ঠেলি, বাকি সবকিছু ফিক্সড রেখে, loss কি বাড়ে না কমে, আর কতটা দ্রুত?" একসাথে মিলিয়ে, এই ভেক্টরটা সেই ঠিক দিকে নির্দেশ করে যা loss-কে সবচেয়ে দ্রুত বাড়াবে, একসাথে প্রতিটা প্যারামিটার বিবেচনা করে।
একটা gradient হলো ঢালের একটা ভেক্টর — প্রতিটা প্যারামিটারের একটা করে — যা একটা ফাংশনের সবচেয়ে খাড়া বৃদ্ধির দিকে নির্দেশ করে, একটা ম্যাগনিটিউড সহ যা সেই বৃদ্ধি কতটা খাড়া তা প্রতিফলিত করে।
একটা মাত্র weight-এর জন্য: একটা পজিটিভ gradient মানে "এই weight বাড়লে loss বাড়ে" — তাই loss কমাতে, সেই weight-টা কমানো উচিত। একটা নেগেটিভ gradient এর উল্টো মানে — weight-টা বাড়ানো উচিত loss কমাতে। Gradient সবসময় বেশি loss-এর দিকে নির্দেশ করে; ট্রেনিং ইচ্ছাকৃতভাবে বিপরীত দিকে যায়।
সূত্র বাদ দিয়ে, একটা gradient বোঝার সবচেয়ে পরিষ্কার উপায় হলো একটা ল্যান্ডস্কেপ কল্পনা করা। Loss function-কে পাহাড়ি ভূখণ্ড হিসেবে কল্পনা করুন, যেখানে যেকোনো বিন্দুর উচ্চতা সেই নির্দিষ্ট weight মানের কম্বিনেশনের জন্য loss কতটা বড় তা প্রতিনিধিত্ব করে। একটা মডেল ট্রেন করা ঠিক সেই ভূখণ্ডের কোথাও দাঁড়িয়ে সবচেয়ে নিচু বিন্দু — সবচেয়ে কম loss-এর বিন্দু — পর্যন্ত হাঁটার চেষ্টা করার মতো।
এবার কল্পনা করুন সেই পাহাড়ের ঢালে একটা নির্দিষ্ট জায়গায় দাঁড়িয়ে, চোখ বাঁধা, পায়ের নিচে মাটি অনুভব করছেন। আপনি পুরো ভূখণ্ড দেখতে পাচ্ছেন না, কিন্তু আপনি অনুভব করতে পারেন ঠিক যেখানে দাঁড়িয়ে আছেন সেখানে কোন দিকটা উপরের দিকে আর কোন দিকটা নিচের দিকে। "কোন দিকটা উপরে" এই স্থানীয়, অনুভব করা বোধটাই ঠিক একটা gradient যা ধরে ফেলে — এটা আপনাকে বলে না পুরো ল্যান্ডস্কেপের সবচেয়ে নিচু বিন্দু কোথায়, শুধু বলে আপনি এখন যেখানে দাঁড়িয়ে সেখান থেকে কোন দিকটা সবচেয়ে খাড়া।
Loss ল্যান্ডস্কেপের যেকোনো বিন্দুতে, gradient সরাসরি উপরের দিকে নির্দেশ করে — বেশি loss-এর দিকে — আর এর দৈর্ঘ্য প্রতিফলিত করে সেখানে ঢালটা কতটা খাড়া। একটা বড় gradient ম্যাগনিটিউড মানে আপনি একটা খাড়া ঢালে আছেন; একটা ছোট মানে মাটিটা প্রায় সমতল।
Gradient-এর এই শুধু-স্থানীয় প্রকৃতিটা প্রচণ্ড গুরুত্বপূর্ণ। একটা পাহাড়ের ঢালে দাঁড়িয়ে, আপনার কোনো উপায় নেই জানার ল্যান্ডস্কেপের অন্য কোথাও একটা অনেক গভীর উপত্যকা আছে কিনা — আপনি শুধু নিজের পায়ের ঠিক নিচের ঢালটা অনুভব করতে পারেন, আর সেটার উপর ভিত্তি করে পরের পদক্ষেপ ঠিক করতে পারেন।
কল্পনা করুন loss একটা মাত্র weight-এর ফাংশন হিসেবে, দুইটা আলাদা গভীরতার উপত্যকার মতো আকৃতি নিয়ে, মাঝে একটা পাহাড় নিয়ে। কম গভীর উপত্যকার ঢালে আংশিক উঠে দাঁড়িয়ে, gradient শুধু আপনাকে বলে "নিচের দিকটা এই দিকে, ঠিক এখানে" — এর কোনো উপায় নেই আপনাকে বলার যে পাহাড়ের অন্যপাশে আরও গভীর উপত্যকা আছে। এটাই ঠিক কেন gradient স্থানীয় চলাচল নির্দেশ করে, গ্লোবাল সেরা উত্তরের একটা নিশ্চিত পথ না — একটা থিম যা এই চ্যাপ্টার পরে আবার ফিরে আসবে।
একবার যেকোনো বিন্দুতে gradient হিসাব করতে পারলে, loss কমানোর একটা অ্যালগরিদম প্রায় স্পষ্ট হয়ে যায়: বারবার gradient-এর বিপরীত দিকে একটা ছোট পদক্ষেপ নিন, কারণ gradient উপরের দিকে নির্দেশ করে আর আপনি নিচে যেতে চান। এটাই ঠিক যা gradient descent করে।
এখানে হলো weight-এর বর্তমান মান, হলো সেই weight-এর সাপেক্ষে loss-এর gradient, আর (গ্রিক অক্ষর eta) হলো learning rate — একটা ছোট পজিটিভ সংখ্যা, যেমনটা Parameters vs Hyperparameters চ্যাপ্টারে দেখা হয়েছে, যা প্রতিটা পদক্ষেপ কতটা বড় তা নিয়ন্ত্রণ করে। মাইনাস সাইনটাই পুরো কৌশল: যেহেতু gradient loss বাড়ার দিকে নির্দেশ করে, এটা বিয়োগ করলে weight loss কমার দিকে সরে যায়।
এই একটা মাত্র আপডেট নিয়ম নেটওয়ার্কের প্রতিটা weight আর bias-এ একসাথে প্রয়োগ হয় — পুরো gradient ভেক্টর হিসাব হয়, তারপর প্রতিটা প্যারামিটার নিজের সংশ্লিষ্ট gradient এন্ট্রির বিপরীতে একটা ছোট পদক্ষেপ নেয়, একসাথে। এই আপডেট বারবার পুনরাবৃত্তি করুন, প্রতিটা নতুন অবস্থানে হিসাব করা নতুন gradient ব্যবহার করে, আর weight-গুলো ধীরে ধীরে কম loss-এর একটা অঞ্চলের দিকে নিচের দিকে হাঁটে।
Learning rate খুব বড় হলে, প্রতিটা পদক্ষেপ ওভারশুট করে — weight-গুলো একটা উপত্যকায় থিতু হওয়ার বদলে loss ল্যান্ডস্কেপ জুড়ে বন্যভাবে লাফিয়ে বেড়ায়, কখনো কখনো loss ভালো হওয়ার বদলে খারাপ হয়ে যায়। Learning rate খুব ছোট হলে, ট্রেনিং এত ধীরে এগোয় যে একটা যুক্তিসঙ্গত সংখ্যক ধাপে প্রায় কোনো উন্নতিই হয় না। ভালোভাবে বেছে নেওয়া একটা মডেল ট্রেন করার সবচেয়ে গুরুত্বপূর্ণ সিদ্ধান্তগুলোর একটা।
Gradient descent হলো একটা ইটারেটিভ অ্যালগরিদম যা বারবার প্রতিটা প্যারামিটারকে এর gradient-এর বিপরীত দিকে একটা ছোট পদক্ষেপ ঠেলে দেয়, ধীরে ধীরে loss কমিয়ে।
উপরের সূত্রে একটা গুরুত্বপূর্ণ বিস্তারিত লুকিয়ে আছে: ঠিকমতো হিসাব করতে জানা দরকার loss কীভাবে বদলায় এই নির্দিষ্ট weight বদলালে — যার মানে প্রথমে কিছু ট্রেনিং উদাহরণের সেটে loss হিসাব করা। প্রতিটা ধাপের আগে সেই gradient হিসাব করতে ঠিক কোন উদাহরণগুলো ব্যবহার হয়, সেটাই সেই একটা ডিজাইন সিদ্ধান্ত যা gradient descent-কে তিনটা আলাদা ভ্যারিয়েন্টে ভাগ করে, যা এরপর দেখানো হবে।
Gradient descent-এর সবচেয়ে আক্ষরিক ভার্সন পুরো ট্রেনিং ডেটাসেট ব্যবহার করে gradient হিসাব করে একটা মাত্র পদক্ষেপ নেওয়ার আগেই। একে বলা হয় batch gradient descent (কখনো কখনো "full-batch" gradient descent, এই চ্যাপ্টারের পরের দিকে দেখানো "mini-batch" ভ্যারিয়েন্টের সাথে বিভ্রান্তি এড়াতে)।
কনক্রিটভাবে: প্রতিটা ট্রেনিং উদাহরণ মডেলের মধ্য দিয়ে চালান, প্রতিটার loss হিসাব করুন, এদের গড় করে একটা সামগ্রিক loss মানে নিয়ে আসুন, সেই গড় loss-এর প্রতিটা weight-এর সাপেক্ষে gradient হিসাব করুন, আর তারপরই একটা মাত্র আপডেট পদক্ষেপ নিন। তারপর পুরো প্রক্রিয়াটা পুনরাবৃত্তি করুন — পরের ধাপের জন্য আবার সব ডেটা চালান।
শক্তি: একটা স্থিতিশীল, সঠিক দিক
যেহেতু gradient পুরো ডেটাসেট থেকে হিসাব করা, এটা কোন দিকটা আসলেই সামগ্রিক loss কমায় তার সবচেয়ে সঠিক সম্ভাব্য অনুমান। প্রতিটা পদক্ষেপ নির্ভরযোগ্যভাবে একটা যুক্তিসঙ্গত দিকে এগোয়, কোনো নয়েজি জিগজ্যাগ ছাড়াই।
দুর্বলতা: প্রতিটা পদক্ষেপে অত্যন্ত ধীর
প্রতিটা আপডেটের জন্য পুরো ডেটাসেটের মধ্য দিয়ে একটা সম্পূর্ণ পাস লাগে। লক্ষ লক্ষ উদাহরণসহ ডেটাসেটের জন্য, এর মানে weight একবার অ্যাডজাস্ট করার আগেই লক্ষ লক্ষ forward pass-এর জন্য অপেক্ষা করা।
দুর্বলতা: ভারী মেমরি চাহিদা
ইমপ্লিমেন্টেশনের উপর নির্ভর করে, একসাথে পুরো ডেটাসেট জুড়ে loss আর gradient হিসাব করতে একসাথে অনেক বেশি ডেটা আর ইন্টারমিডিয়েট মান মেমরিতে রাখা লাগতে পারে।
Batch gradient descent ছোট ডেটাসেটের জন্য ভালোই কাজ করে, যেখানে একটা সম্পূর্ণ পাস সস্তা। কিন্তু আসল deep learning প্রবলেমের সাধারণ বড় ডেটাসেটের জন্য — কখনো কখনো লক্ষ লক্ষ বা কোটি কোটি উদাহরণ — প্রতিটা ছোট পদক্ষেপের আগে একটা সম্পূর্ণ পাসের জন্য অপেক্ষা করা ট্রেনিংকে অবাস্তবভাবে ধীর করে দেয়। এটাই ঠিক সেই সমস্যা যা বাকি দুইটা ভ্যারিয়েন্ট সমাধান করে।
পুরো ডেটাসেট বা একটা মাত্র উদাহরণ ব্যবহার করার বদলে, mini-batch gradient descent প্রতিটা আপডেট পদক্ষেপের আগে ট্রেনিং ডেটার একটা ছোট, র্যান্ডমলি বেছে নেওয়া সাবসেট — একটা "mini-batch" — ব্যবহার করে gradient হিসাব করে। সাধারণ mini-batch সাইজ হলো ২-এর ঘাত, যেমন ৩২, ৬৪, বা ২৫৬ উদাহরণ, যদিও ঠিক সংখ্যাটা নিজেই একটা বেছে নেওয়ার মতো hyperparameter।
সামগ্রিক ট্রেনিং প্রক্রিয়াটা দেখতে এরকম: পুরো ডেটাসেট শাফল করুন, এটাকে ধারাবাহিক mini-batch-এ ভাগ করুন, পালাক্রমে প্রতিটা mini-batch ব্যবহার করে একটা আপডেট পদক্ষেপ চালান, আর একবার প্রতিটা mini-batch ব্যবহার হয়ে গেলে, সেটাকে একটা epoch বলুন আর একটা নতুন শাফল দিয়ে পুনরাবৃত্তি করুন। ডেটার মধ্য দিয়ে একটা সম্পূর্ণ পাসে একটা আপডেটের বদলে (batch gradient descent-এর মতো), mini-batch gradient descent প্রতি epoch-এ অনেকগুলো আপডেট পায় — প্রতিটা mini-batch-এর জন্য একটা করে।
Mini-batch gradient descent প্রতিটা ধাপে ট্রেনিং ডেটার একটা ছোট র্যান্ডম সাবসেট থেকে gradient হিসাব করে, সব ডেটা ব্যবহার করার স্থিতিশীলতা আর শুধু একটা উদাহরণ ব্যবহার করার গতির মধ্যে একটা ভারসাম্য তৈরি করে।
এই পদ্ধতি দুই চরমের বেশিরভাগ ব্যবহারিক সুবিধা ধরে রাখে: mini-batch যথেষ্ট বড় যে gradient অনুমানটা মোটামুটি স্থিতিশীল (বন্যভাবে নয়েজি না), তবুও যথেষ্ট ছোট যে প্রতি epoch-এ অনেক আপডেট হয়, আর যথেষ্ট ছোট যে মেমরিতে আরামে ফিট হয়, বিশেষ করে ডেটার ব্যাচ একসাথে সমান্তরালে প্রসেস করার জন্য ডিজাইন করা GPU-তে। এই কারণেই mini-batch gradient descent, অনেকটাই, আসল deep learning প্র্যাকটিসে সবচেয়ে বেশি ব্যবহৃত ভ্যারিয়েন্ট।
বড় mini-batch মসৃণ, বেশি স্থিতিশীল gradient অনুমান দেয় কিন্তু বেশি মেমরি লাগে আর প্রতি epoch-এ কম আপডেট হয়। ছোট mini-batch বেশি ঘন ঘন আপডেট হয় আর প্রায়ই সামান্য ভালো generalize করে, কিন্তু এদের gradient অনুমান বেশি নয়েজি। বাস্তবে, টিমগুলো সাধারণত তাদের হার্ডওয়্যারের মেমরি আরামে যতটা সামলাতে পারে ততটা বড় mini-batch সাইজ বেছে নেয়, তারপর ফলাফলের উপর ভিত্তি করে সেখান থেকে অ্যাডজাস্ট করে।
Mini-batch আইডিয়াটাকে চরমে ঠেলে দিন, আর mini-batch সাইজ পুরোপুরি একটা মাত্র উদাহরণে নেমে আসে। এটাই stochastic gradient descent (SGD) — gradient হিসাব করা, আর একটা আপডেট পদক্ষেপ নেওয়া, একবারে শুধু একটা র্যান্ডমলি বেছে নেওয়া ট্রেনিং উদাহরণ ব্যবহার করে।
বাস্তবে, অনেকেই "SGD" শব্দটা mini-batch gradient descent-কেও বোঝাতে শিথিলভাবে ব্যবহার করেন, কারণ দুটোই পুরো ডেটাসেটের বদলে একটা সাবসেট ব্যবহার করার একই মূল আইডিয়া শেয়ার করে। কঠোরভাবে বলতে গেলে অবশ্য, "stochastic" gradient descent বলতে এখানে বর্ণনা করা একবারে-একটা-উদাহরণের ভার্সনটাকেই বোঝায়।
যেহেতু প্রতিটা পদক্ষেপের gradient শুধু একটা উদাহরণ থেকে আসে, এটা সামগ্রিক loss কমায় এমন আসল দিকের একটা রুক্ষ, প্রায়ই নয়েজি অনুমান — একটা নির্দিষ্ট ট্রেনিং উদাহরণ হয়তো weight-কে একটু ভুল দিকে নির্দেশ করতে পারে, শুধু সেই উদাহরণের নিজের অদ্ভুততার কারণে। কিন্তু এই নয়েজ নিখুঁতভাবে একটা খারাপ দিক না: ফলাফল স্বরূপ ঝাঁকুনি-দেওয়া, জিগজ্যাগ পথটা আসলে অপ্টিমাইজেশন প্রক্রিয়াকে loss ল্যান্ডস্কেপের ছোট অকার্যকর গর্ত থেকে বের হয়ে আসতে সাহায্য করতে পারে, যেখানে একটা মসৃণ, বেশি "কনফিডেন্ট" পথ আটকে যেতে পারত।
| Batch GD | Mini-Batch GD | Stochastic GD | |
|---|---|---|---|
| প্রতি gradient হিসাবে উদাহরণ | পুরো ডেটাসেট | ছোট সাবসেট (যেমন ৩২–২৫৬) | শুধু ১টা উদাহরণ |
| প্রতি epoch-এ আপডেট | ১ | অনেক (ডেটাসেট সাইজ ÷ batch সাইজ) | প্রতিটা ট্রেনিং উদাহরণে একটা করে |
| Gradient অনুমানের মান | সবচেয়ে সঠিক, সবচেয়ে কম নয়েজি | মোটামুটি সঠিক, মাঝারি নয়েজ | সবচেয়ে কম সঠিক, সবচেয়ে বেশি নয়েজি |
| প্রথম আপডেটের গতি | সবচেয়ে ধীর — সম্পূর্ণ পাসের জন্য অপেক্ষা করে | দ্রুত | সবচেয়ে দ্রুত — তাৎক্ষণিক |
| সাধারণ বাস্তব-জগতের ব্যবহার | বিরল, শুধু ছোট ডেটাসেটে | বাস্তবে স্ট্যান্ডার্ড ডিফল্ট | মাঝে মাঝে, বা একটা কনসেপচুয়াল বেসলাইন হিসেবে |
Stochastic gradient descent একটা র্যান্ডমলি বেছে নেওয়া সিঙ্গেল ট্রেনিং উদাহরণ থেকে হিসাব করা gradient দিয়ে weight আপডেট করে, gradient-এর সঠিকতা বিনিময় করে অত্যন্ত ঘন ঘন, দ্রুত আপডেটের জন্য।
Gradient descent-এর মূল দুর্বলতা সরাসরি Gradient-এর ইনটুইশন সেকশনে প্রতিষ্ঠিত হওয়া বিষয় থেকে আসে: gradient নিখুঁতভাবে স্থানীয়। এটা দুইটা নির্দিষ্ট বিপদ তৈরি করে যেগুলো নাম দিয়ে বোঝার মতো।
একটা local minimum হলো loss ল্যান্ডস্কেপের এমন একটা বিন্দু যা আশেপাশের প্রতিটা বিন্দুর চেয়ে নিচু, কিন্তু অগত্যা সামগ্রিকভাবে সবচেয়ে নিচু বিন্দু না (global minimum)। দুই-উপত্যকার উদাহরণটা আবার কল্পনা করুন: কম গভীর উপত্যকায় দাঁড়িয়ে, gradient সঠিকভাবেই রিপোর্ট করে "আপনি নিচে আছেন, স্থানীয়ভাবে" একবার এর তলায় পৌঁছালে — সেখানে gradient শূন্য, বা প্রায় শূন্যের কাছাকাছি, তাই gradient descent অগ্রগতি করা বন্ধ করে দেয়, যদিও ল্যান্ডস্কেপের অন্য কোথাও একটা অনেক গভীর উপত্যকা থাকতে পারে।
একটা saddle point একটা ভিন্ন ধরনের ফাঁদ: এমন একটা বিন্দু যেখানে ঢালও প্রতিটা দিকে শূন্য (বা প্রায় শূন্য), কিন্তু এটা আদৌ একটা মিনিমাম না — সারফেসটা কিছু দিকে উপরে বাঁকে আর অন্য দিকে নিচে, একটা ঘোড়ার জিন বা দুইটা পাহাড়ের চূড়ার মাঝের একটা গিরিপথের মতো। একটা saddle point-এর কাছে, gradient প্রতিটা দিকেই অত্যন্ত ছোট হয়ে যায়, তাই gradient descent-এর পদক্ষেপ ছোট হয়ে যায় আর অগ্রগতি প্রায় থেমে যেতে পারে, যদিও কাছেই সত্যিকারের কম loss পৌঁছানোযোগ্য।
শুধু একটা বা দুইটা weight-এর একটা ল্যান্ডস্কেপে, local minima কল্পনা করার জন্য বেশি স্বজ্ঞাত বিপদ। কিন্তু আসল নিউরাল নেটওয়ার্কে লক্ষ লক্ষ weight থাকে, আর এমন উচ্চ-মাত্রিক স্পেসে, গবেষণা দেখেছে যে saddle point আসলে সত্যিকারের local minima-র চেয়ে অনেক বেশি সাধারণ বাধা — একটা বিন্দু একসাথে লক্ষ লক্ষ দিকের প্রতিটাতেই একটা মিনিমাম হওয়াটা পরিসংখ্যানগতভাবে এটা কিছু দিকে উপরে আর কিছু দিকে নিচে বাঁকার চেয়ে অনেক কম সম্ভাব্য।
বেশ কয়েকটা ব্যবহারিক টেকনিক gradient descent-কে এদের কোনোটাতে খারাপভাবে আটকে যাওয়া থেকে বের হতে বা এড়াতে সাহায্য করে: mini-batch আর stochastic gradient descent-এ অন্তর্নিহিত নয়েজ নিজেই weight-কে একটা অগভীর ফাঁদ থেকে ঝাঁকিয়ে বের করে দিতে পারে যেখানে full-batch gradient descent হয়তো আরও স্থায়ীভাবে থিতু হতো; আর আরও উন্নত অপ্টিমাইজেশন অ্যালগরিদম, সাধারণ gradient descent-এর উপর ভিত্তি করে, momentum যোগ করে — আগের ধাপ থেকে কিছু "ভেলোসিটি" সামনে বহন করা — বিশেষভাবে সমতল বা সামান্য উপরের দিকের অঞ্চলগুলোর মধ্য দিয়ে ঠেলে যেতে সাহায্য করার জন্য, সম্পূর্ণভাবে থেমে যাওয়ার বদলে।
বাস্তবে, বড়, জটিল নিউরাল নেটওয়ার্কের জন্য, একটা খারাপ local minimum-এ স্থায়ীভাবে আটকে যাওয়া ল্যান্ডস্কেপ রূপকটা যতটা ইঙ্গিত দেয় তার চেয়ে কম সাধারণ — যথেষ্ট weight থাকলে, বাস্তবে পাওয়া বেশিরভাগ local minima loss মানের দিক থেকে global minimum-এর যথেষ্ট কাছাকাছি থাকে যে তখনও একটা সত্যিকারের কার্যকর, ভালো-পারফর্মিং মডেল তৈরি করে।
নিচের ইন্টারেক্টিভ ডেমোটা একটা সহজ বাটি-আকৃতির loss কার্ভ প্লট করে — loss একটা মাত্র weight-এর ফাংশন হিসেবে — আর আপনাকে হাতে হাতে gradient descent-এর মধ্য দিয়ে ধাপে ধাপে যেতে দেয়, নিজেই learning rate বেছে নিয়ে।
একটি লার্নিং রেট বেছে নিন এবং একটি বাটি-আকৃতির লস কার্ভের ওপর গ্রেডিয়েন্ট ডিসেন্টের ধাপগুলো দেখুন। দেখুন কীভাবে একই অন্তর্নিহিত আপডেট নিয়ম এই একটা সংখ্যার উপর নির্ভর করে সম্পূর্ণ ভিন্নভাবে আচরণ করে।
Try stepping through and watch how it behaves.
বিভিন্ন learning rate নিয়ে এক্সপেরিমেন্ট করার সময় কয়েকটা জিনিস খেয়াল করার মতো:
এই সিঙ্গেল-weight বাটিটা ইচ্ছাকৃতভাবে একটা সরলীকৃত প্রতিরূপ একটা সম্পূর্ণ নিউরাল নেটওয়ার্কের আসল loss ল্যান্ডস্কেপের জন্য, যাতে একটার বদলে লক্ষ লক্ষ মাত্রা আছে — কিন্তু এটা যা মূল আচরণ দেখায়, learning rate কীভাবে গতি আর স্থিতিশীলতার মধ্যে ট্রেড-অফ নিয়ন্ত্রণ করে, সেটা যেকোনো স্কেলে ঠিক একইভাবে প্রযোজ্য।