بالنسبة للتعلم العميق الشهير الآن ، من الضروري الحفاظ على روح التعلم - يجب أن يكون المبرمجون ، وخاصة المهندسين المعماريين ، مهتمين دائمًا بالتقنيات الأساسية والخوارزميات الرئيسية ، وعند الضرورة ، يجب عليك الكتابة وإتقانها. لا تهتم بموعد استخدامه - سواء كان استخدامها هي قضية سياسية أو ما إذا كانت تكتب ، فهي قضية فنية ، تمامًا مثل الجنود لا يهتمون بما إذا كان سيقاتلون أم لا ، ولكن حول كيفية الفوز.
كيف يتعلم المبرمجون التعلم الآلي
بالنسبة للمبرمجين ، فإن التعلم الآلي لديه عتبة معينة (هذه العتبة هي أيضًا قدرتها التنافسية الأساسية). أعتقد أن الكثير من الناس سيحصلون على صداع للأوراق الإنجليزية المليئة بالصيغ الرياضية عند تعلم التعلم الآلي ، وقد يستسلمون. ولكن في الواقع ، ليس من الصعب كتابة برنامج تنفيذ خوارزمية التعلم الآلي. فيما يلي خوارزمية الشبكة العصبية متعددة الطبقات (BP) التي تم تنفيذها بواسطة 70 سطرًا من التعليمات البرمجية ، أي التعلم العميق. في الواقع ، ليس فقط الشبكات العصبية ، ولكن معظم خوارزميات التعلم الآلي مثل الانحدار اللوجستي ، شجرة القرار C45/ID3 ، الغابات العشوائية ، بايزي ، الترشيح التعاوني ، الحوسبة الرسم البياني ، الكميون ، Pagerank ، إلخ.
تكمن الصعوبة الحقيقية في التعلم الآلي في سبب حسابها مثل هذا ، وما هو المبدأ الرياضي وراءه ، وكيفية استنتاج الصيغة. تقدم معظم المعلومات على الإنترنت هذا الجزء من المعرفة النظرية ، ولكن نادراً ما تخبرك كيف هي عملية الحساب وتنفيذ البرنامج للخوارزمية. بالنسبة للمبرمجين ، ما عليك القيام به هو فقط التطبيقات الهندسية ، وليس إثبات طريقة حساب رياضية جديدة. في الواقع ، يستخدم معظم مهندسي التعلم الآلي حزم المصدر المفتوح أو برامج الأدوات التي كتبها الآخرون لإدخال البيانات وضبط معاملات الحساب لتدريب النتائج ، ونادراً ما تنفيذ عملية الخوارزمية بأنفسهم. ومع ذلك ، لا يزال من المهم للغاية إتقان عملية الحساب لكل خوارزمية ، بحيث يمكنك فهم التغييرات التي جعلت الخوارزمية البيانات وما تأثير الخوارزمية لتحقيقه.
تركز هذه المقالة على تنفيذ الولادة الواحدة للشبكات العصبية العكسية. فيما يتعلق بموازاة الشبكات العصبية متعددة الآلات ، يوفر Fourinone إطارًا حوسبة متوازيًا للغاية وكاملًا. نحتاج فقط إلى فهم تنفيذ البرنامج المستقل لتصور وتصميم حل موازٍ موزع. إذا لم نفهم عملية حساب الخوارزمية ، فلن تتمكن جميع الأفكار من توسيعها. بالإضافة إلى ذلك ، هناك أيضًا شبكة عصبية تلافيفية ، وهي فكرة تقليل الأبعاد بشكل أساسي ، تستخدم لمعالجة الصور ، والتي ليست ضمن نطاق هذه المقالة.
وصف عملية الشبكة العصبية:
بادئ ذي بدء ، من المهم أن تكون واضحًا أن الشبكة العصبية تقوم بمهام التنبؤ. أعتقد أنك تتذكر طريقة المربعات الأقل التي تعلمتها في المدرسة الثانوية. يمكننا استخدام هذا لجعل تشبيه أقل صرامة ولكن أكثر سهولة:
أولاً ، نريد الحصول على علامات مجموعة البيانات ومجموعة البيانات (في طريقة المربعات الصغرى ، نحصل أيضًا على مجموعة من قيم X و Y)
تناسب الخوارزمية معلمة دالة يمكنها التعبير عن مجموعة البيانات هذه استنادًا إلى مجموعة البيانات هذه والعلامات المقابلة (أي الصيغة التي تحسب A و B في طريقة المربعات الصغرى ، ولكن لا يمكن الحصول على هذه الصيغة مباشرة في الشبكة العصبية)
نحصل على الوظيفة المجهزة (أي الخط المجهز y^= ax+b في طريقة المربعات الصغرى)
بعد ذلك ، بعد إحضار بيانات جديدة ، يمكن إنشاء القيمة المتوقعة المقابلة y^(في طريقة المربعات الصغرى ، هي إحضار y^= ax+b للحصول على y^المتوقعة ، وكذلك خوارزمية الشبكة العصبية ، ولكن الوظيفة التي تم الحصول عليها أكثر تعقيدًا بكثير من طريقة المربعات الأقل).
عملية حساب الشبكات العصبية
يظهر هيكل الشبكة العصبية في الشكل أدناه. أقصى اليسار هو طبقة الإدخال ، أقصى اليمين هو طبقة الإخراج ، والوسط طبقات مخفية متعددة. تتراكم كل عقدة عصبية للطبقة المخفية وطبقة الإخراج عن طريق ضرب عقدة الطبقة السابقة بوزنها. الدائرة التي تحمل علامة "+1" هي المصطلح التقاطع ب. لكل عقدة خارج طبقة الإدخال: y = w0*x0+w1*x1+...+wn*xn+b ، يمكننا أن نعرف أن الشبكة العصبية تعادل بنية الانحدار اللوجستي متعدد الطبقات.
عملية حساب الخوارزمية: تبدأ طبقة الإدخال ، وتحسب من اليسار إلى اليمين ، وتنتقل إلى الأمام طبقة حسب الطبقة حتى تنتج طبقة الإخراج النتيجة. إذا كان هناك فرق بين قيمة النتيجة والقيمة الهدف ، فحسب من اليمين إلى اليسار ، وحساب خطأ كل طبقة عقدة حسب الطبقة ، وضبط جميع أوزان كل عقدة. بعد الوصول إلى طبقة الإدخال في الاتجاه المعاكس ، احسبها مرة أخرى للأمام ، وتكرار الخطوات المذكورة أعلاه حتى تتقارب جميع معلمات الوزن إلى قيمة معقولة. نظرًا لأن برامج الكمبيوتر تحل معلمات المعادلة والأساليب الرياضية مختلفة ، فإنها عادة ما تحدد المعلمات بشكل عشوائي أولاً ، ثم ضبط المعلمات باستمرار لتقليل الخطأ حتى يتم الاقتراب من القيمة الصحيحة ، فإن معظم التعلم الآلي يتدرب باستمرار. دعونا نلقي نظرة فاحصة على تنفيذ هذه العملية من البرنامج.
تنفيذ برنامج الخوارزمية للشبكة العصبية
ينقسم تنفيذ برنامج الخوارزمية للشبكات العصبية إلى ثلاث عمليات: التهيئة ، ونتائج الحساب الأمامي ، والتعديل العكسي للأوزان.
1. عملية التهيئة
نظرًا لأنها شبكة عصبية N-Layer ، فإننا نستخدم طبقة صفيف ثنائية الأبعاد لتسجيل قيمة العقدة. البعد الأول هو عدد الطبقات ، والبعد الثاني هو موضع العقدة للطبقة ، وقيمة الصفيف هي قيمة العقدة ؛ وبالمثل ، يتم تسجيل طبقة قيمة خطأ العقدة أيضًا بطريقة مماثلة. استخدم طبقة الصفيف ثلاثية الأبعاد لتسجيل أوزان كل عقدة. البعد الأول هو عدد الطبقات ، والبعد الثاني هو موضع العقدة للطبقة ، والبعد الثالث هو موضع عقدة الطبقة السفلية ، وقيمة الصفيف هي قيمة وزن العقدة التي تصل إلى طبقة أقل ، والقيمة الأولية هي رقم عشوائي بين 0-1. من أجل تحسين سرعة التقارب ، يتم استخدام ضبط الوزن الزخم هنا. من الضروري تسجيل مبلغ ضبط الوزن الأخير ، واستخدام طبقة الصفيف ثلاثية الأبعاد للتسجيل. معالجة مصطلح التقاطع: يحدد البرنامج قيمة التقاطع إلى 1 ، بحيث يحتاج فقط إلى حساب وزنه.
2. احسب النتائج للأمام
يتم استخدام وظيفة S 1/(1+Math.exp (-z)) لتوحيد قيمة كل عقدة إلى ما بين 0-1 ، ثم حساب طبقة حسب الطبقة حتى طبقة الإخراج. بالنسبة لطبقة الإخراج ، ليست هناك حاجة في الواقع لاستخدام وظيفة S. نحن نعتبر نتيجة الإخراج كقيمة احتمال بين 0 و 1 ، وبالتالي يتم استخدام وظيفة S أيضًا ، والتي تفضي أيضًا إلى توحيد البرنامج.
3. تعديل الوزن بشكل عكسي
كيفية حساب الأخطاء في الشبكات العصبية تستخدم عمومًا وظيفة الخطأ المربعة E ، على النحو التالي:
أي أن مربعات أخطاء مصطلحات الإخراج المتعددة والقيم المستهدفة المقابلة تتراكم وتقسيمها على 2. في الواقع ، هذه هي وظيفة الخطأ في الانحدار اللوجستي. بالنسبة إلى سبب استخدام هذه الوظيفة لحساب الخطأ ، ما هي العقلانية الرياضية وكيف يتم الحصول عليها ، أقترح أن المبرمجين لا يريدون أن يكونوا علماء رياضيات ، لذلك لا تدخل في ذلك بعمق. ما يتعين علينا القيام به الآن هو كيفية أخذ الحد الأدنى لقيمة خطأ هذه الوظيفة E وتحتاج إلى مشتقها. إذا كانت هناك بعض أساسيات الرياضيات المشتقة ، فيمكنك محاولة استنتاج كيفية الحصول على الصيغة التالية من أوزان المشتق للوظيفة E:
لا يهم إذا لم نتمكن من استنتاجها. نحن فقط بحاجة إلى استخدام صيغة النتائج. في برنامجنا ، نستخدم LayererR لتسجيل الخطأ الصحيح بعد اشتقاق وزن E ، ثم ضبط الوزن وفقًا للخطأ الصحيح.
لاحظ أنه يتم استخدام طريقة الزخم هنا لأخذ في الاعتبار تجربة التعديل السابق لتجنب الوقوع في الحد الأدنى المحلي. يمثل K أدناه عدد التكرارات ، MOBP هو مصطلح الزخم ، والمعدل هو خطوة التعلم:
ΔW (k+1) = mobp*ΔW (k)+معدل*err*طبقة
هناك أيضًا العديد من الصيغ المستخدمة أدناه ، والفرق في الواقع ليس كبيرًا جدًا:
ΔW (K+1) = MOBP*ΔW (k)+(1-mobp) معدل*err*طبقة
من أجل تحسين الأداء ، لاحظ أن تنفيذ البرنامج هو حساب الخطأ وضبط الوزن منذ فترة. أولاً ، ضع الموضع في الطبقة الثانية إلى الأخيرة (أي الطبقة الخفية الأخيرة) ، ثم ضبط طبقة الوزن في الطبقة العكسية. اضبط وزن طبقة L وفقًا للخطأ المحسوب بواسطة طبقة L+1 ، وحساب خطأ طبقة L ، وحساب الوزن في المرة القادمة التي يدور فيها لحساب الوزن حتى نهاية الطبقة الأولى (طبقة الإدخال).
ملخص
أثناء عملية الحساب بأكملها ، تتغير قيمة العقدة في كل مرة يتم حسابها ولا تحتاج إلى حفظها. يجب حفظ معلمات الوزن ومعلمات الخطأ وتحتاج إلى تقديم الدعم للتكرار التالي. لذلك ، إذا تصورنا حل حوسبة موازية موزع متعدد الآلات ، يمكننا أن نفهم سبب وجود مفهوم لخادم المعلمة في أطر أخرى.
تنفيذ البرنامج الكامل للشبكة العصبية متعددة الطبقات
يمكن استخدام برنامج التنفيذ التالي bpdeep.java مباشرة ، ومن السهل أيضًا تعديله إلى أي تطبيق لغة آخر مثل C ، C#، Python ، إلخ ، لأنها كلها بيانات أساسية مستخدمة ولا توجد مكتبات Java أخرى (باستثناء الوظائف العشوائية).
استيراد java.util.random ؛ الطبقة العامة bpdeep {public double [] [] layer ؛ // neural network notes double [] [] layererr ؛ المعدل المزدوج العام ؛ // التعلم معامل BPDEEP العام (int [] layernum ، معدل مزدوج ، مزدوج mobp) {this.mobp = mobp ؛ this.rate = معدل ؛ طبقة = مزدوجة جديدة [layernum.length] [] ؛ layererr = new double [layernum.length] [] ؛ layer_weight = new double [layernum.length] [] [] ؛ layer_weight_delta = new double [layernum.length] [] [] ؛ عشوائي عشوائي = جديد عشوائي () ؛ لـ (int l = 0 ؛ l <layernum.length ؛ l ++) {layer [l] = new double [layernum [l]] ؛ layererr [l] = new double [layernum [l]] ؛ if (l+1 <layernum.length) {layer_weight [l] = new double [layernum [l] +1] [layernum [l+1]] ؛ layer_weight_delta [l] = new double [layernum [l] +1] [layernum [l+1]] ؛ لـ (int j = 0 ؛ j <layernum [l] +1 ؛ j ++) لـ (int i = 0 ؛ i <layernum [l+1] ؛ i ++) layer_weight [l] [j] [i] = عشوائي. l = 1 ؛ l <layer.length ؛ l ++) {for (int j = 0 ؛ j <layer [l] لـ (int i = 0 ؛ i <layer [l-1] .length ؛ i ++) {layer [l-1] [i] = l == 1؟ in [i]: layer [l-1] [i] ؛ z+= layer_weight [l-1] [i] [j]*layer [l-1] [i] ؛ } طبقة [l] [j] = 1/(1+math.exp (-z)) ؛ }} layer [layer.length-1] ؛ } // احسب بشكل عكسي طبقة الخطأ حسب الطبقة وتعديل الوزن public updateweight (double [] tar) {int l = layer.length-1 ؛ لـ (int j = 0 ؛ j <layererr [l] .length ؛ j ++) layererr [l] [j] = layer [l] [j]*(1 layer [l] [j])*(tar [j] -layer [l] [j]) ؛ بينما (l-> 0) {for (int j = 0 ؛ j <layererr [l] .length ؛ j ++) {double z = 0.0 ؛ لـ (int i = 0 ؛ i <layererr [l+1] .length ؛ i ++) {z = z+l> 0؟ layererr [l+1] [i]*layer_weight [l] [j] [i]: 0 ؛ layer_weight_delta [l] [j] [i] = mobp*layer_weight_delta [l] [j] [i]+rate*layererr [l+1] [i]*layer [l] [j] ؛ if (j == layererr [l] .length-1) {layer_weight_delta [l] [j+1] [i] = mobp*layer_weight_delta [l] [j+1] layer_weight [l] [j+1] [i]+= layer_weight_delta [l] [j+1] computeout (in) ؛ UpdateWeight (TAR) ؛ }}مثال على استخدام الشبكات العصبية
أخيرًا ، دعنا نجد مثالًا بسيطًا لرؤية التأثيرات السحرية للشبكات العصبية. من أجل تسهيل مراقبة توزيع البيانات ، نختار بيانات الإحداثيات ثنائية الأبعاد. هناك 4 بيانات أدناه. تمثل الكتلة نوع البيانات هو 1 ، ويمثل المثلث نوع البيانات هو 0. يمكنك أن ترى أن البيانات التي تنتمي إلى نوع الكتلة هي (1 ، 2) و (2 ، 1) ، والبيانات التي تنتمي إلى نوع المثلث هي (1 ، 1) ، (2 ، 2). الآن المشكلة هي أننا نحتاج إلى تقسيم البيانات الأربعة إلى 1 و 0 على الطائرة ، واستخدام هذا للتنبؤ بنوع البيانات الجديدة.
يمكننا استخدام خوارزمية الانحدار اللوجستي لحل مشكلة التصنيف أعلاه ، ولكن الانحدار اللوجستي يحصل على خط مستقيم خطي كخط تقسيم. يمكنك أن ترى أنه بغض النظر عن كيفية وضع الخط الأحمر أعلاه ، يتم تقسيم العينة بشكل خاطئ دائمًا إلى أنواع مختلفة. لذلك ، بالنسبة للبيانات المذكورة أعلاه ، لا يمكن لخط واحد مستقيم فقط تقسيم تصنيفها بشكل صحيح. إذا استخدمنا خوارزمية الشبكة العصبية ، فيمكننا الحصول على تأثير تصنيف الشكل أدناه ، وهو ما يعادل إيجاد اتحاد خطوط مستقيمة متعددة لتقسيم المساحة ، وهو أعلى في الدقة.
فيما يلي الكود المصدري لبرنامج الاختبار هذا bpdeeptest.java:
استيراد java.util.arrays ؛ الفئة العامة bpdeeptest {public static void main (string [] args) {// تهيئة التكوين الأساسي للشبكة العصبية // المعلمة الأولى هي مجموعة عدد صحيح ، تمثل عدد طبقات الشبكة العصبية وعدد العقد لكل طبقة. على سبيل المثال ، تعني {3 ، 10 ، 10 ، 10 ، 10 ، 2} أن طبقة الإدخال هي 3 عقد ، طبقة الإخراج هي العقدتين ، وهناك 4 طبقات مخفية في الوسط ، و 10 عقد لكل طبقة // المعلمة الثانية هي حجم خطوة التعلم ، والمعلمة الثالثة هي معامل الزخم BPDEEP BP = جديد BPDEEP (NEW int [] // قم بتعيين بيانات العينة ، المقابلة لبيانات الإحداثيات ذات الأبعاد الثنائية الأبعاد أعلاه [] [] Data = New Double [] [] {1،2} ، {2،2} ، {1،1} ، {2،1}} ؛ // قم بتعيين البيانات الهدف ، المقابلة لتصنيف 4 بيانات تنسيق مزدوجة [] [] الهدف = جديد مزدوج [] {{1،0} ، {0،1} ، {0،1} ، {1،0}} ؛ // التدريب التكراري 5000 مرة لـ (int n = 0 ؛ n <5000 ؛ n ++) لـ (int i = 0 ؛ i <data.length ؛ i ++) bp.train (data [i] ، target [i]) ؛ // تحقق من بيانات العينة بناءً على نتائج التدريب لـ (int j = 0 ؛ j <data.length ؛ j ++) {double [] result = bp.computeout (data [j]) ؛ System.out.println (Arrays.ToString (data [j])+":"+arrays.toString (result)) ؛ } // التنبؤ بتصنيف بيانات جديدة بناءً على نتائج التدريب المزدوجة [] x = New Double [] {3،1} ؛ double [] result = bp.computeout (x) ؛ System.out.println (Arrays.ToString (x)+":"+arrays.toString (result)) ؛ }} ملخص
يوضح برنامج الاختبار أعلاه أن الشبكات العصبية لها تأثيرات تصنيف سحرية. في الواقع ، فإن الشبكات العصبية لها مزايا معينة ، لكنها ليست خوارزميات عالمية قريبة من الدماغ البشري. في كثير من الأحيان قد يخيب أملك. نحتاج أيضًا إلى استخدام الكثير من البيانات من سيناريوهات مختلفة لمراقبة آثارها. يمكننا تغيير الطبقة المخفية ذات الطبقة المكونة من طبقة واحدة إلى طبقات N وضبط عدد العقد والتكرار وحجم خطوة التعلم ومعاملات الزخم لكل طبقة للحصول على نتيجة محسّنة. ومع ذلك ، في كثير من الحالات ، لم يتم تحسين تأثير الطبقة المخفية N للطبقة N بشكل كبير من تأثير الطبقة 1. بدلاً من ذلك ، يكون الحساب أكثر تعقيدًا ويستغرق وقتًا طويلاً. إن فهمنا للشبكات العصبية يتطلب المزيد من الممارسة والخبرة.
ما سبق هو كل المحتوى المشترك في هذه المقالة حول تنفيذ خوارزميات الشبكة العصبية العميقة مع 70 سطر من كود Java. آمل أن يكون ذلك مفيدًا للجميع. إذا كانت هناك أي أوجه قصور ، فيرجى ترك رسالة لإشارةها.