গ্র্যাডিয়েন্ট ডিসেন্ট
এই পাঠে যা শিখবেন
- গ্র্যাডিয়েন্ট ডিসেন্টের আপডেট রুল এবং এটি কেন মিনিমামের দিকে নিয়ে যায়
- লার্নিং রেট কী, এবং এর মান বাছাই কীভাবে কনভারজেন্স বা ডাইভার্জেন্স নির্ধারণ করে
- একটি সত্যিকারের, চলমান ডেমো — কনভার্জিং ও ডাইভার্জিং দুটি রান, উভয়ই সত্যিকারের সংখ্যা দিয়ে
- কেন ব্যবহারিক ML/অপ্টিমাইজেশন সিস্টেমে "ব্লো-আপ গার্ড" প্রয়োজন হয়
১ · গ্র্যাডিয়েন্ট ডিসেন্ট কীভাবে কাজ করে
গ্র্যাডিয়েন্টGradientএকটি বহু-চলক ফাংশনের প্রতিটি চলকের সাপেক্ষে আংশিক ডেরিভেটিভের ভেক্টর — এটি নির্দেশ করে ফাংশনটি সবচেয়ে দ্রুত কোন দিকে বাড়ছে।
একটি ভেক্টর যা নির্দেশ করে ফাংশন f সবচেয়ে দ্রুত কোন দিকে বাড়ছে। তাই
গ্র্যাডিয়েন্টের বিপরীত দিকে ছোট ছোট ধাপে গেলে ফাংশনের মান কমতে থাকে — এটাই গ্র্যাডিয়েন্ট
ডিসেন্টের মূল ধারণা। প্রতিটি চলক x-এর জন্য আপডেট রুল:
$$ x_{n+1} = x_n - \alpha \, \nabla f(x_n) $$
যেখানে α (আলফা) হলো লার্নিং রেট — প্রতি ধাপে কতটা "লাফ" দেওয়া হবে তা
নিয়ন্ত্রণ করে। L42-এর গোল্ডেন সেকশন সার্চের সাথে মূল পার্থক্য: গ্র্যাডিয়েন্ট ডিসেন্ট ফাংশনের ঢাল
(slope) ব্যবহার করে বুদ্ধিদীপ্তভাবে দিক বেছে নেয় (M2-এর নিউটন-রাফসনের মতোই), এবং সরাসরি যেকোনো সংখ্যক
চলকে কাজ করে — তাই এটি মেশিন লার্নিং মডেল ট্রেনিংয়ের (M12/L55-এ বিস্তারিত) মূল ভিত্তি।
নিরাপদ কিন্তু ধীর — মিনিমামের দিকে নির্ভরযোগ্যভাবে এগোয়, তবে কনভার্জ করতে অনেক বেশি ইটারেশন লাগতে পারে।
প্রতি ধাপে এত বড় লাফ দেয় যে মিনিমাম "ওভারশুট" হয়ে যায় — মান দোদুল্যমান (oscillate) হতে হতে বাড়তে থাকে, শেষে ডাইভার্জ করে।
বাস্তব কোডে যদি মান নিয়ন্ত্রণহীনভাবে বাড়তে থাকে, একটি সীমা (threshold) চেক করে থামিয়ে দেওয়া হয় — নয়তো
OverflowError বা অসীম লুপ হতে পারে।২ · ডেমো — কনভার্জিং বনাম ডাইভার্জিং রান
টেস্ট ফাংশন হিসেবে ব্যবহার করছি f(x, y) = (x-3)² + (y+2)² + 5 — একটি সহজ 2D "বাটি"
(bowl) আকৃতির ফাংশন যার প্রকৃত মিনিমাম (x, y) = (3, -2)-এ, যেখানে f = 5।
গ্র্যাডিয়েন্ট: ∇f = (2(x-3), 2(y+2))। শুরুর বিন্দু উভয় রানেই (0, 0)।
import math
def f(x, y):
return (x - 3)**2 + (y + 2)**2 + 5
def grad_f(x, y):
return (2*(x - 3), 2*(y + 2))
def gradient_descent(x0, y0, lr, max_iter, blowup=1e6):
x, y = x0, y0
for i in range(max_iter + 1):
fx = f(x, y)
gx, gy = grad_f(x, y)
gnorm = math.sqrt(gx**2 + gy**2)
print(f"iter {i:3d}: x={x:12.6f} y={y:12.6f} f={fx:14.6f} ||grad||={gnorm:12.6f}")
if abs(x) > blowup or abs(y) > blowup:
print(f"-- মান বিস্ফোরিত (blow up) হয়ে গেছে, ইটারেশন {i}-এ থামানো হলো --")
return None
if gnorm < 1e-6:
print(f"-- কনভার্জ করেছে ইটারেশন {i}-এ --")
return (x, y)
x = x - lr * gx
y = y - lr * gy
return (x, y)
print("=== যুক্তিসঙ্গত লার্নিং রেট (lr = 0.1) ===")
gradient_descent(0.0, 0.0, lr=0.1, max_iter=90)
print()
print("=== অতিরিক্ত বড় লার্নিং রেট (lr = 1.5) ===")
gradient_descent(0.0, 0.0, lr=1.5, max_iter=30, blowup=1e6)
x ≈ 3.000000, y ≈ -2.000000, f ≈ 5.000000 — প্রতি ধাপে গ্র্যাডিয়েন্ট নর্ম একটি স্থির হারে
(০.৮ গুণ, যেহেতু |1 - 2·0.1| = 0.8) কমতে থাকে, একটি পরিষ্কার লিনিয়ার কনভারজেন্স।
lr = 1.5-এ মেথডটি প্রথম ধাপেই ওভারশুট করে (x লাফিয়ে 0 থেকে
9-এ যায়, প্রকৃত মিনিমাম 3-কে পেরিয়ে), এবং প্রতিটি পরবর্তী ধাপে মান দ্বিগুণ হয়ে
চিহ্ন পাল্টে দোদুল্যমান হতে থাকে (|1 - 2·1.5| = 2) — ইটারেশন ১৯-এ
x-এর মান 1,572,867-এ পৌঁছে যায় (থ্রেশহোল্ড 1e6 অতিক্রম করে), এবং
কোড নিজে থেকেই এটি শনাক্ত করে থেমে যায় — সত্যিকারের, পর্যবেক্ষণযোগ্য ডাইভার্জেন্স।
লার্নিং রেট বাছাই গ্র্যাডিয়েন্ট ডিসেন্টের সবচেয়ে গুরুত্বপূর্ণ ব্যবহারিক সিদ্ধান্ত — উপরের এই একই
ফাংশনে lr = 0.1 নির্ভরযোগ্যভাবে কনভার্জ করেছে, কিন্তু lr = 1.5 সম্পূর্ণ
ব্যর্থ হয়েছে। M44-এ আমরা দেখব নিউটনের মেথড কীভাবে ফাংশনের দ্বিতীয় ডেরিভেটিভ (বক্রতা) ব্যবহার করে এই
লার্নিং-রেট-বাছাই সমস্যাটি অনেকাংশে এড়িয়ে যায়, এবং একই ফাংশনে অনেক কম ইটারেশনে কনভার্জ করে।
ভাবনার প্রশ্ন
প্রতিটি প্রশ্ন নিজে কিছুক্ষণ ভাবুন — তারপর "→ উত্তর" চাপুন।
প্র ০১
উপরের ডেমোতে lr = 1.5-এ প্রতিটি ধাপে x ও y-এর চিহ্ন
পাল্টে যাচ্ছে (পজিটিভ থেকে নেগেটিভ, আবার পজিটিভ)। এই "দোদুল্যমান" (oscillating) আচরণটি কেন ঘটছে?
আপডেট রুল x_{n+1} = x_n - α·2(x_n-3)-কে এরর e = x - 3-এর ভাষায় লিখলে
পাওয়া যায় e_{n+1} = (1 - 2α)·e_n। যখন α > 0.5, তখন গুণক
(1 - 2α) ঋণাত্মক হয়ে যায় — তাই প্রতি ধাপে চিহ্ন পাল্টায়। এবং যখন
|1 - 2α| > 1 (অর্থাৎ α > 1), তখন এরর প্রতি ধাপে বড় হতে থাকে —
এটাই দোদুল্যমান ডাইভার্জেন্স।
প্র ০২
যদি lr = 0.5 ঠিক বসানো হতো (উপরের সূত্র e_{n+1} = (1-2α)e_n
অনুযায়ী), তাহলে কী ঘটত বলে আপনার ধারণা?
α = 0.5-এ গুণক (1 - 2·0.5) = 0 হয়ে যায় — অর্থাৎ প্রথম ধাপেই এরর সরাসরি
শূন্য হয়ে যাবে এবং মেথডটি ঠিক এক ধাপে প্রকৃত মিনিমামে পৌঁছাবে! এটি এই নির্দিষ্ট
কোয়াড্রেটিক ফাংশনের একটি বিশেষ কাকতালীয় ঘটনা (কারণ ফাংশনটির বক্রতা ধ্রুবক ২) — বাস্তব, অ-কোয়াড্রেটিক
ফাংশনে এমন নিখুঁত এক-ধাপ কনভারজেন্স সাধারণত ঘটে না।
প্র ০৩ বাস্তব মেশিন লার্নিং ট্রেনিংয়ে একটি একক, স্থির লার্নিং রেট পুরো ট্রেনিং জুড়ে ব্যবহার করার বদলে প্রায়ই "লার্নিং রেট শিডিউল" (ধীরে ধীরে কমানো) ব্যবহার করা হয় — উপরের কনভারজেন্স আচরণ দেখে আপনার কী মনে হয়, কেন এটি সহায়ক হতে পারে?
শুরুতে মিনিমাম থেকে দূরে থাকলে বড় ধাপ দ্রুত অগ্রগতি দেয়, কিন্তু মিনিমামের কাছাকাছি পৌঁছালে সেই একই
বড় ধাপ ওভারশুট ও দোদুল্যমানতা তৈরি করতে পারে (যেমন উপরের lr = 1.5 ডেমোতে দেখা গেছে)।
তাই ধীরে ধীরে লার্নিং রেট কমানো শুরুর গতি এবং শেষের স্থিতিশীলতা — দুটোই ধরে রাখতে সাহায্য করে।
অনুশীলন
-
চিন্তা করুন: উপরের কোড সেলে
lr = 0.1-এর বদলেlr = 0.01ব্যবহার করলে কনভার্জ করতে ইটারেশন সংখ্যা মোটামুটি কত গুণ বাড়বে বলে আপনার ধারণা?এরর প্রতি ধাপে
(1 - 2α)গুণে কমে —α = 0.1-এ গুণক0.8,α = 0.01-এ গুণক0.98। যেহেতু0.98এক-এর অনেক কাছাকাছি, একই টলারেন্সে পৌঁছাতে উল্লেখযোগ্যভাবে বেশি (কয়েক গুণ থেকে দশ গুণের বেশি) ইটারেশন লাগার কথা। -
পরীক্ষা করুন: উপরের কোড সেলে
gradient_descent(0.0, 0.0, lr=0.1, max_iter=90)-কেgradient_descent(0.0, 0.0, lr=0.01, max_iter=900)-এ পরিবর্তন করে Run চেপে আপনার অনুমান যাচাই করুন।lr = 0.01-এ কনভার্জ করতে ৭৮২ ইটারেশন লাগে (lr = 0.1-এর ৭১ ইটারেশনের তুলনায় প্রায় ১১ গুণ বেশি) — যা নিশ্চিত করে ছোট লার্নিং রেট নিরাপদ কিন্তু উল্লেখযোগ্যভাবে ধীর।
আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ
- পরবর্তী পাঠ — অপ্টিমাইজেশনের জন্য নিউটনের মেথড M9 · L44 দ্বিতীয় ডেরিভেটিভ (বক্রতা) ব্যবহার করে গ্র্যাডিয়েন্ট ডিসেন্টের চেয়ে অনেক দ্রুত কনভার্জ করা।
- আগের পাঠ — গোল্ডেন সেকশন সার্চ M9 · L42 ডেরিভেটিভ ছাড়াই 1D মিনিমাম খোঁজা — গ্র্যাডিয়েন্ট ডিসেন্টের সাথে তুলনা করে দেখুন।
- Machine Learning কোর্স সহোদর কোর্স গ্র্যাডিয়েন্ট ডিসেন্ট কীভাবে বাস্তব ML মডেল ট্রেনিংয়ে ব্যবহৃত হয় তার বিস্তারিত — M12/L55-এ এই সংযোগ আরও গভীরভাবে দেখানো হবে।