Jaringan saraf untuk yang terkecil

Hai, dalam contoh ini saya ingin menunjukkan bagaimana Anda dapat mengimplementasikan jaringan Hopfield untuk pengenalan pola.

Saya sendiri, seperti banyak orang pada suatu hari, memutuskan untuk tertarik pada pelatihan program, AI dan jaringan saraf. Untungnya, ada banyak analisis dan contoh di jaringan, tetapi semuanya beroperasi dengan banyak rumus fungsi dan jika Anda tidak mahir dalam matematika (seperti saya), saya akan mencoba menunjukkan contoh sederhana dari jaringan Hopfield menggunakan bahasa Golang (GO).

Deskripsi Jaringan Matematika - Jaringan Hopfield

Mengapa tepatnya jaringan Hopfield?

Contoh yang cukup cepat dan kurang lebih jelas, jika Anda dapat beroperasi dengan istilah-istilah seperti "sederhana" dan "dapat dimengerti" di dunia AI.

Dalam contoh ini, kami akan mencoba mengenali gambar dari gambar hitam putih berukuran 20x20 piksel.

Mari kita coba memahami langkah-langkah yang harus kita selesaikan sebelum kita mendapatkan hasil yang kita inginkan:

  1. Konversi gambar ke vektor
  2. Ubah vektor menjadi matriks
  3. Jumlahkan matriks dan dapatkan satu matriks tunggal (W)
  4. Nol satu matriks tunggal secara diagonal
  5. Lipat gandakan matriks W dengan vektor gambar input
  6. Lewati vektor yang diterima melalui fungsi aktivasi untuk jaringan ini (F)
  7. Ganti vektor baru ke langkah 5 dan lanjutkan operasi sampai kita mendapatkan kondisi jaringan yang stabil (kita akan mendapatkan vektor yang sama pada output).

Mari kita beralih ke kode dengan deskripsi terperinci. Semua perpustakaan yang kami butuhkan:

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

Kami membuat array vektor 3 elemen (jumlah sampel), mengonversi gambar menjadi vektor, dan menambahkan sampel ke array. Vektor 'Y' adalah gambar yang ingin kita kenali.

 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 

Buat array matriks, konversikan semua vektor ke matriks, dan tambahkan ke array matriks. Kami membuat kosong dari matriks W dan mulai menjumlahkan semua matriks, masukkan hasilnya dalam 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) } 

Nol matriks secara diagonal.

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

Kami membuat blank dari vektor output, kalikan matriks dengan vektor Y, masukkan hasilnya ke vektor S, dan gantilah kembali dengan multiplikasi.

 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) } } } 

Lebih lanjut tentang fungsi sigmod ().

Ini adalah fungsi aktivasi F dan prinsip operasinya (dalam contoh kami) adalah untuk mengkonversi data dalam vektor output dan membawanya ke 1 atau -1.

Karena kami bekerja dengan jaringan bipolar, data hanya dapat 1 dan -1.

Gambar harus dikurangi dari RGB ke 1 dan -1, di mana jumlah semua titik dibagi 3 (kecerahan piksel bersyarat) harus cenderung hitam atau putih. Karena R = 255, G = 255, B = 255 berwarna putih, dan R = 0, G = 0, B = 0 berwarna hitam. Saya memilih ambang batas 150, sehingga lebih dari atau sama dengan 150 akan menjadi putih (1) semua yang kurang dari hitam (-1), di mana pilihan antara hitam pada -1 dan putih pada 1 dapat bersyarat, yang kita butuhkan adalah menguraikan hitam dan putih berdasarkan nilai. Putih juga bisa -1, dan hitam 1, dalam hal ini tidak masalah. Perlu juga dipertimbangkan bahwa kami bekerja dengan matriks simetris dan gambar harus sama sisi.

Untuk mengonversi gambar menjadi vektor, Anda perlu merepresentasikan gambar sebagai matriks yang kami potong secara horizontal dan menambahkan setiap layer yang dipotong (dan kami akan memiliki 20 layer) di akhir layer sebelumnya dan mendapatkan vektor sepanjang 400 (20x20).

Dalam contoh, saya tidak memeriksa vektor output untuk stabilitas, tetapi cukup melalui siklus 100 kali, dan pada akhirnya saya memeriksa sampel mana yang terlihat seperti hasil kami. Jaringan entah menebak atau tidak pada saat yang sama memberikan apa yang disebut chimera atau interpretasi gratis dari apa yang bisa dilihatnya. Ini adalah hasil yang saya simpan ke gambar.

Karena kami menggunakan mode jaringan Hopfield yang sinkron, hasilnya akan lemah. Tentu saja, Anda dapat menggunakan asinkron, yang akan membutuhkan lebih banyak waktu dan sumber daya, tetapi hasilnya akan jauh lebih baik.

Contoh kerja:

Masukan gambar -
Jawabannya adalah

Sumber gambar






Seluruh kode
paket utama

 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/id417063/


All Articles