Преглед изворни кода

обучение распознаванию крестика

kpmy пре 9 година
родитељ
комит
629701b085
9 измењених фајлова са 301 додато и 81 уклоњено
  1. 0 1
      .gitignore
  2. BIN
      gone.to/0.png
  3. BIN
      gone.to/1.png
  4. BIN
      gone.to/2.png
  5. 96 76
      gone.to/main.go
  6. 2 1
      model/model.go
  7. 123 0
      model/proc/proc.go
  8. 71 0
      model/std/load-store.go
  9. 9 3
      model/std/sm.go

+ 0 - 1
.gitignore

@@ -22,4 +22,3 @@ _testmain.go
 *.exe
 *.test
 *.prof
-*.pc




+ 96 - 76
gone.to/main.go

@@ -1,14 +1,18 @@
 package main
 
 import (
-	"encoding/json"
 	"github.com/kpmy/ypk/assert"
-	"gone/perc"
-	"gone/perc/std"
-	"io"
+	"github.com/kpmy/ypk/fn"
+	"gone/model"
+	"gone/model/proc"
+	"gone/model/std"
+	"image"
+	"image/color"
+	_ "image/png"
 	"log"
 	"math/rand"
 	"os"
+	"time"
 )
 
 const (
@@ -23,97 +27,113 @@ func init() {
 	log.SetFlags(0)
 }
 
-type Link struct {
-	NodeId int `json:"node"`
-	LinkId int `json:"out"`
-}
+func generate() *model.Layer {
+	rnd := rand.New(rand.NewSource(time.Now().UnixNano()))
+	s := std.New(proc.Sensoric, Nsens, MaxSensOut, func() int {
+		x := rnd.Intn(2)
+		if x == 0 {
+			return 1
+		} else {
+			return -1
+		}
+	})
+	a := std.New(proc.Associative, Nass, Nreact, func() int { return rnd.Intn(201) - 100 })
+	r := std.New(proc.Reactive, Nreact, 1, nil)
 
-type NodeStruct struct {
-	Outs []int  `json:"out"`
-	Ins  []Link `json:"in,omitempty"`
+	std.Join(s, a)
+	std.Join(a, r)
+	return s
 }
 
-type LayerStruct struct {
-	Nodes []*NodeStruct `json:"node"`
-}
+const name = "pc"
 
-func Store(wr io.Writer, first *model.Layer) error {
-	res := make([]*LayerStruct, 0)
-	for l := first; l != nil; l = l.Next {
-		next := &LayerStruct{}
-		for _, n := range l.Nodes {
-			node := &NodeStruct{}
-			for _, w := range n.Weights {
-				node.Outs = append(node.Outs, w)
-			}
-			for k, _ := range n.In {
-				link := Link{NodeId: k.NodeId, LinkId: k.LinkId}
-				node.Ins = append(node.Ins, link)
+func main() {
+	var s, r *model.Layer
+	if _, err := os.Stat(name); os.IsNotExist(err) {
+		s = generate()
+
+		if f, err := os.Create(name); err == nil {
+			if err := std.Store(f, s); err != nil {
+				log.Fatal(err)
 			}
-			next.Nodes = append(next.Nodes, node)
+			f.Close()
 		}
-		res = append(res, next)
+	} else {
+		log.Println("file exists")
 	}
-	return json.NewEncoder(wr).Encode(res)
-}
 
-func Load(rd io.Reader) (ret *model.Layer, err error) {
-	ll := make([]LayerStruct, 0)
-	if err = json.NewDecoder(rd).Decode(ll); err == nil {
-		var this *model.Layer
-		for _, l := range ll {
-			if ret == nil {
-				this = &model.Layer{}
-				ret = this
-			} else {
-				this.Next = &model.Layer{}
-				this = this.Next
-			}
-			for _, n := range l.Nodes {
-				node := model.NewNode()
-				for _, w := range n.Outs {
-					node.Weights = append(node.Weights, w)
-				}
-				node.Out = make([]interface{}, len(node.Weights))
-				for _, l := range n.Ins {
-					link := model.Link{LinkId: l.LinkId, NodeId: l.NodeId}
-					node.In[link] = nil
-				}
-				this.Nodes = append(this.Nodes, node)
-			}
+	if f, err := os.Open(name); err == nil {
+		defer f.Close()
+		if s, err = std.Load(f); err != nil {
+			log.Fatal(err)
 		}
 	}
-	return
-}
+	white := color.RGBA{R: 0xff, G: 0xFF, B: 0xFF, A: 0xFF}
+	if fi, err := os.Open("0.png"); err == nil {
+		if i, _, err := image.Decode(fi); err == nil {
+			j := 0
+			log.Println("image", i.Bounds())
+			for y := i.Bounds().Min.Y; y < i.Bounds().Max.Y; y++ {
+				for x := i.Bounds().Min.X; x < i.Bounds().Max.X; x++ {
+					c := i.At(x, y)
+					if c == white {
+						s.Nodes[j].In[model.Link{NodeId: 0, LinkId: 0}] = 1
+					} else {
+						s.Nodes[j].In[model.Link{NodeId: 0, LinkId: 0}] = 0
+					}
+					j++
+				}
+			}
 
-func main() {
-	s := std.New(Nsens, MaxSensOut, func() int {
-		x := rand.Intn(2)
-		if x == 0 {
-			return 1
 		} else {
-			return -1
+			log.Fatal(err)
 		}
-	})
-	a := std.New(Nass, Nreact, func() int { return rand.Intn(201) - 100 })
-	r := std.New(Nreact, 1, nil)
-
-	std.Join(s, a)
-	std.Join(a, r)
+	} else {
+		log.Fatal(err)
+	}
 
-	log.Println(s)
+	/* for _, n := range s.Nodes {
+		n.In[model.Link{NodeId: 0, LinkId: 0}] = rand.Intn(2)
+	} */
+	t := make([]int, Nreact)
+	for i := 0; i < len(t); i++ {
+		t[i] = -1
+	}
+	t[0] = 1
 
-	if f, err := os.Create("0.pc"); err == nil {
-		Store(f, s)
-		f.Close()
+	for stop := false; !stop; { //autolearn for t pattern
+		for l := s; !fn.IsNil(l); l = l.Next {
+			proc.Process(l)
+			if l.Next != nil {
+				proc.Transfer(l)
+			} else {
+				r = l
+			}
+		}
+		a := make([]int, Nreact)
+		for i, n := range r.Nodes {
+			a[i] = n.Out[0].(int)
+		}
+		log.Println(t)
+		log.Println(a)
+		stop = true
+		for i, _ := range t {
+			switch {
+			case t[i] == 1 && a[i] == 1: //ok
+			case t[i] == 1 && a[i] != t[i]:
+				std.Update(s.Next, r.Nodes[i].In, 1)
+				stop = false
+			case t[i] == -1 && a[i] != t[i]:
+				std.Update(s.Next, r.Nodes[i].In, -1)
+				stop = false
+			}
+		}
 	}
 
-	if f, err := os.Open("0.pc"); err == nil {
-		if s, err = Load(f); err != nil {
+	if f, err := os.Create(name + ".0"); err == nil {
+		if err := std.Store(f, s); err != nil {
 			log.Fatal(err)
 		}
 		f.Close()
 	}
-
-	log.Println(s)
 }

+ 2 - 1
perc/model.go → model/model.go

@@ -16,11 +16,12 @@ type Node struct {
 }
 
 func (n *Node) String() string {
-	return fmt.Sprint("<", n.In, "->", len(n.Out), ">")
+	return fmt.Sprint("<", len(n.In), "->", len(n.Out), ">")
 }
 
 type Layer struct {
 	Nodes []*Node
+	Role  string
 	Next  *Layer
 }
 

+ 123 - 0
model/proc/proc.go

@@ -0,0 +1,123 @@
+package proc
+
+import (
+	"github.com/kpmy/ypk/assert"
+	"github.com/kpmy/ypk/fn"
+	"github.com/kpmy/ypk/halt"
+	"gone/model"
+	"sync"
+)
+
+const (
+	Sensoric    = "sensor"
+	Associative = "assoc"
+	Reactive    = "react"
+)
+
+var fm map[string]func(*model.Node)
+
+var defLink model.Link = model.Link{NodeId: 0, LinkId: 0}
+
+func init() {
+	fm = make(map[string]func(*model.Node))
+
+	fm[Sensoric] = func(n *model.Node) {
+		v := n.In[defLink].(int)
+		for i, w := range n.Weights {
+			n.Out[i] = Sfunc(w, v)
+		}
+	}
+
+	fm[Associative] = func(n *model.Node) {
+		var vl []int
+		for _, v := range n.In {
+			vl = append(vl, v.(int))
+		}
+		v := Afunc(vl...)
+		for i, w := range n.Weights {
+			n.Out[i] = Afuncw(w, v)
+		}
+	}
+	fm[Reactive] = func(n *model.Node) {
+		var vl []int
+		for _, v := range n.In {
+			vl = append(vl, v.(int))
+		}
+		n.Out[0] = Rfunc(vl...)
+	}
+}
+
+func Sfunc(weight, signal int) int {
+	return weight * signal
+}
+
+func Afunc(signal ...int) int {
+	var r int
+	for _, x := range signal {
+		r = r + x
+	}
+	if r >= 8 {
+		r = 1
+	} else {
+		r = 0
+	}
+	return r
+}
+
+func Afuncw(weight, signal int) int {
+	return weight * signal
+}
+
+func Rfunc(signal ...int) int {
+	//log.Println(signal)
+	var r int
+	for _, x := range signal {
+		r = r + x
+	}
+	if r > 0 {
+		r = 1
+	} else if r < 0 {
+		r = -1
+	} else {
+		r = 0
+	}
+	return r
+}
+
+func Process(l *model.Layer) {
+	assert.For(l != nil, 20)
+	if fn, ok := fm[l.Role]; ok {
+		wg := new(sync.WaitGroup)
+		for _, n := range l.Nodes {
+			wg.Add(1)
+			go func(n *model.Node) {
+				fn(n)
+				wg.Done()
+			}(n)
+		}
+		wg.Wait()
+	} else {
+		halt.As(100, l.Role)
+	}
+}
+
+func Transfer(l *model.Layer) {
+	assert.For(l != nil && l.Next != nil, 20)
+	wg := new(sync.WaitGroup)
+	for _, n := range l.Next.Nodes {
+		wg.Add(1)
+		go func(n *model.Node) {
+			tmp := make(map[model.Link]interface{})
+			for k, _ := range n.In {
+				v := l.Nodes[k.NodeId].Out[k.LinkId]
+				if fn.IsNil(v) {
+					halt.As(100, k)
+				}
+				tmp[k] = v
+			}
+			n.In = tmp
+			wg.Done()
+		}(n)
+	}
+	wg.Wait()
+}

+ 71 - 0
model/std/load-store.go

@@ -0,0 +1,71 @@
+package std
+
+import (
+	"encoding/json"
+	"gone/model"
+	"io"
+)
+
+type Link struct {
+	NodeId int `json:"node"`
+	LinkId int `json:"out"`
+}
+
+type NodeStruct struct {
+	Outs []int  `json:"out"`
+	Ins  []Link `json:"in,omitempty"`
+}
+
+type LayerStruct struct {
+	Nodes []*NodeStruct `json:"node"`
+	Role  string        `json:"role"`
+}
+
+func Store(wr io.Writer, first *model.Layer) error {
+	res := make([]*LayerStruct, 0)
+	for l := first; l != nil; l = l.Next {
+		next := &LayerStruct{Role: l.Role}
+		for _, n := range l.Nodes {
+			node := &NodeStruct{}
+			for _, w := range n.Weights {
+				node.Outs = append(node.Outs, w)
+			}
+			for k, _ := range n.In {
+				link := Link{NodeId: k.NodeId, LinkId: k.LinkId}
+				node.Ins = append(node.Ins, link)
+			}
+			next.Nodes = append(next.Nodes, node)
+		}
+		res = append(res, next)
+	}
+	return json.NewEncoder(wr).Encode(res)
+}
+
+func Load(rd io.Reader) (ret *model.Layer, err error) {
+	ll := make([]*LayerStruct, 0)
+	if err = json.NewDecoder(rd).Decode(&ll); err == nil {
+		var this *model.Layer
+		for _, l := range ll {
+			if ret == nil {
+				this = &model.Layer{Role: l.Role}
+				ret = this
+			} else {
+				this.Next = &model.Layer{Role: l.Role}
+				this = this.Next
+			}
+			for _, n := range l.Nodes {
+				node := model.NewNode()
+				for _, w := range n.Outs {
+					node.Weights = append(node.Weights, w)
+				}
+				node.Out = make([]interface{}, len(node.Weights))
+				for _, l := range n.Ins {
+					link := model.Link{LinkId: l.LinkId, NodeId: l.NodeId}
+					node.In[link] = nil
+				}
+				this.Nodes = append(this.Nodes, node)
+			}
+		}
+	}
+	return
+}

+ 9 - 3
perc/std/sm.go → model/std/sm.go

@@ -2,12 +2,12 @@ package std
 
 import (
 	"github.com/kpmy/ypk/assert"
-	"gone/perc"
+	"gone/model"
 	"math/rand"
 )
 
-func New(nn, no int, w_fn func() int) (ret *model.Layer) {
-	ret = &model.Layer{}
+func New(role string, nn, no int, w_fn func() int) (ret *model.Layer) {
+	ret = &model.Layer{Role: role}
 	for i := 0; i < nn; i++ {
 		next := model.NewNode()
 		next.Out = make([]interface{}, rand.Intn(no)+1)
@@ -54,3 +54,9 @@ func Join(in *model.Layer, out *model.Layer) {
 	}
 	in.Next = out
 }
+
+func Update(l *model.Layer, links map[model.Link]interface{}, dw int) {
+	for k, _ := range links {
+		l.Nodes[k.NodeId].Weights[k.LinkId] += dw
+	}
+}