پس‌انتشار

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

روش معمول محاسبه گرادیان (محاسبه اثر هر وزن در خروجی هر نمونه) برای شبکه‌های عصبی پیشخور و به خصوص شبکه‌های عمیق بسیار زمان‌بر و در عمل غیرممکن است. با استفاده از روش پس‌انتشار و با کمک قاعده زنجیره‌ای و مشتق جزئی، در محاسبه گرادیان هر لایه از مشتقات لایه‌های جلوتر استفاده می‌شود و زمان اجرا تا حد زیادی کاهش پیدا می‌کند. استفاده از روش پس‌انتشار در کنار روش گرادیان کاهشی تصادفی، امکان اضافه کردن لایه‌های بیش‌تر به مدل به دلیل صرفه‌جویی زمانی به وجود می‌آید. این افزایش تعداد لایه‌ها از سوی دیگر باعث امکان یادگیری الگوهای پیچیده‌تر می‌شود.

## ساختار ریاضی الگوریتم
جایگزین=|بندانگشتی|604x604پیکسل|محاسبه گرادیان تابع هزینه برای سلول c

برای سلول عصبی c ورودیی که از سلول عصبی p به این سلول وارد می‌شود را با b_{pc} نشان می‌دهیم. وزن این ورودی w_{pc} است و مجموع ضرب ورودی‌ها با وزنهایشان را با a_c نمایش می‌دهیم، یعنی a_c = \sum w_{pc}\times b_{pc}. حال باید بر روی a_c یک تابع غیر خطی اعمال کنیم، این تابع را \theta_c می‌نامیم و خروجی آن را با b_c نمایش می‌دهیم به این معنی که b_c = \theta_c(a_c). به همین شکل خروجی‌هایی که از سلول عصبی c خارج شده و به سلول n وارد می‌شوند را با b_{cn} نمایش می‌دهیم و وزن آن را با w_{cn} . اگر تمام وزنهای این شبکه عصبی را در مجموعه‌ای به اسم W بگنجانیم، هدف در واقع یادگیری این وزنهاست. اگر ورودی ما x باشد و خروجی y و خروجی شبکه عصبی ما h_W(x)، هدف ما پیدا کردن W است به قسمی که برای همه داده‌ها y و h_W(x) به هم خیلی نزدیک شوند. به عبارت دیگر هدف کوچک کردن یک تابع ضرر بر روی تمام داده هاست، اگر داده‌ها را با (x_1, y_1), \cdots, (x_n, y_n) و تابع ضرر را با l نشان دهیم هدف کمینه کردن تابع پایین بر حسب W است:

Q(W) = \sum_{i=1}^n l\left(h_W(x_i),\,\,y_i\right)

به عنوان مثال اگر مسئله رگرسیون است برای l می‌توانیم خطای مربعات را در نظر بگیریم و اگر مسئله دسته‌بندی است برای l می‌شود منفی لگاریتم بازنمایی را استفاده کرد.

برای به‌دست آوردن کمینه Q(W) می‌توان از روش گرادیان کاهشی استفاده کرد، به این معنی که گرادیان تابع را در حساب کرد و کمی در خلاف جهت آن حرکت کرد و این کار را آنقدر ادامه داد تا تابع ضرر خیلی کوچک شود. روش بازگشت به عقب در واقع روشی برای پیدا کردن گرادیان تابع است.

حال فرض کنیم می‌خواهیم گرادیان تابع Q(W) را نسبت به وزن w_{pc} به‌دست بیاوریم. برای این کار نیاز به قاعده زنجیری در مشتق‌گیری داریم. قاعده زنجیری به این شکل کار می‌کند: اگر تابعی داشته باشیم به اسم f که وابسته به سه ورودی u، v و w باشد و هرکدام از این سه ورودی به نوبه خود وابسته به t باشند، مشتق f به t به این شکل محاسبه می‌شود:

\frac{\partial f\left(u(t),v(t),w(t)\right)}{\partial t} = \frac{\partial f}{\partial u} \frac{\partial u}{\partial t} + \frac{\partial f}{\partial v} \frac{\partial v}{\partial t}  + \frac{\partial f}{\partial w} \frac{\partial w}{\partial t} 

با استفاده از این قاعده زنجیری روش بازگشت به عقب را به این شکل دنبال می‌کنیم:

\delta_c = \frac{\partial Q}{\partial a_c}


a_c = \sum_p w_{pc}\times b_{pc}


b_c = \theta_c (a_c)


\delta_c = \frac{\partial Q}{\partial a_c} = \frac{\partial Q}{\partial b_c}\frac{\partial b_c}{\partial a_c} = \frac{\partial Q}{\partial b_c} \times \acute{\theta}_c (a_c) = \left(\sum_n \frac{\partial Q}{\partial a_n}\frac{\partial a_n}{\partial b_c}\right) \times \acute{\theta}_c (a_c) = \left(\sum_n w_{cn}\delta_n \right) \times \acute{\theta}_c (a_c)


\frac{\partial Q}{\partial w_{pc}} = \frac {\partial Q}{\partial a_c} \frac {\partial a_c}{\partial w_{pc}}  = \delta_c b_p 

همان‌طور که در خط پیشین دیدیم برای به‌دست آوردن گرادیان نسبت به w_{pc}
 به دو مقدار نیاز داریم ورودی به سلول عصبی c
 از سلول عصبی p
 که همان b_p
 است و راحت به‌دست می‌آید و \delta_c
 که از روش بازگشتی به‌دست می‌آید و بستگی به آن \delta
‌هایی لابه بعد دارد که سلول c
به آن‌ها وصل است، به‌طور دقیقتر \delta_c = \left(\sum_n w_{cn}\delta_n \right) \times \acute{\theta}_c (a_c)
.

روش بازگشتی برای به‌دست آوردن \delta
‌ها به این شکل کار می‌کند که ابتدا \delta
 را برای سلول‌های لایه خروجی حساب می‌کنیم، و بعد لایه‌ها را به نوبت پایین می‌روم و برای هر سلول \delta
 آن را با ترکیت \delta
‌های لایه‌های بالایی آن طبق فرمول حساب می‌کنیم. محاسبه کردن \delta
 برای لایه خروجی آسان است و مستقیماً با مشتق گرفتن از Q
 به‌دست می‌آید.

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

### پیدا کردن مشتق وزن‌ها نسبت به تابع هزینه
[جایگزین=[نمایشی از یک نورون در شبکه عصبی مصنوعی]|بندانگشتی|نمایشی از یک نورون در شبکه عصبی مصنوعی|257x257پیکسل](https://fa.wikipedia.org/wiki/%D9%BE%D8%B1%D9%88%D9%86%D8%AF%D9%87:ArtificialNeuronModel_english.png)
به کمک قاعده زنجیره‌ای می‌توانیم مشتق تابع هزینه را نسبت به هر یک از وزن‌های شبکه عصبی (w_{ij}) به‌دست بیاوریم: = \frac{\partial E}{\partial o_{j}} \frac{\partial o_{j}}{\partial w_{ij}}
= \frac{\partial E}{\partial o_j} \frac{\partial o_j}{\partial\text{net}_j} \frac{\partial \text{net}_j}{\partial w_{ij}}|}}حال سعی می‌کنیم آخرین کسر سمت راست را ساده کنیم (در \text{net}_j  فقط همان ترکیب خطی خروجی نورون فعلی به w_{ij} وابسته است) : = \frac{\partial}{\partial w_{ij}} \left(\sum_{k=1}^n w_{kj} o_k\right) = \frac{\partial}{\partial w_{ij}}  w_{ij} o_i= o_i.|}}می‌دانیم مشتق خروجی نورون j نسبت به ورودی‌های آن همان مشتق جزئی نسبت به تابع فعال‌سازی است. در واقع دلیل اصلی این‌که تابع فعال‌سازی باید مشتق‌پذیر باشد، محاسبه همین مشتق است:برای مثال در حالتی که تابع فعال سازی، تابع لجستیک باشد:

\frac{\partial o_j}{\partial\text{net}_j} = \frac {\partial}{\partial \text{net}_j} \varphi(\text{net}_j) = \varphi(\text{net}_j)(1-\varphi(\text{net}_j)) = o_j(1-o_j)

حال طبق معادله ۱ یکی یکی بخش‌های مختلف را محاسبه می‌کنیم. کسر اول (مانند آنچه در زیر آمده‌است) با مشخص بودن خروجی و تابع هزینه به راحتی قابل محاسبه است.برای مثال اگر تابع هزینه همان مربعات خطاها باشد،

\frac{\partial E}{\partial o_j} = \frac{\partial E}{\partial y} = \frac{\partial}{\partial y} \frac{1}{2}(t - y)^2 = y - t 

با فرض اینکه E تابعی از همه نورون‌هایی است که از نورون j ام به آن‌ها یال دارد (L = \{u, v, \dots, w\}):

\frac{\partial E(o_j)}{\partial o_j} = \frac{\partial E(\mathrm{net}_u, \text{net}_v, \dots, \mathrm{net}_w)}{\partial o_j}

حال با گرفتن مشتق نسبت به o_j فرم بازگشتی زیر به‌دست می‌آید که همان شکل کلی پس‌انتشار است.
با استفاده از معادله ۱ تا ۵ و حذف بخش‌های مشترک، می‌توانیم مشتق E را نسبت به وزن دلخواه w_{ij} محاسبه کنیم.

: \frac{\partial E}{\partial w_{ij}}
= \frac{\partial E}{\partial o_{j}} \frac{\partial o_{j}}{\partial \text{net}_{j}} \frac{\partial \text{net}_{j}}{\partial w_{ij}}

=  \frac{\partial E}{\partial o_{j}} \frac{\partial o_{j}}{\partial \text{net}_{j}} o_i
:  \frac{\partial E}{\partial w_{ij}} =  o_i \delta_j

که در آن تابع دلتا به صورت زیر است:

\delta_j
=
        \frac{\partial E}{\partial o_j} \frac{\partial o_j}{\partial\text{net}_j}
    = \begin{cases}
            \frac{\partial L(o_j, t)}{\partial o_j} \frac {d \varphi(\text{net}_j)}{d \text{net}_j}                    & \text{if } j \text{ is an output neuron,}\\
            (\sum_{\ell\in L} w_{j \ell}
                            \delta_\ell)\frac {d \varphi(\text{net}_j)}{d \text{net}_j}   & \text{if } j \text{ is an inner neuron.}
\end{cases}

برای مثال اگر \varphi تابع لجستیک باشد:

\delta_j = \frac{\partial E}{\partial o_j} \frac{\partial o_j}{\partial\text{net}_j} = \begin{cases}
(o_j-t_j)o_j(1-o_{j}) & \text{if } j \text{ is an output neuron,}\\
(\sum_{\ell\in L} w_{j \ell} \delta_\ell)o_j(1-o_j)  & \text{if } j \text{ is an inner neuron.}
\end{cases} در نهایت فرم تغییرات وزن به صورت زیر است:

 \Delta w_{ij} = - \eta \frac{\partial E}{\partial w_{ij}} = - \eta o_i \delta_j

## جستارهای وابسته
* شبکه عصبی مصنوعی
* شبکه عصبی
* آدابوست
* بیش‌برازش
* گرادیان کاهشی تصادفی
* قاعده زنجیری

## منابع

رده:الگوریتم‌های یادگیری ماشین
رده:شبکه‌های عصبی مصنوعی