ساخت شبکه عصبی – راهنمای مقدماتی
![ساخت شبکه عصبی – راهنمای مقدماتی](https://blog.faradars.org/wp-content/uploads/2019/05/Building-Your-First-Neural-Network-150x150.jpg)
![ساخت شبکه عصبی – راهنمای مقدماتی](https://blog.faradars.org/wp-content/uploads/2019/05/Building-Your-First-Neural-Network.jpg)
در این نوشته قصد داریم پرده از ابهامات شبکههای عصبی برداریم، همراه با شما اقدام به ساخت شبکه عصبی کنیم و با آنچه در پشت صحنه اتفاق میافتد آشنا شویم.
شبکه عصبی مصنوعی چیست؟
شبکههای عصبی (مصنوعی) به دلیل شباهت نسبیشان به شبکههای عصبی در مغز به این صورت نامگذاری شدهاند و شامل اتصالهایی از جنس نورونهای مصنوعی هستند. این شبکهها از طریق اتصالهای بین نورونها که سیناپس نام دارد فعالیت میکنند. سیناپسها اطلاعات را از یک نورون به نورون دیگر ارسال میکنند. یک نورون میتواند اطلاعات را از یک نورون ورودی بگیرد و سپس آن اطلاعات را به همه نورونهای دیگر که به نورون مزبور وصل هستند، بفرستد. این وضعیت در حالتی که شبکه خود را بسازیم و فعالیت آن را در عمل مشاهده کنیم، معنی بیشتری خواهد یافت.
مبانی شبکه عصبی
جهت برآورده ساختن مقاصد آموزشی این مقاله، خواننده باید درکی مقدماتی از برخی مباحث ابتدایی ریاضیات و آمار نیز داشته باشد. به علاوه اگر میخواهید مدلها را روی سیستم خود اجرا کنید (که البته ضروری نیست)، میبایست همه کتابخانههای مورد نیاز را به درستی نصب کرده باشید و آشنایی متوسطی با پایتون داشته باشید. برای اجرای همه مثالهای این مقاله، کاربر نیازمند کتابخانههای Pandas Numpy ،Matplotlib ،Scikit-Learn ،TensorFlow و Keras خواهد بود.
اگر تاکنون به موضوع شبکههای عصبی پرداخته باشید احتمالاً با مدلی مانند تصویر زیر مواجه شدهاید، اما ممکن است معنای آن را درک نکرده باشید. ما در این مقاله قصد داریم این جعبه سیاه را باز کنیم و سازوکار درونی این مدل را به زبان ساده توضیح دهیم.
نکته: اگر به عملکرد پشت صحنه مدلهای شبکه عصبی مصنوعی علاقهای ندارید، میتوانید مستقیماً به بخش کدهای نمونه در انتهای مقاله مراجعه کنید.
مدلی که ما قصد داریم در این مقاله پیادهسازی کنیم تقریباً به صورت زیر است:
اندازه لایههای مختلف
همان طور که میبینید، شبکه فوق دارای یک لایه ورودی، یک لایه پنهان منفرد و یک لایه خروجی است. البته اندازه هر لایه دلخواه نیست. برخی قواعد استاندارد وجود دارند که باید هنگام تصمیمگیری در مورد تعداد نورونها (دایرههای موجود در هر لایه) در هر لایه، آنها را رعایت کنید. در واقع ما قصد داریم با نتیجهگیری از مدل اصلی فوق تغییراتی بر مبنای نیازهایمان در شبکه ایجاد کنیم. ما به جای 3 نورون ورودی از 4 نورون استفاده میکنیم، به جای 4 نورون در لایه پنهان از 8 نورون استفاده خواهیم کرد و به جای 1 نورون در بخش نورونهای خروجی از 3 نورون استفاده خواهیم کرد. همگی این موارد تصمیمهای حساب شدهای هستند و در ادامه در مورد فرایند این تصمیمگیری بیشتر توضیح میدهیم.
اندازه لایه ورودی ما بر اساس تعداد قابلیتهایی که در مجموعه دادهمان وجود دارد، تعیین میشود. برای نمونه اگر بخواهیم، مجموعه داده سنتی Iris را طبقهبندی بکنیم، تنها آن تعداد از نورونهای ورودی را در مدل خود میگنجانیم که ویژگیهای مطلوب ما را داشته باشند. در مجموعه داده Iris این وضعیت به معنی استفاده از همه ویژگیهای رایج مجموعه داده و گنجاندن «طول کاسبرگ» (sepal length)، «عرض کاسبرگ» (sepal width)، «طول گلبرگ» (petal length) و «عرض گلبرگ» (petal width) است.
![شبکه عصبی مصنوعی](https://blog.faradars.org/wp-content/uploads/2019/05/1_x50quZUZIfcrTORTgSHbhw-1.png)
در نهایت، لایههای پنهان در معرض آزمونوخطا قرار میگیرند. لایههای پنهان موضوع مورد نزاعی هستند که کوهی از پژوهش در پس آنها قرار دارد. به طور کلی یک لایه پنهان منفرد کافی است. 0 لایه پنهان تنها در مورد موقعیتهایی مناسب است که به طور خطی قابل جداسازی باشند. 1 لایه پنهان امکان نگاشت از یک فضای متناهی به فضای دیگر را میدهد. 2 لایه پنهان برای موقعیتهایی مناسب است که شامل کرانهای تصمیم دلخواه باشند. اصطلاح «یادگیری عمیق» (Deep Learning) برگرفته از میزان عمیق بودن مدل یعنی تعداد لایههای پنهان که مدل به کار میگیرد است.
تعداد نورونهای هر لایه
تعداد نورونهایی که در لایه-(های) پنهان وجود دارند نیز در معرض آزمونوخطا است؛ اما برخی راهنماهای متداول مانند تصویر زیر برای انتخاب تعداد نورونها در لایه پنهان وجود دارد:
![شبکه عصبی](https://blog.faradars.org/wp-content/uploads/2019/05/1_ykbtclDP86hRkJYSKSA2Gg-1.png)
در معادله فوق Nh تعداد نورونهای موجود در لایه پنهان است، Ns تعداد نمونههای موجود در دادههای آموزشی، آلفا عامل مقیاسبندی، Ni تعداد نورونهای ورودی و No تعداد نورونهای خروجی است.
این یک رویکرد کاملاً مقدماتی است و برای این که دیدی عمیق از تعداد لایهها و نورونهای هر لایه داشته باشید، توصیه میکنیم این مقاله (+) را مطالعه کنید. کاربران پیشرفته باید از روشهای ظریفتر برای انتخاب تعداد نورونها در لایه پنهان استفاده کنند.
تعداد نورونها در لایه خروجی بسته به نتیجه مورد نظر ما متفاوت خواهد بود. در صورتی که یک رگرسور استفاده شود، تعداد نورونها یک خواهد بود. در صورتی که از برچسبهای گره برای کلاس استفاده میکنید (softmax) باید از بیش از یک نورون خروجی استفاده کنید. اگر از softmax استفاده نمیکنید همچنان میتوانید از یک نورون برای طبقهبندی استفاده کنید. ما در این مقاله قصد داریم از softmax استفاده کنیم تا عملکرد آن را روی مجموعه داده Iris مورد بررسی قرار دهیم. در مجموعه داده Iris میخواهیم بررسی کنیم که آیا یک مشاهده منفرد، کدام یک از گونههای زنبق (Virginica ،Versicolor یا Setosa) است. در حالتی که بخواهیم لایه خروجی ما شامل 3 نورون باشد، 3 نورون مجموعاً برای 3 کلاس وجود خواهد داشت.
تابع softmax
در ادامه softmax را به اختصار بررسی میکنیم تا بفهمیم چرا چنین کاربرد رایجی در تابع فعالسازی لایه خروجی یافته است. softmax برای روشهای طبقهبندی چند کلاسی مختلف مورد استفاده قرار میگیرد و شبکههای عصبی تنها یکی از این کاربردهای متداول هستند.
![شبکه عصبی](https://blog.faradars.org/wp-content/uploads/2019/05/1_q1cQfZJbDT7okF3kct6bAw.png)
softmax در هسته مرکزی خود امکان سرکوب مقادیر پایینتر و برجستهسازی مقادیر بالاتر را میدهد. ما از softmax به این جهت استفاده میکنیم که خروجی تابع به ما امکان میدهد که یک توزیع احتمال را روی برآیندهای متفاوت و متنوع بررسی کنیم. بدیهی است که این وضعیت بسیار قدرتمند است، زیرا به ما امکان میدهد که بسیاری از مسائل پیچیده یادگیری ماشین و یادگیری عمیق را از طریق طبقهبندی چند کلاسی حل کنیم. این امر موجب میشود که softmax برای استفاده روی مجموعه داده Iris مناسب باشد. در مورد کاربردهایی مانند طبقهبندی دودویی میبایست به چیزی مانند sigmoid مراجعه کنیم، زیرا sigmoid یک حالت خاص از softmax است که در آن تعداد کلاسها به دو مورد کاهش یافته است.
ما در لایه پنهان خود ReLU را به عنوان تابع فعالسازی انتخاب کردهایم. ReLU پراستفادهترین تابع در لایه پنهان است و برای این مسئله نیز دلایل خوبی وجود دارد. ReLU به دلیل ماهیت ذاتی خود، نسبت به اغلب گزینههای رایج یادگیری سریعتری دارد. ReLU برای افرادی که سابقه تحصیل در رشته مهندسی برق دارند معنی بیشتری دارد، زیرا مفهومی مشابه مدار یکسوکننده دارد. در ReLU مؤلفههای منفی برابر با 0 تنظیم میشوند. شکل تابع ReLU مانند تصویر زیر است:
![اولین شبکه عصبی](https://blog.faradars.org/wp-content/uploads/2019/05/1_njuH4XVXf-l9pR_RorUOrA.png)
برای دستیابی به درک عمیقتری از تابعهای فعالسازی و آشنایی با گزینههای مختلفی که در این زمینه برای ساخت شبکههای عصبی وجود دارند، میتوانید به این راهنما (+) مراجعه کنید.
بهینهساز
اینک نوبت به انتخاب یک «بهینهساز» (optimizer) رسیده است. ما در این مقاله Adam را انتخاب میکنیم، زیرا محبوبیت بالایی دارد و رو سیستمهای با حافظه کم، کارایی بالایی دارد. احتمالاً در مورد «گرادیان کاهشی تصادفی» (Stochastic Gradient Descent) چیزهایی شنیدهاید. Adam به چند دلیل کارایی بالاتری دارد، نخست این که برخلاف گرادیان کاهشی تصادفی، از پارامتر نرخ یادگیری با استفاده از «میانگین متحرک نمایی» استفاده میکند. Adam در سراسر فرایند یادگیری، از میانگین گشتاور دوم گرادیان برای نرخ یادگیری استفاده میکند.
اگر بخواهیم مواردی که تا به اینجا طراحی کردهایم، جمعبندی کنیم، به صورت زیر خواهد بود:
- 1 لایه ورودی
- 1 لایه پنهان
- 1 لایه خروجی
- 4 نورون ورودی برای 4 ویژگی
- 8 نورون در لایه پنهان که متناظر با تعداد نورونهای ورودی، نورونهای خروجی و اندازه مجموعه داده هستند.
- و در نهایت 3 نورون در لایه خروجی برای 3 کلاس مطلوب داریم.
تابع فعالسازی
همچنین تابعهای فعالسازی خود را بدین صورت انتخاب کردهایم که از ReLU محبوب برای لایه پنهان و از softmax برای لایه خروجی استفاده میکنیم.
در مورد بهینهساز نیز از الگوریتم Adam استفاده خواهیم کرد:
1def baseline_model():
2 model = Sequential()
3 model.add(Dense(8, input_dim=4, activation='relu'))
4 model.add(Dense(3, activation='softmax'))
5 model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
6 return model
تابع فوق مدل مبنای ما را میسازد. ما میتوانیم این تابع را هر زمان که میخواهیم یک مدل جدید بسازیم فراخوانی کنیم. تابع فوق شبکه دقیقی که قبلاً در مقاله توصیف کردیم را میسازد. استدلال ما برای این تصمیمگیریها نیز در بخش فوق توضیح داده شده است.
1model = baseline_model();
2model.fit(X,dummy_y,epochs=125,verbose=1)
3y_pred = model.predict_classes(X)
مقداردهی مدل
3 خط بعدی کد نیز به همین سادگی است. ابتدا یک مدل را مقداردهی کردهایم. سپس در ادامه مدل خود را با استفاده از مجموعه داده تمرینی Iris آموزش دادهایم. به این منظور ابتدا یک مقدار دلخواه از epoch-ها را انتخاب میکنیم و سپس مقدار verbose را برابر با 1 تعیین میکنیم، زیرا این وضعیت به ما امکان میدهد که ببینیم آیا تعداد انتخابی epoch-ها بیش از حد بالا است و موجب هدر رفتن زمان آموزش میشود یا نه.
در هر epoch کل مجموعه یک بار به سمت جلو و یک بار به سمت عقب از شبکه عصبی گذر میکند. این امر موجب بهروزرسانی وزنهای هر گذر میشود.
همان طور که میبینید دقت به میزان زیادی بهبود مییابد و پیرامون 150 epoch همگرا میشود. بر همین مبنا تعداد epoch را تنظیم میکنیم. در نهایت میتوانیم طبقهبندی را با استفاده از ویژگیهای مختلف روی مجموعه دادهها اجرا کنیم:
![اولین شبکه عصبی](https://blog.faradars.org/wp-content/uploads/2019/04/1_G8LWon6-70e-NBJe6frXdQ-1.png)
اگر این نوشته برای شما مفید بوده است، آموزشهای زیر نیز به شما پیشنهاد میشوند:
- مجموعه آموزشهای شبکههای عصبی مصنوعی
- مجموعه آموزشهای شبکههای عصبی مصنوعی در متلب
- مجموعه آموزشهای هوش مصنوعی
- ساخت شبکه عصبی (Neural Network) در پایتون — به زبان ساده
- شبکه عصبی پیچشی (Convolutional Neural Networks) — به زبان ساده
- ساخت شبکه های عصبی در نرم افزار R
==
لطفا برای انتشار مقالات مرتبط با ماشین لرنینگ حتما به مباحث آماری هم بپردازید، متوجه هستم که یادگیری و مطالعه بدون سورپروایزر یک متن حاوی فرمول های ریاضی ممکن است برای همگان آسان نباشد، اما مراجعه به همچین منابعی می تواند محقق را از اشتباهات مکرر بازدارد. برای مثال ای کاش در نگارش این متن به کتاب the elements of statistical learning از رابرت تیبشیرانی و هستی کمک گرفته میشد. جایی در متن که مدرس محترم از رگرسور صحبت فرمودند، در کتاب مذکور که قاعدتأ مبنای آماری شبکه عصبی در مبحث رگرسیون محسوب می شود، مطلب کاملا متفاوتی را ذکر شده. امیداورم فهم من هم از کتاب درست باشد اما رشته تحصیلی من آمار است و تا حدی به آموخته هایم از بابت آشنایی بیشتر با این علم, اطمینان دارم. سپاس فراوان از جناب لطفی که زحمت نگارش این مقاله ارزشمند را متقبل شده اند.