চেইন রুল দিয়ে ব্যাকপ্রপাগেশন ডেরাইভ করা
এই পাঠে যা শিখবেন
- কম্পিউটেশনাল গ্রাফে মাল্টিভেরিয়েবল চেইন রুল ঠিক কীভাবে কাজ করে
- পাঠ ১৯-এর নেটওয়ার্কের পাঁচটি প্যারামিটারের ($w_1,w_2,b_1,w_3,b_2$) প্রতিটির জন্য $\partial L/\partial \theta$ ধাপে ধাপে ডেরাইভ করা
- ব্যাকওয়ার্ড দিকে "আপস্ট্রিম গ্রেডিয়েন্ট × লোকাল গ্রেডিয়েন্ট" প্যাটার্ন চেনা — এটাই ব্যাকপ্রপাগেশনের সম্পূর্ণ যন্ত্র
- সরাসরি সিম্বলিক ডিফারেনশিয়েশনের সাথে ফলাফল মিলিয়ে sanity check করা
১ · মাল্টিভেরিয়েবল চেইন রুল — পথের উপর সমষ্টি
পাঠ ১৩-তে আমরা এক-ভ্যারিয়েবলের চেইন রুল দেখেছি: $\frac{d}{dx}f(g(x))=f'(g(x))g'(x)$। একটি কম্পিউটেশনাল গ্রাফে (পাঠ ১৯) এই নিয়মের একটি সাধারণীকৃত রূপ লাগে, কারণ একটি ভ্যারিয়েবল একাধিক পথ দিয়ে চূড়ান্ত আউটপুটকে প্রভাবিত করতে পারে। সাধারণ নিয়মটি হলো:
যদি $L$ একটি ভ্যারিয়েবল $\theta$-কে একাধিক পথে (গ্রাফের মধ্য দিয়ে) প্রভাবিত করে, তাহলে $\partial L/\partial \theta$ = প্রতিটি পথে থাকা লোকাল গ্রেডিয়েন্টগুলোর গুণফল, এবং তারপর সব পথের উপর যোগফল।
আমাদের পাঠ ১৯-এর নেটওয়ার্কে সুবিধা হলো — এটি একটি সরল চেইন (কোনো branching নেই), তাই প্রতিটি প্যারামিটার থেকে $L$ পর্যন্ত একটিমাত্র পথ আছে। ফলে "সব পথ যোগ করা" ধাপটি এখানে দরকার পড়ে না — শুধু একটি পথ ধরে লোকাল গ্রেডিয়েন্ট গুণ করে গেলেই চলবে। (একাধিক পথের প্রকৃত উদাহরণ — যেমন একটি ভ্যারিয়েবল দুটি ভিন্ন নিউরনে ব্যবহৃত হলে — আরও জটিল নেটওয়ার্কে দেখা যায়, কিন্তু নীতিটা এখানেই সম্পূর্ণ শেখা যায়।)
২ · ব্যাকওয়ার্ড পাস শুরু — $\partial L/\partial \hat{y}$
আমরা $L$ থেকে শুরু করে পেছন দিকে হাঁটব। পাঠ ১৯-এর গ্রাফ অনুযায়ী $L=(\hat{y}-y)^2$, যেখানে $\hat{y}=w_3h+b_2$। সবচেয়ে বাইরের নোড থেকে শুরু করে, পাওয়ার রুল ও চেইন রুল প্রয়োগ করে:
$$ \frac{\partial L}{\partial \hat{y}} = 2(\hat{y}-y) $$
আমাদের সংখ্যায় ($\hat{y}=1.0$, $y=0.0$, পাঠ ১৯ থেকে): $\partial L/\partial \hat{y} = 2(1.0-0.0) = 2.0$। যেহেতু আউটপুট নিউরন লিনিয়ার ($\hat{y}=z_2$ সরাসরি, কোনো অ্যাক্টিভেশন ছাড়া), তাই $\partial \hat{y}/\partial z_2 = 1$ এবং $\partial L/\partial z_2 = \partial L/\partial \hat{y} = 2.0$ অপরিবর্তিত থাকে।
৩ · আউটপুট নিউরনের ওজন — $\partial L/\partial w_3$ ও $\partial L/\partial b_2$
$z_2 = w_3 h + b_2$ নোডের লোকাল গ্রেডিয়েন্ট:
$$ \frac{\partial z_2}{\partial w_3} = h, \qquad \frac{\partial z_2}{\partial b_2} = 1 $$
চেইন রুল প্রয়োগ করে — "আপস্ট্রিম গ্রেডিয়েন্ট" ($\partial L/\partial z_2 = 2(\hat{y}-y)$) গুণ "লোকাল গ্রেডিয়েন্ট":
$$ \frac{\partial L}{\partial w_3} = \frac{\partial L}{\partial z_2}\cdot\frac{\partial z_2}{\partial w_3} = 2(\hat{y}-y)\cdot h \qquad \frac{\partial L}{\partial b_2} = \frac{\partial L}{\partial z_2}\cdot 1 = 2(\hat{y}-y) $$
সংখ্যায় বসিয়ে ($h=0.5$, $\hat{y}-y=1.0$): $\partial L/\partial w_3 = 2.0 \times 0.5 = 1.0$, এবং $\partial L/\partial b_2 = 2.0 \times 1 = 2.0$।
৪ · হিডেন নিউরনে ফিরে যাওয়া — $\partial L/\partial h$ ও $\partial L/\partial z_1$ (পাঠ ১৮-এর সিগময়েড ডেরিভেটিভ)
এবার $h$ ভ্যারিয়েবলটি নিজেই শুধু $z_2$-এর মধ্য দিয়ে $L$-কে প্রভাবিত করে ($z_2=w_3h+b_2$ থেকে $\partial z_2/\partial h = w_3$), তাই:
$$ \frac{\partial L}{\partial h} = \frac{\partial L}{\partial z_2}\cdot\frac{\partial z_2}{\partial h} = 2(\hat{y}-y)\cdot w_3 = 2.0 \times 2.0 = 4.0 $$
এবার $h=\sigma(z_1)$-এর লোকাল গ্রেডিয়েন্ট লাগবে — পাঠ ১৮-তে ডেরাইভ করা সিগময়েডের ডেরিভেটিভ $\sigma'(z_1) = \sigma(z_1)\big(1-\sigma(z_1)\big) = h(1-h)$ ব্যবহার করে:
$$ \frac{\partial L}{\partial z_1} = \frac{\partial L}{\partial h}\cdot\frac{\partial h}{\partial z_1} = \frac{\partial L}{\partial h}\cdot h(1-h) $$
সংখ্যায়: $h(1-h) = 0.5(1-0.5) = 0.25$। তাই $\partial L/\partial z_1 = 4.0 \times 0.25 = 1.0$।
৫ · ইনপুট ওজন ও বায়াস — $\partial L/\partial w_1$, $\partial L/\partial w_2$, $\partial L/\partial b_1$
সবশেষে $z_1 = w_1x_1+w_2x_2+b_1$ নোডের লোকাল গ্রেডিয়েন্ট (পাঠ ১৯-এ প্রথম দেখা):
$$ \frac{\partial z_1}{\partial w_1}=x_1, \qquad \frac{\partial z_1}{\partial w_2}=x_2, \qquad \frac{\partial z_1}{\partial b_1}=1 $$
চেইন রুল প্রয়োগ করে, আপস্ট্রিম গ্রেডিয়েন্ট $\partial L/\partial z_1 = 1.0$ (উপর থেকে) গুণ প্রতিটি লোকাল গ্রেডিয়েন্ট:
$$ \frac{\partial L}{\partial w_1} = \frac{\partial L}{\partial z_1}\cdot x_1 = 1.0\times 1.0 = 1.0 $$
$$ \frac{\partial L}{\partial w_2} = \frac{\partial L}{\partial z_1}\cdot x_2 = 1.0\times 2.0 = 2.0 $$
$$ \frac{\partial L}{\partial b_1} = \frac{\partial L}{\partial z_1}\cdot 1 = 1.0 $$
এভাবে পাঁচটি প্যারামিটারের জন্যই আমরা $L$-এর গ্রেডিয়েন্ট পেয়ে গেলাম — প্রতিটি ধাপে একটিই প্যাটার্ন পুনরাবৃত্তি হয়েছে: আপস্ট্রিম গ্রেডিয়েন্ট গুণ লোকাল গ্রেডিয়েন্ট। এটাই সম্পূর্ণ ব্যাকপ্রপাগেশন অ্যালগরিদম — যত বড় নেটওয়ার্কই হোক না কেন, মূল নীতি ঠিক এটাই, শুধু ধাপের সংখ্যা বাড়ে।
৬ · সরাসরি ডিফারেনশিয়েশনের সাথে মিলিয়ে দেখা — sanity check
চেইন রুল ছাড়া সরাসরি $L$-কে $b_2$-এর ফাংশন হিসেবে পুরোপুরি লিখে ডিফারেনশিয়েট করলেও একই উত্তর আসা উচিত। পুরো কম্পোজিশন প্রতিস্থাপন করে লিখি:
$$ L(b_2) = \big(w_3\,\sigma(w_1x_1+w_2x_2+b_1) + b_2 - y\big)^2 $$
এখানে $b_2$ ছাড়া বাকি সবকিছু ধ্রুবক ধরে সরাসরি পাওয়ার রুল ও চেইন রুল প্রয়োগ করলে (ভেতরের রাশি $u=w_3h+b_2-y$ ধরে, $L=u^2$, $\partial L/\partial b_2 = 2u \cdot \partial u/\partial b_2 = 2u\cdot 1$):
$$ \frac{\partial L}{\partial b_2} = 2\big(w_3h+b_2-y\big) = 2(\hat{y}-y) $$
এটি ধাপে ধাপে ব্যাকওয়ার্ড পাসে পাওয়া $\partial L/\partial b_2 = 2(\hat{y}-y) = 2.0$-এর সাথে অবিকল মেলে। এই মিল কোনো কাকতালীয় ব্যাপার নয় — মাল্টিভেরিয়েবল চেইন রুল ঠিক এই কারণেই সঠিক প্রমাণিত, এটি শুধু সরাসরি ডিফারেনশিয়েশনকে ধাপে ধাপে, পুনর্ব্যবহারযোগ্য অংশে ভাগ করার একটি পদ্ধতিগত উপায়।
নিচের কোডে সম্পূর্ণ ব্যাকওয়ার্ড পাসটি বাস্তবায়ন করা হলো, উপরের প্রতিটি হাতে-হিসাব করা মানের সাথে মিলিয়ে:
import numpy as np
x1, x2 = 1.0, 2.0
y = 0.0
w1, w2, b1 = 0.5, -0.5, 0.5
w3, b2 = 2.0, 0.0
def sigmoid(x):
return 1.0 / (1.0 + np.exp(-x))
# ---- ফরওয়ার্ড পাস (পাঠ ১৯) ----
z1 = w1 * x1 + w2 * x2 + b1
h = sigmoid(z1)
yhat = w3 * h + b2
L = (yhat - y) ** 2
# ---- ব্যাকওয়ার্ড পাস: আপস্ট্রিম গ্রেডিয়েন্ট × লোকাল গ্রেডিয়েন্ট ----
dL_dyhat = 2 * (yhat - y) # dL/dyhat
dL_dz2 = dL_dyhat * 1.0 # আউটপুট লিনিয়ার, তাই dyhat/dz2 = 1
dL_dw3 = dL_dz2 * h # dz2/dw3 = h
dL_db2 = dL_dz2 * 1.0 # dz2/db2 = 1
dL_dh = dL_dz2 * w3 # dz2/dh = w3
sigma_prime = h * (1 - h) # পাঠ ১৮: sigma'(z1) = h(1-h)
dL_dz1 = dL_dh * sigma_prime
dL_dw1 = dL_dz1 * x1 # dz1/dw1 = x1
dL_dw2 = dL_dz1 * x2 # dz1/dw2 = x2
dL_db1 = dL_dz1 * 1.0 # dz1/db1 = 1
print("dL/dw1 =", dL_dw1)
print("dL/dw2 =", dL_dw2)
print("dL/db1 =", dL_db1)
print("dL/dw3 =", dL_dw3)
print("dL/db2 =", dL_db2)
ব্যাকপ্রপাগেশন কোনো নতুন গাণিতিক আবিষ্কার নয় — এটি মাল্টিভেরিয়েবল চেইন রুলের একটি সংগঠিত প্রয়োগ, যেখানে গ্রাফের শেষ থেকে শুরুতে ফিরে গিয়ে প্রতিটি ধাপে "আপস্ট্রিম গ্রেডিয়েন্ট × লোকাল গ্রেডিয়েন্ট" গুণ করা হয়, এবং ফরওয়ার্ড পাসে ক্যাশ করা মান (পাঠ ১৯) পুনরায় ব্যবহার করা হয়। পাঠ ২১-এ আমরা এই একই গণনা সম্পূর্ণরূপে হাতে ও NumPy-তে পাশাপাশি রেখে চূড়ান্তভাবে মিলিয়ে দেখব।
ভাবনার প্রশ্ন
প্রতিটি প্রশ্ন নিজে কিছুক্ষণ ভাবুন — তারপর "→ উত্তর" চাপুন।
প্র ০১ গ্রেডিয়েন্ট কেন ব্যাকওয়ার্ড (আউটপুট থেকে ইনপুটের দিকে) দিকে গণনা করা হয়, ফরওয়ার্ড দিকে নয়?
চেইন রুলে $\partial L/\partial \theta$ বের করতে $L$-এর "কাছাকাছি" থাকা ডেরিভেটিভগুলো (যেমন $\partial L/\partial \hat{y}$) সবার আগে দরকার হয় — এগুলো ছাড়া পরের ধাপে ($\partial L/\partial h$, $\partial L/\partial z_1$...) এগোনো যায় না। উপরন্তু, একবার $L$ থেকে ব্যাকওয়ার্ড গণনা শুরু হলে প্রতিটি আপস্ট্রিম গ্রেডিয়েন্ট (যেমন $\partial L/\partial z_1=1.0$) একটি একক সংখ্যা হয়ে যায়, যা সেখান থেকে শাখা-প্রশাখায় (একাধিক প্যারামিটারে) পুনরায় ব্যবহার করা যায় — এটি ফরওয়ার্ড-দিকের হিসাবের চেয়ে অনেক বেশি efficient, বিশেষত যখন প্যারামিটার সংখ্যা (লক্ষ লক্ষ) আউটপুট সংখ্যার (একটি স্কেলার লস) চেয়ে অনেক বেশি — এটি পাঠ ২২-তে আরও স্পষ্টভাবে দেখা যাবে।
প্র ০২ যদি একটি ভ্যারিয়েবল গ্রাফে দুইটি ভিন্ন পথ দিয়ে $L$-কে প্রভাবিত করত (branching), গ্রেডিয়েন্ট কীভাবে বদলাত?
তখন মাল্টিভেরিয়েবল চেইন রুলের "যোগ" অংশটি সক্রিয় হতো — প্রতিটি পথের জন্য আলাদাভাবে (আপস্ট্রিম × লোকাল) গ্রেডিয়েন্ট গণনা করে তারপর সেগুলো যোগ করতে হতো। উদাহরণ: যদি একটি ওজন $w$ দুটি ভিন্ন নিউরনে ব্যবহৃত হয় (weight sharing, যেমন CNN-এ), তাহলে $\partial L/\partial w$ হবে দুই নিউরন থেকে আসা দুটি গ্রেডিয়েন্টের সমষ্টি। আমাদের সরল চেইন-নেটওয়ার্কে এমন কোনো branching নেই, তাই এই ধাপটি প্রয়োজন হয়নি।
প্র ০৩ আমাদের হিসাবে $\partial L/\partial z_1 = 1.0$ পাওয়া গেছে — এটি কি কাকতালীয়, নাকি আমাদের বেছে নেওয়া সংখ্যার ফল?
এটি সম্পূর্ণভাবে আমাদের বেছে নেওয়া সংখ্যার ফল — একটি সুন্দর কাকতালীয় ব্যাপার নয়, বরং ইচ্ছাকৃত নকশা। $z_1=0$ হওয়ায় $\sigma(z_1)=0.5$ ঠিক অর্ধেক হয়েছে, যার ফলে $\sigma'(z_1)=0.25$ (সিগময়েডের সর্বোচ্চ মান) এবং বাকি গুণফলগুলো মিলে $1.0$ হয়েছে। ভিন্ন ইনপুট/ওজন বেছে নিলে এই মানগুলো অবশ্যই ভিন্ন হতো (দেখুন পাঠ ১৯-এর অনুশীলন ১), তবে ব্যবহৃত পদ্ধতি (চেইন রুল প্রয়োগের ধাপ) ঠিক একই থাকত।
অনুশীলন
-
ধাপে ধাপে ডেরাইভ করুন: আমাদের ব্যাকওয়ার্ড পাসের পদ্ধতি অনুসরণ করে $\partial \hat{y}/\partial b_2$
থেকে শুরু করে দেখান কেন $\partial L/\partial b_2 = 2(\hat{y}-y)$ (কোনো $h$ বা $w_3$ নির্ভরতা ছাড়াই)।
$z_2=w_3h+b_2$ হওয়ায় $\partial z_2/\partial b_2 = 1$ — এখানে $h$ বা $w_3$ কোনোভাবেই এই লোকাল গ্রেডিয়েন্টে প্রভাব ফেলে না। তাই $\partial L/\partial b_2 = \partial L/\partial z_2 \cdot 1 = 2(\hat{y}-y)$। বায়াস টার্মের গ্রেডিয়েন্ট সবসময়ই তার নোডের আপস্ট্রিম গ্রেডিয়েন্টের সমান — এটি একটি সাধারণ প্যাটার্ন।
-
নিজে গণনা করুন: যদি $y=1.0$ হতো (বাকি সব মান পাঠ ১৯-এর মতোই), তাহলে $\partial L/\partial w_3$
এবং $\partial L/\partial w_1$-এর নতুন মান কত হতো?
$\hat{y}=1.0$ অপরিবর্তিত, কিন্তু এখন $\hat{y}-y=0$, তাই $\partial L/\partial\hat{y}=2(1.0-1.0)=0$। যেহেতু পুরো ব্যাকওয়ার্ড চেইন এই একই শূন্য দিয়ে গুণ হয়, তাই $\partial L/\partial w_3=0$ এবং $\partial L/\partial w_1=0$ — অর্থাৎ যখন পূর্বাভাস প্রকৃত লক্ষ্যের সাথে হুবহু মিলে যায়, লস তার সর্বনিম্ন বিন্দুতে থাকে এবং কোনো দিকেই আর গ্রেডিয়েন্ট থাকে না।
-
কোড দিয়ে যাচাই করুন: উপরের code cell-এ
y = 1.0করে Run চাপুন এবং উপরের অনুশীলন ২-এর হাতে-হিসাব করা মানের সাথে মিলিয়ে দেখুন।কোডের আউটপুটে সবগুলো গ্রেডিয়েন্ট (
dL_dw1থেকেdL_db2পর্যন্ত) ঠিক0.0হওয়া উচিত — যা উপরের অনুশীলন ২-এর যুক্তির সাথে মেলে।
আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ
- পাঠ ২১ — সম্পূর্ণ ব্যাকপ্রপ, হাতে-কলমে ও NumPy-তে পরবর্তী পাঠ এই একই নেটওয়ার্কের সম্পূর্ণ ফরওয়ার্ড ও ব্যাকওয়ার্ড পাস পাশাপাশি রেখে চূড়ান্তভাবে মিলিয়ে দেখা হবে।
- সব AI Courses দেখুন ABCL TECH AI Foundations, Python for AI, Machine Learning, Deep Learning, Math for AI ও আরও অনেক কিছু — সব এক জায়গায়।
- Deep Learning কোর্স প্রয়োগ দেখুন বাস্তব ফ্রেমওয়ার্কে (PyTorch/TensorFlow) এই একই ব্যাকওয়ার্ড পাস স্বয়ংক্রিয়ভাবে কীভাবে চলে তা দেখতে।