شبكات عصبية لأصغر

مرحبًا ، في هذا المثال ، أريد أن أوضح كيف يمكنك تنفيذ شبكة هوبفيلد للتعرف على الأنماط.

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

وصف الشبكة الرياضية - شبكة هوبفيلد

لماذا بالضبط شبكة هوبفيلد؟

مثال سريع إلى حد ما وأكثر أو أقل وضوحًا ، إذا كان يمكنك العمل بمصطلحات مثل "بسيطة" و "مفهومة" في عالم الذكاء الاصطناعي.

في هذا المثال ، سنحاول التعرف على الصور من صورة بالأبيض والأسود بقياس 20 × 20 بكسل.

دعونا نحاول فهم الخطوات التي يتعين علينا إكمالها قبل أن نحصل على النتيجة المرجوة:

  1. تحويل الصورة إلى متجه
  2. تحويل المتجهات إلى المصفوفات
  3. اجمع المصفوفات واحصل على مصفوفة واحدة (W)
  4. صفر مصفوفة واحدة قطريا
  5. اضرب المصفوفة W بمتجه صورة الإدخال
  6. قم بتمرير المتجه المستلم من خلال وظيفة التنشيط لهذه الشبكة (F)
  7. استبدل الناقل الجديد بالخطوة 5 واستمر في العملية حتى نحصل على حالة مستقرة للشبكة (سنحصل على نفس المتجه عند الإخراج).

دعنا ننتقل إلى الرمز مع وصف مفصل. جميع المكتبات التي نحتاجها:

package main import ( "github.com/oelmekki/matrix" "fmt" "os" "log" "image" "math" "image/color" "image/png" _ "image/jpeg" ) 

نقوم بإنشاء مجموعة من المتجهات المكونة من 3 عناصر (عدد العينات) ، وتحويل الصور إلى متجهات وإضافة عينات إلى المصفوفة. المتجه "Y" هو الصورة التي نريد التعرف عليها.

 vectorArrays := [3][]float64{} x1 := getVectorFromImage("Images/.jpg") x2 := getVectorFromImage("Images/.jpg") x3 := getVectorFromImage("Images/.jpg") y := getVectorFromImage("Images/Income.jpg") // Add images to the array vectorArrays[0] = x1 vectorArrays[1] = x2 vectorArrays[2] = x3 

قم بإنشاء مصفوفة من المصفوفات وتحويل جميع المتجهات إلى مصفوفات وإضافتها إلى مصفوفة المصفوفات. ننشئ فراغًا من المصفوفة W ونبدأ في جمع كل المصفوفات ونضع النتيجة في W.

 matrixArray := [len(vectorArrays)]matrix.Matrix{} for i, vInArray := range vectorArrays { matrixArray[i] = vectorToMatrix(vInArray, vInArray) } W := matrix.Matrix{} for i, matrixInArray := range matrixArray { if i == 0 { W = matrixInArray continue } W, _ = W.Add(matrixInArray) } 

صفر المصفوفة قطريا.

 for i := 0; i < W.Rows(); i++ { W.SetAt(i, i, 0) } 

ننشئ فراغًا من متجه الإخراج ، ونضرب المصفوفة في متجه Y ، ونضع النتيجة في المتجه S ، ونستبدلها بالضرب.

 S := make([]float64, 400) for II := 0; II < 100; II++ { if II == 0 { S, _ = W.VectorMultiply(y) for i, element := range S { // Activation Func "sigmod" S[i] = sigmod(element) } continue } else { S, _ = W.VectorMultiply(S) for i, element := range S { // Activation Func "sigmod" S[i] = sigmod( element) } } } 

المزيد عن دالة sigmod ().

هذه هي وظيفة التنشيط F ومبدأ تشغيلها (في مثالنا) هو تحويل البيانات في ناقل الإخراج وإحضارها إلى 1 أو -1.

نظرًا لأننا نعمل مع شبكة ثنائية القطب ، فإن البيانات يمكن أن تكون 1 و -1 فقط.

يجب تقليل الصورة من RGB إلى 1 و -1 ، حيث يجب أن يميل مجموع جميع النقاط مقسومًا على 3 (سطوع البكسل الشرطي) إلى الأسود أو الأبيض. نظرًا لأن R = 255 ، G = 255 ، B = 255 باللون الأبيض ، و R = 0 ، G = 0 ، B = 0 أسود. لقد اخترت عتبة 150 ، بحيث يكون أكثر من أو يساوي 150 باللون الأبيض (1) كل ما هو أقل من الأسود (-1) ، حيث يمكن أن يكون الاختيار بين الأسود عند -1 والأبيض عند 1 مشروطًا ، كل ما نحتاجه هو تحليل الأسود والأبيض بالقيم. قد يكون الأبيض أيضًا -1 والأسود 1 ، في هذه الحالة لا يهم. تجدر الإشارة أيضًا إلى أننا نعمل مع مصفوفة متناظرة ويجب أن تكون الصور متساوية.

من أجل تحويل الصورة إلى متجه ، تحتاج إلى تمثيل الصورة كمصفوفة نقوم بقصها أفقيًا وإضافة كل طبقة مقطوعة (وسيكون لدينا 20 طبقة) في نهاية الطبقة السابقة والحصول على متجه 400 (20x20) طويل.

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

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

مثال العمل:

صورة الإدخال -
الجواب

صور المصدر






كود كامل
الحزمة الرئيسية

 package main import ( "github.com/oelmekki/matrix" "fmt" "os" "log" "image" "math" "image/color" "image/png" _ "image/jpeg" ) func vectorToMatrix(v1 []float64, v2 []float64) (matrix.Matrix) { m := matrix.GenerateMatrix(len(v1), len(v2)) for i, elem := range v1 { for i2, elem2 := range v1 { m.SetAt(i, i2, elem2*elem) } } return m } func sigmod(v float64) (float64) { if v >= 0 { return 1 } else { return -1 } } func getVectorFromImage(path string) ([] float64) { reader, err := os.Open(path) if err != nil { log.Fatal(err) } defer reader.Close() m, _, err := image.Decode(reader) if err != nil { log.Fatal(err) } v := make([]float64, 400) vectorIteration := 0 for x := 0; x < 20; x++ { for y := 0; y < 20; y++ { r, g, b, _ := m.At(x, y).RGBA() normalVal := float64(r+g+b) / 3 / 257 if normalVal >= 150 { v[vectorIteration] = 1 } else { v[vectorIteration] = -1 } vectorIteration ++ } } return v } func main() { fmt.Println("Memory size ~ ", int(400/(2*math.Log2(400))), " objects") fmt.Println("1 - ") fmt.Println("2 - ") fmt.Println("3 - ") fmt.Println("-----Start------") vectorArrays := [3][]float64{} x1 := getVectorFromImage("Images/.jpg") x2 := getVectorFromImage("Images/.jpg") x3 := getVectorFromImage("Images/.jpg") y := getVectorFromImage("Images/Income.jpg") vectorArrays[0] = x1 vectorArrays[1] = x2 vectorArrays[2] = x3 matrixArray := [len(vectorArrays)]matrix.Matrix{} for i, vInArray := range vectorArrays { matrixArray[i] = vectorToMatrix(vInArray, vInArray) } W := matrix.Matrix{} for i, matrixInArray := range matrixArray { if i == 0 { W = matrixInArray continue } W, _ = W.Add(matrixInArray) } for i := 0; i < W.Rows(); i++ { W.SetAt(i, i, 0) } S := make([]float64, 400) for II := 0; II < 100; II++ { if II == 0 { S, _ = W.VectorMultiply(y) for i, element := range S { S[i] = sigmod(element) } continue } else { S, _ = W.VectorMultiply(S) for i, element := range S { S[i] = sigmod(element) } } } ar := [3]int{1, 1, 1} for vectorI, v := range vectorArrays { for i, elem := range v { if elem != S[i] { ar[vectorI] = 0 break } } } for i, el := range ar { if el == 1 { fmt.Println("Looks like", i+1) } } img := image.NewRGBA(image.Rect(0, 0, 20, 20)) xx := 0 yy := 0 for i := 0; i < 400; i++ { if i%20 == 0 { yy++ xx = 0 } else { xx++ } if S[i] == -1 { img.Set(xx, yy, color.RGBA{0, 0, 0, 255}) } else { img.Set(xx, yy, color.RGBA{255, 255, 255, 255}) } } f, _ := os.OpenFile("Images/out.png", os.O_WRONLY|os.O_CREATE, 0600) png.Encode(f, img) f.Close() var str string fmt.Scanln(&str) } 

Source: https://habr.com/ru/post/ar417063/


All Articles