چگونه يك شبكه عصبي هوشمند بسازيم؟
مثالي از برنامهنويسي شيءگرا در شبكههاي عصبي و هوش مصنوعي
اشاره :
قدرت و سرعت كامپيوترهاي امروزي به راستي شگفت انگيز است؛ زيرا كامپيوترهاي قدرتمند ميتوانند ميليونها عمليات را در كمتر از يك ثانيه انجام دهند. شايد آرزوي بسياري از ما انسانها اين باشد كه اي كاش ميشد ما نيز مانند اين دستگاهها كارهاي خود را با آن سرعت انجام ميداديم، ولي اين نكته را نبايد ناديده بگيريم كه كارهايي هستند كه ما ميتوانيم آنها را به آساني و در كمترين زمان ممكن انجام دهيم، ولي قويترين كامپيوترهاي امروزي نيز نميتوانند آنها را انجام دهند و آن قدرت تفكري است كه مغز ما انسانها دارد. حال تصور كنيد كه دستگاهي وجود داشته باشد كه علاوه بر قدرت محاسبه و انجام كارهاي فراوان در مدت زمان كوتاه، قدرت تفكر نيز داشته باشد يا به قول معروف هوشمند باشد!اين تصور در حقيقت هدف فناوري هوش مصنوعي يا Artificial Intelligence) AI) است. يكي از راهحلهاي تحقق اين هدف، شبكههاي عصبي است. شبكههاي عصبي در واقع از شبكههاي عصبي و سيستم عصبي انسان الگوبرداري ميكنند. برخي از محققان براين باورند كه هوش مصنوعي و شبكههاي عصبي دو راهحل متفاوت و در دو جهت مختلف هستند، ولي اين باور را نميتوان كاملاً صحيح دانست؛ چرا كه در حقيقت علم شبكههاي عصبي و هوشمصنوعي وابسته به هم هستند. بدينمعنا كه قبل از اينكه Symbolها بتوانند توسط هوش مصنوعي شناسايي شوند، بايد مراحلي طي شود. مثلاً تصور كنيد كه Symbolهايي مانند خانه، انسان يا ميز وجود دارند. قبل از اين كه AI بتواند هر كدام از اين Symbolها را شناسايي كند، بايد از تواناييها و صفات هر كدام از اينها اطلاع كامل حاصل كند. مثلاً تصور كنيد كه يك روبات كه هوش مصنوعي دارد، يك انسان را ميبيند، ولي از كجا ميفهمد كه اين جسم يك انسان است؟ مثلاً بر اساس مشخصاتي مثل داشتن دو پا، دست، صورت، دهان و قدرت تكلم. اما شما وقتي يك انسان ديگر را ميبينيد، نيازي نداريد كه اول تعداد پاهاي او را بشماريد و بعد بگوييد كه اين جسم، انسان است. مغز انسانها ميتواند با ديدن يك جسم فقط براي يك بار ياد بگيرد و اگر مجدداً آن جسم را مشاهده كرد، ميتواند سريع تشخيص دهد و قسمتهاي مختلف مغز ميتوانند به صورت همزمان فعاليت كنند و از اطلاعات درون مغز استفاده نمايند. شبكههاي عصبي در بسياري از پروژههاي هوش مصنوعي به كار گرفته ميشود. مثلاً براي برنامههاي تشخيص و الگوبرداري، شناسايي تصوير و كاراكتر، روباتها و برنامههاي فيلترينگ اطلاعات. اين شبكهها امروزه حتي در اتومبيلهاي بيسرنشين نيز كاربرد دارد. به طوريكه با ديدن و بررسي رانندگي انسانها، ميتوانند رانندگي كنند. در اين مقاله اصول شبكههاي عصبي در برنامهنويسي شيءگرا مورد بررسي قرار ميگيرد. با استفاده از زبان #C و انجام دادن عمليات X-OR ساده ميتوانيد اولين برنامه ساده هوش مصنوعي خود را بنويسيد. لازم به ذكر است كه مثالي كه در اين مقاله از آن استفاده شده، از مقاله Matthew Cochran (سي شارپ كورنر) اقتباس شده است.
براي يادگيري بيشتر شبكههاي عصبي بهتر است اين شبكهها را با شبكههاي عصبي مغز خود مقايسه كنيم. در حقيقت هر نورون در مغز ما يك ورودي دارد كه از نورونهاي ديگر ميآيد و يك خروجي كه به نورون يا نورونهاي بعدي ميرود.
براي اينكه بتوانيم اين كار را دقيقاً در برنامه خود شبيهسازي كنيم، لازم است يك كلاس مانند شكل 1 قسمت اول طراحي كنيم كه ضمن داشتن مشخصههاي خاص، يك خروجي داشته باشد. البته همانطور كه در قسمت دوم نيز مشاهده ميكنيد (شكل 1)، هر نورون ميتواند داري چندين ورودي نيز باشد.
همانطور كه در شكل 1 مشاهده ميكنيد، نورونها به صورت گروهي لايهبندي ميشوند.
وقتي سيگنال يا پالسي به يك لايه ارسال ميشود، اين سيگنال از لايه بالايي شروع به فعاليت ميكند و توسط نورونهاي آن لايه بررسي و اصلاح ميگردد. در حقيقت هر نورون قدرت سيگنال را بالا ميبرد و آن پالس را به لايه بعدي انتقال ميدهد. (شكل 2)
حال كه تقريباً با كار يك لايه عصبي آشنا شديد، ميتوانيم شبكههاي پيچيدهتر را مورد بررسي قرار دهيم. براي اين كار حداقل به سه گروه از نورونهايي كه در شكل 2 ميبينيد، نياز داريم.
همانطور كه در شكل 3 مشاهده ميكنيد، اين شبكه داراي سه لايه است. لايه 1 يا لايه بالايي اين شبكه كه در حقيقت لايه ورودي است، پارامترهاي پالس را تنظيم ميكند و اين مقادير را همراه سيگنال يا پالس به لايههاي بعدي پاس ميدهد، ولي نورونهاي لايه 3 يا لايه خروجي كه در پايينترين سطح شبكه قرار دارد، هيچ سيگنالي را به لايه ديگري نميفرستند و در واقع فقط خروجي دارند.
حال قسمت اصلي كار شبكه فرا ميرسد؛ يعني آموختن به شبكه عصبي. ب
راي اينكه به شبكه عصبي موجود توانايي آموختن بدهيم، بعد از اينكه سيگنال از لايه اول شبكه به لايه پاييني شبكه ميرود، بايد اطلاعات هر نورون را كه روي سيگنال ما اثر ميگذارد، بروزآوري و اصلاح كنيم. اين رويه را به اصطلاح BP يا Back Propagation ميگويند.
در حقيقت با اين كار يعني مقايسه خروجياي كه خودمان محاسبه كردهايم با خروجي شبكه، ميتوانيم مقدار اشتباهاتي كه شبكه ما انجام ميدهد را به دست آوريم.
مثلاً تصور كنيد كه در يك سلول نورون در لايه آخر شبكه يا لايه خروجي اشتباهي داريم، هر نورون در واقع ركورد تمامي نورونهايي كه سيگنال از آن عبور ميكند را نگهداري مينمايد و ميداند كه كدام يك از نورونهاي قبلي يا به اصطلاح نورونهاي والد باعث اين اشتباه ميشوند.
همچنين ميدانيم كه هر كدام از اين نورونهاي شبكه يك مقدار اشتباه را محاسبه كردهاند و از اين طريق شبكه ما ميتواند ياد بگيرد و اگر مقدار ديگري نيز به آن داده شد، ميتواند توانايي محاسبه داشته باشد.
حال كه كمي در مورد شبكههاي عصبي صحبت كرديم، ميتوانيم برنامه سيشارپ خود را شروع كنيم. اولين كاري كه بايد انجام دهيم، ايجاد يك اينترفيس ساده است كه بعداً آن را عملياتي ميكنيم. همانطور كه در كدهاي شكل 4 ميبينيد، يك اينترفيس به نام Interface 1 ساختهايم. اين اينترفيس در واقع حركت يك سيگنال را در شبكه ما تعريف ميكند. وقتي اين كار را انجام داديم، به يك اينترفيس ديگر نياز داريم كه ورودي نورون را تعريف كند. براي اين كار بايد از يك دايركتوري عمومي استفاده كنيم. اين دايركتوري كليد سيگنال يا همان پالس است و خروجي يك كلاس است كه پارامتر Weight پالس را مشخص ميكند. (كدهاي شكل 5).
حال نوبت به نوشتن كدهاي كلاس اصلي برنامه ميرسد. نام اين كلاس را NeuralFactor ميناميم (كدهاي شكل 6).
در كدهاي اين كلاس ميبينيد كه دو مقدار Private به نامهاي Mywight و MyDelta نوع double و جود دارد. كار اصلي اين كلاس، دادن و گرفتن مقادير نورون است و در واقع تغييرات در ورودي نورونها و وزن آنها را نگهداري ميكند. حال ميتوانيم يك اينترفيس براي خود نورون درست كنيم. از آن جايي كه هر نورون هم مشخصات سيگنال و هم Receptor را دارد، بايد از دو اينترفيسي كه قبلاً در شكل هاي 5 و 4 توضيح داده شد، استفاده كند. همچنين هر نورون چيزي مانند يك ورودي ديگر نيز دارد كه به آن Bias ميگوييم.
اضافه براين، بايد دو متد براي انجام كار در شبكه درست كنيم: يكي براي انجام Pulse و ديگري براي يادگيري نورون. كدهاي شكل 7 تمامي اين اينترفيس را مشخص كرده است.
در قسمت پايين اين كدها يك اينترفيس ديگر به نام INeuralLayer مشاهده ميكنيد. اين اينترفيس براي لايههاي نورونهاي شبكه است و براي انتقال پالس از يك لايه به لايه ديگر و توانايي يادگيري در يك لايه به كار گرفته ميشود. و بالاخره آخرين اينترفيس ما خود شبكه را تعريف ميكند. از تواناييهاي اين اينترفيس ميتوان، قابليت نگهداري لايههاي شبكه، انتقال پالس و قابليت يادگيري شبكه را نام برد.
اكنون كه با اينترفيسهاي اين شبكه ساده آشنا شديد، نوبت به ساختن اجزاي اصلي برنامه ميرسد. اولين كاري كه بايد در اين قسمت انجام دهيم، ساختن كلاس اصلي نورون است كه بايد آن را بر اساس اينترفيسهايي كه ساختهايم، درست كنيم. شكل 8 ساختار اصلي اين كلاس را نشان ميدهد.
همانطور كه در اين شكل مشاهده مينماييد، اين كلاس تعدادي متغير و چندين متد دارد. در اين كلاس دو متد اصلي وجود دارد: متد Sigmoid و متد Pulse كدهاي شكل 9 اين دو متد را نشان ميدهد.
اگر كمي به كدهاي شكل 9 و متد Pulse دقت كنيد، متوجه ميشويد كه اين متد جمع هر ورودي يا هر خروجي كه به نورون داده ميشود را دريافت ميكند و در Weight مربوطه كه در دايركتوري است ضرب ميكند و آخرين خروجي آخرين را به متد Sigmoid انتقال ميدهد و در نتيجه خروجي آخر ما عددي بين 0 و 1 خواهد بود.
حال دو كلاس مهم از اين شبكه باقيمانده است: اولين كلاس، كلاس اصلي شبكه يا NeuralNet است و ديگريNeuralLayer، كلاس لايههاي شبكه ما است. اين دو كلاس در شكل 10 به صورت مشخص نشان داده شده است، اما نكته بسيار مهم اين است كه كلاس NuralLayer در حقيقت مسئول نگهداري نورونهاي انتقالدهنده يا فراخوانكننده متد Pulse است.
کلاس اصلي شبکه
کلاس لايههاي شبکه
در اين كلاس از فهرست نورونها استفاده شده است و اين كلاس در اصل نورونها را در خود جا ميدهد. در اين كلاس دو متد كه هيچ مقدار برگشتي ندارند، به نامهاي Pulse و ApplyLearning وجود دارد. اين متدها در حقيقت كار فرستادن پالس و يادگيري لايهها را به عهده دارند. كدهاي شكل 11 اين دو متد را نشان ميدهد.
كلاس NeuralNet (شكل 12) همانطور كه قبلاً توضيح داده شد، يكي از مهمترين كلاسهاي برنامه ما است. در اين كلاس سه متد بسيار مهم وجود دارد: Initialize ،Train و BackProgation متد Initialize در واقع شبكه ما و كامپوننتهاي آن را آماده ميكند. اين متد در واقع متد Factory ما است. در اين متد مقادير عددي نورونهاي ورودي، نورونهاي مخفي و نورونهاي خارجي مشخص ميگردند.
متد BackProgation يكي ديگر از متدهاي اين كلاس است. اين متد ابتدا خطاهاي خروجي نورونها را با محاسبه اختلاف عددي بين مقدار مورد انتظار ما و خروجي نورونها محاسبه ميكند و وقتي كه خروجي همه نورونها بروز گرديد، اين متد خطاهاي نورونهاي پنهان را نيز محاسبه ميكند.
وقتي اين متد توسط برنامه انجام شد، برنامه با استفاده از متد، ()Train و با استفاده از خروجيهاي قبلي ميتواند توانايي يادگيري داشته باشد.
اگر بخواهيم شبكه خود را آموزش دهيم كه عمليات X-OR را انجام دهد، بايد ابتدا يك شبكه بسازيم كه دو نورون ورودي، دو نورون پنهان و يك نورون خروجي داشته باشد. مثلاً ميتوانيم شبكه خود را طوري آموزش دهيم كه بتواند عمليات مشخصشده در جدول 1 را انجام دهد:
كل 13 روند اجرايي برنامه را نشان ميدهد. ميتوانيد سورس كدهاي اين برنامه را از قسمت دريافت فايل سايت ماهنامه شبكه دريافت كنيد و قدم به قدم و با استفاده از راهنماييهايي كه در آن نوشته شده است، تغييراتي در كدها انجام دهيد و اولين برنامه هوش مصنوعي خود را بنوسيد.
منابع:
Neural network - Wikipedia, the free encyclopedia
C#, Visual Studio 2008, Silverlight, ASP.NET, WPF, WCF, WF, and Windows Vista Community
lss/NNIntro/InvSlides.htmlد
Computing Science and Mathematics, University of Stirling
NeuroSolutions: What is a Neural Network?