عنوان

شبکه عصبی دقیقا چطوری یاد می‌گیره؟

شبکهٔ عصبی ایده‌ایه که داره یک بستر ایجاد می‌کنه تا مدل بتونه چیزهای پیچیده‌تر رو بفهمه. این کار رو هم با یک‌سری rule نسبتاً ساده انجام می‌ده؛ ruleهایی که اجازه می‌دن مدل از اشتباه‌هاش یاد بگیره.

یعنی مدل اول یک جواب می‌ده، بعد می‌فهمه جوابش چقدر خوب یا بد بوده و سعی می‌کنه خودش رو طوری تغییر بده که دفعهٔ بعد جواب بهتری بده.

کل داستان شبکهٔ عصبی، gradient descent و backpropagation تهش برمی‌گرده به همین ایدهٔ ساده:

مدل اشتباه می‌کنه، می‌فهمه چقدر اشتباه کرده و یاد می‌گیره کمتر اشتباه کنه.

حالا سؤال اینه که این «یاد گرفتن» دقیقاً چطور اتفاق می‌افته؟

خب اصلاً یک نورون مصنوعی چیه؟

نورون مصنوعی قرار نیست واقعاً شبیه مغز انسان کار کنه؛ فقط یک ایدهٔ ساده‌ست که از نورون‌های مغزی الهام گرفته شده.

فرض کن مدل می‌خواد تصمیم بگیره یک عکس گربه هست یا نه. قبل از اینکه به جواب برسه، کلی عدد بهش می‌رسه؛ مثلاً رنگ بعضی پیکسل‌ها، شکل گوش‌ها، وجود داشتن یا نداشتن سبیل و هزار تا چیز دیگه.

یک نورون مصنوعی این ورودی‌ها رو می‌گیره و برای هر کدوم مشخص می‌کنه که چقدر مهمه. این «مهم بودن» هر ورودی با یک عدد مشخص می‌شه که بهش می‌گیم weight یا وزن.

پس اگر خیلی ساده بخوایم بگیم، یک نورون ورودی‌ها رو می‌گیره، به هر کدوم بر اساس اهمیتش وزن می‌ده، همه رو با هم جمع می‌کنه و در نهایت مشخص می‌کنه خروجی‌اش چقدر فعال باشه.

محاسبهٔ اولیه در یک نورون

z (input × weight) + bias

پس مدل دقیقاً چی رو یاد می‌گیره؟

مدل قرار نیست خودش یک فرمول جدید اختراع کنه. ساختار کلی‌اش از قبل مشخصه؛ می‌دونیم قرار است ورودی‌ها رو بگیره، در weightها ضرب کنه، با هم جمع کنه و یک خروجی بده.

چیزی که مدل نمی‌دونه، مقدار درست weightها و biasهاست. در واقع weight و bias همون چیزهایی هستن که مدل قراره یاد بگیره.

میشه این‌طوری دیدش که مدل یک‌سری پیچ تنظیم داره. هر weight یک پیچه که مشخص می‌کنه یک ورودی چقدر مهمه و bias هم یک پیچ دیگه‌ست که کمک می‌کنه مدل نقطهٔ شروع تصمیمش رو جابه‌جا کنه.

اول کار، مدل هیچ ایده‌ای نداره که کدوم ورودی مهمه. برای همین weightها معمولاً با عددهای کوچک و تقریباً رندوم شروع می‌شن. بعد مدل جواب درست رو با جواب خودش مقایسه می‌کنه و این پیچ‌ها را، نه کاملاً رندوم و نه به یک اندازه، تغییر می‌ده.

یک چیز مهم جا موند: activation function

اگر شبکه فقط ضرب و جمع انجام بده، حتی اگر ده‌ها لایه داشته باشه، در نهایت معادل یک ضرب و جمع بزرگ‌تره. یعنی اضافه کردن لایه‌های بیشتر به تنهایی به مدل کمک نمی‌کنه چیزهای پیچیده‌تری یاد بگیره.

اینجاست که activation function وارد می‌شه. activation function یک تابع کوچیکه که بعد از محاسبهٔ هر نورون قرار می‌گیره و خروجی آن را تغییر می‌ده. این تابع باعث می‌شه مدل فقط یک ماشین جمع و ضرب نباشه و بتواند رابطه‌های غیرخطی را هم یاد بگیره.

یک نورون کامل‌تر

z (input × weight) + bias
output activation(z)

چرا غیرخطی بودن مهمه؟

خیلی از رابطه‌های واقعی خطی نیستن. مثلاً در قیمت خانه، ممکنه افزایش متراژ تا یک حدی روی قیمت خیلی اثر داشته باشه، ولی بعد از یک نقطه اثرش کمتر بشه. یا در تشخیص تصویر، وجود یک پیکسل خاص به تنهایی معنی خاصی نداره، ولی ترکیب چند شکل کنار هم می‌تونه معنی «گوش گربه» بده.

یکی از ساده‌ترین activation functionها، ReLU است.

تابع ReLU

ReLU(z) max(0, z)

یعنی اگر مقدار ورودی مثبت باشه، همون مقدار را رد می‌کنه. اگر منفی باشه، خروجی را صفر می‌کنه.

دو نمونه از رفتار ReLU

ReLU(3) 3
ReLU(-2) 0

یک activation function معروف دیگر، sigmoid است.

تابع Sigmoid

sigmoid(z) 1 / (1 + e^(-z))

خروجی sigmoid همیشه بین صفر و یک است. برای همین وقتی می‌خواهیم خروجی را مثل احتمال ببینیم، خیلی کاربرد دارد.

تفسیر خروجی Sigmoid

output 0.92
probability 92%

forward pass؛ مدل چطور به جواب می‌رسه؟

وقتی داده از ورودی وارد شبکه می‌شه و لایه‌به‌لایه جلو می‌ره تا به prediction برسد، به این فرایند می‌گیم forward pass.

مسیر حرکت داده در شبکه

input → layer 1 → layer 2 → prediction

تا اینجا شبکه فقط دارد جواب تولید می‌کنه. برای یاد گرفتن، مدل باید بفهمه جوابش چقدر با جواب درست فاصله داشته.

مدل از کجا می‌فهمه چقدر خراب کرده؟

فرض کن مدل می‌خواد قیمت یک خانه رو پیش‌بینی کنه. قیمت واقعی خانه مثلاً ۱۰ میلیارد بوده، ولی مدل گفته ۸ میلیارد.

مدل باید این اشتباه را به یک عدد تبدیل کنه تا بفهمه چقدر باید خودش رو تغییر بده. اینجاست که از چیزی به اسم loss function استفاده می‌کنیم.

محاسبهٔ loss

loss (target – prediction)²

اینجا target جواب واقعی و prediction جواب مدل است.

محاسبهٔ خطای پیش‌بینی

target 10
prediction 8
loss (10 – 8)² = 4

اگر مدل به‌جای ۸ میلیارد، ۹.۵ میلیارد را پیش‌بینی می‌کرد، loss کمتر می‌شد.

یک پیش‌بینی بهتر

target 10
prediction 9.5
loss (10 – 9.5)² = 0.25

پس مشخصه که جواب دوم بهتر بوده، چون loss کمتری داره.

gradient دقیقاً چیه؟

حالا مدل می‌دونه جوابش چقدر بد بوده، ولی هنوز باید بفهمه هر weight را به کدام سمت و چقدر تغییر بده.

فرض کن فقط یک weight داریم. اگر این weight را یک مقدار خیلی کوچک تغییر بدیم، loss چه تغییری می‌کنه؟ اگر با بیشتر کردن weight، loss کمتر بشه، حرکت در همان جهت مفیده. اگر loss بیشتر بشه، باید به سمت دیگر حرکت کنیم.

مقداری که این تغییر را اندازه می‌گیره، همون چیزیه که بهش می‌گیم gradient.

> اگر این پارامتر را یک ذره تغییر بدی، loss تقریباً چقدر و در چه جهتی تغییر می‌کنه؟

Gradient یک Weight

gradient d(loss) / d(weight)

اگر gradient یک weight بزرگ باشه، یعنی آن weight اثر زیادی روی اشتباه نهایی مدل داشته. اگر gradient نزدیک صفر باشه، یعنی تغییر کوچک آن weight فعلاً اثر خیلی خاصی روی loss نمی‌گذاره.

gradient descent؛ مدل چطور مسیر بهتر رو پیدا می‌کنه؟

فرض کن روی یک کوه قرار گرفتی و هوا مه‌آلوده. هدفت اینه که خودت رو به پایین‌ترین نقطهٔ دره برسونی، ولی فقط می‌تونی شیب اطراف پات رو ببینی.

gradient descent تقریباً همین کار رو برای مدل انجام می‌ده. مدل روی سطحی حرکت می‌کنه که ارتفاعش مقدار loss است و سعی می‌کنه هر بار یک قدم به سمت پایین برداره.

قانون به‌روزرسانی Weight

new_weight old_weight – learning_rate × gradient

علامت منفی مهمه؛ gradient جهت بالا رفتن loss را نشان می‌ده، ولی ما می‌خوایم به سمت پایین حرکت کنیم.

learning rate اندازهٔ قدم مدل را مشخص می‌کنه. اگر خیلی بزرگ باشه، مدل ممکنه از نقطهٔ خوب رد بشه. اگر خیلی کوچک باشه، یادگیری خیلی کند می‌شه.

قبل از شبکهٔ چندلایه، یک نورون را واقعاً train کنیم

قبل از اینکه سراغ چند لایه بریم، بهتره با یک نورون ساده خودِ gradient را حساب کنیم. اینجا قرار نیست چیزی را حفظ کنیم؛ فقط می‌خواهیم ببینیم مدل با عددها دقیقاً چه کار می‌کنه.

یک ورودی، یک weight، یک bias و یک sigmoid داریم. هدف مدل اینه که برای این ورودی، خروجی نزدیک به یک بده.

مقادیر اولیه

input 1
weight 0.5
bias 0
target 1

در forward pass، اول مقدار z و بعد prediction را حساب می‌کنیم.

Forward Pass

z (input × weight) + bias
z (1 × 0.5) + 0 = 0.5
prediction sigmoid(0.5) = 0.622

مدل باید خروجی یک می‌داده، ولی خروجی‌اش حدود ۰.۶۲۲ شده. حالا loss را حساب می‌کنیم.

Loss اولیه

target 1
prediction 0.622
loss (1 – 0.622)² = 0.143

حالا سؤال اصلی اینه: اگر weight را کمی تغییر بدیم، loss چقدر تغییر می‌کنه؟

برای جواب، مسیر اثر weight را قدم‌به‌قدم دنبال می‌کنیم:

مسیر اثر Weight

weight → z → prediction → loss

قبل از اینکه اثر prediction روی loss را حساب کنیم، تعریف دقیق مشتق را داشته باشیم. مشتق می‌پرسد اگر prediction را به اندازهٔ خیلی کوچک h تغییر بدهیم، loss با چه سرعتی تغییر می‌کند.

تعریف دقیق مشتق Loss نسبت به Prediction

رابطهٔ اصلی

∂L / ∂ŷ
lim(h → 0) [L(ŷ + h) − L(ŷ)] / h

اول اثر prediction روی loss را حساب می‌کنیم.

اثر Prediction روی Loss

d(loss) / d(prediction)
2 × (prediction – target)
d(loss) / d(prediction)
2 × (0.622 – 1)
-0.756

بعد اثر z روی prediction را حساب می‌کنیم. چون activation ما sigmoid است، مشتق آن این شکلیه:

اثر z روی Prediction

d(prediction) / d(z)
prediction × (1 – prediction)
d(prediction) / d(z)
0.622 × (1 – 0.622)
0.235

حالا این دو اثر را ضرب می‌کنیم تا بفهمیم z چقدر در loss نقش داشته.

Gradient نسبت به z

d(loss) / d(z)
d(loss) / d(prediction)
× d(prediction) / d(z)
d(loss) / d(z)
-0.756 × 0.235
-0.178

و چون z از ضرب input در weight ساخته شده، gradient weight این شکلی می‌شه:

Gradient Weight

d(loss) / d(weight)
d(loss) / d(z)
× d(z) / d(weight)
d(loss) / d(weight)
-0.178 × input
-0.178

علامت منفی یعنی با بیشتر کردن weight، loss کمتر می‌شه. اگر learning rate را ۰.۱ در نظر بگیریم، update این شکلیه:

به‌روزرسانی Weight

new_weight
old_weight – learning_rate × gradient
new_weight
0.5 – (0.1 × -0.178)
0.518

bias هم update می‌شه و بعد مدل دوباره forward pass را انجام می‌ده. نتیجهٔ تازه کمی به جواب درست نزدیک‌تر و loss هم کمی کمتر می‌شه.

این فرایند ساده، پایهٔ تمام شبکه‌های بزرگ‌تره. حالا مسئله‌ای که پیش می‌آد اینه که اگر به‌جای یک نورون، چندین لایه داشته باشیم، اثر هر weight چطور محاسبه می‌شه؟

مدل از کجا می‌فهمه هر لایه چقدر مقصر بوده؟

یک weight در لایهٔ اول مستقیماً روی loss اثر نمی‌ذاره. اول خروجی یک نورون را تغییر می‌ده، آن تغییر وارد لایهٔ بعدی می‌شه و در نهایت روی prediction و loss اثر می‌ذاره.

اثر یک Weight در شبکهٔ چندلایه

weight
→ neuron output
→ next layer output
→ prediction
→ loss

سؤال اصلی backpropagation همین است:

هر weight، با عبور از این همه لایه، چقدر در loss نهایی نقش داشته؟

جواب با chain rule به دست می‌آد. chain rule می‌گه اگر یک اتفاق از چند مرحله رد شده، برای فهمیدن اثر مرحلهٔ اول روی نتیجهٔ آخر باید اثر همهٔ مرحله‌ها را پشت سر هم حساب کنیم.

Chain Rule

d(loss) / d(weight)
d(loss) / d(prediction)
× d(prediction) / d(neuron_output)
× d(neuron_output) / d(weight)

این فرمول فقط دارد یک سؤال را جواب می‌دهد: اگر weight را یک ذره تغییر بدیم، در نهایت loss چقدر تغییر می‌کنه؟

backpropagation دقیقاً چه کار می‌کنه؟

در forward pass، داده از لایهٔ اول وارد می‌شه، از لایه‌های بعدی رد می‌شه و در نهایت به prediction می‌رسه. بعد هم loss حساب می‌شه.

در backpropagation، مسیر برعکس می‌شه. مدل از loss شروع می‌کنه و به عقب برمی‌گرده. در هر مرحله بررسی می‌کنه خروجی آن لایه چقدر در اشتباه نهایی نقش داشته و سپس این سهم را به لایهٔ قبلی منتقل می‌کنه.

دو مسیر شبکه

forward pass:
input → layer 1 → layer 2 → prediction → loss
backpropagation:
loss → layer 2 → layer 1 → weights

هر لایه دو کار انجام می‌ده: مشخص می‌کنه خروجی خودش چقدر در loss نقش داشته و مشخص می‌کنه هر weight داخل خودش چقدر مسئول آن خروجی بوده.

پس backpropagation خودش فرآیند یادگیری نیست. backpropagation روشی است که مدل با آن gradient همهٔ weightها و biasها را، حتی در یک شبکهٔ چندلایه، سریع و درست حساب می‌کنه. gradient descent هم از این gradientها استفاده می‌کنه تا مدل را یک قدم به سمت loss کمتر حرکت بده.

یک مثال واقعی و خیلی کوچک

بیا یک شبکهٔ خیلی کوچک داشته باشیم: فقط یک ورودی، یک weight، یک bias و یک sigmoid. هدف مدل اینه که برای این ورودی، خروجی نزدیک به یک بده.

مقادیر اولیه

input 1
weight 0.5
bias 0
target 1

اول forward pass را انجام می‌دیم.

Forward Pass

z (input × weight) + bias
z (1 × 0.5) + 0 = 0.5
prediction sigmoid(0.5) = 0.622

مدل باید خروجی یک می‌داده، ولی خروجی‌اش حدود ۰.۶۲۲ شده. پس loss را حساب می‌کنیم.

Loss اولیه

target 1
prediction 0.622
loss (1 – 0.622)² = 0.143

حالا backpropagation شروع می‌شه. اول می‌پرسیم اگر prediction تغییر کنه، loss چقدر تغییر می‌کنه؟

اثر Prediction روی Loss

d(loss) / d(prediction)
2 × (prediction – target)
d(loss) / d(prediction)
2 × (0.622 – 1)
-0.756

بعد باید اثر z را روی prediction حساب کنیم. چون از sigmoid استفاده کردیم، مشتق sigmoid این شکلیه:

مشتق Sigmoid

d(prediction) / d(z)
prediction × (1 – prediction)
d(prediction) / d(z)
0.622 × (1 – 0.622)
0.235

حالا این دو اثر را با هم ضرب می‌کنیم تا بفهمیم z چقدر در loss نقش داشته.

Gradient نسبت به z

d(loss) / d(z)
d(loss) / d(prediction)
× d(prediction) / d(z)
d(loss) / d(z)
-0.756 × 0.235
-0.178

و چون z از ضرب input در weight ساخته شده، gradient weight این شکلی می‌شه:

Gradient Weight

d(loss) / d(weight)
d(loss) / d(z)
× d(z) / d(weight)
d(loss) / d(weight)
-0.178 × input
-0.178

علامت منفی به ما می‌گه برای کم کردن loss باید weight را بیشتر کنیم.

به‌روزرسانی Weight

new_weight
old_weight – learning_rate × gradient
new_weight
0.5 – (0.1 × -0.178)
0.518

bias هم gradient خودش را می‌گیرد و در این مثال به حدود ۰.۰۱۸ می‌رسد. اگر دوباره forward pass را انجام بدیم، prediction حدود ۰.۶۳۱ می‌شه. هنوز جواب کامل نیست، اما به جواب درست یعنی یک نزدیک‌تر شده و loss هم کمتر شده.

مدل همین چرخه را بارها و بارها تکرار می‌کنه:

چرخهٔ یادگیری

forward pass
→ loss
→ backpropagation
→ update parameters
→ repeat

این دقیقاً همان چیزی است که بهش می‌گیم train کردن مدل.

مثال دوم: یک نورون با loss طبقه‌بندی

یک ورودی، یک weight، یک bias و یک Sigmoid داریم. هدف اینه که خروجی نزدیک به یک بشه.

پارامترها و دادهٔ نمونه

x 1.2
w 0.4
b -0.1
y 1

forward pass

محاسبهٔ Logit

رابطهٔ اصلی

z = w × x + b

جایگذاری مقادیر

(0.4 × 1.2) + (-0.1)
0.38
محاسبهٔ Prediction

رابطهٔ اصلی

ŷ = sigmoid(z)

جایگذاری مقادیر

sigmoid(0.38)
0.594

loss

برای طبقه‌بندی دودویی، معمولاً از binary cross-entropy استفاده می‌کنیم.

Binary Cross-Entropy

L -[y × ln(ŷ) + (1 – y) × ln(1 – ŷ)]

چون y برابر یک است:

Loss نمونه

رابطهٔ اصلی

L = -ln(ŷ)

جایگذاری مقادیر

-ln(0.594)
0.521

محاسبهٔ gradient

مسیر اثر weight اینه:

مسیر اثر Weight

flow w → z → ŷ → L

پس طبق chain rule:

Chain Rule برای یک نورون

رابطهٔ اصلی

∂L/∂w
∂L/∂ŷ × ∂ŷ/∂z × ∂z/∂w

برای ترکیب Sigmoid و Binary Cross-Entropy، بخش اول ساده می‌شه:

Output Delta

رابطهٔ اصلی

∂L/∂z = ŷ − y

جایگذاری مقادیر

0.594 − 1
-0.406

از طرف دیگر:

مشتق‌های محلی

∂z/∂w x
∂z/∂b 1
Gradient Weight

رابطهٔ اصلی

∂L/∂w = ∂L/∂z × x

جایگذاری مقادیر

-0.406 × 1.2
-0.487
Gradient Bias

رابطهٔ اصلی

∂L/∂b = ∂L/∂z

جایگذاری مقادیر

-0.406

gradient منفی می‌گه بیشتر کردن weight و bias، loss را کمتر می‌کنه.

به‌روزرسانی Weight

رابطهٔ اصلی

w_new = w − η × ∂L/∂w

جایگذاری مقادیر

0.4 − (0.1 × -0.487)
0.4487
به‌روزرسانی Bias

رابطهٔ اصلی

b_new = b − η × ∂L/∂b

جایگذاری مقادیر

-0.1 − (0.1 × -0.406)
-0.0594

بعد از این update، prediction به حدود ۰.۶۱۸ می‌رسه و loss کمتر می‌شه.

شبکهٔ دو لایه

در شبکهٔ چندلایه، weightهای لایهٔ اول مستقیم به loss وصل نیستن. ابتدا خروجی یک نورون را تغییر می‌دن، آن تغییر وارد لایهٔ بعدی می‌شه، بعد روی output layer اثر می‌گذاره و در نهایت loss را تغییر می‌ده.

همین‌جا مسئلهٔ اصلی backpropagation به وجود می‌آد: هر weight، با عبور از این همه لایه، چقدر در loss نهایی نقش داشته؟

جواب با chain rule به دست می‌آد. chain rule می‌گه اگر یک اتفاق از چند مرحله رد شده، برای فهمیدن اثر مرحلهٔ اول روی نتیجهٔ آخر باید اثر همهٔ مرحله‌ها را پشت سر هم حساب کنیم.

ساختار شبکه

flow x → hidden layer → output layer → ŷ → L

فرض کن hidden layer دو نورون ReLU دارد.

پارامترهای Hidden Layer

x 1
w₁ 0.6
b₁ -0.1
w₂ -0.4
b₂ 0.6
نورون اول در Hidden Layer

رابطهٔ اصلی

z₁ = w₁ × x + b₁

جایگذاری مقادیر

(0.6 × 1) + (-0.1)
0.5
h₁ = ReLU(z₁)
0.5
نورون دوم در Hidden Layer

رابطهٔ اصلی

z₂ = w₂ × x + b₂

جایگذاری مقادیر

(-0.4 × 1) + 0.6
0.2
h₂ = ReLU(z₂)
0.2

خروجی این دو نورون وارد output layer می‌شه.

پارامترهای Output Layer

v₁ 0.7
v₂ -0.5
c 0.1
y 1
Forward Pass در Output Layer

رابطهٔ اصلی

z₃ = v₁ × h₁ + v₂ × h₂ + c

جایگذاری مقادیر

(0.7 × 0.5) + (-0.5 × 0.2) + 0.1
0.35
ŷ = sigmoid(z₃)
0.587
Loss شبکهٔ دو لایه

رابطهٔ اصلی

L = -ln(ŷ)

جایگذاری مقادیر

-ln(0.587)
0.533

backpropagation در شبکهٔ دو لایه

از loss شروع می‌کنیم و به عقب برمی‌گردیم.

Output Delta

رابطهٔ اصلی

δ₃ = ∂L/∂z₃
ŷ − y

جایگذاری مقادیر

0.587 − 1
-0.413

Gradientهای output layer

Gradient نخست در Output Layer

رابطهٔ اصلی

∂L/∂v₁ = δ₃ × h₁

جایگذاری مقادیر

-0.413 × 0.5
-0.207
Gradient دوم در Output Layer

رابطهٔ اصلی

∂L/∂v₂ = δ₃ × h₂

جایگذاری مقادیر

-0.413 × 0.2
-0.083
Gradient Bias خروجی

رابطهٔ اصلی

∂L/∂c = δ₃

جایگذاری مقادیر

-0.413

برگرداندن خطا به hidden layer

اثر Loss روی Hidden Output اول

رابطهٔ اصلی

∂L/∂h₁ = δ₃ × v₁

جایگذاری مقادیر

-0.413 × 0.7
-0.289
اثر Loss روی Hidden Output دوم

رابطهٔ اصلی

∂L/∂h₂ = δ₃ × v₂

جایگذاری مقادیر

-0.413 × -0.5
0.207

چون هر دو logit در hidden layer مثبت‌اند، مشتق ReLU برای هر دو یک است.

مشتق ReLU

ReLU'(z) 1, if z > 0
ReLU'(z) 0, if z ≤ 0
Hidden Delta اول

رابطهٔ اصلی

δ₁ = ∂L/∂h₁ × ReLU'(z₁)

جایگذاری مقادیر

-0.289 × 1
-0.289
Hidden Delta دوم

رابطهٔ اصلی

δ₂ = ∂L/∂h₂ × ReLU'(z₂)

جایگذاری مقادیر

0.207 × 1
0.207
Gradient Weight اول در Hidden Layer

رابطهٔ اصلی

∂L/∂w₁ = δ₁ × x

جایگذاری مقادیر

-0.289 × 1
-0.289
Gradient Bias اول در Hidden Layer

رابطهٔ اصلی

∂L/∂b₁ = δ₁

جایگذاری مقادیر

-0.289
Gradient Weight دوم در Hidden Layer

رابطهٔ اصلی

∂L/∂w₂ = δ₂ × x

جایگذاری مقادیر

0.207 × 1
0.207
Gradient Bias دوم در Hidden Layer

رابطهٔ اصلی

∂L/∂b₂ = δ₂

جایگذاری مقادیر

0.207

این همان کاریه که backpropagation انجام می‌ده: سهم هر weight در loss را از خروجی به سمت لایه‌های قبل برمی‌گردونه.

در forward pass، داده از لایهٔ اول وارد می‌شه، از لایه‌های بعدی رد می‌شه و در نهایت به prediction و loss می‌رسه. در backpropagation مسیر برعکس می‌شه؛ مدل از loss شروع می‌کنه و به عقب برمی‌گرده.

پس backpropagation خودش فرآیند یادگیری نیست. روشی است که مدل با آن gradient همهٔ weightها و biasها را، حتی در یک شبکهٔ چندلایه، سریع و درست حساب می‌کنه. gradient descent از این gradientها استفاده می‌کنه تا مدل را یک قدم به سمت loss کمتر حرکت بده.

فرم کلی‌تر Backpropagation

Forward Pass در لایهٔ l

Z⁽ˡ⁾ W⁽ˡ⁾A⁽ˡ⁻¹⁾ + b⁽ˡ⁾
A⁽ˡ⁾ g⁽ˡ⁾(Z⁽ˡ⁾)

Backward Pass در لایهٔ l

δ⁽ˡ⁾ ((W⁽ˡ⁺¹⁾)ᵀδ⁽ˡ⁺¹⁾) ⊙ g’⁽ˡ⁾(Z⁽ˡ⁾)

Gradientهای لایهٔ l

∂L/∂W⁽ˡ⁾ δ⁽ˡ⁾(A⁽ˡ⁻¹⁾)ᵀ
∂L/∂b⁽ˡ⁾ δ⁽ˡ⁾

علامت ⊙ یعنی ضرب عضو‌به‌عضو. در یک batch، gradientها روی نمونه‌ها جمع یا میانگین گرفته می‌شن.

آیا backpropagation همیشه بی‌نقص کار می‌کنه؟

نه. backpropagation ابزار خیلی قدرتمندیه، ولی تضمین نمی‌کنه مدل همیشه بهترین جواب ممکن را پیدا کنه.

مدل فقط اطراف نقطه‌ای را می‌بینه که الان در آن قرار دارد؛ مثل کسی که در مه روی کوه حرکت می‌کنه و کل نقشهٔ کوه را نمی‌بینه. ممکنه داخل یک گودی محلی گیر کنه؛ یعنی جایی که اطرافش بهتر به نظر نمی‌رسه، ولی در یک بخش دیگر از سطح loss جواب خیلی بهتری وجود دارد. به این حالت local minimum می‌گیم.

اما مسئله فقط local minimum نیست. در شبکه‌های بزرگ، گاهی مدل به ناحیه‌های خیلی تخت می‌رسه که gradient در آن‌ها نزدیک صفره. در این حالت، مدل تقریباً نمی‌فهمه به کدام سمت باید بره. به این وضعیت معمولاً plateau یا saddle point می‌گن.

یک مشکل مهم دیگر، vanishing gradient است. در شبکه‌های خیلی عمیق، چون gradient باید از لایه‌های زیادی رد بشه، ممکنه آن‌قدر کوچک بشه که لایه‌های ابتدایی تقریباً هیچ سیگنال یادگیری دریافت نکنن.

برعکسش هم وجود داره: exploding gradient. یعنی gradient آن‌قدر بزرگ می‌شه که weightها با هر قدم بیش از حد تغییر می‌کنن و آموزش ناپایدار می‌شه.

بعضی activation functionها هم مشکل مخصوص خودشان را دارن. مثلاً در ReLU، اگر ورودی یک نورون همیشه منفی بماند، خروجی آن نورون دائماً صفر می‌شود و ممکن است دیگر چیزی یاد نگیرد. به این حالت گاهی dead ReLU می‌گن.

در عمل برای کم کردن این مشکلات از روش‌هایی مثل initialization بهتر، normalization، activation functionهای مناسب، optimizerهایی مثل Adam، gradient clipping و معماری‌هایی مثل residual connection استفاده می‌شه.

جمع‌بندی

شبکهٔ عصبی با چند rule ساده شروع می‌کنه، ولی از کنار هم قرار گرفتن تعداد زیادی از همین ruleها می‌تونه چیزهای پیچیده‌ای یاد بگیره.

مدل در forward pass یک prediction می‌ده. loss function می‌گه این prediction چقدر بد بوده. backpropagation به مدل کمک می‌کنه سهم هر weight و bias را در آن اشتباه حساب کنه و gradient descent پارامترها را در جهتی تغییر می‌ده که loss کمتر بشه.

شبکهٔ عصبی با پیش‌بینی کردن، اندازه گرفتن اشتباه، پخش کردن مسئولیت اشتباه بین پارامترها و اصلاح تدریجی آن‌ها یاد می‌گیره.