ترجمة إنشاء شبكة عصبية بسيطةماذا سنفعل؟ سنحاول إنشاء شبكة عصبية بسيطة وصغيرة للغاية ، والتي
سنشرح لك
ونعلمك كيفية تمييز شيء ما. في الوقت نفسه ، لن ندخل في التاريخ والغابة الرياضية (من السهل جدًا العثور على هذه المعلومات) - بدلاً من ذلك ، سنحاول شرح المشكلة (وليس حقيقة أنها ستكون ممكنة) لك ولأنفسنا بالرسومات والتعليمات البرمجية.
ترتبط العديد من المصطلحات في الشبكات العصبية بعلم الأحياء ، لذلك دعونا نبدأ من البداية:

الدماغ شيء معقد ، ولكن يمكن أيضًا تقسيمه إلى عدة أجزاء وعمليات رئيسية:

يمكن أن يكون العامل المسبب
داخليًا أيضًا (على سبيل المثال ، صورة أو فكرة):

الآن دعونا نلقي نظرة على
الأجزاء الأساسية والمبسطة
من الدماغ:
يشبه الدماغ بشكل عام شبكة الكابل.العصبون هو الوحدة الرئيسية في حساب التفاضل والتكامل في الدماغ ، ويستقبل الإشارات الكيميائية للخلايا العصبية الأخرى ويعالجها ، واعتمادًا على عدد من العوامل ، إما أنه لا يفعل شيئًا ، أو يولد نبضًا كهربائيًا ، أو عمل الجهد ، والذي يرسل بعد ذلك إشارات إلى الخلايا العصبية
المتصلة المجاورة من خلال المشابك:

الأحلام ، والذكريات ، وحركات التنظيم الذاتي ، وردود الفعل ، وكل شيء تعتقده أو تفعله كله يرجع إلى هذه العملية: يعمل الملايين أو حتى مليارات الخلايا العصبية على مستويات مختلفة ويخلقون اتصالات تنشئ أنظمة فرعية متوازية مختلفة وتمثل
شبكة عصبية بيولوجية .
بالطبع ، هذه كلها تبسيطات وتعميمات ، ولكن بفضلها يمكننا وصف بسيط
الشبكة العصبية:

ووصفه رسميًا باستخدام الرسم البياني:

مطلوب بعض التوضيح هنا. الدوائر هي الخلايا العصبية ، والخطوط هي روابط بينها ،
وحتى لا تتعقد في هذه المرحلة ، فإن
العلاقة هي حركة مباشرة للمعلومات
من اليسار إلى اليمين . العصبون الأول نشط حاليًا وشيب. قمنا أيضًا بتعيين رقم له (1 - إذا كان يعمل ، 0 - إن لم يكن). تشير الأرقام بين الخلايا العصبية إلى
وزن الاتصال.
توضح الرسوم البيانية أعلاه اللحظة الزمنية للشبكة ، للحصول على عرض أكثر دقة ، تحتاج إلى تقسيمها إلى فترات زمنية:
لإنشاء الشبكة العصبية الخاصة بك ، تحتاج إلى فهم كيفية تأثير الأوزان على الخلايا العصبية وكيفية تدريب الخلايا العصبية. كمثال ، خذ أرنب (أرنب اختبار) وضعه في ظروف تجربة كلاسيكية.

عندما يتم توجيه تيار آمن من الهواء إليهم ، تومض الأرانب مثل البشر:

يمكن رسم نموذج السلوك هذا:

كما هو الحال في الرسم البياني السابق ، تظهر هذه الرسوم البيانية فقط اللحظة التي يشعر فيها الأرنب بنفس ، وبهذه الطريقة نقوم
بترميز الضربة كقيمة منطقية. بالإضافة إلى ذلك ، نحسب ما إذا كان يتم تشغيل العصبون الثاني بناءً على قيمة الوزن. إذا كان الرقم 1 ، يتم تشغيل العصبون الحسي ، ونومض ؛ إذا كان الوزن أقل من 1 ، فلا نومض: فالخلايا العصبية الثانية لها
حد 1.
نقدم عنصرًا آخر - إشارة صوتية آمنة:

يمكننا نمذجة مصلحة الأرنب على النحو التالي:

الفرق الرئيسي هو أن الوزن الآن هو
صفر ، لذلك لم نتلق أرنبًا وامضًا ، حسنًا ، في الوقت الحالي على الأقل. الآن علم الأرنب أن يرمش في الفريق ، يختلط
المهيجات (إشارة الصوت والتنفس):

من المهم أن تحدث هذه الأحداث في
فترات زمنية مختلفة ، في الرسوم البيانية ستبدو كما يلي:

الصوت نفسه لا يفعل شيئًا ، لكن تدفق الهواء لا يزال يجعل الأرنب يومض ، ونظهر ذلك من خلال الأوزان مضروبة في المنبهات (الحمراء).
يمكن التعبير عن السلوك المعقد بشكل تبسيط كتغيير تدريجي في الوزن بين الخلايا العصبية المتصلة بمرور الوقت.
لتدريب الأرنب ، كرر الخطوات:

بالنسبة للمحاولات الثلاث الأولى ، ستبدو المخططات كما يلي:

يرجى ملاحظة أن وزن التحفيز الصوتي ينمو بعد كل تكرار (مظلل باللون الأحمر) ، هذه القيمة الآن تعسفية - اخترنا 0.30 ، ولكن الرقم يمكن أن يكون أي شيء ، حتى سلبي. بعد التكرار الثالث ، لن تلاحظ تغيرًا في سلوك الأرنب ، ولكن بعد التكرار الرابع سيحدث شيء مفاجئ - سيتغير السلوك.

أزلنا التأثير من الهواء ، لكن الأرنب لا يزال يومض عندما سمع صفارة! يمكن أن يشرح هذا السلوك الأخير هذا السلوك:

قمنا بتدريب الأرنب على الاستجابة للصوت عن طريق الوميض.
في تجربة حقيقية من هذا النوع ، قد يتطلب الأمر أكثر من 60 تكرارًا لتحقيق النتيجة.الآن سنترك العالم البيولوجي للدماغ والأرانب ونحاول تكييف كل شيء
تعلمت إنشاء شبكة عصبية اصطناعية. أولاً ، دعنا نحاول القيام بمهمة بسيطة.
لنفترض أن لدينا آلة مزودة بأربعة أزرار تقدم الطعام عند الضغط على اليمين
الأزرار (جيدًا أو الطاقة إذا كنت روبوتًا). تتمثل المهمة في معرفة الزر الذي يمنح المكافأة:

يمكننا تصوير (تخطيطي) ما يفعله الزر عند النقر عليه كما يلي:

من الأفضل حل هذه المشكلة برمتها ، لذلك دعونا نلقي نظرة على جميع النتائج المحتملة ، بما في ذلك النتيجة الصحيحة:
اضغط على الزر الثالث للحصول على العشاء الخاص بك.لإعادة إنشاء شبكة عصبية في التعليمات البرمجية ، نحتاج أولاً إلى إنشاء نموذج أو رسم بياني يمكن ربط الشبكة به. فيما يلي رسم بياني واحد مناسب للمهمة ، بالإضافة إلى أنه يعرض نظيره البيولوجي جيدًا:

تتلقى هذه الشبكة العصبية فقط معلومات واردة - في هذه الحالة سيكون هناك تصور للضغط على الزر. علاوة على ذلك ، تستبدل الشبكة المعلومات الواردة بالأوزان وتقوم بعمل استنتاج بناءً على إضافة طبقة. يبدو الأمر مربكًا بعض الشيء ، ولكن دعنا نرى كيف يتم عرض الزر في نموذجنا:
لاحظ أن جميع الأوزان تساوي 0 ، لذا فإن الشبكة العصبية ، مثل الرضيع ، فارغة تمامًا ، ولكنها مترابطة تمامًا.وبالتالي ، نقارن الحدث الخارجي بطبقة الإدخال للشبكة العصبية ونحسب القيمة عند خرجها. قد تتوافق أو لا تتوافق مع الواقع ، ولكن في الوقت الحالي سنتجاهله ونبدأ في وصف المهمة بطريقة صديقة للكمبيوتر. لنبدأ بإدخال الأوزان (سنستخدم JavaScript):
var inputs = [0,1,0,0]; var weights = [0,0,0,0];
الخطوة التالية هي إنشاء دالة تجمع قيم المدخلات والأوزان وتحسب القيمة عند الإخراج:
function evaluateNeuralNetwork(inputVector, weightVector){ var result = 0; inputVector.forEach(function(inputValue, weightIndex) { layerValue = inputValue*weightVector[weightIndex]; result += layerValue; }); return (result.toFixed(2)); }
كما هو متوقع ، إذا قمنا بتشغيل هذا الرمز ، فسوف نحصل على نفس النتيجة كما في نموذجنا أو الرسم البياني ...
evaluateNeuralNetwork(inputs, weights);
مثال حي:
Neural Net 001 .
ستكون الخطوة التالية في تحسين شبكتنا العصبية طريقة للتحقق من قيم المخرجات أو النتائج الخاصة بها مقارنة بالوضع الحقيقي ،
لنقم أولاً بتشفير هذه الحقيقة بالذات في متغير:

لاكتشاف التناقضات (وعددها) ، نضيف دالة خطأ:
Error = Reality - Neural Net Output
مع ذلك ، يمكننا تقييم أداء شبكتنا العصبية:

ولكن الأهم من ذلك ، ماذا عن المواقف التي يعطي الواقع فيها نتائج إيجابية؟

الآن نحن نعلم أن نموذج الشبكة العصبية لدينا لا يعمل (ونعلم كم) ، عظيم! هذا أمر رائع لأنه يمكننا الآن استخدام وظيفة الخطأ للتحكم في تعلمنا. ولكن كل هذا سيكون منطقيًا إذا أعدنا تعريف وظيفة الخطأ على النحو التالي:
Error = <b>Desired Output</b> - Neural Net Output
هذا التناقض المهم ، لكن هذا التناقض المهم ، يظهر ضمنيًا أننا سنفعل
استخدام النتائج التي تم الحصول عليها سابقًا للمقارنة مع الإجراءات المستقبلية
(وللتدريب كما سنرى لاحقا). إنه موجود في الحياة الحقيقية المليئة
تكرار الأنماط ، لذلك يمكن أن تصبح استراتيجية تطورية (حسنا ، في
معظم الحالات).
بعد ذلك ، في نموذج الكود ، سنضيف متغيرًا جديدًا:
var input = [0,0,1,0]; var weights = [0,0,0,0]; var desiredResult = 1;
وميزة جديدة:
function evaluateNeuralNetError(desired,actual) { return (desired — actual); }
مثال حي:
Neural Net 002 .
لتلخيص المجموع الفرعي . بدأنا بالمهمة ، وصنعنا نموذجها البسيط على شكل شبكة عصبية بيولوجية ، وحصلنا على طريقة لقياس أدائها مقارنة بالواقع أو النتيجة المرجوة. الآن نحن بحاجة إلى إيجاد طريقة لتصحيح الاختلاف - وهي عملية يمكن اعتبارها تدريبًا لكل من أجهزة الكمبيوتر والأشخاص.
كيف تدرب الشبكة العصبية؟أساس تعليم الشبكات العصبية البيولوجية والاصطناعية هو التكرار
وخوارزميات التدريب ، لذلك سنعمل معهم بشكل منفصل. ابدأ بـ
خوارزميات التعلم.
في الطبيعة ، تُفهم خوارزميات التعلم على أنها تغييرات في المواد الفيزيائية أو الكيميائية
خصائص الخلايا العصبية بعد التجارب:

توضيح مثير لكيفية تغير اثنين من الخلايا العصبية بمرور الوقت في الكود ونموذجنا "خوارزمية التعلم" يعني أننا سنغير شيئًا مع مرور الوقت لجعل حياتنا أسهل. لذلك ، دعنا نضيف متغيرًا للإشارة إلى درجة تسهيل الحياة:
var learningRate = 0.20;
وماذا سيتغير؟سيؤدي هذا إلى تغيير الوزن (تمامًا مثل الأرنب!) ، وخاصة وزن الإخراج الذي نريده:

كيفية ترميز مثل هذه الخوارزمية هو اختيارك ، من أجل البساطة ، أضيف معامل التدريب إلى الوزن ، وهنا في شكل دالة:
function learn(inputVector, weightVector) { weightVector.forEach(function(weight, index, weights) { if (inputVector[index] > 0) { weights[index] = weight + learningRate; } }); }
عند استخدامها ، ستضيف وظيفة التعلم هذه ببساطة معامل التعلم الخاص بنا إلى ناقل الوزن
للخلايا العصبية النشطة ، قبل وبعد دورة التدريب (أو التكرار) ، ستكون النتائج على النحو التالي:
مثال حي:
Neural Net 003 .
حسنًا ، الآن بما أننا نتحرك في الاتجاه الصحيح ، فإن التفاصيل الأخيرة لهذا اللغز ستكون مقدمة
التكرار .
الأمر ليس صعبًا ، في الطبيعة نقوم بنفس الشيء مرارًا وتكرارًا ، وفي الكود نشير فقط إلى عدد التكرار:
var trials = 6;
وسيبدو إدخال وظيفة التكرار في شبكتنا العصبية التدريبية كما يلي:
function train(trials) { for (i = 0; i < trials; i++) { neuralNetResult = evaluateNeuralNetwork(input, weights); learn(input, weights); } }
حسنًا ، تقريرنا النهائي:
Neural Net output: 0.00 Error: 1.00 Weight Vector: [0,0,0,0] Neural Net output: 0.20 Error: 0.80 Weight Vector: [0,0,0.2,0] Neural Net output: 0.40 Error: 0.60 Weight Vector: [0,0,0.4,0] Neural Net output: 0.60 Error: 0.40 Weight Vector: [0,0,0.6,0] Neural Net output: 0.80 Error: 0.20 Weight Vector: [0,0,0.8,0] Neural Net output: 1.00 Error: 0.00 Weight Vector: [0,0,1,0]
مثال حي:
Neural Net 004 .
الآن لدينا ناقل الوزن الذي سيعطي نتيجة واحدة فقط (الدجاج للعشاء) ، إذا كان ناقل الإدخال يتوافق مع الواقع (الضغط على الزر الثالث).
فما هو الشيء الرائع الذي فعلناه للتو؟في هذه الحالة بالذات ، يمكن لشبكتنا العصبية (بعد التدريب) التعرف على بيانات الإدخال وقول ما سيؤدي إلى النتيجة المرجوة (ما زلنا بحاجة إلى برمجة مواقف محددة):

بالإضافة إلى ذلك ، فهو نموذج قابل للتطوير ولعبة وأداة لتدريبنا. تمكنا من تعلم شيء جديد عن التعلم الآلي والشبكات العصبية والذكاء الاصطناعي.
تحذير للمستخدمين:
- لم يتم توفير آلية تخزين للمقاييس المدروسة ، لذلك ستنسى هذه الشبكة العصبية كل ما تعرفه. عند تحديث الرمز أو إعادة تشغيله ، تحتاج إلى ست محاولات ناجحة على الأقل حتى يتم تدريب الشبكة بشكل كامل إذا كنت تعتقد أن شخصًا أو جهازًا سيضغط على الأزرار بشكل عشوائي ... سيستغرق ذلك بعض الوقت.
- الشبكات البيولوجية لتعلم أشياء مهمة لها سرعة تعلم 1 ، لذلك أنت بحاجة إلى تكرار ناجح واحد فقط.
- هناك خوارزمية تعلم تشبه إلى حد كبير الخلايا العصبية البيولوجية ، ولها اسم جذاب: قاعدة widroff-hoff ، أو تدريب widroff-hoff .
- لا يتم أخذ عتبات الخلايا العصبية (1 في مثالنا) وتأثيرات إعادة التدريب (مع عدد كبير من التكرار ، ستكون النتيجة أكثر من 1) ، ولكنها مهمة جدًا في الطبيعة وهي مسؤولة عن كتل كبيرة ومعقدة من التفاعلات السلوكية. مثل الأوزان السلبية.
ملاحظات ومراجع لمزيد من القراءة
حاولت أن أتجنب الرياضيات والمصطلحات الصارمة ، ولكن إذا كنت مهتمًا ، فقد قمنا ببناء تصور ، والذي يتم تعريفه على أنه خوارزمية للتعلم تحت الإشراف (
التدريس مع مدرس )
لمصنف مزدوج - وهو أمر صعب.
التركيب البيولوجي للدماغ ليس موضوعًا بسيطًا ، ويرجع ذلك جزئيًا إلى عدم الدقة ، جزئيًا بسبب تعقيده. من الأفضل أن تبدأ بعلم الأعصاب (Purves) وعلم الأعصاب الإدراكي (Gazzaniga). لقد قمت بتعديل وتكييف نموذج الأرنب من Gateway to Memory (Gluck) ، وهو أيضًا دليل رائع لعالم الرسم البياني.
هناك مورد آخر رائع ، وهو مقدمة للشبكات العصبية (Gurney) ، وهو مناسب لجميع احتياجاتك المتعلقة بالذكاء الاصطناعي.
والآن في بيثون! بفضل Ilya Andschmidt لإصدار Python المقدم:
inputs = [0, 1, 0, 0] weights = [0, 0, 0, 0] desired_result = 1 learning_rate = 0.2 trials = 6 def evaluate_neural_network(input_array, weight_array): result = 0 for i in range(len(input_array)): layer_value = input_array[i] * weight_array[i] result += layer_value print("evaluate_neural_network: " + str(result)) print("weights: " + str(weights)) return result def evaluate_error(desired, actual): error = desired - actual print("evaluate_error: " + str(error)) return error def learn(input_array, weight_array): print("learning...") for i in range(len(input_array)): if input_array[i] > 0: weight_array[i] += learning_rate def train(trials): for i in range(trials): neural_net_result = evaluate_neural_network(inputs, weights) learn(inputs, weights) train(trials)
والآن على GO! شكرا لك على هذه النسخة من كيران ماهر.
package main import ( "fmt" "math" ) func main() { fmt.Println("Creating inputs and weights ...") inputs := []float64{0.00, 0.00, 1.00, 0.00} weights := []float64{0.00, 0.00, 0.00, 0.00} desired := 1.00 learningRate := 0.20 trials := 6 train(trials, inputs, weights, desired, learningRate) } func train(trials int, inputs []float64, weights []float64, desired float64, learningRate float64) { for i := 1; i < trials; i++ { weights = learn(inputs, weights, learningRate) output := evaluate(inputs, weights) errorResult := evaluateError(desired, output) fmt.Print("Output: ") fmt.Print(math.Round(output*100) / 100) fmt.Print("\nError: ") fmt.Print(math.Round(errorResult*100) / 100) fmt.Print("\n\n") } } func learn(inputVector []float64, weightVector []float64, learningRate float64) []float64 { for index, inputValue := range inputVector { if inputValue > 0.00 { weightVector[index] = weightVector[index] + learningRate } } return weightVector } func evaluate(inputVector []float64, weightVector []float64) float64 { result := 0.00 for index, inputValue := range inputVector { layerValue := inputValue * weightVector[index] result = result + layerValue } return result } func evaluateError(desired float64, actual float64) float64 { return desired - actual }