خانه / برنامه نویسی / پایتون / پیاده سازی شبکه عصبی بخش اول

پیاده سازی شبکه عصبی بخش اول

در این بخش قرار است بدون استفاده از هیچ کتابخونه ایی یک شبکه عصبی پیاده کنیم

در ادامه یک پیاده سازی ساده داریم و قرار است الگوریتم backpropagation را با پایتون پیاده کنیم

بعضی ها از من میپرسیدن که چگونه مقاله ام را پیاده کنم و من گفتم این بخش توضیح میدهم و در توییت میکنم @iamtrask.

نمونه کد یک شبکه معمولی 

نمونه از کدهای دیگه D, C++ , CUDA

شاید به نظر شما این مثال پیچیده باشد این به چند بخش تقسیم میکنم و توضیح میدهیم

بخش اول یک شبکه عصبی کوچک

یک شبکه عصبی که با استفاده از backpropagation آموزش دیده است ، سعی دارد با ورودی خروجی را پیش بینی کند

با توجه به سه ستون ورودی سعی کنید ستون خروجی را پیش بینی کنید. ما می توانیم این مسئله را با اندازه گیری ساده بین مقادیر ورودی و مقادیر خروجی حل کنیم.

  اگر این کار را کردیم ، می دیدیم که سمت چپ ستون ورودی کاملاً با خروجی ارتباط دارد.

Backpropagation ، در ساده ترین شکل ، آماری مانند این را برای ساختن یک مدل اندازه گیری می کند. بیایید به سمت راست پرش کنیم و از آن برای انجام این کار استفاده کنیم.

شبکه عصبی ۲ لایه 

متغییر تعاریف
X ماتریس داده ورودی که در آن هر ردیف یک مثال آموزشی است
y ماتریس مجموعه داده خروجی که در آن هر ردیف یک نمونه آموزش است
l0 لایه اول شبکه که توسط داده های ورودی مشخص شده است
l1 لایه دوم شبکه که ه آن لایه پنهان هم گفته می شود
syn0 اولین لایه وزن‌ها، Synapse ۰، l۰ را به L۱ متصل می‌کند.
* ضرب در مقطع ابتدایی ، بنابراین دو بردار با اندازه برابر در حال ضرب مقادیر مربوطه ۱ به ۱ هستند تا یک بردار نهایی با اندازه یکسان تولید شود.
تفریق ابتدایی ، بنابراین دو بردار با اندازه مساوی مقادیر مربوطه را از ۱ به ۱ کم می کنند تا یک بردار نهایی با اندازه یکسان تولید شود.
x.dot(y) اگر x و y بردار هستند ، این یک ضرب dot است. اگر هر دو ماتریس باشند ، ضرب ماتریس است. اگر فقط یک ماتریس باشد ، ضرب ماتریس بردار است.

همانطور که در “خروجی بعد از آموزش” می بینید ، کار می کند !!! قبل از توصیف فرآیندها ، توصیه می کنم با کد بازی کنید تا درک خوبی برای نحوه عملکرد آن به دست آورید.

شما هم میتونید از ipython  استفاده کنید و هم به صورت اسکریبتی اجرا کنید ولی من به شما توصیه میکنم با ipython اجرا کنید

  • متغییرl1 را دراولین اجرا و اخرین اجرا مقایسه کنید
  • تابع غیر خطی یا noline را چک کنید این همان چیزی است که به ما احتمال خروجی را می دهد
  • نحوه تغییر l1_error در زمان تکرار بررسی کنید
  • خط ۳۶ و ۳۹ بخشهای مهمی است که باید بهش توجه ویژه ایی داشته باشید

بیایید خط به خط برنامه بررسی کنیم

توصیه میکنم کدها در صفحه جدا باز کنید که زمانی که کد توضیح داده میشود کد را مشاهده کنید

خط اول

در خط اول اومدیم کتابخانه numpy را import  کردیم که برای ضرب ماتریس ها و فرایندهای جبر خطی استفاده میشود

خط چهارم

در خط چهارم تابع nonlinearity تعریف  این غیر خطی تابعی را به نام “سیگموئید” ترسیم می کند یک تابع سیگموئید هر مقدار را به یک مقدار بین ۰ تا ۱ نگاشت می کند. ما از آن برای تبدیل اعداد به احتمالات استفاده می کنیم. همچنین چندین ویژگی مطلوب دیگر برای آموزش شبکه های عصبی دارد.

خط پنجم

توجه داشته باشید که این تابع همچنین می‌تواند مشتق یک sigmoid را ایجاد کند (وقتی deriv = true).
یکی از ویژگی‌های مطلوب یک تابع sigmoid این است که خروجی آن می‌تواند برای ایجاد مشتق خود استفاده شود.
اگر با مشتقات ناآشنا هستید ، فقط به عنوان شیب عملکرد سیگموئید در یک نقطه معین فکر کنید (همانطور که در بالا مشاهده می کنید ، نقاط مختلف دارای شیب های مختلفی هستند). برای اطلاعات بیشتر در مورد مشتقات ، این آموزش مشتقات را از آکادمی خان بررسی کنید.
خط دهم
در این بخش اومدیم با کتابخانه numpy یک ماتریس تعریف کردیم که هر سطر میشود یک نمونه اموزشی  و هر ستون مربوط به یکی از گره های ورودی بنابراین ما سه ورودی به شبکه میدهیم و ۴ نمونه آموزشی داریم
خط شانزدهم
در این خط ما خروجی یا برچسبهای ورودی ها را مشخص میکنیم چون مجموعه داده های ما ۴ تا است پس برای هر مجموعه داده ما باید یک برچسب داشته باشیم
چون هر سطر می شود یک مجوعه داده پس این بردار ما باید ترانهاده شود یعنی اگر سطری است پس باید ستونی شود کتابخانه numpy یک متدی دارد تحت عنوان T که این کار را برای ما انجام می دهد
خط بیستم
در این خط اعداد تصادفی با استفاده از seed  به طور تصادفی توزیع خواهد شد، اما هر بار که شما آموزش خواهید دید، به طور تصادفی به طور تصادفی توزیع خواهند شد. این به شما کمک می‌کند ببینید چگونه تغییرات شما بر شبکه تاثیر می‌گذارند.
خارج از مقاله
کمی در مورد seed صحبت کنیم(از عدد حاصل بعنوان بذر برای تولید عدد “تصادفی” بعدی استفاده می شود. وقتی دانه را تنظیم می کنید (هر بار) ، هر بار همین کار را انجام می دهد ، همین تعداد را به شما می دهد.)
خط بیست و سوم
این ماتریس وزن ما برای این شبکه عصبی است. به این معنی “syn0” گفته می شود که “synapse صفر” باشد. از آنجا که ما فقط ۲ لایه (ورودی و خروجی) داریم ، برای اتصال آنها فقط به یک ماتریس وزن نیاز داریم. ابعاد آن (۳،۱) است زیرا ما ۳ ورودی و ۱ خروجی داریم. یک روش دیگر برای بررسی آن این است که l0 از اندازه ۳ و l1 از اندازه ۱ است. بنابراین ، ما می خواهیم هر گره را در l0 به هر گره در l1 وصل کنیم ، که به ماتریسی از ابعاد (۳،۱) نیاز دارد. 🙂
همچنین توجه داشته باشید که به طور تصادفی با میانگین صفر آغاز می شود. تئوری کاملاً کمی وجود دارد که در مورد وزن دهی اولیه صحبت کند و پیشنهاد دهند چه روشی وجود دارد . در حال حاضر ، فقط آن را به عنوان بهترین تمرین انجام دهید که ایده خوبی است که در ابتدای وزن میانگین صفر داشته باشید.
نکته دیگر این است که “شبکه عصبی” واقعاً فقط این ماتریس است. ما “لایه” l0 و l1 داریم اما آنها مقادیر گذرا براساس مجموعه داده هستند. ما آنها را ذخیره نمی کنیم. تمام یادگیری در ماتریس syn0 ذخیره می شود.
خط بیست پنجم
در این بخش شبکه ما شروع میکند به آموزش دیدن.حلقه چندین بار تکرار میشود تا وزنها و متغییر های شبکه را بهینه کند
خط بیست هشتم
از آنجا که اولین لایه ما ، l0 ، به سادگی داده های ما است. ما به صراحت در این مرحله آن را چنین توصیف می کنیم. به یاد داشته باشید که X شامل ۴ نمونه آموزش (ردیف) است. ما در این پیاده سازی می خواهیم همه آنها را همزمان انجام دهیم. این به آموزش “دسته کامل” معروف است. بنابراین ، ما ۴ ردیف مختلف L0 داریم ، اما می توانید در صورت تمایل ، به عنوان یک مثال آموزشی واحد فکر کنید. در این مرحله هیچ فرقی نمی کند. (اگر بخواهیم بدون تغییر کد ، می توانیم در ۱۰۰۰ یا ۱۰،۰۰۰ بارگذاری کنیم).
خط بیست نهم
این مرحله پیش‌بینی ماست. اساسا ما ابتدا اجازه می‌دهیم که شبکه “تلاش کند” تا خروجی داده‌شده ورودی را پیش‌بینی کند. سپس بررسی خواهیم کرد که چگونه انجام می‌دهد تا بتوانیم برای هر تکرار کمی بهتر عمل کنیم.
این خط شامل ۲ مرحله است. ماتریس اول، l۰ را با syn۰ تعریف می‌کند. دومی خروجی ما را از طریق تابع sigmoid عبور می‌دهد. ابعاد هر یک را در نظر بگیرید:

طبق تعریف ماتریس باید اندازه ها یکی باشد

از آنجا که ما در ۴ نمونه آموزشی بارگذاری کردیم، ۴ حدس برای پاسخ صحیح، یک ماتریس (۴*۱)به پایان رسید. هر خروجی متناظر با حدس شبکه برای یک ورودی خاص است. شاید به این دلیل باشد که ما می‌توانستیم “تعداد دلخواهی از نمونه‌های آموزشی را” داشته باشیم. ضرب ماتریس‌ها همچنان عملی خواهد بود.

خط سی و دوم

بنابراین ، با توجه به اینکه l1 برای هر ورودی یک “حدس” داشت. اکنون می توانیم با کم کردن جواب واقعی (y) از حدس (l1) ، چقدر خوب این کار را کرد. l1_error فقط یک بردار از اعداد مثبت و منفی است که میزان از دست رفته شبکه را نشان می دهد.

خظ سی و شش

در این خط اتفاقات زیادی می افتد بزارید کمی این بخش بیشتر توضیح دهیم و این قسمت به دو بخش تقسیم میکنیم

قسمت اول: مشتق

اگر l1 این سه نقطه را نشان دهد ، کد فوق شیب خطوط زیر را تولید می کند. توجه کنید که مقادیر بسیار بالا مانند x = 2.0 (نقطه سبز) و مقادیر بسیار کم مانند x = -1.0 (نقطه بنفش) دارای شیب های کم عمق هستند. بالاترین شیب شما می تواند در x = 0 (نقطه آبی) باشد. این نقش مهمی ایفا می کند. همچنین توجه داشته باشید که همه مشتقات بین ۰ تا ۱ هستند.

متن کامل: خطای وزنی مشتق شده

روش‌های ریاضی دقیق” بیشتر از “مشتق وزن گرا” وجود دارد، اما من فکر می‌کنم که این مشتق حدس را ثبت می‌کند. خطای L۱ یک ماتریس (۴,۱)است. nonlin (L۱، راست)یک ماتریس (۴,۱)را باز می‌گرداند. کاری که ما می‌کنیم این است که آن‌ها را “elementwise” ضرب کنیم. این تابع (۴,۱)، (L۱)را با مقادیر ضرب شده باز می‌گرداند.

هنگامی که ما “شیب‌های را با خطا ضرب می‌کنیم ، خطای پیش بینی اطمینان بالا را کاهش می دهیم.

باز هم به تصویر sigmoid نگاه کن! اگر شیب واقعا کم‌عمق بود (نزدیک به ۰ سپس شبکه دارای مقدار بسیار بالایی، یا مقدار بسیار کمی بود.
این به این معنی است که شبکه باید به روش دیگه یا سمت دیگر اعتماد دارد یعنی اینکه وقتی ما داریم با شبکه عصبی خط میکشیم خطاها نشون میده این خطاها چطوری کشیده شده
ما اینقدر این فرایند بروز رسانی وزنها انجام میدیهم که شبکه خطاهایش یا به ۰ برسد یا به نزدیک ۰
خط سی و نهم
اکنون ما آماده هستیم تا شبکه خود را به روز کنیم! بیایید نگاهی به یک مثال آموزشی واحد بیندازیم.
در این مثال آموزشی، همه ما برای به روز رسانی وزنه‌های خود، آماده ایم. اجازه دهید وزن چپ (۹.۵)را به روز کنیم.
weight_update = input_value * l1_delta
برای وزن بسیار چپ ، این مقدار ۱٫۰*the l1_delta  را چند برابر می کند. احتمالاً ، این مقدار ۹٫۵ با اندکی افزایش می یابد. چرا فقط یک مقدار کوچک؟ خوب ، پیش بینی در حال حاضر بسیار با اطمینان بود ، و پیش بینی تا حد زیادی درست بود. یک خطای کوچک و یک شیب کوچک به معنی یک به روزرسانی بسیار کوچک است. تمام وزن ها را در نظر بگیرید. با این وجود هر سه اندکی افزایش می یابد.
با این حال، از آنجایی که ما از پیکربندی “دسته‌ای کامل” استفاده می‌کنیم، ما مرحله بالا را بر روی هر چهار نمونه آموزشی انجام می‌دهیم. پس، خیلی بیشتر شبیه تصویر بالا است. بنابراین، خط ۳۹ چه کار می‌کند؟ محاسبه وزن هر وزن برای هر نمونه آموزشی را محاسبه می‌کند، آن‌ها را جمع‌بندی می‌کند و وزن‌ها را در یک خط ساده به روزرسانی می‌کند. با ضرب ماتریس‌ها بازی کنید و خواهید دید که این کار را انجام دهید!
موارد مصرف:
بنابراین ، اکنون که ما به چگونگی بروزرسانی شبکه نگاه کردیم ، بیایید به داده های آموزش خود نگاهی بیندازیم و تأمل کنیم. وقتی ورودی و خروجی هم ۱ باشد ، ما وزن بین آنها را افزایش می دهیم. وقتی یک ورودی ۱ است و یک خروجی ۰ است ، ما وزن بین آنها را کاهش می دهیم.
بنابراین، در چهار مثال آموزش زیر، وزن از ورودی اول به خروجی به طور پیوسته افزایش خواهد یافت و یا بدون تغییر باقی می‌ماند، در حالی که دو طرف دیگر خود را هم در حال افزایش و هم کاهش در مثال‌های آموزشی (لغو روند پیشرفت)می‌یابند. این پدیده چیزی است که باعث می‌شود شبکه ما براساس همبستگی بین ورودی و خروجی یاد بگیرد.

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *